@ng-formworks/core 18.5.2 → 19.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +2 -1
  2. package/fesm2022/ng-formworks-core.mjs +130 -110
  3. package/fesm2022/ng-formworks-core.mjs.map +1 -1
  4. package/package.json +3 -3
  5. package/esm2022/lib/framework-library/framework-library.service.mjs +0 -172
  6. package/esm2022/lib/framework-library/framework.mjs +0 -15
  7. package/esm2022/lib/framework-library/no-framework.component.mjs +0 -17
  8. package/esm2022/lib/framework-library/no-framework.module.mjs +0 -27
  9. package/esm2022/lib/framework-library/no.framework.mjs +0 -19
  10. package/esm2022/lib/json-schema-form.component.mjs +0 -759
  11. package/esm2022/lib/json-schema-form.module.mjs +0 -26
  12. package/esm2022/lib/json-schema-form.service.mjs +0 -695
  13. package/esm2022/lib/locale/de-validation-messages.mjs +0 -60
  14. package/esm2022/lib/locale/en-validation-messages.mjs +0 -60
  15. package/esm2022/lib/locale/es-validation-messages.mjs +0 -57
  16. package/esm2022/lib/locale/fr-validation-messages.mjs +0 -60
  17. package/esm2022/lib/locale/index.mjs +0 -8
  18. package/esm2022/lib/locale/it-validation-messages.mjs +0 -60
  19. package/esm2022/lib/locale/pt-validation-messages.mjs +0 -60
  20. package/esm2022/lib/locale/zh-validation-messages.mjs +0 -60
  21. package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +0 -300
  22. package/esm2022/lib/shared/form-group.functions.mjs +0 -445
  23. package/esm2022/lib/shared/format-regex.constants.mjs +0 -54
  24. package/esm2022/lib/shared/index.mjs +0 -12
  25. package/esm2022/lib/shared/json-schema.functions.mjs +0 -784
  26. package/esm2022/lib/shared/json.validators.mjs +0 -884
  27. package/esm2022/lib/shared/jsonpointer.functions.mjs +0 -1026
  28. package/esm2022/lib/shared/layout.functions.mjs +0 -1158
  29. package/esm2022/lib/shared/merge-schemas.function.mjs +0 -345
  30. package/esm2022/lib/shared/utility.functions.mjs +0 -380
  31. package/esm2022/lib/shared/validator.functions.mjs +0 -584
  32. package/esm2022/lib/widget-library/add-reference.component.mjs +0 -58
  33. package/esm2022/lib/widget-library/button.component.mjs +0 -69
  34. package/esm2022/lib/widget-library/checkbox.component.mjs +0 -102
  35. package/esm2022/lib/widget-library/checkboxes.component.mjs +0 -145
  36. package/esm2022/lib/widget-library/file.component.mjs +0 -32
  37. package/esm2022/lib/widget-library/hidden.component.mjs +0 -51
  38. package/esm2022/lib/widget-library/index.mjs +0 -55
  39. package/esm2022/lib/widget-library/input.component.mjs +0 -116
  40. package/esm2022/lib/widget-library/message.component.mjs +0 -35
  41. package/esm2022/lib/widget-library/none.component.mjs +0 -20
  42. package/esm2022/lib/widget-library/number.component.mjs +0 -120
  43. package/esm2022/lib/widget-library/one-of.component.mjs +0 -32
  44. package/esm2022/lib/widget-library/orderable.directive.mjs +0 -120
  45. package/esm2022/lib/widget-library/radios.component.mjs +0 -151
  46. package/esm2022/lib/widget-library/root.component.mjs +0 -73
  47. package/esm2022/lib/widget-library/section.component.mjs +0 -196
  48. package/esm2022/lib/widget-library/select-framework.component.mjs +0 -44
  49. package/esm2022/lib/widget-library/select-widget.component.mjs +0 -42
  50. package/esm2022/lib/widget-library/select.component.mjs +0 -147
  51. package/esm2022/lib/widget-library/submit.component.mjs +0 -79
  52. package/esm2022/lib/widget-library/tab.component.mjs +0 -38
  53. package/esm2022/lib/widget-library/tabs.component.mjs +0 -106
  54. package/esm2022/lib/widget-library/template.component.mjs +0 -43
  55. package/esm2022/lib/widget-library/textarea.component.mjs +0 -101
  56. package/esm2022/lib/widget-library/widget-library.module.mjs +0 -42
  57. package/esm2022/lib/widget-library/widget-library.service.mjs +0 -226
  58. package/esm2022/ng-formworks-core.mjs +0 -5
  59. package/esm2022/public_api.mjs +0 -13
