@ng-formworks/core 17.2.7 → 17.4.0

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 (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +836 -0
  3. package/esm2022/lib/framework-library/framework-library.service.mjs +175 -0
  4. package/esm2022/lib/framework-library/framework.mjs +15 -0
  5. package/esm2022/lib/framework-library/no-framework.component.mjs +18 -0
  6. package/esm2022/lib/framework-library/no-framework.module.mjs +27 -0
  7. package/esm2022/lib/framework-library/no.framework.mjs +19 -0
  8. package/esm2022/lib/json-schema-form.component.mjs +765 -0
  9. package/esm2022/lib/json-schema-form.module.mjs +26 -0
  10. package/esm2022/lib/json-schema-form.service.mjs +679 -0
  11. package/esm2022/lib/locale/de-validation-messages.mjs +60 -0
  12. package/esm2022/lib/locale/en-validation-messages.mjs +60 -0
  13. package/esm2022/lib/locale/es-validation-messages.mjs +57 -0
  14. package/esm2022/lib/locale/fr-validation-messages.mjs +60 -0
  15. package/esm2022/lib/locale/index.mjs +8 -0
  16. package/esm2022/lib/locale/it-validation-messages.mjs +60 -0
  17. package/esm2022/lib/locale/pt-validation-messages.mjs +60 -0
  18. package/esm2022/lib/locale/zh-validation-messages.mjs +60 -0
  19. package/esm2022/lib/shared/convert-schema-to-draft6.function.mjs +300 -0
  20. package/esm2022/lib/shared/form-group.functions.mjs +442 -0
  21. package/esm2022/lib/shared/format-regex.constants.mjs +54 -0
  22. package/esm2022/lib/shared/index.mjs +12 -0
  23. package/esm2022/lib/shared/json-schema.functions.mjs +784 -0
  24. package/esm2022/lib/shared/json.validators.mjs +884 -0
  25. package/esm2022/lib/shared/jsonpointer.functions.mjs +1026 -0
  26. package/esm2022/lib/shared/layout.functions.mjs +1154 -0
  27. package/esm2022/lib/shared/merge-schemas.function.mjs +345 -0
  28. package/esm2022/lib/shared/utility.functions.mjs +380 -0
  29. package/esm2022/lib/shared/validator.functions.mjs +584 -0
  30. package/esm2022/lib/widget-library/add-reference.component.mjs +61 -0
  31. package/esm2022/lib/widget-library/button.component.mjs +72 -0
  32. package/esm2022/lib/widget-library/checkbox.component.mjs +105 -0
  33. package/esm2022/lib/widget-library/checkboxes.component.mjs +147 -0
  34. package/esm2022/lib/widget-library/file.component.mjs +35 -0
  35. package/esm2022/lib/widget-library/hidden.component.mjs +54 -0
  36. package/esm2022/lib/widget-library/index.mjs +55 -0
  37. package/esm2022/lib/widget-library/input.component.mjs +119 -0
  38. package/esm2022/lib/widget-library/message.component.mjs +38 -0
  39. package/esm2022/lib/widget-library/none.component.mjs +21 -0
  40. package/esm2022/lib/widget-library/number.component.mjs +123 -0
  41. package/esm2022/lib/widget-library/one-of.component.mjs +35 -0
  42. package/esm2022/lib/widget-library/orderable.directive.mjs +123 -0
  43. package/esm2022/lib/widget-library/radios.component.mjs +153 -0
  44. package/esm2022/lib/widget-library/root.component.mjs +79 -0
  45. package/esm2022/lib/widget-library/section.component.mjs +199 -0
  46. package/esm2022/lib/widget-library/select-framework.component.mjs +51 -0
  47. package/esm2022/lib/widget-library/select-widget.component.mjs +46 -0
  48. package/esm2022/lib/widget-library/select.component.mjs +150 -0
  49. package/esm2022/lib/widget-library/submit.component.mjs +82 -0
  50. package/esm2022/lib/widget-library/tab.component.mjs +41 -0
  51. package/esm2022/lib/widget-library/tabs.component.mjs +108 -0
  52. package/esm2022/lib/widget-library/template.component.mjs +46 -0
  53. package/esm2022/lib/widget-library/textarea.component.mjs +104 -0
  54. package/esm2022/lib/widget-library/widget-library.module.mjs +42 -0
  55. package/esm2022/lib/widget-library/widget-library.service.mjs +226 -0
  56. package/esm2022/ng-formworks-core.mjs +5 -0
  57. package/esm2022/public_api.mjs +13 -0
  58. package/fesm2022/ng-formworks-core.mjs +10149 -0
  59. package/fesm2022/ng-formworks-core.mjs.map +1 -0
  60. package/index.d.ts +5 -0
  61. package/lib/framework-library/framework-library.service.d.ts +55 -0
  62. package/lib/framework-library/framework.d.ts +13 -0
  63. package/lib/framework-library/no-framework.component.d.ts +8 -0
  64. package/lib/framework-library/no-framework.module.d.ts +9 -0
  65. package/lib/framework-library/no.framework.d.ts +10 -0
  66. package/lib/json-schema-form.component.d.ts +218 -0
  67. package/lib/json-schema-form.module.d.ts +11 -0
  68. package/lib/json-schema-form.service.d.ts +115 -0
  69. package/lib/locale/de-validation-messages.d.ts +1 -0
  70. package/lib/locale/en-validation-messages.d.ts +1 -0
  71. package/lib/locale/es-validation-messages.d.ts +1 -0
  72. package/lib/locale/fr-validation-messages.d.ts +1 -0
  73. package/{src/lib/locale/index.ts → lib/locale/index.d.ts} +7 -7
  74. package/lib/locale/it-validation-messages.d.ts +1 -0
  75. package/lib/locale/pt-validation-messages.d.ts +1 -0
  76. package/lib/locale/zh-validation-messages.d.ts +1 -0
  77. package/lib/shared/convert-schema-to-draft6.function.d.ts +21 -0
  78. package/lib/shared/form-group.functions.d.ts +100 -0
  79. package/lib/shared/format-regex.constants.d.ts +19 -0
  80. package/lib/shared/index.d.ts +9 -0
  81. package/lib/shared/json-schema.functions.d.ts +193 -0
  82. package/lib/shared/json.validators.d.ts +441 -0
  83. package/lib/shared/jsonpointer.functions.d.ts +416 -0
  84. package/lib/shared/layout.functions.d.ts +83 -0
  85. package/lib/shared/merge-schemas.function.d.ts +19 -0
  86. package/lib/shared/utility.functions.d.ts +165 -0
  87. package/{src/lib/shared/validator.functions.ts → lib/shared/validator.functions.d.ts} +364 -601
  88. package/lib/widget-library/add-reference.component.d.ts +20 -0
  89. package/lib/widget-library/button.component.d.ts +21 -0
  90. package/lib/widget-library/checkbox.component.d.ts +24 -0
  91. package/lib/widget-library/checkboxes.component.d.ts +24 -0
  92. package/lib/widget-library/file.component.d.ts +21 -0
  93. package/lib/widget-library/hidden.component.d.ts +19 -0
  94. package/{src/lib/widget-library/index.ts → lib/widget-library/index.d.ts} +47 -56
  95. package/lib/widget-library/input.component.d.ts +22 -0
  96. package/lib/widget-library/message.component.d.ts +15 -0
  97. package/lib/widget-library/none.component.d.ts +8 -0
  98. package/lib/widget-library/number.component.d.ts +25 -0
  99. package/lib/widget-library/one-of.component.d.ts +21 -0
  100. package/lib/widget-library/orderable.directive.d.ts +41 -0
  101. package/lib/widget-library/radios.component.d.ts +23 -0
  102. package/lib/widget-library/root.component.d.ts +17 -0
  103. package/lib/widget-library/section.component.d.ts +19 -0
  104. package/lib/widget-library/select-framework.component.d.ts +18 -0
  105. package/lib/widget-library/select-widget.component.d.ts +18 -0
  106. package/lib/widget-library/select.component.d.ts +24 -0
  107. package/lib/widget-library/submit.component.d.ts +24 -0
  108. package/lib/widget-library/tab.component.d.ts +14 -0
  109. package/lib/widget-library/tabs.component.d.ts +20 -0
  110. package/lib/widget-library/template.component.d.ts +18 -0
  111. package/lib/widget-library/textarea.component.d.ts +21 -0
  112. package/lib/widget-library/widget-library.module.d.ts +31 -0
  113. package/lib/widget-library/widget-library.service.d.ts +22 -0
  114. package/package.json +64 -53
  115. package/{src/public_api.ts → public_api.d.ts} +9 -21
  116. package/karma.conf.js +0 -46
  117. package/ng-package.json +0 -11
  118. package/src/lib/framework-library/framework-library.service.ts +0 -195
  119. package/src/lib/framework-library/framework.ts +0 -11
  120. package/src/lib/framework-library/no-framework.component.html +0 -2
  121. package/src/lib/framework-library/no-framework.component.ts +0 -11
  122. package/src/lib/framework-library/no-framework.module.ts +0 -18
  123. package/src/lib/framework-library/no.framework.ts +0 -11
  124. package/src/lib/json-schema-form.component.html +0 -7
  125. package/src/lib/json-schema-form.component.ts +0 -809
  126. package/src/lib/json-schema-form.module.ts +0 -17
  127. package/src/lib/json-schema-form.service.ts +0 -907
  128. package/src/lib/locale/de-validation-messages.ts +0 -58
  129. package/src/lib/locale/en-validation-messages.ts +0 -58
  130. package/src/lib/locale/es-validation-messages.ts +0 -55
  131. package/src/lib/locale/fr-validation-messages.ts +0 -58
  132. package/src/lib/locale/it-validation-messages.ts +0 -58
  133. package/src/lib/locale/pt-validation-messages.ts +0 -58
  134. package/src/lib/locale/zh-validation-messages.ts +0 -58
  135. package/src/lib/locale-dates/en-US.ts +0 -5
  136. package/src/lib/shared/convert-schema-to-draft6.function.ts +0 -321
  137. package/src/lib/shared/form-group.functions.ts +0 -522
  138. package/src/lib/shared/format-regex.constants.ts +0 -73
  139. package/src/lib/shared/index.ts +0 -40
  140. package/src/lib/shared/json-schema.functions.ts +0 -788
  141. package/src/lib/shared/json.validators.ts +0 -878
  142. package/src/lib/shared/jsonpointer.functions.ts +0 -1012
  143. package/src/lib/shared/jspointer.functions.json.spec.ts +0 -103
  144. package/src/lib/shared/layout.functions.ts +0 -1233
  145. package/src/lib/shared/merge-schemas.function.ts +0 -329
  146. package/src/lib/shared/utility.functions.ts +0 -373
  147. package/src/lib/shared/validator.functions.spec.ts +0 -55
  148. package/src/lib/widget-library/add-reference.component.ts +0 -59
  149. package/src/lib/widget-library/button.component.ts +0 -54
  150. package/src/lib/widget-library/checkbox.component.ts +0 -74
  151. package/src/lib/widget-library/checkboxes.component.ts +0 -104
  152. package/src/lib/widget-library/file.component.ts +0 -36
  153. package/src/lib/widget-library/hidden.component.ts +0 -39
  154. package/src/lib/widget-library/input.component.ts +0 -76
  155. package/src/lib/widget-library/message.component.ts +0 -29
  156. package/src/lib/widget-library/none.component.ts +0 -12
  157. package/src/lib/widget-library/number.component.ts +0 -79
  158. package/src/lib/widget-library/one-of.component.ts +0 -36
  159. package/src/lib/widget-library/orderable.directive.ts +0 -130
  160. package/src/lib/widget-library/radios.component.ts +0 -101
  161. package/src/lib/widget-library/root.component.ts +0 -78
  162. package/src/lib/widget-library/section.component.ts +0 -133
  163. package/src/lib/widget-library/select-framework.component.ts +0 -50
  164. package/src/lib/widget-library/select-widget.component.ts +0 -46
  165. package/src/lib/widget-library/select.component.ts +0 -96
  166. package/src/lib/widget-library/submit.component.ts +0 -68
  167. package/src/lib/widget-library/tab.component.ts +0 -29
  168. package/src/lib/widget-library/tabs.component.ts +0 -83
  169. package/src/lib/widget-library/template.component.ts +0 -52
  170. package/src/lib/widget-library/textarea.component.ts +0 -68
  171. package/src/lib/widget-library/widget-library.module.ts +0 -13
  172. package/src/lib/widget-library/widget-library.service.ts +0 -234
  173. package/src/test.ts +0 -18
  174. package/tsconfig.lib.json +0 -25
  175. package/tsconfig.lib.prod.json +0 -9
  176. package/tsconfig.spec.json +0 -17
  177. package/tslint.json +0 -11
@@ -0,0 +1,1026 @@
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: "17.3.12", ngImport: i0, type: JsonPointer, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1021
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JsonPointer }); }
1022
+ }
1023
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JsonPointer, decorators: [{
1024
+ type: Injectable
1025
+ }] });
1026
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianNvbnBvaW50ZXIuZnVuY3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZm9ybXdvcmtzLWNvcmUvc3JjL2xpYi9zaGFyZWQvanNvbnBvaW50ZXIuZnVuY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsSUFBSSxFQUVKLGlCQUFpQixFQUNqQiw4QkFBOEIsRUFDOUIsTUFBTSxFQUNOLE9BQU8sRUFDUCxVQUFVLEVBQ1YsZUFBZSxFQUNoQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBQyxVQUFVLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBQyxNQUFNLHVCQUF1QixDQUFDOztBQW1CdkcsTUFBTSxPQUFPLFdBQVc7SUFFdEI7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsTUFBTSxDQUFDLEdBQUcsQ0FDUixNQUFNLEVBQUUsT0FBTyxFQUFFLFVBQVUsR0FBRyxDQUFDLEVBQUUsV0FBbUIsSUFBSSxFQUN4RCxVQUFVLEdBQUcsS0FBSyxFQUFFLE1BQU0sR0FBRyxLQUFLO1FBRWxDLElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtZQUFFLE9BQU8sVUFBVSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztTQUFFO1FBQy9ELElBQUksUUFBUSxHQUFVLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2xELElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUU7WUFDbkQsSUFBSSxTQUFTLEdBQUcsTUFBTSxDQUFDO1lBQ3ZCLElBQUksVUFBVSxJQUFJLFFBQVEsQ0FBQyxNQUFNLElB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Q0FBQzsrR0FuOUJVLFdBQVc7bUhBQVgsV0FBVzs7NEZBQVgsV0FBVztrQkFEdkIsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgY2xlYW5WYWx1ZU9mUXVvdGVzLFxyXG4gIGNvcHksXHJcbiAgRXhwcmVzc2lvblR5cGUsXHJcbiAgZ2V0RXhwcmVzc2lvblR5cGUsXHJcbiAgZ2V0S2V5QW5kVmFsdWVCeUV4cHJlc3Npb25UeXBlLFxyXG4gIGhhc093bixcclxuICBpc0VxdWFsLFxyXG4gIGlzTm90RXF1YWwsXHJcbiAgaXNOb3RFeHByZXNzaW9uXHJcbn0gZnJvbSAnLi91dGlsaXR5LmZ1bmN0aW9ucyc7XHJcbmltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7aXNBcnJheSwgaXNEZWZpbmVkLCBpc0VtcHR5LCBpc01hcCwgaXNOdW1iZXIsIGlzT2JqZWN0LCBpc1N0cmluZ30gZnJvbSAnLi92YWxpZGF0b3IuZnVuY3Rpb25zJztcclxuXHJcbi8qKlxyXG4gKiAnSnNvblBvaW50ZXInIGNsYXNzXHJcbiAqXHJcbiAqIFNvbWUgdXRpbGl0aWVzIGZvciB1c2luZyBKU09OIFBvaW50ZXJzIHdpdGggSlNPTiBvYmplY3RzXHJcbiAqIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2OTAxXHJcbiAqXHJcbiAqIGdldCwgZ2V0Q29weSwgZ2V0Rmlyc3QsIHNldCwgc2V0Q29weSwgaW5zZXJ0LCBpbnNlcnRDb3B5LCByZW1vdmUsIGhhcywgZGljdCxcclxuICogZm9yRWFjaERlZXAsIGZvckVhY2hEZWVwQ29weSwgZXNjYXBlLCB1bmVzY2FwZSwgcGFyc2UsIGNvbXBpbGUsIHRvS2V5LFxyXG4gKiBpc0pzb25Qb2ludGVyLCBpc1N1YlBvaW50ZXIsIHRvSW5kZXhlZFBvaW50ZXIsIHRvR2VuZXJpY1BvaW50ZXIsXHJcbiAqIHRvQ29udHJvbFBvaW50ZXIsIHRvU2NoZW1hUG9pbnRlciwgdG9EYXRhUG9pbnRlciwgcGFyc2VPYmplY3RQYXRoXHJcbiAqXHJcbiAqIFNvbWUgZnVuY3Rpb25zIGJhc2VkIG9uIG1hbnVlbHN0b2ZlcidzIGpzb24tcG9pbnRlciB1dGlsaXRpZXNcclxuICogaHR0cHM6Ly9naXRodWIuY29tL21hbnVlbHN0b2Zlci9qc29uLXBvaW50ZXJcclxuICovXHJcbmV4cG9ydCB0eXBlIFBvaW50ZXIgPSBzdHJpbmcgfCBzdHJpbmdbXTtcclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEpzb25Qb2ludGVyIHtcclxuXHJcbiAgLyoqXHJcbiAgICogJ2dldCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gcmV0cmlldmUgYSB2YWx1ZSBmcm9tIGFuIG9iamVjdC5cclxuICAgKlxyXG4gICAqIC8vICB7IG9iamVjdCB9IG9iamVjdCAtIE9iamVjdCB0byBnZXQgdmFsdWUgZnJvbVxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8gIHsgbnVtYmVyID0gMCB9IHN0YXJ0U2xpY2UgLSBaZXJvLWJhc2VkIGluZGV4IG9mIGZpcnN0IFBvaW50ZXIga2V5IHRvIHVzZVxyXG4gICAqIC8vICB7IG51bWJlciB9IGVuZFNsaWNlIC0gWmVyby1iYXNlZCBpbmRleCBvZiBsYXN0IFBvaW50ZXIga2V5IHRvIHVzZVxyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGdldEJvb2xlYW4gLSBSZXR1cm4gb25seSB0cnVlIG9yIGZhbHNlP1xyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGVycm9ycyAtIFNob3cgZXJyb3IgaWYgbm90IGZvdW5kP1xyXG4gICAqIC8vIHsgb2JqZWN0IH0gLSBMb2NhdGVkIHZhbHVlIChvciB0cnVlIG9yIGZhbHNlIGlmIGdldEJvb2xlYW4gPSB0cnVlKVxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXQoXHJcbiAgICBvYmplY3QsIHBvaW50ZXIsIHN0YXJ0U2xpY2UgPSAwLCBlbmRTbGljZTogbnVtYmVyID0gbnVsbCxcclxuICAgIGdldEJvb2xlYW4gPSBmYWxzZSwgZXJyb3JzID0gZmFsc2VcclxuICApIHtcclxuICAgIGlmIChvYmplY3QgPT09IG51bGwpIHsgcmV0dXJuIGdldEJvb2xlYW4gPyBmYWxzZSA6IHVuZGVmaW5lZDsgfVxyXG4gICAgbGV0IGtleUFycmF5OiBhbnlbXSA9IHRoaXMucGFyc2UocG9pbnRlciwgZXJyb3JzKTtcclxuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09PSAnb2JqZWN0JyAmJiBrZXlBcnJheSAhPT0gbnVsbCkge1xyXG4gICAgICBsZXQgc3ViT2JqZWN0ID0gb2JqZWN0O1xyXG4gICAgICBpZiAoc3RhcnRTbGljZSA+PSBrZXlBcnJheS5sZW5ndGggfHwgZW5kU2xpY2UgPD0gLWtleUFycmF5Lmxlbmd0aCkgeyByZXR1cm4gb2JqZWN0OyB9XHJcbiAgICAgIGlmIChzdGFydFNsaWNlIDw9IC1rZXlBcnJheS5sZW5ndGgpIHsgc3RhcnRTbGljZSA9IDA7IH1cclxuICAgICAgaWYgKCFpc0RlZmluZWQoZW5kU2xpY2UpIHx8IGVuZFNsaWNlID49IGtleUFycmF5Lmxlbmd0aCkgeyBlbmRTbGljZSA9IGtleUFycmF5Lmxlbmd0aDsgfVxyXG4gICAgICBrZXlBcnJheSA9IGtleUFycmF5LnNsaWNlKHN0YXJ0U2xpY2UsIGVuZFNsaWNlKTtcclxuICAgICAgZm9yIChsZXQga2V5IG9mIGtleUFycmF5KSB7XHJcbiAgICAgICAgaWYgKGtleSA9PT0gJy0nICYmIGlzQXJyYXkoc3ViT2JqZWN0KSAmJiBzdWJPYmplY3QubGVuZ3RoKSB7XHJcbiAgICAgICAgICBrZXkgPSBzdWJPYmplY3QubGVuZ3RoIC0gMTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGlzTWFwKHN1Yk9iamVjdCkgJiYgc3ViT2JqZWN0LmhhcyhrZXkpKSB7XHJcbiAgICAgICAgICBzdWJPYmplY3QgPSBzdWJPYmplY3QuZ2V0KGtleSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygc3ViT2JqZWN0ID09PSAnb2JqZWN0JyAmJiBzdWJPYmplY3QgIT09IG51bGwgJiZcclxuICAgICAgICAgIGhhc093bihzdWJPYmplY3QsIGtleSlcclxuICAgICAgICApIHtcclxuICAgICAgICAgIHN1Yk9iamVjdCA9IHN1Yk9iamVjdFtrZXldO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBldmFsdWF0ZWRFeHByZXNzaW9uID0gSnNvblBvaW50ZXIuZXZhbHVhdGVFeHByZXNzaW9uKHN1Yk9iamVjdCwga2V5KTtcclxuICAgICAgICAgIGlmIChldmFsdWF0ZWRFeHByZXNzaW9uLnBhc3NlZCkge1xyXG4gICAgICAgICAgICBzdWJPYmplY3QgPSBldmFsdWF0ZWRFeHByZXNzaW9uLmtleSA/IHN1Yk9iamVjdFtldmFsdWF0ZWRFeHByZXNzaW9uLmtleV0gOiBzdWJPYmplY3Q7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ0Vycm9ycyhlcnJvcnMsIGtleSwgcG9pbnRlciwgb2JqZWN0KTtcclxuICAgICAgICAgICAgcmV0dXJuIGdldEJvb2xlYW4gPyBmYWxzZSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGdldEJvb2xlYW4gPyB0cnVlIDogc3ViT2JqZWN0O1xyXG4gICAgfVxyXG4gICAgaWYgKGVycm9ycyAmJiBrZXlBcnJheSA9PT0gbnVsbCkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBnZXQgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke3BvaW50ZXJ9YCk7XHJcbiAgICB9XHJcbiAgICBpZiAoZXJyb3JzICYmIHR5cGVvZiBvYmplY3QgIT09ICdvYmplY3QnKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ2dldCBlcnJvcjogSW52YWxpZCBvYmplY3Q6Jyk7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3Iob2JqZWN0KTtcclxuICAgIH1cclxuICAgIHJldHVybiBnZXRCb29sZWFuID8gZmFsc2UgOiB1bmRlZmluZWQ7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXRpYyBsb2dFcnJvcnMoZXJyb3JzLCBrZXksIHBvaW50ZXIsIG9iamVjdCkge1xyXG4gICAgaWYgKGVycm9ycykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBnZXQgZXJyb3I6IFwiJHtrZXl9XCIga2V5IG5vdCBmb3VuZCBpbiBvYmplY3QuYCk7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IocG9pbnRlcik7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3Iob2JqZWN0KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2YWx1YXRlcyBjb25kaXRpb25hbCBleHByZXNzaW9uIGluIGZvcm0gb2YgYG1vZGVsLjxwcm9wZXJ0eT49PTx2YWx1ZT5gIG9yXHJcbiAgICogYG1vZGVsLjxwcm9wZXJ0eT4hPTx2YWx1ZT5gIHdoZXJlIHRoZSBmaXJzdCBvbmUgbWVhbnMgdGhhdCB0aGUgdmFsdWUgbXVzdCBtYXRjaCB0byBiZVxyXG4gICAqIHNob3duIGluIGEgZm9ybSwgd2hpbGUgdGhlIGZvcm1lciBzaG93cyB0aGUgcHJvcGVydHkgb25seSB3aGVuIHRoZSBwcm9wZXJ0eSB2YWx1ZSBpcyBub3RcclxuICAgKiBzZXQsIG9yIGRvZXMgbm90IGVxdWFsIHRoZSBnaXZlbiB2YWx1ZS5cclxuICAgKlxyXG4gICAqIC8vIHsgc3ViT2JqZWN0IH0gc3ViT2JqZWN0IC0gIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBkYXRhIHZhbHVlcyBvZiBwcm9wZXJ0aWVzXHJcbiAgICogLy8geyBrZXkgfSBrZXkgLSB0aGUga2V5IGZyb20gdGhlIGZvciBsb29wIGluIGEgZm9ybSBvZiBgPHByb3BlcnR5Pj09PHZhbHVlPmBcclxuICAgKlxyXG4gICAqIFJldHVybnMgdGhlIG9iamVjdCB3aXRoIHR3byBwcm9wZXJ0aWVzLiBUaGUgcHJvcGVydHkgcGFzc2VkIGluZm9ybXMgd2hldGhlclxyXG4gICAqIHRoZSBleHByZXNzaW9uIGV2YWx1YXRlZCBzdWNjZXNzZnVsbHkgYW5kIHRoZSBwcm9wZXJ0eSBrZXkgcmV0dXJucyBlaXRoZXIgdGhlIHNhbWVcclxuICAgKiBrZXkgaWYgaXQgaXMgbm90IGNvbnRhaW5lZCBpbnNpZGUgdGhlIHN1Yk9iamVjdCBvciB0aGUga2V5IG9mIHRoZSBwcm9wZXJ0eSBpZiBpdCBpcyBjb250YWluZWQuXHJcbiAgICovXHJcbiAgc3RhdGljIGV2YWx1YXRlRXhwcmVzc2lvbihzdWJPYmplY3Q6IE9iamVjdCwga2V5OiBhbnkpIHtcclxuICAgIGNvbnN0IGRlZmF1bHRSZXN1bHQgPSB7cGFzc2VkOiBmYWxzZSwga2V5OiBrZXl9O1xyXG4gICAgY29uc3Qga2V5c0FuZEV4cHJlc3Npb24gPSB0aGlzLnBhcnNlS2V5c0FuZEV4cHJlc3Npb24oa2V5LCBzdWJPYmplY3QpO1xyXG4gICAgaWYgKCFrZXlzQW5kRXhwcmVzc2lvbikge1xyXG4gICAgICByZXR1cm4gZGVmYXVsdFJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBvd25DaGVja1Jlc3VsdCA9IHRoaXMuZG9Pd25DaGVja1Jlc3VsdChzdWJPYmplY3QsIGtleXNBbmRFeHByZXNzaW9uKTtcclxuICAgIGlmIChvd25DaGVja1Jlc3VsdCkge1xyXG4gICAgICByZXR1cm4gb3duQ2hlY2tSZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgY2xlYW5lZFZhbHVlID0gY2xlYW5WYWx1ZU9mUXVvdGVzKGtleXNBbmRFeHByZXNzaW9uLmtleUFuZFZhbHVlWzFdKTtcclxuXHJcbiAgICBjb25zdCBldmFsdWF0ZWRSZXN1bHQgPSB0aGlzLnBlcmZvcm1FeHByZXNzaW9uT25WYWx1ZShrZXlzQW5kRXhwcmVzc2lvbiwgY2xlYW5lZFZhbHVlLCBzdWJPYmplY3QpO1xyXG4gICAgaWYgKGV2YWx1YXRlZFJlc3VsdCkge1xyXG4gICAgICByZXR1cm4gZXZhbHVhdGVkUmVzdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkZWZhdWx0UmVzdWx0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGVyZm9ybXMgdGhlIGFjdHVhbCBldmFsdWF0aW9uIG9uIHRoZSBnaXZlbiBleHByZXNzaW9uIHdpdGggZ2l2ZW4gdmFsdWVzIGFuZCBrZXlzLlxyXG4gICAqIC8vIHsgY2xlYW5lZFZhbHVlIH0gY2xlYW5lZFZhbHVlIC0gdGhlIGdpdmVuIHZhbHVlZCBjbGVhbmVkIG9mIHF1b3RlcyBpZiBpdCBoYWQgYW55XHJcbiAgICogLy8geyBzdWJPYmplY3QgfSBzdWJPYmplY3QgLSB0aGUgb2JqZWN0IHdpdGggcHJvcGVydGllcyB2YWx1ZXNcclxuICAgKiAvLyB7IGtleXNBbmRFeHByZXNzaW9uIH0ga2V5c0FuZEV4cHJlc3Npb24gLSBhbiBvYmplY3QgaG9sZGluZyB0aGUgZXhwcmVzc2lvbnMgd2l0aFxyXG4gICAqL1xyXG4gIHByaXZhdGUgc3RhdGljIHBlcmZvcm1FeHByZXNzaW9uT25WYWx1ZShrZXlzQW5kRXhwcmVzc2lvbjogYW55LCBjbGVhbmVkVmFsdWU6IFN0cmluZywgc3ViT2JqZWN0OiBPYmplY3QpIHtcclxuICAgIGNvbnN0IHByb3BlcnR5QnlLZXkgPSBzdWJPYmplY3Rba2V5c0FuZEV4cHJlc3Npb24ua2V5QW5kVmFsdWVbMF1dO1xyXG4gICAgaWYgKHRoaXMuZG9Db21wYXJpc29uQnlFeHByZXNzaW9uVHlwZShrZXlzQW5kRXhwcmVzc2lvbi5leHByZXNzaW9uVHlwZSwgcHJvcGVydHlCeUtleSwgY2xlYW5lZFZhbHVlKSkge1xyXG4gICAgICByZXR1cm4ge3Bhc3NlZDogdHJ1ZSwga2V5OiBrZXlzQW5kRXhwcmVzc2lvbi5rZXlBbmRWYWx1ZVswXX07XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXRpYyBkb0NvbXBhcmlzb25CeUV4cHJlc3Npb25UeXBlKGV4cHJlc3Npb25UeXBlOiBFeHByZXNzaW9uVHlwZSwgcHJvcGVydHlCeUtleSwgY2xlYW5lZFZhbHVlOiBTdHJpbmcpOiBCb29sZWFuIHtcclxuICAgIGlmIChpc0VxdWFsKGV4cHJlc3Npb25UeXBlKSkge1xyXG4gICAgICByZXR1cm4gcHJvcGVydHlCeUtleSA9PT0gY2xlYW5lZFZhbHVlO1xyXG4gICAgfVxyXG4gICAgaWYgKGlzTm90RXF1YWwoZXhwcmVzc2lvblR5cGUpKSB7XHJcbiAgICAgIHJldHVybiBwcm9wZXJ0eUJ5S2V5ICE9PSBjbGVhbmVkVmFsdWU7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEb2VzIHRoZSBjaGVja3Mgd2hlbiB0aGUgcGFyc2VkIGtleSBpcyBhY3R1YWxseSBubyBhIHByb3BlcnR5IGluc2lkZSBzdWJPYmplY3QuXHJcbiAgICogVGhhdCB3b3VsZCBtZWFuIHRoYXQgdGhlIGVxdWFsIGNvbXBhcmlzb24gbWFrZXMgbm8gc2Vuc2UgYW5kIHRodXMgdGhlIG5lZ2F0aXZlIHJlc3VsdFxyXG4gICAqIGlzIHJldHVybmVkLCBhbmQgdGhlIG5vdCBlcXVhbCBjb21wYXJpc29uIGlzIG5vdCBuZWNlc3NhcnkgYmVjYXVzZSBpdCBkb2Vzbid0IGVxdWFsXHJcbiAgICogb2J2aW91c2x5LiBSZXR1cm5zIG51bGwgd2hlbiB0aGUgZ2l2ZW4ga2V5IGlzIGEgcmVhbCBwcm9wZXJ0eSBpbnNpZGUgdGhlIHN1Yk9iamVjdC5cclxuICAgKiAvLyB7IHN1Yk9iamVjdCB9IHN1Yk9iamVjdCAtIHRoZSBvYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIHZhbHVlc1xyXG4gICAqIC8vIHsga2V5c0FuZEV4cHJlc3Npb24gfSBrZXlzQW5kRXhwcmVzc2lvbiAtIGFuIG9iamVjdCBob2xkaW5nIHRoZSBleHByZXNzaW9ucyB3aXRoXHJcbiAgICogdGhlIGFzc29jaWF0ZWQga2V5cy5cclxuICAgKi9cclxuICBwcml2YXRlIHN0YXRpYyBkb093bkNoZWNrUmVzdWx0KHN1Yk9iamVjdDogT2JqZWN0LCBrZXlzQW5kRXhwcmVzc2lvbikge1xyXG4gICAgbGV0IG93bkNoZWNrUmVzdWx0ID0gbnVsbDtcclxuICAgIGlmICghaGFzT3duKHN1Yk9iamVjdCwga2V5c0FuZEV4cHJlc3Npb24ua2V5QW5kVmFsdWVbMF0pKSB7XHJcbiAgICAgIGlmIChpc0VxdWFsKGtleXNBbmRFeHByZXNzaW9uLmV4cHJlc3Npb25UeXBlKSkge1xyXG4gICAgICAgIG93bkNoZWNrUmVzdWx0ID0ge3Bhc3NlZDogZmFsc2UsIGtleTogbnVsbH07XHJcbiAgICAgIH1cclxuICAgICAgaWYgKGlzTm90RXF1YWwoa2V5c0FuZEV4cHJlc3Npb24uZXhwcmVzc2lvblR5cGUpKSB7XHJcbiAgICAgICAgb3duQ2hlY2tSZXN1bHQgPSB7cGFzc2VkOiB0cnVlLCBrZXk6IG51bGx9O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gb3duQ2hlY2tSZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEb2VzIHRoZSBiYXNpYyBjaGVja3MgYW5kIHRyaWVzIHRvIHBhcnNlIGFuIGV4cHJlc3Npb24gYW5kIGEgcGFpclxyXG4gICAqIG9mIGtleSBhbmQgdmFsdWUuXHJcbiAgICogLy8geyBrZXkgfSBrZXkgLSB0aGUgb3JpZ2luYWwgZm9yIGxvb3AgY3JlYXRlZCB2YWx1ZSBjb250YWluaW5nIGtleSBhbmQgdmFsdWUgaW4gb25lIHN0cmluZ1xyXG4gICAqIC8vIHsgc3ViT2JqZWN0IH0gc3ViT2JqZWN0IC0gdGhlIG9iamVjdCB3aXRoIHByb3BlcnRpZXMgdmFsdWVzXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBzdGF0aWMgcGFyc2VLZXlzQW5kRXhwcmVzc2lvbihrZXk6IHN0cmluZywgc3ViT2JqZWN0KSB7XHJcbiAgICBpZiAodGhpcy5rZXlPclN1Yk9iakVtcHR5KGtleSwgc3ViT2JqZWN0KSkge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGNvbnN0IGV4cHJlc3Npb25UeXBlID0gZ2V0RXhwcmVzc2lvblR5cGUoa2V5LnRvU3RyaW5nKCkpO1xyXG4gICAgaWYgKGlzTm90RXhwcmVzc2lvbihleHByZXNzaW9uVHlwZSkpIHtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICBjb25zdCBrZXlBbmRWYWx1ZSA9IGdldEtleUFuZFZhbHVlQnlFeHByZXNzaW9uVHlwZShleHByZXNzaW9uVHlwZSwga2V5KTtcclxuICAgIGlmICgha2V5QW5kVmFsdWUgfHwgIWtleUFuZFZhbHVlWzBdIHx8ICFrZXlBbmRWYWx1ZVsxXSkge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIHJldHVybiB7ZXhwcmVzc2lvblR5cGU6IGV4cHJlc3Npb25UeXBlLCBrZXlBbmRWYWx1ZToga2V5QW5kVmFsdWV9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzdGF0aWMga2V5T3JTdWJPYmpFbXB0eShrZXk6IGFueSwgc3ViT2JqZWN0OiBPYmplY3QpIHtcclxuICAgIHJldHVybiAha2V5IHx8ICFzdWJPYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZ2V0Q29weScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gZGVlcGx5IGNsb25lIGEgdmFsdWUgZnJvbSBhbiBvYmplY3QuXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBPYmplY3QgdG8gZ2V0IHZhbHVlIGZyb21cclxuICAgKiAvLyAgeyBQb2ludGVyIH0gcG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICB7IG51bWJlciA9IDAgfSBzdGFydFNsaWNlIC0gWmVyby1iYXNlZCBpbmRleCBvZiBmaXJzdCBQb2ludGVyIGtleSB0byB1c2VcclxuICAgKiAvLyAgeyBudW1iZXIgfSBlbmRTbGljZSAtIFplcm8tYmFzZWQgaW5kZXggb2YgbGFzdCBQb2ludGVyIGtleSB0byB1c2VcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBnZXRCb29sZWFuIC0gUmV0dXJuIG9ubHkgdHJ1ZSBvciBmYWxzZT9cclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBlcnJvcnMgLSBTaG93IGVycm9yIGlmIG5vdCBmb3VuZD9cclxuICAgKiAvLyB7IG9iamVjdCB9IC0gTG9jYXRlZCB2YWx1ZSAob3IgdHJ1ZSBvciBmYWxzZSBpZiBnZXRCb29sZWFuID0gdHJ1ZSlcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0Q29weShcclxuICAgIG9iamVjdCwgcG9pbnRlciwgc3RhcnRTbGljZSA9IDAsIGVuZFNsaWNlOiBudW1iZXIgPSBudWxsLFxyXG4gICAgZ2V0Qm9vbGVhbiA9IGZhbHNlLCBlcnJvcnMgPSBmYWxzZVxyXG4gICkge1xyXG4gICAgY29uc3Qgb2JqZWN0VG9Db3B5ID1cclxuICAgICAgdGhpcy5nZXQob2JqZWN0LCBwb2ludGVyLCBzdGFydFNsaWNlLCBlbmRTbGljZSwgZ2V0Qm9vbGVhbiwgZXJyb3JzKTtcclxuICAgIHJldHVybiB0aGlzLmZvckVhY2hEZWVwQ29weShvYmplY3RUb0NvcHkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2dldEZpcnN0JyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogVGFrZXMgYW4gYXJyYXkgb2YgSlNPTiBQb2ludGVycyBhbmQgb2JqZWN0cyxcclxuICAgKiBjaGVja3MgZWFjaCBvYmplY3QgZm9yIGEgdmFsdWUgc3BlY2lmaWVkIGJ5IHRoZSBwb2ludGVyLFxyXG4gICAqIGFuZCByZXR1cm5zIHRoZSBmaXJzdCB2YWx1ZSBmb3VuZC5cclxuICAgKlxyXG4gICAqIC8vICB7IFtvYmplY3QsIHBvaW50ZXJdW10gfSBpdGVtcyAtIEFycmF5IG9mIG9iamVjdHMgYW5kIHBvaW50ZXJzIHRvIGNoZWNrXHJcbiAgICogLy8gIHsgYW55ID0gbnVsbCB9IGRlZmF1bHRWYWx1ZSAtIFZhbHVlIHRvIHJldHVybiBpZiBub3RoaW5nIGZvdW5kXHJcbiAgICogLy8gIHsgYm9vbGVhbiA9IGZhbHNlIH0gZ2V0Q29weSAtIFJldHVybiBhIGNvcHkgaW5zdGVhZD9cclxuICAgKiAvLyAgLSBGaXJzdCB2YWx1ZSBmb3VuZFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXRGaXJzdChpdGVtcywgZGVmYXVsdFZhbHVlOiBhbnkgPSBudWxsLCBnZXRDb3B5ID0gZmFsc2UpIHtcclxuICAgIGlmIChpc0VtcHR5KGl0ZW1zKSkgeyByZXR1cm47IH1cclxuICAgIGlmIChpc0FycmF5KGl0ZW1zKSkge1xyXG4gICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgaXRlbXMpIHtcclxuICAgICAgICBpZiAoaXNFbXB0eShpdGVtKSkgeyBjb250aW51ZTsgfVxyXG4gICAgICAgIGlmIChpc0FycmF5KGl0ZW0pICYmIGl0ZW0ubGVuZ3RoID49IDIpIHtcclxuICAgICAgICAgIGlmIChpc0VtcHR5KGl0ZW1bMF0pIHx8IGlzRW1wdHkoaXRlbVsxXSkpIHsgY29udGludWU7IH1cclxuICAgICAgICAgIGNvbnN0IHZhbHVlID0gZ2V0Q29weSA/XHJcbiAgICAgICAgICAgIHRoaXMuZ2V0Q29weShpdGVtWzBdLCBpdGVtWzFdKSA6XHJcbiAgICAgICAgICAgIHRoaXMuZ2V0KGl0ZW1bMF0sIGl0ZW1bMV0pO1xyXG4gICAgICAgICAgaWYgKHZhbHVlKSB7IHJldHVybiB2YWx1ZTsgfVxyXG4gICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ2dldEZpcnN0IGVycm9yOiBJbnB1dCBub3QgaW4gY29ycmVjdCBmb3JtYXQuXFxuJyArXHJcbiAgICAgICAgICAnU2hvdWxkIGJlOiBbIFsgb2JqZWN0MSwgcG9pbnRlcjEgXSwgWyBvYmplY3QgMiwgcG9pbnRlcjIgXSwgZXRjLi4uIF0nKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcclxuICAgIH1cclxuICAgIGlmIChpc01hcChpdGVtcykpIHtcclxuICAgICAgZm9yIChjb25zdCBbb2JqZWN0LCBwb2ludGVyXSBvZiBpdGVtcykge1xyXG4gICAgICAgIGlmIChvYmplY3QgPT09IG51bGwgfHwgIXRoaXMuaXNKc29uUG9pbnRlcihwb2ludGVyKSkgeyBjb250aW51ZTsgfVxyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gZ2V0Q29weSA/XHJcbiAgICAgICAgICB0aGlzLmdldENvcHkob2JqZWN0LCBwb2ludGVyKSA6XHJcbiAgICAgICAgICB0aGlzLmdldChvYmplY3QsIHBvaW50ZXIpO1xyXG4gICAgICAgIGlmICh2YWx1ZSkgeyByZXR1cm4gdmFsdWU7IH1cclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xyXG4gICAgfVxyXG4gICAgY29uc29sZS5lcnJvcignZ2V0Rmlyc3QgZXJyb3I6IElucHV0IG5vdCBpbiBjb3JyZWN0IGZvcm1hdC5cXG4nICtcclxuICAgICAgJ1Nob3VsZCBiZTogWyBbIG9iamVjdDEsIHBvaW50ZXIxIF0sIFsgb2JqZWN0IDIsIHBvaW50ZXIyIF0sIGV0Yy4uLiBdJyk7XHJcbiAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2dldEZpcnN0Q29weScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFNpbWlsYXIgdG8gZ2V0Rmlyc3QsIGJ1dCBhbHdheXMgcmV0dXJucyBhIGNvcHkuXHJcbiAgICpcclxuICAgKiAvLyAgeyBbb2JqZWN0LCBwb2ludGVyXVtdIH0gaXRlbXMgLSBBcnJheSBvZiBvYmplY3RzIGFuZCBwb2ludGVycyB0byBjaGVja1xyXG4gICAqIC8vICB7IGFueSA9IG51bGwgfSBkZWZhdWx0VmFsdWUgLSBWYWx1ZSB0byByZXR1cm4gaWYgbm90aGluZyBmb3VuZFxyXG4gICAqIC8vICAtIENvcHkgb2YgZmlyc3QgdmFsdWUgZm91bmRcclxuICAgKi9cclxuICBzdGF0aWMgZ2V0Rmlyc3RDb3B5KGl0ZW1zLCBkZWZhdWx0VmFsdWU6IGFueSA9IG51bGwpIHtcclxuICAgIGNvbnN0IGZpcnN0Q29weSA9IHRoaXMuZ2V0Rmlyc3QoaXRlbXMsIGRlZmF1bHRWYWx1ZSwgdHJ1ZSk7XHJcbiAgICByZXR1cm4gZmlyc3RDb3B5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3NldCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gc2V0IGEgdmFsdWUgb24gYW4gb2JqZWN0LlxyXG4gICAqIEFsc28gY3JlYXRlcyBhbnkgbWlzc2luZyBzdWIgb2JqZWN0cyBvciBhcnJheXMgdG8gY29udGFpbiB0aGF0IHZhbHVlLlxyXG4gICAqXHJcbiAgICogSWYgdGhlIG9wdGlvbmFsIGZvdXJ0aCBwYXJhbWV0ZXIgaXMgVFJVRSBhbmQgdGhlIGlubmVyLW1vc3QgY29udGFpbmVyXHJcbiAgICogaXMgYW4gYXJyYXksIHRoZSBmdW5jdGlvbiB3aWxsIGluc2VydCB0aGUgdmFsdWUgYXMgYSBuZXcgaXRlbSBhdCB0aGVcclxuICAgKiBzcGVjaWZpZWQgbG9jYXRpb24gaW4gdGhlIGFycmF5LCByYXRoZXIgdGhhbiBvdmVyd3JpdGluZyB0aGUgZXhpc3RpbmdcclxuICAgKiB2YWx1ZSAoaWYgYW55KSBhdCB0aGF0IGxvY2F0aW9uLlxyXG4gICAqXHJcbiAgICogU28gc2V0KFsxLCAyLCAzXSwgJy8xJywgNCkgPT4gWzEsIDQsIDNdXHJcbiAgICogYW5kXHJcbiAgICogU28gc2V0KFsxLCAyLCAzXSwgJy8xJywgNCwgdHJ1ZSkgPT4gWzEsIDQsIDIsIDNdXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIHNldCB2YWx1ZSBpblxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gVGhlIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICAgdmFsdWUgLSBUaGUgbmV3IHZhbHVlIHRvIHNldFxyXG4gICAqIC8vICB7IGJvb2xlYW4gfSBpbnNlcnQgLSBpbnNlcnQgdmFsdWU/XHJcbiAgICogLy8geyBvYmplY3QgfSAtIFRoZSBvcmlnaW5hbCBvYmplY3QsIG1vZGlmaWVkIHdpdGggdGhlIHNldCB2YWx1ZVxyXG4gICAqL1xyXG4gIHN0YXRpYyBzZXQob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSwgaW5zZXJ0ID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IGtleUFycmF5ID0gdGhpcy5wYXJzZShwb2ludGVyKTtcclxuICAgIGlmIChrZXlBcnJheSAhPT0gbnVsbCAmJiBrZXlBcnJheS5sZW5ndGgpIHtcclxuICAgICAgbGV0IHN1Yk9iamVjdCA9IG9iamVjdDtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBrZXlBcnJheS5sZW5ndGggLSAxOyArK2kpIHtcclxuICAgICAgICBsZXQga2V5ID0ga2V5QXJyYXlbaV07XHJcbiAgICAgICAgaWYgKGtleSA9PT0gJy0nICYmIGlzQXJyYXkoc3ViT2JqZWN0KSkge1xyXG4gICAgICAgICAga2V5ID0gc3ViT2JqZWN0Lmxlbmd0aDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGlzTWFwKHN1Yk9iamVjdCkgJiYgc3ViT2JqZWN0LmhhcyhrZXkpKSB7XHJcbiAgICAgICAgICBzdWJPYmplY3QgPSBzdWJPYmplY3QuZ2V0KGtleSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmICghaGFzT3duKHN1Yk9iamVjdCwga2V5KSkge1xyXG4gICAgICAgICAgICBzdWJPYmplY3Rba2V5XSA9IChrZXlBcnJheVtpICsgMV0ubWF0Y2goL14oXFxkK3wtKSQvKSkgPyBbXSA6IHt9O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgc3ViT2JqZWN0ID0gc3ViT2JqZWN0W2tleV07XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IGxhc3RLZXkgPSBrZXlBcnJheVtrZXlBcnJheS5sZW5ndGggLSAxXTtcclxuICAgICAgaWYgKGlzQXJyYXkoc3ViT2JqZWN0KSAmJiBsYXN0S2V5ID09PSAnLScpIHtcclxuICAgICAgICBzdWJPYmplY3QucHVzaCh2YWx1ZSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoaW5zZXJ0ICYmIGlzQXJyYXkoc3ViT2JqZWN0KSAmJiAhaXNOYU4oK2xhc3RLZXkpKSB7XHJcbiAgICAgICAgc3ViT2JqZWN0LnNwbGljZShsYXN0S2V5LCAwLCB2YWx1ZSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoaXNNYXAoc3ViT2JqZWN0KSkge1xyXG4gICAgICAgIHN1Yk9iamVjdC5zZXQobGFzdEtleSwgdmFsdWUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHN1Yk9iamVjdFtsYXN0S2V5XSA9IHZhbHVlO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBvYmplY3Q7XHJcbiAgICB9XHJcbiAgICBjb25zb2xlLmVycm9yKGBzZXQgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke3BvaW50ZXJ9YCk7XHJcbiAgICByZXR1cm4gb2JqZWN0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3NldENvcHknIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBDb3BpZXMgYW4gb2JqZWN0IGFuZCB1c2VzIGEgSlNPTiBQb2ludGVyIHRvIHNldCBhIHZhbHVlIG9uIHRoZSBjb3B5LlxyXG4gICAqIEFsc28gY3JlYXRlcyBhbnkgbWlzc2luZyBzdWIgb2JqZWN0cyBvciBhcnJheXMgdG8gY29udGFpbiB0aGF0IHZhbHVlLlxyXG4gICAqXHJcbiAgICogSWYgdGhlIG9wdGlvbmFsIGZvdXJ0aCBwYXJhbWV0ZXIgaXMgVFJVRSBhbmQgdGhlIGlubmVyLW1vc3QgY29udGFpbmVyXHJcbiAgICogaXMgYW4gYXJyYXksIHRoZSBmdW5jdGlvbiB3aWxsIGluc2VydCB0aGUgdmFsdWUgYXMgYSBuZXcgaXRlbSBhdCB0aGVcclxuICAgKiBzcGVjaWZpZWQgbG9jYXRpb24gaW4gdGhlIGFycmF5LCByYXRoZXIgdGhhbiBvdmVyd3JpdGluZyB0aGUgZXhpc3RpbmcgdmFsdWUuXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIGNvcHkgYW5kIHNldCB2YWx1ZSBpblxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gVGhlIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICAgdmFsdWUgLSBUaGUgdmFsdWUgdG8gc2V0XHJcbiAgICogLy8gIHsgYm9vbGVhbiB9IGluc2VydCAtIGluc2VydCB2YWx1ZT9cclxuICAgKiAvLyB7IG9iamVjdCB9IC0gVGhlIG5ldyBvYmplY3Qgd2l0aCB0aGUgc2V0IHZhbHVlXHJcbiAgICovXHJcbiAgc3RhdGljIHNldENvcHkob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSwgaW5zZXJ0ID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IGtleUFycmF5ID0gdGhpcy5wYXJzZShwb2ludGVyKTtcclxuICAgIGlmIChrZXlBcnJheSAhPT0gbnVsbCkge1xyXG4gICAgICBjb25zdCBuZXdPYmplY3QgPSBjb3B5KG9iamVjdCk7XHJcbiAgICAgIGxldCBzdWJPYmplY3QgPSBuZXdPYmplY3Q7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwga2V5QXJyYXkubGVuZ3RoIC0gMTsgKytpKSB7XHJcbiAgICAgICAgbGV0IGtleSA9IGtleUFycmF5W2ldO1xyXG4gICAgICAgIGlmIChrZXkgPT09ICctJyAmJiBpc0FycmF5KHN1Yk9iamVjdCkpIHtcclxuICAgICAgICAgIGtleSA9IHN1Yk9iamVjdC5sZW5ndGg7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc01hcChzdWJPYmplY3QpICYmIHN1Yk9iamVjdC5oYXMoa2V5KSkge1xyXG4gICAgICAgICAgc3ViT2JqZWN0LnNldChrZXksIGNvcHkoc3ViT2JqZWN0LmdldChrZXkpKSk7XHJcbiAgICAgICAgICBzdWJPYmplY3QgPSBzdWJPYmplY3QuZ2V0KGtleSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGlmICghaGFzT3duKHN1Yk9iamVjdCwga2V5KSkge1xyXG4gICAgICAgICAgICBzdWJPYmplY3Rba2V5XSA9IChrZXlBcnJheVtpICsgMV0ubWF0Y2goL14oXFxkK3wtKSQvKSkgPyBbXSA6IHt9O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgc3ViT2JqZWN0W2tleV0gPSBjb3B5KHN1Yk9iamVjdFtrZXldKTtcclxuICAgICAgICAgIHN1Yk9iamVjdCA9IHN1Yk9iamVjdFtrZXldO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBjb25zdCBsYXN0S2V5ID0ga2V5QXJyYXlba2V5QXJyYXkubGVuZ3RoIC0gMV07XHJcbiAgICAgIGlmIChpc0FycmF5KHN1Yk9iamVjdCkgJiYgbGFzdEtleSA9PT0gJy0nKSB7XHJcbiAgICAgICAgc3ViT2JqZWN0LnB1c2godmFsdWUpO1xyXG4gICAgICB9IGVsc2UgaWYgKGluc2VydCAmJiBpc0FycmF5KHN1Yk9iamVjdCkgJiYgIWlzTmFOKCtsYXN0S2V5KSkge1xyXG4gICAgICAgIHN1Yk9iamVjdC5zcGxpY2UobGFzdEtleSwgMCwgdmFsdWUpO1xyXG4gICAgICB9IGVsc2UgaWYgKGlzTWFwKHN1Yk9iamVjdCkpIHtcclxuICAgICAgICBzdWJPYmplY3Quc2V0KGxhc3RLZXksIHZhbHVlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBzdWJPYmplY3RbbGFzdEtleV0gPSB2YWx1ZTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gbmV3T2JqZWN0O1xyXG4gICAgfVxyXG4gICAgY29uc29sZS5lcnJvcihgc2V0Q29weSBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7cG9pbnRlcn1gKTtcclxuICAgIHJldHVybiBvYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5zZXJ0JyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQ2FsbHMgJ3NldCcgd2l0aCBpbnNlcnQgPSBUUlVFXHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBvYmplY3QgdG8gaW5zZXJ0IHZhbHVlIGluXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBvaW50ZXIgLSBKU09OIFBvaW50ZXIgKHN0cmluZyBvciBhcnJheSlcclxuICAgKiAvLyAgIHZhbHVlIC0gdmFsdWUgdG8gaW5zZXJ0XHJcbiAgICogLy8geyBvYmplY3QgfVxyXG4gICAqL1xyXG4gIHN0YXRpYyBpbnNlcnQob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSkge1xyXG4gICAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRoaXMuc2V0KG9iamVjdCwgcG9pbnRlciwgdmFsdWUsIHRydWUpO1xyXG4gICAgcmV0dXJuIHVwZGF0ZWRPYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaW5zZXJ0Q29weScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIENhbGxzICdzZXRDb3B5JyB3aXRoIGluc2VydCA9IFRSVUVcclxuICAgKlxyXG4gICAqIC8vICB7IG9iamVjdCB9IG9iamVjdCAtIG9iamVjdCB0byBpbnNlcnQgdmFsdWUgaW5cclxuICAgKiAvLyAgeyBQb2ludGVyIH0gcG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KVxyXG4gICAqIC8vICAgdmFsdWUgLSB2YWx1ZSB0byBpbnNlcnRcclxuICAgKiAvLyB7IG9iamVjdCB9XHJcbiAgICovXHJcbiAgc3RhdGljIGluc2VydENvcHkob2JqZWN0LCBwb2ludGVyLCB2YWx1ZSkge1xyXG4gICAgY29uc3QgdXBkYXRlZE9iamVjdCA9IHRoaXMuc2V0Q29weShvYmplY3QsIHBvaW50ZXIsIHZhbHVlLCB0cnVlKTtcclxuICAgIHJldHVybiB1cGRhdGVkT2JqZWN0O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3JlbW92ZScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVzZXMgYSBKU09OIFBvaW50ZXIgdG8gcmVtb3ZlIGEga2V5IGFuZCBpdHMgYXR0cmlidXRlIGZyb20gYW4gb2JqZWN0XHJcbiAgICpcclxuICAgKiAvLyAgeyBvYmplY3QgfSBvYmplY3QgLSBvYmplY3QgdG8gZGVsZXRlIGF0dHJpYnV0ZSBmcm9tXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBvaW50ZXIgLSBKU09OIFBvaW50ZXIgKHN0cmluZyBvciBhcnJheSlcclxuICAgKiAvLyB7IG9iamVjdCB9XHJcbiAgICovXHJcbiAgc3RhdGljIHJlbW92ZShvYmplY3QsIHBvaW50ZXIpIHtcclxuICAgIGNvbnN0IGtleUFycmF5ID0gdGhpcy5wYXJzZShwb2ludGVyKTtcclxuICAgIGlmIChrZXlBcnJheSAhPT0gbnVsbCAmJiBrZXlBcnJheS5sZW5ndGgpIHtcclxuICAgICAgbGV0IGxhc3RLZXkgPSBrZXlBcnJheS5wb3AoKTtcclxuICAgICAgY29uc3QgcGFyZW50T2JqZWN0ID0gdGhpcy5nZXQob2JqZWN0LCBrZXlBcnJheSk7XHJcbiAgICAgIGlmIChpc0FycmF5KHBhcmVudE9iamVjdCkpIHtcclxuICAgICAgICBpZiAobGFzdEtleSA9PT0gJy0nKSB7IGxhc3RLZXkgPSBwYXJlbnRPYmplY3QubGVuZ3RoIC0gMTsgfVxyXG4gICAgICAgIHBhcmVudE9iamVjdC5zcGxpY2UobGFzdEtleSwgMSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QocGFyZW50T2JqZWN0KSkge1xyXG4gICAgICAgIGRlbGV0ZSBwYXJlbnRPYmplY3RbbGFzdEtleV07XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG9iamVjdDtcclxuICAgIH1cclxuICAgIGNvbnNvbGUuZXJyb3IoYHJlbW92ZSBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7cG9pbnRlcn1gKTtcclxuICAgIHJldHVybiBvYmplY3Q7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaGFzJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogVGVzdHMgaWYgYW4gb2JqZWN0IGhhcyBhIHZhbHVlIGF0IHRoZSBsb2NhdGlvbiBzcGVjaWZpZWQgYnkgYSBKU09OIFBvaW50ZXJcclxuICAgKlxyXG4gICAqIC8vICB7IG9iamVjdCB9IG9iamVjdCAtIG9iamVjdCB0byBjaGVrIGZvciB2YWx1ZVxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8geyBib29sZWFuIH1cclxuICAgKi9cclxuICBzdGF0aWMgaGFzKG9iamVjdCwgcG9pbnRlcikge1xyXG4gICAgY29uc3QgaGFzVmFsdWUgPSB0aGlzLmdldChvYmplY3QsIHBvaW50ZXIsIDAsIG51bGwsIHRydWUpO1xyXG4gICAgcmV0dXJuIGhhc1ZhbHVlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2RpY3QnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBSZXR1cm5zIGEgKHBvaW50ZXIgLT4gdmFsdWUpIGRpY3Rpb25hcnkgZm9yIGFuIG9iamVjdFxyXG4gICAqXHJcbiAgICogLy8gIHsgb2JqZWN0IH0gb2JqZWN0IC0gVGhlIG9iamVjdCB0byBjcmVhdGUgYSBkaWN0aW9uYXJ5IGZyb21cclxuICAgKiAvLyB7IG9iamVjdCB9IC0gVGhlIHJlc3VsdGluZyBkaWN0aW9uYXJ5IG9iamVjdFxyXG4gICAqL1xyXG4gIHN0YXRpYyBkaWN0KG9iamVjdCkge1xyXG4gICAgY29uc3QgcmVzdWx0czogYW55ID0ge307XHJcbiAgICB0aGlzLmZvckVhY2hEZWVwKG9iamVjdCwgKHZhbHVlLCBwb2ludGVyKSA9PiB7XHJcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJlc3VsdHNbcG9pbnRlcl0gPSB2YWx1ZTsgfVxyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gcmVzdWx0cztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdmb3JFYWNoRGVlcCcgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEl0ZXJhdGVzIG92ZXIgb3duIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBhbiBvYmplY3Qgb3IgaXRlbXMgaW4gYW4gYXJyYXlcclxuICAgKiBhbmQgaW52b2tlcyBhbiBpdGVyYXRlZSBmdW5jdGlvbiBmb3IgZWFjaCBrZXkvdmFsdWUgb3IgaW5kZXgvdmFsdWUgcGFpci5cclxuICAgKiBCeSBkZWZhdWx0LCBpdGVyYXRlcyBvdmVyIGl0ZW1zIHdpdGhpbiBvYmplY3RzIGFuZCBhcnJheXMgYWZ0ZXIgY2FsbGluZ1xyXG4gICAqIHRoZSBpdGVyYXRlZSBmdW5jdGlvbiBvbiB0aGUgY29udGFpbmluZyBvYmplY3Qgb3IgYXJyYXkgaXRzZWxmLlxyXG4gICAqXHJcbiAgICogVGhlIGl0ZXJhdGVlIGlzIGludm9rZWQgd2l0aCB0aHJlZSBhcmd1bWVudHM6ICh2YWx1ZSwgcG9pbnRlciwgcm9vdE9iamVjdCksXHJcbiAgICogd2hlcmUgcG9pbnRlciBpcyBhIEpTT04gcG9pbnRlciBpbmRpY2F0aW5nIHRoZSBsb2NhdGlvbiBvZiB0aGUgY3VycmVudFxyXG4gICAqIHZhbHVlIHdpdGhpbiB0aGUgcm9vdCBvYmplY3QsIGFuZCByb290T2JqZWN0IGlzIHRoZSByb290IG9iamVjdCBpbml0aWFsbHlcclxuICAgKiBzdWJtaXR0ZWQgdG8gdGggZnVuY3Rpb24uXHJcbiAgICpcclxuICAgKiBJZiBhIHRoaXJkIG9wdGlvbmFsIHBhcmFtZXRlciAnYm90dG9tVXAnIGlzIHNldCB0byBUUlVFLCB0aGUgaXRlcmF0b3JcclxuICAgKiBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBvbiBzdWItb2JqZWN0cyBhbmQgYXJyYXlzIGFmdGVyIGJlaW5nXHJcbiAgICogY2FsbGVkIG9uIHRoZWlyIGNvbnRlbnRzLCByYXRoZXIgdGhhbiBiZWZvcmUsIHdoaWNoIGlzIHRoZSBkZWZhdWx0LlxyXG4gICAqXHJcbiAgICogVGhpcyBmdW5jdGlvbiBjYW4gYWxzbyBvcHRpb25hbGx5IGJlIGNhbGxlZCBkaXJlY3RseSBvbiBhIHN1Yi1vYmplY3QgYnlcclxuICAgKiBpbmNsdWRpbmcgb3B0aW9uYWwgNHRoIGFuZCA1dGggcGFyYW1ldGVyc3MgdG8gc3BlY2lmeSB0aGUgaW5pdGlhbFxyXG4gICAqIHJvb3Qgb2JqZWN0IGFuZCBwb2ludGVyLlxyXG4gICAqXHJcbiAgICogLy8gIHsgb2JqZWN0IH0gb2JqZWN0IC0gdGhlIGluaXRpYWwgb2JqZWN0IG9yIGFycmF5XHJcbiAgICogLy8gIHsgKHY6IGFueSwgcD86IHN0cmluZywgbz86IGFueSkgPT4gYW55IH0gZnVuY3Rpb24gLSBpdGVyYXRlZSBmdW5jdGlvblxyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGJvdHRvbVVwIC0gb3B0aW9uYWwsIHNldCB0byBUUlVFIHRvIHJldmVyc2UgZGlyZWN0aW9uXHJcbiAgICogLy8gIHsgb2JqZWN0ID0gb2JqZWN0IH0gcm9vdE9iamVjdCAtIG9wdGlvbmFsLCByb290IG9iamVjdCBvciBhcnJheVxyXG4gICAqIC8vICB7IHN0cmluZyA9ICcnIH0gcG9pbnRlciAtIG9wdGlvbmFsLCBKU09OIFBvaW50ZXIgdG8gb2JqZWN0IHdpdGhpbiByb290T2JqZWN0XHJcbiAgICogLy8geyBvYmplY3QgfSAtIFRoZSBtb2RpZmllZCBvYmplY3RcclxuICAgKi9cclxuICBzdGF0aWMgZm9yRWFjaERlZXAoXHJcbiAgICBvYmplY3QsIGZuOiAodjogYW55LCBwPzogc3RyaW5nLCBvPzogYW55KSA9PiBhbnkgPSAodikgPT4gdixcclxuICAgIGJvdHRvbVVwID0gZmFsc2UsIHBvaW50ZXIgPSAnJywgcm9vdE9iamVjdCA9IG9iamVjdFxyXG4gICkge1xyXG4gICAgaWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGBmb3JFYWNoRGVlcCBlcnJvcjogSXRlcmF0b3IgaXMgbm90IGEgZnVuY3Rpb246YCwgZm4pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAoIWJvdHRvbVVwKSB7IGZuKG9iamVjdCwgcG9pbnRlciwgcm9vdE9iamVjdCk7IH1cclxuICAgIGlmIChpc09iamVjdChvYmplY3QpIHx8IGlzQXJyYXkob2JqZWN0KSkge1xyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhvYmplY3QpKSB7XHJcbiAgICAgICAgY29uc3QgbmV3UG9pbnRlciA9IHBvaW50ZXIgKyAnLycgKyB0aGlzLmVzY2FwZShrZXkpO1xyXG4gICAgICAgIHRoaXMuZm9yRWFjaERlZXAob2JqZWN0W2tleV0sIGZuLCBib3R0b21VcCwgbmV3UG9pbnRlciwgcm9vdE9iamVjdCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChib3R0b21VcCkgeyBmbihvYmplY3QsIHBvaW50ZXIsIHJvb3RPYmplY3QpOyB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZm9yRWFjaERlZXBDb3B5JyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogU2ltaWxhciB0byBmb3JFYWNoRGVlcCwgYnV0IHJldHVybnMgYSBjb3B5IG9mIHRoZSBvcmlnaW5hbCBvYmplY3QsIHdpdGhcclxuICAgKiB0aGUgc2FtZSBrZXlzIGFuZCBpbmRleGVzLCBidXQgd2l0aCB2YWx1ZXMgcmVwbGFjZWQgd2l0aCB0aGUgcmVzdWx0IG9mXHJcbiAgICogdGhlIGl0ZXJhdGVlIGZ1bmN0aW9uLlxyXG4gICAqXHJcbiAgICogLy8gIHsgb2JqZWN0IH0gb2JqZWN0IC0gdGhlIGluaXRpYWwgb2JqZWN0IG9yIGFycmF5XHJcbiAgICogLy8gIHsgKHY6IGFueSwgaz86IHN0cmluZywgbz86IGFueSwgcD86IGFueSkgPT4gYW55IH0gZnVuY3Rpb24gLSBpdGVyYXRlZSBmdW5jdGlvblxyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGJvdHRvbVVwIC0gb3B0aW9uYWwsIHNldCB0byBUUlVFIHRvIHJldmVyc2UgZGlyZWN0aW9uXHJcbiAgICogLy8gIHsgb2JqZWN0ID0gb2JqZWN0IH0gcm9vdE9iamVjdCAtIG9wdGlvbmFsLCByb290IG9iamVjdCBvciBhcnJheVxyXG4gICAqIC8vICB7IHN0cmluZyA9ICcnIH0gcG9pbnRlciAtIG9wdGlvbmFsLCBKU09OIFBvaW50ZXIgdG8gb2JqZWN0IHdpdGhpbiByb290T2JqZWN0XHJcbiAgICogLy8geyBvYmplY3QgfSAtIFRoZSBjb3BpZWQgb2JqZWN0XHJcbiAgICovXHJcbiAgc3RhdGljIGZvckVhY2hEZWVwQ29weShcclxuICAgIG9iamVjdCwgZm46ICh2OiBhbnksIHA/OiBzdHJpbmcsIG8/OiBhbnkpID0+IGFueSA9ICh2KSA9PiB2LFxyXG4gICAgYm90dG9tVXAgPSBmYWxzZSwgcG9pbnRlciA9ICcnLCByb290T2JqZWN0ID0gb2JqZWN0XHJcbiAgKSB7XHJcbiAgICBpZiAodHlwZW9mIGZuICE9PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYGZvckVhY2hEZWVwQ29weSBlcnJvcjogSXRlcmF0b3IgaXMgbm90IGEgZnVuY3Rpb246YCwgZm4pO1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGlmIChpc09iamVjdChvYmplY3QpIHx8IGlzQXJyYXkob2JqZWN0KSkge1xyXG4gICAgICBsZXQgbmV3T2JqZWN0ID0gaXNBcnJheShvYmplY3QpID8gWyAuLi5vYmplY3QgXSA6IHsgLi4ub2JqZWN0IH07XHJcbiAgICAgIGlmICghYm90dG9tVXApIHsgbmV3T2JqZWN0ID0gZm4obmV3T2JqZWN0LCBwb2ludGVyLCByb290T2JqZWN0KTsgfVxyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhuZXdPYmplY3QpKSB7XHJcbiAgICAgICAgY29uc3QgbmV3UG9pbnRlciA9IHBvaW50ZXIgKyAnLycgKyB0aGlzLmVzY2FwZShrZXkpO1xyXG4gICAgICAgIG5ld09iamVjdFtrZXldID0gdGhpcy5mb3JFYWNoRGVlcENvcHkoXHJcbiAgICAgICAgICBuZXdPYmplY3Rba2V5XSwgZm4sIGJvdHRvbVVwLCBuZXdQb2ludGVyLCByb290T2JqZWN0XHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAoYm90dG9tVXApIHsgbmV3T2JqZWN0ID0gZm4obmV3T2JqZWN0LCBwb2ludGVyLCByb290T2JqZWN0KTsgfVxyXG4gICAgICByZXR1cm4gbmV3T2JqZWN0O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIGZuKG9iamVjdCwgcG9pbnRlciwgcm9vdE9iamVjdCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnZXNjYXBlJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogRXNjYXBlcyBhIHN0cmluZyByZWZlcmVuY2Uga2V5XHJcbiAgICpcclxuICAgKiAvLyAgeyBzdHJpbmcgfSBrZXkgLSBzdHJpbmcga2V5IHRvIGVzY2FwZVxyXG4gICAqIC8vIHsgc3RyaW5nIH0gLSBlc2NhcGVkIGtleVxyXG4gICAqL1xyXG4gIHN0YXRpYyBlc2NhcGUoa2V5KSB7XHJcbiAgICBjb25zdCBlc2NhcGVkID0ga2V5LnRvU3RyaW5nKCkucmVwbGFjZSgvfi9nLCAnfjAnKS5yZXBsYWNlKC9cXC8vZywgJ34xJyk7XHJcbiAgICByZXR1cm4gZXNjYXBlZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd1bmVzY2FwZScgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIFVuZXNjYXBlcyBhIHN0cmluZyByZWZlcmVuY2Uga2V5XHJcbiAgICpcclxuICAgKiAvLyAgeyBzdHJpbmcgfSBrZXkgLSBzdHJpbmcga2V5IHRvIHVuZXNjYXBlXHJcbiAgICogLy8geyBzdHJpbmcgfSAtIHVuZXNjYXBlZCBrZXlcclxuICAgKi9cclxuICBzdGF0aWMgdW5lc2NhcGUoa2V5KSB7XHJcbiAgICBjb25zdCB1bmVzY2FwZWQgPSBrZXkudG9TdHJpbmcoKS5yZXBsYWNlKC9+MS9nLCAnLycpLnJlcGxhY2UoL34wL2csICd+Jyk7XHJcbiAgICByZXR1cm4gdW5lc2NhcGVkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3BhcnNlJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQ29udmVydHMgYSBzdHJpbmcgSlNPTiBQb2ludGVyIGludG8gYSBhcnJheSBvZiBrZXlzXHJcbiAgICogKGlmIGlucHV0IGlzIGFscmVhZHkgYW4gYW4gYXJyYXkgb2Yga2V5cywgaXQgaXMgcmV0dXJuZWQgdW5jaGFuZ2VkKVxyXG4gICAqXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBvaW50ZXIgLSBKU09OIFBvaW50ZXIgKHN0cmluZyBvciBhcnJheSlcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBlcnJvcnMgLSBTaG93IGVycm9yIGlmIGludmFsaWQgcG9pbnRlcj9cclxuICAgKiAvLyB7IHN0cmluZ1tdIH0gLSBKU09OIFBvaW50ZXIgYXJyYXkgb2Yga2V5c1xyXG4gICAqL1xyXG4gIHN0YXRpYyBwYXJzZShwb2ludGVyLCBlcnJvcnMgPSBmYWxzZSkge1xyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIocG9pbnRlcikpIHtcclxuICAgICAgaWYgKGVycm9ycykgeyBjb25zb2xlLmVycm9yKGBwYXJzZSBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7cG9pbnRlcn1gKTsgfVxyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGlmIChpc0FycmF5KHBvaW50ZXIpKSB7IHJldHVybiA8c3RyaW5nW10+cG9pbnRlcjsgfVxyXG4gICAgaWYgKHR5cGVvZiBwb2ludGVyID09PSAnc3RyaW5nJykge1xyXG4gICAgICBpZiAoKDxzdHJpbmc+cG9pbnRlcilbMF0gPT09ICcjJykgeyBwb2ludGVyID0gcG9pbnRlci5zbGljZSgxKTsgfVxyXG4gICAgICBpZiAoPHN0cmluZz5wb2ludGVyID09PSAnJyB8fCA8c3RyaW5nPnBvaW50ZXIgPT09ICcvJykgeyByZXR1cm4gW107IH1cclxuICAgICAgcmV0dXJuICg8c3RyaW5nPnBvaW50ZXIpLnNsaWNlKDEpLnNwbGl0KCcvJykubWFwKHRoaXMudW5lc2NhcGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2NvbXBpbGUnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBDb252ZXJ0cyBhbiBhcnJheSBvZiBrZXlzIGludG8gYSBKU09OIFBvaW50ZXIgc3RyaW5nXHJcbiAgICogKGlmIGlucHV0IGlzIGFscmVhZHkgYSBzdHJpbmcsIGl0IGlzIG5vcm1hbGl6ZWQgYW5kIHJldHVybmVkKVxyXG4gICAqXHJcbiAgICogVGhlIG9wdGlvbmFsIHNlY29uZCBwYXJhbWV0ZXIgaXMgYSBkZWZhdWx0IHdoaWNoIHdpbGwgcmVwbGFjZSBhbnkgZW1wdHkga2V5cy5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8gIHsgc3RyaW5nIHwgbnVtYmVyID0gJycgfSBkZWZhdWx0VmFsdWUgLSBEZWZhdWx0IHZhbHVlXHJcbiAgICogLy8gIHsgYm9vbGVhbiA9IGZhbHNlIH0gZXJyb3JzIC0gU2hvdyBlcnJvciBpZiBpbnZhbGlkIHBvaW50ZXI/XHJcbiAgICogLy8geyBzdHJpbmcgfSAtIEpTT04gUG9pbnRlciBzdHJpbmdcclxuICAgKi9cclxuICBzdGF0aWMgY29tcGlsZShwb2ludGVyLCBkZWZhdWx0VmFsdWUgPSAnJywgZXJyb3JzID0gZmFsc2UpIHtcclxuICAgIGlmIChwb2ludGVyID09PSAnIycpIHsgcmV0dXJuICcnOyB9XHJcbiAgICBpZiAoIXRoaXMuaXNKc29uUG9pbnRlcihwb2ludGVyKSkge1xyXG4gICAgICBpZiAoZXJyb3JzKSB7IGNvbnNvbGUuZXJyb3IoYGNvbXBpbGUgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke3BvaW50ZXJ9YCk7IH1cclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAoaXNBcnJheShwb2ludGVyKSkge1xyXG4gICAgICBpZiAoKDxzdHJpbmdbXT5wb2ludGVyKS5sZW5ndGggPT09IDApIHsgcmV0dXJuICcnOyB9XHJcbiAgICAgIHJldHVybiAnLycgKyAoPHN0cmluZ1tdPnBvaW50ZXIpLm1hcChcclxuICAgICAgICBrZXkgPT4ga2V5ID09PSAnJyA/IGRlZmF1bHRWYWx1ZSA6IHRoaXMuZXNjYXBlKGtleSlcclxuICAgICAgKS5qb2luKCcvJyk7XHJcbiAgICB9XHJcbiAgICBpZiAodHlwZW9mIHBvaW50ZXIgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGlmIChwb2ludGVyWzBdID09PSAnIycpIHsgcG9pbnRlciA9IHBvaW50ZXIuc2xpY2UoMSk7IH1cclxuICAgICAgcmV0dXJuIHBvaW50ZXI7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndG9LZXknIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBFeHRyYWN0cyBuYW1lIG9mIHRoZSBmaW5hbCBrZXkgZnJvbSBhIEpTT04gUG9pbnRlci5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBwb2ludGVyIC0gSlNPTiBQb2ludGVyIChzdHJpbmcgb3IgYXJyYXkpXHJcbiAgICogLy8gIHsgYm9vbGVhbiA9IGZhbHNlIH0gZXJyb3JzIC0gU2hvdyBlcnJvciBpZiBpbnZhbGlkIHBvaW50ZXI/XHJcbiAgICogLy8geyBzdHJpbmcgfSAtIHRoZSBleHRyYWN0ZWQga2V5XHJcbiAgICovXHJcbiAgc3RhdGljIHRvS2V5KHBvaW50ZXIsIGVycm9ycyA9IGZhbHNlKSB7XHJcbiAgICBjb25zdCBrZXlBcnJheSA9IHRoaXMucGFyc2UocG9pbnRlciwgZXJyb3JzKTtcclxuICAgIGlmIChrZXlBcnJheSA9PT0gbnVsbCkgeyByZXR1cm4gbnVsbDsgfVxyXG4gICAgaWYgKCFrZXlBcnJheS5sZW5ndGgpIHsgcmV0dXJuICcnOyB9XHJcbiAgICByZXR1cm4ga2V5QXJyYXlba2V5QXJyYXkubGVuZ3RoIC0gMV07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAnaXNKc29uUG9pbnRlcicgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIENoZWNrcyBhIHN0cmluZyBvciBhcnJheSB2YWx1ZSB0byBkZXRlcm1pbmUgaWYgaXQgaXMgYSB2YWxpZCBKU09OIFBvaW50ZXIuXHJcbiAgICogUmV0dXJucyB0cnVlIGlmIGEgc3RyaW5nIGlzIGVtcHR5LCBvciBzdGFydHMgd2l0aCAnLycgb3IgJyMvJy5cclxuICAgKiBSZXR1cm5zIHRydWUgaWYgYW4gYXJyYXkgY29udGFpbnMgb25seSBzdHJpbmcgdmFsdWVzLlxyXG4gICAqXHJcbiAgICogLy8gICB2YWx1ZSAtIHZhbHVlIHRvIGNoZWNrXHJcbiAgICogLy8geyBib29sZWFuIH0gLSB0cnVlIGlmIHZhbHVlIGlzIGEgdmFsaWQgSlNPTiBQb2ludGVyLCBvdGhlcndpc2UgZmFsc2VcclxuICAgKi9cclxuICBzdGF0aWMgaXNKc29uUG9pbnRlcih2YWx1ZSkge1xyXG4gICAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XHJcbiAgICAgIHJldHVybiB2YWx1ZS5ldmVyeShrZXkgPT4gdHlwZW9mIGtleSA9PT0gJ3N0cmluZycpO1xyXG4gICAgfSBlbHNlIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcclxuICAgICAgaWYgKHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gJyMnKSB7IHJldHVybiB0cnVlOyB9XHJcbiAgICAgIGlmICh2YWx1ZVswXSA9PT0gJy8nIHx8IHZhbHVlLnNsaWNlKDAsIDIpID09PSAnIy8nKSB7XHJcbiAgICAgICAgcmV0dXJuICEvKH5bXjAxXXx+JCkvZy50ZXN0KHZhbHVlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ2lzU3ViUG9pbnRlcicgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIENoZWNrcyB3aGV0aGVyIG9uZSBKU09OIFBvaW50ZXIgaXMgYSBzdWJzZXQgb2YgYW5vdGhlci5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBzaG9ydFBvaW50ZXIgLSBwb3RlbnRpYWwgc3Vic2V0IEpTT04gUG9pbnRlclxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBsb25nUG9pbnRlciAtIHBvdGVudGlhbCBzdXBlcnNldCBKU09OIFBvaW50ZXJcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSB0cnVlSWZNYXRjaGluZyAtIHJldHVybiB0cnVlIGlmIHBvaW50ZXJzIG1hdGNoP1xyXG4gICAqIC8vICB7IGJvb2xlYW4gPSBmYWxzZSB9IGVycm9ycyAtIFNob3cgZXJyb3IgaWYgaW52YWxpZCBwb2ludGVyP1xyXG4gICAqIC8vIHsgYm9vbGVhbiB9IC0gdHJ1ZSBpZiBzaG9ydFBvaW50ZXIgaXMgYSBzdWJzZXQgb2YgbG9uZ1BvaW50ZXIsIGZhbHNlIGlmIG5vdFxyXG4gICAqL1xyXG4gIHN0YXRpYyBpc1N1YlBvaW50ZXIoXHJcbiAgICBzaG9ydFBvaW50ZXIsIGxvbmdQb2ludGVyLCB0cnVlSWZNYXRjaGluZyA9IGZhbHNlLCBlcnJvcnMgPSBmYWxzZVxyXG4gICkge1xyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoc2hvcnRQb2ludGVyKSB8fCAhdGhpcy5pc0pzb25Qb2ludGVyKGxvbmdQb2ludGVyKSkge1xyXG4gICAgICBpZiAoZXJyb3JzKSB7XHJcbiAgICAgICAgbGV0IGludmFsaWQgPSAnJztcclxuICAgICAgICBpZiAoIXRoaXMuaXNKc29uUG9pbnRlcihzaG9ydFBvaW50ZXIpKSB7IGludmFsaWQgKz0gYCAxOiAke3Nob3J0UG9pbnRlcn1gOyB9XHJcbiAgICAgICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIobG9uZ1BvaW50ZXIpKSB7IGludmFsaWQgKz0gYCAyOiAke2xvbmdQb2ludGVyfWA7IH1cclxuICAgICAgICBjb25zb2xlLmVycm9yKGBpc1N1YlBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyICR7aW52YWxpZH1gKTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBzaG9ydFBvaW50ZXIgPSB0aGlzLmNvbXBpbGUoc2hvcnRQb2ludGVyLCAnJywgZXJyb3JzKTtcclxuICAgIGxvbmdQb2ludGVyID0gdGhpcy5jb21waWxlKGxvbmdQb2ludGVyLCAnJywgZXJyb3JzKTtcclxuICAgIHJldHVybiBzaG9ydFBvaW50ZXIgPT09IGxvbmdQb2ludGVyID8gdHJ1ZUlmTWF0Y2hpbmcgOlxyXG4gICAgICBgJHtzaG9ydFBvaW50ZXJ9L2AgPT09IGxvbmdQb2ludGVyLnNsaWNlKDAsIHNob3J0UG9pbnRlci5sZW5ndGggKyAxKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd0b0luZGV4ZWRQb2ludGVyJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogTWVyZ2VzIGFuIGFycmF5IG9mIG51bWVyaWMgaW5kZXhlcyBhbmQgYSBnZW5lcmljIHBvaW50ZXIgdG8gY3JlYXRlIGFuXHJcbiAgICogaW5kZXhlZCBwb2ludGVyIGZvciBhIHNwZWNpZmljIGl0ZW0uXHJcbiAgICpcclxuICAgKiBGb3IgZXhhbXBsZSwgbWVyZ2luZyB0aGUgZ2VuZXJpYyBwb2ludGVyICcvZm9vLy0vYmFyLy0vYmF6JyBhbmRcclxuICAgKiB0aGUgYXJyYXkgWzQsIDJdIHdvdWxkIHJlc3VsdCBpbiB0aGUgaW5kZXhlZCBwb2ludGVyICcvZm9vLzQvYmFyLzIvYmF6J1xyXG4gICAqXHJcbiAgICpcclxuICAgKiAvLyAgeyBQb2ludGVyIH0gZ2VuZXJpY1BvaW50ZXIgLSBUaGUgZ2VuZXJpYyBwb2ludGVyXHJcbiAgICogLy8gIHsgbnVtYmVyW10gfSBpbmRleEFycmF5IC0gVGhlIGFycmF5IG9mIG51bWVyaWMgaW5kZXhlc1xyXG4gICAqIC8vICB7IE1hcDxzdHJpbmcsIG51bWJlcj4gfSBhcnJheU1hcCAtIEFuIG9wdGlvbmFsIGFycmF5IG1hcFxyXG4gICAqIC8vIHsgc3RyaW5nIH0gLSBUaGUgbWVyZ2VkIHBvaW50ZXIgd2l0aCBpbmRleGVzXHJcbiAgICovXHJcbiAgc3RhdGljIHRvSW5kZXhlZFBvaW50ZXIoXHJcbiAgICBnZW5lcmljUG9pbnRlciwgaW5kZXhBcnJheSwgYXJyYXlNYXA6IE1hcDxzdHJpbmcsIG51bWJlcj4gPSBudWxsXHJcbiAgKSB7XHJcbiAgICBpZiAodGhpcy5pc0pzb25Qb2ludGVyKGdlbmVyaWNQb2ludGVyKSAmJiBpc0FycmF5KGluZGV4QXJyYXkpKSB7XHJcbiAgICAgIGxldCBpbmRleGVkUG9pbnRlciA9IHRoaXMuY29tcGlsZShnZW5lcmljUG9pbnRlcik7XHJcbiAgICAgIGlmIChpc01hcChhcnJheU1hcCkpIHtcclxuICAgICAgICBsZXQgYXJyYXlJbmRleCA9IDA7XHJcbiAgICAgICAgcmV0dXJuIGluZGV4ZWRQb2ludGVyLnJlcGxhY2UoL1xcL1xcLSg/PVxcL3wkKS9nLCAoa2V5LCBzdHJpbmdJbmRleCkgPT5cclxuICAgICAgICAgIGFycmF5TWFwLmhhcygoPHN0cmluZz5pbmRleGVkUG9pbnRlcikuc2xpY2UoMCwgc3RyaW5nSW5kZXgpKSA/XHJcbiAgICAgICAgICAgICcvJyArIGluZGV4QXJyYXlbYXJyYXlJbmRleCsrXSA6IGtleVxyXG4gICAgICAgICk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZm9yIChjb25zdCBwb2ludGVySW5kZXggb2YgaW5kZXhBcnJheSkge1xyXG4gICAgICAgICAgaW5kZXhlZFBvaW50ZXIgPSBpbmRleGVkUG9pbnRlci5yZXBsYWNlKCcvLScsICcvJyArIHBvaW50ZXJJbmRleCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBpbmRleGVkUG9pbnRlcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoZ2VuZXJpY1BvaW50ZXIpKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvSW5kZXhlZFBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBQb2ludGVyOiAke2dlbmVyaWNQb2ludGVyfWApO1xyXG4gICAgfVxyXG4gICAgaWYgKCFpc0FycmF5KGluZGV4QXJyYXkpKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvSW5kZXhlZFBvaW50ZXIgZXJyb3I6IEludmFsaWQgaW5kZXhBcnJheTogJHtpbmRleEFycmF5fWApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogJ3RvR2VuZXJpY1BvaW50ZXInIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBDb21wYXJlcyBhbiBpbmRleGVkIHBvaW50ZXIgdG8gYW4gYXJyYXkgbWFwIGFuZCByZW1vdmVzIGxpc3QgYXJyYXlcclxuICAgKiBpbmRleGVzIChidXQgbGVhdmVzIHR1cGxlIGFycnJheSBpbmRleGVzIGFuZCBhbGwgb2JqZWN0IGtleXMsIGluY2x1ZGluZ1xyXG4gICAqIG51bWVyaWMga2V5cykgdG8gY3JlYXRlIGEgZ2VuZXJpYyBwb2ludGVyLlxyXG4gICAqXHJcbiAgICogRm9yIGV4YW1wbGUsIHVzaW5nIHRoZSBpbmRleGVkIHBvaW50ZXIgJy9mb28vMS9iYXIvMi9iYXovMycgYW5kXHJcbiAgICogdGhlIGFycmF5TWFwIFtbJy9mb28nLCAwXSwgWycvZm9vLy0vYmFyJywgM10sIFsnL2Zvby8tL2Jhci8tL2JheicsIDBdXVxyXG4gICAqIHdvdWxkIHJlc3VsdCBpbiB0aGUgZ2VuZXJpYyBwb2ludGVyICcvZm9vLy0vYmFyLzIvYmF6Ly0nXHJcbiAgICogVXNpbmcgdGhlIGluZGV4ZWQgcG9pbnRlciAnL2Zvby8xL2Jhci80L2Jhei8zJyBhbmQgdGhlIHNhbWUgYXJyYXlNYXBcclxuICAgKiB3b3VsZCByZXN1bHQgaW4gdGhlIGdlbmVyaWMgcG9pbnRlciAnL2Zvby8tL2Jhci8tL2Jhei8tJ1xyXG4gICAqICh0aGUgYmFyIGFycmF5IGhhcyAzIHR1cGxlIGl0ZW1zLCBzbyBpbmRleCAyIGlzIHJldGFpbmVkLCBidXQgNCBpcyByZW1vdmVkKVxyXG4gICAqXHJcbiAgICogVGhlIHN0cnVjdHVyZSBvZiB0aGUgYXJyYXlNYXAgaXM6IFtbJ3BhdGggdG8gYXJyYXknLCBudW1iZXIgb2YgdHVwbGUgaXRlbXNdLi4uXVxyXG4gICAqXHJcbiAgICpcclxuICAgKiAvLyAgeyBQb2ludGVyIH0gaW5kZXhlZFBvaW50ZXIgLSBUaGUgaW5kZXhlZCBwb2ludGVyIChhcnJheSBvciBzdHJpbmcpXHJcbiAgICogLy8gIHsgTWFwPHN0cmluZywgbnVtYmVyPiB9IGFycmF5TWFwIC0gVGhlIG9wdGlvbmFsIGFycmF5IG1hcCAoZm9yIHByZXNlcnZpbmcgdHVwbGUgaW5kZXhlcylcclxuICAgKiAvLyB7IHN0cmluZyB9IC0gVGhlIGdlbmVyaWMgcG9pbnRlciB3aXRoIGluZGV4ZXMgcmVtb3ZlZFxyXG4gICAqL1xyXG4gIHN0YXRpYyB0b0dlbmVyaWNQb2ludGVyKGluZGV4ZWRQb2ludGVyLCBhcnJheU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCkpIHtcclxuICAgIGlmICh0aGlzLmlzSnNvblBvaW50ZXIoaW5kZXhlZFBvaW50ZXIpICYmIGlzTWFwKGFycmF5TWFwKSkge1xyXG4gICAgICBjb25zdCBwb2ludGVyQXJyYXkgPSB0aGlzLnBhcnNlKGluZGV4ZWRQb2ludGVyKTtcclxuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBwb2ludGVyQXJyYXkubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBjb25zdCBzdWJQb2ludGVyID0gdGhpcy5jb21waWxlKHBvaW50ZXJBcnJheS5zbGljZSgwLCBpKSk7XHJcbiAgICAgICAgaWYgKGFycmF5TWFwLmhhcyhzdWJQb2ludGVyKSAmJlxyXG4gICAgICAgICAgYXJyYXlNYXAuZ2V0KHN1YlBvaW50ZXIpIDw9ICtwb2ludGVyQXJyYXlbaV1cclxuICAgICAgICApIHtcclxuICAgICAgICAgIHBvaW50ZXJBcnJheVtpXSA9ICctJztcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRoaXMuY29tcGlsZShwb2ludGVyQXJyYXkpO1xyXG4gICAgfVxyXG4gICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoaW5kZXhlZFBvaW50ZXIpKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvR2VuZXJpY1BvaW50ZXIgZXJyb3I6IGludmFsaWQgSlNPTiBQb2ludGVyOiAke2luZGV4ZWRQb2ludGVyfWApO1xyXG4gICAgfVxyXG4gICAgaWYgKCFpc01hcChhcnJheU1hcCkpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgdG9HZW5lcmljUG9pbnRlciBlcnJvcjogaW52YWxpZCBhcnJheU1hcDogJHthcnJheU1hcH1gKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICd0b0NvbnRyb2xQb2ludGVyJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhIEpTT04gUG9pbnRlciBmb3IgYSBkYXRhIG9iamVjdCBhbmQgcmV0dXJucyBhIEpTT04gUG9pbnRlciBmb3IgdGhlXHJcbiAgICogbWF0Y2hpbmcgY29udHJvbCBpbiBhbiBBbmd1bGFyIEZvcm1Hcm91cC5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBkYXRhUG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KSB0byBhIGRhdGEgb2JqZWN0XHJcbiAgICogLy8gIHsgRm9ybUdyb3VwIH0gZm9ybUdyb3VwIC0gQW5ndWxhciBGb3JtR3JvdXAgdG8gZ2V0IHZhbHVlIGZyb21cclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBjb250cm9sTXVzdEV4aXN0IC0gT25seSByZXR1cm4gaWYgY29udHJvbCBleGlzdHM/XHJcbiAgICogLy8geyBQb2ludGVyIH0gLSBKU09OIFBvaW50ZXIgKHN0cmluZykgdG8gdGhlIGZvcm1Hcm91cCBvYmplY3RcclxuICAgKi9cclxuICBzdGF0aWMgdG9Db250cm9sUG9pbnRlcihkYXRhUG9pbnRlciwgZm9ybUdyb3VwLCBjb250cm9sTXVzdEV4aXN0ID0gZmFsc2UpIHtcclxuICAgIGNvbnN0IGRhdGFQb2ludGVyQXJyYXkgPSB0aGlzLnBhcnNlKGRhdGFQb2ludGVyKTtcclxuICAgIGNvbnN0IGNvbnRyb2xQb2ludGVyQXJyYXk6IHN0cmluZ1tdID0gW107XHJcbiAgICBsZXQgc3ViR3JvdXAgPSBmb3JtR3JvdXA7XHJcbiAgICBpZiAoZGF0YVBvaW50ZXJBcnJheSAhPT0gbnVsbCkge1xyXG4gICAgICBmb3IgKGNvbnN0IGtleSBvZiBkYXRhUG9pbnRlckFycmF5KSB7XHJcbiAgICAgICAgaWYgKGhhc093bihzdWJHcm91cCwgJ2NvbnRyb2xzJykpIHtcclxuICAgICAgICAgIGNvbnRyb2xQb2ludGVyQXJyYXkucHVzaCgnY29udHJvbHMnKTtcclxuICAgICAgICAgIHN1Ykdyb3VwID0gc3ViR3JvdXAuY29udHJvbHM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc0FycmF5KHN1Ykdyb3VwKSAmJiAoa2V5ID09PSAnLScpKSB7XHJcbiAgICAgICAgICBjb250cm9sUG9pbnRlckFycmF5LnB1c2goKHN1Ykdyb3VwLmxlbmd0aCAtIDEpLnRvU3RyaW5nKCkpO1xyXG4gICAgICAgICAgc3ViR3JvdXAgPSBzdWJHcm91cFtzdWJHcm91cC5sZW5ndGggLSAxXTtcclxuICAgICAgICB9IGVsc2UgaWYgKGhhc093bihzdWJHcm91cCwga2V5KSkge1xyXG4gICAgICAgICAgY29udHJvbFBvaW50ZXJBcnJheS5wdXNoKGtleSk7XHJcbiAgICAgICAgICBzdWJHcm91cCA9IHN1Ykdyb3VwW2tleV07XHJcbiAgICAgICAgfSBlbHNlIGlmIChjb250cm9sTXVzdEV4aXN0KSB7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGB0b0NvbnRyb2xQb2ludGVyIGVycm9yOiBVbmFibGUgdG8gZmluZCBcIiR7a2V5fVwiIGl0ZW0gaW4gRm9ybUdyb3VwLmApO1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcihkYXRhUG9pbnRlcik7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGZvcm1Hcm91cCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnRyb2xQb2ludGVyQXJyYXkucHVzaChrZXkpO1xyXG4gICAgICAgICAgc3ViR3JvdXAgPSB7IGNvbnRyb2xzOiB7fSB9O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gdGhpcy5jb21waWxlKGNvbnRyb2xQb2ludGVyQXJyYXkpO1xyXG4gICAgfVxyXG4gICAgY29uc29sZS5lcnJvcihgdG9Db250cm9sUG9pbnRlciBlcnJvcjogSW52YWxpZCBKU09OIFBvaW50ZXI6ICR7ZGF0YVBvaW50ZXJ9YCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndG9TY2hlbWFQb2ludGVyJyBmdW5jdGlvblxyXG4gICAqXHJcbiAgICogQWNjZXB0cyBhIEpTT04gUG9pbnRlciB0byBhIHZhbHVlIGluc2lkZSBhIGRhdGEgb2JqZWN0IGFuZCBhIEpTT04gc2NoZW1hXHJcbiAgICogZm9yIHRoYXQgb2JqZWN0LlxyXG4gICAqXHJcbiAgICogUmV0dXJucyBhIFBvaW50ZXIgdG8gdGhlIHN1Yi1zY2hlbWEgZm9yIHRoZSB2YWx1ZSBpbnNpZGUgdGhlIG9iamVjdCdzIHNjaGVtYS5cclxuICAgKlxyXG4gICAqIC8vICB7IFBvaW50ZXIgfSBkYXRhUG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KSB0byBhbiBvYmplY3RcclxuICAgKiAvLyAgIHNjaGVtYSAtIEpTT04gc2NoZW1hIGZvciB0aGUgb2JqZWN0XHJcbiAgICogLy8geyBQb2ludGVyIH0gLSBKU09OIFBvaW50ZXIgKHN0cmluZykgdG8gdGhlIG9iamVjdCdzIHNjaGVtYVxyXG4gICAqL1xyXG4gIHN0YXRpYyB0b1NjaGVtYVBvaW50ZXIoZGF0YVBvaW50ZXIsIHNjaGVtYSkge1xyXG4gICAgaWYgKHRoaXMuaXNKc29uUG9pbnRlcihkYXRhUG9pbnRlcikgJiYgdHlwZW9mIHNjaGVtYSA9PT0gJ29iamVjdCcpIHtcclxuICAgICAgY29uc3QgcG9pbnRlckFycmF5ID0gdGhpcy5wYXJzZShkYXRhUG9pbnRlcik7XHJcbiAgICAgIGlmICghcG9pbnRlckFycmF5Lmxlbmd0aCkgeyByZXR1cm4gJyc7IH1cclxuICAgICAgY29uc3QgZmlyc3RLZXkgPSBwb2ludGVyQXJyYXkuc2hpZnQoKTtcclxuICAgICAgaWYgKHNjaGVtYS50eXBlID09PSAnb2JqZWN0JyB8fCBzY2hlbWEucHJvcGVydGllcyB8fCBzY2hlbWEuYWRkaXRpb25hbFByb3BlcnRpZXMpIHtcclxuICAgICAgICBpZiAoKHNjaGVtYS5wcm9wZXJ0aWVzIHx8IHt9KVtmaXJzdEtleV0pIHtcclxuICAgICAgICAgIHJldHVybiBgL3Byb3BlcnRpZXMvJHt0aGlzLmVzY2FwZShmaXJzdEtleSl9YCArXHJcbiAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLnByb3BlcnRpZXNbZmlyc3RLZXldKTtcclxuICAgICAgICB9IGVsc2UgIGlmIChzY2hlbWEuYWRkaXRpb25hbFByb3BlcnRpZXMpIHtcclxuICAgICAgICAgIHJldHVybiAnL2FkZGl0aW9uYWxQcm9wZXJ0aWVzJyArXHJcbiAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLmFkZGl0aW9uYWxQcm9wZXJ0aWVzKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgaWYgKChzY2hlbWEudHlwZSA9PT0gJ2FycmF5JyB8fCBzY2hlbWEuaXRlbXMpICYmXHJcbiAgICAgICAgKGlzTnVtYmVyKGZpcnN0S2V5KSB8fCBmaXJzdEtleSA9PT0gJy0nIHx8IGZpcnN0S2V5ID09PSAnJylcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgYXJyYXlJdGVtID0gZmlyc3RLZXkgPT09ICctJyB8fCBmaXJzdEtleSA9PT0gJycgPyAwIDogK2ZpcnN0S2V5O1xyXG4gICAgICAgIGlmIChpc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcclxuICAgICAgICAgIGlmIChhcnJheUl0ZW0gPCBzY2hlbWEuaXRlbXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAnL2l0ZW1zLycgKyBhcnJheUl0ZW0gK1xyXG4gICAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLml0ZW1zW2FycmF5SXRlbV0pO1xyXG4gICAgICAgICAgfSBlbHNlIGlmIChzY2hlbWEuYWRkaXRpb25hbEl0ZW1zKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAnL2FkZGl0aW9uYWxJdGVtcycgK1xyXG4gICAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLmFkZGl0aW9uYWxJdGVtcyk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChzY2hlbWEuaXRlbXMpKSB7XHJcbiAgICAgICAgICByZXR1cm4gJy9pdGVtcycgKyB0aGlzLnRvU2NoZW1hUG9pbnRlcihwb2ludGVyQXJyYXksIHNjaGVtYS5pdGVtcyk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChzY2hlbWEuYWRkaXRpb25hbEl0ZW1zKSkge1xyXG4gICAgICAgICAgcmV0dXJuICcvYWRkaXRpb25hbEl0ZW1zJyArXHJcbiAgICAgICAgICAgIHRoaXMudG9TY2hlbWFQb2ludGVyKHBvaW50ZXJBcnJheSwgc2NoZW1hLmFkZGl0aW9uYWxJdGVtcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoYHRvU2NoZW1hUG9pbnRlciBlcnJvcjogRGF0YSBwb2ludGVyICR7ZGF0YVBvaW50ZXJ9IGAgK1xyXG4gICAgICAgIGBub3QgY29tcGF0aWJsZSB3aXRoIHNjaGVtYSAke3NjaGVtYX1gKTtcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAoIXRoaXMuaXNKc29uUG9pbnRlcihkYXRhUG9pbnRlcikpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihgdG9TY2hlbWFQb2ludGVyIGVycm9yOiBJbnZhbGlkIEpTT04gUG9pbnRlcjogJHtkYXRhUG9pbnRlcn1gKTtcclxuICAgIH1cclxuICAgIGlmICh0eXBlb2Ygc2NoZW1hICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICBjb25zb2xlLmVycm9yKGB0b1NjaGVtYVBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBTY2hlbWE6ICR7c2NoZW1hfWApO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiAndG9EYXRhUG9pbnRlcicgZnVuY3Rpb25cclxuICAgKlxyXG4gICAqIEFjY2VwdHMgYSBKU09OIFBvaW50ZXIgdG8gYSBzdWItc2NoZW1hIGluc2lkZSBhIEpTT04gc2NoZW1hIGFuZCB0aGUgc2NoZW1hLlxyXG4gICAqXHJcbiAgICogSWYgcG9zc2libGUsIHJldHVybnMgYSBnZW5lcmljIFBvaW50ZXIgdG8gdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWUgaW5zaWRlXHJcbiAgICogdGhlIGRhdGEgb2JqZWN0IGRlc2NyaWJlZCBieSB0aGUgSlNPTiBzY2hlbWEuXHJcbiAgICpcclxuICAgKiBSZXR1cm5zIG51bGwgaWYgdGhlIHN1Yi1zY2hlbWEgaXMgaW4gYW4gYW1iaWd1b3VzIGxvY2F0aW9uIChzdWNoIGFzXHJcbiAgICogZGVmaW5pdGlvbnMgb3IgYWRkaXRpb25hbFByb3BlcnRpZXMpIHdoZXJlIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlXHJcbiAgICogbG9jYXRpb24gY2Fubm90IGJlIGRldGVybWluZWQuXHJcbiAgICpcclxuICAgKiAvLyAgeyBQb2ludGVyIH0gc2NoZW1hUG9pbnRlciAtIEpTT04gUG9pbnRlciAoc3RyaW5nIG9yIGFycmF5KSB0byBhIEpTT04gc2NoZW1hXHJcbiAgICogLy8gICBzY2hlbWEgLSB0aGUgSlNPTiBzY2hlbWFcclxuICAgKiAvLyAgeyBib29sZWFuID0gZmFsc2UgfSBlcnJvcnMgLSBTaG93IGVycm9ycz9cclxuICAgKiAvLyB7IFBvaW50ZXIgfSAtIEpTT04gUG9pbnRlciAoc3RyaW5nKSB0byB0aGUgdmFsdWUgaW4gdGhlIGRhdGEgb2JqZWN0XHJcbiAgICovXHJcbiAgc3RhdGljIHRvRGF0YVBvaW50ZXIoc2NoZW1hUG9pbnRlciwgc2NoZW1hLCBlcnJvcnMgPSBmYWxzZSkge1xyXG4gICAgaWYgKHRoaXMuaXNKc29uUG9pbnRlcihzY2hlbWFQb2ludGVyKSAmJiB0eXBlb2Ygc2NoZW1hID09PSAnb2JqZWN0JyAmJlxyXG4gICAgICB0aGlzLmhhcyhzY2hlbWEsIHNjaGVtYVBvaW50ZXIpXHJcbiAgICApIHtcclxuICAgICAgY29uc3QgcG9pbnRlckFycmF5ID0gdGhpcy5wYXJzZShzY2hlbWFQb2ludGVyKTtcclxuICAgICAgaWYgKCFwb2ludGVyQXJyYXkubGVuZ3RoKSB7IHJldHVybiAnJzsgfVxyXG4gICAgICBjb25zdCBmaXJzdEtleSA9IHBvaW50ZXJBcnJheS5zaGlmdCgpO1xyXG4gICAgICBpZiAoZmlyc3RLZXkgPT09ICdwcm9wZXJ0aWVzJyB8fFxyXG4gICAgICAgIChmaXJzdEtleSA9PT0gJ2l0ZW1zJyAmJiBpc0FycmF5KHNjaGVtYS5pdGVtcykpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGNvbnN0IHNlY29uZEtleSA9IHBvaW50ZXJBcnJheS5zaGlmdCgpO1xyXG4gICAgICAgIGNvbnN0IHBvaW50ZXJTdWZmaXggPSB0aGlzLnRvRGF0YVBvaW50ZXIocG9pbnRlckFycmF5LCBzY2hlbWFbZmlyc3RLZXldW3NlY29uZEtleV0pO1xyXG4gICAgICAgIHJldHVybiBwb2ludGVyU3VmZml4ID09PSBudWxsID8gbnVsbCA6ICcvJyArIHNlY29uZEtleSArIHBvaW50ZXJTdWZmaXg7XHJcbiAgICAgIH0gZWxzZSBpZiAoZmlyc3RLZXkgPT09ICdhZGRpdGlvbmFsSXRlbXMnIHx8XHJcbiAgICAgICAgKGZpcnN0S2V5ID09PSAnaXRlbXMnICYmIGlzT2JqZWN0KHNjaGVtYS5pdGVtcykpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGNvbnN0IHBvaW50ZXJTdWZmaXggPSB0aGlzLnRvRGF0YVBvaW50ZXIocG9pbnRlckFycmF5LCBzY2hlbWFbZmlyc3RLZXldKTtcclxuICAgICAgICByZXR1cm4gcG9pbnRlclN1ZmZpeCA9PT0gbnVsbCA/IG51bGwgOiAnLy0nICsgcG9pbnRlclN1ZmZpeDtcclxuICAgICAgfSBlbHNlIGlmIChbJ2FsbE9mJywgJ2FueU9mJywgJ29uZU9mJ10uaW5jbHVkZXMoZmlyc3RLZXkpKSB7XHJcbiAgICAgICAgY29uc3Qgc2Vjb25kS2V5ID0gcG9pbnRlckFycmF5LnNoaWZ0KCk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudG9EYXRhUG9pbnRlcihwb2ludGVyQXJyYXksIHNjaGVtYVtmaXJzdEtleV1bc2Vjb25kS2V5XSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoZmlyc3RLZXkgPT09ICdub3QnKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudG9EYXRhUG9pbnRlcihwb2ludGVyQXJyYXksIHNjaGVtYVtmaXJzdEtleV0pO1xyXG4gICAgICB9IGVsc2UgaWYgKFsnY29udGFpbnMnLCAnZGVmaW5pdGlvbnMnLCAnZGVwZW5kZW5jaWVzJywgJ2FkZGl0aW9uYWxJdGVtcycsXHJcbiAgICAgICAgJ2FkZGl0aW9uYWxQcm9wZXJ0aWVzJywgJ3BhdHRlcm5Qcm9wZXJ0aWVzJywgJ3Byb3BlcnR5TmFtZXMnXS5pbmNsdWRlcyhmaXJzdEtleSlcclxuICAgICAgKSB7XHJcbiAgICAgICAgaWYgKGVycm9ycykgeyBjb25zb2xlLmVycm9yKGB0b0RhdGFQb2ludGVyIGVycm9yOiBBbWJpZ3VvdXMgbG9jYXRpb25gKTsgfVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH1cclxuICAgIGlmIChlcnJvcnMpIHtcclxuICAgICAgaWYgKCF0aGlzLmlzSnNvblBvaW50ZXIoc2NoZW1hUG9pbnRlcikpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKGB0b0RhdGFQb2ludGVyIGVycm9yOiBJbnZhbGlkIEpTT04gUG9pbnRlcjogJHtzY2hlbWFQb2ludGVyfWApO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHRvRGF0YVBvaW50ZXIgZXJyb3I6IEludmFsaWQgSlNPTiBTY2hlbWE6ICR7c2NoZW1hfWApO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0eXBlb2Ygc2NoZW1hICE9PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYHRvRGF0YVBvaW50ZXIgZXJyb3I6IFBvaW50ZXIgJHtzY2hlbWFQb2ludGVyfSBpbnZhbGlkIGZvciBTY2hlbWE6ICR7c2NoZW1hfWApO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICdwYXJzZU9iamVjdFBhdGgnIGZ1bmN0aW9uXHJcbiAgICpcclxuICAgKiBQYXJzZXMgYSBKYXZhU2NyaXB0IG9iamVjdCBwYXRoIGludG8gYW4gYXJyYXkgb2Yga2V5cywgd2hpY2hcclxuICAgKiBjYW4gdGhlbiBiZSBwYXNzZWQgdG8gY29tcGlsZSgpIHRvIGNvbnZlcnQgaW50byBhIHN0cmluZyBKU09OIFBvaW50ZXIuXHJcbiAgICpcclxuICAgKiBCYXNlZCBvbiBtaWtlLW1hcmNhY2NpJ3MgZXhjZWxsZW50IG9iamVjdHBhdGggcGFyc2UgZnVuY3Rpb246XHJcbiAgICogaHR0cHM6Ly9naXRodWIuY29tL21pa2UtbWFyY2FjY2kvb2JqZWN0cGF0aFxyXG4gICAqXHJcbiAgICogLy8gIHsgUG9pbnRlciB9IHBhdGggLSBUaGUgb2JqZWN0IHBhdGggdG8gcGFyc2VcclxuICAgKiAvLyB7IHN0cmluZ1tdIH0gLSBUaGUgcmVzdWx0aW5nIGFycmF5IG9mIGtleXNcclxuICAgKi9cclxuICBzdGF0aWMgcGFyc2VPYmplY3RQYXRoKHBhdGgpIHtcclxuICAgIGlmIChpc0FycmF5KHBhdGgpKSB7IHJldHVybiA8c3RyaW5nW10+cGF0aDsgfVxyXG4gICAgaWYgKHRoaXMuaXNKc29uUG9pbnRlcihwYXRoKSkgeyByZXR1cm4gdGhpcy5wYXJzZShwYXRoKTsgfVxyXG4gICAgaWYgKHR5cGVvZiBwYXRoID09PSAnc3RyaW5nJykge1xyXG4gICAgICBsZXQgaW5kZXggPSAwO1xyXG4gICAgICBjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcclxuICAgICAgd2hpbGUgKGluZGV4IDwgcGF0aC5sZW5ndGgpIHtcclxuICAgICAgICBjb25zdCBuZXh0RG90ID0gcGF0aC5pbmRleE9mKCcuJywgaW5kZXgpO1xyXG4gICAgICAgIGNvbnN0IG5leHRPQiA9IHBhdGguaW5kZXhPZignWycsIGluZGV4KTsgLy8gbmV4dCBvcGVuIGJyYWNrZXRcclxuICAgICAgICBpZiAobmV4dERvdCA9PT0gLTEgJiYgbmV4dE9CID09PSAtMSkgeyAvLyBsYXN0IGl0ZW1cclxuICAgICAgICAgIHBhcnRzLnB1c2gocGF0aC5zbGljZShpbmRleCkpO1xyXG4gICAgICAgICAgaW5kZXggPSBwYXRoLmxlbmd0aDtcclxuICAgICAgICB9IGVsc2UgaWYgKG5leHREb3QgIT09IC0xICYmIChuZXh0RG90IDwgbmV4dE9CIHx8IG5leHRPQiA9PT0gLTEpKSB7IC8vIGRvdCBub3RhdGlvblxyXG4gICAgICAgICAgcGFydHMucHVzaChwYXRoLnNsaWNlKGluZGV4LCBuZXh0RG90KSk7XHJcbiAgICAgICAgICBpbmRleCA9IG5leHREb3QgKyAxO1xyXG4gICAgICAgIH0gZWxzZSB7IC8vIGJyYWNrZXQgbm90YXRpb25cclxuICAgICAgICAgIGlmIChuZXh0T0IgPiBpbmRleCkge1xyXG4gICAgICAgICAgICBwYXJ0cy5wdXNoKHBhdGguc2xpY2UoaW5kZXgsIG5leHRPQikpO1xyXG4gICAgICAgICAgICBpbmRleCA9IG5leHRPQjtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGNvbnN0IHF1b3RlID0gcGF0aC5jaGFyQXQobmV4dE9CICsgMSk7XHJcbiAgICAgICAgICBpZiAocXVvdGUgPT09ICdcIicgfHwgcXVvdGUgPT09ICdcXCcnKSB7IC8vIGVuY2xvc2luZyBxdW90ZXNcclxuICAgICAgICAgICAgbGV0IG5leHRDQiA9IHBhdGguaW5kZXhPZihxdW90ZSArICddJywgbmV4dE9CKTsgLy8gbmV4dCBjbG9zZSBicmFja2V0XHJcbiAgICAgICAgICAgIHdoaWxlIChuZXh0Q0IgIT09IC0xICYmIHBhdGguY2hhckF0KG5leHRDQiAtIDEpID09PSAnXFxcXCcpIHtcclxuICAgICAgICAgICAgICBuZXh0Q0IgPSBwYXRoLmluZGV4T2YocXVvdGUgKyAnXScsIG5leHRDQiArIDIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChuZXh0Q0IgPT09IC0xKSB7IG5leHRDQiA9IHBhdGgubGVuZ3RoOyB9XHJcbiAgICAgICAgICAgIHBhcnRzLnB1c2gocGF0aC5zbGljZShpbmRleCArIDIsIG5leHRDQilcclxuICAgICAgICAgICAgICAucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcJyArIHF1b3RlLCAnZycpLCBxdW90ZSkpO1xyXG4gICAgICAgICAgICBpbmRleCA9IG5leHRDQiArIDI7XHJcbiAgICAgICAgICB9IGVsc2UgeyAvLyBubyBlbmNsb3NpbmcgcXVvdGVzXHJcbiAgICAgICAgICAgIGxldCBuZXh0Q0IgPSBwYXRoLmluZGV4T2YoJ10nLCBuZXh0T0IpOyAvLyBuZXh0IGNsb3NlIGJyYWNrZXRcclxuICAgICAgICAgICAgaWYgKG5leHRDQiA9PT0gLTEpIHsgbmV4dENCID0gcGF0aC5sZW5ndGg7IH1cclxuICAgICAgICAgICAgcGFydHMucHVzaChwYXRoLnNsaWNlKGluZGV4ICsgMSwgbmV4dENCKSk7XHJcbiAgICAgICAgICAgIGluZGV4ID0gbmV4dENCICsgMTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChwYXRoLmNoYXJBdChpbmRleCkgPT09ICcuJykgeyBpbmRleCsrOyB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBwYXJ0cztcclxuICAgIH1cclxuICAgIGNvbnNvbGUuZXJyb3IoJ3BhcnNlT2JqZWN0UGF0aCBlcnJvcjogSW5wdXQgb2JqZWN0IHBhdGggbXVzdCBiZSBhIHN0cmluZy4nKTtcclxuICB9XHJcbn1cclxuIl19