@@ -1,1026 +0,0 @@
1
- import { cleanValueOfQuotes, copy, getExpressionType, getKeyAndValueByExpressionType, hasOwn, isEqual, isNotEqual, isNotExpression } from './utility.functions';
2
- import { Injectable } from '@angular/core';
3
- import { isArray, isDefined, isEmpty, isMap, isNumber, isObject, isString } from './validator.functions';
4
- import * as i0 from "@angular/core";
5
- export class JsonPointer {
6
- /**
7
- * 'get' function
8
- *
9
- * Uses a JSON Pointer to retrieve a value from an object.
10
- *
11
- * // { object } object - Object to get value from
12
- * // { Pointer } pointer - JSON Pointer (string or array)
13
- * // { number = 0 } startSlice - Zero-based index of first Pointer key to use
14
- * // { number } endSlice - Zero-based index of last Pointer key to use
15
- * // { boolean = false } getBoolean - Return only true or false?
16
- * // { boolean = false } errors - Show error if not found?
17
- * // { object } - Located value (or true or false if getBoolean = true)
18
- */
19
- static get(object, pointer, startSlice = 0, endSlice = null, getBoolean = false, errors = false) {
20
- if (object === null) {
21
- return getBoolean ? false : undefined;
22
- }
23
- let keyArray = this.parse(pointer, errors);
24
- if (typeof object === 'object' && keyArray !== null) {
25
- let subObject = object;
26
- if (startSlice >= keyArray.length || endSlice <= -keyArray.length) {
27
- return object;
28
- }
29
- if (startSlice <= -keyArray.length) {
30
- startSlice = 0;
31
- }
32
- if (!isDefined(endSlice) || endSlice >= keyArray.length) {
33
- endSlice = keyArray.length;
34
- }
35
- keyArray = keyArray.slice(startSlice, endSlice);
36
- for (let key of keyArray) {
37
- if (key === '-' && isArray(subObject) && subObject.length) {
38
- key = subObject.length - 1;
39
- }
40
- if (isMap(subObject) && subObject.has(key)) {
41
- subObject = subObject.get(key);
42
- }
43
- else if (typeof subObject === 'object' && subObject !== null &&
44
- hasOwn(subObject, key)) {
45
- subObject = subObject[key];
46
- }
47
- else {
48
- const evaluatedExpression = JsonPointer.evaluateExpression(subObject, key);
49
- if (evaluatedExpression.passed) {
50
- subObject = evaluatedExpression.key ? subObject[evaluatedExpression.key] : subObject;
51
- }
52
- else {
53
- this.logErrors(errors, key, pointer, object);
54
- return getBoolean ? false : undefined;
55
- }
56
- }
57
- }
58
- return getBoolean ? true : subObject;
59
- }
60
- if (errors && keyArray === null) {
61
- console.error(`get error: Invalid JSON Pointer: ${pointer}`);
62
- }
63
- if (errors && typeof object !== 'object') {
64
- console.error('get error: Invalid object:');
65
- console.error(object);
66
- }
67
- return getBoolean ? false : undefined;
68
- }
69
- static logErrors(errors, key, pointer, object) {
70
- if (errors) {
71
- console.error(`get error: "${key}" key not found in object.`);
72
- console.error(pointer);
73
- console.error(object);
74
- }
75
- }
76
- /**
77
- * Evaluates conditional expression in form of `model.<property>==<value>` or
78
- * `model.<property>!=<value>` where the first one means that the value must match to be
79
- * shown in a form, while the former shows the property only when the property value is not
80
- * set, or does not equal the given value.
81
- *
82
- * // { subObject } subObject - an object containing the data values of properties
83
- * // { key } key - the key from the for loop in a form of `<property>==<value>`
84
- *
85
- * Returns the object with two properties. The property passed informs whether
86
- * the expression evaluated successfully and the property key returns either the same
87
- * key if it is not contained inside the subObject or the key of the property if it is contained.
88
- */
89
- static evaluateExpression(subObject, key) {
90
- const defaultResult = { passed: false, key: key };
91
- const keysAndExpression = this.parseKeysAndExpression(key, subObject);
92
- if (!keysAndExpression) {
93
- return defaultResult;
94
- }
95
- const ownCheckResult = this.doOwnCheckResult(subObject, keysAndExpression);
96
- if (ownCheckResult) {
97
- return ownCheckResult;
98
- }
99
- const cleanedValue = cleanValueOfQuotes(keysAndExpression.keyAndValue[1]);
100
- const evaluatedResult = this.performExpressionOnValue(keysAndExpression, cleanedValue, subObject);
101
- if (evaluatedResult) {
102
- return evaluatedResult;
103
- }
104
- return defaultResult;
105
- }
106
- /**
107
- * Performs the actual evaluation on the given expression with given values and keys.
108
- * // { cleanedValue } cleanedValue - the given valued cleaned of quotes if it had any
109
- * // { subObject } subObject - the object with properties values
110
- * // { keysAndExpression } keysAndExpression - an object holding the expressions with
111
- */
112
- static performExpressionOnValue(keysAndExpression, cleanedValue, subObject) {
113
- const propertyByKey = subObject[keysAndExpression.keyAndValue[0]];
114
- if (this.doComparisonByExpressionType(keysAndExpression.expressionType, propertyByKey, cleanedValue)) {
115
- return { passed: true, key: keysAndExpression.keyAndValue[0] };
116
- }
117
- return null;
118
- }
119
- static doComparisonByExpressionType(expressionType, propertyByKey, cleanedValue) {
120
- if (isEqual(expressionType)) {
121
- return propertyByKey === cleanedValue;
122
- }
123
- if (isNotEqual(expressionType)) {
124
- return propertyByKey !== cleanedValue;
125
- }
126
- return false;
127
- }
128
- /**
129
- * Does the checks when the parsed key is actually no a property inside subObject.
130
- * That would mean that the equal comparison makes no sense and thus the negative result
131
- * is returned, and the not equal comparison is not necessary because it doesn't equal
132
- * obviously. Returns null when the given key is a real property inside the subObject.
133
- * // { subObject } subObject - the object with properties values
134
- * // { keysAndExpression } keysAndExpression - an object holding the expressions with
135
- * the associated keys.
136
- */
137
- static doOwnCheckResult(subObject, keysAndExpression) {
138
- let ownCheckResult = null;
139
- if (!hasOwn(subObject, keysAndExpression.keyAndValue[0])) {
140
- if (isEqual(keysAndExpression.expressionType)) {
141
- ownCheckResult = { passed: false, key: null };
142
- }
143
- if (isNotEqual(keysAndExpression.expressionType)) {
144
- ownCheckResult = { passed: true, key: null };
145
- }
146
- }
147
- return ownCheckResult;
148
- }
149
- /**
150
- * Does the basic checks and tries to parse an expression and a pair
151
- * of key and value.
152
- * // { key } key - the original for loop created value containing key and value in one string
153
- * // { subObject } subObject - the object with properties values
154
- */
155
- static parseKeysAndExpression(key, subObject) {
156
- if (this.keyOrSubObjEmpty(key, subObject)) {
157
- return null;
158
- }
159
- const expressionType = getExpressionType(key.toString());
160
- if (isNotExpression(expressionType)) {
161
- return null;
162
- }
163
- const keyAndValue = getKeyAndValueByExpressionType(expressionType, key);
164
- if (!keyAndValue || !keyAndValue[0] || !keyAndValue[1]) {
165
- return null;
166
- }
167
- return { expressionType: expressionType, keyAndValue: keyAndValue };
168
- }
169
- static keyOrSubObjEmpty(key, subObject) {
170
- return !key || !subObject;
171
- }
172
- /**
173
- * 'getCopy' function
174
- *
175
- * Uses a JSON Pointer to deeply clone a value from an object.
176
- *
177
- * // { object } object - Object to get value from
178
- * // { Pointer } pointer - JSON Pointer (string or array)
179
- * // { number = 0 } startSlice - Zero-based index of first Pointer key to use
180
- * // { number } endSlice - Zero-based index of last Pointer key to use
181
- * // { boolean = false } getBoolean - Return only true or false?
182
- * // { boolean = false } errors - Show error if not found?
183
- * // { object } - Located value (or true or false if getBoolean = true)
184
- */
185
- static getCopy(object, pointer, startSlice = 0, endSlice = null, getBoolean = false, errors = false) {
186
- const objectToCopy = this.get(object, pointer, startSlice, endSlice, getBoolean, errors);
187
- return this.forEachDeepCopy(objectToCopy);
188
- }
189
- /**
190
- * 'getFirst' function
191
- *
192
- * Takes an array of JSON Pointers and objects,
193
- * checks each object for a value specified by the pointer,
194
- * and returns the first value found.
195
- *
196
- * // { [object, pointer][] } items - Array of objects and pointers to check
197
- * // { any = null } defaultValue - Value to return if nothing found
198
- * // { boolean = false } getCopy - Return a copy instead?
199
- * // - First value found
200
- */
201
- static getFirst(items, defaultValue = null, getCopy = false) {
202
- if (isEmpty(items)) {
203
- return;
204
- }
205
- if (isArray(items)) {
206
- for (const item of items) {
207
- if (isEmpty(item)) {
208
- continue;
209
- }
210
- if (isArray(item) && item.length >= 2) {
211
- if (isEmpty(item[0]) || isEmpty(item[1])) {
212
- continue;
213
- }
214
- const value = getCopy ?
215
- this.getCopy(item[0], item[1]) :
216
- this.get(item[0], item[1]);
217
- if (value) {
218
- return value;
219
- }
220
- continue;
221
- }
222
- console.error('getFirst error: Input not in correct format.\n' +
223
- 'Should be: [ [ object1, pointer1 ], [ object 2, pointer2 ], etc... ]');
224
- return;
225
- }
226
- return defaultValue;
227
- }
228
- if (isMap(items)) {
229
- for (const [object, pointer] of items) {
230
- if (object === null || !this.isJsonPointer(pointer)) {
231
- continue;
232
- }
233
- const value = getCopy ?
234
- this.getCopy(object, pointer) :
235
- this.get(object, pointer);
236
- if (value) {
237
- return value;
238
- }
239
- }
240
- return defaultValue;
241
- }
242
- console.error('getFirst error: Input not in correct format.\n' +
243
- 'Should be: [ [ object1, pointer1 ], [ object 2, pointer2 ], etc... ]');
244
- return defaultValue;
245
- }
246
- /**
247
- * 'getFirstCopy' function
248
- *
249
- * Similar to getFirst, but always returns a copy.
250
- *
251
- * // { [object, pointer][] } items - Array of objects and pointers to check
252
- * // { any = null } defaultValue - Value to return if nothing found
253
- * // - Copy of first value found
254
- */
255
- static getFirstCopy(items, defaultValue = null) {
256
- const firstCopy = this.getFirst(items, defaultValue, true);
257
- return firstCopy;
258
- }
259
- /**
260
- * 'set' function
261
- *
262
- * Uses a JSON Pointer to set a value on an object.
263
- * Also creates any missing sub objects or arrays to contain that value.
264
- *
265
- * If the optional fourth parameter is TRUE and the inner-most container
266
- * is an array, the function will insert the value as a new item at the
267
- * specified location in the array, rather than overwriting the existing
268
- * value (if any) at that location.
269
- *
270
- * So set([1, 2, 3], '/1', 4) => [1, 4, 3]
271
- * and
272
- * So set([1, 2, 3], '/1', 4, true) => [1, 4, 2, 3]
273
- *
274
- * // { object } object - The object to set value in
275
- * // { Pointer } pointer - The JSON Pointer (string or array)
276
- * // value - The new value to set
277
- * // { boolean } insert - insert value?
278
- * // { object } - The original object, modified with the set value
279
- */
280
- static set(object, pointer, value, insert = false) {
281
- const keyArray = this.parse(pointer);
282
- if (keyArray !== null && keyArray.length) {
283
- let subObject = object;
284
- for (let i = 0; i < keyArray.length - 1; ++i) {
285
- let key = keyArray[i];
286
- if (key === '-' && isArray(subObject)) {
287
- key = subObject.length;
288
- }
289
- if (isMap(subObject) && subObject.has(key)) {
290
- subObject = subObject.get(key);
291
- }
292
- else {
293
- if (!hasOwn(subObject, key)) {
294
- subObject[key] = (keyArray[i + 1].match(/^(\d+|-)$/)) ? [] : {};
295
- }
296
- subObject = subObject[key];
297
- }
298
- }
299
- const lastKey = keyArray[keyArray.length - 1];
300
- if (isArray(subObject) && lastKey === '-') {
301
- subObject.push(value);
302
- }
303
- else if (insert && isArray(subObject) && !isNaN(+lastKey)) {
304
- subObject.splice(lastKey, 0, value);
305
- }
306
- else if (isMap(subObject)) {
307
- subObject.set(lastKey, value);
308
- }
309
- else {
310
- subObject[lastKey] = value;
311
- }
312
- return object;
313
- }
314
- console.error(`set error: Invalid JSON Pointer: ${pointer}`);
315
- return object;
316
- }
317
- /**
318
- * 'setCopy' function
319
- *
320
- * Copies an object and uses a JSON Pointer to set a value on the copy.
321
- * Also creates any missing sub objects or arrays to contain that value.
322
- *
323
- * If the optional fourth parameter is TRUE and the inner-most container
324
- * is an array, the function will insert the value as a new item at the
325
- * specified location in the array, rather than overwriting the existing value.
326
- *
327
- * // { object } object - The object to copy and set value in
328
- * // { Pointer } pointer - The JSON Pointer (string or array)
329
- * // value - The value to set
330
- * // { boolean } insert - insert value?
331
- * // { object } - The new object with the set value
332
- */
333
- static setCopy(object, pointer, value, insert = false) {
334
- const keyArray = this.parse(pointer);
335
- if (keyArray !== null) {
336
- const newObject = copy(object);
337
- let subObject = newObject;
338
- for (let i = 0; i < keyArray.length - 1; ++i) {
339
- let key = keyArray[i];
340
- if (key === '-' && isArray(subObject)) {
341
- key = subObject.length;
342
- }
343
- if (isMap(subObject) && subObject.has(key)) {
344
- subObject.set(key, copy(subObject.get(key)));
345
- subObject = subObject.get(key);
346
- }
347
- else {
348
- if (!hasOwn(subObject, key)) {
349
- subObject[key] = (keyArray[i + 1].match(/^(\d+|-)$/)) ? [] : {};
350
- }
351
- subObject[key] = copy(subObject[key]);
352
- subObject = subObject[key];
353
- }
354
- }
355
- const lastKey = keyArray[keyArray.length - 1];
356
- if (isArray(subObject) && lastKey === '-') {
357
- subObject.push(value);
358
- }
359
- else if (insert && isArray(subObject) && !isNaN(+lastKey)) {
360
- subObject.splice(lastKey, 0, value);
361
- }
362
- else if (isMap(subObject)) {
363
- subObject.set(lastKey, value);
364
- }
365
- else {
366
- subObject[lastKey] = value;
367
- }
368
- return newObject;
369
- }
370
- console.error(`setCopy error: Invalid JSON Pointer: ${pointer}`);
371
- return object;
372
- }
373
- /**
374
- * 'insert' function
375
- *
376
- * Calls 'set' with insert = TRUE
377
- *
378
- * // { object } object - object to insert value in
379
- * // { Pointer } pointer - JSON Pointer (string or array)
380
- * // value - value to insert
381
- * // { object }
382
- */
383
- static insert(object, pointer, value) {
384
- const updatedObject = this.set(object, pointer, value, true);
385
- return updatedObject;
386
- }
387
- /**
388
- * 'insertCopy' function
389
- *
390
- * Calls 'setCopy' with insert = TRUE
391
- *
392
- * // { object } object - object to insert value in
393
- * // { Pointer } pointer - JSON Pointer (string or array)
394
- * // value - value to insert
395
- * // { object }
396
- */
397
- static insertCopy(object, pointer, value) {
398
- const updatedObject = this.setCopy(object, pointer, value, true);
399
- return updatedObject;
400
- }
401
- /**
402
- * 'remove' function
403
- *
404
- * Uses a JSON Pointer to remove a key and its attribute from an object
405
- *
406
- * // { object } object - object to delete attribute from
407
- * // { Pointer } pointer - JSON Pointer (string or array)
408
- * // { object }
409
- */
410
- static remove(object, pointer) {
411
- const keyArray = this.parse(pointer);
412
- if (keyArray !== null && keyArray.length) {
413
- let lastKey = keyArray.pop();
414
- const parentObject = this.get(object, keyArray);
415
- if (isArray(parentObject)) {
416
- if (lastKey === '-') {
417
- lastKey = parentObject.length - 1;
418
- }
419
- parentObject.splice(lastKey, 1);
420
- }
421
- else if (isObject(parentObject)) {
422
- delete parentObject[lastKey];
423
- }
424
- return object;
425
- }
426
- console.error(`remove error: Invalid JSON Pointer: ${pointer}`);
427
- return object;
428
- }
429
- /**
430
- * 'has' function
431
- *
432
- * Tests if an object has a value at the location specified by a JSON Pointer
433
- *
434
- * // { object } object - object to chek for value
435
- * // { Pointer } pointer - JSON Pointer (string or array)
436
- * // { boolean }
437
- */
438
- static has(object, pointer) {
439
- const hasValue = this.get(object, pointer, 0, null, true);
440
- return hasValue;
441
- }
442
- /**
443
- * 'dict' function
444
- *
445
- * Returns a (pointer -> value) dictionary for an object
446
- *
447
- * // { object } object - The object to create a dictionary from
448
- * // { object } - The resulting dictionary object
449
- */
450
- static dict(object) {
451
- const results = {};
452
- this.forEachDeep(object, (value, pointer) => {
453
- if (typeof value !== 'object') {
454
- results[pointer] = value;
455
- }
456
- });
457
- return results;
458
- }
459
- /**
460
- * 'forEachDeep' function
461
- *
462
- * Iterates over own enumerable properties of an object or items in an array
463
- * and invokes an iteratee function for each key/value or index/value pair.
464
- * By default, iterates over items within objects and arrays after calling
465
- * the iteratee function on the containing object or array itself.
466
- *
467
- * The iteratee is invoked with three arguments: (value, pointer, rootObject),
468
- * where pointer is a JSON pointer indicating the location of the current
469
- * value within the root object, and rootObject is the root object initially
470
- * submitted to th function.
471
- *
472
- * If a third optional parameter 'bottomUp' is set to TRUE, the iterator
473
- * function will be called on sub-objects and arrays after being
474
- * called on their contents, rather than before, which is the default.
475
- *
476
- * This function can also optionally be called directly on a sub-object by
477
- * including optional 4th and 5th parameterss to specify the initial
478
- * root object and pointer.
479
- *
480
- * // { object } object - the initial object or array
481
- * // { (v: any, p?: string, o?: any) => any } function - iteratee function
482
- * // { boolean = false } bottomUp - optional, set to TRUE to reverse direction
483
- * // { object = object } rootObject - optional, root object or array
484
- * // { string = '' } pointer - optional, JSON Pointer to object within rootObject
485
- * // { object } - The modified object
486
- */
487
- static forEachDeep(object, fn = (v) => v, bottomUp = false, pointer = '', rootObject = object) {
488
- if (typeof fn !== 'function') {
489
- console.error(`forEachDeep error: Iterator is not a function:`, fn);
490
- return;
491
- }
492
- if (!bottomUp) {
493
- fn(object, pointer, rootObject);
494
- }
495
- if (isObject(object) || isArray(object)) {
496
- for (const key of Object.keys(object)) {
497
- const newPointer = pointer + '/' + this.escape(key);
498
- this.forEachDeep(object[key], fn, bottomUp, newPointer, rootObject);
499
- }
500
- }
501
- if (bottomUp) {
502
- fn(object, pointer, rootObject);
503
- }
504
- }
505
- /**
506
- * 'forEachDeepCopy' function
507
- *
508
- * Similar to forEachDeep, but returns a copy of the original object, with
509
- * the same keys and indexes, but with values replaced with the result of
510
- * the iteratee function.
511
- *
512
- * // { object } object - the initial object or array
513
- * // { (v: any, k?: string, o?: any, p?: any) => any } function - iteratee function
514
- * // { boolean = false } bottomUp - optional, set to TRUE to reverse direction
515
- * // { object = object } rootObject - optional, root object or array
516
- * // { string = '' } pointer - optional, JSON Pointer to object within rootObject
517
- * // { object } - The copied object
518
- */
519
- static forEachDeepCopy(object, fn = (v) => v, bottomUp = false, pointer = '', rootObject = object) {
520
- if (typeof fn !== 'function') {
521
- console.error(`forEachDeepCopy error: Iterator is not a function:`, fn);
522
- return null;
523
- }
524
- if (isObject(object) || isArray(object)) {
525
- let newObject = isArray(object) ? [...object] : { ...object };
526
- if (!bottomUp) {
527
- newObject = fn(newObject, pointer, rootObject);
528
- }
529
- for (const key of Object.keys(newObject)) {
530
- const newPointer = pointer + '/' + this.escape(key);
531
- newObject[key] = this.forEachDeepCopy(newObject[key], fn, bottomUp, newPointer, rootObject);
532
- }
533
- if (bottomUp) {
534
- newObject = fn(newObject, pointer, rootObject);
535
- }
536
- return newObject;
537
- }
538
- else {
539
- return fn(object, pointer, rootObject);
540
- }
541
- }
542
- /**
543
- * 'escape' function
544
- *
545
- * Escapes a string reference key
546
- *
547
- * // { string } key - string key to escape
548
- * // { string } - escaped key
549
- */
550
- static escape(key) {
551
- const escaped = key.toString().replace(/~/g, '~0').replace(/\//g, '~1');
552
- return escaped;
553
- }
554
- /**
555
- * 'unescape' function
556
- *
557
- * Unescapes a string reference key
558
- *
559
- * // { string } key - string key to unescape
560
- * // { string } - unescaped key
561
- */
562
- static unescape(key) {
563
- const unescaped = key.toString().replace(/~1/g, '/').replace(/~0/g, '~');
564
- return unescaped;
565
- }
566
- /**
567
- * 'parse' function
568
- *
569
- * Converts a string JSON Pointer into a array of keys
570
- * (if input is already an an array of keys, it is returned unchanged)
571
- *
572
- * // { Pointer } pointer - JSON Pointer (string or array)
573
- * // { boolean = false } errors - Show error if invalid pointer?
574
- * // { string[] } - JSON Pointer array of keys
575
- */
576
- static parse(pointer, errors = false) {
577
- if (!this.isJsonPointer(pointer)) {
578
- if (errors) {
579
- console.error(`parse error: Invalid JSON Pointer: ${pointer}`);
580
- }
581
- return null;
582
- }
583
- if (isArray(pointer)) {
584
- return pointer;
585
- }
586
- if (typeof pointer === 'string') {
587
- if (pointer[0] === '#') {
588
- pointer = pointer.slice(1);
589
- }
590
- if (pointer === '' || pointer === '/') {
591
- return [];
592
- }
593
- return pointer.slice(1).split('/').map(this.unescape);
594
- }
595
- }
596
- /**
597
- * 'compile' function
598
- *
599
- * Converts an array of keys into a JSON Pointer string
600
- * (if input is already a string, it is normalized and returned)
601
- *
602
- * The optional second parameter is a default which will replace any empty keys.
603
- *
604
- * // { Pointer } pointer - JSON Pointer (string or array)
605
- * // { string | number = '' } defaultValue - Default value
606
- * // { boolean = false } errors - Show error if invalid pointer?
607
- * // { string } - JSON Pointer string
608
- */
609
- static compile(pointer, defaultValue = '', errors = false) {
610
- if (pointer === '#') {
611
- return '';
612
- }
613
- if (!this.isJsonPointer(pointer)) {
614
- if (errors) {
615
- console.error(`compile error: Invalid JSON Pointer: ${pointer}`);
616
- }
617
- return null;
618
- }
619
- if (isArray(pointer)) {
620
- if (pointer.length === 0) {
621
- return '';
622
- }
623
- return '/' + pointer.map(key => key === '' ? defaultValue : this.escape(key)).join('/');
624
- }
625
- if (typeof pointer === 'string') {
626
- if (pointer[0] === '#') {
627
- pointer = pointer.slice(1);
628
- }
629
- return pointer;
630
- }
631
- }
632
- /**
633
- * 'toKey' function
634
- *
635
- * Extracts name of the final key from a JSON Pointer.
636
- *
637
- * // { Pointer } pointer - JSON Pointer (string or array)
638
- * // { boolean = false } errors - Show error if invalid pointer?
639
- * // { string } - the extracted key
640
- */
641
- static toKey(pointer, errors = false) {
642
- const keyArray = this.parse(pointer, errors);
643
- if (keyArray === null) {
644
- return null;
645
- }
646
- if (!keyArray.length) {
647
- return '';
648
- }
649
- return keyArray[keyArray.length - 1];
650
- }
651
- /**
652
- * 'isJsonPointer' function
653
- *
654
- * Checks a string or array value to determine if it is a valid JSON Pointer.
655
- * Returns true if a string is empty, or starts with '/' or '#/'.
656
- * Returns true if an array contains only string values.
657
- *
658
- * // value - value to check
659
- * // { boolean } - true if value is a valid JSON Pointer, otherwise false
660
- */
661
- static isJsonPointer(value) {
662
- if (isArray(value)) {
663
- return value.every(key => typeof key === 'string');
664
- }
665
- else if (isString(value)) {
666
- if (value === '' || value === '#') {
667
- return true;
668
- }
669
- if (value[0] === '/' || value.slice(0, 2) === '#/') {
670
- return !/(~[^01]|~$)/g.test(value);
671
- }
672
- }
673
- return false;
674
- }
675
- /**
676
- * 'isSubPointer' function
677
- *
678
- * Checks whether one JSON Pointer is a subset of another.
679
- *
680
- * // { Pointer } shortPointer - potential subset JSON Pointer
681
- * // { Pointer } longPointer - potential superset JSON Pointer
682
- * // { boolean = false } trueIfMatching - return true if pointers match?
683
- * // { boolean = false } errors - Show error if invalid pointer?
684
- * // { boolean } - true if shortPointer is a subset of longPointer, false if not
685
- */
686
- static isSubPointer(shortPointer, longPointer, trueIfMatching = false, errors = false) {
687
- if (!this.isJsonPointer(shortPointer) || !this.isJsonPointer(longPointer)) {
688
- if (errors) {
689
- let invalid = '';
690
- if (!this.isJsonPointer(shortPointer)) {
691
- invalid += ` 1: ${shortPointer}`;
692
- }
693
- if (!this.isJsonPointer(longPointer)) {
694
- invalid += ` 2: ${longPointer}`;
695
- }
696
- console.error(`isSubPointer error: Invalid JSON Pointer ${invalid}`);
697
- }
698
- return;
699
- }
700
- shortPointer = this.compile(shortPointer, '', errors);
701
- longPointer = this.compile(longPointer, '', errors);
702
- return shortPointer === longPointer ? trueIfMatching :
703
- `${shortPointer}/` === longPointer.slice(0, shortPointer.length + 1);
704
- }
705
- /**
706
- * 'toIndexedPointer' function
707
- *
708
- * Merges an array of numeric indexes and a generic pointer to create an
709
- * indexed pointer for a specific item.
710
- *
711
- * For example, merging the generic pointer '/foo/-/bar/-/baz' and
712
- * the array [4, 2] would result in the indexed pointer '/foo/4/bar/2/baz'
713
- *
714
- *
715
- * // { Pointer } genericPointer - The generic pointer
716
- * // { number[] } indexArray - The array of numeric indexes
717
- * // { Map<string, number> } arrayMap - An optional array map
718
- * // { string } - The merged pointer with indexes
719
- */
720
- static toIndexedPointer(genericPointer, indexArray, arrayMap = null) {
721
- if (this.isJsonPointer(genericPointer) && isArray(indexArray)) {
722
- let indexedPointer = this.compile(genericPointer);
723
- if (isMap(arrayMap)) {
724
- let arrayIndex = 0;
725
- return indexedPointer.replace(/\/\-(?=\/|$)/g, (key, stringIndex) => arrayMap.has(indexedPointer.slice(0, stringIndex)) ?
726
- '/' + indexArray[arrayIndex++] : key);
727
- }
728
- else {
729
- for (const pointerIndex of indexArray) {
730
- indexedPointer = indexedPointer.replace('/-', '/' + pointerIndex);
731
- }
732
- return indexedPointer;
733
- }
734
- }
735
- if (!this.isJsonPointer(genericPointer)) {
736
- console.error(`toIndexedPointer error: Invalid JSON Pointer: ${genericPointer}`);
737
- }
738
- if (!isArray(indexArray)) {
739
- console.error(`toIndexedPointer error: Invalid indexArray: ${indexArray}`);
740
- }
741
- }
742
- /**
743
- * 'toGenericPointer' function
744
- *
745
- * Compares an indexed pointer to an array map and removes list array
746
- * indexes (but leaves tuple arrray indexes and all object keys, including
747
- * numeric keys) to create a generic pointer.
748
- *
749
- * For example, using the indexed pointer '/foo/1/bar/2/baz/3' and
750
- * the arrayMap [['/foo', 0], ['/foo/-/bar', 3], ['/foo/-/bar/-/baz', 0]]
751
- * would result in the generic pointer '/foo/-/bar/2/baz/-'
752
- * Using the indexed pointer '/foo/1/bar/4/baz/3' and the same arrayMap
753
- * would result in the generic pointer '/foo/-/bar/-/baz/-'
754
- * (the bar array has 3 tuple items, so index 2 is retained, but 4 is removed)
755
- *
756
- * The structure of the arrayMap is: [['path to array', number of tuple items]...]
757
- *
758
- *
759
- * // { Pointer } indexedPointer - The indexed pointer (array or string)
760
- * // { Map<string, number> } arrayMap - The optional array map (for preserving tuple indexes)
761
- * // { string } - The generic pointer with indexes removed
762
- */
763
- static toGenericPointer(indexedPointer, arrayMap = new Map()) {
764
- if (this.isJsonPointer(indexedPointer) && isMap(arrayMap)) {
765
- const pointerArray = this.parse(indexedPointer);
766
- for (let i = 1; i < pointerArray.length; i++) {
767
- const subPointer = this.compile(pointerArray.slice(0, i));
768
- if (arrayMap.has(subPointer) &&
769
- arrayMap.get(subPointer) <= +pointerArray[i]) {
770
- pointerArray[i] = '-';
771
- }
772
- }
773
- return this.compile(pointerArray);
774
- }
775
- if (!this.isJsonPointer(indexedPointer)) {
776
- console.error(`toGenericPointer error: invalid JSON Pointer: ${indexedPointer}`);
777
- }
778
- if (!isMap(arrayMap)) {
779
- console.error(`toGenericPointer error: invalid arrayMap: ${arrayMap}`);
780
- }
781
- }
782
- /**
783
- * 'toControlPointer' function
784
- *
785
- * Accepts a JSON Pointer for a data object and returns a JSON Pointer for the
786
- * matching control in an Angular FormGroup.
787
- *
788
- * // { Pointer } dataPointer - JSON Pointer (string or array) to a data object
789
- * // { FormGroup } formGroup - Angular FormGroup to get value from
790
- * // { boolean = false } controlMustExist - Only return if control exists?
791
- * // { Pointer } - JSON Pointer (string) to the formGroup object
792
- */
793
- static toControlPointer(dataPointer, formGroup, controlMustExist = false) {
794
- const dataPointerArray = this.parse(dataPointer);
795
- const controlPointerArray = [];
796
- let subGroup = formGroup;
797
- if (dataPointerArray !== null) {
798
- for (const key of dataPointerArray) {
799
- if (hasOwn(subGroup, 'controls')) {
800
- controlPointerArray.push('controls');
801
- subGroup = subGroup.controls;
802
- }
803
- if (isArray(subGroup) && (key === '-')) {
804
- controlPointerArray.push((subGroup.length - 1).toString());
805
- subGroup = subGroup[subGroup.length - 1];
806
- }
807
- else if (hasOwn(subGroup, key)) {
808
- controlPointerArray.push(key);
809
- subGroup = subGroup[key];
810
- }
811
- else if (controlMustExist) {
812
- console.error(`toControlPointer error: Unable to find "${key}" item in FormGroup.`);
813
- console.error(dataPointer);
814
- console.error(formGroup);
815
- return;
816
- }
817
- else {
818
- controlPointerArray.push(key);
819
- subGroup = { controls: {} };
820
- }
821
- }
822
- return this.compile(controlPointerArray);
823
- }
824
- console.error(`toControlPointer error: Invalid JSON Pointer: ${dataPointer}`);
825
- }
826
- /**
827
- * 'toSchemaPointer' function
828
- *
829
- * Accepts a JSON Pointer to a value inside a data object and a JSON schema
830
- * for that object.
831
- *
832
- * Returns a Pointer to the sub-schema for the value inside the object's schema.
833
- *
834
- * // { Pointer } dataPointer - JSON Pointer (string or array) to an object
835
- * // schema - JSON schema for the object
836
- * // { Pointer } - JSON Pointer (string) to the object's schema
837
- */
838
- static toSchemaPointer(dataPointer, schema) {
839
- if (this.isJsonPointer(dataPointer) && typeof schema === 'object') {
840
- const pointerArray = this.parse(dataPointer);
841
- if (!pointerArray.length) {
842
- return '';
843
- }
844
- const firstKey = pointerArray.shift();
845
- if (schema.type === 'object' || schema.properties || schema.additionalProperties) {
846
- if ((schema.properties || {})[firstKey]) {
847
- return `/properties/${this.escape(firstKey)}` +
848
- this.toSchemaPointer(pointerArray, schema.properties[firstKey]);
849
- }
850
- else if (schema.additionalProperties) {
851
- return '/additionalProperties' +
852
- this.toSchemaPointer(pointerArray, schema.additionalProperties);
853
- }
854
- }
855
- if ((schema.type === 'array' || schema.items) &&
856
- (isNumber(firstKey) || firstKey === '-' || firstKey === '')) {
857
- const arrayItem = firstKey === '-' || firstKey === '' ? 0 : +firstKey;
858
- if (isArray(schema.items)) {
859
- if (arrayItem < schema.items.length) {
860
- return '/items/' + arrayItem +
861
- this.toSchemaPointer(pointerArray, schema.items[arrayItem]);
862
- }
863
- else if (schema.additionalItems) {
864
- return '/additionalItems' +
865
- this.toSchemaPointer(pointerArray, schema.additionalItems);
866
- }
867
- }
868
- else if (isObject(schema.items)) {
869
- return '/items' + this.toSchemaPointer(pointerArray, schema.items);
870
- }
871
- else if (isObject(schema.additionalItems)) {
872
- return '/additionalItems' +
873
- this.toSchemaPointer(pointerArray, schema.additionalItems);
874
- }
875
- }
876
- console.error(`toSchemaPointer error: Data pointer ${dataPointer} ` +
877
- `not compatible with schema ${schema}`);
878
- return null;
879
- }
880
- if (!this.isJsonPointer(dataPointer)) {
881
- console.error(`toSchemaPointer error: Invalid JSON Pointer: ${dataPointer}`);
882
- }
883
- if (typeof schema !== 'object') {
884
- console.error(`toSchemaPointer error: Invalid JSON Schema: ${schema}`);
885
- }
886
- return null;
887
- }
888
- /**
889
- * 'toDataPointer' function
890
- *
891
- * Accepts a JSON Pointer to a sub-schema inside a JSON schema and the schema.
892
- *
893
- * If possible, returns a generic Pointer to the corresponding value inside
894
- * the data object described by the JSON schema.
895
- *
896
- * Returns null if the sub-schema is in an ambiguous location (such as
897
- * definitions or additionalProperties) where the corresponding value
898
- * location cannot be determined.
899
- *
900
- * // { Pointer } schemaPointer - JSON Pointer (string or array) to a JSON schema
901
- * // schema - the JSON schema
902
- * // { boolean = false } errors - Show errors?
903
- * // { Pointer } - JSON Pointer (string) to the value in the data object
904
- */
905
- static toDataPointer(schemaPointer, schema, errors = false) {
906
- if (this.isJsonPointer(schemaPointer) && typeof schema === 'object' &&
907
- this.has(schema, schemaPointer)) {
908
- const pointerArray = this.parse(schemaPointer);
909
- if (!pointerArray.length) {
910
- return '';
911
- }
912
- const firstKey = pointerArray.shift();
913
- if (firstKey === 'properties' ||
914
- (firstKey === 'items' && isArray(schema.items))) {
915
- const secondKey = pointerArray.shift();
916
- const pointerSuffix = this.toDataPointer(pointerArray, schema[firstKey][secondKey]);
917
- return pointerSuffix === null ? null : '/' + secondKey + pointerSuffix;
918
- }
919
- else if (firstKey === 'additionalItems' ||
920
- (firstKey === 'items' && isObject(schema.items))) {
921
- const pointerSuffix = this.toDataPointer(pointerArray, schema[firstKey]);
922
- return pointerSuffix === null ? null : '/-' + pointerSuffix;
923
- }
924
- else if (['allOf', 'anyOf', 'oneOf'].includes(firstKey)) {
925
- const secondKey = pointerArray.shift();
926
- return this.toDataPointer(pointerArray, schema[firstKey][secondKey]);
927
- }
928
- else if (firstKey === 'not') {
929
- return this.toDataPointer(pointerArray, schema[firstKey]);
930
- }
931
- else if (['contains', 'definitions', 'dependencies', 'additionalItems',
932
- 'additionalProperties', 'patternProperties', 'propertyNames'].includes(firstKey)) {
933
- if (errors) {
934
- console.error(`toDataPointer error: Ambiguous location`);
935
- }
936
- }
937
- return '';
938
- }
939
- if (errors) {
940
- if (!this.isJsonPointer(schemaPointer)) {
941
- console.error(`toDataPointer error: Invalid JSON Pointer: ${schemaPointer}`);
942
- }
943
- if (typeof schema !== 'object') {
944
- console.error(`toDataPointer error: Invalid JSON Schema: ${schema}`);
945
- }
946
- if (typeof schema !== 'object') {
947
- console.error(`toDataPointer error: Pointer ${schemaPointer} invalid for Schema: ${schema}`);
948
- }
949
- }
950
- return null;
951
- }
952
- /**
953
- * 'parseObjectPath' function
954
- *
955
- * Parses a JavaScript object path into an array of keys, which
956
- * can then be passed to compile() to convert into a string JSON Pointer.
957
- *
958
- * Based on mike-marcacci's excellent objectpath parse function:
959
- * https://github.com/mike-marcacci/objectpath
960
- *
961
- * // { Pointer } path - The object path to parse
962
- * // { string[] } - The resulting array of keys
963
- */
964
- static parseObjectPath(path) {
965
- if (isArray(path)) {
966
- return path;
967
- }
968
- if (this.isJsonPointer(path)) {
969
- return this.parse(path);
970
- }
971
- if (typeof path === 'string') {
972
- let index = 0;
973
- const parts = [];
974
- while (index < path.length) {
975
- const nextDot = path.indexOf('.', index);
976
- const nextOB = path.indexOf('[', index); // next open bracket
977
- if (nextDot === -1 && nextOB === -1) { // last item
978
- parts.push(path.slice(index));
979
- index = path.length;
980
- }
981
- else if (nextDot !== -1 && (nextDot < nextOB || nextOB === -1)) { // dot notation
982
- parts.push(path.slice(index, nextDot));
983
- index = nextDot + 1;
984
- }
985
- else { // bracket notation
986
- if (nextOB > index) {
987
- parts.push(path.slice(index, nextOB));
988
- index = nextOB;
989
- }
990
- const quote = path.charAt(nextOB + 1);
991
- if (quote === '"' || quote === '\'') { // enclosing quotes
992
- let nextCB = path.indexOf(quote + ']', nextOB); // next close bracket
993
- while (nextCB !== -1 && path.charAt(nextCB - 1) === '\\') {
994
- nextCB = path.indexOf(quote + ']', nextCB + 2);
995
- }
996
- if (nextCB === -1) {
997
- nextCB = path.length;
998
- }
999
- parts.push(path.slice(index + 2, nextCB)
1000
- .replace(new RegExp('\\' + quote, 'g'), quote));
1001
- index = nextCB + 2;
1002
- }
1003
- else { // no enclosing quotes
1004
- let nextCB = path.indexOf(']', nextOB); // next close bracket
1005
- if (nextCB === -1) {
1006
- nextCB = path.length;
1007
- }
1008
- parts.push(path.slice(index + 1, nextCB));
1009
- index = nextCB + 1;
1010
- }
1011
- if (path.charAt(index) === '.') {
1012
- index++;
1013
- }
1014
- }
1015
- }
1016
- return parts;
1017
- }
1018
- console.error('parseObjectPath error: Input object path must be a string.');
1019
- }
1020
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: JsonPointer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1021
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: JsonPointer }); }
1022
- }
1023
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: JsonPointer, decorators: [{
1024
- type: Injectable
1025
- }] });
1026
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbnBvaW50ZXIuZnVuY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZm9ybXdvcmtzLWNvcmUvc3JjL2xpYi9zaGFyZWQvanNvbnBvaW50ZXIuZnVuY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsSUFBSSxFQUVKLGlCQUFpQixFQUNqQiw4QkFBOEIsRUFDOUIsTUFBTSxFQUNOLE9BQU8sRUFDUCxVQUFVLEVBQ1YsZUFBZSxFQUNoQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDOztBQW1CdkcsTUFBTSxPQUFPLFdBQVc7SUFFdEI7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsTUFBTSxDQUFDLEdBQUcsQ0FDUixNQUFNLEVBQUUsT0FBTyxFQUFFLFVBQVUsR0FBRyxDQUFDLEVBQUUsV0FBbUIsSUFBSSxFQUN4RCxVQUFVLEdBQUcsS0FBSyxFQUFFLE1BQU0sR0FBRyxLQUFLO1FBRWxDLElBQUksTUFBTSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQUMsT0FBTyxVQUFVLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO1FBQUMsQ0FBQztRQUMvRCxJQUFJLFFBQVEsR0FBVSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNsRCxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxRQUFRLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDcEQsSUFBSSxTQUFTLEdBQUcsTUFBTSxDQUFDO1lBQ3ZCLElBQUksVUFBVSxJQUFJLFFB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QUMsSUFBSSxNQUFNLENBQUMsSUFBSSxHQUFHLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO3dCQUNsRCxLQUFLLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FBQztvQkFDckIsQ0FBQzt5QkFBTSxDQUFDLENBQUMsc0JBQXNCO3dCQUM3QixJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLHFCQUFxQjt3QkFDN0QsSUFBSSxNQUFNLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQzs0QkFBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQzt3QkFBQyxDQUFDO3dCQUM1QyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO3dCQUMxQyxLQUFLLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FBQztvQkFDckIsQ0FBQztvQkFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7d0JBQUMsS0FBSyxFQUFFLENBQUM7b0JBQUMsQ0FBQztnQkFDOUMsQ0FBQztZQUNILENBQUM7WUFDRCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7UUFDRCxPQUFPLENBQUMsS0FBSyxDQUFDLDREQUE0RCxDQUFDLENBQUM7SUFDOUUsQ0FBQzsrR0FuOUJVLFdBQVc7bUhBQVgsV0FBVzs7NEZBQVgsV0FBVztrQkFEdkIsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgY2xlYW5WYWx1ZU9mUXVvdGVzLFxyXG4gIGNvcHksXHJcbiAgRXhwcmVzc2lvblR5cGUsXHJcbiAgZ2V0RXhwcmVzc2lvblR5cGUsXHJcbiAgZ2V0S2V5QW5kVmFsdWVCeUV4cHJlc3Npb25UeXBlLFxyXG4gIGhhc093bixcclxuICBpc0VxdWFsLFxyXG4gIGlzTm90RXF1YWwsXHJcbiAgaXNOb3RFeHByZXNzaW9uXHJcbn0gZnJvbSAnLi91dGlsaXR5LmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7aXNBcnJheSwgaXNEZWZpbmVkLCBpc0VtcHR5LCBpc01hcCwgaXNOdW1iZXIsIGlzT2JqZWN0LCBpc1N0cmluZ30gZnJvbSAnLi92YWxpZGF0b3IuZnVuY3Rpb25zJztcclxuXHJcbi8qKlxyXG4gKiAnSnNvblBvaW50ZXInIGNsYXNzXHJcbiAqXHJcbiAqIFNvbWUgdXRpbGl0aWVzIGZvciB1c2luZyBKU09OIFBvaW50ZXJzIHdpdGggSlNPTiBvYmplY3RzXHJcbiAqIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2OTAxXHJcbiAqXHJcbiAqIGdldCwgZ2V0Q29weSwgZ2V0Rmlyc3QsIHNldCwgc2V0Q29weSwgaW5zZXJ0LCBpbnNlcnRDb3B5LCByZW1vdmUsIGhhcywgZGljdCxcclxuICogZm9yRWFjaERlZXAsIGZvckVhY2hEZWVwQ29weSwgZXNjYXBlLCB1bmVzY2FwZSwgcGFyc2UsIGNvbXBpbGUsIHRvS2V5LFxyXG4gKiBpc0pzb25Qb2ludGVyLCBpc1N1YlBvaW50ZXIsIHRvSW5kZXhlZFBvaW50ZXIsIHRvR2VuZXJpY1BvaW50ZXIsXHJcbiAqIHRvQ29udHJvbFBvaW50ZXIsIHRvU2NoZW1hUG9pbnRlciwgdG9EYXRhUG9pbnRlciwgcGFyc2VPYmplY3RQYXRoXHJcbiAqXHJcbiAqIFNvbWUgZnVuY3Rpb25zIGJhc2VkIG9uIG1hbnVlbHN0b2ZlcidzIGpzb24tcG9pbnRlciB1dGlsaXRpZXNcclxuICogaHR0cHM6Ly9naXRodWIuY29tL21hbnVlbHN0b2Zlci9qc29uLXBvaW50ZXJcclxuICovXHJcbmV4cG9ydCB0eXBlIFBvaW50ZXIgPSBzdHJpbmcgfCBzdHJpbmdbXTtcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEpzb25Qb2ludGVyIHtcclxuXHJcbiAgLyoqXHJcbiAgICogJ2dldCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gcmV0cmlldmUgYSB2YWx1ZSBmcm9tIGFuIG9iamVjdC5cclxuICAgKlxyXG4gICAqIC8vICB7IG9iamVjdCB9IG9iamVjdCAtIE9iamVjdCB0byBnZXQgdmFsdWUgZnJvbVxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8gIHsgbnVtYmVyID0gMCB9IHN0YXJ0U2xpY2UgLSBaZXJvLWJhc2VkIGluZGV4IG9mIGZpcnN0IFBvaW50ZXIga2V5IHRvIHVzZVxyXG4gICAqIC8vICB7IG51bWJlciB9IGVuZFNsaWNlIC0gWmVyby1iYXNlZCBpbmRleCBvZiBsYXN0IFBvaW50ZXIga2V5IHRvIHVzZVxyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGdldEJvb2xlYW4gLSBSZXR1cm4gb25seSB0cnVlIG9yIGZhbHNlP1xyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGVycm9ycyAtIFNob3cgZXJyb3IgaWYgbm90IGZvdW5kP1xyXG4gICAqIC8vIHsgb2JqZWN0IH0gLSBMb2NhdGVkIHZhbHVlIChvciB0cnVlIG9yIGZhbHNlIGlmIGdldEJvb2xlYW4gPSB0cnVlKVxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXQoXHJcbiAgICBvYmplY3QsIHBvaW50ZXIsIHN0YXJ0U2xpY2UgPSAwLCBlbmRTbGljZTogbnVtYmVyID0gbnVsbCxcclxuICAgIGdldEJvb2xlYW4gPSBmYWxzZSwgZXJyb3JzID0gZmFsc2VcclxuICApIHtcclxuICAgIGlmIChvYmplY3QgPT09IG51bGwpIHsgcmV0dXJuIGdldEJvb2xlYW4gPyBmYWxzZSA6IHVuZGVmaW5lZDsgfVxyXG4gICAgbGV0IGtleUFycmF5OiBhbnlbXSA9IHRoaXMucGFyc2UocG9pbnRlciwgZXJyb3JzKTtcclxuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09PSAnb2JqZWN0JyAmJiBrZXlBcnJheSAhPT0gbnVsbCkge1xyXG4gICAgICBsZXQgc3ViT2JqZWN0ID0gb2JqZWN0O1xyXG4gICAgICBpZiAoc3RhcnRTbGljZSA+PSBrZXlBcnJheS5sZW5ndGggfHwgZW5kU2xpY2UgPD0gLWtleUFycmF5Lmxlbmd0aCkgeyByZXR1cm4gb2JqZWN0OyB9XHJcbiAgICAgIGlmIChzdGFydFNsaWNlIDw9IC1rZXlBcnJheS5sZW5ndGgpIHsgc3RhcnRTbGljZSA9IDA7IH1cclxuICAgICAgaWYgKCFpc0RlZmluZWQoZW5kU2xpY2UpIHx8IGVuZFNsaWNlID49IGtleUFycmF5Lmxlbmd0aCkgeyBlbmRTbGljZSA9IGtleUFycmF5Lmxlbmd0aDsgfVxyXG4gICAgICBrZXlBcnJheSA9IGtleUFycmF5LnNsaWNlKHN0YXJ0U2xpY2UsIGVuZFNsaWNlKTtcclxuICAgICAgZm9yIChsZXQga2V5IG9mIGtleUFycmF5KSB7XHJcbiAgICAgICAgaWYgKGtleSA9PT0gJy0nICYmIGlzQXJyYXkoc3ViT2JqZWN0KSAmJiBzdWJPYmplY3QubGVuZ3RoKSB7XHJcbiAgICAgICAgICBrZXkgPSBzdWJPYmplY3QubGVuZ3RoIC0gMTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGlzTWFwKHN1Yk9iamVjdCkgJiYgc3ViT2JqZWN0LmhhcyhrZXkpKSB7XHJcbiAgICAgICAgICBzdWJPYmplY3QgPSBzdWJPYmplY3QuZ2V0KGtleSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygc3ViT2JqZWN0ID09PSAnb2JqZWN0JyAmJiBzdWJPYmplY3QgIT09IG51bGwgJiZcclxuICAgICAgICAgIGhhc093bihzdWJPYmplY3QsIGtleSlcclxuICAgICAgICApIHtcclxuICAgICAgICAgIHN1Yk9iamVjdCA9IHN1Yk9iamVjdFtrZXldO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBldmFsdWF0ZWRFeHByZXNzaW9uID0gSnNvblBvaW50ZXIuZXZhbHVhdGVFeHByZXNzaW9uKHN1Yk9iamVjdCwga2V5KTtcclxuICAgICAgICAgIGlmIChldmFsdWF0ZWRFeHByZXNzaW9uLnBhc3NlZCkge1xyXG4gICAgICAgICAgICBzdWJPYmplY3QgPSBldmFsdWF0ZWRFeHByZXNzaW9uLmtleSA/IHN1Yk9iamVjdFtldmFsdWF0ZWRFeHByZXNzaW9uLmtleV0gOiBzdWJPYmplY3Q7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ0Vycm9ycyhlcnJvcnMsIGtleSwgcG9pbnRlciwgb2JqZWN0KTtcclxuICAgICAgICAgICAgcmV0dXJuIGdldEJvb2xlYW4gPyBmYWxzZSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGdldEJvb2xlYW4gPyB0cnVlIDogc3ViT2JqZWN0O1xyXG4gICAgfVxyXG4gICAgaWYgKGVycm9ycyAmJiBrZXlBcnJheSA9PT0gbnVsbCkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBnZXQgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke3BvaW50ZXJ9YCk7XHJcbiAgICB9XHJcbiAgICBpZiAoZXJyb3JzICYmIHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ2dldCBlcnJvcjogSW52YWxpZCBvYmplY3Q6Jyk7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3Iob2JqZWN0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBnZXRCb29sZWFuID8gZmFsc2UgOiB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXRpYyBsb2dFcnJvcnMoZXJyb3JzLCBrZXksIHBvaW50ZXIsIG9iamVjdCkge1xyXG4gICAgaWYgKGVycm9ycykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBnZXQgZXJyb3I6IFwiJHtrZXl9XCIga2V5IG5vdCBmb3VuZCBpbiBvYmplY3QuYCk7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IocG9pbnRlcik7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3Iob2JqZWN0KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2YWx1YXRlcyBjb25kaXRpb25hbCBleHByZXNzaW9uIGluIGZvcm0gb2YgYG1vZGVsLjxwcm9wZXJ0eT49PTx2YWx1ZT5gIG9yXHJcbiAgICogYG1vZGVsLjxwcm9wZXJ0eT4hPTx2YWx1ZT5gIHdoZXJlIHRoZSBmaXJzdCBvbmUgbWVhbnMgdGhhdCB0aGUgdmFsdWUgbXVzdCBtYXRjaCB0byBiZVxyXG4gICAqIHNob3duIGluIGEgZm9ybSwgd2hpbGUgdGhlIGZvcm1lciBzaG93cyB0aGUgcHJvcGVydHkgb25seSB3aGVuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBub3RcclxuICAgKiBzZXQsIG9yIGRvZXMgbm90IGVxdWFsIHRoZSBnaXZlbiB2YWx1ZS5cclxuICAgKlxyXG4gICAqIC8vIHsgc3ViT2JqZWN0IH0gc3ViT2JqZWN0IC0gIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBkYXRhIHZhbHVlcyBvZiBwcm9wZXJ0aWVzXHJcbiAgICogLy8geyBrZXkgfSBrZXkgLSB0aGUga2V5IGZyb20gdGhlIGZvciBsb29wIGluIGEgZm9ybSBvZiBgPHByb3BlcnR5Pj09PHZhbHVlPmBcclxuICAgKlxyXG4gICAqIFJldHVybnMgdGhlIG9iamVjdCB3aXRoIHR3byBwcm9wZXJ0aWVzLiBUaGUgcHJvcGVydHkgcGFzc2VkIGluZm9ybXMgd2hldGhlclxyXG4gICAqIHRoZSBleHByZXNzaW9uIGV2YWx1YXRlZCBzdWNjZXNzZnVsbHkgYW5kIHRoZSBwcm9wZXJ0eSBrZXkgcmV0dXJucyBlaXRoZXIgdGhlIHNhbWVcclxuICAgKiBrZXkgaWYgaXQgaXMgbm90IGNvbnRhaW5lZCBpbnNpZGUgdGhlIHN1Yk9iamVjdCBvciB0aGUga2V5IG9mIHRoZSBwcm9wZXJ0eSBpZiBpdCBpcyBjb250YWluZWQuXHJcbiAgICovXHJcbiAgc3RhdGljIGV2YWx1YXRlRXhwcmVzc2lvbihzdWJPYmplY3Q6IE9iamVjdCwga2V5OiBhbnkpIHtcclxuICAgIGNvbnN0IGRlZmF1bHRSZXN1bHQgPSB7cGFzc2VkOiBmYWxzZSwga2V5OiBrZXl9O1xyXG4gICAgY29uc3Qga2V5c0FuZEV4cHJlc3Npb24gPSB0aGlzLnBhcnNlS2V5c0FuZEV4cHJlc3Npb24oa2V5LCBzdWJPYmplY3QpO1xyXG4gICAgaWYgKCFrZXlzQW5kRXhwcmVzc2lvbikge1xyXG4gICAgICByZXR1cm4gZGVmYXVsdFJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBvd25DaGVja1Jlc3VsdCA9IHRoaXMuZG9Pd25DaGVja1Jlc3VsdChzdWJPYmplY3QsIGtleXNBbmRFeHByZXNzaW9uKTtcclxuICAgIGlmIChvd25DaGVja1Jlc3VsdCkge1xyXG4gICAgICByZXR1cm4gb3duQ2hlY2tSZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY2xlYW5lZFZhbHVlID0gY2xlYW5WYWx1ZU9mUXVvdGVzKGtleXNBbmRFeHByZXNzaW9uLmtleUFuZFZhbHVlWzFdKTtcclxuXHJcbiAgICBjb25zdCBldmFsdWF0ZWRSZXN1bHQgPSB0aGlzLnBlcmZvcm1FeHByZXNzaW9uT25WYWx1ZShrZXlzQW5kRXhwcmVzc2lvbiwgY2xlYW5lZFZhbHVlLCBzdWJPYmplY3QpO1xyXG4gICAgaWYgKGV2YWx1YXRlZFJlc3VsdCkge1xyXG4gICAgICByZXR1cm4gZXZhbHVhdGVkUmVzdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkZWZhdWx0UmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgdGhlIGFjdHVhbCBldmFsdWF0aW9uIG9uIHRoZSBnaXZlbiBleHByZXNzaW9uIHdpdGggZ2l2ZW4gdmFsdWVzIGFuZCBrZXlzLlxyXG4gICAqIC8vIHsgY2xlYW5lZFZhbHVlIH0gY2xlYW5lZFZhbHVlIC0gdGhlIGdpdmVuIHZhbHVlZCBjbGVhbmVkIG9mIHF1b3RlcyBpZiBpdCBoYWQgYW55XHJcbiAgICogLy8geyBzdWJPYmplY3QgfSBzdWJPYmplY3QgLSB0aGUgb2JqZWN0IHdpdGggcHJvcGVydGllcyB2YWx1ZXNcclxuICAgKiAvLyB7IGtleXNBbmRFeHByZXNzaW9uIH0ga2V5c0FuZEV4cHJlc3Npb24gLSBhbiBvYmplY3QgaG9sZGluZyB0aGUgZXhwcmVzc2lvbnMgd2l0aFxyXG4gICAqL1xyXG4gIHByaXZhdGUgc3RhdGljIHBlcmZvcm1FeHByZXNzaW9uT25WYWx1ZShrZXlzQW5kRXhwcmVzc2lvbjogYW55LCBjbGVhbmVkVmFsdWU6IFN0cmluZywgc3ViT2JqZWN0OiBPYmplY3QpIHtcclxuICAgIGNvbnN0IHByb3BlcnR5QnlLZXkgPSBzdWJPYmplY3Rba2V5c0FuZEV4cHJlc3Npb24ua2V5QW5kVmFsdWVbMF1dO1xyXG4gICAgaWYgKHRoaXMuZG9Db21wYXJpc29uQnlFeHByZXNzaW9uVHlwZShrZXlzQW5kRXhwcmVzc2lvbi5leHByZXNzaW9uVHlwZSwgcHJvcGVydHlCeUtleSwgY2xlYW5lZFZhbHVlKSkge1xyXG4gICAgICByZXR1cm4ge3Bhc3NlZDogdHJ1ZSwga2V5OiBrZXlzQW5kRXhwcmVzc2lvbi5rZXlBbmRWYWx1ZVswXX07XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXRpYyBkb0NvbXBhcmlzb25CeUV4cHJlc3Npb25UeXBlKGV4cHJlc3Npb25UeXBlOiBFeHByZXNzaW9uVHlwZSwgcHJvcGVydHlCeUtleSwgY2xlYW5lZFZhbHVlOiBTdHJpbmcpOiBCb29sZWFuIHtcclxuICAgIGlmIChpc0VxdWFsKGV4cHJlc3Npb25UeXBlKSkge1xyXG4gICAgICByZXR1cm4gcHJvcGVydHlCeUtleSA9PT0gY2xlYW5lZFZhbHVlO1xyXG4gICAgfVxyXG4gICAgaWYgKGlzTm90RXF1YWwoZXhwcmVzc2lvblR5cGUpKSB7XHJcbiAgICAgIHJldHVybiBwcm9wZXJ0eUJ5S2V5ICE9PSBjbGVhbmVkVmFsdWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEb2VzIHRoZSBjaGVja3Mgd2hlbiB0aGUgcGFyc2VkIGtleSBpcyBhY3R1YWxseSBubyBhIHByb3BlcnR5IGluc2lkZSBzdWJPYmplY3QuXHJcbiAgICogVGhhdCB3b3VsZCBtZWFuIHRoYXQgdGhlIGVxdWFsIGNvbXBhcmlzb24gbWFrZXMgbm8gc2Vuc2UgYW5kIHRodXMgdGhlIG5lZ2F0aXZlIHJlc3VsdFxyXG4gICAqIGlzIHJldHVybmVkLCBhbmQgdGhlIG5vdCBlcXVhbCBjb21wYXJpc29uIGlzIG5vdCBuZWNlc3NhcnkgYmVjYXVzZSBpdCBkb2Vzbid0IGVxdWFsXHJcbiAgICogb2J2aW91c2x5LiBSZXR1cm5zIG51bGwgd2hlbiB0aGUgZ2l2ZW4ga2V5IGlzIGEgcmVhbCBwcm9wZXJ0eSBpbnNpZGUgdGhlIHN1Yk9iamVjdC5cclxuICAgKiAvLyB7IHN1Yk9iamVjdCB9IHN1Yk9iamVjdCAtIHRoZSBvYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIHZhbHVlc1xyXG4gICAqIC8vIHsga2V5c0FuZEV4cHJlc3Npb24gfSBrZXlzQW5kRXhwcmVzc2lvbiAtIGFuIG9iamVjdCBob2xkaW5nIHRoZSBleHByZXNzaW9ucyB3aXRoXHJcbiAgICogdGhlIGFzc29jaWF0ZWQga2V5cy5cclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBkb093bkNoZWNrUmVzdWx0KHN1Yk9iamVjdDogT2JqZWN0LCBrZXlzQW5kRXhwcmVzc2lvbikge1xyXG4gICAgbGV0IG93bkNoZWNrUmVzdWx0ID0gbnVsbDtcclxuICAgIGlmICghaGFzT3duKHN1Yk9iamVjdCwga2V5c0FuZEV4cHJlc3Npb24ua2V5QW5kVmFsdWVbMF0pKSB7XHJcbiAgICAgIGlmIChpc0VxdWFsKGtleXNBbmRFeHByZXNzaW9uLmV4cHJlc3Npb25UeXBlKSkge1xyXG4gICAgICAgIG93bkNoZWNrUmVzdWx0ID0ge3Bhc3NlZDogZmFsc2UsIGtleTogbnVsbH07XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGlzTm90RXF1YWwoa2V5c0FuZEV4cHJlc3Npb24uZXhwcmVzc2lvblR5cGUpKSB7XHJcbiAgICAgICAgb3duQ2hlY2tSZXN1bHQgPSB7cGFzc2VkOiB0cnVlLCBrZXk6IG51bGx9O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gb3duQ2hlY2tSZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEb2VzIHRoZSBiYXNpYyBjaGVja3MgYW5kIHRyaWVzIHRvIHBhcnNlIGFuIGV4cHJlc3Npb24gYW5kIGEgcGFpclxyXG4gICAqIG9mIGtleSBhbmQgdmFsdWUuXHJcbiAgICogLy8geyBrZXkgfSBrZXkgLSB0aGUgb3JpZ2luYWwgZm9yIGxvb3AgY3JlYXRlZCB2YWx1ZSBjb250YWluaW5nIGtleSBhbmQgdmFsdWUgaW4gb25lIHN0cmluZ1xyXG4gICAqIC8vIHsgc3ViT2JqZWN0IH0gc3ViT2JqZWN0IC0gdGhlIG9iamVjdCB3aXRoIHByb3BlcnRpZXMgdmFsdWVzXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VLZXlzQW5kRXhwcmVzc2lvbihrZXk6IHN0cmluZywgc3ViT2JqZWN0KSB7XHJcbiAgICBpZiAodGhpcy5rZXlPclN1Yk9iakVtcHR5KGtleSwgc3ViT2JqZWN0KSkge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGNvbnN0IGV4cHJlc3Npb25UeXBlID0gZ2V0RXhwcmVzc2lvblR5cGUoa2V5LnRvU3RyaW5nKCkpO1xyXG4gICAgaWYgKGlzTm90RXhwcmVzc2lvbihleHByZXNzaW9uVHlwZSkpIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICBjb25zdCBrZXlBbmRWYWx1ZSA9IGdldEtleUFuZFZhbHVlQnlFeHByZXNzaW9uVHlwZShleHByZXNzaW9uVHlwZSwga2V5KTtcclxuICAgIGlmICgha2V5QW5kVmFsdWUgfHwgIWtleUFuZFZhbHVlWzBdIHx8ICFrZXlBbmRWYWx1ZVsxXSkge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIHJldHVybiB7ZXhwcmVzc2lvblR5cGU6IGV4cHJlc3Npb25UeXBlLCBrZXlBbmRWYWx1ZToga2V5QW5kVmFsdWV9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzdGF0aWMga2V5T3JTdWJPYmpFbXB0eShrZXk6IGFueSwgc3ViT2JqZWN0OiBPYmplY3QpIHtcclxuICAgIHJldHVybiAha2V5IHx8ICFzdWJPYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZ2V0Q29weScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gZGVlcGx5IGNsb25lIGEgdmFsdWUgZnJvbSBhbiBvYmplY3QuXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBPYmplY3QgdG8gZ2V0IHZhbHVlIGZyb21cclxuICAgKiAvLyAgeyBQb2ludGVyIH0gcG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICB7IG51bWJlciA9IDAgfSBzdGFydFNsaWNlIC0gWmVyby1iYXNlZCBpbmRleCBvZiBmaXJzdCBQb2ludGVyIGtleSB0byB1c2VcclxuICAgKiAvLyAgeyBudW1iZXIgfSBlbmRTbGljZSAtIFplcm8tYmFzZWQgaW5kZXggb2YgbGFzdCBQb2ludGVyIGtleSB0byB1c2VcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBnZXRCb29sZWFuIC0gUmV0dXJuIG9ubHkgdHJ1ZSBvciBmYWxzZT9cclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBlcnJvcnMgLSBTaG93IGVycm9yIGlmIG5vdCBmb3VuZD9cclxuICAgKiAvLyB7IG9iamVjdCB9IC0gTG9jYXRlZCB2YWx1ZSAob3IgdHJ1ZSBvciBmYWxzZSBpZiBnZXRCb29sZWFuID0gdHJ1ZSlcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0Q29weShcclxuICAgIG9iamVjdCwgcG9pbnRlciwgc3RhcnRTbGljZSA9IDAsIGVuZFNsaWNlOiBudW1iZXIgPSBudWxsLFxyXG4gICAgZ2V0Qm9vbGVhbiA9IGZhbHNlLCBlcnJvcnMgPSBmYWxzZVxyXG4gICkge1xyXG4gICAgY29uc3Qgb2JqZWN0VG9Db3B5ID1cclxuICAgICAgdGhpcy5nZXQob2JqZWN0LCBwb2ludGVyLCBzdGFydFNsaWNlLCBlbmRTbGljZSwgZ2V0Qm9vbGVhbiwgZXJyb3JzKTtcclxuICAgIHJldHVybiB0aGlzLmZvckVhY2hEZWVwQ29weShvYmplY3RUb0NvcHkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2dldEZpcnN0JyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogVGFrZXMgYW4gYXJyYXkgb2YgSlNPTiBQb2ludGVycyBhbmQgb2JqZWN0cyxcclxuICAgKiBjaGVja3MgZWFjaCBvYmplY3QgZm9yIGEgdmFsdWUgc3BlY2lmaWVkIGJ5IHRoZSBwb2ludGVyLFxyXG4gICAqIGFuZCByZXR1cm5zIHRoZSBmaXJzdCB2YWx1ZSBmb3VuZC5cclxuICAgKlxyXG4gICAqIC8vICB7IFtvYmplY3QsIHBvaW50ZXJdW10gfSBpdGVtcyAtIEFycmF5IG9mIG9iamVjdHMgYW5kIHBvaW50ZXJzIHRvIGNoZWNrXHJcbiAgICogLy8gIHsgYW55ID0gbnVsbCB9IGRlZmF1bHRWYWx1ZSAtIFZhbHVlIHRvIHJldHVybiBpZiBub3RoaW5nIGZvdW5kXHJcbiAgICogLy8gIHsgYm9vbGVhbiA9IGZhbHNlIH0gZ2V0Q29weSAtIFJldHVybiBhIGNvcHkgaW5zdGVhZD9cclxuICAgKiAvLyAgLSBGaXJzdCB2YWx1ZSBmb3VuZFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXRGaXJzdChpdGVtcywgZGVmYXVsdFZhbHVlOiBhbnkgPSBudWxsLCBnZXRDb3B5ID0gZmFsc2UpIHtcclxuICAgIGlmIChpc0VtcHR5KGl0ZW1zKSkgeyByZXR1cm47IH1cclxuICAgIGlmIChpc0FycmF5KGl0ZW1zKSkge1xyXG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcclxuICAgICAgICBpZiAoaXNFbXB0eShpdGVtKSkgeyBjb250aW51ZTsgfVxyXG4gICAgICAgIGlmIChpc0FycmF5KGl0ZW0pICYmIGl0ZW0ubGVuZ3RoID49IDIpIHtcclxuICAgICAgICAgIGlmIChpc0VtcHR5KGl0ZW1bMF0pIHx8IGlzRW1wdHkoaXRlbVsxXSkpIHsgY29udGludWU7IH1cclxuICAgICAgICAgIGNvbnN0IHZhbHVlID0gZ2V0Q29weSA/XHJcbiAgICAgICAgICAgIHRoaXMuZ2V0Q29weShpdGVtWzBdLCBpdGVtWzFdKSA6XHJcbiAgICAgICAgICAgIHRoaXMuZ2V0KGl0ZW1bMF0sIGl0ZW1bMV0pO1xyXG4gICAgICAgICAgaWYgKHZhbHVlKSB7IHJldHVybiB2YWx1ZTsgfVxyXG4gICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ2dldEZpcnN0IGVycm9yOiBJbnB1dCBub3QgaW4gY29ycmVjdCBmb3JtYXQuXFxuJyArXHJcbiAgICAgICAgICAnU2hvdWxkIGJlOiBbIFsgb2JqZWN0MSwgcG9pbnRlcjEgXSwgWyBvYmplY3QgMiwgcG9pbnRlcjIgXSwgZXRjLi4uIF0nKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcclxuICAgIH1cclxuICAgIGlmIChpc01hcChpdGVtcykpIHtcclxuICAgICAgZm9yIChjb25zdCBbb2JqZWN0LCBwb2ludGVyXSBvZiBpdGVtcykge1xyXG4gICAgICAgIGlmIChvYmplY3QgPT09IG51bGwgfHwgIXRoaXMuaXNKc29uUG9pbnRlcihwb2ludGVyKSkgeyBjb250aW51ZTsgfVxyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gZ2V0Q29weSA/XHJcbiAgICAgICAgICB0aGlzLmdldENvcHkob2JqZWN0LCBwb2ludGVyKSA6XHJcbiAgICAgICAgICB0aGlzLmdldChvYmplY3QsIHBvaW50ZXIpO1xyXG4gICAgICAgIGlmICh2YWx1ZSkgeyByZXR1cm4gdmFsdWU7IH1cclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xyXG4gICAgfVxyXG4gICAgY29uc29sZS5lcnJvcignZ2V0Rmlyc3QgZXJyb3I6IElucHV0IG5vdCBpbiBjb3JyZWN0IGZvcm1hdC5cXG4nICtcclxuICAgICAgJ1Nob3VsZCBiZTogWyBbIG9iamVjdDEsIHBvaW50ZXIxIF0sIFsgb2JqZWN0IDIsIHBvaW50ZXIyIF0sIGV0Yy4uLiBdJyk7XHJcbiAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2dldEZpcnN0Q29weScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFNpbWlsYXIgdG8gZ2V0Rmlyc3QsIGJ1dCBhbHdheXMgcmV0dXJucyBhIGNvcHkuXHJcbiAgICpcclxuICAgKiAvLyAgeyBbb2JqZWN0LCBwb2ludGVyXVtdIH0gaXRlbXMgLSBBcnJheSBvZiBvYmplY3RzIGFuZCBwb2ludGVycyB0byBjaGVja1xyXG4gICAqIC8vICB7IGFueSA9IG51bGwgfSBkZWZhdWx0VmFsdWUgLSBWYWx1ZSB0byByZXR1cm4gaWYgbm90aGluZyBmb3VuZFxyXG4gICAqIC8vICAtIENvcHkgb2YgZmlyc3QgdmFsdWUgZm91bmRcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0Rmlyc3RDb3B5KGl0ZW1zLCBkZWZhdWx0VmFsdWU6IGFueSA9IG51bGwpIHtcclxuICAgIGNvbnN0IGZpcnN0Q29weSA9IHRoaXMuZ2V0Rmlyc3QoaXRlbXMsIGRlZmF1bHRWYWx1ZSwgdHJ1ZSk7XHJcbiAgICByZXR1cm4gZmlyc3RDb3B5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3NldCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gc2V0IGEgdmFsdWUgb24gYW4gb2JqZWN0LlxyXG4gICAqIEFsc28gY3JlYXRlcyBhbnkgbWlzc2luZyBzdWIgb2JqZWN0cyBvciBhcnJheXMgdG8gY29udGFpbiB0aGF0IHZhbHVlLlxyXG4gICAqXHJcbiAgICogSWYgdGhlIG9wdGlvbmFsIGZvdXJ0aCBwYXJhbWV0ZXIgaXMgVFJVRSBhbmQgdGhlIGlubmVyLW1vc3QgY29udGFpbmVyXHJcbiAgICogaXMgYW4gYXJyYXksIHRoZSBmdW5jdGlvbiB3aWxsIGluc2VydCB0aGUgdmFsdWUgYXMgYSBuZXcgaXRlbSBhdCB0aGVcclxuICAgKiBzcGVjaWZpZWQgbG9jYXRpb24gaW4gdGhlIGFycmF5LCByYXRoZXIgdGhhbiBvdmVyd3JpdGluZyB0aGUgZXhpc3RpbmdcclxuICAgKiB2YWx1ZSAoaWYgYW55KSBhdCB0aGF0IGxvY2F0aW9uLlxyXG4gICAqXHJcbiAgICogU28gc2V0KFsxLCAyLCAzXSwgJy8xJywgNCkgPT4gWzEsIDQsIDNdXHJcbiAgICogYW5kXHJcbiAgICogU28gc2V0KFsxLCAyLCAzXSwgJy8xJywgNCwgdHJ1ZSkgPT4gWzEsIDQsIDIsIDNdXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIHNldCB2YWx1ZSBpblxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gVGhlIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICAgdmFsdWUgLSBUaGUgbmV3IHZhbHVlIHRvIHNldFxyXG4gICAqIC8vICB7IGJvb2xlYW4gfSBpbnNlcnQgLSBpbnNlcnQgdmFsdWU/XHJcbiAgICogLy8geyBvYmplY3QgfSAtIFRoZSBvcmlnaW5hbCBvYmplY3QsIG1vZGlmaWVkIHdpdGggdGhlIHNldCB2YWx1ZVxyXG4gICAqL1xyXG4gIHN0YXRpYyBzZXQob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSwgaW5zZXJ0ID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IGtleUFycmF5ID0gdGhpcy5wYXJzZShwb2ludGVyKTtcclxuICAgIGlmIChrZXlBcnJheSAhPT0gbnVsbCAmJiBrZXlBcnJheS5sZW5ndGgpIHtcclxuICAgICAgbGV0IHN1Yk9iamVjdCA9IG9iamVjdDtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlBcnJheS5sZW5ndGggLSAxOyArK2kpIHtcclxuICAgICAgICBsZXQga2V5ID0ga2V5QXJyYXlbaV07XHJcbiAgICAgICAgaWYgKGtleSA9PT0gJy0nICYmIGlzQXJyYXkoc3ViT2JqZWN0KSkge1xyXG4gICAgICAgICAga2V5ID0gc3ViT2JqZWN0Lmxlbmd0aDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGlzTWFwKHN1Yk9iamVjdCkgJiYgc3ViT2JqZWN0LmhhcyhrZXkpKSB7XHJcbiAgICAgICAgICBzdWJPYmplY3QgPSBzdWJPYmplY3QuZ2V0KGtleSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmICghaGFzT3duKHN1Yk9iamVjdCwga2V5KSkge1xyXG4gICAgICAgICAgICBzdWJPYmplY3Rba2V5XSA9IChrZXlBcnJheVtpICsgMV0ubWF0Y2goL14oXFxkK3wtKSQvKSkgPyBbXSA6IHt9O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgc3ViT2JqZWN0ID0gc3ViT2JqZWN0W2tleV07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGxhc3RLZXkgPSBrZXlBcnJheVtrZXlBcnJheS5sZW5ndGggLSAxXTtcclxuICAgICAgaWYgKGlzQXJyYXkoc3ViT2JqZWN0KSAmJiBsYXN0S2V5ID09PSAnLScpIHtcclxuICAgICAgICBzdWJPYmplY3QucHVzaCh2YWx1ZSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoaW5zZXJ0ICYmIGlzQXJyYXkoc3ViT2JqZWN0KSAmJiAhaXNOYU4oK2xhc3RLZXkpKSB7XHJcbiAgICAgICAgc3ViT2JqZWN0LnNwbGljZShsYXN0S2V5LCAwLCB2YWx1ZSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoaXNNYXAoc3ViT2JqZWN0KSkge1xyXG4gICAgICAgIHN1Yk9iamVjdC5zZXQobGFzdEtleSwgdmFsdWUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHN1Yk9iamVjdFtsYXN0S2V5XSA9IHZhbHVlO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBvYmplY3Q7XHJcbiAgICB9XHJcbiAgICBjb25zb2xlLmVycm9yKGBzZXQgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke3BvaW50ZXJ9YCk7XHJcbiAgICByZXR1cm4gb2JqZWN0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3NldENvcHknIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBDb3BpZXMgYW4gb2JqZWN0IGFuZCB1c2VzIGEgSlNPTiBQb2ludGVyIHRvIHNldCBhIHZhbHVlIG9uIHRoZSBjb3B5LlxyXG4gICAqIEFsc28gY3JlYXRlcyBhbnkgbWlzc2luZyBzdWIgb2JqZWN0cyBvciBhcnJheXMgdG8gY29udGFpbiB0aGF0IHZhbHVlLlxyXG4gICAqXHJcbiAgICogSWYgdGhlIG9wdGlvbmFsIGZvdXJ0aCBwYXJhbWV0ZXIgaXMgVFJVRSBhbmQgdGhlIGlubmVyLW1vc3QgY29udGFpbmVyXHJcbiAgICogaXMgYW4gYXJyYXksIHRoZSBmdW5jdGlvbiB3aWxsIGluc2VydCB0aGUgdmFsdWUgYXMgYSBuZXcgaXRlbSBhdCB0aGVcclxuICAgKiBzcGVjaWZpZWQgbG9jYXRpb24gaW4gdGhlIGFycmF5LCByYXRoZXIgdGhhbiBvdmVyd3JpdGluZyB0aGUgZXhpc3RpbmcgdmFsdWUuXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIGNvcHkgYW5kIHNldCB2YWx1ZSBpblxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gVGhlIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICAgdmFsdWUgLSBUaGUgdmFsdWUgdG8gc2V0XHJcbiAgICogLy8gIHsgYm9vbGVhbiB9IGluc2VydCAtIGluc2VydCB2YWx1ZT9cclxuICAgKiAvLyB7IG9iamVjdCB9IC0gVGhlIG5ldyBvYmplY3Qgd2l0aCB0aGUgc2V0IHZhbHVlXHJcbiAgICovXHJcbiAgc3RhdGljIHNldENvcHkob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSwgaW5zZXJ0ID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IGtleUFycmF5ID0gdGhpcy5wYXJzZShwb2ludGVyKTtcclxuICAgIGlmIChrZXlBcnJheSAhPT0gbnVsbCkge1xyXG4gICAgICBjb25zdCBuZXdPYmplY3QgPSBjb3B5KG9iamVjdCk7XHJcbiAgICAgIGxldCBzdWJPYmplY3QgPSBuZXdPYmplY3Q7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5QXJyYXkubGVuZ3RoIC0gMTsgKytpKSB7XHJcbiAgICAgICAgbGV0IGtleSA9IGtleUFycmF5W2ldO1xyXG4gICAgICAgIGlmIChrZXkgPT09ICctJyAmJiBpc0FycmF5KHN1Yk9iamVjdCkpIHtcclxuICAgICAgICAgIGtleSA9IHN1Yk9iamVjdC5sZW5ndGg7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc01hcChzdWJPYmplY3QpICYmIHN1Yk9iamVjdC5oYXMoa2V5KSkge1xyXG4gICAgICAgICAgc3ViT2JqZWN0LnNldChrZXksIGNvcHkoc3ViT2JqZWN0LmdldChrZXkpKSk7XHJcbiAgICAgICAgICBzdWJPYmplY3QgPSBzdWJPYmplY3QuZ2V0KGtleSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmICghaGFzT3duKHN1Yk9iamVjdCwga2V5KSkge1xyXG4gICAgICAgICAgICBzdWJPYmplY3Rba2V5XSA9IChrZXlBcnJheVtpICsgMV0ubWF0Y2goL14oXFxkK3wtKSQvKSkgPyBbXSA6IHt9O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgc3ViT2JqZWN0W2tleV0gPSBjb3B5KHN1Yk9iamVjdFtrZXldKTtcclxuICAgICAgICAgIHN1Yk9iamVjdCA9IHN1Yk9iamVjdFtrZXldO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBjb25zdCBsYXN0S2V5ID0ga2V5QXJyYXlba2V5QXJyYXkubGVuZ3RoIC0gMV07XHJcbiAgICAgIGlmIChpc0FycmF5KHN1Yk9iamVjdCkgJiYgbGFzdEtleSA9PT0gJy0nKSB7XHJcbiAgICAgICAgc3ViT2JqZWN0LnB1c2godmFsdWUpO1xyXG4gICAgICB9IGVsc2UgaWYgKGluc2VydCAmJiBpc0FycmF5KHN1Yk9iamVjdCkgJiYgIWlzTmFOKCtsYXN0S2V5KSkge1xyXG4gICAgICAgIHN1Yk9iamVjdC5zcGxpY2UobGFzdEtleSwgMCwgdmFsdWUpO1xyXG4gICAgICB9IGVsc2UgaWYgKGlzTWFwKHN1Yk9iamVjdCkpIHtcclxuICAgICAgICBzdWJPYmplY3Quc2V0KGxhc3RLZXksIHZhbHVlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBzdWJPYmplY3RbbGFzdEtleV0gPSB2YWx1ZTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gbmV3T2JqZWN0O1xyXG4gICAgfVxyXG4gICAgY29uc29sZS5lcnJvcihgc2V0Q29weSBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7cG9pbnRlcn1gKTtcclxuICAgIHJldHVybiBvYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5zZXJ0JyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQ2FsbHMgJ3NldCcgd2l0aCBpbnNlcnQgPSBUUlVFXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBvYmplY3QgdG8gaW5zZXJ0IHZhbHVlIGluXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBvaW50ZXIgLSBKU09OIFBvaW50ZXIgKHN0cmluZyBvciBhcnJheSlcclxuICAgKiAvLyAgIHZhbHVlIC0gdmFsdWUgdG8gaW5zZXJ0XHJcbiAgICogLy8geyBvYmplY3QgfVxyXG4gICAqL1xyXG4gIHN0YXRpYyBpbnNlcnQob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSkge1xyXG4gICAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRoaXMuc2V0KG9iamVjdCwgcG9pbnRlciwgdmFsdWUsIHRydWUpO1xyXG4gICAgcmV0dXJuIHVwZGF0ZWRPYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5zZXJ0Q29weScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIENhbGxzICdzZXRDb3B5JyB3aXRoIGluc2VydCA9IFRSVUVcclxuICAgKlxyXG4gICAqIC8vICB7IG9iamVjdCB9IG9iamVjdCAtIG9iamVjdCB0byBpbnNlcnQgdmFsdWUgaW5cclxuICAgKiAvLyAgeyBQb2ludGVyIH0gcG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICAgdmFsdWUgLSB2YWx1ZSB0byBpbnNlcnRcclxuICAgKiAvLyB7IG9iamVjdCB9XHJcbiAgICovXHJcbiAgc3RhdGljIGluc2VydENvcHkob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSkge1xyXG4gICAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRoaXMuc2V0Q29weShvYmplY3QsIHBvaW50ZXIsIHZhbHVlLCB0cnVlKTtcclxuICAgIHJldHVybiB1cGRhdGVkT2JqZWN0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3JlbW92ZScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gcmVtb3ZlIGEga2V5IGFuZCBpdHMgYXR0cmlidXRlIGZyb20gYW4gb2JqZWN0XHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBvYmplY3QgdG8gZGVsZXRlIGF0dHJpYnV0ZSBmcm9tXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBvaW50ZXIgLSBKU09OIFBvaW50ZXIgKHN0cmluZyBvciBhcnJheSlcclxuICAgKiAvLyB7IG9iamVjdCB9XHJcbiAgICovXHJcbiAgc3RhdGljIHJlbW92ZShvYmplY3QsIHBvaW50ZXIpIHtcclxuICAgIGNvbnN0IGtleUFycmF5ID0gdGhpcy5wYXJzZShwb2ludGVyKTtcclxuICAgIGlmIChrZXlBcnJheSAhPT0gbnVsbCAmJiBrZXlBcnJheS5sZW5ndGgpIHtcclxuICAgICAgbGV0IGxhc3RLZXkgPSBrZXlBcnJheS5wb3AoKTtcclxuICAgICAgY29uc3QgcGFyZW50T2JqZWN0ID0gdGhpcy5nZXQob2JqZWN0LCBrZXlBcnJheSk7XHJcbiAgICAgIGlmIChpc0FycmF5KHBhcmVudE9iamVjdCkpIHtcclxuICAgICAgICBpZiAobGFzdEtleSA9PT0gJy0nKSB7IGxhc3RLZXkgPSBwYXJlbnRPYmplY3QubGVuZ3RoIC0gMTsgfVxyXG4gICAgICAgIHBhcmVudE9iamVjdC5zcGxpY2UobGFzdEtleSwgMSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocGFyZW50T2JqZWN0KSkge1xyXG4gICAgICAgIGRlbGV0ZSBwYXJlbnRPYmplY3RbbGFzdEtleV07XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG9iamVjdDtcclxuICAgIH1cclxuICAgIGNvbnNvbGUuZXJyb3IoYHJlbW92ZSBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7cG9pbnRlcn1gKTtcclxuICAgIHJldHVybiBvYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaGFzJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogVGVzdHMgaWYgYW4gb2JqZWN0IGhhcyBhIHZhbHVlIGF0IHRoZSBsb2NhdGlvbiBzcGVjaWZpZWQgYnkgYSBKU09OIFBvaW50ZXJcclxuICAgKlxyXG4gICAqIC8vICB7IG9iamVjdCB9IG9iamVjdCAtIG9iamVjdCB0byBjaGVrIGZvciB2YWx1ZVxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8geyBib29sZWFuIH1cclxuICAgKi9cclxuICBzdGF0aWMgaGFzKG9iamVjdCwgcG9pbnRlcikge1xyXG4gICAgY29uc3QgaGFzVmFsdWUgPSB0aGlzLmdldChvYmplY3QsIHBvaW50ZXIsIDAsIG51bGwsIHRydWUpO1xyXG4gICAgcmV0dXJuIGhhc1ZhbHVlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2RpY3QnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBSZXR1cm5zIGEgKHBvaW50ZXIgLT4gdmFsdWUpIGRpY3Rpb25hcnkgZm9yIGFuIG9iamVjdFxyXG4gICAqXHJcbiAgICogLy8gIHsgb2JqZWN0IH0gb2JqZWN0IC0gVGhlIG9iamVjdCB0byBjcmVhdGUgYSBkaWN0aW9uYXJ5IGZyb21cclxuICAgKiAvLyB7IG9iamVjdCB9IC0gVGhlIHJlc3VsdGluZyBkaWN0aW9uYXJ5IG9iamVjdFxyXG4gICAqL1xyXG4gIHN0YXRpYyBkaWN0KG9iamVjdCkge1xyXG4gICAgY29uc3QgcmVzdWx0czogYW55ID0ge307XHJcbiAgICB0aGlzLmZvckVhY2hEZWVwKG9iamVjdCwgKHZhbHVlLCBwb2ludGVyKSA9PiB7XHJcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJlc3VsdHNbcG9pbnRlcl0gPSB2YWx1ZTsgfVxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcmVzdWx0cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdmb3JFYWNoRGVlcCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEl0ZXJhdGVzIG92ZXIgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBhbiBvYmplY3Qgb3IgaXRlbXMgaW4gYW4gYXJyYXlcclxuICAgKiBhbmQgaW52b2tlcyBhbiBpdGVyYXRlZSBmdW5jdGlvbiBmb3IgZWFjaCBrZXkvdmFsdWUgb3IgaW5kZXgvdmFsdWUgcGFpci5cclxuICAgKiBCeSBkZWZhdWx0LCBpdGVyYXRlcyBvdmVyIGl0ZW1zIHdpdGhpbiBvYmplY3RzIGFuZCBhcnJheXMgYWZ0ZXIgY2FsbGluZ1xyXG4gICAqIHRoZSBpdGVyYXRlZSBmdW5jdGlvbiBvbiB0aGUgY29udGFpbmluZyBvYmplY3Qgb3IgYXJyYXkgaXRzZWxmLlxyXG4gICAqXHJcbiAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgcG9pbnRlciwgcm9vdE9iamVjdCksXHJcbiAgICogd2hlcmUgcG9pbnRlciBpcyBhIEpTT04gcG9pbnRlciBpbmRpY2F0aW5nIHRoZSBsb2NhdGlvbiBvZiB0aGUgY3VycmVudFxyXG4gICAqIHZhbHVlIHdpdGhpbiB0aGUgcm9vdCBvYmplY3QsIGFuZCByb290T2JqZWN0IGlzIHRoZSByb290IG9iamVjdCBpbml0aWFsbHlcclxuICAgKiBzdWJtaXR0ZWQgdG8gdGggZnVuY3Rpb24uXHJcbiAgICpcclxuICAgKiBJZiBhIHRoaXJkIG9wdGlvbmFsIHBhcmFtZXRlciAnYm90dG9tVXAnIGlzIHNldCB0byBUUlVFLCB0aGUgaXRlcmF0b3JcclxuICAgKiBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBvbiBzdWItb2JqZWN0cyBhbmQgYXJyYXlzIGFmdGVyIGJlaW5nXHJcbiAgICogY2FsbGVkIG9uIHRoZWlyIGNvbnRlbnRzLCByYXRoZXIgdGhhbiBiZWZvcmUsIHdoaWNoIGlzIHRoZSBkZWZhdWx0LlxyXG4gICAqXHJcbiAgICogVGhpcyBmdW5jdGlvbiBjYW4gYWxzbyBvcHRpb25hbGx5IGJlIGNhbGxlZCBkaXJlY3RseSBvbiBhIHN1Yi1vYmplY3QgYnlcclxuICAgKiBpbmNsdWRpbmcgb3B0aW9uYWwgNHRoIGFuZCA1dGggcGFyYW1ldGVyc3MgdG8gc3BlY2lmeSB0aGUgaW5pdGlhbFxyXG4gICAqIHJvb3Qgb2JqZWN0IGFuZCBwb2ludGVyLlxyXG4gICAqXHJcbiAgICogLy8gIHsgb2JqZWN0IH0gb2JqZWN0IC0gdGhlIGluaXRpYWwgb2JqZWN0IG9yIGFycmF5XHJcbiAgICogLy8gIHsgKHY6IGFueSwgcD86IHN0cmluZywgbz86IGFueSkgPT4gYW55IH0gZnVuY3Rpb24gLSBpdGVyYXRlZSBmdW5jdGlvblxyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGJvdHRvbVVwIC0gb3B0aW9uYWwsIHNldCB0byBUUlVFIHRvIHJldmVyc2UgZGlyZWN0aW9uXHJcbiAgICogLy8gIHsgb2JqZWN0ID0gb2JqZWN0IH0gcm9vdE9iamVjdCAtIG9wdGlvbmFsLCByb290IG9iamVjdCBvciBhcnJheVxyXG4gICAqIC8vICB7IHN0cmluZyA9ICcnIH0gcG9pbnRlciAtIG9wdGlvbmFsLCBKU09OIFBvaW50ZXIgdG8gb2JqZWN0IHdpdGhpbiByb290T2JqZWN0XHJcbiAgICogLy8geyBvYmplY3QgfSAtIFRoZSBtb2RpZmllZCBvYmplY3RcclxuICAgKi9cclxuICBzdGF0aWMgZm9yRWFjaERlZXAoXHJcbiAgICBvYmplY3QsIGZuOiAodjogYW55LCBwPzogc3RyaW5nLCBvPzogYW55KSA9PiBhbnkgPSAodikgPT4gdixcclxuICAgIGJvdHRvbVVwID0gZmFsc2UsIHBvaW50ZXIgPSAnJywgcm9vdE9iamVjdCA9IG9iamVjdFxyXG4gICkge1xyXG4gICAgaWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBmb3JFYWNoRGVlcCBlcnJvcjogSXRlcmF0b3IgaXMgbm90IGEgZnVuY3Rpb246YCwgZm4pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAoIWJvdHRvbVVwKSB7IGZuKG9iamVjdCwgcG9pbnRlciwgcm9vdE9iamVjdCk7IH1cclxuICAgIGlmIChpc09iamVjdChvYmplY3QpIHx8IGlzQXJyYXkob2JqZWN0KSkge1xyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhvYmplY3QpKSB7XHJcbiAgICAgICAgY29uc3QgbmV3UG9pbnRlciA9IHBvaW50ZXIgKyAnLycgKyB0aGlzLmVzY2FwZShrZXkpO1xyXG4gICAgICAgIHRoaXMuZm9yRWFjaERlZXAob2JqZWN0W2tleV0sIGZuLCBib3R0b21VcCwgbmV3UG9pbnRlciwgcm9vdE9iamVjdCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChib3R0b21VcCkgeyBmbihvYmplY3QsIHBvaW50ZXIsIHJvb3RPYmplY3QpOyB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZm9yRWFjaERlZXBDb3B5JyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogU2ltaWxhciB0byBmb3JFYWNoRGVlcCwgYnV0IHJldHVybnMgYSBjb3B5IG9mIHRoZSBvcmlnaW5hbCBvYmplY3QsIHdpdGhcclxuICAgKiB0aGUgc2FtZSBrZXlzIGFuZCBpbmRleGVzLCBidXQgd2l0aCB2YWx1ZXMgcmVwbGFjZWQgd2l0aCB0aGUgcmVzdWx0IG9mXHJcbiAgICogdGhlIGl0ZXJhdGVlIGZ1bmN0aW9uLlxyXG4gICAqXHJcbiAgICogLy8gIHsgb2JqZWN0IH0gb2JqZWN0IC0gdGhlIGluaXRpYWwgb2JqZWN0IG9yIGFycmF5XHJcbiAgICogLy8gIHsgKHY6IGFueSwgaz86IHN0cmluZywgbz86IGFueSwgcD86IGFueSkgPT4gYW55IH0gZnVuY3Rpb24gLSBpdGVyYXRlZSBmdW5jdGlvblxyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGJvdHRvbVVwIC0gb3B0aW9uYWwsIHNldCB0byBUUlVFIHRvIHJldmVyc2UgZGlyZWN0aW9uXHJcbiAgICogLy8gIHsgb2JqZWN0ID0gb2JqZWN0IH0gcm9vdE9iamVjdCAtIG9wdGlvbmFsLCByb290IG9iamVjdCBvciBhcnJheVxyXG4gICAqIC8vICB7IHN0cmluZyA9ICcnIH0gcG9pbnRlciAtIG9wdGlvbmFsLCBKU09OIFBvaW50ZXIgdG8gb2JqZWN0IHdpdGhpbiByb290T2JqZWN0XHJcbiAgICogLy8geyBvYmplY3QgfSAtIFRoZSBjb3BpZWQgb2JqZWN0XHJcbiAgICovXHJcbiAgc3RhdGljIGZvckVhY2hEZWVwQ29weShcclxuICAgIG9iamVjdCwgZm46ICh2OiBhbnksIHA/OiBzdHJpbmcsIG8/OiBhbnkpID0+IGFueSA9ICh2KSA9PiB2LFxyXG4gICAgYm90dG9tVXAgPSBmYWxzZSwgcG9pbnRlciA9ICcnLCByb290T2JqZWN0ID0gb2JqZWN0XHJcbiAgKSB7XHJcbiAgICBpZiAodHlwZW9mIGZuICE9PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYGZvckVhY2hEZWVwQ29weSBlcnJvcjogSXRlcmF0b3IgaXMgbm90IGEgZnVuY3Rpb246YCwgZm4pO1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGlmIChpc09iamVjdChvYmplY3QpIHx8IGlzQXJyYXkob2JqZWN0KSkge1xyXG4gICAgICBsZXQgbmV3T2JqZWN0ID0gaXNBcnJheShvYmplY3QpID8gWyAuLi5vYmplY3QgXSA6IHsgLi4ub2JqZWN0IH07XHJcbiAgICAgIGlmICghYm90dG9tVXApIHsgbmV3T2JqZWN0ID0gZm4obmV3T2JqZWN0LCBwb2ludGVyLCByb290T2JqZWN0KTsgfVxyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhuZXdPYmplY3QpKSB7XHJcbiAgICAgICAgY29uc3QgbmV3UG9pbnRlciA9IHBvaW50ZXIgKyAnLycgKyB0aGlzLmVzY2FwZShrZXkpO1xyXG4gICAgICAgIG5ld09iamVjdFtrZXldID0gdGhpcy5mb3JFYWNoRGVlcENvcHkoXHJcbiAgICAgICAgICBuZXdPYmplY3Rba2V5XSwgZm4sIGJvdHRvbVVwLCBuZXdQb2ludGVyLCByb290T2JqZWN0XHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAoYm90dG9tVXApIHsgbmV3T2JqZWN0ID0gZm4obmV3T2JqZWN0LCBwb2ludGVyLCByb290T2JqZWN0KTsgfVxyXG4gICAgICByZXR1cm4gbmV3T2JqZWN0O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIGZuKG9iamVjdCwgcG9pbnRlciwgcm9vdE9iamVjdCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZXNjYXBlJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogRXNjYXBlcyBhIHN0cmluZyByZWZlcmVuY2Uga2V5XHJcbiAgICpcclxuICAgKiAvLyAgeyBzdHJpbmcgfSBrZXkgLSBzdHJpbmcga2V5IHRvIGVzY2FwZVxyXG4gICAqIC8vIHsgc3RyaW5nIH0gLSBlc2NhcGVkIGtleVxyXG4gICAqL1xyXG4gIHN0YXRpYyBlc2NhcGUoa2V5KSB7XHJcbiAgICBjb25zdCBlc2NhcGVkID0ga2V5LnRvU3RyaW5nKCkucmVwbGFjZSgvfi9nLCAnfjAnKS5yZXBsYWNlKC9cXC8vZywgJ34xJyk7XHJcbiAgICByZXR1cm4gZXNjYXBlZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd1bmVzY2FwZScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVuZXNjYXBlcyBhIHN0cmluZyByZWZlcmVuY2Uga2V5XHJcbiAgICpcclxuICAgKiAvLyAgeyBzdHJpbmcgfSBrZXkgLSBzdHJpbmcga2V5IHRvIHVuZXNjYXBlXHJcbiAgICogLy8geyBzdHJpbmcgfSAtIHVuZXNjYXBlZCBrZXlcclxuICAgKi9cclxuICBzdGF0aWMgdW5lc2NhcGUoa2V5KSB7XHJcbiAgICBjb25zdCB1bmVzY2FwZWQgPSBrZXkudG9TdHJpbmcoKS5yZXBsYWNlKC9+MS9nLCAnLycpLnJlcGxhY2UoL34wL2csICd+Jyk7XHJcbiAgICByZXR1cm4gdW5lc2NhcGVkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3BhcnNlJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQ29udmVydHMgYSBzdHJpbmcgSlNPTiBQb2ludGVyIGludG8gYSBhcnJheSBvZiBrZXlzXHJcbiAgICogKGlmIGlucHV0IGlzIGFscmVhZHkgYW4gYW4gYXJyYXkgb2Yga2V5cywgaXQgaXMgcmV0dXJuZWQgdW5jaGFuZ2VkKVxyXG4gICAqXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBvaW50ZXIgLSBKU09OIFBvaW50ZXIgKHN0cmluZyBvciBhcnJheSlcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBlcnJvcnMgLSBTaG93IGVycm9yIGlmIGludmFsaWQgcG9pbnRlcj9cclxuICAgKiAvLyB7IHN0cmluZ1tdIH0gLSBKU09OIFBvaW50ZXIgYXJyYXkgb2Yga2V5c1xyXG4gICAqL1xyXG4gIHN0YXRpYyBwYXJzZShwb2ludGVyLCBlcnJvcnMgPSBmYWxzZSkge1xyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIocG9pbnRlcikpIHtcclxuICAgICAgaWYgKGVycm9ycykgeyBjb25zb2xlLmVycm9yKGBwYXJzZSBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7cG9pbnRlcn1gKTsgfVxyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGlmIChpc0FycmF5KHBvaW50ZXIpKSB7IHJldHVybiA8c3RyaW5nW10+cG9pbnRlcjsgfVxyXG4gICAgaWYgKHR5cGVvZiBwb2ludGVyID09PSAnc3RyaW5nJykge1xyXG4gICAgICBpZiAoKDxzdHJpbmc+cG9pbnRlcilbMF0gPT09ICcjJykgeyBwb2ludGVyID0gcG9pbnRlci5zbGljZSgxKTsgfVxyXG4gICAgICBpZiAoPHN0cmluZz5wb2ludGVyID09PSAnJyB8fCA8c3RyaW5nPnBvaW50ZXIgPT09ICcvJykgeyByZXR1cm4gW107IH1cclxuICAgICAgcmV0dXJuICg8c3RyaW5nPnBvaW50ZXIpLnNsaWNlKDEpLnNwbGl0KCcvJykubWFwKHRoaXMudW5lc2NhcGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2NvbXBpbGUnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBDb252ZXJ0cyBhbiBhcnJheSBvZiBrZXlzIGludG8gYSBKU09OIFBvaW50ZXIgc3RyaW5nXHJcbiAgICogKGlmIGlucHV0IGlzIGFscmVhZHkgYSBzdHJpbmcsIGl0IGlzIG5vcm1hbGl6ZWQgYW5kIHJldHVybmVkKVxyXG4gICAqXHJcbiAgICogVGhlIG9wdGlvbmFsIHNlY29uZCBwYXJhbWV0ZXIgaXMgYSBkZWZhdWx0IHdoaWNoIHdpbGwgcmVwbGFjZSBhbnkgZW1wdHkga2V5cy5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8gIHsgc3RyaW5nIHwgbnVtYmVyID0gJycgfSBkZWZhdWx0VmFsdWUgLSBEZWZhdWx0IHZhbHVlXHJcbiAgICogLy8gIHsgYm9vbGVhbiA9IGZhbHNlIH0gZXJyb3JzIC0gU2hvdyBlcnJvciBpZiBpbnZhbGlkIHBvaW50ZXI/XHJcbiAgICogLy8geyBzdHJpbmcgfSAtIEpTT04gUG9pbnRlciBzdHJpbmdcclxuICAgKi9cclxuICBzdGF0aWMgY29tcGlsZShwb2ludGVyLCBkZWZhdWx0VmFsdWUgPSAnJywgZXJyb3JzID0gZmFsc2UpIHtcclxuICAgIGlmIChwb2ludGVyID09PSAnIycpIHsgcmV0dXJuICcnOyB9XHJcbiAgICBpZiAoIXRoaXMuaXNKc29uUG9pbnRlcihwb2ludGVyKSkge1xyXG4gICAgICBpZiAoZXJyb3JzKSB7IGNvbnNvbGUuZXJyb3IoYGNvbXBpbGUgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke3BvaW50ZXJ9YCk7IH1cclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAoaXNBcnJheShwb2ludGVyKSkge1xyXG4gICAgICBpZiAoKDxzdHJpbmdbXT5wb2ludGVyKS5sZW5ndGggPT09IDApIHsgcmV0dXJuICcnOyB9XHJcbiAgICAgIHJldHVybiAnLycgKyAoPHN0cmluZ1tdPnBvaW50ZXIpLm1hcChcclxuICAgICAgICBrZXkgPT4ga2V5ID09PSAnJyA/IGRlZmF1bHRWYWx1ZSA6IHRoaXMuZXNjYXBlKGtleSlcclxuICAgICAgKS5qb2luKCcvJyk7XHJcbiAgICB9XHJcbiAgICBpZiAodHlwZW9mIHBvaW50ZXIgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGlmIChwb2ludGVyWzBdID09PSAnIycpIHsgcG9pbnRlciA9IHBvaW50ZXIuc2xpY2UoMSk7IH1cclxuICAgICAgcmV0dXJuIHBvaW50ZXI7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndG9LZXknIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBFeHRyYWN0cyBuYW1lIG9mIHRoZSBmaW5hbCBrZXkgZnJvbSBhIEpTT04gUG9pbnRlci5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8gIHsgYm9vbGVhbiA9IGZhbHNlIH0gZXJyb3JzIC0gU2hvdyBlcnJvciBpZiBpbnZhbGlkIHBvaW50ZXI/XHJcbiAgICogLy8geyBzdHJpbmcgfSAtIHRoZSBleHRyYWN0ZWQga2V5XHJcbiAgICovXHJcbiAgc3RhdGljIHRvS2V5KHBvaW50ZXIsIGVycm9ycyA9IGZhbHNlKSB7XHJcbiAgICBjb25zdCBrZXlBcnJheSA9IHRoaXMucGFyc2UocG9pbnRlciwgZXJyb3JzKTtcclxuICAgIGlmIChrZXlBcnJheSA9PT0gbnVsbCkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgaWYgKCFrZXlBcnJheS5sZW5ndGgpIHsgcmV0dXJuICcnOyB9XHJcbiAgICByZXR1cm4ga2V5QXJyYXlba2V5QXJyYXkubGVuZ3RoIC0gMV07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaXNKc29uUG9pbnRlcicgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIENoZWNrcyBhIHN0cmluZyBvciBhcnJheSB2YWx1ZSB0byBkZXRlcm1pbmUgaWYgaXQgaXMgYSB2YWxpZCBKU09OIFBvaW50ZXIuXHJcbiAgICogUmV0dXJucyB0cnVlIGlmIGEgc3RyaW5nIGlzIGVtcHR5LCBvciBzdGFydHMgd2l0aCAnLycgb3IgJyMvJy5cclxuICAgKiBSZXR1cm5zIHRydWUgaWYgYW4gYXJyYXkgY29udGFpbnMgb25seSBzdHJpbmcgdmFsdWVzLlxyXG4gICAqXHJcbiAgICogLy8gICB2YWx1ZSAtIHZhbHVlIHRvIGNoZWNrXHJcbiAgICogLy8geyBib29sZWFuIH0gLSB0cnVlIGlmIHZhbHVlIGlzIGEgdmFsaWQgSlNPTiBQb2ludGVyLCBvdGhlcndpc2UgZmFsc2VcclxuICAgKi9cclxuICBzdGF0aWMgaXNKc29uUG9pbnRlcih2YWx1ZSkge1xyXG4gICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XHJcbiAgICAgIHJldHVybiB2YWx1ZS5ldmVyeShrZXkgPT4gdHlwZW9mIGtleSA9PT0gJ3N0cmluZycpO1xyXG4gICAgfSBlbHNlIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcclxuICAgICAgaWYgKHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gJyMnKSB7IHJldHVybiB0cnVlOyB9XHJcbiAgICAgIGlmICh2YWx1ZVswXSA9PT0gJy8nIHx8IHZhbHVlLnNsaWNlKDAsIDIpID09PSAnIy8nKSB7XHJcbiAgICAgICAgcmV0dXJuICEvKH5bXjAxXXx+JCkvZy50ZXN0KHZhbHVlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2lzU3ViUG9pbnRlcicgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIENoZWNrcyB3aGV0aGVyIG9uZSBKU09OIFBvaW50ZXIgaXMgYSBzdWJzZXQgb2YgYW5vdGhlci5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBzaG9ydFBvaW50ZXIgLSBwb3RlbnRpYWwgc3Vic2V0IEpTT04gUG9pbnRlclxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBsb25nUG9pbnRlciAtIHBvdGVudGlhbCBzdXBlcnNldCBKU09OIFBvaW50ZXJcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSB0cnVlSWZNYXRjaGluZyAtIHJldHVybiB0cnVlIGlmIHBvaW50ZXJzIG1hdGNoP1xyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGVycm9ycyAtIFNob3cgZXJyb3IgaWYgaW52YWxpZCBwb2ludGVyP1xyXG4gICAqIC8vIHsgYm9vbGVhbiB9IC0gdHJ1ZSBpZiBzaG9ydFBvaW50ZXIgaXMgYSBzdWJzZXQgb2YgbG9uZ1BvaW50ZXIsIGZhbHNlIGlmIG5vdFxyXG4gICAqL1xyXG4gIHN0YXRpYyBpc1N1YlBvaW50ZXIoXHJcbiAgICBzaG9ydFBvaW50ZXIsIGxvbmdQb2ludGVyLCB0cnVlSWZNYXRjaGluZyA9IGZhbHNlLCBlcnJvcnMgPSBmYWxzZVxyXG4gICkge1xyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoc2hvcnRQb2ludGVyKSB8fCAhdGhpcy5pc0pzb25Qb2ludGVyKGxvbmdQb2ludGVyKSkge1xyXG4gICAgICBpZiAoZXJyb3JzKSB7XHJcbiAgICAgICAgbGV0IGludmFsaWQgPSAnJztcclxuICAgICAgICBpZiAoIXRoaXMuaXNKc29uUG9pbnRlcihzaG9ydFBvaW50ZXIpKSB7IGludmFsaWQgKz0gYCAxOiAke3Nob3J0UG9pbnRlcn1gOyB9XHJcbiAgICAgICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIobG9uZ1BvaW50ZXIpKSB7IGludmFsaWQgKz0gYCAyOiAke2xvbmdQb2ludGVyfWA7IH1cclxuICAgICAgICBjb25zb2xlLmVycm9yKGBpc1N1YlBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyICR7aW52YWxpZH1gKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBzaG9ydFBvaW50ZXIgPSB0aGlzLmNvbXBpbGUoc2hvcnRQb2ludGVyLCAnJywgZXJyb3JzKTtcclxuICAgIGxvbmdQb2ludGVyID0gdGhpcy5jb21waWxlKGxvbmdQb2ludGVyLCAnJywgZXJyb3JzKTtcclxuICAgIHJldHVybiBzaG9ydFBvaW50ZXIgPT09IGxvbmdQb2ludGVyID8gdHJ1ZUlmTWF0Y2hpbmcgOlxyXG4gICAgICBgJHtzaG9ydFBvaW50ZXJ9L2AgPT09IGxvbmdQb2ludGVyLnNsaWNlKDAsIHNob3J0UG9pbnRlci5sZW5ndGggKyAxKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd0b0luZGV4ZWRQb2ludGVyJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogTWVyZ2VzIGFuIGFycmF5IG9mIG51bWVyaWMgaW5kZXhlcyBhbmQgYSBnZW5lcmljIHBvaW50ZXIgdG8gY3JlYXRlIGFuXHJcbiAgICogaW5kZXhlZCBwb2ludGVyIGZvciBhIHNwZWNpZmljIGl0ZW0uXHJcbiAgICpcclxuICAgKiBGb3IgZXhhbXBsZSwgbWVyZ2luZyB0aGUgZ2VuZXJpYyBwb2ludGVyICcvZm9vLy0vYmFyLy0vYmF6JyBhbmRcclxuICAgKiB0aGUgYXJyYXkgWzQsIDJdIHdvdWxkIHJlc3VsdCBpbiB0aGUgaW5kZXhlZCBwb2ludGVyICcvZm9vLzQvYmFyLzIvYmF6J1xyXG4gICAqXHJcbiAgICpcclxuICAgKiAvLyAgeyBQb2ludGVyIH0gZ2VuZXJpY1BvaW50ZXIgLSBUaGUgZ2VuZXJpYyBwb2ludGVyXHJcbiAgICogLy8gIHsgbnVtYmVyW10gfSBpbmRleEFycmF5IC0gVGhlIGFycmF5IG9mIG51bWVyaWMgaW5kZXhlc1xyXG4gICAqIC8vICB7IE1hcDxzdHJpbmcsIG51bWJlcj4gfSBhcnJheU1hcCAtIEFuIG9wdGlvbmFsIGFycmF5IG1hcFxyXG4gICAqIC8vIHsgc3RyaW5nIH0gLSBUaGUgbWVyZ2VkIHBvaW50ZXIgd2l0aCBpbmRleGVzXHJcbiAgICovXHJcbiAgc3RhdGljIHRvSW5kZXhlZFBvaW50ZXIoXHJcbiAgICBnZW5lcmljUG9pbnRlciwgaW5kZXhBcnJheSwgYXJyYXlNYXA6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBudWxsXHJcbiAgKSB7XHJcbiAgICBpZiAodGhpcy5pc0pzb25Qb2ludGVyKGdlbmVyaWNQb2ludGVyKSAmJiBpc0FycmF5KGluZGV4QXJyYXkpKSB7XHJcbiAgICAgIGxldCBpbmRleGVkUG9pbnRlciA9IHRoaXMuY29tcGlsZShnZW5lcmljUG9pbnRlcik7XHJcbiAgICAgIGlmIChpc01hcChhcnJheU1hcCkpIHtcclxuICAgICAgICBsZXQgYXJyYXlJbmRleCA9IDA7XHJcbiAgICAgICAgcmV0dXJuIGluZGV4ZWRQb2ludGVyLnJlcGxhY2UoL1xcL1xcLSg/PVxcL3wkKS9nLCAoa2V5LCBzdHJpbmdJbmRleCkgPT5cclxuICAgICAgICAgIGFycmF5TWFwLmhhcygoPHN0cmluZz5pbmRleGVkUG9pbnRlcikuc2xpY2UoMCwgc3RyaW5nSW5kZXgpKSA/XHJcbiAgICAgICAgICAgICcvJyArIGluZGV4QXJyYXlbYXJyYXlJbmRleCsrXSA6IGtleVxyXG4gICAgICAgICk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZm9yIChjb25zdCBwb2ludGVySW5kZXggb2YgaW5kZXhBcnJheSkge1xyXG4gICAgICAgICAgaW5kZXhlZFBvaW50ZXIgPSBpbmRleGVkUG9pbnRlci5yZXBsYWNlKCcvLScsICcvJyArIHBvaW50ZXJJbmRleCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBpbmRleGVkUG9pbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoZ2VuZXJpY1BvaW50ZXIpKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvSW5kZXhlZFBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke2dlbmVyaWNQb2ludGVyfWApO1xyXG4gICAgfVxyXG4gICAgaWYgKCFpc0FycmF5KGluZGV4QXJyYXkpKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvSW5kZXhlZFBvaW50ZXIgZXJyb3I6IEludmFsaWQgaW5kZXhBcnJheTogJHtpbmRleEFycmF5fWApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3RvR2VuZXJpY1BvaW50ZXInIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBDb21wYXJlcyBhbiBpbmRleGVkIHBvaW50ZXIgdG8gYW4gYXJyYXkgbWFwIGFuZCByZW1vdmVzIGxpc3QgYXJyYXlcclxuICAgKiBpbmRleGVzIChidXQgbGVhdmVzIHR1cGxlIGFycnJheSBpbmRleGVzIGFuZCBhbGwgb2JqZWN0IGtleXMsIGluY2x1ZGluZ1xyXG4gICAqIG51bWVyaWMga2V5cykgdG8gY3JlYXRlIGEgZ2VuZXJpYyBwb2ludGVyLlxyXG4gICAqXHJcbiAgICogRm9yIGV4YW1wbGUsIHVzaW5nIHRoZSBpbmRleGVkIHBvaW50ZXIgJy9mb28vMS9iYXIvMi9iYXovMycgYW5kXHJcbiAgICogdGhlIGFycmF5TWFwIFtbJy9mb28nLCAwXSwgWycvZm9vLy0vYmFyJywgM10sIFsnL2Zvby8tL2Jhci8tL2JheicsIDBdXVxyXG4gICAqIHdvdWxkIHJlc3VsdCBpbiB0aGUgZ2VuZXJpYyBwb2ludGVyICcvZm9vLy0vYmFyLzIvYmF6Ly0nXHJcbiAgICogVXNpbmcgdGhlIGluZGV4ZWQgcG9pbnRlciAnL2Zvby8xL2Jhci80L2Jhei8zJyBhbmQgdGhlIHNhbWUgYXJyYXlNYXBcclxuICAgKiB3b3VsZCByZXN1bHQgaW4gdGhlIGdlbmVyaWMgcG9pbnRlciAnL2Zvby8tL2Jhci8tL2Jhei8tJ1xyXG4gICAqICh0aGUgYmFyIGFycmF5IGhhcyAzIHR1cGxlIGl0ZW1zLCBzbyBpbmRleCAyIGlzIHJldGFpbmVkLCBidXQgNCBpcyByZW1vdmVkKVxyXG4gICAqXHJcbiAgICogVGhlIHN0cnVjdHVyZSBvZiB0aGUgYXJyYXlNYXAgaXM6IFtbJ3BhdGggdG8gYXJyYXknLCBudW1iZXIgb2YgdHVwbGUgaXRlbXNdLi4uXVxyXG4gICAqXHJcbiAgICpcclxuICAgKiAvLyAgeyBQb2ludGVyIH0gaW5kZXhlZFBvaW50ZXIgLSBUaGUgaW5kZXhlZCBwb2ludGVyIChhcnJheSBvciBzdHJpbmcpXHJcbiAgICogLy8gIHsgTWFwPHN0cmluZywgbnVtYmVyPiB9IGFycmF5TWFwIC0gVGhlIG9wdGlvbmFsIGFycmF5IG1hcCAoZm9yIHByZXNlcnZpbmcgdHVwbGUgaW5kZXhlcylcclxuICAgKiAvLyB7IHN0cmluZyB9IC0gVGhlIGdlbmVyaWMgcG9pbnRlciB3aXRoIGluZGV4ZXMgcmVtb3ZlZFxyXG4gICAqL1xyXG4gIHN0YXRpYyB0b0dlbmVyaWNQb2ludGVyKGluZGV4ZWRQb2ludGVyLCBhcnJheU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCkpIHtcclxuICAgIGlmICh0aGlzLmlzSnNvblBvaW50ZXIoaW5kZXhlZFBvaW50ZXIpICYmIGlzTWFwKGFycmF5TWFwKSkge1xyXG4gICAgICBjb25zdCBwb2ludGVyQXJyYXkgPSB0aGlzLnBhcnNlKGluZGV4ZWRQb2ludGVyKTtcclxuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBwb2ludGVyQXJyYXkubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBjb25zdCBzdWJQb2ludGVyID0gdGhpcy5jb21waWxlKHBvaW50ZXJBcnJheS5zbGljZSgwLCBpKSk7XHJcbiAgICAgICAgaWYgKGFycmF5TWFwLmhhcyhzdWJQb2ludGVyKSAmJlxyXG4gICAgICAgICAgYXJyYXlNYXAuZ2V0KHN1YlBvaW50ZXIpIDw9ICtwb2ludGVyQXJyYXlbaV1cclxuICAgICAgICApIHtcclxuICAgICAgICAgIHBvaW50ZXJBcnJheVtpXSA9ICctJztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRoaXMuY29tcGlsZShwb2ludGVyQXJyYXkpO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoaW5kZXhlZFBvaW50ZXIpKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvR2VuZXJpY1BvaW50ZXIgZXJyb3I6IGludmFsaWQgSlNPTiBQb2ludGVyOiAke2luZGV4ZWRQb2ludGVyfWApO1xyXG4gICAgfVxyXG4gICAgaWYgKCFpc01hcChhcnJheU1hcCkpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgdG9HZW5lcmljUG9pbnRlciBlcnJvcjogaW52YWxpZCBhcnJheU1hcDogJHthcnJheU1hcH1gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd0b0NvbnRyb2xQb2ludGVyJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhIEpTT04gUG9pbnRlciBmb3IgYSBkYXRhIG9iamVjdCBhbmQgcmV0dXJucyBhIEpTT04gUG9pbnRlciBmb3IgdGhlXHJcbiAgICogbWF0Y2hpbmcgY29udHJvbCBpbiBhbiBBbmd1bGFyIEZvcm1Hcm91cC5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBkYXRhUG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KSB0byBhIGRhdGEgb2JqZWN0XHJcbiAgICogLy8gIHsgRm9ybUdyb3VwIH0gZm9ybUdyb3VwIC0gQW5ndWxhciBGb3JtR3JvdXAgdG8gZ2V0IHZhbHVlIGZyb21cclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBjb250cm9sTXVzdEV4aXN0IC0gT25seSByZXR1cm4gaWYgY29udHJvbCBleGlzdHM/XHJcbiAgICogLy8geyBQb2ludGVyIH0gLSBKU09OIFBvaW50ZXIgKHN0cmluZykgdG8gdGhlIGZvcm1Hcm91cCBvYmplY3RcclxuICAgKi9cclxuICBzdGF0aWMgdG9Db250cm9sUG9pbnRlcihkYXRhUG9pbnRlciwgZm9ybUdyb3VwLCBjb250cm9sTXVzdEV4aXN0ID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IGRhdGFQb2ludGVyQXJyYXkgPSB0aGlzLnBhcnNlKGRhdGFQb2ludGVyKTtcclxuICAgIGNvbnN0IGNvbnRyb2xQb2ludGVyQXJyYXk6IHN0cmluZ1tdID0gW107XHJcbiAgICBsZXQgc3ViR3JvdXAgPSBmb3JtR3JvdXA7XHJcbiAgICBpZiAoZGF0YVBvaW50ZXJBcnJheSAhPT0gbnVsbCkge1xyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBkYXRhUG9pbnRlckFycmF5KSB7XHJcbiAgICAgICAgaWYgKGhhc093bihzdWJHcm91cCwgJ2NvbnRyb2xzJykpIHtcclxuICAgICAgICAgIGNvbnRyb2xQb2ludGVyQXJyYXkucHVzaCgnY29udHJvbHMnKTtcclxuICAgICAgICAgIHN1Ykdyb3VwID0gc3ViR3JvdXAuY29udHJvbHM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc0FycmF5KHN1Ykdyb3VwKSAmJiAoa2V5ID09PSAnLScpKSB7XHJcbiAgICAgICAgICBjb250cm9sUG9pbnRlckFycmF5LnB1c2goKHN1Ykdyb3VwLmxlbmd0aCAtIDEpLnRvU3RyaW5nKCkpO1xyXG4gICAgICAgICAgc3ViR3JvdXAgPSBzdWJHcm91cFtzdWJHcm91cC5sZW5ndGggLSAxXTtcclxuICAgICAgICB9IGVsc2UgaWYgKGhhc093bihzdWJHcm91cCwga2V5KSkge1xyXG4gICAgICAgICAgY29udHJvbFBvaW50ZXJBcnJheS5wdXNoKGtleSk7XHJcbiAgICAgICAgICBzdWJHcm91cCA9IHN1Ykdyb3VwW2tleV07XHJcbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sTXVzdEV4aXN0KSB7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGB0b0NvbnRyb2xQb2ludGVyIGVycm9yOiBVbmFibGUgdG8gZmluZCBcIiR7a2V5fVwiIGl0ZW0gaW4gRm9ybUdyb3VwLmApO1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcihkYXRhUG9pbnRlcik7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1Hcm91cCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnRyb2xQb2ludGVyQXJyYXkucHVzaChrZXkpO1xyXG4gICAgICAgICAgc3ViR3JvdXAgPSB7IGNvbnRyb2xzOiB7fSB9O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gdGhpcy5jb21waWxlKGNvbnRyb2xQb2ludGVyQXJyYXkpO1xyXG4gICAgfVxyXG4gICAgY29uc29sZS5lcnJvcihgdG9Db250cm9sUG9pbnRlciBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7ZGF0YVBvaW50ZXJ9YCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndG9TY2hlbWFQb2ludGVyJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhIEpTT04gUG9pbnRlciB0byBhIHZhbHVlIGluc2lkZSBhIGRhdGEgb2JqZWN0IGFuZCBhIEpTT04gc2NoZW1hXHJcbiAgICogZm9yIHRoYXQgb2JqZWN0LlxyXG4gICAqXHJcbiAgICogUmV0dXJucyBhIFBvaW50ZXIgdG8gdGhlIHN1Yi1zY2hlbWEgZm9yIHRoZSB2YWx1ZSBpbnNpZGUgdGhlIG9iamVjdCdzIHNjaGVtYS5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBkYXRhUG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KSB0byBhbiBvYmplY3RcclxuICAgKiAvLyAgIHNjaGVtYSAtIEpTT04gc2NoZW1hIGZvciB0aGUgb2JqZWN0XHJcbiAgICogLy8geyBQb2ludGVyIH0gLSBKU09OIFBvaW50ZXIgKHN0cmluZykgdG8gdGhlIG9iamVjdCdzIHNjaGVtYVxyXG4gICAqL1xyXG4gIHN0YXRpYyB0b1NjaGVtYVBvaW50ZXIoZGF0YVBvaW50ZXIsIHNjaGVtYSkge1xyXG4gICAgaWYgKHRoaXMuaXNKc29uUG9pbnRlcihkYXRhUG9pbnRlcikgJiYgdHlwZW9mIHNjaGVtYSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgY29uc3QgcG9pbnRlckFycmF5ID0gdGhpcy5wYXJzZShkYXRhUG9pbnRlcik7XHJcbiAgICAgIGlmICghcG9pbnRlckFycmF5Lmxlbmd0aCkgeyByZXR1cm4gJyc7IH1cclxuICAgICAgY29uc3QgZmlyc3RLZXkgPSBwb2ludGVyQXJyYXkuc2hpZnQoKTtcclxuICAgICAgaWYgKHNjaGVtYS50eXBlID09PSAnb2JqZWN0JyB8fCBzY2hlbWEucHJvcGVydGllcyB8fCBzY2hlbWEuYWRkaXRpb25hbFByb3BlcnRpZXMpIHtcclxuICAgICAgICBpZiAoKHNjaGVtYS5wcm9wZXJ0aWVzIHx8IHt9KVtmaXJzdEtleV0pIHtcclxuICAgICAgICAgIHJldHVybiBgL3Byb3BlcnRpZXMvJHt0aGlzLmVzY2FwZShmaXJzdEtleSl9YCArXHJcbiAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLnByb3BlcnRpZXNbZmlyc3RLZXldKTtcclxuICAgICAgICB9IGVsc2UgIGlmIChzY2hlbWEuYWRkaXRpb25hbFByb3BlcnRpZXMpIHtcclxuICAgICAgICAgIHJldHVybiAnL2FkZGl0aW9uYWxQcm9wZXJ0aWVzJyArXHJcbiAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLmFkZGl0aW9uYWxQcm9wZXJ0aWVzKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKChzY2hlbWEudHlwZSA9PT0gJ2FycmF5JyB8fCBzY2hlbWEuaXRlbXMpICYmXHJcbiAgICAgICAgKGlzTnVtYmVyKGZpcnN0S2V5KSB8fCBmaXJzdEtleSA9PT0gJy0nIHx8IGZpcnN0S2V5ID09PSAnJylcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgYXJyYXlJdGVtID0gZmlyc3RLZXkgPT09ICctJyB8fCBmaXJzdEtleSA9PT0gJycgPyAwIDogK2ZpcnN0S2V5O1xyXG4gICAgICAgIGlmIChpc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcclxuICAgICAgICAgIGlmIChhcnJheUl0ZW0gPCBzY2hlbWEuaXRlbXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAnL2l0ZW1zLycgKyBhcnJheUl0ZW0gK1xyXG4gICAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLml0ZW1zW2FycmF5SXRlbV0pO1xyXG4gICAgICAgICAgfSBlbHNlIGlmIChzY2hlbWEuYWRkaXRpb25hbEl0ZW1zKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAnL2FkZGl0aW9uYWxJdGVtcycgK1xyXG4gICAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLmFkZGl0aW9uYWxJdGVtcyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChzY2hlbWEuaXRlbXMpKSB7XHJcbiAgICAgICAgICByZXR1cm4gJy9pdGVtcycgKyB0aGlzLnRvU2NoZW1hUG9pbnRlcihwb2ludGVyQXJyYXksIHNjaGVtYS5pdGVtcyk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChzY2hlbWEuYWRkaXRpb25hbEl0ZW1zKSkge1xyXG4gICAgICAgICAgcmV0dXJuICcvYWRkaXRpb25hbEl0ZW1zJyArXHJcbiAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLmFkZGl0aW9uYWxJdGVtcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvU2NoZW1hUG9pbnRlciBlcnJvcjogRGF0YSBwb2ludGVyICR7ZGF0YVBvaW50ZXJ9IGAgK1xyXG4gICAgICAgIGBub3QgY29tcGF0aWJsZSB3aXRoIHNjaGVtYSAke3NjaGVtYX1gKTtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAoIXRoaXMuaXNKc29uUG9pbnRlcihkYXRhUG9pbnRlcikpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgdG9TY2hlbWFQb2ludGVyIGVycm9yOiBJbnZhbGlkIEpTT04gUG9pbnRlcjogJHtkYXRhUG9pbnRlcn1gKTtcclxuICAgIH1cclxuICAgIGlmICh0eXBlb2Ygc2NoZW1hICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGB0b1NjaGVtYVBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBTY2hlbWE6ICR7c2NoZW1hfWApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndG9EYXRhUG9pbnRlcicgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEFjY2VwdHMgYSBKU09OIFBvaW50ZXIgdG8gYSBzdWItc2NoZW1hIGluc2lkZSBhIEpTT04gc2NoZW1hIGFuZCB0aGUgc2NoZW1hLlxyXG4gICAqXHJcbiAgICogSWYgcG9zc2libGUsIHJldHVybnMgYSBnZW5lcmljIFBvaW50ZXIgdG8gdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWUgaW5zaWRlXHJcbiAgICogdGhlIGRhdGEgb2JqZWN0IGRlc2NyaWJlZCBieSB0aGUgSlNPTiBzY2hlbWEuXHJcbiAgICpcclxuICAgKiBSZXR1cm5zIG51bGwgaWYgdGhlIHN1Yi1zY2hlbWEgaXMgaW4gYW4gYW1iaWd1b3VzIGxvY2F0aW9uIChzdWNoIGFzXHJcbiAgICogZGVmaW5pdGlvbnMgb3IgYWRkaXRpb25hbFByb3BlcnRpZXMpIHdoZXJlIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlXHJcbiAgICogbG9jYXRpb24gY2Fubm90IGJlIGRldGVybWluZWQuXHJcbiAgICpcclxuICAgKiAvLyAgeyBQb2ludGVyIH0gc2NoZW1hUG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KSB0byBhIEpTT04gc2NoZW1hXHJcbiAgICogLy8gICBzY2hlbWEgLSB0aGUgSlNPTiBzY2hlbWFcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBlcnJvcnMgLSBTaG93IGVycm9ycz9cclxuICAgKiAvLyB7IFBvaW50ZXIgfSAtIEpTT04gUG9pbnRlciAoc3RyaW5nKSB0byB0aGUgdmFsdWUgaW4gdGhlIGRhdGEgb2JqZWN0XHJcbiAgICovXHJcbiAgc3RhdGljIHRvRGF0YVBvaW50ZXIoc2NoZW1hUG9pbnRlciwgc2NoZW1hLCBlcnJvcnMgPSBmYWxzZSkge1xyXG4gICAgaWYgKHRoaXMuaXNKc29uUG9pbnRlcihzY2hlbWFQb2ludGVyKSAmJiB0eXBlb2Ygc2NoZW1hID09PSAnb2JqZWN0JyAmJlxyXG4gICAgICB0aGlzLmhhcyhzY2hlbWEsIHNjaGVtYVBvaW50ZXIpXHJcbiAgICApIHtcclxuICAgICAgY29uc3QgcG9pbnRlckFycmF5ID0gdGhpcy5wYXJzZShzY2hlbWFQb2ludGVyKTtcclxuICAgICAgaWYgKCFwb2ludGVyQXJyYXkubGVuZ3RoKSB7IHJldHVybiAnJzsgfVxyXG4gICAgICBjb25zdCBmaXJzdEtleSA9IHBvaW50ZXJBcnJheS5zaGlmdCgpO1xyXG4gICAgICBpZiAoZmlyc3RLZXkgPT09ICdwcm9wZXJ0aWVzJyB8fFxyXG4gICAgICAgIChmaXJzdEtleSA9PT0gJ2l0ZW1zJyAmJiBpc0FycmF5KHNjaGVtYS5pdGVtcykpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGNvbnN0IHNlY29uZEtleSA9IHBvaW50ZXJBcnJheS5zaGlmdCgpO1xyXG4gICAgICAgIGNvbnN0IHBvaW50ZXJTdWZmaXggPSB0aGlzLnRvRGF0YVBvaW50ZXIocG9pbnRlckFycmF5LCBzY2hlbWFbZmlyc3RLZXldW3NlY29uZEtleV0pO1xyXG4gICAgICAgIHJldHVybiBwb2ludGVyU3VmZml4ID09PSBudWxsID8gbnVsbCA6ICcvJyArIHNlY29uZEtleSArIHBvaW50ZXJTdWZmaXg7XHJcbiAgICAgIH0gZWxzZSBpZiAoZmlyc3RLZXkgPT09ICdhZGRpdGlvbmFsSXRlbXMnIHx8XHJcbiAgICAgICAgKGZpcnN0S2V5ID09PSAnaXRlbXMnICYmIGlzT2JqZWN0KHNjaGVtYS5pdGVtcykpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGNvbnN0IHBvaW50ZXJTdWZmaXggPSB0aGlzLnRvRGF0YVBvaW50ZXIocG9pbnRlckFycmF5LCBzY2hlbWFbZmlyc3RLZXldKTtcclxuICAgICAgICByZXR1cm4gcG9pbnRlclN1ZmZpeCA9PT0gbnVsbCA/IG51bGwgOiAnLy0nICsgcG9pbnRlclN1ZmZpeDtcclxuICAgICAgfSBlbHNlIGlmIChbJ2FsbE9mJywgJ2FueU9mJywgJ29uZU9mJ10uaW5jbHVkZXMoZmlyc3RLZXkpKSB7XHJcbiAgICAgICAgY29uc3Qgc2Vjb25kS2V5ID0gcG9pbnRlckFycmF5LnNoaWZ0KCk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudG9EYXRhUG9pbnRlcihwb2ludGVyQXJyYXksIHNjaGVtYVtmaXJzdEtleV1bc2Vjb25kS2V5XSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoZmlyc3RLZXkgPT09ICdub3QnKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudG9EYXRhUG9pbnRlcihwb2ludGVyQXJyYXksIHNjaGVtYVtmaXJzdEtleV0pO1xyXG4gICAgICB9IGVsc2UgaWYgKFsnY29udGFpbnMnLCAnZGVmaW5pdGlvbnMnLCAnZGVwZW5kZW5jaWVzJywgJ2FkZGl0aW9uYWxJdGVtcycsXHJcbiAgICAgICAgJ2FkZGl0aW9uYWxQcm9wZXJ0aWVzJywgJ3BhdHRlcm5Qcm9wZXJ0aWVzJywgJ3Byb3BlcnR5TmFtZXMnXS5pbmNsdWRlcyhmaXJzdEtleSlcclxuICAgICAgKSB7XHJcbiAgICAgICAgaWYgKGVycm9ycykgeyBjb25zb2xlLmVycm9yKGB0b0RhdGFQb2ludGVyIGVycm9yOiBBbWJpZ3VvdXMgbG9jYXRpb25gKTsgfVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH1cclxuICAgIGlmIChlcnJvcnMpIHtcclxuICAgICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoc2NoZW1hUG9pbnRlcikpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKGB0b0RhdGFQb2ludGVyIGVycm9yOiBJbnZhbGlkIEpTT04gUG9pbnRlcjogJHtzY2hlbWFQb2ludGVyfWApO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHRvRGF0YVBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBTY2hlbWE6ICR7c2NoZW1hfWApO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHRvRGF0YVBvaW50ZXIgZXJyb3I6IFBvaW50ZXIgJHtzY2hlbWFQb2ludGVyfSBpbnZhbGlkIGZvciBTY2hlbWE6ICR7c2NoZW1hfWApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdwYXJzZU9iamVjdFBhdGgnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBQYXJzZXMgYSBKYXZhU2NyaXB0IG9iamVjdCBwYXRoIGludG8gYW4gYXJyYXkgb2Yga2V5cywgd2hpY2hcclxuICAgKiBjYW4gdGhlbiBiZSBwYXNzZWQgdG8gY29tcGlsZSgpIHRvIGNvbnZlcnQgaW50byBhIHN0cmluZyBKU09OIFBvaW50ZXIuXHJcbiAgICpcclxuICAgKiBCYXNlZCBvbiBtaWtlLW1hcmNhY2NpJ3MgZXhjZWxsZW50IG9iamVjdHBhdGggcGFyc2UgZnVuY3Rpb246XHJcbiAgICogaHR0cHM6Ly9naXRodWIuY29tL21pa2UtbWFyY2FjY2kvb2JqZWN0cGF0aFxyXG4gICAqXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBhdGggLSBUaGUgb2JqZWN0IHBhdGggdG8gcGFyc2VcclxuICAgKiAvLyB7IHN0cmluZ1tdIH0gLSBUaGUgcmVzdWx0aW5nIGFycmF5IG9mIGtleXNcclxuICAgKi9cclxuICBzdGF0aWMgcGFyc2VPYmplY3RQYXRoKHBhdGgpIHtcclxuICAgIGlmIChpc0FycmF5KHBhdGgpKSB7IHJldHVybiA8c3RyaW5nW10+cGF0aDsgfVxyXG4gICAgaWYgKHRoaXMuaXNKc29uUG9pbnRlcihwYXRoKSkgeyByZXR1cm4gdGhpcy5wYXJzZShwYXRoKTsgfVxyXG4gICAgaWYgKHR5cGVvZiBwYXRoID09PSAnc3RyaW5nJykge1xyXG4gICAgICBsZXQgaW5kZXggPSAwO1xyXG4gICAgICBjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcclxuICAgICAgd2hpbGUgKGluZGV4IDwgcGF0aC5sZW5ndGgpIHtcclxuICAgICAgICBjb25zdCBuZXh0RG90ID0gcGF0aC5pbmRleE9mKCcuJywgaW5kZXgpO1xyXG4gICAgICAgIGNvbnN0IG5leHRPQiA9IHBhdGguaW5kZXhPZignWycsIGluZGV4KTsgLy8gbmV4dCBvcGVuIGJyYWNrZXRcclxuICAgICAgICBpZiAobmV4dERvdCA9PT0gLTEgJiYgbmV4dE9CID09PSAtMSkgeyAvLyBsYXN0IGl0ZW1cclxuICAgICAgICAgIHBhcnRzLnB1c2gocGF0aC5zbGljZShpbmRleCkpO1xyXG4gICAgICAgICAgaW5kZXggPSBwYXRoLmxlbmd0aDtcclxuICAgICAgICB9IGVsc2UgaWYgKG5leHREb3QgIT09IC0xICYmIChuZXh0RG90IDwgbmV4dE9CIHx8IG5leHRPQiA9PT0gLTEpKSB7IC8vIGRvdCBub3RhdGlvblxyXG4gICAgICAgICAgcGFydHMucHVzaChwYXRoLnNsaWNlKGluZGV4LCBuZXh0RG90KSk7XHJcbiAgICAgICAgICBpbmRleCA9IG5leHREb3QgKyAxO1xyXG4gICAgICAgIH0gZWxzZSB7IC8vIGJyYWNrZXQgbm90YXRpb25cclxuICAgICAgICAgIGlmIChuZXh0T0IgPiBpbmRleCkge1xyXG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHBhdGguc2xpY2UoaW5kZXgsIG5leHRPQikpO1xyXG4gICAgICAgICAgICBpbmRleCA9IG5leHRPQjtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGNvbnN0IHF1b3RlID0gcGF0aC5jaGFyQXQobmV4dE9CICsgMSk7XHJcbiAgICAgICAgICBpZiAocXVvdGUgPT09ICdcIicgfHwgcXVvdGUgPT09ICdcXCcnKSB7IC8vIGVuY2xvc2luZyBxdW90ZXNcclxuICAgICAgICAgICAgbGV0IG5leHRDQiA9IHBhdGguaW5kZXhPZihxdW90ZSArICddJywgbmV4dE9CKTsgLy8gbmV4dCBjbG9zZSBicmFja2V0XHJcbiAgICAgICAgICAgIHdoaWxlIChuZXh0Q0IgIT09IC0xICYmIHBhdGguY2hhckF0KG5leHRDQiAtIDEpID09PSAnXFxcXCcpIHtcclxuICAgICAgICAgICAgICBuZXh0Q0IgPSBwYXRoLmluZGV4T2YocXVvdGUgKyAnXScsIG5leHRDQiArIDIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChuZXh0Q0IgPT09IC0xKSB7IG5leHRDQiA9IHBhdGgubGVuZ3RoOyB9XHJcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocGF0aC5zbGljZShpbmRleCArIDIsIG5leHRDQilcclxuICAgICAgICAgICAgICAucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcJyArIHF1b3RlLCAnZycpLCBxdW90ZSkpO1xyXG4gICAgICAgICAgICBpbmRleCA9IG5leHRDQiArIDI7XHJcbiAgICAgICAgICB9IGVsc2UgeyAvLyBubyBlbmNsb3NpbmcgcXVvdGVzXHJcbiAgICAgICAgICAgIGxldCBuZXh0Q0IgPSBwYXRoLmluZGV4T2YoJ10nLCBuZXh0T0IpOyAvLyBuZXh0IGNsb3NlIGJyYWNrZXRcclxuICAgICAgICAgICAgaWYgKG5leHRDQiA9PT0gLTEpIHsgbmV4dENCID0gcGF0aC5sZW5ndGg7IH1cclxuICAgICAgICAgICAgcGFydHMucHVzaChwYXRoLnNsaWNlKGluZGV4ICsgMSwgbmV4dENCKSk7XHJcbiAgICAgICAgICAgIGluZGV4ID0gbmV4dENCICsgMTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChwYXRoLmNoYXJBdChpbmRleCkgPT09ICcuJykgeyBpbmRleCsrOyB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBwYXJ0cztcclxuICAgIH1cclxuICAgIGNvbnNvbGUuZXJyb3IoJ3BhcnNlT2JqZWN0UGF0aCBlcnJvcjogSW5wdXQgb2JqZWN0IHBhdGggbXVzdCBiZSBhIHN0cmluZy4nKTtcclxuICB9XHJcbn1cclxuIl19