@decaf-ts/db-decorators 0.6.1 → 0.6.3
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.
- package/LICENSE.md +21 -157
- package/README.md +571 -10
- package/dist/db-decorators.cjs +1599 -426
- package/dist/db-decorators.esm.cjs +1597 -428
- package/lib/esm/identity/decorators.d.ts +7 -0
- package/lib/esm/identity/decorators.js +11 -4
- package/lib/esm/identity/index.js +3 -3
- package/lib/esm/identity/utils.d.ts +36 -23
- package/lib/esm/identity/utils.js +38 -25
- package/lib/esm/index.d.ts +12 -27
- package/lib/esm/index.js +13 -28
- package/lib/esm/interfaces/BulkCrudOperator.d.ts +39 -0
- package/lib/esm/interfaces/BulkCrudOperator.js +1 -1
- package/lib/esm/interfaces/Contextual.d.ts +17 -0
- package/lib/esm/interfaces/Contextual.js +1 -1
- package/lib/esm/interfaces/CrudOperator.d.ts +26 -23
- package/lib/esm/interfaces/CrudOperator.js +1 -1
- package/lib/esm/interfaces/IRepository.d.ts +10 -2
- package/lib/esm/interfaces/IRepository.js +1 -1
- package/lib/esm/interfaces/index.js +5 -5
- package/lib/esm/model/constants.d.ts +11 -13
- package/lib/esm/model/constants.js +12 -14
- package/lib/esm/model/decorators.d.ts +112 -23
- package/lib/esm/model/decorators.js +119 -29
- package/lib/esm/model/index.d.ts +1 -0
- package/lib/esm/model/index.js +7 -6
- package/lib/esm/model/model.d.ts +2 -141
- package/lib/esm/model/model.js +2 -13
- package/lib/esm/model/overrides.d.ts +1 -0
- package/lib/esm/model/overrides.js +34 -0
- package/lib/esm/model/utils.d.ts +39 -0
- package/lib/esm/model/utils.js +42 -3
- package/lib/esm/model/validation.d.ts +51 -8
- package/lib/esm/model/validation.js +246 -107
- package/lib/esm/operations/Operations.d.ts +65 -3
- package/lib/esm/operations/Operations.js +68 -6
- package/lib/esm/operations/OperationsRegistry.d.ts +44 -16
- package/lib/esm/operations/OperationsRegistry.js +46 -18
- package/lib/esm/operations/constants.d.ts +27 -8
- package/lib/esm/operations/constants.js +16 -9
- package/lib/esm/operations/decorators.d.ts +140 -134
- package/lib/esm/operations/decorators.js +152 -137
- package/lib/esm/operations/index.js +6 -6
- package/lib/esm/operations/types.d.ts +10 -0
- package/lib/esm/operations/types.js +1 -1
- package/lib/esm/repository/BaseRepository.d.ts +322 -0
- package/lib/esm/repository/BaseRepository.js +297 -7
- package/lib/esm/repository/Context.d.ts +153 -2
- package/lib/esm/repository/Context.js +154 -6
- package/lib/esm/repository/Repository.d.ts +89 -0
- package/lib/esm/repository/Repository.js +102 -15
- package/lib/esm/repository/constants.d.ts +7 -0
- package/lib/esm/repository/constants.js +8 -1
- package/lib/esm/repository/errors.d.ts +61 -34
- package/lib/esm/repository/errors.js +62 -35
- package/lib/esm/repository/index.js +9 -9
- package/lib/esm/repository/types.d.ts +25 -0
- package/lib/esm/repository/types.js +1 -1
- package/lib/esm/repository/utils.d.ts +11 -0
- package/lib/esm/repository/utils.js +4 -4
- package/lib/esm/repository/wrappers.d.ts +2 -2
- package/lib/esm/repository/wrappers.js +5 -5
- package/lib/esm/validation/constants.d.ts +20 -5
- package/lib/esm/validation/constants.js +22 -7
- package/lib/esm/validation/decorators.d.ts +101 -19
- package/lib/esm/validation/decorators.js +109 -27
- package/lib/esm/validation/index.js +5 -5
- package/lib/esm/validation/validation.js +10 -2
- package/lib/esm/validation/validators/ReadOnlyValidator.d.ts +32 -8
- package/lib/esm/validation/validators/ReadOnlyValidator.js +34 -10
- package/lib/esm/validation/validators/TimestampValidator.d.ts +37 -3
- package/lib/esm/validation/validators/TimestampValidator.js +39 -5
- package/lib/esm/validation/validators/UpdateValidator.d.ts +28 -11
- package/lib/esm/validation/validators/UpdateValidator.js +23 -8
- package/lib/esm/validation/validators/index.js +4 -4
- package/lib/identity/decorators.cjs +8 -1
- package/lib/identity/decorators.d.ts +7 -0
- package/lib/identity/utils.cjs +35 -22
- package/lib/identity/utils.d.ts +36 -23
- package/lib/index.cjs +14 -28
- package/lib/index.d.ts +12 -27
- package/lib/interfaces/BulkCrudOperator.cjs +1 -1
- package/lib/interfaces/BulkCrudOperator.d.ts +39 -0
- package/lib/interfaces/Contextual.cjs +1 -1
- package/lib/interfaces/Contextual.d.ts +17 -0
- package/lib/interfaces/CrudOperator.cjs +1 -1
- package/lib/interfaces/CrudOperator.d.ts +26 -23
- package/lib/interfaces/IRepository.cjs +1 -1
- package/lib/interfaces/IRepository.d.ts +10 -2
- package/lib/model/constants.cjs +12 -14
- package/lib/model/constants.d.ts +11 -13
- package/lib/model/decorators.cjs +114 -24
- package/lib/model/decorators.d.ts +112 -23
- package/lib/model/index.cjs +2 -1
- package/lib/model/index.d.ts +1 -0
- package/lib/model/model.cjs +1 -13
- package/lib/model/model.d.ts +2 -141
- package/lib/model/overrides.cjs +36 -0
- package/lib/model/overrides.d.ts +1 -0
- package/lib/model/utils.cjs +40 -1
- package/lib/model/utils.d.ts +39 -0
- package/lib/model/validation.cjs +246 -104
- package/lib/model/validation.d.ts +51 -8
- package/lib/operations/Operations.cjs +66 -4
- package/lib/operations/Operations.d.ts +65 -3
- package/lib/operations/OperationsRegistry.cjs +45 -17
- package/lib/operations/OperationsRegistry.d.ts +44 -16
- package/lib/operations/constants.cjs +16 -9
- package/lib/operations/constants.d.ts +27 -8
- package/lib/operations/decorators.cjs +150 -135
- package/lib/operations/decorators.d.ts +140 -134
- package/lib/operations/types.cjs +1 -1
- package/lib/operations/types.d.ts +10 -0
- package/lib/repository/BaseRepository.cjs +291 -1
- package/lib/repository/BaseRepository.d.ts +322 -0
- package/lib/repository/Context.cjs +153 -5
- package/lib/repository/Context.d.ts +153 -2
- package/lib/repository/Repository.cjs +96 -9
- package/lib/repository/Repository.d.ts +89 -0
- package/lib/repository/constants.cjs +8 -1
- package/lib/repository/constants.d.ts +7 -0
- package/lib/repository/errors.cjs +62 -35
- package/lib/repository/errors.d.ts +61 -34
- package/lib/repository/types.cjs +1 -1
- package/lib/repository/types.d.ts +25 -0
- package/lib/repository/utils.cjs +1 -1
- package/lib/repository/utils.d.ts +11 -0
- package/lib/repository/wrappers.cjs +3 -3
- package/lib/repository/wrappers.d.ts +2 -2
- package/lib/validation/constants.cjs +21 -6
- package/lib/validation/constants.d.ts +20 -5
- package/lib/validation/decorators.cjs +102 -20
- package/lib/validation/decorators.d.ts +101 -19
- package/lib/validation/validation.cjs +9 -1
- package/lib/validation/validators/ReadOnlyValidator.cjs +33 -9
- package/lib/validation/validators/ReadOnlyValidator.d.ts +32 -8
- package/lib/validation/validators/TimestampValidator.cjs +38 -4
- package/lib/validation/validators/TimestampValidator.d.ts +37 -3
- package/lib/validation/validators/UpdateValidator.cjs +23 -8
- package/lib/validation/validators/UpdateValidator.d.ts +28 -11
- package/package.json +2 -2
package/dist/db-decorators.cjs
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
})(this, (function (exports, decoratorValidation, tslib, reflection, typedObjectAccumulator) { 'use strict';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* @
|
|
8
|
+
* @description Database reflection keys
|
|
9
|
+
* @summary Collection of keys used for reflection metadata in database operations
|
|
9
10
|
* @const DBKeys
|
|
10
|
-
*
|
|
11
|
-
* @memberOf module:db-decorators.Model
|
|
11
|
+
* @memberOf module:db-decorators
|
|
12
12
|
*/
|
|
13
13
|
const DBKeys = {
|
|
14
14
|
REFLECT: `${decoratorValidation.ModelKeys.REFLECT}persistence.`,
|
|
@@ -27,27 +27,35 @@
|
|
|
27
27
|
ORIGINAL: "__originalObj",
|
|
28
28
|
};
|
|
29
29
|
/**
|
|
30
|
-
* @
|
|
31
|
-
*
|
|
32
|
-
* @const
|
|
33
|
-
*
|
|
34
|
-
* @category Managers
|
|
35
|
-
* @subcategory Constants
|
|
30
|
+
* @description Default separator character for composite indexes
|
|
31
|
+
* @summary The default separator character used when concatenating multiple fields into a single index
|
|
32
|
+
* @const DefaultSeparator
|
|
33
|
+
* @memberOf module:db-decorators
|
|
36
34
|
*/
|
|
37
35
|
const DefaultSeparator = "_";
|
|
38
36
|
/**
|
|
39
|
-
* @
|
|
40
|
-
* @
|
|
41
|
-
*
|
|
42
|
-
* @memberOf module:db-decorators
|
|
37
|
+
* @description Default format for timestamp fields
|
|
38
|
+
* @summary Standard date format string used for timestamp fields in database models
|
|
39
|
+
* @const DEFAULT_TIMESTAMP_FORMAT
|
|
40
|
+
* @memberOf module:db-decorators
|
|
43
41
|
*/
|
|
44
42
|
const DEFAULT_TIMESTAMP_FORMAT = "dd/MM/yyyy HH:mm:ss:S";
|
|
45
43
|
|
|
46
44
|
/**
|
|
47
|
-
* @
|
|
45
|
+
* @description Collection of default error messages used by validators.
|
|
46
|
+
* @summary Holds the default error messages for various validation scenarios including ID validation, readonly properties, and timestamps.
|
|
47
|
+
* @typedef {Object} ErrorMessages
|
|
48
|
+
* @property {Object} ID - Error messages for ID validation
|
|
49
|
+
* @property {string} ID.INVALID - Error message when an ID is invalid
|
|
50
|
+
* @property {string} ID.REQUIRED - Error message when an ID is missing
|
|
51
|
+
* @property {Object} READONLY - Error messages for readonly properties
|
|
52
|
+
* @property {string} READONLY.INVALID - Error message when attempting to update a readonly property
|
|
53
|
+
* @property {Object} TIMESTAMP - Error messages for timestamp validation
|
|
54
|
+
* @property {string} TIMESTAMP.REQUIRED - Error message when a timestamp is missing
|
|
55
|
+
* @property {string} TIMESTAMP.DATE - Error message when a timestamp is not a valid date
|
|
56
|
+
* @property {string} TIMESTAMP.INVALID - Error message when a timestamp is not increasing
|
|
48
57
|
* @const DEFAULT_ERROR_MESSAGES
|
|
49
|
-
*
|
|
50
|
-
* @memberOf module:db-decorators.Model
|
|
58
|
+
* @memberOf module:validation
|
|
51
59
|
*/
|
|
52
60
|
const DEFAULT_ERROR_MESSAGES = {
|
|
53
61
|
ID: {
|
|
@@ -64,9 +72,14 @@
|
|
|
64
72
|
},
|
|
65
73
|
};
|
|
66
74
|
/**
|
|
67
|
-
* @
|
|
75
|
+
* @description Constants used for reflection-based validation during update operations.
|
|
76
|
+
* @summary Keys used for storing and retrieving validation metadata on model properties during update operations.
|
|
77
|
+
* @typedef {Object} ValidationKeys
|
|
78
|
+
* @property {string} REFLECT - Base reflection key prefix for update validation
|
|
79
|
+
* @property {string} TIMESTAMP - Key for timestamp validation
|
|
80
|
+
* @property {string} READONLY - Key for readonly property validation
|
|
68
81
|
* @const UpdateValidationKeys
|
|
69
|
-
* @memberOf module:
|
|
82
|
+
* @memberOf module:validation
|
|
70
83
|
*/
|
|
71
84
|
const UpdateValidationKeys = {
|
|
72
85
|
REFLECT: "db.update.validation.",
|
|
@@ -75,11 +88,29 @@
|
|
|
75
88
|
};
|
|
76
89
|
|
|
77
90
|
/**
|
|
78
|
-
* @
|
|
79
|
-
*
|
|
91
|
+
* @description A validator that ensures properties marked as readonly cannot be modified during updates.
|
|
92
|
+
* @summary Validator for the {@link readonly} decorator that checks if a value has been changed during an update operation. It compares the new value with the old value and returns an error message if they are not equal.
|
|
93
|
+
* @param {any} value - The value to be validated
|
|
94
|
+
* @param {any} oldValue - The previous value to compare against
|
|
95
|
+
* @param {string} [message] - Optional custom error message
|
|
80
96
|
* @class ReadOnlyValidator
|
|
81
|
-
* @
|
|
82
|
-
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Using ReadOnlyValidator with a readonly property
|
|
99
|
+
* class User {
|
|
100
|
+
* @readonly()
|
|
101
|
+
* id: string;
|
|
102
|
+
*
|
|
103
|
+
* name: string;
|
|
104
|
+
*
|
|
105
|
+
* constructor(id: string, name: string) {
|
|
106
|
+
* this.id = id;
|
|
107
|
+
* this.name = name;
|
|
108
|
+
* }
|
|
109
|
+
* }
|
|
110
|
+
*
|
|
111
|
+
* // This will trigger validation error when trying to update
|
|
112
|
+
* const user = new User('123', 'John');
|
|
113
|
+
* user.id = '456'; // Will be prevented by ReadOnlyValidator
|
|
83
114
|
* @category Validators
|
|
84
115
|
*/
|
|
85
116
|
exports.ReadOnlyValidator = class ReadOnlyValidator extends decoratorValidation.Validator {
|
|
@@ -87,17 +118,23 @@
|
|
|
87
118
|
super(DEFAULT_ERROR_MESSAGES.READONLY.INVALID);
|
|
88
119
|
}
|
|
89
120
|
/**
|
|
90
|
-
* @
|
|
121
|
+
* @description Implementation of the base validator's hasErrors method.
|
|
122
|
+
* @summary This method is required by the Validator interface but not used in this validator as validation only happens during updates.
|
|
123
|
+
* @param {any} value - The value to validate
|
|
124
|
+
* @param {any[]} args - Additional arguments
|
|
125
|
+
* @return {string | undefined} Always returns undefined as this validator only works during updates
|
|
91
126
|
*/
|
|
92
127
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
93
128
|
hasErrors(value, ...args) {
|
|
94
129
|
return undefined;
|
|
95
130
|
}
|
|
96
131
|
/**
|
|
97
|
-
* @
|
|
98
|
-
* @
|
|
99
|
-
* @param {any}
|
|
100
|
-
* @param {
|
|
132
|
+
* @description Checks if a value has been modified during an update operation.
|
|
133
|
+
* @summary Validates a value has not changed by comparing it with the previous value using deep equality.
|
|
134
|
+
* @param {any} value - The new value to validate
|
|
135
|
+
* @param {any} oldValue - The original value to compare against
|
|
136
|
+
* @param {string} [message] - Optional custom error message to override the default
|
|
137
|
+
* @return {string | undefined} An error message if validation fails, undefined otherwise
|
|
101
138
|
*/
|
|
102
139
|
updateHasErrors(value, oldValue, message) {
|
|
103
140
|
if (value === undefined)
|
|
@@ -113,21 +150,55 @@
|
|
|
113
150
|
], exports.ReadOnlyValidator);
|
|
114
151
|
|
|
115
152
|
/**
|
|
116
|
-
* @
|
|
117
|
-
*
|
|
153
|
+
* @description A validator that ensures timestamp values are only updated with newer timestamps.
|
|
154
|
+
* @summary Validates the update of a timestamp by comparing the new timestamp with the old one, ensuring the new timestamp is more recent.
|
|
155
|
+
* @param {Date|string|number} value - The timestamp value to validate
|
|
156
|
+
* @param {Date|string|number} oldValue - The previous timestamp to compare against
|
|
157
|
+
* @param {string} [message] - Optional custom error message
|
|
118
158
|
* @class TimestampValidator
|
|
119
|
-
* @
|
|
120
|
-
*
|
|
159
|
+
* @example
|
|
160
|
+
* // Using TimestampValidator with a timestamp property
|
|
161
|
+
* class Document {
|
|
162
|
+
* @timestamp()
|
|
163
|
+
* updatedAt: Date;
|
|
164
|
+
*
|
|
165
|
+
* title: string;
|
|
166
|
+
*
|
|
167
|
+
* constructor(title: string) {
|
|
168
|
+
* this.title = title;
|
|
169
|
+
* this.updatedAt = new Date();
|
|
170
|
+
* }
|
|
171
|
+
* }
|
|
172
|
+
*
|
|
173
|
+
* // This will trigger validation error when trying to update with an older timestamp
|
|
174
|
+
* const doc = new Document('My Document');
|
|
175
|
+
* const oldDate = new Date(2020, 0, 1);
|
|
176
|
+
* doc.updatedAt = oldDate; // Will be prevented by TimestampValidator
|
|
121
177
|
* @category Validators
|
|
122
178
|
*/
|
|
123
179
|
exports.TimestampValidator = class TimestampValidator extends decoratorValidation.Validator {
|
|
124
180
|
constructor() {
|
|
125
181
|
super(DEFAULT_ERROR_MESSAGES.TIMESTAMP.INVALID);
|
|
126
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* @description Implementation of the base validator's hasErrors method.
|
|
185
|
+
* @summary This method is required by the Validator interface but not used in this validator as validation only happens during updates.
|
|
186
|
+
* @param {any} value - The timestamp value to validate
|
|
187
|
+
* @param {any[]} args - Additional arguments
|
|
188
|
+
* @return {string | undefined} Always returns undefined as this validator only works during updates
|
|
189
|
+
*/
|
|
127
190
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
128
191
|
hasErrors(value, ...args) {
|
|
129
192
|
return undefined;
|
|
130
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* @description Validates that a timestamp is newer than its previous value.
|
|
196
|
+
* @summary Checks if a timestamp has been updated with a more recent value by converting both values to Date objects and comparing them.
|
|
197
|
+
* @param {Date|string|number} value - The new timestamp value to validate
|
|
198
|
+
* @param {Date|string|number} oldValue - The original timestamp to compare against
|
|
199
|
+
* @param {string} [message] - Optional custom error message to override the default
|
|
200
|
+
* @return {string | undefined} An error message if validation fails (new timestamp is not newer), undefined otherwise
|
|
201
|
+
*/
|
|
131
202
|
updateHasErrors(value, oldValue, message) {
|
|
132
203
|
if (value === undefined)
|
|
133
204
|
return;
|
|
@@ -149,15 +220,30 @@
|
|
|
149
220
|
], exports.TimestampValidator);
|
|
150
221
|
|
|
151
222
|
/**
|
|
152
|
-
* @
|
|
153
|
-
*
|
|
154
|
-
* @param {string} [message]
|
|
155
|
-
* @param {string[]} [acceptedTypes]
|
|
156
|
-
*
|
|
223
|
+
* @description Abstract base class for validators that compare new values with old values during updates.
|
|
224
|
+
* @summary Base class for an Update validator that provides a framework for implementing validation logic that compares a new value with its previous state.
|
|
225
|
+
* @param {string} [message] - Error message. Defaults to {@link DecoratorMessages#DEFAULT}
|
|
226
|
+
* @param {string[]} [acceptedTypes] - The accepted value types by the decorator
|
|
157
227
|
* @class UpdateValidator
|
|
158
|
-
* @
|
|
159
|
-
*
|
|
160
|
-
*
|
|
228
|
+
* @example
|
|
229
|
+
* // Extending UpdateValidator to create a custom validator
|
|
230
|
+
* class MyCustomValidator extends UpdateValidator {
|
|
231
|
+
* constructor() {
|
|
232
|
+
* super("Custom validation failed");
|
|
233
|
+
* }
|
|
234
|
+
*
|
|
235
|
+
* public updateHasErrors(value: any, oldValue: any): string | undefined {
|
|
236
|
+
* // Custom validation logic
|
|
237
|
+
* if (value === oldValue) {
|
|
238
|
+
* return this.message;
|
|
239
|
+
* }
|
|
240
|
+
* return undefined;
|
|
241
|
+
* }
|
|
242
|
+
*
|
|
243
|
+
* hasErrors(value: any): string | undefined {
|
|
244
|
+
* return undefined; // Not used for update validators
|
|
245
|
+
* }
|
|
246
|
+
* }
|
|
161
247
|
* @category Validators
|
|
162
248
|
*/
|
|
163
249
|
class UpdateValidator extends decoratorValidation.Validator {
|
|
@@ -166,15 +252,24 @@
|
|
|
166
252
|
}
|
|
167
253
|
}
|
|
168
254
|
|
|
255
|
+
/**
|
|
256
|
+
* @description Generates a key for update validation metadata.
|
|
257
|
+
* @summary Builds the key to store as metadata under Reflections for update validation by prefixing the provided key with the update validation prefix.
|
|
258
|
+
* @param {string} key - The base key to be prefixed
|
|
259
|
+
* @return {string} The complete metadata key for update validation
|
|
260
|
+
* @function updateKey
|
|
261
|
+
* @memberOf module:db-decorators
|
|
262
|
+
*/
|
|
169
263
|
decoratorValidation.Validation.updateKey = function (key) {
|
|
170
264
|
return UpdateValidationKeys.REFLECT + key;
|
|
171
265
|
};
|
|
172
266
|
|
|
173
267
|
/**
|
|
174
|
-
* @
|
|
175
|
-
* @
|
|
176
|
-
*
|
|
177
|
-
* @
|
|
268
|
+
* @description Database operation key constants
|
|
269
|
+
* @summary Enum defining CRUD operations and their lifecycle phases
|
|
270
|
+
* @enum {string}
|
|
271
|
+
* @readonly
|
|
272
|
+
* @memberOf module:db-decorators
|
|
178
273
|
*/
|
|
179
274
|
exports.OperationKeys = void 0;
|
|
180
275
|
(function (OperationKeys) {
|
|
@@ -186,6 +281,13 @@
|
|
|
186
281
|
OperationKeys["ON"] = "on.";
|
|
187
282
|
OperationKeys["AFTER"] = "after.";
|
|
188
283
|
})(exports.OperationKeys || (exports.OperationKeys = {}));
|
|
284
|
+
/**
|
|
285
|
+
* @description Bulk database operation key constants
|
|
286
|
+
* @summary Enum defining bulk CRUD operations for handling multiple records at once
|
|
287
|
+
* @enum {string}
|
|
288
|
+
* @readonly
|
|
289
|
+
* @memberOf module:db-decorators
|
|
290
|
+
*/
|
|
189
291
|
exports.BulkCrudOperationKeys = void 0;
|
|
190
292
|
(function (BulkCrudOperationKeys) {
|
|
191
293
|
BulkCrudOperationKeys["CREATE_ALL"] = "createAll";
|
|
@@ -194,11 +296,10 @@
|
|
|
194
296
|
BulkCrudOperationKeys["DELETE_ALL"] = "deleteAll";
|
|
195
297
|
})(exports.BulkCrudOperationKeys || (exports.BulkCrudOperationKeys = {}));
|
|
196
298
|
/**
|
|
299
|
+
* @description Grouped CRUD operations for decorator mapping
|
|
197
300
|
* @summary Maps out groups of CRUD operations for easier mapping of decorators
|
|
198
|
-
*
|
|
199
|
-
* @
|
|
200
|
-
*
|
|
201
|
-
* @memberOf module:db-decorators.Operations
|
|
301
|
+
* @const DBOperations
|
|
302
|
+
* @memberOf module:db-decorators
|
|
202
303
|
*/
|
|
203
304
|
const DBOperations = {
|
|
204
305
|
CREATE: [exports.OperationKeys.CREATE],
|
|
@@ -216,26 +317,47 @@
|
|
|
216
317
|
};
|
|
217
318
|
|
|
218
319
|
/**
|
|
219
|
-
* @
|
|
220
|
-
*
|
|
320
|
+
* @description Registry for database operation handlers
|
|
321
|
+
* @summary Manages and stores operation handlers for different model properties and operations
|
|
221
322
|
* @class OperationsRegistry
|
|
222
|
-
* @
|
|
223
|
-
*
|
|
224
|
-
* @
|
|
225
|
-
*
|
|
226
|
-
* @
|
|
323
|
+
* @template M - Model type
|
|
324
|
+
* @template R - Repository type
|
|
325
|
+
* @template V - Metadata type
|
|
326
|
+
* @template F - Repository flags
|
|
327
|
+
* @template C - Context type
|
|
328
|
+
* @example
|
|
329
|
+
* // Create a registry and register a handler
|
|
330
|
+
* const registry = new OperationsRegistry();
|
|
331
|
+
* registry.register(myHandler, OperationKeys.CREATE, targetModel, 'propertyName');
|
|
332
|
+
*
|
|
333
|
+
* // Get handlers for a specific operation
|
|
334
|
+
* const handlers = registry.get(targetModel.constructor.name, 'propertyName', 'onCreate');
|
|
335
|
+
*
|
|
336
|
+
* @mermaid
|
|
337
|
+
* classDiagram
|
|
338
|
+
* class OperationsRegistry {
|
|
339
|
+
* -cache: Record~string, Record~string|symbol, Record~string, Record~string, OperationHandler~~~~
|
|
340
|
+
* +get(target, propKey, operation, accum)
|
|
341
|
+
* +register(handler, operation, target, propKey)
|
|
342
|
+
* }
|
|
227
343
|
*/
|
|
228
344
|
class OperationsRegistry {
|
|
229
345
|
constructor() {
|
|
230
346
|
this.cache = {};
|
|
231
347
|
}
|
|
232
348
|
/**
|
|
233
|
-
* @
|
|
234
|
-
* @
|
|
235
|
-
* @
|
|
236
|
-
* @
|
|
237
|
-
* @
|
|
238
|
-
* @
|
|
349
|
+
* @description Retrieves operation handlers for a specific target and operation
|
|
350
|
+
* @summary Finds all registered handlers for a given target, property, and operation, including from parent classes
|
|
351
|
+
* @template M - Model type extending Model
|
|
352
|
+
* @template R - Repository type extending IRepository
|
|
353
|
+
* @template V - Metadata type
|
|
354
|
+
* @template F - Repository flags extending RepositoryFlags
|
|
355
|
+
* @template C - Context type extending Context<F>
|
|
356
|
+
* @param {string | Record<string, any>} target - The target class name or object
|
|
357
|
+
* @param {string} propKey - The property key to get handlers for
|
|
358
|
+
* @param {string} operation - The operation key to get handlers for
|
|
359
|
+
* @param {OperationHandler[]} [accum] - Accumulator for recursive calls
|
|
360
|
+
* @return {OperationHandler[] | undefined} Array of handlers or undefined if none found
|
|
239
361
|
*/
|
|
240
362
|
get(target, propKey, operation, accum) {
|
|
241
363
|
accum = accum || [];
|
|
@@ -257,11 +379,18 @@
|
|
|
257
379
|
return this.get(proto, propKey, operation, accum);
|
|
258
380
|
}
|
|
259
381
|
/**
|
|
260
|
-
* @
|
|
261
|
-
* @
|
|
262
|
-
* @
|
|
263
|
-
* @
|
|
264
|
-
* @
|
|
382
|
+
* @description Registers an operation handler for a specific target and operation
|
|
383
|
+
* @summary Stores a handler in the registry for a given target, property, and operation
|
|
384
|
+
* @template M - Model type extending Model
|
|
385
|
+
* @template R - Repository type extending IRepository
|
|
386
|
+
* @template V - Metadata type
|
|
387
|
+
* @template F - Repository flags extending RepositoryFlags
|
|
388
|
+
* @template C - Context type extending Context<F>
|
|
389
|
+
* @param {OperationHandler} handler - The handler function to register
|
|
390
|
+
* @param {OperationKeys} operation - The operation key to register the handler for
|
|
391
|
+
* @param {M} target - The target model instance
|
|
392
|
+
* @param {string | symbol} propKey - The property key to register the handler for
|
|
393
|
+
* @return {void}
|
|
265
394
|
*/
|
|
266
395
|
register(handler, operation, target, propKey) {
|
|
267
396
|
const name = target.constructor.name;
|
|
@@ -279,259 +408,336 @@
|
|
|
279
408
|
}
|
|
280
409
|
|
|
281
410
|
/**
|
|
282
|
-
* @
|
|
283
|
-
*
|
|
411
|
+
* @description Static utility class for database operation management
|
|
412
|
+
* @summary Provides functionality for registering, retrieving, and managing database operation handlers
|
|
284
413
|
* @class Operations
|
|
285
|
-
*
|
|
286
|
-
* @
|
|
414
|
+
* @template M - Model type
|
|
415
|
+
* @template R - Repository type
|
|
416
|
+
* @template V - Metadata type
|
|
417
|
+
* @template F - Repository flags
|
|
418
|
+
* @template C - Context type
|
|
419
|
+
* @example
|
|
420
|
+
* // Register a handler for a create operation
|
|
421
|
+
* Operations.register(myHandler, OperationKeys.CREATE, targetModel, 'propertyName');
|
|
422
|
+
*
|
|
423
|
+
* // Get handlers for a specific operation
|
|
424
|
+
* const handlers = Operations.get(targetModel.constructor.name, 'propertyName', 'onCreate');
|
|
425
|
+
*
|
|
426
|
+
* @mermaid
|
|
427
|
+
* classDiagram
|
|
428
|
+
* class Operations {
|
|
429
|
+
* -registry: OperationsRegistry
|
|
430
|
+
* +getHandlerName(handler)
|
|
431
|
+
* +key(str)
|
|
432
|
+
* +get(targetName, propKey, operation)
|
|
433
|
+
* -getOpRegistry()
|
|
434
|
+
* +register(handler, operation, target, propKey)
|
|
435
|
+
* }
|
|
436
|
+
* Operations --> OperationsRegistry : uses
|
|
287
437
|
*/
|
|
288
438
|
class Operations {
|
|
289
439
|
constructor() { }
|
|
440
|
+
/**
|
|
441
|
+
* @description Gets a unique name for an operation handler
|
|
442
|
+
* @summary Returns the name of the handler function or generates a hash if name is not available
|
|
443
|
+
* @param {OperationHandler<any, any, any, any, any>} handler - The handler function to get the name for
|
|
444
|
+
* @return {string} The name of the handler or a generated hash
|
|
445
|
+
*/
|
|
290
446
|
static getHandlerName(handler) {
|
|
291
447
|
if (handler.name)
|
|
292
448
|
return handler.name;
|
|
293
449
|
console.warn("Handler name not defined. A name will be generated, but this is not desirable. please avoid using anonymous functions");
|
|
294
450
|
return decoratorValidation.Hashing.hash(handler.toString());
|
|
295
451
|
}
|
|
452
|
+
/**
|
|
453
|
+
* @description Generates a reflection metadata key
|
|
454
|
+
* @summary Creates a fully qualified metadata key by prefixing with the reflection namespace
|
|
455
|
+
* @param {string} str - The operation key string to prefix
|
|
456
|
+
* @return {string} The fully qualified metadata key
|
|
457
|
+
*/
|
|
296
458
|
static key(str) {
|
|
297
459
|
return exports.OperationKeys.REFLECT + str;
|
|
298
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* @description Retrieves operation handlers for a specific target and operation
|
|
463
|
+
* @summary Gets registered handlers from the operations registry for a given target, property, and operation
|
|
464
|
+
* @template M - Model type extending Model
|
|
465
|
+
* @template R - Repository type extending IRepository
|
|
466
|
+
* @template V - Metadata type, defaults to object
|
|
467
|
+
* @template F - Repository flags extending RepositoryFlags
|
|
468
|
+
* @template C - Context type extending Context<F>
|
|
469
|
+
* @param {string | Record<string, any>} targetName - The target class name or object
|
|
470
|
+
* @param {string} propKey - The property key to get handlers for
|
|
471
|
+
* @param {string} operation - The operation key to get handlers for
|
|
472
|
+
* @return {any} The registered handlers for the specified target, property, and operation
|
|
473
|
+
*/
|
|
299
474
|
static get(targetName, propKey, operation) {
|
|
300
475
|
return Operations.registry.get(targetName, propKey, operation);
|
|
301
476
|
}
|
|
477
|
+
/**
|
|
478
|
+
* @description Gets or initializes the operations registry
|
|
479
|
+
* @summary Returns the existing registry or creates a new one if it doesn't exist
|
|
480
|
+
* @return {OperationsRegistry} The operations registry instance
|
|
481
|
+
* @private
|
|
482
|
+
*/
|
|
302
483
|
static getOpRegistry() {
|
|
303
484
|
if (!Operations.registry)
|
|
304
485
|
Operations.registry = new OperationsRegistry();
|
|
305
486
|
return Operations.registry;
|
|
306
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* @description Registers an operation handler for a specific target and operation
|
|
490
|
+
* @summary Adds a handler to the operations registry for a given target, property, and operation
|
|
491
|
+
* @template V - Model type extending Model
|
|
492
|
+
* @param {OperationHandler<V, any, any>} handler - The handler function to register
|
|
493
|
+
* @param {OperationKeys} operation - The operation key to register the handler for
|
|
494
|
+
* @param {V} target - The target model instance
|
|
495
|
+
* @param {string | symbol} propKey - The property key to register the handler for
|
|
496
|
+
* @return {void}
|
|
497
|
+
*/
|
|
307
498
|
static register(handler, operation, target, propKey) {
|
|
308
499
|
Operations.getOpRegistry().register(handler, operation, target, propKey);
|
|
309
500
|
}
|
|
310
501
|
}
|
|
311
502
|
|
|
503
|
+
/**
|
|
504
|
+
* @description Internal function to register operation handlers
|
|
505
|
+
* @summary Registers an operation handler for a specific operation key on a target property
|
|
506
|
+
* @param {OperationKeys} op - The operation key to handle
|
|
507
|
+
* @param {OperationHandler<any, any, any, any, any>} handler - The handler function to register
|
|
508
|
+
* @return {PropertyDecorator} A decorator that registers the handler
|
|
509
|
+
* @function handle
|
|
510
|
+
* @category Property Decorators
|
|
511
|
+
*/
|
|
312
512
|
function handle(op, handler) {
|
|
313
513
|
return (target, propertyKey) => {
|
|
314
514
|
Operations.register(handler, op, target, propertyKey);
|
|
315
515
|
};
|
|
316
516
|
}
|
|
317
517
|
/**
|
|
318
|
-
* @
|
|
319
|
-
*
|
|
320
|
-
* @
|
|
321
|
-
* @param
|
|
322
|
-
* @param {
|
|
323
|
-
*
|
|
324
|
-
* @see on
|
|
325
|
-
*
|
|
518
|
+
* @description Decorator for handling create and update operations
|
|
519
|
+
* @summary Defines a behavior to execute during both create and update operations
|
|
520
|
+
* @template V - Type for metadata, defaults to object
|
|
521
|
+
* @param {StandardOperationHandler<any, any, V, any, any> | UpdateOperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
522
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
523
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
326
524
|
* @function onCreateUpdate
|
|
327
|
-
*
|
|
328
|
-
* @category Decorators
|
|
525
|
+
* @category Property Decorators
|
|
329
526
|
*/
|
|
330
527
|
function onCreateUpdate(handler, data) {
|
|
331
528
|
return on(DBOperations.CREATE_UPDATE, handler, data);
|
|
332
529
|
}
|
|
333
530
|
/**
|
|
334
|
-
* @
|
|
335
|
-
*
|
|
336
|
-
* @
|
|
337
|
-
* @param
|
|
338
|
-
* @param {
|
|
339
|
-
*
|
|
340
|
-
* @see on
|
|
341
|
-
*
|
|
531
|
+
* @description Decorator for handling update operations
|
|
532
|
+
* @summary Defines a behavior to execute during update operations
|
|
533
|
+
* @template V - Type for metadata, defaults to object
|
|
534
|
+
* @param {UpdateOperationHandler<any, any, V, any>} handler - The method called upon the operation
|
|
535
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
536
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
342
537
|
* @function onUpdate
|
|
343
|
-
*
|
|
344
|
-
* @category Decorators
|
|
538
|
+
* @category Property Decorators
|
|
345
539
|
*/
|
|
346
540
|
function onUpdate(handler, data) {
|
|
347
541
|
return on(DBOperations.UPDATE, handler, data);
|
|
348
542
|
}
|
|
349
543
|
/**
|
|
350
|
-
* @
|
|
351
|
-
*
|
|
352
|
-
* @
|
|
353
|
-
* @param
|
|
354
|
-
*
|
|
355
|
-
* @
|
|
356
|
-
*
|
|
544
|
+
* @description Decorator for handling create operations
|
|
545
|
+
* @summary Defines a behavior to execute during create operations
|
|
546
|
+
* @template V - Type for metadata, defaults to object
|
|
547
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
548
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
549
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
357
550
|
* @function onCreate
|
|
358
|
-
*
|
|
359
|
-
* @category Decorators
|
|
551
|
+
* @category Property Decorators
|
|
360
552
|
*/
|
|
361
553
|
function onCreate(handler, data) {
|
|
362
554
|
return on(DBOperations.CREATE, handler, data);
|
|
363
555
|
}
|
|
364
556
|
/**
|
|
365
|
-
* @
|
|
366
|
-
*
|
|
367
|
-
* @
|
|
368
|
-
* @param
|
|
369
|
-
*
|
|
370
|
-
* @
|
|
371
|
-
*
|
|
557
|
+
* @description Decorator for handling read operations
|
|
558
|
+
* @summary Defines a behavior to execute during read operations
|
|
559
|
+
* @template V - Type for metadata, defaults to object
|
|
560
|
+
* @param {IdOperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
561
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
562
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
372
563
|
* @function onRead
|
|
373
|
-
*
|
|
374
|
-
* @category Decorators
|
|
564
|
+
* @category Property Decorators
|
|
375
565
|
*/
|
|
376
566
|
function onRead(handler, data) {
|
|
377
567
|
return on(DBOperations.READ, handler, data);
|
|
378
568
|
}
|
|
379
569
|
/**
|
|
380
|
-
* @
|
|
381
|
-
*
|
|
382
|
-
* @
|
|
383
|
-
* @param
|
|
384
|
-
*
|
|
385
|
-
* @
|
|
386
|
-
*
|
|
570
|
+
* @description Decorator for handling delete operations
|
|
571
|
+
* @summary Defines a behavior to execute during delete operations
|
|
572
|
+
* @template V - Type for metadata, defaults to object
|
|
573
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
574
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
575
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
387
576
|
* @function onDelete
|
|
388
|
-
*
|
|
389
|
-
* @category Decorators
|
|
577
|
+
* @category Property Decorators
|
|
390
578
|
*/
|
|
391
579
|
function onDelete(handler, data) {
|
|
392
580
|
return on(DBOperations.DELETE, handler, data);
|
|
393
581
|
}
|
|
394
582
|
/**
|
|
395
|
-
* @
|
|
396
|
-
*
|
|
397
|
-
* @
|
|
398
|
-
* @param
|
|
399
|
-
*
|
|
400
|
-
* @
|
|
401
|
-
*
|
|
583
|
+
* @description Decorator for handling all operation types
|
|
584
|
+
* @summary Defines a behavior to execute during any database operation
|
|
585
|
+
* @template V - Type for metadata, defaults to object
|
|
586
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
587
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
588
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
402
589
|
* @function onAny
|
|
403
|
-
*
|
|
404
|
-
* @category Decorators
|
|
590
|
+
* @category Property Decorators
|
|
405
591
|
*/
|
|
406
592
|
function onAny(handler, data) {
|
|
407
593
|
return on(DBOperations.ALL, handler, data);
|
|
408
594
|
}
|
|
409
595
|
/**
|
|
410
|
-
* @
|
|
411
|
-
*
|
|
412
|
-
* @
|
|
413
|
-
* @param {
|
|
414
|
-
* @param
|
|
415
|
-
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
596
|
+
* @description Base decorator for handling database operations
|
|
597
|
+
* @summary Defines a behavior to execute during specified database operations
|
|
598
|
+
* @template V - Type for metadata, defaults to object
|
|
599
|
+
* @param {OperationKeys[] | DBOperations} [op=DBOperations.ALL] - One or more operation types to handle
|
|
600
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called upon the operation
|
|
601
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
602
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
418
603
|
* @function on
|
|
419
|
-
*
|
|
420
|
-
* @
|
|
604
|
+
* @category Property Decorators
|
|
605
|
+
* @example
|
|
606
|
+
* // Example usage:
|
|
607
|
+
* class MyModel {
|
|
608
|
+
* @on(DBOperations.CREATE, myHandler)
|
|
609
|
+
* myProperty: string;
|
|
610
|
+
* }
|
|
421
611
|
*/
|
|
422
612
|
function on(op = DBOperations.ALL, handler, data) {
|
|
423
613
|
return operation(exports.OperationKeys.ON, op, handler, data);
|
|
424
614
|
}
|
|
425
615
|
/**
|
|
426
|
-
* @
|
|
427
|
-
*
|
|
428
|
-
* @
|
|
429
|
-
* @param
|
|
430
|
-
*
|
|
431
|
-
* @
|
|
432
|
-
*
|
|
616
|
+
* @description Decorator for handling post-create and post-update operations
|
|
617
|
+
* @summary Defines a behavior to execute after both create and update operations
|
|
618
|
+
* @template V - Type for metadata, defaults to object
|
|
619
|
+
* @param {StandardOperationHandler<any, any, V, any, any> | UpdateOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
620
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
621
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
433
622
|
* @function afterCreateUpdate
|
|
434
|
-
*
|
|
435
|
-
* @category Decorators
|
|
623
|
+
* @category Property Decorators
|
|
436
624
|
*/
|
|
437
625
|
function afterCreateUpdate(handler, data) {
|
|
438
626
|
return after(DBOperations.CREATE_UPDATE, handler, data);
|
|
439
627
|
}
|
|
440
628
|
/**
|
|
441
|
-
* @
|
|
442
|
-
*
|
|
443
|
-
* @
|
|
444
|
-
* @param
|
|
445
|
-
*
|
|
446
|
-
* @
|
|
447
|
-
*
|
|
629
|
+
* @description Decorator for handling post-update operations
|
|
630
|
+
* @summary Defines a behavior to execute after update operations
|
|
631
|
+
* @template V - Type for metadata, defaults to object
|
|
632
|
+
* @param {UpdateOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
633
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
634
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
448
635
|
* @function afterUpdate
|
|
449
|
-
*
|
|
450
|
-
* @category Decorators
|
|
636
|
+
* @category Property Decorators
|
|
451
637
|
*/
|
|
452
638
|
function afterUpdate(handler, data) {
|
|
453
639
|
return after(DBOperations.UPDATE, handler, data);
|
|
454
640
|
}
|
|
455
641
|
/**
|
|
456
|
-
* @
|
|
457
|
-
*
|
|
458
|
-
* @
|
|
459
|
-
* @param
|
|
460
|
-
*
|
|
461
|
-
* @
|
|
462
|
-
*
|
|
642
|
+
* @description Decorator for handling post-create operations
|
|
643
|
+
* @summary Defines a behavior to execute after create operations
|
|
644
|
+
* @template V - Type for metadata, defaults to object
|
|
645
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
646
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
647
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
463
648
|
* @function afterCreate
|
|
464
|
-
*
|
|
465
|
-
* @category Decorators
|
|
649
|
+
* @category Property Decorators
|
|
466
650
|
*/
|
|
467
651
|
function afterCreate(handler, data) {
|
|
468
652
|
return after(DBOperations.CREATE, handler, data);
|
|
469
653
|
}
|
|
470
654
|
/**
|
|
471
|
-
* @
|
|
472
|
-
*
|
|
473
|
-
* @
|
|
474
|
-
* @param
|
|
475
|
-
* @param {
|
|
476
|
-
*
|
|
477
|
-
* @see after
|
|
478
|
-
*
|
|
655
|
+
* @description Decorator for handling post-read operations
|
|
656
|
+
* @summary Defines a behavior to execute after read operations
|
|
657
|
+
* @template V - Type for metadata, defaults to object
|
|
658
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
659
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
660
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
479
661
|
* @function afterRead
|
|
480
|
-
*
|
|
481
|
-
* @category Decorators
|
|
662
|
+
* @category Property Decorators
|
|
482
663
|
*/
|
|
483
664
|
function afterRead(handler, data) {
|
|
484
665
|
return after(DBOperations.READ, handler, data);
|
|
485
666
|
}
|
|
486
667
|
/**
|
|
487
|
-
* @
|
|
488
|
-
*
|
|
489
|
-
* @
|
|
490
|
-
* @param
|
|
491
|
-
* @param {
|
|
492
|
-
*
|
|
493
|
-
* @see after
|
|
494
|
-
*
|
|
668
|
+
* @description Decorator for handling post-delete operations
|
|
669
|
+
* @summary Defines a behavior to execute after delete operations
|
|
670
|
+
* @template V - Type for metadata, defaults to object
|
|
671
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
672
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
673
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
495
674
|
* @function afterDelete
|
|
496
|
-
*
|
|
497
|
-
* @category Decorators
|
|
675
|
+
* @category Property Decorators
|
|
498
676
|
*/
|
|
499
677
|
function afterDelete(handler, data) {
|
|
500
678
|
return after(DBOperations.DELETE, handler, data);
|
|
501
679
|
}
|
|
502
680
|
/**
|
|
503
|
-
* @
|
|
504
|
-
*
|
|
505
|
-
* @
|
|
506
|
-
* @param
|
|
507
|
-
* @param {
|
|
508
|
-
*
|
|
509
|
-
* @see after
|
|
510
|
-
*
|
|
681
|
+
* @description Decorator for handling post-operation for all operation types
|
|
682
|
+
* @summary Defines a behavior to execute after any database operation
|
|
683
|
+
* @template V - Type for metadata, defaults to object
|
|
684
|
+
* @param {StandardOperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
685
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
686
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
511
687
|
* @function afterAny
|
|
512
|
-
*
|
|
513
|
-
* @category Decorators
|
|
688
|
+
* @category Property Decorators
|
|
514
689
|
*/
|
|
515
690
|
function afterAny(handler, data) {
|
|
516
691
|
return after(DBOperations.ALL, handler, data);
|
|
517
692
|
}
|
|
518
693
|
/**
|
|
519
|
-
* @
|
|
520
|
-
*
|
|
521
|
-
* @
|
|
522
|
-
* @param {
|
|
523
|
-
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* @param data
|
|
527
|
-
* @param args
|
|
694
|
+
* @description Base decorator for handling post-operation behaviors
|
|
695
|
+
* @summary Defines a behavior to execute after specified database operations
|
|
696
|
+
* @template V - Type for metadata, defaults to object
|
|
697
|
+
* @param {OperationKeys[] | DBOperations} [op=DBOperations.ALL] - One or more operation types to handle
|
|
698
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The method called after the operation
|
|
699
|
+
* @param {V} [data] - Optional metadata to pass to the handler
|
|
700
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
528
701
|
* @function after
|
|
529
|
-
*
|
|
530
|
-
* @
|
|
702
|
+
* @category Property Decorators
|
|
703
|
+
* @example
|
|
704
|
+
* // Example usage:
|
|
705
|
+
* class MyModel {
|
|
706
|
+
* @after(DBOperations.CREATE, myHandler)
|
|
707
|
+
* myProperty: string;
|
|
708
|
+
* }
|
|
531
709
|
*/
|
|
532
710
|
function after(op = DBOperations.ALL, handler, data) {
|
|
533
711
|
return operation(exports.OperationKeys.AFTER, op, handler, data);
|
|
534
712
|
}
|
|
713
|
+
/**
|
|
714
|
+
* @description Core decorator factory for operation handlers
|
|
715
|
+
* @summary Creates decorators that register handlers for database operations
|
|
716
|
+
* @template V - Type for metadata, defaults to object
|
|
717
|
+
* @param {OperationKeys.ON | OperationKeys.AFTER} baseOp - Whether the handler runs during or after the operation
|
|
718
|
+
* @param {OperationKeys[]} [operation=DBOperations.ALL] - The specific operations to handle
|
|
719
|
+
* @param {OperationHandler<any, any, V, any, any>} handler - The handler function to execute
|
|
720
|
+
* @param {V} [dataToAdd] - Optional metadata to pass to the handler
|
|
721
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
722
|
+
* @function operation
|
|
723
|
+
* @category Property Decorators
|
|
724
|
+
* @mermaid
|
|
725
|
+
* sequenceDiagram
|
|
726
|
+
* participant Client
|
|
727
|
+
* participant Decorator as @operation
|
|
728
|
+
* participant Operations as Operations Registry
|
|
729
|
+
* participant Handler
|
|
730
|
+
*
|
|
731
|
+
* Client->>Decorator: Apply to property
|
|
732
|
+
* Decorator->>Operations: Register handler
|
|
733
|
+
* Decorator->>Decorator: Store metadata
|
|
734
|
+
*
|
|
735
|
+
* Note over Client,Handler: Later, during operation execution
|
|
736
|
+
* Client->>Operations: Execute operation
|
|
737
|
+
* Operations->>Handler: Call registered handler
|
|
738
|
+
* Handler-->>Operations: Return result
|
|
739
|
+
* Operations-->>Client: Return final result
|
|
740
|
+
*/
|
|
535
741
|
function operation(baseOp, operation = DBOperations.ALL, handler, dataToAdd) {
|
|
536
742
|
return (target, propertyKey) => {
|
|
537
743
|
const name = target.constructor.name;
|
|
@@ -562,12 +768,16 @@
|
|
|
562
768
|
}
|
|
563
769
|
|
|
564
770
|
/**
|
|
565
|
-
* @
|
|
566
|
-
*
|
|
567
|
-
* @param {string}
|
|
568
|
-
*
|
|
569
|
-
* @
|
|
570
|
-
* @
|
|
771
|
+
* @description Base error class for the repository module
|
|
772
|
+
* @summary Abstract base error class that all other error types extend from. Provides common error handling functionality.
|
|
773
|
+
* @param {string} name - The name of the error
|
|
774
|
+
* @param {string|Error} msg - The error message or Error object
|
|
775
|
+
* @param {number} code - The HTTP status code associated with this error
|
|
776
|
+
* @class BaseError
|
|
777
|
+
* @example
|
|
778
|
+
* // This is an abstract class and should not be instantiated directly
|
|
779
|
+
* // Instead, use one of the concrete error classes:
|
|
780
|
+
* throw new ValidationError('Invalid data provided');
|
|
571
781
|
*/
|
|
572
782
|
class BaseError extends Error {
|
|
573
783
|
constructor(name, msg, code = 500) {
|
|
@@ -581,12 +791,16 @@
|
|
|
581
791
|
}
|
|
582
792
|
}
|
|
583
793
|
/**
|
|
584
|
-
* @
|
|
585
|
-
*
|
|
586
|
-
* @param {string} msg
|
|
587
|
-
*
|
|
794
|
+
* @description Error thrown when validation fails
|
|
795
|
+
* @summary Represents a failure in the Model details, typically thrown when data validation fails
|
|
796
|
+
* @param {string|Error} msg - The error message or Error object
|
|
797
|
+
* @return {ValidationError} A new ValidationError instance
|
|
588
798
|
* @class ValidationError
|
|
589
|
-
* @
|
|
799
|
+
* @example
|
|
800
|
+
* // Throw a validation error when data is invalid
|
|
801
|
+
* if (!isValid(data)) {
|
|
802
|
+
* throw new ValidationError('Invalid data format');
|
|
803
|
+
* }
|
|
590
804
|
*/
|
|
591
805
|
class ValidationError extends BaseError {
|
|
592
806
|
constructor(msg) {
|
|
@@ -594,12 +808,18 @@
|
|
|
594
808
|
}
|
|
595
809
|
}
|
|
596
810
|
/**
|
|
597
|
-
* @
|
|
598
|
-
*
|
|
599
|
-
* @param {string} msg
|
|
600
|
-
*
|
|
811
|
+
* @description Error thrown for internal system failures
|
|
812
|
+
* @summary Represents an internal failure (should mean an error in code) with HTTP 500 status code
|
|
813
|
+
* @param {string|Error} msg - The error message or Error object
|
|
814
|
+
* @return {InternalError} A new InternalError instance
|
|
601
815
|
* @class InternalError
|
|
602
|
-
* @
|
|
816
|
+
* @example
|
|
817
|
+
* // Throw an internal error when an unexpected condition occurs
|
|
818
|
+
* try {
|
|
819
|
+
* // Some operation
|
|
820
|
+
* } catch (error) {
|
|
821
|
+
* throw new InternalError('Unexpected internal error occurred');
|
|
822
|
+
* }
|
|
603
823
|
*/
|
|
604
824
|
class InternalError extends BaseError {
|
|
605
825
|
constructor(msg) {
|
|
@@ -607,13 +827,18 @@
|
|
|
607
827
|
}
|
|
608
828
|
}
|
|
609
829
|
/**
|
|
610
|
-
* @
|
|
611
|
-
*
|
|
612
|
-
* @param {string} msg
|
|
613
|
-
*
|
|
830
|
+
* @description Error thrown when serialization or deserialization fails
|
|
831
|
+
* @summary Represents a failure in the Model de/serialization, typically when converting between data formats
|
|
832
|
+
* @param {string|Error} msg - The error message or Error object
|
|
833
|
+
* @return {SerializationError} A new SerializationError instance
|
|
614
834
|
* @class SerializationError
|
|
615
|
-
* @
|
|
616
|
-
*
|
|
835
|
+
* @example
|
|
836
|
+
* // Throw a serialization error when JSON parsing fails
|
|
837
|
+
* try {
|
|
838
|
+
* const data = JSON.parse(invalidJson);
|
|
839
|
+
* } catch (error) {
|
|
840
|
+
* throw new SerializationError('Failed to parse JSON data');
|
|
841
|
+
* }
|
|
617
842
|
*/
|
|
618
843
|
class SerializationError extends BaseError {
|
|
619
844
|
constructor(msg) {
|
|
@@ -621,13 +846,17 @@
|
|
|
621
846
|
}
|
|
622
847
|
}
|
|
623
848
|
/**
|
|
624
|
-
* @
|
|
625
|
-
*
|
|
626
|
-
* @param {string} msg
|
|
627
|
-
*
|
|
849
|
+
* @description Error thrown when a requested resource is not found
|
|
850
|
+
* @summary Represents a failure in finding a model, resulting in a 404 HTTP status code
|
|
851
|
+
* @param {string|Error} msg - The error message or Error object
|
|
852
|
+
* @return {NotFoundError} A new NotFoundError instance
|
|
628
853
|
* @class NotFoundError
|
|
629
|
-
* @
|
|
630
|
-
*
|
|
854
|
+
* @example
|
|
855
|
+
* // Throw a not found error when a record doesn't exist
|
|
856
|
+
* const user = await repository.findById(id);
|
|
857
|
+
* if (!user) {
|
|
858
|
+
* throw new NotFoundError(`User with ID ${id} not found`);
|
|
859
|
+
* }
|
|
631
860
|
*/
|
|
632
861
|
class NotFoundError extends BaseError {
|
|
633
862
|
constructor(msg) {
|
|
@@ -635,13 +864,17 @@
|
|
|
635
864
|
}
|
|
636
865
|
}
|
|
637
866
|
/**
|
|
638
|
-
* @
|
|
639
|
-
*
|
|
640
|
-
* @param {string} msg
|
|
641
|
-
*
|
|
867
|
+
* @description Error thrown when a conflict occurs in the storage
|
|
868
|
+
* @summary Represents a conflict in the storage, typically when trying to create a duplicate resource
|
|
869
|
+
* @param {string|Error} msg - The error message or Error object
|
|
870
|
+
* @return {ConflictError} A new ConflictError instance
|
|
642
871
|
* @class ConflictError
|
|
643
|
-
* @
|
|
644
|
-
*
|
|
872
|
+
* @example
|
|
873
|
+
* // Throw a conflict error when trying to create a duplicate record
|
|
874
|
+
* const existingUser = await repository.findByEmail(email);
|
|
875
|
+
* if (existingUser) {
|
|
876
|
+
* throw new ConflictError(`User with email ${email} already exists`);
|
|
877
|
+
* }
|
|
645
878
|
*/
|
|
646
879
|
class ConflictError extends BaseError {
|
|
647
880
|
constructor(msg) {
|
|
@@ -819,6 +1052,13 @@
|
|
|
819
1052
|
return getAllPropertyDecoratorsRecursive(proto, accumulator, ...prefixes);
|
|
820
1053
|
};
|
|
821
1054
|
|
|
1055
|
+
/**
|
|
1056
|
+
* @description Default configuration flags for repository operations.
|
|
1057
|
+
* @summary Provides default values for repository operation flags, excluding the timestamp property.
|
|
1058
|
+
* These flags control behavior such as context handling, validation, error handling, and more.
|
|
1059
|
+
* @const DefaultRepositoryFlags
|
|
1060
|
+
* @memberOf module:db-decorators
|
|
1061
|
+
*/
|
|
822
1062
|
const DefaultRepositoryFlags = {
|
|
823
1063
|
parentContext: undefined,
|
|
824
1064
|
childContexts: [],
|
|
@@ -831,16 +1071,95 @@
|
|
|
831
1071
|
rebuildWithTransient: true,
|
|
832
1072
|
};
|
|
833
1073
|
|
|
1074
|
+
/**
|
|
1075
|
+
* @description Default factory for creating context instances.
|
|
1076
|
+
* @summary A factory function that creates new Context instances with the provided repository flags.
|
|
1077
|
+
* It automatically adds a timestamp to the context and returns a properly typed context instance.
|
|
1078
|
+
* @const DefaultContextFactory
|
|
1079
|
+
* @memberOf module:db-decorators
|
|
1080
|
+
*/
|
|
834
1081
|
const DefaultContextFactory = (arg) => {
|
|
835
1082
|
return new Context().accumulate(Object.assign({}, arg, { timestamp: new Date() }));
|
|
836
1083
|
};
|
|
1084
|
+
/**
|
|
1085
|
+
* @description A context management class for handling repository operations.
|
|
1086
|
+
* @summary The Context class provides a mechanism for managing repository operations with flags,
|
|
1087
|
+
* parent-child relationships, and state accumulation. It allows for hierarchical context chains
|
|
1088
|
+
* and maintains operation-specific configurations while supporting type safety through generics.
|
|
1089
|
+
*
|
|
1090
|
+
* @template F - Type extending RepositoryFlags that defines the context configuration
|
|
1091
|
+
*
|
|
1092
|
+
* @param {ObjectAccumulator<F>} cache - The internal cache storing accumulated values
|
|
1093
|
+
*
|
|
1094
|
+
* @class
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* ```typescript
|
|
1098
|
+
* // Creating a new context with repository flags
|
|
1099
|
+
* const context = new Context<RepositoryFlags>();
|
|
1100
|
+
*
|
|
1101
|
+
* // Accumulating values
|
|
1102
|
+
* const enrichedContext = context.accumulate({
|
|
1103
|
+
* writeOperation: true,
|
|
1104
|
+
* affectedTables: ['users'],
|
|
1105
|
+
* operation: OperationKeys.CREATE
|
|
1106
|
+
* });
|
|
1107
|
+
*
|
|
1108
|
+
* // Accessing values
|
|
1109
|
+
* const isWrite = enrichedContext.get('writeOperation'); // true
|
|
1110
|
+
* const tables = enrichedContext.get('affectedTables'); // ['users']
|
|
1111
|
+
* ```
|
|
1112
|
+
*
|
|
1113
|
+
* @mermaid
|
|
1114
|
+
* sequenceDiagram
|
|
1115
|
+
* participant C as Client
|
|
1116
|
+
* participant Ctx as Context
|
|
1117
|
+
* participant Cache as ObjectAccumulator
|
|
1118
|
+
*
|
|
1119
|
+
* C->>Ctx: new Context()
|
|
1120
|
+
* Ctx->>Cache: create cache
|
|
1121
|
+
*
|
|
1122
|
+
* C->>Ctx: accumulate(value)
|
|
1123
|
+
* Ctx->>Cache: accumulate(value)
|
|
1124
|
+
* Cache-->>Ctx: updated cache
|
|
1125
|
+
* Ctx-->>C: updated context
|
|
1126
|
+
*
|
|
1127
|
+
* C->>Ctx: get(key)
|
|
1128
|
+
* Ctx->>Cache: get(key)
|
|
1129
|
+
* alt Key exists in cache
|
|
1130
|
+
* Cache-->>Ctx: value
|
|
1131
|
+
* else Key not found
|
|
1132
|
+
* Ctx->>Ctx: check parent context
|
|
1133
|
+
* alt Parent exists
|
|
1134
|
+
* Ctx->>Parent: get(key)
|
|
1135
|
+
* Parent-->>Ctx: value
|
|
1136
|
+
* else No parent
|
|
1137
|
+
* Ctx-->>C: throw error
|
|
1138
|
+
* end
|
|
1139
|
+
* end
|
|
1140
|
+
* Ctx-->>C: requested value
|
|
1141
|
+
*/
|
|
837
1142
|
class Context {
|
|
838
|
-
|
|
839
|
-
constructor(obj) {
|
|
1143
|
+
constructor() {
|
|
840
1144
|
this.cache = new typedObjectAccumulator.ObjectAccumulator();
|
|
841
|
-
|
|
842
|
-
|
|
1145
|
+
Object.defineProperty(this, "cache", {
|
|
1146
|
+
value: new typedObjectAccumulator.ObjectAccumulator(),
|
|
1147
|
+
writable: false,
|
|
1148
|
+
enumerable: false,
|
|
1149
|
+
configurable: true,
|
|
1150
|
+
});
|
|
843
1151
|
}
|
|
1152
|
+
static { this.factory = DefaultContextFactory; }
|
|
1153
|
+
/**
|
|
1154
|
+
* @description Accumulates new values into the context.
|
|
1155
|
+
* @summary Merges the provided value object with the existing context state,
|
|
1156
|
+
* creating a new immutable cache state.
|
|
1157
|
+
*
|
|
1158
|
+
* @template F - current accumulator type
|
|
1159
|
+
* @template V - Type extending object for the values to accumulate
|
|
1160
|
+
* @param {V} value - The object containing values to accumulate
|
|
1161
|
+
* @returns A new context instance with accumulated values
|
|
1162
|
+
*/
|
|
844
1163
|
accumulate(value) {
|
|
845
1164
|
Object.defineProperty(this, "cache", {
|
|
846
1165
|
value: this.cache.accumulate(value),
|
|
@@ -853,6 +1172,17 @@
|
|
|
853
1172
|
get timestamp() {
|
|
854
1173
|
return this.cache.timestamp;
|
|
855
1174
|
}
|
|
1175
|
+
/**
|
|
1176
|
+
* @description Retrieves a value from the context by key.
|
|
1177
|
+
* @summary Attempts to get a value from the current context's cache.
|
|
1178
|
+
* If not found, traverses up the parent context chain.
|
|
1179
|
+
*
|
|
1180
|
+
* @template K - Type extending keyof F for the key to retrieve
|
|
1181
|
+
* @template F - Accumulator type
|
|
1182
|
+
* @param {K} key - The key to retrieve from the context
|
|
1183
|
+
* @returns The value associated with the key
|
|
1184
|
+
* @throws {Error} If the key is not found in the context chain
|
|
1185
|
+
*/
|
|
856
1186
|
get(key) {
|
|
857
1187
|
try {
|
|
858
1188
|
return this.cache.get(key);
|
|
@@ -863,15 +1193,46 @@
|
|
|
863
1193
|
throw e;
|
|
864
1194
|
}
|
|
865
1195
|
}
|
|
1196
|
+
/**
|
|
1197
|
+
* @description Creates a child context
|
|
1198
|
+
* @summary Generates a new context instance with current context as parent
|
|
1199
|
+
*
|
|
1200
|
+
* @template M - Type extending Model
|
|
1201
|
+
* @param {OperationKeys} operation - The operation type
|
|
1202
|
+
* @param {Constructor<M>} [model] - Optional model constructor
|
|
1203
|
+
* @returns {C} New child context instance
|
|
1204
|
+
*/
|
|
866
1205
|
child(operation, model) {
|
|
867
1206
|
return Context.childFrom(this, {
|
|
868
1207
|
operation: operation,
|
|
869
1208
|
affectedTables: model ? [model] : [],
|
|
870
1209
|
});
|
|
871
1210
|
}
|
|
1211
|
+
/**
|
|
1212
|
+
* @description Creates a child context from another context
|
|
1213
|
+
* @summary Generates a new context instance with parent reference
|
|
1214
|
+
*
|
|
1215
|
+
* @template F - Type extending Repository Flags
|
|
1216
|
+
* @template C - Type extending Context<F>
|
|
1217
|
+
* @param {C} context - The parent context
|
|
1218
|
+
* @param {Partial<F>} [overrides] - Optional flag overrides
|
|
1219
|
+
* @returns {C} New child context instance
|
|
1220
|
+
*/
|
|
872
1221
|
static childFrom(context, overrides) {
|
|
873
1222
|
return Context.factory(Object.assign({}, context.cache, overrides || {}));
|
|
874
1223
|
}
|
|
1224
|
+
/**
|
|
1225
|
+
* @description Creates a new context from operation parameters
|
|
1226
|
+
* @summary Generates a context instance for specific operation
|
|
1227
|
+
*
|
|
1228
|
+
* @template F - Type extending Repository Flags
|
|
1229
|
+
* @template M - Type extending Model
|
|
1230
|
+
* @param {OperationKeys.DELETE} operation - The operation type
|
|
1231
|
+
* @param {Partial<F>} overrides - Flag overrides
|
|
1232
|
+
* @param {Constructor<M>} model - The model constructor
|
|
1233
|
+
* @param {any} args - Operation arguments
|
|
1234
|
+
* @returns {Promise<C>} Promise resolving to new context
|
|
1235
|
+
*/
|
|
875
1236
|
static async from(operation, overrides, model,
|
|
876
1237
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
877
1238
|
...args) {
|
|
@@ -880,6 +1241,33 @@
|
|
|
880
1241
|
model: model,
|
|
881
1242
|
}));
|
|
882
1243
|
}
|
|
1244
|
+
/**
|
|
1245
|
+
* @description Prepares arguments for context operations
|
|
1246
|
+
* @summary Creates a context args object with the specified operation parameters
|
|
1247
|
+
*
|
|
1248
|
+
* @template F - Type extending {@link RepositoryFlags}
|
|
1249
|
+
* @template M - Type extending {@link Model}
|
|
1250
|
+
* @param {OperationKeys.DELETE} operation - The operation type
|
|
1251
|
+
* @param {Constructor<M>} model - The model constructor
|
|
1252
|
+
* @param {any[]} args - Operation arguments
|
|
1253
|
+
* @param {Contextual<F>} [contextual] - Optional contextual object
|
|
1254
|
+
* @param {Partial<F>} [overrides] - Optional flag overrides
|
|
1255
|
+
* @returns {Promise<ContextArgs>} Promise resolving to context arguments
|
|
1256
|
+
*
|
|
1257
|
+
* @mermaid
|
|
1258
|
+
* sequenceDiagram
|
|
1259
|
+
* participant C as Context
|
|
1260
|
+
* participant M as Model
|
|
1261
|
+
* participant A as Args
|
|
1262
|
+
*
|
|
1263
|
+
* C->>C: Receive operation request
|
|
1264
|
+
* C->>M: Validate model constructor
|
|
1265
|
+
* C->>C: Create child context
|
|
1266
|
+
* C->>A: Process operation args
|
|
1267
|
+
* A->>C: Return context args
|
|
1268
|
+
* C->>C: Apply overrides
|
|
1269
|
+
* C->>C: Return final context
|
|
1270
|
+
*/
|
|
883
1271
|
static async args(operation, model, args, contextual, overrides) {
|
|
884
1272
|
const last = args.pop();
|
|
885
1273
|
async function getContext() {
|
|
@@ -915,7 +1303,7 @@
|
|
|
915
1303
|
*
|
|
916
1304
|
* @function prefixMethod
|
|
917
1305
|
*
|
|
918
|
-
* @memberOf module:db-decorators
|
|
1306
|
+
* @memberOf module:db-decorators
|
|
919
1307
|
*/
|
|
920
1308
|
function prefixMethod(obj, after, prefix, afterName) {
|
|
921
1309
|
async function wrapper(...args) {
|
|
@@ -969,7 +1357,7 @@
|
|
|
969
1357
|
*
|
|
970
1358
|
* @function wrapMethodWithContext
|
|
971
1359
|
*
|
|
972
|
-
* @memberOf module:db-decorators
|
|
1360
|
+
* @memberOf module:db-decorators
|
|
973
1361
|
*/
|
|
974
1362
|
function wrapMethodWithContext(obj, before, method, after, methodName) {
|
|
975
1363
|
const name = methodName ? methodName : method.name;
|
|
@@ -993,17 +1381,24 @@
|
|
|
993
1381
|
}
|
|
994
1382
|
|
|
995
1383
|
/**
|
|
996
|
-
* @
|
|
997
|
-
* @
|
|
998
|
-
*
|
|
999
|
-
* @
|
|
1000
|
-
*
|
|
1001
|
-
* @throws {InternalError} if no property or more than one properties are {@link id} decorated
|
|
1002
|
-
* or no value is set in that property
|
|
1003
|
-
*
|
|
1384
|
+
* @description Finds the primary key attribute for a model
|
|
1385
|
+
* @summary Searches in all the properties in the object for an {@link id} decorated property and returns the property key and metadata
|
|
1386
|
+
* @param {Model} model - The model object to search for primary key
|
|
1387
|
+
* @return {Object} An object containing the id property name and its metadata
|
|
1004
1388
|
* @function findPrimaryKey
|
|
1005
|
-
*
|
|
1006
|
-
*
|
|
1389
|
+
* @mermaid
|
|
1390
|
+
* sequenceDiagram
|
|
1391
|
+
* participant Caller
|
|
1392
|
+
* participant findPrimaryKey
|
|
1393
|
+
* participant getAllPropertyDecoratorsRecursive
|
|
1394
|
+
*
|
|
1395
|
+
* Caller->>findPrimaryKey: model
|
|
1396
|
+
* findPrimaryKey->>getAllPropertyDecoratorsRecursive: get decorators
|
|
1397
|
+
* getAllPropertyDecoratorsRecursive-->>findPrimaryKey: decorators
|
|
1398
|
+
* findPrimaryKey->>findPrimaryKey: filter ID decorators
|
|
1399
|
+
* findPrimaryKey->>findPrimaryKey: validate single ID property
|
|
1400
|
+
* findPrimaryKey-->>Caller: {id, props}
|
|
1401
|
+
* @memberOf module:db-decorators
|
|
1007
1402
|
*/
|
|
1008
1403
|
function findPrimaryKey(model) {
|
|
1009
1404
|
const decorators = getAllPropertyDecoratorsRecursive(model, undefined, DBKeys.REFLECT + DBKeys.ID);
|
|
@@ -1028,19 +1423,25 @@
|
|
|
1028
1423
|
};
|
|
1029
1424
|
}
|
|
1030
1425
|
/**
|
|
1031
|
-
* @
|
|
1032
|
-
* @
|
|
1033
|
-
*
|
|
1034
|
-
* @param {
|
|
1035
|
-
* @
|
|
1036
|
-
* @
|
|
1037
|
-
*
|
|
1038
|
-
*
|
|
1039
|
-
*
|
|
1040
|
-
*
|
|
1041
|
-
*
|
|
1042
|
-
*
|
|
1043
|
-
*
|
|
1426
|
+
* @description Retrieves the primary key value from a model
|
|
1427
|
+
* @summary Searches for the ID-decorated property in the model and returns its value
|
|
1428
|
+
* @param {Model} model - The model object to extract the ID from
|
|
1429
|
+
* @param {boolean} [returnEmpty=false] - Whether to return undefined if no ID value is found
|
|
1430
|
+
* @return {string | number | bigint} The primary key value
|
|
1431
|
+
* @function findModelId
|
|
1432
|
+
* @mermaid
|
|
1433
|
+
* sequenceDiagram
|
|
1434
|
+
* participant Caller
|
|
1435
|
+
* participant findModelId
|
|
1436
|
+
* participant findPrimaryKey
|
|
1437
|
+
*
|
|
1438
|
+
* Caller->>findModelId: model, returnEmpty
|
|
1439
|
+
* findModelId->>findPrimaryKey: model
|
|
1440
|
+
* findPrimaryKey-->>findModelId: {id, props}
|
|
1441
|
+
* findModelId->>findModelId: extract model[id]
|
|
1442
|
+
* findModelId->>findModelId: validate ID exists if required
|
|
1443
|
+
* findModelId-->>Caller: ID value
|
|
1444
|
+
* @memberOf module:db-decorators
|
|
1044
1445
|
*/
|
|
1045
1446
|
function findModelId(model, returnEmpty = false) {
|
|
1046
1447
|
const idProp = findPrimaryKey(model).id;
|
|
@@ -1050,12 +1451,115 @@
|
|
|
1050
1451
|
return modelId;
|
|
1051
1452
|
}
|
|
1052
1453
|
|
|
1454
|
+
/**
|
|
1455
|
+
* @description Base repository implementation providing CRUD operations for models.
|
|
1456
|
+
* @summary The BaseRepository class serves as a foundation for repository implementations, providing
|
|
1457
|
+
* abstract and concrete methods for creating, reading, updating, and deleting model instances.
|
|
1458
|
+
* It handles operation lifecycles including prefix and suffix operations, and enforces decorators.
|
|
1459
|
+
* @template M - The model type extending Model
|
|
1460
|
+
* @template F - The repository flags type, defaults to RepositoryFlags
|
|
1461
|
+
* @template C - The context type, defaults to Context<F>
|
|
1462
|
+
* @param {Constructor<M>} clazz - The constructor for the model class
|
|
1463
|
+
* @class BaseRepository
|
|
1464
|
+
* @example
|
|
1465
|
+
* class UserModel extends Model {
|
|
1466
|
+
* @id()
|
|
1467
|
+
* id: string;
|
|
1468
|
+
*
|
|
1469
|
+
* @required()
|
|
1470
|
+
* name: string;
|
|
1471
|
+
* }
|
|
1472
|
+
*
|
|
1473
|
+
* class UserRepository extends BaseRepository<UserModel> {
|
|
1474
|
+
* constructor() {
|
|
1475
|
+
* super(UserModel);
|
|
1476
|
+
* }
|
|
1477
|
+
*
|
|
1478
|
+
* async create(model: UserModel): Promise<UserModel> {
|
|
1479
|
+
* // Implementation
|
|
1480
|
+
* return model;
|
|
1481
|
+
* }
|
|
1482
|
+
*
|
|
1483
|
+
* async read(key: string): Promise<UserModel> {
|
|
1484
|
+
* // Implementation
|
|
1485
|
+
* return new UserModel({ id: key, name: 'User' });
|
|
1486
|
+
* }
|
|
1487
|
+
*
|
|
1488
|
+
* async update(model: UserModel): Promise<UserModel> {
|
|
1489
|
+
* // Implementation
|
|
1490
|
+
* return model;
|
|
1491
|
+
* }
|
|
1492
|
+
*
|
|
1493
|
+
* async delete(key: string): Promise<UserModel> {
|
|
1494
|
+
* // Implementation
|
|
1495
|
+
* const model = await this.read(key);
|
|
1496
|
+
* return model;
|
|
1497
|
+
* }
|
|
1498
|
+
* }
|
|
1499
|
+
*
|
|
1500
|
+
* @mermaid
|
|
1501
|
+
* sequenceDiagram
|
|
1502
|
+
* participant C as Client
|
|
1503
|
+
* participant R as Repository
|
|
1504
|
+
* participant P as Prefix Methods
|
|
1505
|
+
* participant D as Database
|
|
1506
|
+
* participant S as Suffix Methods
|
|
1507
|
+
* participant V as Validators/Decorators
|
|
1508
|
+
*
|
|
1509
|
+
* Note over C,V: Create Operation
|
|
1510
|
+
* C->>R: create(model)
|
|
1511
|
+
* R->>P: createPrefix(model)
|
|
1512
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1513
|
+
* P->>D: Database operation
|
|
1514
|
+
* D->>S: createSuffix(model)
|
|
1515
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1516
|
+
* S->>C: Return model
|
|
1517
|
+
*
|
|
1518
|
+
* Note over C,V: Read Operation
|
|
1519
|
+
* C->>R: read(key)
|
|
1520
|
+
* R->>P: readPrefix(key)
|
|
1521
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1522
|
+
* P->>D: Database operation
|
|
1523
|
+
* D->>S: readSuffix(model)
|
|
1524
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1525
|
+
* S->>C: Return model
|
|
1526
|
+
*
|
|
1527
|
+
* Note over C,V: Update Operation
|
|
1528
|
+
* C->>R: update(model)
|
|
1529
|
+
* R->>P: updatePrefix(model)
|
|
1530
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1531
|
+
* P->>D: Database operation
|
|
1532
|
+
* D->>S: updateSuffix(model)
|
|
1533
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1534
|
+
* S->>C: Return model
|
|
1535
|
+
*
|
|
1536
|
+
* Note over C,V: Delete Operation
|
|
1537
|
+
* C->>R: delete(key)
|
|
1538
|
+
* R->>P: deletePrefix(key)
|
|
1539
|
+
* P->>V: enforceDBDecorators(ON)
|
|
1540
|
+
* P->>D: Database operation
|
|
1541
|
+
* D->>S: deleteSuffix(model)
|
|
1542
|
+
* S->>V: enforceDBDecorators(AFTER)
|
|
1543
|
+
* S->>C: Return model
|
|
1544
|
+
*/
|
|
1053
1545
|
class BaseRepository {
|
|
1546
|
+
/**
|
|
1547
|
+
* @description Gets the model class constructor.
|
|
1548
|
+
* @summary Retrieves the constructor for the model class associated with this repository.
|
|
1549
|
+
* Throws an error if no class definition is found.
|
|
1550
|
+
* @return {Constructor<M>} The constructor for the model class
|
|
1551
|
+
*/
|
|
1054
1552
|
get class() {
|
|
1055
1553
|
if (!this._class)
|
|
1056
1554
|
throw new InternalError(`No class definition found for this repository`);
|
|
1057
1555
|
return this._class;
|
|
1058
1556
|
}
|
|
1557
|
+
/**
|
|
1558
|
+
* @description Gets the primary key property name of the model.
|
|
1559
|
+
* @summary Retrieves the name of the property that serves as the primary key for the model.
|
|
1560
|
+
* If not already determined, it finds the primary key using the model's decorators.
|
|
1561
|
+
* @return The name of the primary key property
|
|
1562
|
+
*/
|
|
1059
1563
|
get pk() {
|
|
1060
1564
|
if (!this._pk) {
|
|
1061
1565
|
const { id, props } = findPrimaryKey(new this.class());
|
|
@@ -1064,6 +1568,12 @@
|
|
|
1064
1568
|
}
|
|
1065
1569
|
return this._pk;
|
|
1066
1570
|
}
|
|
1571
|
+
/**
|
|
1572
|
+
* @description Gets the primary key properties.
|
|
1573
|
+
* @summary Retrieves the properties associated with the primary key of the model.
|
|
1574
|
+
* If not already determined, it triggers the pk getter to find the primary key properties.
|
|
1575
|
+
* @return {any} The properties of the primary key
|
|
1576
|
+
*/
|
|
1067
1577
|
get pkProps() {
|
|
1068
1578
|
if (!this._pkProps) {
|
|
1069
1579
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -1081,19 +1591,53 @@
|
|
|
1081
1591
|
wrapMethodWithContext(self, self[name + "Prefix"], m, self[name + "Suffix"]);
|
|
1082
1592
|
});
|
|
1083
1593
|
}
|
|
1594
|
+
/**
|
|
1595
|
+
* @description Creates multiple model instances in the repository.
|
|
1596
|
+
* @summary Persists multiple model instances to the underlying data store by calling
|
|
1597
|
+
* the create method for each model in the array.
|
|
1598
|
+
* @param {M[]} models - The array of model instances to create
|
|
1599
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1600
|
+
* @return {Promise<M[]>} A promise that resolves to an array of created model instances
|
|
1601
|
+
*/
|
|
1084
1602
|
async createAll(models, ...args) {
|
|
1085
1603
|
return Promise.all(models.map((m) => this.create(m, ...args)));
|
|
1086
1604
|
}
|
|
1605
|
+
/**
|
|
1606
|
+
* @description Prepares a model for creation and executes pre-creation operations.
|
|
1607
|
+
* @summary Processes a model before it is created in the data store. This includes
|
|
1608
|
+
* creating a context, instantiating a new model instance, and enforcing any decorators
|
|
1609
|
+
* that should be applied before creation.
|
|
1610
|
+
* @param {M} model - The model instance to prepare for creation
|
|
1611
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1612
|
+
* @return A promise that resolves to an array containing the prepared model and context arguments
|
|
1613
|
+
*/
|
|
1087
1614
|
async createPrefix(model, ...args) {
|
|
1088
1615
|
const contextArgs = await Context.args(exports.OperationKeys.CREATE, this.class, args);
|
|
1089
1616
|
model = new this.class(model);
|
|
1090
1617
|
await enforceDBDecorators(this, contextArgs.context, model, exports.OperationKeys.CREATE, exports.OperationKeys.ON);
|
|
1091
1618
|
return [model, ...contextArgs.args];
|
|
1092
1619
|
}
|
|
1620
|
+
/**
|
|
1621
|
+
* @description Processes a model after creation and executes post-creation operations.
|
|
1622
|
+
* @summary Finalizes a model after it has been created in the data store. This includes
|
|
1623
|
+
* enforcing any decorators that should be applied after creation.
|
|
1624
|
+
* @param {M} model - The model instance that was created
|
|
1625
|
+
* @param {C} context - The context for the operation
|
|
1626
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1627
|
+
*/
|
|
1093
1628
|
async createSuffix(model, context) {
|
|
1094
1629
|
await enforceDBDecorators(this, context, model, exports.OperationKeys.CREATE, exports.OperationKeys.AFTER);
|
|
1095
1630
|
return model;
|
|
1096
1631
|
}
|
|
1632
|
+
/**
|
|
1633
|
+
* @description Prepares multiple models for creation and executes pre-creation operations.
|
|
1634
|
+
* @summary Processes multiple models before they are created in the data store. This includes
|
|
1635
|
+
* creating a context, instantiating new model instances, and enforcing any decorators
|
|
1636
|
+
* that should be applied before creation for each model.
|
|
1637
|
+
* @param {M[]} models - The array of model instances to prepare for creation
|
|
1638
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1639
|
+
* @return A promise that resolves to an array containing the prepared models and context arguments
|
|
1640
|
+
*/
|
|
1097
1641
|
async createAllPrefix(models, ...args) {
|
|
1098
1642
|
const contextArgs = await Context.args(exports.OperationKeys.CREATE, this.class, args);
|
|
1099
1643
|
await Promise.all(models.map(async (m) => {
|
|
@@ -1103,17 +1647,50 @@
|
|
|
1103
1647
|
}));
|
|
1104
1648
|
return [models, ...contextArgs.args];
|
|
1105
1649
|
}
|
|
1650
|
+
/**
|
|
1651
|
+
* @description Processes multiple models after creation and executes post-creation operations.
|
|
1652
|
+
* @summary Finalizes multiple models after they have been created in the data store. This includes
|
|
1653
|
+
* enforcing any decorators that should be applied after creation for each model.
|
|
1654
|
+
* @param {M[]} models - The array of model instances that were created
|
|
1655
|
+
* @param {C} context - The context for the operation
|
|
1656
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1657
|
+
*/
|
|
1106
1658
|
async createAllSuffix(models, context) {
|
|
1107
1659
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, exports.OperationKeys.CREATE, exports.OperationKeys.AFTER)));
|
|
1108
1660
|
return models;
|
|
1109
1661
|
}
|
|
1662
|
+
/**
|
|
1663
|
+
* @description Retrieves multiple model instances from the repository by their primary keys.
|
|
1664
|
+
* @summary Fetches multiple model instances from the underlying data store using their primary keys
|
|
1665
|
+
* by calling the read method for each key in the array.
|
|
1666
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to retrieve
|
|
1667
|
+
* @param {any[]} args - Additional arguments for the read operation
|
|
1668
|
+
* @return {Promise<M[]>} A promise that resolves to an array of retrieved model instances
|
|
1669
|
+
*/
|
|
1110
1670
|
async readAll(keys, ...args) {
|
|
1111
1671
|
return await Promise.all(keys.map((id) => this.read(id, ...args)));
|
|
1112
1672
|
}
|
|
1673
|
+
/**
|
|
1674
|
+
* @description Processes a model after retrieval and executes post-read operations.
|
|
1675
|
+
* @summary Finalizes a model after it has been retrieved from the data store. This includes
|
|
1676
|
+
* enforcing any decorators that should be applied after reading.
|
|
1677
|
+
* @param {M} model - The model instance that was retrieved
|
|
1678
|
+
* @param {C} context - The context for the operation
|
|
1679
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1680
|
+
*/
|
|
1113
1681
|
async readSuffix(model, context) {
|
|
1114
1682
|
await enforceDBDecorators(this, context, model, exports.OperationKeys.READ, exports.OperationKeys.AFTER);
|
|
1115
1683
|
return model;
|
|
1116
1684
|
}
|
|
1685
|
+
/**
|
|
1686
|
+
* @description Prepares for reading a model and executes pre-read operations.
|
|
1687
|
+
* @summary Processes a key before a model is read from the data store. This includes
|
|
1688
|
+
* creating a context, instantiating a new model instance with the key, and enforcing any decorators
|
|
1689
|
+
* that should be applied before reading.
|
|
1690
|
+
* @param {string} key - The primary key of the model to read
|
|
1691
|
+
* @param {any[]} args - Additional arguments for the read operation
|
|
1692
|
+
* @return A promise that resolves to an array containing the key and context arguments
|
|
1693
|
+
*/
|
|
1117
1694
|
async readPrefix(key, ...args) {
|
|
1118
1695
|
const contextArgs = await Context.args(exports.OperationKeys.READ, this.class, args);
|
|
1119
1696
|
const model = new this.class();
|
|
@@ -1121,6 +1698,15 @@
|
|
|
1121
1698
|
await enforceDBDecorators(this, contextArgs.context, model, exports.OperationKeys.READ, exports.OperationKeys.ON);
|
|
1122
1699
|
return [key, ...contextArgs.args];
|
|
1123
1700
|
}
|
|
1701
|
+
/**
|
|
1702
|
+
* @description Prepares for reading multiple models and executes pre-read operations.
|
|
1703
|
+
* @summary Processes multiple keys before models are read from the data store. This includes
|
|
1704
|
+
* creating a context, instantiating new model instances with the keys, and enforcing any decorators
|
|
1705
|
+
* that should be applied before reading for each key.
|
|
1706
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to read
|
|
1707
|
+
* @param {any[]} args - Additional arguments for the read operation
|
|
1708
|
+
* @return A promise that resolves to an array containing the keys and context arguments
|
|
1709
|
+
*/
|
|
1124
1710
|
async readAllPrefix(keys, ...args) {
|
|
1125
1711
|
const contextArgs = await Context.args(exports.OperationKeys.READ, this.class, args);
|
|
1126
1712
|
await Promise.all(keys.map(async (k) => {
|
|
@@ -1130,17 +1716,50 @@
|
|
|
1130
1716
|
}));
|
|
1131
1717
|
return [keys, ...contextArgs.args];
|
|
1132
1718
|
}
|
|
1719
|
+
/**
|
|
1720
|
+
* @description Processes multiple models after retrieval and executes post-read operations.
|
|
1721
|
+
* @summary Finalizes multiple models after they have been retrieved from the data store. This includes
|
|
1722
|
+
* enforcing any decorators that should be applied after reading for each model.
|
|
1723
|
+
* @param {M[]} models - The array of model instances that were retrieved
|
|
1724
|
+
* @param {C} context - The context for the operation
|
|
1725
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1726
|
+
*/
|
|
1133
1727
|
async readAllSuffix(models, context) {
|
|
1134
1728
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, exports.OperationKeys.READ, exports.OperationKeys.AFTER)));
|
|
1135
1729
|
return models;
|
|
1136
1730
|
}
|
|
1731
|
+
/**
|
|
1732
|
+
* @description Updates multiple model instances in the repository.
|
|
1733
|
+
* @summary Updates multiple model instances in the underlying data store by calling
|
|
1734
|
+
* the update method for each model in the array.
|
|
1735
|
+
* @param {M[]} models - The array of model instances to update
|
|
1736
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1737
|
+
* @return {Promise<M[]>} A promise that resolves to an array of updated model instances
|
|
1738
|
+
*/
|
|
1137
1739
|
async updateAll(models, ...args) {
|
|
1138
1740
|
return Promise.all(models.map((m) => this.update(m, ...args)));
|
|
1139
1741
|
}
|
|
1742
|
+
/**
|
|
1743
|
+
* @description Processes a model after update and executes post-update operations.
|
|
1744
|
+
* @summary Finalizes a model after it has been updated in the data store. This includes
|
|
1745
|
+
* enforcing any decorators that should be applied after updating.
|
|
1746
|
+
* @param {M} model - The model instance that was updated
|
|
1747
|
+
* @param {C} context - The context for the operation
|
|
1748
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1749
|
+
*/
|
|
1140
1750
|
async updateSuffix(model, context) {
|
|
1141
1751
|
await enforceDBDecorators(this, context, model, exports.OperationKeys.UPDATE, exports.OperationKeys.AFTER);
|
|
1142
1752
|
return model;
|
|
1143
1753
|
}
|
|
1754
|
+
/**
|
|
1755
|
+
* @description Prepares a model for update and executes pre-update operations.
|
|
1756
|
+
* @summary Processes a model before it is updated in the data store. This includes
|
|
1757
|
+
* creating a context, validating the primary key, retrieving the existing model,
|
|
1758
|
+
* and enforcing any decorators that should be applied before updating.
|
|
1759
|
+
* @param {M} model - The model instance to prepare for update
|
|
1760
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1761
|
+
* @return A promise that resolves to an array containing the prepared model and context arguments
|
|
1762
|
+
*/
|
|
1144
1763
|
async updatePrefix(model, ...args) {
|
|
1145
1764
|
const contextArgs = await Context.args(exports.OperationKeys.UPDATE, this.class, args);
|
|
1146
1765
|
const id = model[this.pk];
|
|
@@ -1150,6 +1769,15 @@
|
|
|
1150
1769
|
await enforceDBDecorators(this, contextArgs.context, model, exports.OperationKeys.UPDATE, exports.OperationKeys.ON, oldModel);
|
|
1151
1770
|
return [model, ...contextArgs.args];
|
|
1152
1771
|
}
|
|
1772
|
+
/**
|
|
1773
|
+
* @description Prepares multiple models for update and executes pre-update operations.
|
|
1774
|
+
* @summary Processes multiple models before they are updated in the data store. This includes
|
|
1775
|
+
* creating a context, instantiating new model instances, and enforcing any decorators
|
|
1776
|
+
* that should be applied before updating for each model.
|
|
1777
|
+
* @param {M[]} models - The array of model instances to prepare for update
|
|
1778
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1779
|
+
* @return A promise that resolves to an array containing the prepared models and context arguments
|
|
1780
|
+
*/
|
|
1153
1781
|
async updateAllPrefix(models, ...args) {
|
|
1154
1782
|
const contextArgs = await Context.args(exports.OperationKeys.UPDATE, this.class, args);
|
|
1155
1783
|
await Promise.all(models.map((m) => {
|
|
@@ -1159,23 +1787,65 @@
|
|
|
1159
1787
|
}));
|
|
1160
1788
|
return [models, ...contextArgs.args];
|
|
1161
1789
|
}
|
|
1790
|
+
/**
|
|
1791
|
+
* @description Processes multiple models after update and executes post-update operations.
|
|
1792
|
+
* @summary Finalizes multiple models after they have been updated in the data store. This includes
|
|
1793
|
+
* enforcing any decorators that should be applied after updating for each model.
|
|
1794
|
+
* @param {M[]} models - The array of model instances that were updated
|
|
1795
|
+
* @param {C} context - The context for the operation
|
|
1796
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1797
|
+
*/
|
|
1162
1798
|
async updateAllSuffix(models, context) {
|
|
1163
1799
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, exports.OperationKeys.UPDATE, exports.OperationKeys.AFTER)));
|
|
1164
1800
|
return models;
|
|
1165
1801
|
}
|
|
1802
|
+
/**
|
|
1803
|
+
* @description Deletes multiple model instances from the repository by their primary keys.
|
|
1804
|
+
* @summary Removes multiple model instances from the underlying data store using their primary keys
|
|
1805
|
+
* by calling the delete method for each key in the array.
|
|
1806
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to delete
|
|
1807
|
+
* @param {any[]} args - Additional arguments for the delete operation
|
|
1808
|
+
* @return {Promise<M[]>} A promise that resolves to an array of deleted model instances
|
|
1809
|
+
*/
|
|
1166
1810
|
async deleteAll(keys, ...args) {
|
|
1167
1811
|
return Promise.all(keys.map((k) => this.delete(k, ...args)));
|
|
1168
1812
|
}
|
|
1813
|
+
/**
|
|
1814
|
+
* @description Processes a model after deletion and executes post-delete operations.
|
|
1815
|
+
* @summary Finalizes a model after it has been deleted from the data store. This includes
|
|
1816
|
+
* enforcing any decorators that should be applied after deletion.
|
|
1817
|
+
* @param {M} model - The model instance that was deleted
|
|
1818
|
+
* @param {C} context - The context for the operation
|
|
1819
|
+
* @return {Promise<M>} A promise that resolves to the processed model instance
|
|
1820
|
+
*/
|
|
1169
1821
|
async deleteSuffix(model, context) {
|
|
1170
1822
|
await enforceDBDecorators(this, context, model, exports.OperationKeys.DELETE, exports.OperationKeys.AFTER);
|
|
1171
1823
|
return model;
|
|
1172
1824
|
}
|
|
1825
|
+
/**
|
|
1826
|
+
* @description Prepares for deleting a model and executes pre-delete operations.
|
|
1827
|
+
* @summary Processes a key before a model is deleted from the data store. This includes
|
|
1828
|
+
* creating a context, retrieving the model to be deleted, and enforcing any decorators
|
|
1829
|
+
* that should be applied before deletion.
|
|
1830
|
+
* @param {any} key - The primary key of the model to delete
|
|
1831
|
+
* @param {any[]} args - Additional arguments for the delete operation
|
|
1832
|
+
* @return A promise that resolves to an array containing the key and context arguments
|
|
1833
|
+
*/
|
|
1173
1834
|
async deletePrefix(key, ...args) {
|
|
1174
1835
|
const contextArgs = await Context.args(exports.OperationKeys.DELETE, this.class, args);
|
|
1175
1836
|
const model = await this.read(key, ...contextArgs.args);
|
|
1176
1837
|
await enforceDBDecorators(this, contextArgs.context, model, exports.OperationKeys.DELETE, exports.OperationKeys.ON);
|
|
1177
1838
|
return [key, ...contextArgs.args];
|
|
1178
1839
|
}
|
|
1840
|
+
/**
|
|
1841
|
+
* @description Prepares for deleting multiple models and executes pre-delete operations.
|
|
1842
|
+
* @summary Processes multiple keys before models are deleted from the data store. This includes
|
|
1843
|
+
* creating a context, retrieving the models to be deleted, and enforcing any decorators
|
|
1844
|
+
* that should be applied before deletion for each model.
|
|
1845
|
+
* @param {string[] | number[]} keys - The array of primary keys of the models to delete
|
|
1846
|
+
* @param {any[]} args - Additional arguments for the delete operation
|
|
1847
|
+
* @return A promise that resolves to an array containing the keys and context arguments
|
|
1848
|
+
*/
|
|
1179
1849
|
async deleteAllPrefix(keys, ...args) {
|
|
1180
1850
|
const contextArgs = await Context.args(exports.OperationKeys.DELETE, this.class, args);
|
|
1181
1851
|
const models = await this.readAll(keys, ...contextArgs.args);
|
|
@@ -1184,10 +1854,26 @@
|
|
|
1184
1854
|
}));
|
|
1185
1855
|
return [keys, ...contextArgs.args];
|
|
1186
1856
|
}
|
|
1857
|
+
/**
|
|
1858
|
+
* @description Processes multiple models after deletion and executes post-delete operations.
|
|
1859
|
+
* @summary Finalizes multiple models after they have been deleted from the data store. This includes
|
|
1860
|
+
* enforcing any decorators that should be applied after deletion for each model.
|
|
1861
|
+
* @param {M[]} models - The array of model instances that were deleted
|
|
1862
|
+
* @param {C} context - The context for the operation
|
|
1863
|
+
* @return {Promise<M[]>} A promise that resolves to the array of processed model instances
|
|
1864
|
+
*/
|
|
1187
1865
|
async deleteAllSuffix(models, context) {
|
|
1188
1866
|
await Promise.all(models.map((m) => enforceDBDecorators(this, context, m, exports.OperationKeys.DELETE, exports.OperationKeys.AFTER)));
|
|
1189
1867
|
return models;
|
|
1190
1868
|
}
|
|
1869
|
+
/**
|
|
1870
|
+
* @description Merges two model instances into a new instance.
|
|
1871
|
+
* @summary Creates a new model instance by combining properties from an old model and a new model.
|
|
1872
|
+
* Properties from the new model override properties from the old model if they are defined.
|
|
1873
|
+
* @param {M} oldModel - The original model instance
|
|
1874
|
+
* @param {M} model - The new model instance with updated properties
|
|
1875
|
+
* @return {M} A new model instance with merged properties
|
|
1876
|
+
*/
|
|
1191
1877
|
merge(oldModel, model) {
|
|
1192
1878
|
const extract = (model) => Object.entries(model).reduce((accum, [key, val]) => {
|
|
1193
1879
|
if (typeof val !== "undefined")
|
|
@@ -1196,24 +1882,87 @@
|
|
|
1196
1882
|
}, {});
|
|
1197
1883
|
return new this.class(Object.assign({}, extract(oldModel), extract(model)));
|
|
1198
1884
|
}
|
|
1885
|
+
/**
|
|
1886
|
+
* @description Returns a string representation of the repository.
|
|
1887
|
+
* @summary Creates a string that identifies this repository by the name of its model class.
|
|
1888
|
+
* @return {string} A string representation of the repository
|
|
1889
|
+
*/
|
|
1199
1890
|
toString() {
|
|
1200
1891
|
return `${this.class.name} Repository`;
|
|
1201
1892
|
}
|
|
1202
1893
|
}
|
|
1203
1894
|
|
|
1895
|
+
/**
|
|
1896
|
+
* @description Concrete repository implementation with validation support.
|
|
1897
|
+
* @summary The Repository class extends BaseRepository to provide additional validation
|
|
1898
|
+
* functionality. It overrides prefix methods to perform model validation before database
|
|
1899
|
+
* operations and throws ValidationError when validation fails.
|
|
1900
|
+
* @template M - The model type extending Model
|
|
1901
|
+
* @template F - The repository flags type, defaults to RepositoryFlags
|
|
1902
|
+
* @template C - The context type, defaults to Context<F>
|
|
1903
|
+
* @class Repository
|
|
1904
|
+
* @example
|
|
1905
|
+
* class UserModel extends Model {
|
|
1906
|
+
* @id()
|
|
1907
|
+
* id: string;
|
|
1908
|
+
*
|
|
1909
|
+
* @required()
|
|
1910
|
+
* @minLength(3)
|
|
1911
|
+
* name: string;
|
|
1912
|
+
* }
|
|
1913
|
+
*
|
|
1914
|
+
* class UserRepository extends Repository<UserModel> {
|
|
1915
|
+
* constructor() {
|
|
1916
|
+
* super(UserModel);
|
|
1917
|
+
* }
|
|
1918
|
+
*
|
|
1919
|
+
* async create(model: UserModel): Promise<UserModel> {
|
|
1920
|
+
* // Implementation with automatic validation
|
|
1921
|
+
* return model;
|
|
1922
|
+
* }
|
|
1923
|
+
* }
|
|
1924
|
+
*
|
|
1925
|
+
* // Using the repository
|
|
1926
|
+
* const repo = new UserRepository();
|
|
1927
|
+
* try {
|
|
1928
|
+
* const user = await repo.create({ name: 'Jo' }); // Will throw ValidationError
|
|
1929
|
+
* } catch (error) {
|
|
1930
|
+
* console.error(error); // ValidationError: name must be at least 3 characters
|
|
1931
|
+
* }
|
|
1932
|
+
*/
|
|
1204
1933
|
class Repository extends BaseRepository {
|
|
1205
1934
|
constructor(clazz) {
|
|
1206
1935
|
super(clazz);
|
|
1207
1936
|
}
|
|
1937
|
+
/**
|
|
1938
|
+
* @description Prepares a model for creation with validation.
|
|
1939
|
+
* @summary Overrides the base createPrefix method to add validation checks.
|
|
1940
|
+
* Creates a context, instantiates a new model, enforces decorators, and validates
|
|
1941
|
+
* the model before allowing creation to proceed.
|
|
1942
|
+
* @param {M} model - The model instance to prepare for creation
|
|
1943
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1944
|
+
* @return A promise that resolves to an array containing the validated model and context arguments
|
|
1945
|
+
* @throws {ValidationError} If the model fails validation
|
|
1946
|
+
*/
|
|
1208
1947
|
async createPrefix(model, ...args) {
|
|
1209
1948
|
const contextArgs = await Context.args(exports.OperationKeys.CREATE, this.class, args);
|
|
1210
1949
|
model = new this.class(model);
|
|
1211
1950
|
await enforceDBDecorators(this, contextArgs.context, model, exports.OperationKeys.CREATE, exports.OperationKeys.ON);
|
|
1212
|
-
const errors = model.hasErrors();
|
|
1951
|
+
const errors = await Promise.resolve(model.hasErrors());
|
|
1213
1952
|
if (errors)
|
|
1214
1953
|
throw new ValidationError(errors.toString());
|
|
1215
1954
|
return [model, ...contextArgs.args];
|
|
1216
1955
|
}
|
|
1956
|
+
/**
|
|
1957
|
+
* @description Prepares multiple models for creation with validation.
|
|
1958
|
+
* @summary Overrides the base createAllPrefix method to add validation checks for multiple models.
|
|
1959
|
+
* Creates a context, instantiates new models, enforces decorators, and validates
|
|
1960
|
+
* each model before allowing creation to proceed. Collects validation errors from all models.
|
|
1961
|
+
* @param {M[]} models - The array of model instances to prepare for creation
|
|
1962
|
+
* @param {any[]} args - Additional arguments for the create operation
|
|
1963
|
+
* @return {Promise<any[]>} A promise that resolves to an array containing the validated models and context arguments
|
|
1964
|
+
* @throws {ValidationError} If any model fails validation, with details about which models failed
|
|
1965
|
+
*/
|
|
1217
1966
|
async createAllPrefix(models, ...args) {
|
|
1218
1967
|
const contextArgs = await Context.args(exports.OperationKeys.CREATE, this.class, args);
|
|
1219
1968
|
await Promise.all(models.map(async (m) => {
|
|
@@ -1221,9 +1970,8 @@
|
|
|
1221
1970
|
await enforceDBDecorators(this, contextArgs.context, m, exports.OperationKeys.CREATE, exports.OperationKeys.ON);
|
|
1222
1971
|
return m;
|
|
1223
1972
|
}));
|
|
1224
|
-
const
|
|
1225
|
-
|
|
1226
|
-
.reduce((accum, e, i) => {
|
|
1973
|
+
const modelsValidation = await Promise.all(models.map((m) => Promise.resolve(m.hasErrors())));
|
|
1974
|
+
const errors = modelsValidation.reduce((accum, e, i) => {
|
|
1227
1975
|
if (e)
|
|
1228
1976
|
accum =
|
|
1229
1977
|
typeof accum === "string"
|
|
@@ -1235,6 +1983,18 @@
|
|
|
1235
1983
|
throw new ValidationError(errors);
|
|
1236
1984
|
return [models, ...contextArgs.args];
|
|
1237
1985
|
}
|
|
1986
|
+
/**
|
|
1987
|
+
* @description Prepares a model for update with validation.
|
|
1988
|
+
* @summary Overrides the base updatePrefix method to add validation checks.
|
|
1989
|
+
* Creates a context, validates the primary key, retrieves the existing model,
|
|
1990
|
+
* merges the old and new models, enforces decorators, and validates the model
|
|
1991
|
+
* before allowing the update to proceed.
|
|
1992
|
+
* @param {M} model - The model instance to prepare for update
|
|
1993
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
1994
|
+
* @return A promise that resolves to an array containing the validated model and context arguments
|
|
1995
|
+
* @throws {InternalError} If the model doesn't have a primary key value
|
|
1996
|
+
* @throws {ValidationError} If the model fails validation
|
|
1997
|
+
*/
|
|
1238
1998
|
async updatePrefix(model, ...args) {
|
|
1239
1999
|
const contextArgs = await Context.args(exports.OperationKeys.UPDATE, this.class, args);
|
|
1240
2000
|
const pk = model[this.pk];
|
|
@@ -1243,11 +2003,23 @@
|
|
|
1243
2003
|
const oldModel = await this.read(pk);
|
|
1244
2004
|
model = this.merge(oldModel, model);
|
|
1245
2005
|
await enforceDBDecorators(this, contextArgs.context, model, exports.OperationKeys.UPDATE, exports.OperationKeys.ON, oldModel);
|
|
1246
|
-
const errors = model.hasErrors(oldModel);
|
|
2006
|
+
const errors = await Promise.resolve(model.hasErrors(oldModel));
|
|
1247
2007
|
if (errors)
|
|
1248
2008
|
throw new ValidationError(errors.toString());
|
|
1249
2009
|
return [model, ...contextArgs.args];
|
|
1250
2010
|
}
|
|
2011
|
+
/**
|
|
2012
|
+
* @description Prepares multiple models for update with validation.
|
|
2013
|
+
* @summary Overrides the base updateAllPrefix method to add validation checks for multiple models.
|
|
2014
|
+
* Creates a context, validates primary keys, retrieves existing models, merges old and new models,
|
|
2015
|
+
* enforces decorators, and validates each model before allowing updates to proceed.
|
|
2016
|
+
* Collects validation errors from all models.
|
|
2017
|
+
* @param {M[]} models - The array of model instances to prepare for update
|
|
2018
|
+
* @param {any[]} args - Additional arguments for the update operation
|
|
2019
|
+
* @return A promise that resolves to an array containing the validated models and context arguments
|
|
2020
|
+
* @throws {InternalError} If any model doesn't have a primary key value
|
|
2021
|
+
* @throws {ValidationError} If any model fails validation, with details about which models failed
|
|
2022
|
+
*/
|
|
1251
2023
|
async updateAllPrefix(models, ...args) {
|
|
1252
2024
|
const contextArgs = await Context.args(exports.OperationKeys.UPDATE, this.class, args);
|
|
1253
2025
|
const ids = models.map((m) => {
|
|
@@ -1259,9 +2031,8 @@
|
|
|
1259
2031
|
const oldModels = await this.readAll(ids, ...contextArgs.args);
|
|
1260
2032
|
models = models.map((m, i) => this.merge(oldModels[i], m));
|
|
1261
2033
|
await Promise.all(models.map((m, i) => enforceDBDecorators(this, contextArgs.context, m, exports.OperationKeys.UPDATE, exports.OperationKeys.ON, oldModels[i])));
|
|
1262
|
-
const
|
|
1263
|
-
|
|
1264
|
-
.reduce((accum, e, i) => {
|
|
2034
|
+
const modelsValidation = await Promise.all(models.map((m, i) => Promise.resolve(m.hasErrors(oldModels[i]))));
|
|
2035
|
+
const errors = modelsValidation.reduce((accum, e, i) => {
|
|
1265
2036
|
if (e)
|
|
1266
2037
|
accum =
|
|
1267
2038
|
typeof accum === "string"
|
|
@@ -1273,19 +2044,25 @@
|
|
|
1273
2044
|
throw new ValidationError(errors);
|
|
1274
2045
|
return [models, ...contextArgs.args];
|
|
1275
2046
|
}
|
|
2047
|
+
/**
|
|
2048
|
+
* @description Creates a reflection key for database operations.
|
|
2049
|
+
* @summary Generates a key for storing metadata in the reflection system by prefixing
|
|
2050
|
+
* the provided key with the database reflection prefix.
|
|
2051
|
+
* @param {string} key - The base key to prefix
|
|
2052
|
+
* @return {string} The prefixed reflection key
|
|
2053
|
+
*/
|
|
1276
2054
|
static key(key) {
|
|
1277
2055
|
return DBKeys.REFLECT + key;
|
|
1278
2056
|
}
|
|
1279
2057
|
}
|
|
1280
2058
|
|
|
1281
2059
|
/**
|
|
1282
|
-
*
|
|
1283
|
-
*
|
|
1284
|
-
* @param {string} [message]
|
|
1285
|
-
*
|
|
1286
|
-
* @
|
|
1287
|
-
*
|
|
1288
|
-
* @category Decorators
|
|
2060
|
+
* @description Prevents a property from being modified after initial creation.
|
|
2061
|
+
* @summary Marks the property as readonly, causing validation errors if attempts are made to modify it during updates.
|
|
2062
|
+
* @param {string} [message] - The error message to display when validation fails. Defaults to {@link DEFAULT_ERROR_MESSAGES.READONLY.INVALID}
|
|
2063
|
+
* @return {PropertyDecorator} A decorator function that can be applied to class properties
|
|
2064
|
+
* @function readonly
|
|
2065
|
+
* @category Property Decorators
|
|
1289
2066
|
*/
|
|
1290
2067
|
function readonly(message = DEFAULT_ERROR_MESSAGES.READONLY.INVALID) {
|
|
1291
2068
|
const key = decoratorValidation.Validation.updateKey(DBKeys.READONLY);
|
|
@@ -1295,13 +2072,28 @@
|
|
|
1295
2072
|
}))
|
|
1296
2073
|
.apply();
|
|
1297
2074
|
}
|
|
2075
|
+
/**
|
|
2076
|
+
* @description Handler function that sets a timestamp property to the current timestamp.
|
|
2077
|
+
* @summary Updates a model property with the current timestamp from the repository context.
|
|
2078
|
+
* @template M - The model type extending Model
|
|
2079
|
+
* @template R - The repository type extending IRepository
|
|
2080
|
+
* @template V - The data type for the operation
|
|
2081
|
+
* @template F - The repository flags type
|
|
2082
|
+
* @template C - The context type
|
|
2083
|
+
* @param {C} context - The repository context containing the current timestamp
|
|
2084
|
+
* @param {V} data - The data being processed
|
|
2085
|
+
* @param key - The property key to update
|
|
2086
|
+
* @param {M} model - The model instance being updated
|
|
2087
|
+
* @return {Promise<void>} A promise that resolves when the timestamp has been set
|
|
2088
|
+
* @function timestampHandler
|
|
2089
|
+
* @memberOf module:db-decorators
|
|
2090
|
+
*/
|
|
1298
2091
|
async function timestampHandler(context, data, key, model) {
|
|
1299
2092
|
model[key] = context.timestamp;
|
|
1300
2093
|
}
|
|
1301
2094
|
/**
|
|
1302
|
-
*
|
|
1303
|
-
*
|
|
1304
|
-
* Makes it a {@link date}
|
|
2095
|
+
* @description Automatically manages timestamp properties for tracking creation and update times.
|
|
2096
|
+
* @summary Marks the property as a timestamp, making it required and ensuring it's a valid date. The property will be automatically updated with the current timestamp during specified operations.
|
|
1305
2097
|
*
|
|
1306
2098
|
* Date Format:
|
|
1307
2099
|
*
|
|
@@ -1321,13 +2113,30 @@
|
|
|
1321
2113
|
* S = miliseconds
|
|
1322
2114
|
* </pre>
|
|
1323
2115
|
*
|
|
1324
|
-
* @param {
|
|
1325
|
-
* @param {string} [format] The
|
|
1326
|
-
* @
|
|
1327
|
-
*
|
|
1328
|
-
* @
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
2116
|
+
* @param {OperationKeys[]} operation - The operations to act on. Defaults to {@link DBOperations.CREATE_UPDATE}
|
|
2117
|
+
* @param {string} [format] - The timestamp format. Defaults to {@link DEFAULT_TIMESTAMP_FORMAT}
|
|
2118
|
+
* @return {PropertyDecorator} A decorator function that can be applied to class properties
|
|
2119
|
+
* @function timestamp
|
|
2120
|
+
* @category Property Decorators
|
|
2121
|
+
* @mermaid
|
|
2122
|
+
* sequenceDiagram
|
|
2123
|
+
* participant C as Client
|
|
2124
|
+
* participant M as Model
|
|
2125
|
+
* participant T as TimestampDecorator
|
|
2126
|
+
* participant V as Validator
|
|
2127
|
+
*
|
|
2128
|
+
* C->>M: Create/Update model
|
|
2129
|
+
* M->>T: Process timestamp property
|
|
2130
|
+
* T->>M: Apply required validation
|
|
2131
|
+
* T->>M: Apply date format validation
|
|
2132
|
+
*
|
|
2133
|
+
* alt Update operation
|
|
2134
|
+
* T->>V: Register timestamp validator
|
|
2135
|
+
* V->>M: Validate timestamp is newer
|
|
2136
|
+
* end
|
|
2137
|
+
*
|
|
2138
|
+
* T->>M: Set current timestamp
|
|
2139
|
+
* M->>C: Return updated model
|
|
1331
2140
|
*/
|
|
1332
2141
|
function timestamp(operation = DBOperations.CREATE_UPDATE, format = DEFAULT_TIMESTAMP_FORMAT) {
|
|
1333
2142
|
const key = decoratorValidation.Validation.updateKey(DBKeys.TIMESTAMP);
|
|
@@ -1344,6 +2153,22 @@
|
|
|
1344
2153
|
.define(...decorators)
|
|
1345
2154
|
.apply();
|
|
1346
2155
|
}
|
|
2156
|
+
/**
|
|
2157
|
+
* @description Handler function that serializes a property to JSON string during create and update operations.
|
|
2158
|
+
* @summary Converts a complex object property to a JSON string before storing it in the database.
|
|
2159
|
+
* @template M - The model type extending Model
|
|
2160
|
+
* @template R - The repository type extending IRepository
|
|
2161
|
+
* @template V - The data type for the operation
|
|
2162
|
+
* @template F - The repository flags type
|
|
2163
|
+
* @template C - The context type
|
|
2164
|
+
* @param {C} context - The repository context
|
|
2165
|
+
* @param {V} data - The data being processed
|
|
2166
|
+
* @param key - The property key to serialize
|
|
2167
|
+
* @param {M} model - The model instance being processed
|
|
2168
|
+
* @return {Promise<void>} A promise that resolves when the property has been serialized
|
|
2169
|
+
* @function serializeOnCreateUpdate
|
|
2170
|
+
* @memberOf module:db-decorators
|
|
2171
|
+
*/
|
|
1347
2172
|
async function serializeOnCreateUpdate(context, data, key, model) {
|
|
1348
2173
|
if (!model[key])
|
|
1349
2174
|
return;
|
|
@@ -1355,6 +2180,22 @@
|
|
|
1355
2180
|
throw new SerializationError(`Failed to serialize ${key.toString()} property of model ${model.constructor.name}: e`);
|
|
1356
2181
|
}
|
|
1357
2182
|
}
|
|
2183
|
+
/**
|
|
2184
|
+
* @description Handler function that deserializes a property from JSON string after database operations.
|
|
2185
|
+
* @summary Converts a JSON string property back to its original complex object form after retrieving it from the database.
|
|
2186
|
+
* @template M - The model type extending Model
|
|
2187
|
+
* @template R - The repository type extending IRepository
|
|
2188
|
+
* @template V - The data type for the operation
|
|
2189
|
+
* @template F - The repository flags type
|
|
2190
|
+
* @template C - The context type
|
|
2191
|
+
* @param {C} context - The repository context
|
|
2192
|
+
* @param {V} data - The data being processed
|
|
2193
|
+
* @param key - The property key to deserialize
|
|
2194
|
+
* @param {M} model - The model instance being processed
|
|
2195
|
+
* @return {Promise<void>} A promise that resolves when the property has been deserialized
|
|
2196
|
+
* @function serializeAfterAll
|
|
2197
|
+
* @memberOf module:db-decorators
|
|
2198
|
+
*/
|
|
1358
2199
|
async function serializeAfterAll(context, data, key, model) {
|
|
1359
2200
|
if (!model[key])
|
|
1360
2201
|
return;
|
|
@@ -1368,146 +2209,323 @@
|
|
|
1368
2209
|
}
|
|
1369
2210
|
}
|
|
1370
2211
|
/**
|
|
1371
|
-
* @
|
|
1372
|
-
* @
|
|
1373
|
-
*
|
|
2212
|
+
* @description Enables automatic JSON serialization and deserialization for complex object properties.
|
|
2213
|
+
* @summary Decorator that automatically converts complex objects to JSON strings before storing in the database and back to objects when retrieving them.
|
|
2214
|
+
* @return {PropertyDecorator} A decorator function that can be applied to class properties
|
|
1374
2215
|
* @function serialize
|
|
1375
|
-
*
|
|
1376
|
-
* @
|
|
2216
|
+
* @category Property Decorators
|
|
2217
|
+
* @mermaid
|
|
2218
|
+
* sequenceDiagram
|
|
2219
|
+
* participant C as Client
|
|
2220
|
+
* participant M as Model
|
|
2221
|
+
* participant S as SerializeDecorator
|
|
2222
|
+
* participant DB as Database
|
|
2223
|
+
*
|
|
2224
|
+
* Note over C,DB: Create/Update Flow
|
|
2225
|
+
* C->>M: Set complex object property
|
|
2226
|
+
* M->>S: Process property (create/update)
|
|
2227
|
+
* S->>M: Convert to JSON string
|
|
2228
|
+
* M->>DB: Store serialized data
|
|
2229
|
+
*
|
|
2230
|
+
* Note over C,DB: Retrieval Flow
|
|
2231
|
+
* C->>M: Request model
|
|
2232
|
+
* M->>DB: Fetch data
|
|
2233
|
+
* DB->>M: Return with serialized property
|
|
2234
|
+
* M->>S: Process property (after all ops)
|
|
2235
|
+
* S->>M: Parse JSON back to object
|
|
2236
|
+
* M->>C: Return model with deserialized property
|
|
1377
2237
|
*/
|
|
1378
2238
|
function serialize() {
|
|
1379
2239
|
return reflection.apply(onCreateUpdate(serializeOnCreateUpdate), after(DBOperations.ALL, serializeAfterAll), decoratorValidation.type([String.name, Object.name]), reflection.metadata(Repository.key(DBKeys.SERIALIZE), {}));
|
|
1380
2240
|
}
|
|
1381
2241
|
|
|
2242
|
+
/**
|
|
2243
|
+
* @description Decorator that marks a property as an ID field
|
|
2244
|
+
* @summary Creates a composite decorator that marks a property as required, readonly, and as the ID field for database operations
|
|
2245
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2246
|
+
* @function id
|
|
2247
|
+
* @category Property Decorators
|
|
2248
|
+
*/
|
|
1382
2249
|
function id() {
|
|
1383
2250
|
return reflection.apply(decoratorValidation.required(), readonly(), decoratorValidation.propMetadata(Repository.key(DBKeys.ID), {}));
|
|
1384
2251
|
}
|
|
1385
2252
|
|
|
1386
2253
|
/**
|
|
1387
|
-
* @
|
|
2254
|
+
* @description
|
|
2255
|
+
* Retrieves validation decorator definitions from a model for update operations, including
|
|
2256
|
+
* support for special handling of list decorators.
|
|
1388
2257
|
*
|
|
1389
|
-
* @
|
|
1390
|
-
*
|
|
1391
|
-
*
|
|
2258
|
+
* @summary
|
|
2259
|
+
* Iterates over the model's own enumerable properties and filters out those specified in the
|
|
2260
|
+
* `propsToIgnore` array. For each remaining property, retrieves validation decorators specific
|
|
2261
|
+
* to update operations using the `UpdateValidationKeys.REFLECT` key. Additionally, it explicitly
|
|
2262
|
+
* checks for and appends any `LIST` type decorators to ensure proper validation of collection types.
|
|
1392
2263
|
*
|
|
1393
|
-
* @
|
|
1394
|
-
* @return {ModelErrorDefinition | undefined}
|
|
2264
|
+
* @template M - A generic parameter extending the `Model` class, representing the model type being inspected.
|
|
1395
2265
|
*
|
|
1396
|
-
* @
|
|
2266
|
+
* @param {M} model - The model instance whose properties are being inspected for update-related validations.
|
|
2267
|
+
* @param {string[]} propsToIgnore - A list of property names to exclude from the validation decorator retrieval process.
|
|
2268
|
+
*
|
|
2269
|
+
* @return {ValidationPropertyDecoratorDefinition[]} An array of validation decorator definitions, including both
|
|
2270
|
+
* update-specific and list-type decorators, excluding those for ignored properties.
|
|
2271
|
+
*
|
|
2272
|
+
* @function getValidatableUpdateProps
|
|
1397
2273
|
*/
|
|
1398
|
-
function
|
|
2274
|
+
function getValidatableUpdateProps(model, propsToIgnore) {
|
|
1399
2275
|
const decoratedProperties = [];
|
|
1400
|
-
for (const prop in
|
|
1401
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
2276
|
+
for (const prop in model) {
|
|
2277
|
+
if (Object.prototype.hasOwnProperty.call(model, prop) &&
|
|
2278
|
+
!propsToIgnore.includes(prop)) {
|
|
2279
|
+
const validationPropertyDefinition = decoratorValidation.getValidationDecorators(model, prop, UpdateValidationKeys.REFLECT);
|
|
2280
|
+
const listDecorator = decoratorValidation.getValidationDecorators(model, prop).decorators.find(({ key }) => key === decoratorValidation.ValidationKeys.LIST);
|
|
2281
|
+
if (listDecorator)
|
|
2282
|
+
validationPropertyDefinition.decorators.push(listDecorator);
|
|
2283
|
+
decoratedProperties.push(validationPropertyDefinition);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
return decoratedProperties;
|
|
2287
|
+
}
|
|
2288
|
+
function validateDecorator(newModel, oldModel, prop, decorator, async) {
|
|
2289
|
+
const validator = decoratorValidation.Validation.get(decorator.key);
|
|
2290
|
+
if (!validator) {
|
|
2291
|
+
throw new Error(`Missing validator for ${decorator.key}`);
|
|
2292
|
+
}
|
|
2293
|
+
// Skip validators that aren't UpdateValidators
|
|
2294
|
+
if (!validator.updateHasErrors)
|
|
2295
|
+
return decoratorValidation.toConditionalPromise(undefined, async);
|
|
2296
|
+
// skip async decorators if validateDecorators is called synchronously (async = false)
|
|
2297
|
+
if (!async && decorator.props.async)
|
|
2298
|
+
return decoratorValidation.toConditionalPromise(undefined, async);
|
|
2299
|
+
const decoratorProps = Object.values(decorator.props) || {};
|
|
2300
|
+
// const context = PathProxyEngine.create(obj, {
|
|
2301
|
+
// ignoreUndefined: true,
|
|
2302
|
+
// ignoreNull: true,
|
|
2303
|
+
// });
|
|
2304
|
+
const maybeError = validator.updateHasErrors(newModel[prop], oldModel[prop], ...decoratorProps);
|
|
2305
|
+
return decoratorValidation.toConditionalPromise(maybeError, async);
|
|
2306
|
+
}
|
|
2307
|
+
function validateDecorators(newModel, oldModel, prop, decorators, async) {
|
|
2308
|
+
const result = {};
|
|
2309
|
+
for (const decorator of decorators) {
|
|
2310
|
+
// skip async decorators if validateDecorators is called synchronously (async = false)
|
|
2311
|
+
if (!async && decorator.props.async)
|
|
1409
2312
|
continue;
|
|
1410
|
-
let
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
2313
|
+
let validationErrors = validateDecorator(newModel, oldModel, prop, decorator, async);
|
|
2314
|
+
/*
|
|
2315
|
+
If the decorator is a list, each element must be checked.
|
|
2316
|
+
When 'async' is true, the 'err' will always be a pending promise initially,
|
|
2317
|
+
so the '!err' check will evaluate to false (even if the promise later resolves with no errors)
|
|
2318
|
+
*/
|
|
2319
|
+
if (decorator.key === decoratorValidation.ValidationKeys.LIST && (!validationErrors || async)) {
|
|
2320
|
+
const newPropValue = newModel[prop];
|
|
2321
|
+
const oldPropValue = oldModel[prop];
|
|
2322
|
+
const newValues = newPropValue instanceof Set ? [...newPropValue] : newPropValue;
|
|
2323
|
+
const oldValues = oldPropValue instanceof Set ? [...oldPropValue] : oldPropValue;
|
|
2324
|
+
if (newValues && newValues.length > 0) {
|
|
2325
|
+
const types = decorator.props.class ||
|
|
2326
|
+
decorator.props.clazz ||
|
|
2327
|
+
decorator.props.customTypes;
|
|
2328
|
+
const allowedTypes = [types].flat().map((t) => String(t).toLowerCase());
|
|
2329
|
+
const errs = newValues.map((childValue) => {
|
|
2330
|
+
// find by id so the list elements order doesn't matter
|
|
2331
|
+
const id = findModelId(childValue, true);
|
|
2332
|
+
if (!id)
|
|
2333
|
+
return "Failed to find model id";
|
|
2334
|
+
const oldModel = oldValues.find((el) => id === findModelId(el, true));
|
|
2335
|
+
if (decoratorValidation.Model.isModel(childValue)) {
|
|
2336
|
+
return childValue.hasErrors(oldModel);
|
|
2337
|
+
}
|
|
2338
|
+
return allowedTypes.includes(typeof childValue)
|
|
2339
|
+
? undefined
|
|
2340
|
+
: "Value has no validatable type";
|
|
2341
|
+
});
|
|
2342
|
+
if (async) {
|
|
2343
|
+
validationErrors = Promise.all(errs).then((result) => {
|
|
2344
|
+
const allEmpty = result.every((r) => !r);
|
|
2345
|
+
return allEmpty ? undefined : result;
|
|
2346
|
+
});
|
|
2347
|
+
}
|
|
2348
|
+
else {
|
|
2349
|
+
const allEmpty = errs.every((r) => !r);
|
|
2350
|
+
validationErrors = errs.length > 0 && !allEmpty ? errs : undefined;
|
|
2351
|
+
}
|
|
1421
2352
|
}
|
|
1422
2353
|
}
|
|
1423
|
-
if (
|
|
1424
|
-
result =
|
|
1425
|
-
|
|
2354
|
+
if (validationErrors)
|
|
2355
|
+
result[decorator.key] = validationErrors;
|
|
2356
|
+
}
|
|
2357
|
+
if (!async)
|
|
2358
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
2359
|
+
const keys = Object.keys(result);
|
|
2360
|
+
const promises = Object.values(result);
|
|
2361
|
+
return Promise.all(promises).then((resolvedValues) => {
|
|
2362
|
+
const res = {};
|
|
2363
|
+
for (let i = 0; i < resolvedValues.length; i++) {
|
|
2364
|
+
const val = resolvedValues[i];
|
|
2365
|
+
if (val !== undefined) {
|
|
2366
|
+
res[keys[i]] = val;
|
|
2367
|
+
}
|
|
1426
2368
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
2369
|
+
return Object.keys(res).length > 0 ? res : undefined;
|
|
2370
|
+
});
|
|
2371
|
+
}
|
|
2372
|
+
/**
|
|
2373
|
+
* @description Validates changes between two model versions
|
|
2374
|
+
* @summary Compares an old and new model version to validate update operations
|
|
2375
|
+
* @template M - Type extending Model
|
|
2376
|
+
* @param {M} oldModel - The original model version
|
|
2377
|
+
* @param {M} newModel - The updated model version
|
|
2378
|
+
* @param {boolean} async - A flag indicating whether validation should be asynchronous.
|
|
2379
|
+
* @param {...string[]} exceptions - Properties to exclude from validation
|
|
2380
|
+
* @return {ModelErrorDefinition|undefined} Error definition if validation fails, undefined otherwise
|
|
2381
|
+
* @function validateCompare
|
|
2382
|
+
* @memberOf module:db-decorators
|
|
2383
|
+
* @mermaid
|
|
2384
|
+
* sequenceDiagram
|
|
2385
|
+
* participant Caller
|
|
2386
|
+
* participant validateCompare
|
|
2387
|
+
* participant Reflection
|
|
2388
|
+
* participant Validation
|
|
2389
|
+
*
|
|
2390
|
+
* Caller->>validateCompare: oldModel, newModel, exceptions
|
|
2391
|
+
* validateCompare->>Reflection: get decorated properties
|
|
2392
|
+
* Reflection-->>validateCompare: property decorators
|
|
2393
|
+
* loop For each decorated property
|
|
2394
|
+
* validateCompare->>Validation: get validator
|
|
2395
|
+
* Validation-->>validateCompare: validator
|
|
2396
|
+
* validateCompare->>validateCompare: validate property update
|
|
2397
|
+
* end
|
|
2398
|
+
* loop For nested models
|
|
2399
|
+
* validateCompare->>validateCompare: validate nested models
|
|
2400
|
+
* end
|
|
2401
|
+
* validateCompare-->>Caller: validation errors or undefined
|
|
2402
|
+
*/
|
|
2403
|
+
function validateCompare(oldModel, newModel, async, ...exceptions) {
|
|
2404
|
+
const decoratedProperties = getValidatableUpdateProps(newModel, exceptions);
|
|
2405
|
+
const result = {};
|
|
2406
|
+
const nestedErrors = {};
|
|
2407
|
+
for (const { prop, decorators } of decoratedProperties) {
|
|
2408
|
+
const propKey = String(prop);
|
|
2409
|
+
let propValue = newModel[prop];
|
|
2410
|
+
if (!decorators?.length)
|
|
1439
2411
|
continue;
|
|
1440
|
-
|
|
1441
|
-
const
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
if (
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
default:
|
|
1466
|
-
throw new Error(`Invalid attribute type ${c}`);
|
|
1467
|
-
}
|
|
1468
|
-
err = currentList
|
|
1469
|
-
.map((v) => {
|
|
1470
|
-
const id = findModelId(v, true);
|
|
1471
|
-
if (!id)
|
|
1472
|
-
return "Failed to find model id";
|
|
1473
|
-
const oldModel = oldList.find((el) => id === findModelId(el, true));
|
|
1474
|
-
if (!oldModel)
|
|
1475
|
-
return; // nothing to compare with
|
|
1476
|
-
return v.hasErrors(oldModel);
|
|
1477
|
-
})
|
|
1478
|
-
.filter((e) => !!e);
|
|
1479
|
-
if (!err?.length) {
|
|
1480
|
-
// if the result is an empty list...
|
|
1481
|
-
err = undefined;
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
break;
|
|
1486
|
-
default:
|
|
1487
|
-
try {
|
|
1488
|
-
if (newModel[prop] &&
|
|
1489
|
-
oldModel[prop])
|
|
1490
|
-
err = newModel[prop].hasErrors(oldModel[prop]);
|
|
1491
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1492
|
-
}
|
|
1493
|
-
catch (e) {
|
|
1494
|
-
console.warn(decoratorValidation.sf("Model should be validatable but its not"));
|
|
1495
|
-
}
|
|
2412
|
+
// Get the default type validator
|
|
2413
|
+
const designTypeDec = decorators.find((d) => [decoratorValidation.ModelKeys.TYPE, decoratorValidation.ValidationKeys.TYPE].includes(d.key));
|
|
2414
|
+
if (!designTypeDec)
|
|
2415
|
+
continue;
|
|
2416
|
+
const designType = designTypeDec.props.name;
|
|
2417
|
+
// Handle array or Set types and enforce the presence of @list decorator
|
|
2418
|
+
if ([Array.name, Set.name].includes(designType)) {
|
|
2419
|
+
const { decorators } = reflection.Reflection.getPropertyDecorators(decoratorValidation.ValidationKeys.REFLECT, newModel, propKey);
|
|
2420
|
+
if (!decorators.some((d) => d.key === decoratorValidation.ValidationKeys.LIST)) {
|
|
2421
|
+
result[propKey] = {
|
|
2422
|
+
[decoratorValidation.ValidationKeys.TYPE]: `Array or Set property '${propKey}' requires a @list decorator`,
|
|
2423
|
+
};
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
if (propValue &&
|
|
2427
|
+
!(Array.isArray(propValue) || propValue instanceof Set)) {
|
|
2428
|
+
result[propKey] = {
|
|
2429
|
+
[decoratorValidation.ValidationKeys.TYPE]: `Property '${String(prop)}' must be either an array or a Set`,
|
|
2430
|
+
};
|
|
2431
|
+
continue;
|
|
2432
|
+
}
|
|
2433
|
+
// Remove design:type decorator, since @list decorator already ensures type
|
|
2434
|
+
for (let i = decorators.length - 1; i >= 0; i--) {
|
|
2435
|
+
if (decorators[i].key === decoratorValidation.ModelKeys.TYPE) {
|
|
2436
|
+
decorators.splice(i, 1);
|
|
1496
2437
|
}
|
|
1497
2438
|
}
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
2439
|
+
propValue = propValue instanceof Set ? [...propValue] : propValue;
|
|
2440
|
+
}
|
|
2441
|
+
const propErrors = validateDecorators(newModel, oldModel, propKey, decorators, async) || {};
|
|
2442
|
+
// Check for nested properties.
|
|
2443
|
+
// To prevent unnecessary processing, "propValue" must be defined and validatable
|
|
2444
|
+
const isConstr = decoratorValidation.Model.isPropertyModel(newModel, propKey);
|
|
2445
|
+
// if propValue !== undefined, null
|
|
2446
|
+
if (propValue && isConstr) {
|
|
2447
|
+
const instance = propValue;
|
|
2448
|
+
const isInvalidModel = typeof instance !== "object" ||
|
|
2449
|
+
!instance.hasErrors ||
|
|
2450
|
+
typeof instance.hasErrors !== "function";
|
|
2451
|
+
if (isInvalidModel) {
|
|
2452
|
+
// propErrors[ValidationKeys.TYPE] =
|
|
2453
|
+
// "Model should be validatable but it's not.";
|
|
2454
|
+
console.warn("Model should be validatable but it's not.");
|
|
2455
|
+
}
|
|
2456
|
+
else {
|
|
2457
|
+
nestedErrors[propKey] = instance.hasErrors(oldModel[prop]);
|
|
1501
2458
|
}
|
|
1502
2459
|
}
|
|
2460
|
+
// Add to the result if we have any errors
|
|
2461
|
+
// Async mode returns a Promise that resolves to undefined when no errors exist
|
|
2462
|
+
if (Object.keys(propErrors).length > 0 || async)
|
|
2463
|
+
result[propKey] = propErrors;
|
|
2464
|
+
// Then merge any nested errors
|
|
2465
|
+
if (!async) {
|
|
2466
|
+
Object.entries(nestedErrors[propKey] || {}).forEach(([key, error]) => {
|
|
2467
|
+
if (error !== undefined) {
|
|
2468
|
+
result[`${propKey}.${key}`] = error;
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
2471
|
+
}
|
|
1503
2472
|
}
|
|
1504
|
-
|
|
2473
|
+
// Synchronous return
|
|
2474
|
+
if (!async) {
|
|
2475
|
+
return (Object.keys(result).length > 0
|
|
2476
|
+
? new decoratorValidation.ModelErrorDefinition(result)
|
|
2477
|
+
: undefined);
|
|
2478
|
+
}
|
|
2479
|
+
const merged = result; // TODO: apply filtering
|
|
2480
|
+
const keys = Object.keys(merged);
|
|
2481
|
+
const promises = Object.values(merged);
|
|
2482
|
+
return Promise.allSettled(promises).then(async (results) => {
|
|
2483
|
+
const result = {};
|
|
2484
|
+
for (const [parentProp, nestedErrPromise] of Object.entries(nestedErrors)) {
|
|
2485
|
+
const nestedPropDecErrors = (await nestedErrPromise);
|
|
2486
|
+
if (nestedPropDecErrors)
|
|
2487
|
+
Object.entries(nestedPropDecErrors).forEach(([nestedProp, nestedPropDecError]) => {
|
|
2488
|
+
if (nestedPropDecError !== undefined) {
|
|
2489
|
+
const nestedKey = [parentProp, nestedProp].join(".");
|
|
2490
|
+
result[nestedKey] = nestedPropDecError;
|
|
2491
|
+
}
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
for (let i = 0; i < results.length; i++) {
|
|
2495
|
+
const key = keys[i];
|
|
2496
|
+
const res = results[i];
|
|
2497
|
+
if (res.status === "fulfilled" && res.value !== undefined) {
|
|
2498
|
+
result[key] = res.value;
|
|
2499
|
+
}
|
|
2500
|
+
else if (res.status === "rejected") {
|
|
2501
|
+
result[key] =
|
|
2502
|
+
res.reason instanceof Error
|
|
2503
|
+
? res.reason.message
|
|
2504
|
+
: String(res.reason || "Validation failed");
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
return Object.keys(result).length > 0
|
|
2508
|
+
? new decoratorValidation.ModelErrorDefinition(result)
|
|
2509
|
+
: undefined;
|
|
2510
|
+
});
|
|
1505
2511
|
}
|
|
1506
2512
|
|
|
1507
2513
|
/**
|
|
1508
|
-
*
|
|
1509
|
-
* @
|
|
1510
|
-
* @
|
|
2514
|
+
* @description Hashes a property value during create or update operations
|
|
2515
|
+
* @summary Callback function used by the hash decorator to apply hashing to a property value
|
|
2516
|
+
* @template M - Type extending Model
|
|
2517
|
+
* @template R - Type extending IRepository
|
|
2518
|
+
* @template V - Type for metadata
|
|
2519
|
+
* @template F - Type extending RepositoryFlags
|
|
2520
|
+
* @template C - Type extending Context
|
|
2521
|
+
* @param {C} context - The operation context
|
|
2522
|
+
* @param {V} data - Metadata for the operation
|
|
2523
|
+
* @param key - The property key to hash
|
|
2524
|
+
* @param {M} model - The model being processed
|
|
2525
|
+
* @param {M} [oldModel] - The previous model state (for updates)
|
|
2526
|
+
* @return {void}
|
|
2527
|
+
* @function hashOnCreateUpdate
|
|
2528
|
+
* @memberOf module:db-decorators
|
|
1511
2529
|
*/
|
|
1512
2530
|
function hashOnCreateUpdate(context, data, key, model, oldModel) {
|
|
1513
2531
|
if (typeof model[key] === "undefined")
|
|
@@ -1517,9 +2535,32 @@
|
|
|
1517
2535
|
return;
|
|
1518
2536
|
model[key] = hash;
|
|
1519
2537
|
}
|
|
2538
|
+
/**
|
|
2539
|
+
* @description Creates a decorator that hashes a property value
|
|
2540
|
+
* @summary Decorator that automatically hashes a property value during create and update operations
|
|
2541
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2542
|
+
* @function hash
|
|
2543
|
+
* @category Property Decorators
|
|
2544
|
+
*/
|
|
1520
2545
|
function hash() {
|
|
1521
2546
|
return reflection.apply(onCreateUpdate(hashOnCreateUpdate), decoratorValidation.propMetadata(Repository.key(DBKeys.HASH), {}));
|
|
1522
2547
|
}
|
|
2548
|
+
/**
|
|
2549
|
+
* @description Composes a property value from other properties during create or update operations
|
|
2550
|
+
* @summary Callback function used by composed decorators to generate a property value from other properties
|
|
2551
|
+
* @template M - Type extending Model
|
|
2552
|
+
* @template R - Type extending IRepository
|
|
2553
|
+
* @template V - Type extending ComposedFromMetadata
|
|
2554
|
+
* @template F - Type extending RepositoryFlags
|
|
2555
|
+
* @template C - Type extending Context
|
|
2556
|
+
* @param {C} context - The operation context
|
|
2557
|
+
* @param {V} data - Metadata for the composition
|
|
2558
|
+
* @param key - The property key to set the composed value on
|
|
2559
|
+
* @param {M} model - The model being processed
|
|
2560
|
+
* @return {void}
|
|
2561
|
+
* @function composedFromCreateUpdate
|
|
2562
|
+
* @memberOf module:db-decorators
|
|
2563
|
+
*/
|
|
1523
2564
|
function composedFromCreateUpdate(context, data, key, model) {
|
|
1524
2565
|
try {
|
|
1525
2566
|
const { args, type, prefix, suffix, separator } = data;
|
|
@@ -1542,6 +2583,19 @@
|
|
|
1542
2583
|
throw new InternalError(`Failed to compose value: ${e}`);
|
|
1543
2584
|
}
|
|
1544
2585
|
}
|
|
2586
|
+
/**
|
|
2587
|
+
* @description Creates a decorator that composes a property value from other properties
|
|
2588
|
+
* @summary Base function for creating property composition decorators
|
|
2589
|
+
* @param {string[]} args - Property names to compose from
|
|
2590
|
+
* @param {boolean} [hashResult=false] - Whether to hash the composed result
|
|
2591
|
+
* @param {string} [separator=DefaultSeparator] - Character used to join the composed values
|
|
2592
|
+
* @param {"keys"|"values"} [type="values"] - Whether to use property keys or values
|
|
2593
|
+
* @param {string} [prefix=""] - Optional prefix to add to the composed value
|
|
2594
|
+
* @param {string} [suffix=""] - Optional suffix to add to the composed value
|
|
2595
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2596
|
+
* @function composedFrom
|
|
2597
|
+
* @category PropertyDecorators
|
|
2598
|
+
*/
|
|
1545
2599
|
function composedFrom(args, hashResult = false, separator = DefaultSeparator, type = "values", prefix = "", suffix = "") {
|
|
1546
2600
|
const data = {
|
|
1547
2601
|
args: args,
|
|
@@ -1559,27 +2613,65 @@
|
|
|
1559
2613
|
decorators.push(hash());
|
|
1560
2614
|
return reflection.apply(...decorators);
|
|
1561
2615
|
}
|
|
2616
|
+
/**
|
|
2617
|
+
* @description Creates a decorator that composes a property value from property keys
|
|
2618
|
+
* @summary Decorator that generates a property value by joining the names of other properties
|
|
2619
|
+
* @param {string[]} args - Property names to compose from
|
|
2620
|
+
* @param {string} [separator=DefaultSeparator] - Character used to join the property names
|
|
2621
|
+
* @param {boolean} [hash=false] - Whether to hash the composed result
|
|
2622
|
+
* @param {string} [prefix=""] - Optional prefix to add to the composed value
|
|
2623
|
+
* @param {string} [suffix=""] - Optional suffix to add to the composed value
|
|
2624
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2625
|
+
* @function composedFromKeys
|
|
2626
|
+
* @category PropertyDecorators
|
|
2627
|
+
*/
|
|
1562
2628
|
function composedFromKeys(args, separator = DefaultSeparator, hash = false, prefix = "", suffix = "") {
|
|
1563
2629
|
return composedFrom(args, hash, separator, "keys", prefix, suffix);
|
|
1564
2630
|
}
|
|
2631
|
+
/**
|
|
2632
|
+
* @description Creates a decorator that composes a property value from property values
|
|
2633
|
+
* @summary Decorator that generates a property value by joining the values of other properties
|
|
2634
|
+
* @param {string[]} args - Property names whose values will be composed
|
|
2635
|
+
* @param {string} [separator=DefaultSeparator] - Character used to join the property values
|
|
2636
|
+
* @param {boolean} [hash=false] - Whether to hash the composed result
|
|
2637
|
+
* @param {string} [prefix=""] - Optional prefix to add to the composed value
|
|
2638
|
+
* @param {string} [suffix=""] - Optional suffix to add to the composed value
|
|
2639
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2640
|
+
* @function composed
|
|
2641
|
+
* @category PropertyDecorators
|
|
2642
|
+
*/
|
|
1565
2643
|
function composed(args, separator = DefaultSeparator, hash = false, prefix = "", suffix = "") {
|
|
1566
2644
|
return composedFrom(args, hash, separator, "values", prefix, suffix);
|
|
1567
2645
|
}
|
|
1568
2646
|
/**
|
|
1569
|
-
* Creates a
|
|
1570
|
-
*
|
|
1571
|
-
* @param {CrudOperations} operation - The type of operation
|
|
1572
|
-
* @
|
|
1573
|
-
*
|
|
2647
|
+
* @description Creates a function that updates a version property during operations
|
|
2648
|
+
* @summary Factory function that generates a callback for incrementing version numbers
|
|
2649
|
+
* @param {CrudOperations} operation - The type of operation (CREATE or UPDATE)
|
|
2650
|
+
* @return {Function} A callback function that updates the version property
|
|
1574
2651
|
* @template M - Type extending Model
|
|
1575
|
-
* @template
|
|
1576
|
-
*
|
|
1577
|
-
* @
|
|
1578
|
-
* @
|
|
1579
|
-
* @
|
|
1580
|
-
* @
|
|
1581
|
-
* @
|
|
1582
|
-
*
|
|
2652
|
+
* @template R - Type extending IRepository
|
|
2653
|
+
* @template V - Type for metadata
|
|
2654
|
+
* @template F - Type extending RepositoryFlags
|
|
2655
|
+
* @template C - Type extending Context
|
|
2656
|
+
* @function versionCreateUpdate
|
|
2657
|
+
* @memberOf module:db-decorators
|
|
2658
|
+
* @mermaid
|
|
2659
|
+
* sequenceDiagram
|
|
2660
|
+
* participant Caller
|
|
2661
|
+
* participant versionCreateUpdate
|
|
2662
|
+
*
|
|
2663
|
+
* Caller->>versionCreateUpdate: operation
|
|
2664
|
+
* versionCreateUpdate-->>Caller: callback function
|
|
2665
|
+
* Note over Caller,versionCreateUpdate: When callback is executed:
|
|
2666
|
+
* Caller->>versionCreateUpdate: context, data, key, model
|
|
2667
|
+
* alt operation is CREATE
|
|
2668
|
+
* versionCreateUpdate->>versionCreateUpdate: set version to 1
|
|
2669
|
+
* else operation is UPDATE
|
|
2670
|
+
* versionCreateUpdate->>versionCreateUpdate: increment version
|
|
2671
|
+
* else invalid operation
|
|
2672
|
+
* versionCreateUpdate->>versionCreateUpdate: throw error
|
|
2673
|
+
* end
|
|
2674
|
+
* versionCreateUpdate-->>Caller: void
|
|
1583
2675
|
*/
|
|
1584
2676
|
function versionCreateUpdate(operation) {
|
|
1585
2677
|
return function versionCreateUpdate(context, data, key, model) {
|
|
@@ -1601,18 +2693,22 @@
|
|
|
1601
2693
|
};
|
|
1602
2694
|
}
|
|
1603
2695
|
/**
|
|
1604
|
-
* @description Creates a decorator for versioning a property in a model
|
|
1605
|
-
* @summary This decorator applies multiple sub-decorators to handle version management during create and update operations
|
|
1606
|
-
*
|
|
1607
|
-
* @
|
|
1608
|
-
*
|
|
1609
|
-
* - Applies a version update on create operations
|
|
1610
|
-
* - Applies a version update on update operations
|
|
1611
|
-
* - Adds metadata indicating this property is used for versioning
|
|
2696
|
+
* @description Creates a decorator for versioning a property in a model
|
|
2697
|
+
* @summary This decorator applies multiple sub-decorators to handle version management during create and update operations
|
|
2698
|
+
* @return {PropertyDecorator} A composite decorator that sets the type to Number, manages version updates, and adds versioning metadata
|
|
2699
|
+
* @function version
|
|
2700
|
+
* @category PropertyDecorators
|
|
1612
2701
|
*/
|
|
1613
2702
|
function version() {
|
|
1614
2703
|
return reflection.apply(decoratorValidation.type(Number.name), onCreate(versionCreateUpdate(exports.OperationKeys.CREATE)), onUpdate(versionCreateUpdate(exports.OperationKeys.UPDATE)), decoratorValidation.propMetadata(Repository.key(DBKeys.VERSION), true));
|
|
1615
2704
|
}
|
|
2705
|
+
/**
|
|
2706
|
+
* @description Creates a decorator that marks a property as transient
|
|
2707
|
+
* @summary Decorator that indicates a property should not be persisted to the database
|
|
2708
|
+
* @return {PropertyDecorator} A decorator that can be applied to class properties
|
|
2709
|
+
* @function transient
|
|
2710
|
+
* @category PropertyDecorators
|
|
2711
|
+
*/
|
|
1616
2712
|
function transient() {
|
|
1617
2713
|
return function transient(model, attribute) {
|
|
1618
2714
|
decoratorValidation.propMetadata(Repository.key(DBKeys.TRANSIENT), true)(model, attribute);
|
|
@@ -1620,21 +2716,81 @@
|
|
|
1620
2716
|
};
|
|
1621
2717
|
}
|
|
1622
2718
|
|
|
2719
|
+
/**
|
|
2720
|
+
* @description Validates the model and checks for errors
|
|
2721
|
+
* @summary Validates the current model state and optionally compares with a previous version
|
|
2722
|
+
* @template M - Type extending Model
|
|
2723
|
+
* @param {M|any} [previousVersion] - Optional previous version of the model for comparison
|
|
2724
|
+
* @param {...any[]} exclusions - Properties to exclude from validation
|
|
2725
|
+
* @return {ModelErrorDefinition|undefined} Error definition if validation fails, undefined otherwise
|
|
2726
|
+
* @function hasErrors
|
|
2727
|
+
* @memberOf module:db-decorators
|
|
2728
|
+
*/
|
|
2729
|
+
// @ts-expect-error Overriding Model prototype method with dynamic conditional return type.
|
|
1623
2730
|
decoratorValidation.Model.prototype.hasErrors = function (previousVersion, ...exclusions) {
|
|
1624
2731
|
if (previousVersion && !(previousVersion instanceof decoratorValidation.Model)) {
|
|
1625
2732
|
exclusions.unshift(previousVersion);
|
|
1626
2733
|
previousVersion = undefined;
|
|
1627
2734
|
}
|
|
1628
|
-
const
|
|
2735
|
+
const async = this.isAsync();
|
|
2736
|
+
const errs = decoratorValidation.validate(this, async, ...exclusions);
|
|
2737
|
+
if (async) {
|
|
2738
|
+
return Promise.resolve(errs).then((resolvedErrs) => {
|
|
2739
|
+
if (resolvedErrs || !previousVersion) {
|
|
2740
|
+
return resolvedErrs;
|
|
2741
|
+
}
|
|
2742
|
+
return validateCompare(previousVersion, this, async, ...exclusions);
|
|
2743
|
+
});
|
|
2744
|
+
}
|
|
1629
2745
|
if (errs || !previousVersion)
|
|
1630
2746
|
return errs;
|
|
1631
|
-
|
|
2747
|
+
// @ts-expect-error Overriding Model prototype method with dynamic conditional return type.
|
|
2748
|
+
return validateCompare(previousVersion, this, async, ...exclusions);
|
|
1632
2749
|
};
|
|
1633
2750
|
|
|
2751
|
+
/**
|
|
2752
|
+
* @description Checks if a model is marked as transient
|
|
2753
|
+
* @summary Determines whether a model class has been decorated with the transient decorator
|
|
2754
|
+
* @template M - Type extending Model
|
|
2755
|
+
* @param {M} model - The model instance to check
|
|
2756
|
+
* @return {boolean} True if the model is transient, false otherwise
|
|
2757
|
+
* @function isTransient
|
|
2758
|
+
* @memberOf module:db-decorators
|
|
2759
|
+
*/
|
|
1634
2760
|
function isTransient(model) {
|
|
1635
2761
|
return !!(Reflect.getMetadata(Repository.key(DBKeys.TRANSIENT), model.constructor) ||
|
|
1636
2762
|
Reflect.getMetadata(Repository.key(DBKeys.TRANSIENT), decoratorValidation.Model.get(model.constructor.name)));
|
|
1637
2763
|
}
|
|
2764
|
+
/**
|
|
2765
|
+
* @description Separates transient properties from a model
|
|
2766
|
+
* @summary Extracts properties marked as transient into a separate object
|
|
2767
|
+
* @template M - Type extending Model
|
|
2768
|
+
* @param {M} model - The model instance to process
|
|
2769
|
+
* @return {Object} Object containing the model without transient properties and a separate transient object
|
|
2770
|
+
* @property {M} model - The model with transient properties removed
|
|
2771
|
+
* @property {Record<string, any>} [transient] - Object containing the transient properties
|
|
2772
|
+
* @function modelToTransient
|
|
2773
|
+
* @memberOf module:db-decorators
|
|
2774
|
+
* @mermaid
|
|
2775
|
+
* sequenceDiagram
|
|
2776
|
+
* participant Caller
|
|
2777
|
+
* participant modelToTransient
|
|
2778
|
+
* participant isTransient
|
|
2779
|
+
* participant getAllPropertyDecoratorsRecursive
|
|
2780
|
+
*
|
|
2781
|
+
* Caller->>modelToTransient: model
|
|
2782
|
+
* modelToTransient->>isTransient: check if model is transient
|
|
2783
|
+
* isTransient-->>modelToTransient: transient status
|
|
2784
|
+
* alt model is not transient
|
|
2785
|
+
* modelToTransient-->>Caller: {model}
|
|
2786
|
+
* else model is transient
|
|
2787
|
+
* modelToTransient->>getAllPropertyDecoratorsRecursive: get transient properties
|
|
2788
|
+
* getAllPropertyDecoratorsRecursive-->>modelToTransient: property decorators
|
|
2789
|
+
* modelToTransient->>modelToTransient: separate properties
|
|
2790
|
+
* modelToTransient->>Model.build: rebuild model without transient props
|
|
2791
|
+
* modelToTransient-->>Caller: {model, transient}
|
|
2792
|
+
* end
|
|
2793
|
+
*/
|
|
1638
2794
|
function modelToTransient(model) {
|
|
1639
2795
|
if (!isTransient(model))
|
|
1640
2796
|
return { model: model };
|
|
@@ -1660,6 +2816,19 @@
|
|
|
1660
2816
|
return result;
|
|
1661
2817
|
}
|
|
1662
2818
|
|
|
2819
|
+
/**
|
|
2820
|
+
* @description Database decorators for TypeScript applications
|
|
2821
|
+
* @summary A comprehensive library providing decorators and utilities for database operations, model definitions, validation, and repository patterns in TypeScript applications
|
|
2822
|
+
* @module db-decorators
|
|
2823
|
+
*/
|
|
2824
|
+
/**
|
|
2825
|
+
* @description Current version of the reflection package
|
|
2826
|
+
* @summary Stores the semantic version number of the package
|
|
2827
|
+
* @const VERSION
|
|
2828
|
+
* @memberOf module:db-decorators
|
|
2829
|
+
*/
|
|
2830
|
+
const VERSION = "0.6.3";
|
|
2831
|
+
|
|
1663
2832
|
exports.BaseError = BaseError;
|
|
1664
2833
|
exports.BaseRepository = BaseRepository;
|
|
1665
2834
|
exports.ConflictError = ConflictError;
|
|
@@ -1679,6 +2848,7 @@
|
|
|
1679
2848
|
exports.SerializationError = SerializationError;
|
|
1680
2849
|
exports.UpdateValidationKeys = UpdateValidationKeys;
|
|
1681
2850
|
exports.UpdateValidator = UpdateValidator;
|
|
2851
|
+
exports.VERSION = VERSION;
|
|
1682
2852
|
exports.ValidationError = ValidationError;
|
|
1683
2853
|
exports.after = after;
|
|
1684
2854
|
exports.afterAny = afterAny;
|
|
@@ -1696,6 +2866,7 @@
|
|
|
1696
2866
|
exports.getAllPropertyDecoratorsRecursive = getAllPropertyDecoratorsRecursive;
|
|
1697
2867
|
exports.getDbDecorators = getDbDecorators;
|
|
1698
2868
|
exports.getHandlerArgs = getHandlerArgs;
|
|
2869
|
+
exports.getValidatableUpdateProps = getValidatableUpdateProps;
|
|
1699
2870
|
exports.hash = hash;
|
|
1700
2871
|
exports.hashOnCreateUpdate = hashOnCreateUpdate;
|
|
1701
2872
|
exports.id = id;
|
|
@@ -1719,9 +2890,11 @@
|
|
|
1719
2890
|
exports.timestampHandler = timestampHandler;
|
|
1720
2891
|
exports.transient = transient;
|
|
1721
2892
|
exports.validateCompare = validateCompare;
|
|
2893
|
+
exports.validateDecorator = validateDecorator;
|
|
2894
|
+
exports.validateDecorators = validateDecorators;
|
|
1722
2895
|
exports.version = version;
|
|
1723
2896
|
exports.versionCreateUpdate = versionCreateUpdate;
|
|
1724
2897
|
exports.wrapMethodWithContext = wrapMethodWithContext;
|
|
1725
2898
|
|
|
1726
2899
|
}));
|
|
1727
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGItZGVjb3JhdG9ycy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9tb2RlbC9jb25zdGFudHMudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9jb25zdGFudHMudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi92YWxpZGF0b3JzL1JlYWRPbmx5VmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vdmFsaWRhdG9ycy9UaW1lc3RhbXBWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi92YWxpZGF0b3JzL1VwZGF0ZVZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL3ZhbGlkYXRpb24udHMiLCIuLi9zcmMvb3BlcmF0aW9ucy9jb25zdGFudHMudHMiLCIuLi9zcmMvb3BlcmF0aW9ucy9PcGVyYXRpb25zUmVnaXN0cnkudHMiLCIuLi9zcmMvb3BlcmF0aW9ucy9PcGVyYXRpb25zLnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L2Vycm9ycy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L3V0aWxzLnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvQ29udGV4dC50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L3dyYXBwZXJzLnRzIiwiLi4vc3JjL2lkZW50aXR5L3V0aWxzLnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvQmFzZVJlcG9zaXRvcnkudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS9SZXBvc2l0b3J5LnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9pZGVudGl0eS9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL21vZGVsL3ZhbGlkYXRpb24udHMiLCIuLi9zcmMvbW9kZWwvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9tb2RlbC9tb2RlbC50cyIsIi4uL3NyYy9tb2RlbC91dGlscy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNb2RlbEtleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgSG9sZHMgdGhlIE1vZGVsIHJlZmxlY3Rpb24ga2V5c1xuICogQGNvbnN0IERCS2V5c1xuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5Nb2RlbFxuICovXG5leHBvcnQgY29uc3QgREJLZXlzID0ge1xuICBSRUZMRUNUOiBgJHtNb2RlbEtleXMuUkVGTEVDVH1wZXJzaXN0ZW5jZS5gLFxuICBSRVBPU0lUT1JZOiBcInJlcG9zaXRvcnlcIixcbiAgQ0xBU1M6IFwiX2NsYXNzXCIsXG4gIElEOiBcImlkXCIsXG4gIElOREVYOiBcImluZGV4XCIsXG4gIFVOSVFVRTogXCJ1bmlxdWVcIixcbiAgU0VSSUFMSVpFOiBcInNlcmlhbGl6ZVwiLFxuICBSRUFET05MWTogXCJyZWFkb25seVwiLFxuICBUSU1FU1RBTVA6IFwidGltZXN0YW1wXCIsXG4gIFRSQU5TSUVOVDogXCJ0cmFuc2llbnRcIixcbiAgSEFTSDogXCJoYXNoXCIsXG4gIENPTVBPU0VEOiBcImNvbXBvc2VkXCIsXG4gIFZFUlNJT046IFwidmVyc2lvblwiLFxuICBPUklHSU5BTDogXCJfX29yaWdpbmFsT2JqXCIsXG59O1xuXG4vKipcbiAqIEBzdW1tYXJ5IFRoZSBkZWZhdWx0IHNlcGFyYXRvciB3aGVuIGNvbmNhdGVuYXRpbmcgaW5kZXhlc1xuICpcbiAqIEBjb25zdCBEZWZhdWx0SW5kZXhTZXBhcmF0b3JcbiAqXG4gKiBAY2F0ZWdvcnkgTWFuYWdlcnNcbiAqIEBzdWJjYXRlZ29yeSBDb25zdGFudHNcbiAqL1xuZXhwb3J0IGNvbnN0IERlZmF1bHRTZXBhcmF0b3IgPSBcIl9cIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBIb2xkcyB0aGUgZGVmYXVsdCB0aW1lc3RhbXAgZGF0ZSBmb3JtYXRcbiAqIEBjb25zdGFudCBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuTW9kZWxcbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVCA9IFwiZGQvTU0veXl5eSBISDptbTpzczpTXCI7XG4iLCJpbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgaG9sZHMgdGhlIGRlZmF1bHQgZXJyb3IgbWVzc2FnZXNcbiAqIEBjb25zdCBERUZBVUxUX0VSUk9SX01FU1NBR0VTXG4gKlxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLk1vZGVsXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0VSUk9SX01FU1NBR0VTID0ge1xuICBJRDoge1xuICAgIElOVkFMSUQ6IFwiVGhpcyBJZCBpcyBpbnZhbGlkXCIsXG4gICAgUkVRVUlSRUQ6IFwiVGhlIElkIGlzIG1hbmRhdG9yeVwiLFxuICB9LFxuICBSRUFET05MWToge1xuICAgIElOVkFMSUQ6IFwiVGhpcyBjYW5ub3QgYmUgdXBkYXRlZFwiLFxuICB9LFxuICBUSU1FU1RBTVA6IHtcbiAgICBSRVFVSVJFRDogXCJUaW1lc3RhbXAgaXMgTWFuZGF0b3J5XCIsXG4gICAgREFURTogXCJUaGUgVGltZXN0YW1wIG11c3QgdGhlIGEgdmFsaWQgZGF0ZVwiLFxuICAgIElOVkFMSUQ6IFwiVGhpcyB2YWx1ZSBtdXN0IGFsd2F5cyBpbmNyZWFzZVwiLFxuICB9LFxufTtcblxuLyoqXG4gKiBAc3VtbWFyeSBVcGRhdGUgcmVmbGVjdGlvbiBrZXlzXG4gKiBAY29uc3QgVXBkYXRlVmFsaWRhdGlvbktleXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5PcGVyYXRpb25zXG4gKi9cbmV4cG9ydCBjb25zdCBVcGRhdGVWYWxpZGF0aW9uS2V5cyA9IHtcbiAgUkVGTEVDVDogXCJkYi51cGRhdGUudmFsaWRhdGlvbi5cIixcbiAgVElNRVNUQU1QOiBEQktleXMuVElNRVNUQU1QLFxuICBSRUFET05MWTogREJLZXlzLlJFQURPTkxZLFxufTtcbiIsImltcG9ydCB7IHZhbGlkYXRvciwgVmFsaWRhdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVXBkYXRlVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBpc0VxdWFsIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgVmFsaWRhdG9yIGZvciB0aGUge0BsaW5rIHJlYWRvbmx5fSBkZWNvcmF0b3JcbiAqXG4gKiBAY2xhc3MgUmVhZE9ubHlWYWxpZGF0b3JcbiAqIEBleHRlbmRzIFZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVXBkYXRlVmFsaWRhdGlvbktleXMuUkVBRE9OTFkpXG5leHBvcnQgY2xhc3MgUmVhZE9ubHlWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihERUZBVUxUX0VSUk9SX01FU1NBR0VTLlJFQURPTkxZLklOVkFMSUQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbmhlcml0RG9jXG4gICAqL1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGhhc0Vycm9ycyh2YWx1ZTogYW55LCAuLi5hcmdzOiBhbnlbXSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSB2YWx1ZSBoYXMgbm90IGNoYW5nZWRcbiAgICogQHBhcmFtIHthbnl9IHZhbHVlXG4gICAqIEBwYXJhbSB7YW55fSBvbGRWYWx1ZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlIG92ZXJyaWRlXG4gICAqL1xuICBwdWJsaWMgdXBkYXRlSGFzRXJyb3JzKFxuICAgIHZhbHVlOiBhbnksXG4gICAgb2xkVmFsdWU6IGFueSxcbiAgICBtZXNzYWdlPzogc3RyaW5nLFxuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICByZXR1cm4gaXNFcXVhbCh2YWx1ZSwgb2xkVmFsdWUpXG4gICAgICA/IHVuZGVmaW5lZFxuICAgICAgOiB0aGlzLmdldE1lc3NhZ2UobWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UpO1xuICB9XG59XG4iLCJpbXBvcnQgeyB2YWxpZGF0b3IsIFZhbGlkYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFVwZGF0ZVZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFZhbGlkYXRlcyB0aGUgdXBkYXRlIG9mIGEgdGltZXN0YW1wXG4gKlxuICogQGNsYXNzIFRpbWVzdGFtcFZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihVcGRhdGVWYWxpZGF0aW9uS2V5cy5USU1FU1RBTVApXG5leHBvcnQgY2xhc3MgVGltZXN0YW1wVmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuSU5WQUxJRCk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIGhhc0Vycm9ycyh2YWx1ZTogYW55LCAuLi5hcmdzOiBhbnlbXSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGVIYXNFcnJvcnMoXG4gICAgdmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudW1iZXIsXG4gICAgb2xkVmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudW1iZXIsXG4gICAgbWVzc2FnZT86IHN0cmluZ1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICBtZXNzYWdlID0gbWVzc2FnZSB8fCB0aGlzLmdldE1lc3NhZ2UobWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UpO1xuXG4gICAgdHJ5IHtcbiAgICAgIHZhbHVlID0gbmV3IERhdGUodmFsdWUpO1xuICAgICAgb2xkVmFsdWUgPSBuZXcgRGF0ZShvbGRWYWx1ZSk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlIDw9IG9sZFZhbHVlID8gbWVzc2FnZSA6IHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyBhcyBEZWNvcmF0b3JNZXNzYWdlcyxcbiAgVmFsaWRhdG9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgQmFzZSBjbGFzcyBmb3IgYW4gVXBkYXRlIHZhbGlkYXRvclxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gZXJyb3IgbWVzc2FnZS4gZGVmYXVsdHMgdG8ge0BsaW5rIERlY29yYXRvck1lc3NhZ2VzI0RFRkFVTFR9XG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBbYWNjZXB0ZWRUeXBlc10gdGhlIGFjY2VwdGVkIHZhbHVlIHR5cGVzIGJ5IHRoZSBkZWNvcmF0b3JcbiAqXG4gKiBAY2xhc3MgVXBkYXRlVmFsaWRhdG9yXG4gKiBAYWJzdHJhY3RcbiAqIEBleHRlbmRzIFZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBVcGRhdGVWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3Ige1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgbWVzc2FnZTogc3RyaW5nID0gRGVjb3JhdG9yTWVzc2FnZXMuREVGQVVMVCxcbiAgICAuLi5hY2NlcHRlZFR5cGVzOiBzdHJpbmdbXVxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlLCAuLi5hY2NlcHRlZFR5cGVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSB2YWxpZGF0ZXMgYSB2YWx1ZSBieSBjb21wYXJpbmcgdG8gaXRzIG9sZCB2ZXJzaW9uXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZVxuICAgKiBAcGFyYW0ge2FueX0gb2xkVmFsdWVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJnc1xuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHVwZGF0ZUhhc0Vycm9ycyhcbiAgICB2YWx1ZTogYW55LFxuICAgIG9sZFZhbHVlOiBhbnksXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkO1xufVxuIiwiaW1wb3J0IHtcbiAgVmFsaWRhdG9yLFxuICBWYWxpZGF0aW9uLFxuICBWYWxpZGF0b3JEZWZpbml0aW9uLFxuICBJVmFsaWRhdG9yUmVnaXN0cnksXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFVwZGF0ZVZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cblZhbGlkYXRpb24udXBkYXRlS2V5ID0gZnVuY3Rpb24gKGtleTogc3RyaW5nKSB7XG4gIHJldHVybiBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNUICsga2V5O1xufTtcblxuZGVjbGFyZSBtb2R1bGUgXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICBkZWNsYXJlIGNsYXNzIFZhbGlkYXRpb24ge1xuICAgIHByaXZhdGUgc3RhdGljIGFjdGluZ1ZhbGlkYXRvclJlZ2lzdHJ5PztcbiAgICBwcml2YXRlIGNvbnN0cnVjdG9yKCk7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgYWN0aW5nIFZhbGlkYXRvclJlZ2lzdHJ5XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0lWYWxpZGF0b3JSZWdpc3RyeX0gdmFsaWRhdG9yUmVnaXN0cnkgdGhlIG5ldyBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgdmFsaWRhdG9yIFJlZ2lzdHJ5XG4gICAgICogQHBhcmFtIHtmdW5jdGlvbihWYWxpZGF0b3IpOiBWYWxpZGF0b3J9IFttaWdyYXRpb25IYW5kbGVyXSB0aGUgbWV0aG9kIHRvIG1hcCB0aGUgdmFsaWRhdG9yIGlmIHJlcXVpcmVkO1xuICAgICAqL1xuICAgIHN0YXRpYyBzZXRSZWdpc3RyeShcbiAgICAgIHZhbGlkYXRvclJlZ2lzdHJ5OiBJVmFsaWRhdG9yUmVnaXN0cnk8VmFsaWRhdG9yPixcbiAgICAgIG1pZ3JhdGlvbkhhbmRsZXI/OiAodmFsaWRhdG9yOiBWYWxpZGF0b3IpID0+IFZhbGlkYXRvclxuICAgICk6IHZvaWQ7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgUmV0dXJucyB0aGUgY3VycmVudCBWYWxpZGF0b3JSZWdpc3RyeVxuICAgICAqXG4gICAgICogQHJldHVybiBJVmFsaWRhdG9yUmVnaXN0cnksIGRlZmF1bHRzIHRvIHtAbGluayBWYWxpZGF0b3JSZWdpc3RyeX1cbiAgICAgKi9cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRSZWdpc3RyeTtcbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYSB2YWxpZGF0b3JcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWxpZGF0b3JLZXkgb25lIG9mIHRoZSB7QGxpbmsgVmFsaWRhdGlvbktleXN9XG4gICAgICogQHJldHVybiB7VmFsaWRhdG9yIHwgdW5kZWZpbmVkfSB0aGUgcmVnaXN0ZXJlZCBWYWxpZGF0b3Igb3IgdW5kZWZpbmVkIGlmIHRoZXJlIGlzIG5vbm8gbWF0Y2hpbmcgdGhlIHByb3ZpZGVkIGtleVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXQ8VCBleHRlbmRzIFZhbGlkYXRvcj4odmFsaWRhdG9yS2V5OiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkO1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJlZ2lzdGVycyB0aGUgcHJvdmlkZWQgdmFsaWRhdG9ycyBvbnRvIHRoZSByZWdpc3RyeVxuICAgICAqXG4gICAgICogQHBhcmFtIHtUW10gfCBWYWxpZGF0b3JEZWZpbml0aW9uW119IHZhbGlkYXRvclxuICAgICAqL1xuICAgIHN0YXRpYyByZWdpc3RlcjxUIGV4dGVuZHMgVmFsaWRhdG9yPihcbiAgICAgIC4uLnZhbGlkYXRvcjogKFZhbGlkYXRvckRlZmluaXRpb24gfCBUKVtdXG4gICAgKTogdm9pZDtcbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBCdWlsZHMgdGhlIGtleSB0byBzdG9yZSBhcyBNZXRhZGF0YSB1bmRlciBSZWZsZWN0aW9uc1xuICAgICAqIEBkZXNjcmlwdGlvbiBjb25jYXRlbmF0ZXMge0BsaW5rIFZhbGlkYXRpb25LZXlzI1JFRkxFQ1R9IHdpdGggdGhlIHByb3ZpZGVkIGtleVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleVxuICAgICAqL1xuICAgIHN0YXRpYyBrZXkoa2V5OiBzdHJpbmcpOiBzdHJpbmc7XG5cbiAgICBzdGF0aWMgdXBkYXRlS2V5KGtleTogc3RyaW5nKTogc3RyaW5nO1xuICB9XG59XG4iLCIvKipcbiAqIEBzdW1tYXJ5IFNldCBvZiBjb25zdGFudHMgdG8gZGVmaW5lIGRiIENSVUQgb3BlcmF0aW9ucyBhbmQgdGhlaXIgZXF1aXZhbGVudCAnb24nIGFuZCAnYWZ0ZXInIHBoYXNlc1xuICogQGNvbnN0IE9wZXJhdGlvbktleXNcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuT3BlcmF0aW9uc1xuICovXG5leHBvcnQgZW51bSBPcGVyYXRpb25LZXlzIHtcbiAgUkVGTEVDVCA9IFwiZGVjYWYubW9kZWwuZGIub3BlcmF0aW9ucy5cIixcbiAgQ1JFQVRFID0gXCJjcmVhdGVcIixcbiAgUkVBRCA9IFwicmVhZFwiLFxuICBVUERBVEUgPSBcInVwZGF0ZVwiLFxuICBERUxFVEUgPSBcImRlbGV0ZVwiLFxuICBPTiA9IFwib24uXCIsXG4gIEFGVEVSID0gXCJhZnRlci5cIixcbn1cblxuZXhwb3J0IHR5cGUgQ3J1ZE9wZXJhdGlvbnMgPVxuICB8IE9wZXJhdGlvbktleXMuQ1JFQVRFXG4gIHwgT3BlcmF0aW9uS2V5cy5SRUFEXG4gIHwgT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgfCBPcGVyYXRpb25LZXlzLkRFTEVURTtcblxuZXhwb3J0IGVudW0gQnVsa0NydWRPcGVyYXRpb25LZXlzIHtcbiAgQ1JFQVRFX0FMTCA9IFwiY3JlYXRlQWxsXCIsXG4gIFJFQURfQUxMID0gXCJyZWFkQWxsXCIsXG4gIFVQREFURV9BTEwgPSBcInVwZGF0ZUFsbFwiLFxuICBERUxFVEVfQUxMID0gXCJkZWxldGVBbGxcIixcbn1cblxuZXhwb3J0IHR5cGUgQnVsa0NydWRPcGVyYXRpb25zID1cbiAgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuQ1JFQVRFX0FMTFxuICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5SRUFEX0FMTFxuICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5VUERBVEVfQUxMXG4gIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzLkRFTEVURV9BTEw7XG5cbi8qKlxuICogQHN1bW1hcnkgTWFwcyBvdXQgZ3JvdXBzIG9mIENSVUQgb3BlcmF0aW9ucyBmb3IgZWFzaWVyIG1hcHBpbmcgb2YgZGVjb3JhdG9yc1xuICpcbiAqIEBjb25zdGFudCBEQk9wZXJhdGlvbnNcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuT3BlcmF0aW9uc1xuICovXG5leHBvcnQgY29uc3QgREJPcGVyYXRpb25zOiBSZWNvcmQ8c3RyaW5nLCBDcnVkT3BlcmF0aW9uc1tdPiA9IHtcbiAgQ1JFQVRFOiBbT3BlcmF0aW9uS2V5cy5DUkVBVEVdLFxuICBSRUFEOiBbT3BlcmF0aW9uS2V5cy5SRUFEXSxcbiAgVVBEQVRFOiBbT3BlcmF0aW9uS2V5cy5VUERBVEVdLFxuICBERUxFVEU6IFtPcGVyYXRpb25LZXlzLkRFTEVURV0sXG4gIENSRUFURV9VUERBVEU6IFtPcGVyYXRpb25LZXlzLkNSRUFURSwgT3BlcmF0aW9uS2V5cy5VUERBVEVdLFxuICBSRUFEX0NSRUFURTogW09wZXJhdGlvbktleXMuUkVBRCwgT3BlcmF0aW9uS2V5cy5DUkVBVEVdLFxuICBBTEw6IFtcbiAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gIF0sXG59O1xuIiwiaW1wb3J0IHsgT3BlcmF0aW9uSGFuZGxlciB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0lSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBPcGVyYXRpb25zIH0gZnJvbSBcIi4vT3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3R5cGVzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgSG9sZHMgdGhlIHJlZ2lzdGVyZWQgb3BlcmF0aW9uIGhhbmRsZXJzXG4gKlxuICogQGNsYXNzIE9wZXJhdGlvbnNSZWdpc3RyeVxuICogQGltcGxlbWVudHMgSVJlZ2lzdHJ5PE9wZXJhdGlvbkhhbmRsZXI8YW55Pj5cbiAqXG4gKiBAc2VlIE9wZXJhdGlvbkhhbmRsZXJcbiAqXG4gKiBAY2F0ZWdvcnkgT3BlcmF0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgT3BlcmF0aW9uc1JlZ2lzdHJ5IHtcbiAgcHJpdmF0ZSByZWFkb25seSBjYWNoZTogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBSZWNvcmQ8XG4gICAgICBzdHJpbmcgfCBzeW1ib2wsXG4gICAgICBSZWNvcmQ8c3RyaW5nLCBSZWNvcmQ8c3RyaW5nLCBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBhbnksIGFueSwgYW55Pj4+XG4gICAgPlxuICA+ID0ge307XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHJldHJpZXZlcyBhbiB7QGxpbmsgT3BlcmF0aW9uSGFuZGxlcn0gaWYgaXQgZXhpc3RzXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0YXJnZXRcbiAgICogQHBhcmFtIHtzdHJpbmd9IHByb3BLZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wZXJhdGlvblxuICAgKiBAcGFyYW0gYWNjdW1cbiAgICogQHJldHVybiB7T3BlcmF0aW9uSGFuZGxlciB8IHVuZGVmaW5lZH1cbiAgICovXG4gIGdldDxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICAgIFYsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbiAgPihcbiAgICB0YXJnZXQ6IHN0cmluZyB8IFJlY29yZDxzdHJpbmcsIGFueT4sXG4gICAgcHJvcEtleTogc3RyaW5nLFxuICAgIG9wZXJhdGlvbjogc3RyaW5nLFxuICAgIGFjY3VtPzogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPltdXG4gICk6IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz5bXSB8IHVuZGVmaW5lZCB7XG4gICAgYWNjdW0gPSBhY2N1bSB8fCBbXTtcbiAgICBsZXQgbmFtZTtcbiAgICB0cnkge1xuICAgICAgbmFtZSA9IHR5cGVvZiB0YXJnZXQgPT09IFwic3RyaW5nXCIgPyB0YXJnZXQgOiB0YXJnZXQuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIGFjY3VtLnVuc2hpZnQoXG4gICAgICAgIC4uLk9iamVjdC52YWx1ZXModGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dIHx8IFtdKVxuICAgICAgKTtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHR5cGVvZiB0YXJnZXQgPT09IFwic3RyaW5nXCIgfHxcbiAgICAgICAgdGFyZ2V0ID09PSBPYmplY3QucHJvdG90eXBlIHx8XG4gICAgICAgIE9iamVjdC5nZXRQcm90b3R5cGVPZih0YXJnZXQpID09PSBPYmplY3QucHJvdG90eXBlXG4gICAgICApXG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9XG5cbiAgICBsZXQgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGFyZ2V0KTtcbiAgICBpZiAocHJvdG8uY29uc3RydWN0b3IubmFtZSA9PT0gbmFtZSkgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2V0PE0sIFIsIFYsIEYsIEM+KHByb3RvLCBwcm9wS2V5LCBvcGVyYXRpb24sIGFjY3VtKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgYW4ge0BsaW5rIE9wZXJhdGlvbkhhbmRsZXJ9XG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcn0gaGFuZGxlclxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3BlcmF0aW9uXG4gICAqIEBwYXJhbSB7e319IHRhcmdldFxuICAgKiBAcGFyYW0ge3N0cmluZyB8IHN5bWJvbH0gcHJvcEtleVxuICAgKi9cbiAgcmVnaXN0ZXI8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWLFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gID4oXG4gICAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPixcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgdGFyZ2V0OiBNLFxuICAgIHByb3BLZXk6IHN0cmluZyB8IHN5bWJvbFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBuYW1lID0gdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgY29uc3QgaGFuZGxlck5hbWUgPSBPcGVyYXRpb25zLmdldEhhbmRsZXJOYW1lKGhhbmRsZXIpO1xuXG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdKSB0aGlzLmNhY2hlW25hbWVdID0ge307XG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldKSB0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldID0ge307XG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl0pXG4gICAgICB0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl0gPSB7fTtcbiAgICBpZiAodGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dW2hhbmRsZXJOYW1lXSkgcmV0dXJuO1xuICAgIHRoaXMuY2FjaGVbbmFtZV1bcHJvcEtleV1bb3BlcmF0aW9uXVtoYW5kbGVyTmFtZV0gPSBoYW5kbGVyO1xuICB9XG59XG4iLCJpbXBvcnQgeyBIYXNoaW5nLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IE9wZXJhdGlvbkhhbmRsZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uc1JlZ2lzdHJ5IH0gZnJvbSBcIi4vT3BlcmF0aW9uc1JlZ2lzdHJ5XCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3R5cGVzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgU3RhdGljIGNsYXNzIGhvbGRpbmcgY29tbW9uIE9wZXJhdGlvbiBGdW5jdGlvbmFsaXR5XG4gKlxuICogQGNsYXNzIE9wZXJhdGlvbnNcbiAqXG4gKiBAY2F0ZWdvcnkgT3BlcmF0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgT3BlcmF0aW9ucyB7XG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdHJ5OiBPcGVyYXRpb25zUmVnaXN0cnk7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgc3RhdGljIGdldEhhbmRsZXJOYW1lKGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIGFueSwgYW55LCBhbnk+KSB7XG4gICAgaWYgKGhhbmRsZXIubmFtZSkgcmV0dXJuIGhhbmRsZXIubmFtZTtcblxuICAgIGNvbnNvbGUud2FybihcbiAgICAgIFwiSGFuZGxlciBuYW1lIG5vdCBkZWZpbmVkLiBBIG5hbWUgd2lsbCBiZSBnZW5lcmF0ZWQsIGJ1dCB0aGlzIGlzIG5vdCBkZXNpcmFibGUuIHBsZWFzZSBhdm9pZCB1c2luZyBhbm9ueW1vdXMgZnVuY3Rpb25zXCJcbiAgICApO1xuICAgIHJldHVybiBIYXNoaW5nLmhhc2goaGFuZGxlci50b1N0cmluZygpKTtcbiAgfVxuXG4gIHN0YXRpYyBrZXkoc3RyOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gT3BlcmF0aW9uS2V5cy5SRUZMRUNUICsgc3RyO1xuICB9XG5cbiAgc3RhdGljIGdldDxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICAgIFYgPSBvYmplY3QsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID4oXG4gICAgdGFyZ2V0TmFtZTogc3RyaW5nIHwgUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBwcm9wS2V5OiBzdHJpbmcsXG4gICAgb3BlcmF0aW9uOiBzdHJpbmdcbiAgKSB7XG4gICAgcmV0dXJuIE9wZXJhdGlvbnMucmVnaXN0cnkuZ2V0PE0sIFIsIFYsIEYsIEM+KFxuICAgICAgdGFyZ2V0TmFtZSxcbiAgICAgIHByb3BLZXksXG4gICAgICBvcGVyYXRpb25cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0T3BSZWdpc3RyeSgpIHtcbiAgICBpZiAoIU9wZXJhdGlvbnMucmVnaXN0cnkpIE9wZXJhdGlvbnMucmVnaXN0cnkgPSBuZXcgT3BlcmF0aW9uc1JlZ2lzdHJ5KCk7XG4gICAgcmV0dXJuIE9wZXJhdGlvbnMucmVnaXN0cnk7XG4gIH1cblxuICBzdGF0aWMgcmVnaXN0ZXI8ViBleHRlbmRzIE1vZGVsPihcbiAgICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPFYsIGFueSwgYW55PixcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgdGFyZ2V0OiBWLFxuICAgIHByb3BLZXk6IHN0cmluZyB8IHN5bWJvbFxuICApIHtcbiAgICBPcGVyYXRpb25zLmdldE9wUmVnaXN0cnkoKS5yZWdpc3RlcihcbiAgICAgIGhhbmRsZXIgYXMgYW55LFxuICAgICAgb3BlcmF0aW9uLFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcEtleVxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIElkT3BlcmF0aW9uSGFuZGxlcixcbiAgT3BlcmF0aW9uSGFuZGxlcixcbiAgU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyLFxuICBVcGRhdGVPcGVyYXRpb25IYW5kbGVyLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgREJPcGVyYXRpb25zLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25zIH0gZnJvbSBcIi4vT3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgYXBwbHkgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IHByb3BNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuZnVuY3Rpb24gaGFuZGxlKFxuICBvcDogT3BlcmF0aW9uS2V5cyxcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgYW55LCBhbnksIGFueT5cbikge1xuICByZXR1cm4gKHRhcmdldDogYW55LCBwcm9wZXJ0eUtleTogc3RyaW5nKSA9PiB7XG4gICAgT3BlcmF0aW9ucy5yZWdpc3RlcihoYW5kbGVyLCBvcCwgdGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gIH07XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgb24gdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFfVxuICpcbiAqIEBwYXJhbSB7T25PcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIGluIG9yZGVyIHRvIHRoZSBoYW5kbGVyIG1ldGhvZFxuICpcbiAqIEBzZWUgb25cbiAqXG4gKiBAZnVuY3Rpb24gb25DcmVhdGVVcGRhdGVcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25DcmVhdGVVcGRhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6XG4gICAgfCBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PlxuICAgIHwgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURSwgaGFuZGxlciwgZGF0YSk7XG59XG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IG9uIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuVVBEQVRFfVxuICpcbiAqIEBwYXJhbSB7T25PcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIGluIG9yZGVyIHRvIHRoZSBoYW5kbGVyIG1ldGhvZFxuICpcbiAqIEBzZWUgb25cbiAqXG4gKiBAZnVuY3Rpb24gb25VcGRhdGVcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5VUERBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBvbiB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zLkNSRUFURX1cbiAqXG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBAc2VlIG9uXG4gKlxuICogQGZ1bmN0aW9uIG9uQ3JlYXRlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uQ3JlYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLkNSRUFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgb24gdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5SRUFEfVxuICpcbiAqIEBwYXJhbSB7T25PcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICpcbiAqIEBzZWUgb25cbiAqXG4gKiBAZnVuY3Rpb24gb25SZWFkXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uUmVhZDxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogSWRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLlJFQUQsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IG9uIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuREVMRVRFfVxuICpcbiAqIEBwYXJhbSB7T25PcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICpcbiAqIEBzZWUgb25cbiAqXG4gKiBAZnVuY3Rpb24gb25EZWxldGVcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25EZWxldGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YTogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuREVMRVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBvbiB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zLkRFTEVURX1cbiAqXG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBAc2VlIG9uXG4gKlxuICogQGZ1bmN0aW9uIG9uQW55XG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uQW55PFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLkFMTCwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgb24gdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9uc31cbiAqXG4gKiBAcGFyYW0ge09wZXJhdGlvbktleXNbXSB8IERCT3BlcmF0aW9uc30gb3AgT25lIG9mIHtAbGluayBEQk9wZXJhdGlvbnN9XG4gKiBAcGFyYW0ge09uT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBleDogaGFuZGxlciguLi5hcmdzLCAuLi5wcm9wcy5tYXAocCA9PiB0YXJnZXRbcF0pKVxuICpcbiAqIEBmdW5jdGlvbiBvblxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbjxWID0gb2JqZWN0PihcbiAgb3A6IE9wZXJhdGlvbktleXNbXSA9IERCT3BlcmF0aW9ucy5BTEwsXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb3BlcmF0aW9uKE9wZXJhdGlvbktleXMuT04sIG9wLCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgYWZ0ZXIgdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFfVxuICpcbiAqIEBwYXJhbSB7QWZ0ZXJPcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICpcbiAqIEBzZWUgYWZ0ZXJcbiAqXG4gKiBAZnVuY3Rpb24gYWZ0ZXJDcmVhdGVVcGRhdGVcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJDcmVhdGVVcGRhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6XG4gICAgfCBTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PlxuICAgIHwgVXBkYXRlT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBhZnRlciB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zLlVQREFURX1cbiAqXG4gKiBAcGFyYW0ge0FmdGVyT3BlcmF0aW9uSGFuZGxlcjxhbnk+fSBoYW5kbGVyIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIGRhdGFcbiAqXG4gKiBAc2VlIGFmdGVyXG4gKlxuICogQGZ1bmN0aW9uIGFmdGVyVXBkYXRlXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gYWZ0ZXIoREJPcGVyYXRpb25zLlVQREFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgYWZ0ZXIgdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5DUkVBVEV9XG4gKlxuICogQHBhcmFtIHtBZnRlck9wZXJhdGlvbkhhbmRsZXI8YW55Pn0gaGFuZGxlciBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSBkYXRhXG4gKlxuICogQHNlZSBhZnRlclxuICpcbiAqIEBmdW5jdGlvbiBhZnRlckNyZWF0ZVxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlckNyZWF0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gYWZ0ZXIoREJPcGVyYXRpb25zLkNSRUFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgYWZ0ZXIgdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5SRUFEfVxuICpcbiAqIEBwYXJhbSB7QWZ0ZXJPcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIGluIG9yZGVyIHRvIHRoZSBoYW5kbGVyIG1ldGhvZFxuICpcbiAqIEBzZWUgYWZ0ZXJcbiAqXG4gKiBAZnVuY3Rpb24gYWZ0ZXJSZWFkXG4gKlxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyUmVhZDxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5SRUFELCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW91ciB0byBzZXQgYWZ0ZXIgdGhlIGRlZmluZWQge0BsaW5rIERCT3BlcmF0aW9ucy5ERUxFVEV9XG4gKlxuICogQHBhcmFtIHtBZnRlck9wZXJhdGlvbkhhbmRsZXI8YW55Pn0gaGFuZGxlciBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSBkYXRhXG4gKiBAcGFyYW0ge2FueVtdfSBbYXJnc10gQXJndW1lbnRzIHRoYXQgd2lsbCBiZSBwYXNzZWQgaW4gb3JkZXIgdG8gdGhlIGhhbmRsZXIgbWV0aG9kXG4gKlxuICogQHNlZSBhZnRlclxuICpcbiAqIEBmdW5jdGlvbiBhZnRlckRlbGV0ZVxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlckRlbGV0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5ERUxFVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvdXIgdG8gc2V0IGFmdGVyIHRoZSBkZWZpbmVkIHtAbGluayBEQk9wZXJhdGlvbnMuREVMRVRFfVxuICpcbiAqIEBwYXJhbSB7QWZ0ZXJPcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0gZGF0YVxuICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdIEFyZ3VtZW50cyB0aGF0IHdpbGwgYmUgcGFzc2VkIGluIG9yZGVyIHRvIHRoZSBoYW5kbGVyIG1ldGhvZFxuICpcbiAqIEBzZWUgYWZ0ZXJcbiAqXG4gKiBAZnVuY3Rpb24gYWZ0ZXJBbnlcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJBbnk8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuQUxMLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3VyIHRvIHNldCBvbiB0aGUgZGVmaW5lZCB7QGxpbmsgREJPcGVyYXRpb25zfVxuICpcbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c1tdIHwgREJPcGVyYXRpb25zfSBvcCBPbmUgb2Yge0BsaW5rIERCT3BlcmF0aW9uc31cbiAqIEBwYXJhbSB7QWZ0ZXJPcGVyYXRpb25IYW5kbGVyPGFueT59IGhhbmRsZXIgVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKlxuICogZXg6IGhhbmRsZXIoLi4uYXJncywgLi4ucHJvcHMubWFwKHAgPT4gdGFyZ2V0W3BdKSlcbiAqXG4gKiBAcGFyYW0gZGF0YVxuICogQHBhcmFtIGFyZ3NcbiAqIEBmdW5jdGlvbiBhZnRlclxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlcjxWID0gb2JqZWN0PihcbiAgb3A6IE9wZXJhdGlvbktleXNbXSA9IERCT3BlcmF0aW9ucy5BTEwsXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YT86IFZcbikge1xuICByZXR1cm4gb3BlcmF0aW9uKE9wZXJhdGlvbktleXMuQUZURVIsIG9wLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9wZXJhdGlvbjxWID0gb2JqZWN0PihcbiAgYmFzZU9wOiBPcGVyYXRpb25LZXlzLk9OIHwgT3BlcmF0aW9uS2V5cy5BRlRFUixcbiAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzW10gPSBEQk9wZXJhdGlvbnMuQUxMLFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGFUb0FkZD86IFZcbikge1xuICByZXR1cm4gKHRhcmdldDogb2JqZWN0LCBwcm9wZXJ0eUtleT86IGFueSkgPT4ge1xuICAgIGNvbnN0IG5hbWUgPSB0YXJnZXQuY29uc3RydWN0b3IubmFtZTtcbiAgICBjb25zdCBkZWNvcmF0b3JzID0gb3BlcmF0aW9uLnJlZHVjZSgoYWNjdW06IGFueVtdLCBvcCkgPT4ge1xuICAgICAgY29uc3QgY29tcG91bmRLZXkgPSBiYXNlT3AgKyBvcDtcbiAgICAgIGxldCBkYXRhID0gUmVmbGVjdC5nZXRNZXRhZGF0YShcbiAgICAgICAgT3BlcmF0aW9ucy5rZXkoY29tcG91bmRLZXkpLFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHByb3BlcnR5S2V5XG4gICAgICApO1xuICAgICAgaWYgKCFkYXRhKVxuICAgICAgICBkYXRhID0ge1xuICAgICAgICAgIG9wZXJhdGlvbjogb3AsXG4gICAgICAgICAgaGFuZGxlcnM6IHt9LFxuICAgICAgICB9O1xuXG4gICAgICBjb25zdCBoYW5kbGVyS2V5ID0gT3BlcmF0aW9ucy5nZXRIYW5kbGVyTmFtZShoYW5kbGVyKTtcblxuICAgICAgaWYgKFxuICAgICAgICAhZGF0YS5oYW5kbGVyc1tuYW1lXSB8fFxuICAgICAgICAhZGF0YS5oYW5kbGVyc1tuYW1lXVtwcm9wZXJ0eUtleV0gfHxcbiAgICAgICAgIShoYW5kbGVyS2V5IGluIGRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldKVxuICAgICAgKSB7XG4gICAgICAgIGRhdGEuaGFuZGxlcnNbbmFtZV0gPSBkYXRhLmhhbmRsZXJzW25hbWVdIHx8IHt9O1xuICAgICAgICBkYXRhLmhhbmRsZXJzW25hbWVdW3Byb3BlcnR5S2V5XSA9XG4gICAgICAgICAgZGF0YS5oYW5kbGVyc1tuYW1lXVtwcm9wZXJ0eUtleV0gfHwge307XG4gICAgICAgIGRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldW2hhbmRsZXJLZXldID0ge1xuICAgICAgICAgIGRhdGE6IGRhdGFUb0FkZCxcbiAgICAgICAgfTtcblxuICAgICAgICBhY2N1bS5wdXNoKFxuICAgICAgICAgIGhhbmRsZShjb21wb3VuZEtleSBhcyBPcGVyYXRpb25LZXlzLCBoYW5kbGVyKSxcbiAgICAgICAgICBwcm9wTWV0YWRhdGEoT3BlcmF0aW9ucy5rZXkoY29tcG91bmRLZXkpLCBkYXRhKVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sIFtdKTtcbiAgICByZXR1cm4gYXBwbHkoLi4uZGVjb3JhdG9ycykodGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gIH07XG59XG4iLCIvKipcbiAqIEBzdW1tYXJ5IEJhc2UgRXJyb3JcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbXNnIHRoZSBlcnJvciBtZXNzYWdlXG4gKlxuICogQGNsYXNzIEJhc2VETFRFcnJvclxuICogQGV4dGVuZHMgRXJyb3JcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgcmVhZG9ubHkgY29kZSE6IG51bWJlcjtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKG5hbWU6IHN0cmluZywgbXNnOiBzdHJpbmcgfCBFcnJvciwgY29kZTogbnVtYmVyID0gNTAwKSB7XG4gICAgaWYgKG1zZyBpbnN0YW5jZW9mIEJhc2VFcnJvcikgcmV0dXJuIG1zZztcbiAgICBjb25zdCBtZXNzYWdlID0gYFske25hbWV9XSAke21zZyBpbnN0YW5jZW9mIEVycm9yID8gbXNnLm1lc3NhZ2UgOiBtc2d9YDtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLmNvZGUgPSBjb2RlO1xuICAgIGlmIChtc2cgaW5zdGFuY2VvZiBFcnJvcikgdGhpcy5zdGFjayA9IG1zZy5zdGFjaztcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIHRoZSBNb2RlbCBkZXRhaWxzXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBWYWxpZGF0aW9uRXJyb3JcbiAqIEBleHRlbmRzIEJhc2VFcnJvclxuICovXG5leHBvcnQgY2xhc3MgVmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKFZhbGlkYXRpb25FcnJvci5uYW1lLCBtc2csIDQyMik7XG4gIH1cbn1cbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbiBpbnRlcm5hbCBmYWlsdXJlIChzaG91bGQgbWVhbiBhbiBlcnJvciBpbiBjb2RlKVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgSW50ZXJuYWxFcnJvclxuICogQGV4dGVuZHMgQmFzZUVycm9yXG4gKi9cbmV4cG9ydCBjbGFzcyBJbnRlcm5hbEVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKEludGVybmFsRXJyb3IubmFtZSwgbXNnLCA1MDApO1xuICB9XG59XG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIHRoZSBNb2RlbCBkZS9zZXJpYWxpemF0aW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBTZXJpYWxpemF0aW9uRXJyb3JcbiAqIEBleHRlbmRzIEJhc2VFcnJvclxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIFNlcmlhbGl6YXRpb25FcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihTZXJpYWxpemF0aW9uRXJyb3IubmFtZSwgbXNnLCA0MjIpO1xuICB9XG59XG5cbi8qKlxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgaW4gZmluZGluZyBhIG1vZGVsXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IG1zZyB0aGUgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjbGFzcyBOb3RGb3VuZEVycm9yXG4gKiBAZXh0ZW5kcyBCYXNlRXJyb3JcbiAqXG4gKi9cbmV4cG9ydCBjbGFzcyBOb3RGb3VuZEVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKE5vdEZvdW5kRXJyb3IubmFtZSwgbXNnLCA0MDQpO1xuICB9XG59XG4vKipcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBjb25mbGljdCBpbiB0aGUgc3RvcmFnZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtc2cgdGhlIGVycm9yIG1lc3NhZ2VcbiAqXG4gKiBAY2xhc3MgQ29uZmxpY3RFcnJvclxuICogQGV4dGVuZHMgQmFzZUVycm9yXG4gKlxuICovXG5leHBvcnQgY2xhc3MgQ29uZmxpY3RFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihDb25mbGljdEVycm9yLm5hbWUsIG1zZywgNDA5KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgT3BlcmF0aW9ucyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL09wZXJhdGlvbnNcIjtcbmltcG9ydCB7IE9wZXJhdGlvbkhhbmRsZXIsIFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXIgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy90eXBlc1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgRGVjb3JhdG9yTWV0YWRhdGEsIFJlZmxlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCwgTW9kZWxLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuL0NvbnRleHRcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCB0eXBlIENvbnRleHRBcmdzPFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+ID0ge1xuICBjb250ZXh0OiBDO1xuICBhcmdzOiBhbnlbXTtcbn07XG5cbi8qKlxuICogQHN1bW1hcnkgcmV0cmlldmVzIHRoZSBhcmd1bWVudHMgZm9yIHRoZSBoYW5kbGVyXG4gKiBAcGFyYW0ge2FueX0gZGVjIHRoZSBkZWNvcmF0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wIHRoZSBwcm9wZXJ0eSBuYW1lXG4gKiBAcGFyYW0ge3t9fSBtIHRoZSBtb2RlbFxuICogQHBhcmFtIHt7fX0gW2FjY3VtXSBhY2N1bXVsYXRvciB1c2VkIGZvciBpbnRlcm5hbCByZWN1cnNpdmVuZXNzXG4gKlxuICogQGZ1bmN0aW9uIGdldEhhbmRsZXJBcmdzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgY29uc3QgZ2V0SGFuZGxlckFyZ3MgPSBmdW5jdGlvbiAoXG4gIGRlYzogYW55LFxuICBwcm9wOiBzdHJpbmcsXG4gIG06IENvbnN0cnVjdG9yPGFueT4sXG4gIGFjY3VtPzogUmVjb3JkPHN0cmluZywgeyBhcmdzOiBzdHJpbmdbXSB9PlxuKTogUmVjb3JkPHN0cmluZywgeyBhcmdzOiBzdHJpbmdbXSB9PiB8IHZvaWQge1xuICBjb25zdCBuYW1lID0gbS5jb25zdHJ1Y3Rvci5uYW1lO1xuICBpZiAoIW5hbWUpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiQ291bGQgbm90IGRldGVybWluZSBtb2RlbCBjbGFzc1wiKTtcbiAgYWNjdW0gPSBhY2N1bSB8fCB7fTtcblxuICBpZiAoZGVjLnByb3BzLmhhbmRsZXJzW25hbWVdICYmIGRlYy5wcm9wcy5oYW5kbGVyc1tuYW1lXVtwcm9wXSlcbiAgICBhY2N1bSA9IHsgLi4uZGVjLnByb3BzLmhhbmRsZXJzW25hbWVdW3Byb3BdLCAuLi5hY2N1bSB9O1xuXG4gIGxldCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihtKTtcbiAgaWYgKHByb3RvID09PSBPYmplY3QucHJvdG90eXBlKSByZXR1cm4gYWNjdW07XG4gIGlmIChwcm90by5jb25zdHJ1Y3Rvci5uYW1lID09PSBuYW1lKSBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90byk7XG5cbiAgcmV0dXJuIGdldEhhbmRsZXJBcmdzKGRlYywgcHJvcCwgcHJvdG8sIGFjY3VtKTtcbn07XG5cbi8qKlxuICpcbiAqIEBwYXJhbSB7SVJlcG9zaXRvcnk8VD59IHJlcG9cbiAqIEBwYXJhbSBjb250ZXh0XG4gKiBAcGFyYW0ge1R9IG1vZGVsXG4gKiBAcGFyYW0gb3BlcmF0aW9uXG4gKiBAcGFyYW0gcHJlZml4XG4gKlxuICogQHBhcmFtIG9sZE1vZGVsXG4gKiBAZnVuY3Rpb24gZW5mb3JjZURCUHJvcGVydHlEZWNvcmF0b3JzQXN5bmNcbiAqXG4gKiBAbWVtYmVyT2YgZGItZGVjb3JhdG9ycy51dGlsc1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5mb3JjZURCRGVjb3JhdG9yczxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYgZXh0ZW5kcyBvYmplY3QgPSBvYmplY3QsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4oXG4gIHJlcG86IFIsXG4gIGNvbnRleHQ6IEMsXG4gIG1vZGVsOiBNLFxuICBvcGVyYXRpb246IHN0cmluZyxcbiAgcHJlZml4OiBzdHJpbmcsXG4gIG9sZE1vZGVsPzogTVxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGRlY29yYXRvcnM6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+IHwgdW5kZWZpbmVkID1cbiAgICBnZXREYkRlY29yYXRvcnMobW9kZWwsIG9wZXJhdGlvbiwgcHJlZml4KTtcblxuICBpZiAoIWRlY29yYXRvcnMpIHJldHVybjtcblxuICBmb3IgKGNvbnN0IHByb3AgaW4gZGVjb3JhdG9ycykge1xuICAgIGNvbnN0IGRlY3M6IERlY29yYXRvck1ldGFkYXRhW10gPSBkZWNvcmF0b3JzW3Byb3BdO1xuICAgIGZvciAoY29uc3QgZGVjIG9mIGRlY3MpIHtcbiAgICAgIGNvbnN0IHsga2V5IH0gPSBkZWM7XG4gICAgICBjb25zdCBoYW5kbGVyczogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPltdIHwgdW5kZWZpbmVkID1cbiAgICAgICAgT3BlcmF0aW9ucy5nZXQ8TSwgUiwgViwgRiwgQz4obW9kZWwsIHByb3AsIHByZWZpeCArIGtleSk7XG4gICAgICBpZiAoIWhhbmRsZXJzIHx8ICFoYW5kbGVycy5sZW5ndGgpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgIGBDb3VsZCBub3QgZmluZCByZWdpc3RlcmVkIGhhbmRsZXIgZm9yIHRoZSBvcGVyYXRpb24gJHtwcmVmaXggKyBrZXl9IHVuZGVyIHByb3BlcnR5ICR7cHJvcH1gXG4gICAgICAgICk7XG5cbiAgICAgIGNvbnN0IGhhbmRsZXJBcmdzID0gZ2V0SGFuZGxlckFyZ3MoZGVjLCBwcm9wLCBtb2RlbCBhcyBhbnkpO1xuXG4gICAgICBpZiAoIWhhbmRsZXJBcmdzIHx8IE9iamVjdC52YWx1ZXMoaGFuZGxlckFyZ3MpLmxlbmd0aCAhPT0gaGFuZGxlcnMubGVuZ3RoKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkFyZ3MgYW5kIGhhbmRsZXJzIGxlbmd0aCBkbyBub3QgbWF0Y2hcIik7XG5cbiAgICAgIGxldCBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+O1xuICAgICAgbGV0IGRhdGE6IGFueTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaGFuZGxlcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaGFuZGxlciA9IGhhbmRsZXJzW2ldO1xuICAgICAgICBkYXRhID0gT2JqZWN0LnZhbHVlcyhoYW5kbGVyQXJncylbaV07XG5cbiAgICAgICAgY29uc3QgYXJnczogYW55W10gPSBbY29udGV4dCwgZGF0YS5kYXRhLCBwcm9wLCBtb2RlbF07XG5cbiAgICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gT3BlcmF0aW9uS2V5cy5VUERBVEUgJiYgcHJlZml4ID09PSBPcGVyYXRpb25LZXlzLk9OKSB7XG4gICAgICAgICAgaWYgKCFvbGRNb2RlbClcbiAgICAgICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTWlzc2luZyBvbGQgbW9kZWwgZm9yIHVwZGF0ZSBvcGVyYXRpb25cIik7XG4gICAgICAgICAgYXJncy5wdXNoKG9sZE1vZGVsKTtcbiAgICAgICAgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IChoYW5kbGVyIGFzIFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz4pLmFwcGx5KFxuICAgICAgICAgICAgcmVwbyxcbiAgICAgICAgICAgIGFyZ3MgYXMgW0MsIFYsIGtleW9mIE0sIE0sIE1dXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgICAgIGNvbnN0IG1zZyA9IGBGYWlsZWQgdG8gZXhlY3V0ZSBoYW5kbGVyICR7aGFuZGxlci5uYW1lfSBmb3IgJHtwcm9wfSBvbiAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9IGR1ZSB0byBlcnJvcjogJHtlfWA7XG4gICAgICAgICAgaWYgKGNvbnRleHQuZ2V0KFwiYnJlYWtPbkhhbmRsZXJFcnJvclwiKSkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IobXNnKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhtc2cpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogU3BlY2lmaWMgZm9yIERCIERlY29yYXRvcnNcbiAqIEBwYXJhbSB7VH0gbW9kZWxcbiAqIEBwYXJhbSB7c3RyaW5nfSBvcGVyYXRpb24gQ1JVRCB7QGxpbmsgT3BlcmF0aW9uS2V5c31cbiAqIEBwYXJhbSB7c3RyaW5nfSBbZXh0cmFQcmVmaXhdXG4gKlxuICogQGZ1bmN0aW9uIGdldERiUHJvcGVydHlEZWNvcmF0b3JzXG4gKlxuICogQG1lbWJlck9mIGRiLWRlY29yYXRvcnMudXRpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldERiRGVjb3JhdG9yczxUIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogVCxcbiAgb3BlcmF0aW9uOiBzdHJpbmcsXG4gIGV4dHJhUHJlZml4Pzogc3RyaW5nXG4pOiBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YVtdPiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGRlY29yYXRvcnM6IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+IHwgdW5kZWZpbmVkID1cbiAgICBSZWZsZWN0aW9uLmdldEFsbFByb3BlcnR5RGVjb3JhdG9ycyhcbiAgICAgIG1vZGVsLFxuICAgICAgLy8gdW5kZWZpbmVkLFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUZMRUNUICsgKGV4dHJhUHJlZml4ID8gZXh0cmFQcmVmaXggOiBcIlwiKVxuICAgICk7XG4gIGlmICghZGVjb3JhdG9ycykgcmV0dXJuO1xuICByZXR1cm4gT2JqZWN0LmtleXMoZGVjb3JhdG9ycykucmVkdWNlKFxuICAgIChhY2N1bTogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGFbXT4gfCB1bmRlZmluZWQsIGRlY29yYXRvcikgPT4ge1xuICAgICAgY29uc3QgZGVjID0gZGVjb3JhdG9yc1tkZWNvcmF0b3JdLmZpbHRlcigoZCkgPT4gZC5rZXkgPT09IG9wZXJhdGlvbik7XG4gICAgICBpZiAoZGVjICYmIGRlYy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKCFhY2N1bSkgYWNjdW0gPSB7fTtcbiAgICAgICAgYWNjdW1bZGVjb3JhdG9yXSA9IGRlYztcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2N1bTtcbiAgICB9LFxuICAgIHVuZGVmaW5lZFxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgZGVjb3JhdG9ycyBmb3IgYW4gb2JqZWN0J3MgcHJvcGVydGllcyBwcmVmaXhlZCBieSB7QHBhcmFtIHByZWZpeGVzfSByZWN1cnNpdmVseVxuICogQHBhcmFtIG1vZGVsXG4gKiBAcGFyYW0gYWNjdW1cbiAqIEBwYXJhbSBwcmVmaXhlc1xuICpcbiAqIEBmdW5jdGlvbiBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5SZXBvc2l0b3J5XG4gKi9cbmV4cG9ydCBjb25zdCBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUgPSBmdW5jdGlvbiA8VCBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IFQsXG4gIGFjY3VtOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9IHwgdW5kZWZpbmVkLFxuICAuLi5wcmVmaXhlczogc3RyaW5nW11cbik6IHsgW2luZGV4ZXI6IHN0cmluZ106IGFueVtdIH0gfCB1bmRlZmluZWQge1xuICBjb25zdCBhY2N1bXVsYXRvciA9IGFjY3VtIHx8IHt9O1xuICBjb25zdCBtZXJnZURlY29yYXRvcnMgPSBmdW5jdGlvbiAoZGVjczogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSkge1xuICAgIGNvbnN0IHB1c2hPclNxdWFzaCA9IChrZXk6IHN0cmluZywgLi4udmFsdWVzOiBhbnlbXSkgPT4ge1xuICAgICAgdmFsdWVzLmZvckVhY2goKHZhbCkgPT4ge1xuICAgICAgICBsZXQgbWF0Y2g6IGFueTtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICEobWF0Y2ggPSBhY2N1bXVsYXRvcltrZXldLmZpbmQoKGUpID0+IGUua2V5ID09PSB2YWwua2V5KSkgfHxcbiAgICAgICAgICBtYXRjaC5wcm9wcy5vcGVyYXRpb24gIT09IHZhbC5wcm9wcy5vcGVyYXRpb25cbiAgICAgICAgKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3Jba2V5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbC5rZXkgPT09IE1vZGVsS2V5cy5UWVBFKSByZXR1cm47XG5cbiAgICAgICAgY29uc3QgeyBoYW5kbGVycywgb3BlcmF0aW9uIH0gPSB2YWwucHJvcHM7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICFvcGVyYXRpb24gfHxcbiAgICAgICAgICAhb3BlcmF0aW9uLm1hdGNoKFxuICAgICAgICAgICAgbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgYF4oOj8ke09wZXJhdGlvbktleXMuT059fCR7T3BlcmF0aW9uS2V5cy5BRlRFUn0pKDo/JHtPcGVyYXRpb25LZXlzLkNSRUFURX18JHtPcGVyYXRpb25LZXlzLlJFQUR9fCR7T3BlcmF0aW9uS2V5cy5VUERBVEV9fCR7T3BlcmF0aW9uS2V5cy5ERUxFVEV9KSRgXG4gICAgICAgICAgICApXG4gICAgICAgICAgKVxuICAgICAgICApIHtcbiAgICAgICAgICBhY2N1bXVsYXRvcltrZXldLnB1c2godmFsKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBhY2N1bUhhbmRsZXJzID0gbWF0Y2gucHJvcHMuaGFuZGxlcnM7XG5cbiAgICAgICAgT2JqZWN0LmVudHJpZXMoaGFuZGxlcnMpLmZvckVhY2goKFtjbGF6eiwgaGFuZGxlckRlZl0pID0+IHtcbiAgICAgICAgICBpZiAoIShjbGF6eiBpbiBhY2N1bUhhbmRsZXJzKSkge1xuICAgICAgICAgICAgYWNjdW1IYW5kbGVyc1tjbGF6el0gPSBoYW5kbGVyRGVmO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGhhbmRsZXJEZWYgYXMgb2JqZWN0KS5mb3JFYWNoKFxuICAgICAgICAgICAgKFtoYW5kbGVyUHJvcCwgaGFuZGxlcl0pID0+IHtcbiAgICAgICAgICAgICAgaWYgKCEoaGFuZGxlclByb3AgaW4gYWNjdW1IYW5kbGVyc1tjbGF6el0pKSB7XG4gICAgICAgICAgICAgICAgYWNjdW1IYW5kbGVyc1tjbGF6el1baGFuZGxlclByb3BdID0gaGFuZGxlcjtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBPYmplY3QuZW50cmllcyhoYW5kbGVyIGFzIG9iamVjdCkuZm9yRWFjaChcbiAgICAgICAgICAgICAgICAoW2hhbmRsZXJLZXksIGFyZ3NPYmpdKSA9PiB7XG4gICAgICAgICAgICAgICAgICBpZiAoIShoYW5kbGVyS2V5IGluIGFjY3VtSGFuZGxlcnNbY2xhenpdW2hhbmRsZXJQcm9wXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYWNjdW1IYW5kbGVyc1tjbGF6el1baGFuZGxlclByb3BdW2hhbmRsZXJLZXldID0gYXJnc09iajtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICAgICBgU2tpcHBpbmcgaGFuZGxlciByZWdpc3RyYXRpb24gZm9yICR7Y2xhenp9IHVuZGVyIHByb3AgJHtoYW5kbGVyUHJvcH0gYmVjYXVzZSBoYW5kbGVyIGlzIHRoZSBzYW1lYFxuICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgT2JqZWN0LmVudHJpZXMoZGVjcykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICBhY2N1bXVsYXRvcltrZXldID0gYWNjdW11bGF0b3Jba2V5XSB8fCBbXTtcbiAgICAgIHB1c2hPclNxdWFzaChrZXksIC4uLnZhbHVlKTtcbiAgICB9KTtcbiAgfTtcblxuICBjb25zdCBkZWNzOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9IHwgdW5kZWZpbmVkID1cbiAgICBSZWZsZWN0aW9uLmdldEFsbFByb3BlcnR5RGVjb3JhdG9ycyhtb2RlbCwgLi4ucHJlZml4ZXMpO1xuICBpZiAoZGVjcykgbWVyZ2VEZWNvcmF0b3JzKGRlY3MpO1xuXG4gIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kZWwpID09PSBPYmplY3QucHJvdG90eXBlKSByZXR1cm4gYWNjdW11bGF0b3I7XG5cbiAgLy8gY29uc3QgbmFtZSA9IG1vZGVsLmNvbnN0cnVjdG9yLm5hbWU7XG4gIGNvbnN0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZGVsKTtcbiAgaWYgKCFwcm90bykgcmV0dXJuIGFjY3VtdWxhdG9yO1xuICAvLyBpZiAocHJvdG8uY29uc3RydWN0b3IgJiYgcHJvdG8uY29uc3RydWN0b3IubmFtZSA9PT0gbmFtZSlcbiAgLy8gICAgIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKVxuICByZXR1cm4gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKHByb3RvLCBhY2N1bXVsYXRvciwgLi4ucHJlZml4ZXMpO1xufTtcbiIsImltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmV4cG9ydCBjb25zdCBEZWZhdWx0UmVwb3NpdG9yeUZsYWdzOiBPbWl0PFJlcG9zaXRvcnlGbGFncywgXCJ0aW1lc3RhbXBcIj4gPSB7XG4gIHBhcmVudENvbnRleHQ6IHVuZGVmaW5lZCxcbiAgY2hpbGRDb250ZXh0czogW10sXG4gIGlnbm9yZWRWYWxpZGF0aW9uUHJvcGVydGllczogW10sXG4gIGNhbGxBcmdzOiBbXSxcbiAgd3JpdGVPcGVyYXRpb246IGZhbHNlLFxuICBhZmZlY3RlZFRhYmxlczogW10sXG4gIG9wZXJhdGlvbjogdW5kZWZpbmVkLFxuICBicmVha09uSGFuZGxlckVycm9yOiB0cnVlLFxuICByZWJ1aWxkV2l0aFRyYW5zaWVudDogdHJ1ZSxcbn07XG4iLCJpbXBvcnQgeyBDb250ZXh0QXJncyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBDb250ZXh0dWFsIH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvQ29udGV4dHVhbFwiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgRGVmYXVsdFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgT2JqZWN0QWNjdW11bGF0b3IgfSBmcm9tIFwidHlwZWQtb2JqZWN0LWFjY3VtdWxhdG9yXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgdHlwZSBDb250ZXh0RmFjdG9yeTxGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzPiA9IDxDIGV4dGVuZHMgQ29udGV4dDxGPj4oXG4gIGFyZzogT21pdDxGLCBcInRpbWVzdGFtcFwiPlxuKSA9PiBDO1xuXG5leHBvcnQgY29uc3QgRGVmYXVsdENvbnRleHRGYWN0b3J5OiBDb250ZXh0RmFjdG9yeTxhbnk+ID0gPFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbj4oXG4gIGFyZzogT21pdDxGLCBcInRpbWVzdGFtcFwiPlxuKSA9PiB7XG4gIHJldHVybiBuZXcgQ29udGV4dDxGPigpLmFjY3VtdWxhdGUoXG4gICAgT2JqZWN0LmFzc2lnbih7fSwgYXJnLCB7IHRpbWVzdGFtcDogbmV3IERhdGUoKSB9KSBhcyBGXG4gICkgYXMgQztcbn07XG5cbmV4cG9ydCBjbGFzcyBDb250ZXh0PEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3M+IHtcbiAgc3RhdGljIGZhY3Rvcnk6IENvbnRleHRGYWN0b3J5PGFueT4gPSBEZWZhdWx0Q29udGV4dEZhY3Rvcnk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjYWNoZTogRiAmIE9iamVjdEFjY3VtdWxhdG9yPEY+ID1cbiAgICBuZXcgT2JqZWN0QWNjdW11bGF0b3IoKSBhcyBGICYgT2JqZWN0QWNjdW11bGF0b3I8Rj47XG5cbiAgY29uc3RydWN0b3Iob2JqPzogRikge1xuICAgIGlmIChvYmopIHJldHVybiB0aGlzLmFjY3VtdWxhdGUob2JqKTtcbiAgfVxuXG4gIGFjY3VtdWxhdGU8ViBleHRlbmRzIG9iamVjdD4odmFsdWU6IFYpIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgXCJjYWNoZVwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5jYWNoZS5hY2N1bXVsYXRlKHZhbHVlKSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzIGFzIHVua25vd24gYXMgQ29udGV4dDxGICYgVj47XG4gIH1cblxuICBnZXQgdGltZXN0YW1wKCkge1xuICAgIHJldHVybiB0aGlzLmNhY2hlLnRpbWVzdGFtcDtcbiAgfVxuXG4gIGdldDxLIGV4dGVuZHMga2V5b2YgRj4oa2V5OiBLKTogRltLXSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIGlmICh0aGlzLmNhY2hlLnBhcmVudENvbnRleHQpIHJldHVybiB0aGlzLmNhY2hlLnBhcmVudENvbnRleHQuZ2V0KGtleSk7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxuXG4gIGNoaWxkPE0gZXh0ZW5kcyBNb2RlbCwgQyBleHRlbmRzIENvbnRleHQ8Rj4+KFxuICAgIG9wZXJhdGlvbjogT3BlcmF0aW9uS2V5cyxcbiAgICBtb2RlbD86IENvbnN0cnVjdG9yPE0+XG4gICk6IEMge1xuICAgIHJldHVybiBDb250ZXh0LmNoaWxkRnJvbTxGLCBDPihcbiAgICAgIHRoaXMgYXMgdW5rbm93biBhcyBDLFxuICAgICAge1xuICAgICAgICBvcGVyYXRpb246IG9wZXJhdGlvbixcbiAgICAgICAgYWZmZWN0ZWRUYWJsZXM6IG1vZGVsID8gW21vZGVsXSA6IFtdLFxuICAgICAgfSBhcyB1bmtub3duIGFzIFBhcnRpYWw8Rj5cbiAgICApO1xuICB9XG5cbiAgc3RhdGljIGNoaWxkRnJvbTxGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLCBDIGV4dGVuZHMgQ29udGV4dDxGPj4oXG4gICAgY29udGV4dDogQyxcbiAgICBvdmVycmlkZXM/OiBQYXJ0aWFsPEY+XG4gICk6IEMge1xuICAgIHJldHVybiBDb250ZXh0LmZhY3RvcnkoXG4gICAgICBPYmplY3QuYXNzaWduKHt9LCBjb250ZXh0LmNhY2hlLCBvdmVycmlkZXMgfHwge30pXG4gICAgKSBhcyB1bmtub3duIGFzIEM7XG4gIH1cblxuICBzdGF0aWMgYXN5bmMgZnJvbTxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbiAgPihcbiAgICBvcGVyYXRpb246XG4gICAgICB8IE9wZXJhdGlvbktleXMuQ1JFQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuUkVBRFxuICAgICAgfCBPcGVyYXRpb25LZXlzLlVQREFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICBvdmVycmlkZXM6IFBhcnRpYWw8Rj4sXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPEM+IHtcbiAgICByZXR1cm4gQ29udGV4dC5mYWN0b3J5KFxuICAgICAgT2JqZWN0LmFzc2lnbih7fSwgRGVmYXVsdFJlcG9zaXRvcnlGbGFncywgb3ZlcnJpZGVzLCB7XG4gICAgICAgIG9wZXJhdGlvbjogb3BlcmF0aW9uLFxuICAgICAgICBtb2RlbDogbW9kZWwsXG4gICAgICB9KVxuICAgICkgYXMgQztcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBhcmdzPFxuICAgIE0gZXh0ZW5kcyBNb2RlbCxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbiAgICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICA+KFxuICAgIG9wZXJhdGlvbjpcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5DUkVBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5SRUFEXG4gICAgICB8IE9wZXJhdGlvbktleXMuVVBEQVRFXG4gICAgICB8IE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPixcbiAgICBhcmdzOiBhbnlbXSxcbiAgICBjb250ZXh0dWFsPzogQ29udGV4dHVhbDxGPixcbiAgICBvdmVycmlkZXM/OiBQYXJ0aWFsPEY+XG4gICk6IFByb21pc2U8Q29udGV4dEFyZ3M8RiwgQz4+IHtcbiAgICBjb25zdCBsYXN0ID0gYXJncy5wb3AoKTtcblxuICAgIGFzeW5jIGZ1bmN0aW9uIGdldENvbnRleHQoKSB7XG4gICAgICBpZiAoY29udGV4dHVhbClcbiAgICAgICAgcmV0dXJuIGNvbnRleHR1YWwuY29udGV4dChvcGVyYXRpb24sIG92ZXJyaWRlcyB8fCB7fSwgbW9kZWwsIC4uLmFyZ3MpO1xuICAgICAgcmV0dXJuIENvbnRleHQuZnJvbShvcGVyYXRpb24sIG92ZXJyaWRlcyB8fCB7fSwgbW9kZWwsIC4uLmFyZ3MpO1xuICAgIH1cblxuICAgIGxldCBjOiBDO1xuICAgIGlmIChsYXN0KSB7XG4gICAgICBpZiAobGFzdCBpbnN0YW5jZW9mIENvbnRleHQpIHtcbiAgICAgICAgYyA9IGxhc3QgYXMgQztcbiAgICAgICAgYXJncy5wdXNoKGxhc3QpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYyA9IChhd2FpdCBnZXRDb250ZXh0KCkpIGFzIEM7XG4gICAgICAgIGFyZ3MucHVzaChsYXN0LCBjKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYyA9IChhd2FpdCBnZXRDb250ZXh0KCkpIGFzIEM7XG4gICAgICBhcmdzLnB1c2goYyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgY29udGV4dDogYywgYXJnczogYXJncyB9O1xuICB9XG59XG4iLCJpbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgbWV0aG9kIHRvIGNoYW5nZSBhIG1ldGhvZCBvZiBhbiBvYmplY3QgcHJlZml4aW5nIGl0IHdpdGggYW5vdGhlclxuICogQHBhcmFtIHthbnl9IG9iaiBUaGUgQmFzZSBPYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGFmdGVyIFRoZSBvcmlnaW5hbCBtZXRob2RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWZpeCBUaGUgUHJlZml4IG1ldGhvZC4gVGhlIG91dHB1dCB3aWxsIGJlIHVzZWQgYXMgYXJndW1lbnRzIGluIHRoZSBvcmlnaW5hbCBtZXRob2RcbiAqIEBwYXJhbSB7c3RyaW5nfSBbYWZ0ZXJOYW1lXSBXaGVuIHRoZSBhZnRlciBmdW5jdGlvbiBhbm1lIGNhbm5vdCBiZSBleHRyYWN0ZWQsIHBhc3MgaXQgaGVyZVxuICpcbiAqIEBmdW5jdGlvbiBwcmVmaXhNZXRob2RcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlZml4TWV0aG9kKFxuICBvYmo6IGFueSxcbiAgYWZ0ZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBwcmVmaXg6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBhZnRlck5hbWU/OiBzdHJpbmdcbikge1xuICBhc3luYyBmdW5jdGlvbiB3cmFwcGVyKHRoaXM6IGFueSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKHByZWZpeC5jYWxsKHRoaXMsIC4uLmFyZ3MpKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGFmdGVyLmFwcGx5KHRoaXMsIHJlc3VsdHMpKTtcbiAgfVxuICBjb25zdCB3cmFwcGVkID0gd3JhcHBlci5iaW5kKG9iaik7XG4gIGNvbnN0IG5hbWUgPSBhZnRlck5hbWUgPyBhZnRlck5hbWUgOiBhZnRlci5uYW1lO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkod3JhcHBlZCwgXCJuYW1lXCIsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IG5hbWUsXG4gIH0pO1xuICBvYmpbbmFtZV0gPSB3cmFwcGVkO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgbWV0aG9kIHRvIGNoYW5nZSBhIG1ldGhvZCBvZiBhbiBvYmplY3Qgc3VmZml4aW5nIGl0IHdpdGggYW5vdGhlclxuICogQHBhcmFtIHthbnl9IG9iaiBUaGUgQmFzZSBPYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGJlZm9yZSBUaGUgb3JpZ2luYWwgbWV0aG9kXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBzdWZmaXggVGhlIFByZWZpeCBtZXRob2QuIFRoZSBvdXRwdXQgd2lsbCBiZSB1c2VkIGFzIGFyZ3VtZW50cyBpbiB0aGUgb3JpZ2luYWwgbWV0aG9kXG4gKiBAcGFyYW0ge3N0cmluZ30gW2JlZm9yZU5hbWVdIFdoZW4gdGhlIGFmdGVyIGZ1bmN0aW9uIGFubWUgY2Fubm90IGJlIGV4dHJhY3RlZCwgcGFzcyBpdCBoZXJlXG4gKlxuICogQGZ1bmN0aW9uIHN1ZmZpeE1ldGhvZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5SZXBvc2l0b3J5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdWZmaXhNZXRob2QoXG4gIG9iajogYW55LFxuICBiZWZvcmU6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBzdWZmaXg6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBiZWZvcmVOYW1lPzogc3RyaW5nXG4pIHtcbiAgYXN5bmMgZnVuY3Rpb24gd3JhcHBlcih0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShiZWZvcmUuY2FsbCh0aGlzLCAuLi5hcmdzKSk7XG4gICAgcmV0dXJuIHN1ZmZpeC5jYWxsKHRoaXMsIC4uLnJlc3VsdHMpO1xuICB9XG4gIGNvbnN0IHdyYXBwZWQgPSB3cmFwcGVyLmJpbmQob2JqKTtcbiAgY29uc3QgbmFtZSA9IGJlZm9yZU5hbWUgPyBiZWZvcmVOYW1lIDogYmVmb3JlLm5hbWU7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3cmFwcGVkLCBcIm5hbWVcIiwge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICB2YWx1ZTogbmFtZSxcbiAgfSk7XG4gIG9ialtuYW1lXSA9IHdyYXBwZWQ7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgVXRpbCBtZXRob2QgdG8gd3JhcCBhIG1ldGhvZCBvZiBhbiBvYmplY3Qgd2l0aCBhZGRpdGlvbmFsIGxvZ2ljXG4gKlxuICogQHBhcmFtIHthbnl9IG9iaiBUaGUgQmFzZSBPYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGJlZm9yZSB0aGUgbWV0aG9kIHRvIGJlIHByZWZpeGVkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgdGhlIG1ldGhvZCB0byBiZSB3cmFwcGVkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBhZnRlciBUaGUgbWV0aG9kIHRvIGJlIHN1ZmZpeGVkXG4gKiBAcGFyYW0ge3N0cmluZ30gW21ldGhvZE5hbWVdIFdoZW4gdGhlIGFmdGVyIGZ1bmN0aW9uIGFubWUgY2Fubm90IGJlIGV4dHJhY3RlZCwgcGFzcyBpdCBoZXJlXG4gKlxuICogQGZ1bmN0aW9uIHdyYXBNZXRob2RXaXRoQ29udGV4dFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5SZXBvc2l0b3J5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3cmFwTWV0aG9kV2l0aENvbnRleHQoXG4gIG9iajogYW55LFxuICBiZWZvcmU6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBtZXRob2Q6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBhZnRlcjogKC4uLmFyZ3M6IGFueVtdKSA9PiBhbnksXG4gIG1ldGhvZE5hbWU/OiBzdHJpbmdcbikge1xuICBjb25zdCBuYW1lID0gbWV0aG9kTmFtZSA/IG1ldGhvZE5hbWUgOiBtZXRob2QubmFtZTtcbiAgb2JqW25hbWVdID0gbmV3IFByb3h5KG9ialtuYW1lXSwge1xuICAgIGFwcGx5OiBhc3luYyAodGFyZ2V0LCB0aGlzQXJnLCBhcmdBcnJheSkgPT4ge1xuICAgICAgbGV0IHRyYW5zZm9ybWVkQXJncyA9IGJlZm9yZS5jYWxsKHRoaXNBcmcsIC4uLmFyZ0FycmF5KTtcbiAgICAgIGlmICh0cmFuc2Zvcm1lZEFyZ3MgaW5zdGFuY2VvZiBQcm9taXNlKVxuICAgICAgICB0cmFuc2Zvcm1lZEFyZ3MgPSBhd2FpdCB0cmFuc2Zvcm1lZEFyZ3M7XG4gICAgICBjb25zdCBjb250ZXh0ID0gdHJhbnNmb3JtZWRBcmdzW3RyYW5zZm9ybWVkQXJncy5sZW5ndGggLSAxXSBhcyBhbnk7XG4gICAgICBpZiAoIShjb250ZXh0IGluc3RhbmNlb2YgQ29udGV4dCkpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTWlzc2luZyBhIGNvbnRleHRcIik7XG4gICAgICBsZXQgcmVzdWx0cyA9IGF3YWl0IHRhcmdldC5jYWxsKHRoaXNBcmcsIC4uLnRyYW5zZm9ybWVkQXJncyk7XG4gICAgICBpZiAocmVzdWx0cyBpbnN0YW5jZW9mIFByb21pc2UpIHJlc3VsdHMgPSBhd2FpdCByZXN1bHRzO1xuICAgICAgcmVzdWx0cyA9IGFmdGVyLmNhbGwodGhpc0FyZywgcmVzdWx0cywgY29udGV4dCk7XG4gICAgICBpZiAocmVzdWx0cyBpbnN0YW5jZW9mIFByb21pc2UpIHJlc3VsdHMgPSBhd2FpdCByZXN1bHRzO1xuICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfSxcbiAgfSk7XG59XG4iLCJpbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS91dGlsc1wiO1xuaW1wb3J0IHsgTW9kZWwsIE1vZGVsS2V5cywgc2YgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvZXJyb3JzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgUmV0dXJucyB0aGUgcHJpbWFyeSBrZXkgYXR0cmlidXRlIGZvciBhIHtAbGluayBNb2RlbH1cbiAqIEBkZXNjcmlwdGlvbiBzZWFyY2hlcyBpbiBhbGwgdGhlIHByb3BlcnRpZXMgaW4gdGhlIG9iamVjdCBmb3IgYW4ge0BsaW5rIGlkfSBkZWNvcmF0ZWQgcHJvcGVydHlcbiAqXG4gKiBAcGFyYW0ge01vZGVsfSBtb2RlbFxuICpcbiAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IGlmIG5vIHByb3BlcnR5IG9yIG1vcmUgdGhhbiBvbmUgcHJvcGVydGllcyBhcmUge0BsaW5rIGlkfSBkZWNvcmF0ZWRcbiAqIG9yIG5vIHZhbHVlIGlzIHNldCBpbiB0aGF0IHByb3BlcnR5XG4gKlxuICogQGZ1bmN0aW9uIGZpbmRQcmltYXJ5S2V5XG4gKlxuICogQGNhdGVnb3J5IG1hbmFnZXJzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUHJpbWFyeUtleTxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKSB7XG4gIGNvbnN0IGRlY29yYXRvcnMgPSBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUoXG4gICAgbW9kZWwsXG4gICAgdW5kZWZpbmVkLFxuICAgIERCS2V5cy5SRUZMRUNUICsgREJLZXlzLklEXG4gICk7XG4gIGNvbnN0IGlkRGVjb3JhdG9ycyA9IE9iamVjdC5lbnRyaWVzKGRlY29yYXRvcnMgYXMgb2JqZWN0KS5yZWR1Y2UoXG4gICAgKGFjY3VtOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9LCBbcHJvcCwgZGVjc10pID0+IHtcbiAgICAgIGNvbnN0IGZpbHRlcmVkID0gKGRlY3MgYXMgeyBrZXk6IHN0cmluZyB9W10pLmZpbHRlcihcbiAgICAgICAgKGQpID0+IGQua2V5ICE9PSBNb2RlbEtleXMuVFlQRVxuICAgICAgKTtcbiAgICAgIGlmIChmaWx0ZXJlZCAmJiBmaWx0ZXJlZC5sZW5ndGgpIHtcbiAgICAgICAgYWNjdW1bcHJvcF0gPSBhY2N1bVtwcm9wXSB8fCBbXTtcbiAgICAgICAgYWNjdW1bcHJvcF0ucHVzaCguLi5maWx0ZXJlZCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdW07XG4gICAgfSxcbiAgICB7fVxuICApO1xuXG4gIGlmICghaWREZWNvcmF0b3JzIHx8ICFPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmxlbmd0aClcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkNvdWxkIG5vdCBmaW5kIElEIGRlY29yYXRlZCBQcm9wZXJ0eVwiKTtcbiAgaWYgKE9iamVjdC5rZXlzKGlkRGVjb3JhdG9ycykubGVuZ3RoID4gMSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihzZihPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmpvaW4oXCIsIFwiKSkpO1xuICBjb25zdCBpZFByb3AgPSBPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpWzBdO1xuICBpZiAoIWlkUHJvcCkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCBJRCBkZWNvcmF0ZWQgUHJvcGVydHlcIik7XG4gIHJldHVybiB7XG4gICAgaWQ6IGlkUHJvcCBhcyBrZXlvZiBNLFxuICAgIHByb3BzOiBpZERlY29yYXRvcnNbaWRQcm9wXVswXS5wcm9wcyxcbiAgfTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBwcmltYXJ5IGtleSB2YWx1ZSBmb3IgYSB7QGxpbmsgTW9kZWx9XG4gKiBAZGVzY3JpcHRpb24gc2VhcmNoZXMgaW4gYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHRoZSBvYmplY3QgZm9yIGFuIHtAbGluayBwa30gZGVjb3JhdGVkIHByb3BlcnR5XG4gKlxuICogQHBhcmFtIHtNb2RlbH0gbW9kZWxcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3JldHVybkVtcHR5XVxuICogQHJldHVybiB7c3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50fSBwcmltYXJ5IGtleVxuICpcbiAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IGlmIG5vIHByb3BlcnR5IG9yIG1vcmUgdGhhbiBvbmUgcHJvcGVydGllcyBhcmUge0BsaW5rIHBrfSBkZWNvcmF0ZWRcbiAqIEB0aHJvd3Mge05vdEZvdW5kRXJyb3J9IHJldHVybkVtcHR5IGlzIGZhbHNlIGFuZCBubyB2YWx1ZSBpcyBzZXQgb24gdGhlIHtAbGluayBwa30gZGVjb3JhdGVkIHByb3BlcnR5XG4gKlxuICogQGZ1bmN0aW9uIGZpbmRNb2RlbElEXG4gKlxuICogQGNhdGVnb3J5IG1hbmFnZXJzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kTW9kZWxJZDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTSxcbiAgcmV0dXJuRW1wdHkgPSBmYWxzZVxuKTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50IHtcbiAgY29uc3QgaWRQcm9wID0gZmluZFByaW1hcnlLZXkobW9kZWwpLmlkO1xuICBjb25zdCBtb2RlbElkID0gbW9kZWxbaWRQcm9wXTtcbiAgaWYgKHR5cGVvZiBtb2RlbElkID09PSBcInVuZGVmaW5lZFwiICYmICFyZXR1cm5FbXB0eSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7aWRQcm9wIGFzIHN0cmluZ31gXG4gICAgKTtcbiAgcmV0dXJuIG1vZGVsSWQgYXMgc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50O1xufVxuIiwiaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgZW5mb3JjZURCRGVjb3JhdG9ycyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyB3cmFwTWV0aG9kV2l0aENvbnRleHQgfSBmcm9tIFwiLi93cmFwcGVyc1wiO1xuaW1wb3J0IHsgZmluZFByaW1hcnlLZXkgfSBmcm9tIFwiLi4vaWRlbnRpdHkvdXRpbHNcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi9Db250ZXh0XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZVJlcG9zaXRvcnk8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiBpbXBsZW1lbnRzIElSZXBvc2l0b3J5PE0sIEYsIEM+XG57XG4gIHByaXZhdGUgcmVhZG9ubHkgX2NsYXNzITogQ29uc3RydWN0b3I8TT47XG4gIHByaXZhdGUgX3BrIToga2V5b2YgTTtcbiAgcHJpdmF0ZSBfcGtQcm9wcyE6IGFueTtcblxuICBnZXQgY2xhc3MoKSB7XG4gICAgaWYgKCF0aGlzLl9jbGFzcylcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBObyBjbGFzcyBkZWZpbml0aW9uIGZvdW5kIGZvciB0aGlzIHJlcG9zaXRvcnlgKTtcbiAgICByZXR1cm4gdGhpcy5fY2xhc3M7XG4gIH1cblxuICBnZXQgcGsoKToga2V5b2YgTSB7XG4gICAgaWYgKCF0aGlzLl9waykge1xuICAgICAgY29uc3QgeyBpZCwgcHJvcHMgfSA9IGZpbmRQcmltYXJ5S2V5KG5ldyB0aGlzLmNsYXNzKCkpO1xuICAgICAgdGhpcy5fcGsgPSBpZDtcbiAgICAgIHRoaXMuX3BrUHJvcHMgPSBwcm9wcztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3BrO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBwa1Byb3BzKCk6IGFueSB7XG4gICAgaWYgKCF0aGlzLl9wa1Byb3BzKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgICBjb25zdCBwayA9IHRoaXMucGs7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9wa1Byb3BzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGNsYXp6PzogQ29uc3RydWN0b3I8TT4pIHtcbiAgICBpZiAoY2xhenopIHRoaXMuX2NsYXNzID0gY2xheno7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby10aGlzLWFsaWFzXG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgW3RoaXMuY3JlYXRlLCB0aGlzLnJlYWQsIHRoaXMudXBkYXRlLCB0aGlzLmRlbGV0ZV0uZm9yRWFjaCgobSkgPT4ge1xuICAgICAgY29uc3QgbmFtZSA9IG0ubmFtZTtcbiAgICAgIHdyYXBNZXRob2RXaXRoQ29udGV4dChcbiAgICAgICAgc2VsZixcbiAgICAgICAgKHNlbGYgYXMgYW55KVtuYW1lICsgXCJQcmVmaXhcIl0sXG4gICAgICAgIG0sXG4gICAgICAgIChzZWxmIGFzIGFueSlbbmFtZSArIFwiU3VmZml4XCJdXG4gICAgICApO1xuICAgIH0pO1xuICB9XG5cbiAgYWJzdHJhY3QgY3JlYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT47XG5cbiAgYXN5bmMgY3JlYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKG1vZGVscy5tYXAoKG0pID0+IHRoaXMuY3JlYXRlKG0sIC4uLmFyZ3MpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlUHJlZml4KG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgbW9kZWwgPSBuZXcgdGhpcy5jbGFzcyhtb2RlbCk7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICApO1xuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZVN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlQWxsUHJlZml4KG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKGFzeW5jIChtKSA9PiB7XG4gICAgICAgIG0gPSBuZXcgdGhpcy5jbGFzcyhtKTtcbiAgICAgICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSlcbiAgICApO1xuICAgIHJldHVybiBbbW9kZWxzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVBbGxTdWZmaXgobW9kZWxzOiBNW10sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWxzO1xuICB9XG5cbiAgYWJzdHJhY3QgcmVhZChrZXk6IHN0cmluZyB8IG51bWJlciwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+O1xuXG4gIGFzeW5jIHJlYWRBbGwoa2V5czogc3RyaW5nW10gfCBudW1iZXJbXSwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE1bXT4ge1xuICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChrZXlzLm1hcCgoaWQpID0+IHRoaXMucmVhZChpZCwgLi4uYXJncykpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyByZWFkU3VmZml4KG1vZGVsOiBNLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgcmVhZFByZWZpeChrZXk6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBtb2RlbDogTSA9IG5ldyB0aGlzLmNsYXNzKCk7XG4gICAgbW9kZWxbdGhpcy5wa10gPSBrZXkgYXMgYW55O1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICk7XG4gICAgcmV0dXJuIFtrZXksIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRBbGxQcmVmaXgoa2V5czogc3RyaW5nW10gfCBudW1iZXJbXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGtleXMubWFwKGFzeW5jIChrKSA9PiB7XG4gICAgICAgIGNvbnN0IG0gPSBuZXcgdGhpcy5jbGFzcygpO1xuICAgICAgICBtW3RoaXMucGtdID0gayBhcyBhbnk7XG4gICAgICAgIHJldHVybiBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIFtrZXlzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyByZWFkQWxsU3VmZml4KG1vZGVsczogTVtdLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuICAgIHJldHVybiBtb2RlbHM7XG4gIH1cblxuICBhYnN0cmFjdCB1cGRhdGUobW9kZWw6IE0sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPjtcblxuICBhc3luYyB1cGRhdGVBbGwobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueSk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKG1vZGVscy5tYXAoKG0pID0+IHRoaXMudXBkYXRlKG0sIC4uLmFyZ3MpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlU3VmZml4KG1vZGVsOiBNLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICApO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyB1cGRhdGVQcmVmaXgobW9kZWw6IE0sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBpZCA9IG1vZGVsW3RoaXMucGtdO1xuICAgIGlmICghaWQpXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYE5vIHZhbHVlIGZvciB0aGUgSWQgaXMgZGVmaW5lZCB1bmRlciB0aGUgcHJvcGVydHkgJHt0aGlzLnBrIGFzIHN0cmluZ31gXG4gICAgICApO1xuICAgIGNvbnN0IG9sZE1vZGVsID0gYXdhaXQgdGhpcy5yZWFkKGlkIGFzIHN0cmluZyk7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT04sXG4gICAgICBvbGRNb2RlbFxuICAgICk7XG4gICAgcmV0dXJuIFttb2RlbCwgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlQWxsUHJlZml4KG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PiB7XG4gICAgICAgIG0gPSBuZXcgdGhpcy5jbGFzcyhtKTtcbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBtO1xuICAgICAgfSlcbiAgICApO1xuICAgIHJldHVybiBbbW9kZWxzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyB1cGRhdGVBbGxTdWZmaXgobW9kZWxzOiBNW10sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5BRlRFUlxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWxzO1xuICB9XG5cbiAgYWJzdHJhY3QgZGVsZXRlKGtleTogc3RyaW5nIHwgbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT47XG5cbiAgYXN5bmMgZGVsZXRlQWxsKGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICByZXR1cm4gUHJvbWlzZS5hbGwoa2V5cy5tYXAoKGspID0+IHRoaXMuZGVsZXRlKGssIC4uLmFyZ3MpKSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZGVsZXRlU3VmZml4KG1vZGVsOiBNLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICApO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVQcmVmaXgoa2V5OiBhbnksIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBtb2RlbCA9IGF3YWl0IHRoaXMucmVhZChrZXksIC4uLmNvbnRleHRBcmdzLmFyZ3MpO1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgKTtcbiAgICByZXR1cm4gW2tleSwgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBwcm90ZWN0ZWQgYXN5bmMgZGVsZXRlQWxsUHJlZml4KGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBtb2RlbHMgPSBhd2FpdCB0aGlzLnJlYWRBbGwoa2V5cywgLi4uY29udGV4dEFyZ3MuYXJncyk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKGFzeW5jIChtKSA9PiB7XG4gICAgICAgIHJldHVybiBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICByZXR1cm4gW2tleXMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZUFsbFN1ZmZpeChtb2RlbHM6IE1bXSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuICAgIHJldHVybiBtb2RlbHM7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWVyZ2Uob2xkTW9kZWw6IE0sIG1vZGVsOiBNKTogTSB7XG4gICAgY29uc3QgZXh0cmFjdCA9IChtb2RlbDogTSkgPT5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG1vZGVsKS5yZWR1Y2UoKGFjY3VtOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsICE9PSBcInVuZGVmaW5lZFwiKSBhY2N1bVtrZXldID0gdmFsO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB7fSk7XG5cbiAgICByZXR1cm4gbmV3IHRoaXMuY2xhc3MoT2JqZWN0LmFzc2lnbih7fSwgZXh0cmFjdChvbGRNb2RlbCksIGV4dHJhY3QobW9kZWwpKSk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5jbGFzcy5uYW1lfSBSZXBvc2l0b3J5YDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgZW5mb3JjZURCRGVjb3JhdG9ycyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yLCBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcbmltcG9ydCB7IEJhc2VSZXBvc2l0b3J5IH0gZnJvbSBcIi4vQmFzZVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi9Db250ZXh0XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUmVwb3NpdG9yeTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+IGV4dGVuZHMgQmFzZVJlcG9zaXRvcnk8TSwgRiwgQz4ge1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoY2xheno/OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIHN1cGVyKGNsYXp6KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyBjcmVhdGVQcmVmaXgoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxbTSwgLi4uYW55W11dPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBtb2RlbCA9IG5ldyB0aGlzLmNsYXNzKG1vZGVsKTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzKFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICk7XG5cbiAgICBjb25zdCBlcnJvcnMgPSBtb2RlbC5oYXNFcnJvcnMoKTtcbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycy50b1N0cmluZygpKTtcblxuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChcbiAgICBtb2RlbHM6IE1bXSxcbiAgICAuLi5hcmdzOiBhbnlbXVxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoYXN5bmMgKG0pID0+IHtcbiAgICAgICAgbSA9IG5ldyB0aGlzLmNsYXNzKG0pO1xuICAgICAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgICB9KVxuICAgICk7XG4gICAgY29uc3QgZXJyb3JzID0gbW9kZWxzXG4gICAgICAubWFwKChtKSA9PiBtLmhhc0Vycm9ycygpKVxuICAgICAgLnJlZHVjZSgoYWNjdW06IHN0cmluZyB8IHVuZGVmaW5lZCwgZSwgaSkgPT4ge1xuICAgICAgICBpZiAoZSlcbiAgICAgICAgICBhY2N1bSA9XG4gICAgICAgICAgICB0eXBlb2YgYWNjdW0gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgPyBhY2N1bSArIGBcXG4gLSAke2l9OiAke2UudG9TdHJpbmcoKX1gXG4gICAgICAgICAgICAgIDogYCAtICR7aX06ICR7ZS50b1N0cmluZygpfWA7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sIHVuZGVmaW5lZCk7XG4gICAgaWYgKGVycm9ycykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJvcnMpO1xuICAgIHJldHVybiBbbW9kZWxzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyB1cGRhdGVQcmVmaXgoXG4gICAgbW9kZWw6IE0sXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxbTSwgLi4uYXJnczogYW55W11dPiB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBwayA9IChtb2RlbCBhcyBhbnkpW3RoaXMucGtdO1xuICAgIGlmICghcGspXG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgYE5vIHZhbHVlIGZvciB0aGUgSWQgaXMgZGVmaW5lZCB1bmRlciB0aGUgcHJvcGVydHkgJHt0aGlzLnBrIGFzIHN0cmluZ31gXG4gICAgICApO1xuXG4gICAgY29uc3Qgb2xkTW9kZWw6IE0gPSBhd2FpdCB0aGlzLnJlYWQocGspO1xuXG4gICAgbW9kZWwgPSB0aGlzLm1lcmdlKG9sZE1vZGVsLCBtb2RlbCk7XG5cbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzKFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTixcbiAgICAgIG9sZE1vZGVsXG4gICAgKTtcblxuICAgIGNvbnN0IGVycm9ycyA9IG1vZGVsLmhhc0Vycm9ycyhvbGRNb2RlbCBhcyBhbnkpO1xuICAgIGlmIChlcnJvcnMpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyb3JzLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFzeW5jIHVwZGF0ZUFsbFByZWZpeChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGNvbnN0IGlkcyA9IG1vZGVscy5tYXAoKG0pID0+IHtcbiAgICAgIGNvbnN0IGlkID0gbVt0aGlzLnBrXTtcbiAgICAgIGlmICh0eXBlb2YgaWQgPT09IFwidW5kZWZpbmVkXCIpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFxuICAgICAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7dGhpcy5wayBhcyBzdHJpbmd9YFxuICAgICAgICApO1xuICAgICAgcmV0dXJuIGlkIGFzIHN0cmluZztcbiAgICB9KTtcbiAgICBjb25zdCBvbGRNb2RlbHM6IE1bXSA9IGF3YWl0IHRoaXMucmVhZEFsbChpZHMsIC4uLmNvbnRleHRBcmdzLmFyZ3MpO1xuICAgIG1vZGVscyA9IG1vZGVscy5tYXAoKG0sIGkpID0+IHRoaXMubWVyZ2Uob2xkTW9kZWxzW2ldLCBtKSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtLCBpKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT04sXG4gICAgICAgICAgb2xkTW9kZWxzW2ldXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuXG4gICAgY29uc3QgZXJyb3JzID0gbW9kZWxzXG4gICAgICAubWFwKChtLCBpKSA9PiBtLmhhc0Vycm9ycyhvbGRNb2RlbHNbaV0gYXMgYW55KSlcbiAgICAgIC5yZWR1Y2UoKGFjY3VtOiBzdHJpbmcgfCB1bmRlZmluZWQsIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUpXG4gICAgICAgICAgYWNjdW0gPVxuICAgICAgICAgICAgdHlwZW9mIGFjY3VtID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgID8gYWNjdW0gKyBgXFxuIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YFxuICAgICAgICAgICAgICA6IGAgLSAke2l9OiAke2UudG9TdHJpbmcoKX1gO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LCB1bmRlZmluZWQpO1xuICAgIGlmIChlcnJvcnMpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyb3JzKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICBzdGF0aWMga2V5KGtleTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIERCS2V5cy5SRUZMRUNUICsga2V5O1xuICB9XG59XG4iLCJpbXBvcnQgXCIuL3ZhbGlkYXRpb25cIjtcbmltcG9ydCB7XG4gIGRhdGUsXG4gIERlY29yYXRpb24sXG4gIE1vZGVsLFxuICBwcm9wTWV0YWRhdGEsXG4gIHJlcXVpcmVkLFxuICB0eXBlLFxuICBWYWxpZGF0aW9uLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMsIERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVCB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IERCT3BlcmF0aW9ucywgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgYWZ0ZXIsIG9uLCBvbkNyZWF0ZVVwZGF0ZSB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IFNlcmlhbGl6YXRpb25FcnJvciB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L2Vycm9yc1wiO1xuaW1wb3J0IHsgYXBwbHksIG1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9Db250ZXh0XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS90eXBlc1wiO1xuXG4vKipcbiAqIE1hcmtzIHRoZSBwcm9wZXJ0eSBhcyByZWFkb25seS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5SRUFET05MWS5JTlZBTElEfVxuICpcbiAqIEBkZWNvcmF0b3IgcmVhZG9ubHlcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZG9ubHkoXG4gIG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUkVBRE9OTFkuSU5WQUxJRFxuKSB7XG4gIGNvbnN0IGtleSA9IFZhbGlkYXRpb24udXBkYXRlS2V5KERCS2V5cy5SRUFET05MWSk7XG4gIHJldHVybiBEZWNvcmF0aW9uLmZvcihrZXkpXG4gICAgLmRlZmluZShcbiAgICAgIHByb3BNZXRhZGF0YShrZXksIHtcbiAgICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIH0pXG4gICAgKVxuICAgIC5hcHBseSgpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdGltZXN0YW1wSGFuZGxlcjxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSk6IFByb21pc2U8dm9pZD4ge1xuICAobW9kZWwgYXMgYW55KVtrZXldID0gY29udGV4dC50aW1lc3RhbXA7XG59XG5cbi8qKlxuICogTWFya3MgdGhlIHByb3BlcnR5IGFzIHRpbWVzdGFtcC5cbiAqIE1ha2VzIGl0IHtAbGluayByZXF1aXJlZH1cbiAqIE1ha2VzIGl0IGEge0BsaW5rIGRhdGV9XG4gKlxuICogRGF0ZSBGb3JtYXQ6XG4gKlxuICogPHByZT5cbiAqICAgICAgVXNpbmcgc2ltaWxhciBmb3JtYXR0aW5nIGFzIE1vbWVudC5qcywgQ2xhc3MgRGF0ZVRpbWVGb3JtYXR0ZXIgKEphdmEpLCBhbmQgQ2xhc3MgU2ltcGxlRGF0ZUZvcm1hdCAoSmF2YSksXG4gKiAgICAgIEkgaW1wbGVtZW50ZWQgYSBjb21wcmVoZW5zaXZlIHNvbHV0aW9uIGZvcm1hdERhdGUoZGF0ZSwgcGF0dGVyblN0cikgd2hlcmUgdGhlIGNvZGUgaXMgZWFzeSB0byByZWFkIGFuZCBtb2RpZnkuXG4gKiAgICAgIFlvdSBjYW4gZGlzcGxheSBkYXRlLCB0aW1lLCBBTS9QTSwgZXRjLlxuICpcbiAqICAgICAgRGF0ZSBhbmQgVGltZSBQYXR0ZXJuc1xuICogICAgICB5eSA9IDItZGlnaXQgeWVhcjsgeXl5eSA9IGZ1bGwgeWVhclxuICogICAgICBNID0gZGlnaXQgbW9udGg7IE1NID0gMi1kaWdpdCBtb250aDsgTU1NID0gc2hvcnQgbW9udGggbmFtZTsgTU1NTSA9IGZ1bGwgbW9udGggbmFtZVxuICogICAgICBFRUVFID0gZnVsbCB3ZWVrZGF5IG5hbWU7IEVFRSA9IHNob3J0IHdlZWtkYXkgbmFtZVxuICogICAgICBkID0gZGlnaXQgZGF5OyBkZCA9IDItZGlnaXQgZGF5XG4gKiAgICAgIGggPSBob3VycyBhbS9wbTsgaGggPSAyLWRpZ2l0IGhvdXJzIGFtL3BtOyBIID0gaG91cnM7IEhIID0gMi1kaWdpdCBob3Vyc1xuICogICAgICBtID0gbWludXRlczsgbW0gPSAyLWRpZ2l0IG1pbnV0ZXM7IGFhYSA9IEFNL1BNXG4gKiAgICAgIHMgPSBzZWNvbmRzOyBzcyA9IDItZGlnaXQgc2Vjb25kc1xuICogICAgICBTID0gbWlsaXNlY29uZHNcbiAqIDwvcHJlPlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nW119IG9wZXJhdGlvbiBUaGUge0BsaW5rIERCT3BlcmF0aW9uc30gdG8gYWN0IG9uLiBEZWZhdWx0cyB0byB7QGxpbmsgREJPcGVyYXRpb25zLkNSRUFURV9VUERBVEV9XG4gKiBAcGFyYW0ge3N0cmluZ30gW2Zvcm1hdF0gVGhlIFRpbWVTdGFtcCBmb3JtYXQuIGRlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVR9XG4gKiBAcGFyYW0ge3tuZXc6IFVwZGF0ZVZhbGlkYXRvcn19IFt2YWxpZGF0b3JdIGRlZmF1bHRzIHRvIHtAbGluayBUaW1lc3RhbXBWYWxpZGF0b3J9XG4gKlxuICogQGRlY29yYXRvciB0aW1lc3RhbXBcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdGltZXN0YW1wKFxuICBvcGVyYXRpb246IE9wZXJhdGlvbktleXNbXSA9IERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFIGFzIHVua25vd24gYXMgT3BlcmF0aW9uS2V5c1tdLFxuICBmb3JtYXQ6IHN0cmluZyA9IERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVFxuKSB7XG4gIGNvbnN0IGtleSA9IFZhbGlkYXRpb24udXBkYXRlS2V5KERCS2V5cy5USU1FU1RBTVApO1xuXG4gIGNvbnN0IGRlY29yYXRvcnM6IGFueVtdID0gW1xuICAgIGRhdGUoZm9ybWF0LCBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlRJTUVTVEFNUC5EQVRFKSxcbiAgICByZXF1aXJlZChERUZBVUxUX0VSUk9SX01FU1NBR0VTLlRJTUVTVEFNUC5SRVFVSVJFRCksXG4gICAgb24ob3BlcmF0aW9uLCB0aW1lc3RhbXBIYW5kbGVyKSxcbiAgXTtcblxuICBpZiAob3BlcmF0aW9uLmluZGV4T2YoT3BlcmF0aW9uS2V5cy5VUERBVEUpICE9PSAtMSlcbiAgICBkZWNvcmF0b3JzLnB1c2goXG4gICAgICBwcm9wTWV0YWRhdGEoVmFsaWRhdGlvbi51cGRhdGVLZXkoREJLZXlzLlRJTUVTVEFNUCksIHtcbiAgICAgICAgbWVzc2FnZTogREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuSU5WQUxJRCxcbiAgICAgIH0pXG4gICAgKTtcbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKGtleSlcbiAgICAuZGVmaW5lKC4uLmRlY29yYXRvcnMpXG4gICAgLmFwcGx5KCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXJpYWxpemVPbkNyZWF0ZVVwZGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIW1vZGVsW2tleV0pIHJldHVybjtcbiAgdHJ5IHtcbiAgICBtb2RlbFtrZXldID0gSlNPTi5zdHJpbmdpZnkobW9kZWxba2V5XSkgYXMgTVtrZXlvZiBNXTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgYEZhaWxlZCB0byBzZXJpYWxpemUgJHtrZXkudG9TdHJpbmcoKX0gcHJvcGVydHkgb2YgbW9kZWwgJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfTogZWBcbiAgICApO1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXJpYWxpemVBZnRlckFsbDxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIW1vZGVsW2tleV0pIHJldHVybjtcbiAgaWYgKHR5cGVvZiBtb2RlbFtrZXldICE9PSBcInN0cmluZ1wiKSByZXR1cm47XG5cbiAgdHJ5IHtcbiAgICBtb2RlbFtrZXldID0gSlNPTi5wYXJzZShtb2RlbFtrZXldKTtcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIGRlc2VyaWFsaXplICR7a2V5LnRvU3RyaW5nKCl9IHByb3BlcnR5IG9mIG1vZGVsICR7bW9kZWwuY29uc3RydWN0b3IubmFtZX06ICR7ZX1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFNlcmlhbGl6ZSBEZWNvcmF0b3JcbiAqIEBkZXNjcmlwdGlvbiBwcm9wZXJ0aWVzIGRlY29yYXRlZCB3aWxsIHRoZSBzZXJpYWxpemVkIGJlZm9yZSBzdG9yZWQgaW4gdGhlIGRiXG4gKlxuICogQGZ1bmN0aW9uIHNlcmlhbGl6ZVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6d2FsbGV0LWRiLkRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlcmlhbGl6ZSgpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIG9uQ3JlYXRlVXBkYXRlKHNlcmlhbGl6ZU9uQ3JlYXRlVXBkYXRlKSxcbiAgICBhZnRlcihEQk9wZXJhdGlvbnMuQUxMLCBzZXJpYWxpemVBZnRlckFsbCksXG4gICAgdHlwZShbU3RyaW5nLm5hbWUsIE9iamVjdC5uYW1lXSksXG4gICAgbWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLlNFUklBTElaRSksIHt9KVxuICApO1xufVxuIiwiaW1wb3J0IHsgcHJvcE1ldGFkYXRhLCByZXF1aXJlZCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IHJlYWRvbmx5IH0gZnJvbSBcIi4uL3ZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgYXBwbHkgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGlkKCkge1xuICByZXR1cm4gYXBwbHkoXG4gICAgcmVxdWlyZWQoKSxcbiAgICByZWFkb25seSgpLFxuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuSUQpLCB7fSlcbiAgKTtcbn1cbiIsImltcG9ydCB7XG4gIE1vZGVsLFxuICBNb2RlbEVycm9yRGVmaW5pdGlvbixcbiAgTW9kZWxFcnJvcnMsXG4gIE1vZGVsS2V5cyxcbiAgUmVzZXJ2ZWRNb2RlbHMsXG4gIHNmLFxuICBWYWxpZGF0YWJsZSxcbiAgVmFsaWRhdGlvbixcbiAgVmFsaWRhdGlvbktleXMsXG4gIFZhbGlkYXRpb25Qcm9wZXJ0eURlY29yYXRvckRlZmluaXRpb24sXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERlY29yYXRvck1ldGFkYXRhLCBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBVcGRhdGVWYWxpZGF0aW9uS2V5cywgVXBkYXRlVmFsaWRhdG9yIH0gZnJvbSBcIi4uL3ZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGZpbmRNb2RlbElkIH0gZnJvbSBcIi4uL2lkZW50aXR5XCI7XG5cbi8qKlxuICogQHN1bW1hcnkgVmFsaWRhdGVzIHRoZSB1cGRhdGUgb2YgYSBtb2RlbFxuICpcbiAqIEBwYXJhbSB7VH0gb2xkTW9kZWxcbiAqIEBwYXJhbSB7VH0gbmV3TW9kZWxcbiAqIEBwYXJhbSB7c3RyaW5nW119IFtleGNlcHRpb25zXVxuICpcbiAqIEBmdW5jdGlvbiB2YWxpZGF0ZUNvbXBhcmVcbiAqIEByZXR1cm4ge01vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkfVxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5Nb2RlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVDb21wYXJlPE0gZXh0ZW5kcyBNb2RlbD4oXG4gIG9sZE1vZGVsOiBNLFxuICBuZXdNb2RlbDogTSxcbiAgLi4uZXhjZXB0aW9uczogc3RyaW5nW11cbik6IE1vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGVjb3JhdGVkUHJvcGVydGllczogVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbltdID0gW107XG4gIGZvciAoY29uc3QgcHJvcCBpbiBuZXdNb2RlbClcbiAgICBpZiAoXG4gICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobmV3TW9kZWwsIHByb3ApICYmXG4gICAgICBleGNlcHRpb25zLmluZGV4T2YocHJvcCkgPT09IC0xXG4gICAgKVxuICAgICAgZGVjb3JhdGVkUHJvcGVydGllcy5wdXNoKFxuICAgICAgICBSZWZsZWN0aW9uLmdldFByb3BlcnR5RGVjb3JhdG9ycyhcbiAgICAgICAgICBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgICAgIG5ld01vZGVsLFxuICAgICAgICAgIHByb3BcbiAgICAgICAgKSBhcyBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uXG4gICAgICApO1xuXG4gIGxldCByZXN1bHQ6IE1vZGVsRXJyb3JzIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIGZvciAoY29uc3QgZGVjb3JhdGVkUHJvcGVydHkgb2YgZGVjb3JhdGVkUHJvcGVydGllcykge1xuICAgIGNvbnN0IHsgcHJvcCwgZGVjb3JhdG9ycyB9ID0gZGVjb3JhdGVkUHJvcGVydHk7XG5cbiAgICBkZWNvcmF0b3JzLnNoaWZ0KCk7IC8vIHJlbW92ZSB0aGUgZGVzaWduOnR5cGUgZGVjb3JhdG9yLCBzaW5jZSB0aGUgdHlwZSB3aWxsIGFscmVhZHkgYmUgY2hlY2tlZFxuXG4gICAgaWYgKCFkZWNvcmF0b3JzIHx8ICFkZWNvcmF0b3JzLmxlbmd0aCkgY29udGludWU7XG4gICAgbGV0IGVycnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgICBmb3IgKGNvbnN0IGRlY29yYXRvciBvZiBkZWNvcmF0b3JzKSB7XG4gICAgICBjb25zdCB2YWxpZGF0b3I6IFVwZGF0ZVZhbGlkYXRvciA9IFZhbGlkYXRpb24uZ2V0KFxuICAgICAgICBkZWNvcmF0b3Iua2V5XG4gICAgICApIGFzIFVwZGF0ZVZhbGlkYXRvcjtcbiAgICAgIGlmICghdmFsaWRhdG9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgYENvdWxkIG5vdCBmaW5kIE1hdGNoaW5nIHZhbGlkYXRvciBmb3IgJHtkZWNvcmF0b3Iua2V5fSBmb3IgcHJvcGVydHkgJHtTdHJpbmcoZGVjb3JhdGVkUHJvcGVydHkucHJvcCl9YFxuICAgICAgICApO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB2YWxpZGF0b3IudXBkYXRlSGFzRXJyb3JzKFxuICAgICAgICAobmV3TW9kZWwgYXMgYW55KVtwcm9wLnRvU3RyaW5nKCldLFxuICAgICAgICAob2xkTW9kZWwgYXMgYW55KVtwcm9wLnRvU3RyaW5nKCldLFxuICAgICAgICAuLi5PYmplY3QudmFsdWVzKGRlY29yYXRvci5wcm9wcylcbiAgICAgICk7XG5cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgZXJycyA9IGVycnMgfHwge307XG4gICAgICAgIGVycnNbZGVjb3JhdG9yLmtleV0gPSBlcnI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVycnMpIHtcbiAgICAgIHJlc3VsdCA9IHJlc3VsdCB8fCB7fTtcbiAgICAgIHJlc3VsdFtkZWNvcmF0ZWRQcm9wZXJ0eS5wcm9wLnRvU3RyaW5nKCldID0gZXJycztcbiAgICB9XG4gIH1cbiAgLy8gdGVzdHMgbmVzdGVkIGNsYXNzZXNcbiAgZm9yIChjb25zdCBwcm9wIG9mIE9iamVjdC5rZXlzKG5ld01vZGVsKS5maWx0ZXIoKGspID0+IHtcbiAgICBpZiAoZXhjZXB0aW9ucy5pbmNsdWRlcyhrKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiAhcmVzdWx0IHx8ICFyZXN1bHRba107XG4gIH0pKSB7XG4gICAgbGV0IGVycjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIC8vIGlmIGEgbmVzdGVkIE1vZGVsXG4gICAgY29uc3QgYWxsRGVjb3JhdG9ycyA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgVmFsaWRhdGlvbktleXMuUkVGTEVDVCxcbiAgICAgIG5ld01vZGVsLFxuICAgICAgcHJvcFxuICAgICkuZGVjb3JhdG9ycztcbiAgICBjb25zdCBkZWNvcmF0b3JzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgbmV3TW9kZWwsXG4gICAgICBwcm9wXG4gICAgKS5kZWNvcmF0b3JzLmZpbHRlcihcbiAgICAgIChkKSA9PiBbTW9kZWxLZXlzLlRZUEUsIFZhbGlkYXRpb25LZXlzLlRZUEVdLmluZGV4T2YoZC5rZXkgYXMgYW55KSAhPT0gLTFcbiAgICApO1xuICAgIGlmICghZGVjb3JhdG9ycyB8fCAhZGVjb3JhdG9ycy5sZW5ndGgpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGRlYyA9IGRlY29yYXRvcnMucG9wKCkgYXMgRGVjb3JhdG9yTWV0YWRhdGE7XG4gICAgY29uc3QgY2xhenogPSBkZWMucHJvcHMubmFtZVxuICAgICAgPyBbZGVjLnByb3BzLm5hbWVdXG4gICAgICA6IEFycmF5LmlzQXJyYXkoZGVjLnByb3BzLmN1c3RvbVR5cGVzKVxuICAgICAgICA/IGRlYy5wcm9wcy5jdXN0b21UeXBlc1xuICAgICAgICA6IFtkZWMucHJvcHMuY3VzdG9tVHlwZXNdO1xuICAgIGNvbnN0IHJlc2VydmVkID0gT2JqZWN0LnZhbHVlcyhSZXNlcnZlZE1vZGVscykubWFwKCh2KSA9PlxuICAgICAgdi50b0xvd2VyQ2FzZSgpXG4gICAgKSBhcyBzdHJpbmdbXTtcblxuICAgIGZvciAoY29uc3QgYyBvZiBjbGF6eikge1xuICAgICAgaWYgKHJlc2VydmVkLmluZGV4T2YoYy50b0xvd2VyQ2FzZSgpKSA9PT0gLTEpIHtcbiAgICAgICAgc3dpdGNoIChjKSB7XG4gICAgICAgICAgY2FzZSBBcnJheS5uYW1lOlxuICAgICAgICAgIGNhc2UgU2V0Lm5hbWU6XG4gICAgICAgICAgICBpZiAoYWxsRGVjb3JhdG9ycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgY29uc3QgbGlzdERlYyA9IGFsbERlY29yYXRvcnMuZmluZChcbiAgICAgICAgICAgICAgICAoZCkgPT4gZC5rZXkgPT09IFZhbGlkYXRpb25LZXlzLkxJU1RcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgaWYgKGxpc3REZWMpIHtcbiAgICAgICAgICAgICAgICBsZXQgY3VycmVudExpc3QsIG9sZExpc3Q7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGMpIHtcbiAgICAgICAgICAgICAgICAgIGNhc2UgQXJyYXkubmFtZTpcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudExpc3QgPSAobmV3TW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF07XG4gICAgICAgICAgICAgICAgICAgIG9sZExpc3QgPSAob2xkTW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF07XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgY2FzZSBTZXQubmFtZTpcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudExpc3QgPSAobmV3TW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55PilbXG4gICAgICAgICAgICAgICAgICAgICAgcHJvcFxuICAgICAgICAgICAgICAgICAgICBdLnZhbHVlcygpO1xuICAgICAgICAgICAgICAgICAgICBvbGRMaXN0ID0gKG9sZE1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdLnZhbHVlcygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhdHRyaWJ1dGUgdHlwZSAke2N9YCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZXJyID0gY3VycmVudExpc3RcbiAgICAgICAgICAgICAgICAgIC5tYXAoKHY6IFZhbGlkYXRhYmxlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlkID0gZmluZE1vZGVsSWQodiBhcyBhbnksIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlkKSByZXR1cm4gXCJGYWlsZWQgdG8gZmluZCBtb2RlbCBpZFwiO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBvbGRNb2RlbCA9IG9sZExpc3QuZmluZChcbiAgICAgICAgICAgICAgICAgICAgICAoZWw6IGFueSkgPT4gaWQgPT09IGZpbmRNb2RlbElkKGVsLCB0cnVlKVxuICAgICAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghb2xkTW9kZWwpIHJldHVybjsgLy8gbm90aGluZyB0byBjb21wYXJlIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHYuaGFzRXJyb3JzKG9sZE1vZGVsKTtcbiAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAuZmlsdGVyKChlOiBhbnkpID0+ICEhZSkgYXMgYW55O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFlcnI/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlc3VsdCBpcyBhbiBlbXB0eSBsaXN0Li4uXG4gICAgICAgICAgICAgICAgICBlcnIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIChuZXdNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXSAmJlxuICAgICAgICAgICAgICAgIChvbGRNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgZXJyID0gKG5ld01vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdLmhhc0Vycm9ycyhcbiAgICAgICAgICAgICAgICAgIChvbGRNb2RlbCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oc2YoXCJNb2RlbCBzaG91bGQgYmUgdmFsaWRhdGFibGUgYnV0IGl0cyBub3RcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdCB8fCB7fTtcbiAgICAgICAgcmVzdWx0W3Byb3BdID0gZXJyIGFzIGFueTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdCA/IG5ldyBNb2RlbEVycm9yRGVmaW5pdGlvbihyZXN1bHQpIDogdW5kZWZpbmVkO1xufVxuIiwiaW1wb3J0IHsgREJLZXlzLCBEZWZhdWx0U2VwYXJhdG9yIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBhcHBseSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHtcbiAgSGFzaGluZyxcbiAgTW9kZWwsXG4gIHByb3BNZXRhZGF0YSxcbiAgdHlwZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgb25DcmVhdGUsIG9uQ3JlYXRlVXBkYXRlLCBvblVwZGF0ZSB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9lcnJvcnNcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9SZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvQ29udGV4dFwiO1xuaW1wb3J0IHsgQ3J1ZE9wZXJhdGlvbnMsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdHlwZXNcIjtcblxuLyoqXG4gKlxuICogQHBhcmFtIHtzdHJ9IHN0clxuICogQG1lbWJlck9mIGRiLWRlY29yYXRvcnMubW9kZWxcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaGFzaE9uQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgViBleHRlbmRzIG9iamVjdCxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPih0aGlzOiBSLCBjb250ZXh0OiBDLCBkYXRhOiBWLCBrZXk6IGtleW9mIE0sIG1vZGVsOiBNLCBvbGRNb2RlbD86IE0pOiB2b2lkIHtcbiAgaWYgKHR5cGVvZiBtb2RlbFtrZXldID09PSBcInVuZGVmaW5lZFwiKSByZXR1cm47XG4gIGNvbnN0IGhhc2ggPSBIYXNoaW5nLmhhc2goKG1vZGVsIGFzIGFueSlba2V5XSk7XG4gIGlmIChvbGRNb2RlbCAmJiAobW9kZWwgYXMgYW55KVtrZXldID09PSBoYXNoKSByZXR1cm47XG4gIG1vZGVsW2tleV0gPSBoYXNoO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzaCgpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIG9uQ3JlYXRlVXBkYXRlKGhhc2hPbkNyZWF0ZVVwZGF0ZSksXG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5IQVNIKSwge30pXG4gICk7XG59XG5cbmV4cG9ydCB0eXBlIENvbXBvc2VkRnJvbU1ldGFkYXRhID0ge1xuICBhcmdzOiBzdHJpbmdbXTtcbiAgc2VwYXJhdG9yOiBzdHJpbmc7XG4gIGhhc2hSZXN1bHQ6IGJvb2xlYW47XG4gIHR5cGU6IFwia2V5c1wiIHwgXCJ2YWx1ZXNcIjtcbiAgcHJlZml4Pzogc3RyaW5nO1xuICBzdWZmaXg/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zZWRGcm9tQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgViBleHRlbmRzIENvbXBvc2VkRnJvbU1ldGFkYXRhLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pIHtcbiAgdHJ5IHtcbiAgICBjb25zdCB7IGFyZ3MsIHR5cGUsIHByZWZpeCwgc3VmZml4LCBzZXBhcmF0b3IgfSA9IGRhdGE7XG4gICAgY29uc3QgY29tcG9zZWQgPSBhcmdzLm1hcCgoYXJnOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghKGFyZyBpbiBtb2RlbCkpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBQcm9wZXJ0eSAke2FyZ30gbm90IGZvdW5kIHRvIGNvbXBvc2UgZnJvbWApO1xuICAgICAgaWYgKHR5cGUgPT09IFwia2V5c1wiKSByZXR1cm4gYXJnO1xuICAgICAgaWYgKHR5cGVvZiAobW9kZWwgYXMgYW55KVthcmddID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgUHJvcGVydHkgJHthcmdzfSBkb2VzIG5vdCBjb250YWluIGEgdmFsdWUgdG8gY29tcG9zZSBmcm9tYFxuICAgICAgICApO1xuICAgICAgcmV0dXJuICgobW9kZWwgYXMgYW55KVthcmddIGFzIGFueSkudG9TdHJpbmcoKTtcbiAgICB9KTtcblxuICAgIGlmIChwcmVmaXgpIGNvbXBvc2VkLnVuc2hpZnQocHJlZml4KTtcbiAgICBpZiAoc3VmZml4KSBjb21wb3NlZC5wdXNoKHN1ZmZpeCk7XG5cbiAgICAobW9kZWwgYXMgYW55KVtrZXldID0gY29tcG9zZWQuam9pbihzZXBhcmF0b3IpO1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgRmFpbGVkIHRvIGNvbXBvc2UgdmFsdWU6ICR7ZX1gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb21wb3NlZEZyb20oXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBoYXNoUmVzdWx0OiBib29sZWFuID0gZmFsc2UsXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgdHlwZTogXCJrZXlzXCIgfCBcInZhbHVlc1wiID0gXCJ2YWx1ZXNcIixcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIGNvbnN0IGRhdGE6IENvbXBvc2VkRnJvbU1ldGFkYXRhID0ge1xuICAgIGFyZ3M6IGFyZ3MsXG4gICAgaGFzaFJlc3VsdDogaGFzaFJlc3VsdCxcbiAgICBzZXBhcmF0b3I6IHNlcGFyYXRvcixcbiAgICB0eXBlOiB0eXBlLFxuICAgIHByZWZpeDogcHJlZml4LFxuICAgIHN1ZmZpeDogc3VmZml4LFxuICB9O1xuXG4gIGNvbnN0IGRlY29yYXRvcnMgPSBbXG4gICAgb25DcmVhdGVVcGRhdGUoY29tcG9zZWRGcm9tQ3JlYXRlVXBkYXRlLCBkYXRhKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLkNPTVBPU0VEKSwgZGF0YSksXG4gIF07XG4gIGlmIChoYXNoUmVzdWx0KSBkZWNvcmF0b3JzLnB1c2goaGFzaCgpKTtcbiAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zZWRGcm9tS2V5cyhcbiAgYXJnczogc3RyaW5nW10sXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgaGFzaDogYm9vbGVhbiA9IGZhbHNlLFxuICBwcmVmaXggPSBcIlwiLFxuICBzdWZmaXggPSBcIlwiXG4pIHtcbiAgcmV0dXJuIGNvbXBvc2VkRnJvbShhcmdzLCBoYXNoLCBzZXBhcmF0b3IsIFwia2V5c1wiLCBwcmVmaXgsIHN1ZmZpeCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wb3NlZChcbiAgYXJnczogc3RyaW5nW10sXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgaGFzaDogYm9vbGVhbiA9IGZhbHNlLFxuICBwcmVmaXggPSBcIlwiLFxuICBzdWZmaXggPSBcIlwiXG4pIHtcbiAgcmV0dXJuIGNvbXBvc2VkRnJvbShhcmdzLCBoYXNoLCBzZXBhcmF0b3IsIFwidmFsdWVzXCIsIHByZWZpeCwgc3VmZml4KTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVjb3JhdG9yIGZ1bmN0aW9uIHRoYXQgdXBkYXRlcyB0aGUgdmVyc2lvbiBvZiBhIG1vZGVsIGR1cmluZyBjcmVhdGUgb3IgdXBkYXRlIG9wZXJhdGlvbnMuXG4gKlxuICogQHBhcmFtIHtDcnVkT3BlcmF0aW9uc30gb3BlcmF0aW9uIC0gVGhlIHR5cGUgb2Ygb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZCAoQ1JFQVRFIG9yIFVQREFURSkuXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IEEgZnVuY3Rpb24gdGhhdCB1cGRhdGVzIHRoZSB2ZXJzaW9uIG9mIHRoZSBtb2RlbCBiYXNlZCBvbiB0aGUgb3BlcmF0aW9uIHR5cGUuXG4gKlxuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFYgLSBUeXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeTxNPlxuICpcbiAqIEB0aGlzIHtWfSAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8TT59IGNvbnRleHQgLSBUaGUgY29udGV4dCBvZiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge3Vua25vd259IGRhdGEgLSBBZGRpdGlvbmFsIGRhdGEgZm9yIHRoZSBvcGVyYXRpb24gKG5vdCB1c2VkIGluIHRoaXMgZnVuY3Rpb24pXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSBvZiB0aGUgdmVyc2lvbiBwcm9wZXJ0eSBpbiB0aGUgbW9kZWxcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgYmVpbmcgdXBkYXRlZFxuICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgYW4gaW52YWxpZCBvcGVyYXRpb24gaXMgcHJvdmlkZWQgb3IgaWYgdmVyc2lvbiB1cGRhdGUgZmFpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcnNpb25DcmVhdGVVcGRhdGUob3BlcmF0aW9uOiBDcnVkT3BlcmF0aW9ucykge1xuICByZXR1cm4gZnVuY3Rpb24gdmVyc2lvbkNyZWF0ZVVwZGF0ZTxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICAgIFYgZXh0ZW5kcyBvYmplY3QsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSkge1xuICAgIHRyeSB7XG4gICAgICBzd2l0Y2ggKG9wZXJhdGlvbikge1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuQ1JFQVRFOlxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpW2tleV0gPSAxO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuVVBEQVRFOlxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpW2tleV0rKztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgSW52YWxpZCBvcGVyYXRpb246ICR7b3BlcmF0aW9ufWApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBGYWlsZWQgdG8gdXBkYXRlIHZlcnNpb246ICR7ZX1gKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgZm9yIHZlcnNpb25pbmcgYSBwcm9wZXJ0eSBpbiBhIG1vZGVsLlxuICogQHN1bW1hcnkgVGhpcyBkZWNvcmF0b3IgYXBwbGllcyBtdWx0aXBsZSBzdWItZGVjb3JhdG9ycyB0byBoYW5kbGUgdmVyc2lvbiBtYW5hZ2VtZW50IGR1cmluZyBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zLlxuICpcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gQSBjb21wb3NpdGUgZGVjb3JhdG9yIHRoYXQ6XG4gKiAgIC0gU2V0cyB0aGUgdHlwZSBvZiB0aGUgcHJvcGVydHkgdG8gTnVtYmVyXG4gKiAgIC0gQXBwbGllcyBhIHZlcnNpb24gdXBkYXRlIG9uIGNyZWF0ZSBvcGVyYXRpb25zXG4gKiAgIC0gQXBwbGllcyBhIHZlcnNpb24gdXBkYXRlIG9uIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiAgIC0gQWRkcyBtZXRhZGF0YSBpbmRpY2F0aW5nIHRoaXMgcHJvcGVydHkgaXMgdXNlZCBmb3IgdmVyc2lvbmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvbigpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIHR5cGUoTnVtYmVyLm5hbWUpLFxuICAgIG9uQ3JlYXRlKHZlcnNpb25DcmVhdGVVcGRhdGUoT3BlcmF0aW9uS2V5cy5DUkVBVEUpKSxcbiAgICBvblVwZGF0ZSh2ZXJzaW9uQ3JlYXRlVXBkYXRlKE9wZXJhdGlvbktleXMuVVBEQVRFKSksXG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5WRVJTSU9OKSwgdHJ1ZSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zaWVudCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHRyYW5zaWVudChtb2RlbDogYW55LCBhdHRyaWJ1dGU6IHN0cmluZykge1xuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKSwgdHJ1ZSkobW9kZWwsIGF0dHJpYnV0ZSk7XG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLCB0cnVlKShtb2RlbC5jb25zdHJ1Y3Rvcik7XG4gIH07XG59XG4iLCJpbXBvcnQge1xuICBDb21wYXJhYmxlLFxuICBIYXNoYWJsZSxcbiAgTW9kZWxBcmcsXG4gIE1vZGVsRXJyb3JEZWZpbml0aW9uLFxuICBTZXJpYWxpemFibGUsXG4gIFZhbGlkYXRhYmxlLFxuICBNb2RlbCxcbiAgdmFsaWRhdGUsXG4gIENvbnN0cnVjdG9yLFxuICBNb2RlbEJ1aWxkZXJGdW5jdGlvbixcbiAgQnVpbGRlclJlZ2lzdHJ5LFxuICBNb2RlbENvbnN0cnVjdG9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyB2YWxpZGF0ZUNvbXBhcmUgfSBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5cbk1vZGVsLnByb3RvdHlwZS5oYXNFcnJvcnMgPSBmdW5jdGlvbiA8TSBleHRlbmRzIE1vZGVsPihcbiAgdGhpczogTSxcbiAgcHJldmlvdXNWZXJzaW9uPzogTSB8IGFueSxcbiAgLi4uZXhjbHVzaW9uczogYW55W11cbik6IE1vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHByZXZpb3VzVmVyc2lvbiAmJiAhKHByZXZpb3VzVmVyc2lvbiBpbnN0YW5jZW9mIE1vZGVsKSkge1xuICAgIGV4Y2x1c2lvbnMudW5zaGlmdChwcmV2aW91c1ZlcnNpb24pO1xuICAgIHByZXZpb3VzVmVyc2lvbiA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IGVycnMgPSB2YWxpZGF0ZSh0aGlzLCAuLi5leGNsdXNpb25zKTtcbiAgaWYgKGVycnMgfHwgIXByZXZpb3VzVmVyc2lvbikgcmV0dXJuIGVycnM7XG5cbiAgcmV0dXJuIHZhbGlkYXRlQ29tcGFyZShwcmV2aW91c1ZlcnNpb24sIHRoaXMsIC4uLmV4Y2x1c2lvbnMpO1xufTtcblxuZGVjbGFyZSBtb2R1bGUgXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIiB7XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvYmFuLXRzLWNvbW1lbnRcbiAgLy8gQHRzLWV4cGVjdC1lcnJvclxuICBkZWNsYXJlIGFic3RyYWN0IGNsYXNzIE1vZGVsXG4gICAgaW1wbGVtZW50cyBWYWxpZGF0YWJsZSwgU2VyaWFsaXphYmxlLCBIYXNoYWJsZSwgQ29tcGFyYWJsZTxNb2RlbD5cbiAge1xuICAgIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihhcmc/OiBNb2RlbEFyZzxNb2RlbD4pO1xuXG4gICAgaGFzRXJyb3JzKC4uLmV4Y2x1c2lvbnM6IGFueVtdKTogTW9kZWxFcnJvckRlZmluaXRpb24gfCB1bmRlZmluZWQ7XG4gICAgaGFzRXJyb3JzKFxuICAgICAgcHJldmlvdXNWZXJzaW9uPzogTW9kZWwgfCBhbnksXG4gICAgICAuLi5leGNsdXNpb25zOiBhbnlbXVxuICAgICk6IE1vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgQ29tcGFyZSBvYmplY3QgZXF1YWxpdHkgcmVjdXJzaXZlbHlcbiAgICAgKiBAcGFyYW0ge2FueX0gb2JqIG9iamVjdCB0byBjb21wYXJlIHRvXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtleGNlcHRpb25zXSBwcm9wZXJ0eSBuYW1lcyB0byBiZSBleGNsdWRlZCBmcm9tIHRoZSBjb21wYXJpc29uXG4gICAgICovXG4gICAgZXF1YWxzKG9iajogYW55LCAuLi5leGNlcHRpb25zOiBzdHJpbmdbXSk6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSBzZXJpYWxpemVkIG1vZGVsIGFjY29yZGluZyB0byB0aGUgY3VycmVudGx5IGRlZmluZWQge0BsaW5rIFNlcmlhbGl6ZXJ9XG4gICAgICovXG4gICAgc2VyaWFsaXplKCk6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IE92ZXJyaWRlIHRoZSBpbXBsZW1lbnRhdGlvbiBmb3IganMncyAndG9TdHJpbmcoKScgd2hpY2ggc3Vja3MuLi5cbiAgICAgKiBAb3ZlcnJpZGVcbiAgICAgKi9cbiAgICB0b1N0cmluZygpOiBzdHJpbmc7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBEZWZpbmVzIGEgZGVmYXVsdCBpbXBsZW1lbnRhdGlvbiBmb3Igb2JqZWN0IGhhc2guIFJlbGllcyBvbiBhIHZlcnkgYmFzaWMgaW1wbGVtZW50YXRpb24gYmFzZWQgb24gSmF2YSdzIHN0cmluZyBoYXNoO1xuICAgICAqL1xuICAgIGhhc2goKTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgRGVzZXJpYWxpemVzIGEgTW9kZWxcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gICAgICpcbiAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgaXQgZmFpbHMgdG8gcGFyc2UgdGhlIHN0cmluZywgb3IgaWYgaXQgZmFpbHMgdG8gYnVpbGQgdGhlIG1vZGVsXG4gICAgICovXG4gICAgc3RhdGljIGRlc2VyaWFsaXplKHN0cjogc3RyaW5nKTogYW55O1xuXG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgUmVwb3B1bGF0ZXMgdGhlIE9iamVjdCBwcm9wZXJ0aWVzIHdpdGggdGhlIG9uZXMgZnJvbSB0aGUgbmV3IG9iamVjdFxuICAgICAqIEBkZXNjcmlwdGlvbiBJdGVyYXRlcyBhbGwgY29tbW9uIHByb3BlcnRpZXMgb2Ygb2JqIChpZiBleGlzdGluZykgYW5kIHNlbGYsIGFuZCBjb3BpZXMgdGhlbSBvbnRvIHNlbGZcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7VH0gc2VsZlxuICAgICAqIEBwYXJhbSB7VCB8IFJlY29yZDxzdHJpbmcsIGFueT59IFtvYmpdXG4gICAgICpcbiAgICAgKi9cbiAgICBzdGF0aWMgZnJvbU9iamVjdDxUIGV4dGVuZHMgTW9kZWw+KFxuICAgICAgc2VsZjogVCxcbiAgICAgIG9iaj86IFQgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICAgKTogVDtcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJlcG9wdWxhdGVzIHRoZSBpbnN0YW5jZSB3aXRoIHRoZSBvbmVzIGZyb20gdGhlIG5ldyBNb2RlbCBPYmplY3RcbiAgICAgKiBAZGVzY3JpcHRpb24gSXRlcmF0ZXMgYWxsIGNvbW1vbiBwcm9wZXJ0aWVzIG9mIG9iaiAoaWYgZXhpc3RpbmcpIGFuZCBzZWxmLCBhbmQgY29waWVzIHRoZW0gb250byBzZWxmLlxuICAgICAqIElzIGF3YXJlIG9mIG5lc3RlZCBNb2RlbCBPYmplY3RzIGFuZCByZWJ1aWxkcyB0aGVtIGFsc28uXG4gICAgICogV2hlbiBMaXN0IHByb3BlcnRpZXMgYXJlIGRlY29yYXRlZCB3aXRoIHtAbGluayBsaXN0fSwgdGhleSBsaXN0IGl0ZW1zIHdpbGwgYWxzbyBiZSByZWJ1aWx0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1R9IHNlbGZcbiAgICAgKiBAcGFyYW0ge1QgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+fSBbb2JqXVxuICAgICAqXG4gICAgICovXG4gICAgc3RhdGljIGZyb21Nb2RlbDxUIGV4dGVuZHMgTW9kZWw+KFxuICAgICAgc2VsZjogVCxcbiAgICAgIG9iaj86IFQgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+XG4gICAgKTogVDtcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFNldHMgdGhlIEdsb2JhbCB7QGxpbmsgTW9kZWxCdWlsZGVyRnVuY3Rpb259XG4gICAgICogQHBhcmFtIHtNb2RlbEJ1aWxkZXJGdW5jdGlvbn0gW2J1aWxkZXJdXG4gICAgICovXG4gICAgc3RhdGljIHNldEJ1aWxkZXIoYnVpbGRlcj86IE1vZGVsQnVpbGRlckZ1bmN0aW9uKTogdm9pZDtcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgY3VycmVudCBnbG9iYWwge0BsaW5rIE1vZGVsQnVpbGRlckZ1bmN0aW9ufVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRCdWlsZGVyKCk6IE1vZGVsQnVpbGRlckZ1bmN0aW9uIHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgY3VycmVudCB7QGxpbmsgTW9kZWxSZWdpc3RyeU1hbmFnZXJ9XG4gICAgICpcbiAgICAgKiBAcmV0dXJuIE1vZGVsUmVnaXN0cnksIGRlZmF1bHRzIHRvIHtAbGluayBNb2RlbFJlZ2lzdHJ5TWFuYWdlcn1cbiAgICAgKi9cbiAgICBwcml2YXRlIHN0YXRpYyBnZXRSZWdpc3RyeTtcblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGN1cnJlbnQgYWN0aW5nTW9kZWxSZWdpc3RyeVxuICAgICAqXG4gICAgICogQHBhcmFtIHtCdWlsZGVyUmVnaXN0cnl9IG1vZGVsUmVnaXN0cnkgdGhlIG5ldyBpbXBsZW1lbnRhdGlvbiBvZiBSZWdpc3RyeVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRSZWdpc3RyeShtb2RlbFJlZ2lzdHJ5OiBCdWlsZGVyUmVnaXN0cnk8YW55Pik6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSByZWdpc3RlciBuZXcgTW9kZWxzXG4gICAgICogQHBhcmFtIHthbnl9IGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFtuYW1lXSB3aGVuIG5vdCBkZWZpbmVkLCB0aGUgbmFtZSBvZiB0aGUgY29uc3RydWN0b3Igd2lsbCBiZSB1c2VkXG4gICAgICpcbiAgICAgKiBAc2VlIE1vZGVsUmVnaXN0cnlcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVnaXN0ZXI8VCBleHRlbmRzIE1vZGVsPihcbiAgICAgIGNvbnN0cnVjdG9yOiBNb2RlbENvbnN0cnVjdG9yPFQ+LFxuICAgICAgbmFtZT86IHN0cmluZ1xuICAgICk6IHZvaWQ7XG5cbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBHZXRzIGEgcmVnaXN0ZXJlZCBNb2RlbCB7QGxpbmsgTW9kZWxDb25zdHJ1Y3Rvcn1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqXG4gICAgICogQHNlZSBNb2RlbFJlZ2lzdHJ5XG4gICAgICovXG4gICAgc3RhdGljIGdldDxUIGV4dGVuZHMgTW9kZWw+KG5hbWU6IHN0cmluZyk6IE1vZGVsQ29uc3RydWN0b3I8VD4gfCB1bmRlZmluZWQ7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IG9ialxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBbY2xhenpdIHdoZW4gcHJvdmlkZWQsIGl0IHdpbGwgYXR0ZW1wdCB0byBmaW5kIHRoZSBtYXRjaGluZyBjb25zdHJ1Y3RvclxuICAgICAqXG4gICAgICogQHRocm93cyBFcnJvciBJZiBjbGF6eiBpcyBub3QgZm91bmQsIG9yIG9iaiBpcyBub3QgYSB7QGxpbmsgTW9kZWx9IG1lYW5pbmcgaXQgaGFzIG5vIHtAbGluayBNb2RlbEtleXMuQU5DSE9SfSBwcm9wZXJ0eVxuICAgICAqXG4gICAgICogQHNlZSBNb2RlbFJlZ2lzdHJ5XG4gICAgICovXG4gICAgc3RhdGljIGJ1aWxkPFQgZXh0ZW5kcyBNb2RlbD4ob2JqPzogUmVjb3JkPHN0cmluZywgYW55PiwgY2xheno/OiBzdHJpbmcpOiBUO1xuXG4gICAgc3RhdGljIGdldE1ldGFkYXRhPFYgZXh0ZW5kcyBNb2RlbD4obW9kZWw6IFYpOiBhbnk7XG5cbiAgICBzdGF0aWMgZ2V0QXR0cmlidXRlczxWIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBDb25zdHJ1Y3RvcjxWPiB8IFYpOiBzdHJpbmdbXTtcblxuICAgIHN0YXRpYyBlcXVhbHM8TSBleHRlbmRzIE1vZGVsPihcbiAgICAgIG9iajE6IE0sXG4gICAgICBvYmoyOiBNLFxuICAgICAgLi4uZXhjZXB0aW9uczogYW55W11cbiAgICApOiBib29sZWFuO1xuXG4gICAgc3RhdGljIGhhc0Vycm9yczxNIGV4dGVuZHMgTW9kZWw+KFxuICAgICAgbW9kZWw6IE0sXG4gICAgICAuLi5wcm9wc1RvSWdub3JlOiBzdHJpbmdbXVxuICAgICk6IE1vZGVsRXJyb3JEZWZpbml0aW9uIHwgdW5kZWZpbmVkO1xuXG4gICAgc3RhdGljIHNlcmlhbGl6ZTxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKTogYW55O1xuXG4gICAgc3RhdGljIGhhc2g8TSBleHRlbmRzIE1vZGVsPihtb2RlbDogTSk6IGFueTtcblxuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IEJ1aWxkcyB0aGUga2V5IHRvIHN0b3JlIGFzIE1ldGFkYXRhIHVuZGVyIFJlZmxlY3Rpb25zXG4gICAgICogQGRlc2NyaXB0aW9uIGNvbmNhdGVuYXRlcyB7QGxpbmsgTW9kZWxLZXlzI1JFRkxFQ1R9IHdpdGggdGhlIHByb3ZpZGVkIGtleVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICAgKi9cbiAgICBzdGF0aWMga2V5KHN0cjogc3RyaW5nKTogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGRlc2NyaXB0aW9uIERldGVybWluZXMgaWYgYW4gb2JqZWN0IGlzIGEgbW9kZWwgaW5zdGFuY2Ugb3IgaGFzIG1vZGVsIG1ldGFkYXRhXG4gICAgICogQHN1bW1hcnkgQ2hlY2tzIHdoZXRoZXIgYSBnaXZlbiBvYmplY3QgaXMgZWl0aGVyIGFuIGluc3RhbmNlIG9mIHRoZSBNb2RlbCBjbGFzcyBvclxuICAgICAqIGhhcyBtb2RlbCBtZXRhZGF0YSBhdHRhY2hlZCB0byBpdC4gVGhpcyBmdW5jdGlvbiBpcyBlc3NlbnRpYWwgZm9yIHNlcmlhbGl6YXRpb24gYW5kXG4gICAgICogZGVzZXJpYWxpemF0aW9uIHByb2Nlc3NlcywgYXMgaXQgaGVscHMgaWRlbnRpZnkgbW9kZWwgb2JqZWN0cyB0aGF0IG5lZWQgc3BlY2lhbCBoYW5kbGluZy5cbiAgICAgKiBJdCBzYWZlbHkgaGFuZGxlcyBwb3RlbnRpYWwgZXJyb3JzIGR1cmluZyBtZXRhZGF0YSByZXRyaWV2YWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsIGFueT59IHRhcmdldCAtIFRoZSBvYmplY3QgdG8gY2hlY2tcbiAgICAgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBvYmplY3QgaXMgYSBtb2RlbCBpbnN0YW5jZSBvciBoYXMgbW9kZWwgbWV0YWRhdGEsIGZhbHNlIG90aGVyd2lzZVxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBgYGB0eXBlc2NyaXB0XG4gICAgICogLy8gQ2hlY2sgaWYgYW4gb2JqZWN0IGlzIGEgbW9kZWxcbiAgICAgKiBjb25zdCB1c2VyID0gbmV3IFVzZXIoeyBuYW1lOiBcIkpvaG5cIiB9KTtcbiAgICAgKiBjb25zdCBpc1VzZXJNb2RlbCA9IGlzTW9kZWwodXNlcik7IC8vIHRydWVcbiAgICAgKlxuICAgICAqIC8vIENoZWNrIGEgcGxhaW4gb2JqZWN0XG4gICAgICogY29uc3QgcGxhaW5PYmplY3QgPSB7IG5hbWU6IFwiSm9oblwiIH07XG4gICAgICogY29uc3QgaXNQbGFpbk9iamVjdE1vZGVsID0gaXNNb2RlbChwbGFpbk9iamVjdCk7IC8vIGZhbHNlXG4gICAgICogYGBgXG4gICAgICovXG4gICAgc3RhdGljIGlzTW9kZWwodGFyZ2V0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIEBkZXNjcmlwdGlvbiBDaGVja3MgaWYgYSBwcm9wZXJ0eSBvZiBhIG1vZGVsIGlzIGl0c2VsZiBhIG1vZGVsIG9yIGhhcyBhIG1vZGVsIHR5cGVcbiAgICAgKiBAc3VtbWFyeSBEZXRlcm1pbmVzIHdoZXRoZXIgYSBzcGVjaWZpYyBwcm9wZXJ0eSBvZiBhIG1vZGVsIGluc3RhbmNlIGlzIGVpdGhlciBhIG1vZGVsIGluc3RhbmNlXG4gICAgICogb3IgaGFzIGEgdHlwZSB0aGF0IGlzIHJlZ2lzdGVyZWQgYXMgYSBtb2RlbC4gVGhpcyBmdW5jdGlvbiBpcyB1c2VkIGZvciBtb2RlbCBzZXJpYWxpemF0aW9uXG4gICAgICogYW5kIGRlc2VyaWFsaXphdGlvbiB0byBwcm9wZXJseSBoYW5kbGUgbmVzdGVkIG1vZGVscy5cbiAgICAgKiBAdGVtcGxhdGUgTSBleHRlbmRzIHtAbGluayBNb2RlbH1cbiAgICAgKiBAcGFyYW0ge019IHRhcmdldCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBjaGVja1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyaWJ1dGUgLSBUaGUgcHJvcGVydHkgbmFtZSB0byBjaGVja1xuICAgICAqIEByZXR1cm4ge2Jvb2xlYW4gfCBzdHJpbmcgfCB1bmRlZmluZWR9IFJldHVybnMgdHJ1ZSBpZiB0aGUgcHJvcGVydHkgaXMgYSBtb2RlbCBpbnN0YW5jZSxcbiAgICAgKiB0aGUgbW9kZWwgbmFtZSBpZiB0aGUgcHJvcGVydHkgaGFzIGEgbW9kZWwgdHlwZSwgb3IgdW5kZWZpbmVkIGlmIG5vdCBhIG1vZGVsXG4gICAgICovXG4gICAgc3RhdGljIGlzUHJvcGVydHlNb2RlbDxNIGV4dGVuZHMgTW9kZWw+KFxuICAgICAgdGFyZ2V0OiBNLFxuICAgICAgYXR0cmlidXRlOiBzdHJpbmdcbiAgICApOiBib29sZWFuIHwgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICB9XG59XG4iLCJpbXBvcnQge1xuICBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUsXG4gIFJlcG9zaXRvcnksXG4gIFNlcmlhbGl6YXRpb25FcnJvcixcbn0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1RyYW5zaWVudDxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKSB7XG4gIHJldHVybiAhIShcbiAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLCBtb2RlbC5jb25zdHJ1Y3RvcikgfHxcbiAgICBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgUmVwb3NpdG9yeS5rZXkoREJLZXlzLlRSQU5TSUVOVCksXG4gICAgICBNb2RlbC5nZXQobW9kZWwuY29uc3RydWN0b3IubmFtZSkgYXMgYW55XG4gICAgKVxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbW9kZWxUb1RyYW5zaWVudDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTVxuKTogeyBtb2RlbDogTTsgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PiB9IHtcbiAgaWYgKCFpc1RyYW5zaWVudChtb2RlbCkpIHJldHVybiB7IG1vZGVsOiBtb2RlbCB9O1xuICBjb25zdCBkZWNzOiBSZWNvcmQ8c3RyaW5nLCBhbnlbXT4gPSBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUoXG4gICAgbW9kZWwsXG4gICAgdW5kZWZpbmVkLFxuICAgIFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpXG4gICkgYXMgUmVjb3JkPHN0cmluZywgYW55W10+O1xuXG4gIGNvbnN0IHJlc3VsdCA9IE9iamVjdC5lbnRyaWVzKGRlY3MpLnJlZHVjZShcbiAgICAoXG4gICAgICBhY2N1bTogeyBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PjsgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PiB9LFxuICAgICAgW2ssIHZhbF1cbiAgICApID0+IHtcbiAgICAgIGNvbnN0IHRyYW5zaWVudCA9IHZhbC5maW5kKChlbCkgPT4gZWwua2V5ID09PSBcIlwiKTtcbiAgICAgIGlmICh0cmFuc2llbnQpIHtcbiAgICAgICAgYWNjdW0udHJhbnNpZW50ID0gYWNjdW0udHJhbnNpZW50IHx8IHt9O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGFjY3VtLnRyYW5zaWVudFtrXSA9IG1vZGVsW2sgYXMga2V5b2YgTV07XG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2VyaWFsaXphdGlvbkVycm9yKFxuICAgICAgICAgICAgYEZhaWxlZCB0byBzZXJpYWxpemUgdHJhbnNpZW50IHByb3BlcnR5ICR7a306ICR7ZX1gXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWNjdW0ubW9kZWwgPSBhY2N1bS5tb2RlbCB8fCB7fTtcbiAgICAgICAgYWNjdW0ubW9kZWxba10gPSAobW9kZWwgYXMgUmVjb3JkPHN0cmluZywgYW55Pilba107XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdW07XG4gICAgfSxcbiAgICB7fSBhcyB7IG1vZGVsOiBSZWNvcmQ8c3RyaW5nLCBhbnk+OyB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+IH1cbiAgKTtcbiAgcmVzdWx0Lm1vZGVsID0gTW9kZWwuYnVpbGQocmVzdWx0Lm1vZGVsLCBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgcmV0dXJuIHJlc3VsdCBhcyB7IG1vZGVsOiBNOyB0cmFuc2llbnQ/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+IH07XG59XG4iXSwibmFtZXMiOlsiTW9kZWxLZXlzIiwiUmVhZE9ubHlWYWxpZGF0b3IiLCJWYWxpZGF0b3IiLCJpc0VxdWFsIiwiX19kZWNvcmF0ZSIsInZhbGlkYXRvciIsIlRpbWVzdGFtcFZhbGlkYXRvciIsIkRlY29yYXRvck1lc3NhZ2VzIiwiVmFsaWRhdGlvbiIsIk9wZXJhdGlvbktleXMiLCJCdWxrQ3J1ZE9wZXJhdGlvbktleXMiLCJIYXNoaW5nIiwicHJvcE1ldGFkYXRhIiwiYXBwbHkiLCJSZWZsZWN0aW9uIiwiT2JqZWN0QWNjdW11bGF0b3IiLCJzZiIsIkRlY29yYXRpb24iLCJkYXRlIiwicmVxdWlyZWQiLCJ0eXBlIiwibWV0YWRhdGEiLCJWYWxpZGF0aW9uS2V5cyIsIlJlc2VydmVkTW9kZWxzIiwiTW9kZWxFcnJvckRlZmluaXRpb24iLCJNb2RlbCIsInZhbGlkYXRlIl0sIm1hcHBpbmdzIjoiOzs7Ozs7SUFFQTs7Ozs7SUFLRztBQUNVLFVBQUEsTUFBTSxHQUFHO0lBQ3BCLElBQUEsT0FBTyxFQUFFLENBQUEsRUFBR0EsNkJBQVMsQ0FBQyxPQUFPLENBQWMsWUFBQSxDQUFBO0lBQzNDLElBQUEsVUFBVSxFQUFFLFlBQVk7SUFDeEIsSUFBQSxLQUFLLEVBQUUsUUFBUTtJQUNmLElBQUEsRUFBRSxFQUFFLElBQUk7SUFDUixJQUFBLEtB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
|
|
2900
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGItZGVjb3JhdG9ycy5janMiLCJzb3VyY2VzIjpbIi4uL3NyYy9tb2RlbC9jb25zdGFudHMudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9jb25zdGFudHMudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi92YWxpZGF0b3JzL1JlYWRPbmx5VmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vdmFsaWRhdG9ycy9UaW1lc3RhbXBWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi92YWxpZGF0b3JzL1VwZGF0ZVZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL3ZhbGlkYXRpb24udHMiLCIuLi9zcmMvb3BlcmF0aW9ucy9jb25zdGFudHMudHMiLCIuLi9zcmMvb3BlcmF0aW9ucy9PcGVyYXRpb25zUmVnaXN0cnkudHMiLCIuLi9zcmMvb3BlcmF0aW9ucy9PcGVyYXRpb25zLnRzIiwiLi4vc3JjL29wZXJhdGlvbnMvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L2Vycm9ycy50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L3V0aWxzLnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvQ29udGV4dC50cyIsIi4uL3NyYy9yZXBvc2l0b3J5L3dyYXBwZXJzLnRzIiwiLi4vc3JjL2lkZW50aXR5L3V0aWxzLnRzIiwiLi4vc3JjL3JlcG9zaXRvcnkvQmFzZVJlcG9zaXRvcnkudHMiLCIuLi9zcmMvcmVwb3NpdG9yeS9SZXBvc2l0b3J5LnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9pZGVudGl0eS9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL21vZGVsL3ZhbGlkYXRpb24udHMiLCIuLi9zcmMvbW9kZWwvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy9tb2RlbC9vdmVycmlkZXMudHMiLCIuLi9zcmMvbW9kZWwvdXRpbHMudHMiLCIuLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTW9kZWxLZXlzIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEYXRhYmFzZSByZWZsZWN0aW9uIGtleXNcbiAqIEBzdW1tYXJ5IENvbGxlY3Rpb24gb2Yga2V5cyB1c2VkIGZvciByZWZsZWN0aW9uIG1ldGFkYXRhIGluIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEBjb25zdCBEQktleXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgREJLZXlzID0ge1xuICBSRUZMRUNUOiBgJHtNb2RlbEtleXMuUkVGTEVDVH1wZXJzaXN0ZW5jZS5gLFxuICBSRVBPU0lUT1JZOiBcInJlcG9zaXRvcnlcIixcbiAgQ0xBU1M6IFwiX2NsYXNzXCIsXG4gIElEOiBcImlkXCIsXG4gIElOREVYOiBcImluZGV4XCIsXG4gIFVOSVFVRTogXCJ1bmlxdWVcIixcbiAgU0VSSUFMSVpFOiBcInNlcmlhbGl6ZVwiLFxuICBSRUFET05MWTogXCJyZWFkb25seVwiLFxuICBUSU1FU1RBTVA6IFwidGltZXN0YW1wXCIsXG4gIFRSQU5TSUVOVDogXCJ0cmFuc2llbnRcIixcbiAgSEFTSDogXCJoYXNoXCIsXG4gIENPTVBPU0VEOiBcImNvbXBvc2VkXCIsXG4gIFZFUlNJT046IFwidmVyc2lvblwiLFxuICBPUklHSU5BTDogXCJfX29yaWdpbmFsT2JqXCIsXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IHNlcGFyYXRvciBjaGFyYWN0ZXIgZm9yIGNvbXBvc2l0ZSBpbmRleGVzXG4gKiBAc3VtbWFyeSBUaGUgZGVmYXVsdCBzZXBhcmF0b3IgY2hhcmFjdGVyIHVzZWQgd2hlbiBjb25jYXRlbmF0aW5nIG11bHRpcGxlIGZpZWxkcyBpbnRvIGEgc2luZ2xlIGluZGV4XG4gKiBAY29uc3QgRGVmYXVsdFNlcGFyYXRvclxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBjb25zdCBEZWZhdWx0U2VwYXJhdG9yID0gXCJfXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgZm9ybWF0IGZvciB0aW1lc3RhbXAgZmllbGRzXG4gKiBAc3VtbWFyeSBTdGFuZGFyZCBkYXRlIGZvcm1hdCBzdHJpbmcgdXNlZCBmb3IgdGltZXN0YW1wIGZpZWxkcyBpbiBkYXRhYmFzZSBtb2RlbHNcbiAqIEBjb25zdCBERUZBVUxUX1RJTUVTVEFNUF9GT1JNQVRcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9USU1FU1RBTVBfRk9STUFUID0gXCJkZC9NTS95eXl5IEhIOm1tOnNzOlNcIjtcbiIsImltcG9ydCB7IERCS2V5cyB9IGZyb20gXCIuLi9tb2RlbC9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29sbGVjdGlvbiBvZiBkZWZhdWx0IGVycm9yIG1lc3NhZ2VzIHVzZWQgYnkgdmFsaWRhdG9ycy5cbiAqIEBzdW1tYXJ5IEhvbGRzIHRoZSBkZWZhdWx0IGVycm9yIG1lc3NhZ2VzIGZvciB2YXJpb3VzIHZhbGlkYXRpb24gc2NlbmFyaW9zIGluY2x1ZGluZyBJRCB2YWxpZGF0aW9uLCByZWFkb25seSBwcm9wZXJ0aWVzLCBhbmQgdGltZXN0YW1wcy5cbiAqIEB0eXBlZGVmIHtPYmplY3R9IEVycm9yTWVzc2FnZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBJRCAtIEVycm9yIG1lc3NhZ2VzIGZvciBJRCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSUQuSU5WQUxJRCAtIEVycm9yIG1lc3NhZ2Ugd2hlbiBhbiBJRCBpcyBpbnZhbGlkXG4gKiBAcHJvcGVydHkge3N0cmluZ30gSUQuUkVRVUlSRUQgLSBFcnJvciBtZXNzYWdlIHdoZW4gYW4gSUQgaXMgbWlzc2luZ1xuICogQHByb3BlcnR5IHtPYmplY3R9IFJFQURPTkxZIC0gRXJyb3IgbWVzc2FnZXMgZm9yIHJlYWRvbmx5IHByb3BlcnRpZXNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRUFET05MWS5JTlZBTElEIC0gRXJyb3IgbWVzc2FnZSB3aGVuIGF0dGVtcHRpbmcgdG8gdXBkYXRlIGEgcmVhZG9ubHkgcHJvcGVydHlcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBUSU1FU1RBTVAgLSBFcnJvciBtZXNzYWdlcyBmb3IgdGltZXN0YW1wIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUSU1FU1RBTVAuUkVRVUlSRUQgLSBFcnJvciBtZXNzYWdlIHdoZW4gYSB0aW1lc3RhbXAgaXMgbWlzc2luZ1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFRJTUVTVEFNUC5EQVRFIC0gRXJyb3IgbWVzc2FnZSB3aGVuIGEgdGltZXN0YW1wIGlzIG5vdCBhIHZhbGlkIGRhdGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUSU1FU1RBTVAuSU5WQUxJRCAtIEVycm9yIG1lc3NhZ2Ugd2hlbiBhIHRpbWVzdGFtcCBpcyBub3QgaW5jcmVhc2luZ1xuICogQGNvbnN0IERFRkFVTFRfRVJST1JfTUVTU0FHRVNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6dmFsaWRhdGlvblxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyA9IHtcbiAgSUQ6IHtcbiAgICBJTlZBTElEOiBcIlRoaXMgSWQgaXMgaW52YWxpZFwiLFxuICAgIFJFUVVJUkVEOiBcIlRoZSBJZCBpcyBtYW5kYXRvcnlcIixcbiAgfSxcbiAgUkVBRE9OTFk6IHtcbiAgICBJTlZBTElEOiBcIlRoaXMgY2Fubm90IGJlIHVwZGF0ZWRcIixcbiAgfSxcbiAgVElNRVNUQU1QOiB7XG4gICAgUkVRVUlSRUQ6IFwiVGltZXN0YW1wIGlzIE1hbmRhdG9yeVwiLFxuICAgIERBVEU6IFwiVGhlIFRpbWVzdGFtcCBtdXN0IHRoZSBhIHZhbGlkIGRhdGVcIixcbiAgICBJTlZBTElEOiBcIlRoaXMgdmFsdWUgbXVzdCBhbHdheXMgaW5jcmVhc2VcIixcbiAgfSxcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENvbnN0YW50cyB1c2VkIGZvciByZWZsZWN0aW9uLWJhc2VkIHZhbGlkYXRpb24gZHVyaW5nIHVwZGF0ZSBvcGVyYXRpb25zLlxuICogQHN1bW1hcnkgS2V5cyB1c2VkIGZvciBzdG9yaW5nIGFuZCByZXRyaWV2aW5nIHZhbGlkYXRpb24gbWV0YWRhdGEgb24gbW9kZWwgcHJvcGVydGllcyBkdXJpbmcgdXBkYXRlIG9wZXJhdGlvbnMuXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBWYWxpZGF0aW9uS2V5c1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFRkxFQ1QgLSBCYXNlIHJlZmxlY3Rpb24ga2V5IHByZWZpeCBmb3IgdXBkYXRlIHZhbGlkYXRpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUSU1FU1RBTVAgLSBLZXkgZm9yIHRpbWVzdGFtcCB2YWxpZGF0aW9uXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkVBRE9OTFkgLSBLZXkgZm9yIHJlYWRvbmx5IHByb3BlcnR5IHZhbGlkYXRpb25cbiAqIEBjb25zdCBVcGRhdGVWYWxpZGF0aW9uS2V5c1xuICogQG1lbWJlck9mIG1vZHVsZTp2YWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBVcGRhdGVWYWxpZGF0aW9uS2V5cyA9IHtcbiAgUkVGTEVDVDogXCJkYi51cGRhdGUudmFsaWRhdGlvbi5cIixcbiAgVElNRVNUQU1QOiBEQktleXMuVElNRVNUQU1QLFxuICBSRUFET05MWTogREJLZXlzLlJFQURPTkxZLFxufTtcbiIsImltcG9ydCB7IHZhbGlkYXRvciwgVmFsaWRhdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVXBkYXRlVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBpc0VxdWFsIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgdmFsaWRhdG9yIHRoYXQgZW5zdXJlcyBwcm9wZXJ0aWVzIG1hcmtlZCBhcyByZWFkb25seSBjYW5ub3QgYmUgbW9kaWZpZWQgZHVyaW5nIHVwZGF0ZXMuXG4gKiBAc3VtbWFyeSBWYWxpZGF0b3IgZm9yIHRoZSB7QGxpbmsgcmVhZG9ubHl9IGRlY29yYXRvciB0aGF0IGNoZWNrcyBpZiBhIHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQgZHVyaW5nIGFuIHVwZGF0ZSBvcGVyYXRpb24uIEl0IGNvbXBhcmVzIHRoZSBuZXcgdmFsdWUgd2l0aCB0aGUgb2xkIHZhbHVlIGFuZCByZXR1cm5zIGFuIGVycm9yIG1lc3NhZ2UgaWYgdGhleSBhcmUgbm90IGVxdWFsLlxuICogQHBhcmFtIHthbnl9IHZhbHVlIC0gVGhlIHZhbHVlIHRvIGJlIHZhbGlkYXRlZFxuICogQHBhcmFtIHthbnl9IG9sZFZhbHVlIC0gVGhlIHByZXZpb3VzIHZhbHVlIHRvIGNvbXBhcmUgYWdhaW5zdFxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSAtIE9wdGlvbmFsIGN1c3RvbSBlcnJvciBtZXNzYWdlXG4gKiBAY2xhc3MgUmVhZE9ubHlWYWxpZGF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBVc2luZyBSZWFkT25seVZhbGlkYXRvciB3aXRoIGEgcmVhZG9ubHkgcHJvcGVydHlcbiAqIGNsYXNzIFVzZXIge1xuICogICBAcmVhZG9ubHkoKVxuICogICBpZDogc3RyaW5nO1xuICogICBcbiAqICAgbmFtZTogc3RyaW5nO1xuICogICBcbiAqICAgY29uc3RydWN0b3IoaWQ6IHN0cmluZywgbmFtZTogc3RyaW5nKSB7XG4gKiAgICAgdGhpcy5pZCA9IGlkO1xuICogICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gKiAgIH1cbiAqIH1cbiAqIFxuICogLy8gVGhpcyB3aWxsIHRyaWdnZXIgdmFsaWRhdGlvbiBlcnJvciB3aGVuIHRyeWluZyB0byB1cGRhdGVcbiAqIGNvbnN0IHVzZXIgPSBuZXcgVXNlcignMTIzJywgJ0pvaG4nKTtcbiAqIHVzZXIuaWQgPSAnNDU2JzsgLy8gV2lsbCBiZSBwcmV2ZW50ZWQgYnkgUmVhZE9ubHlWYWxpZGF0b3JcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVXBkYXRlVmFsaWRhdGlvbktleXMuUkVBRE9OTFkpXG5leHBvcnQgY2xhc3MgUmVhZE9ubHlWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcihERUZBVUxUX0VSUk9SX01FU1NBR0VTLlJFQURPTkxZLklOVkFMSUQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYmFzZSB2YWxpZGF0b3IncyBoYXNFcnJvcnMgbWV0aG9kLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBpcyByZXF1aXJlZCBieSB0aGUgVmFsaWRhdG9yIGludGVyZmFjZSBidXQgbm90IHVzZWQgaW4gdGhpcyB2YWxpZGF0b3IgYXMgdmFsaWRhdGlvbiBvbmx5IGhhcHBlbnMgZHVyaW5nIHVwZGF0ZXMuXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byB2YWxpZGF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHNcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfSBBbHdheXMgcmV0dXJucyB1bmRlZmluZWQgYXMgdGhpcyB2YWxpZGF0b3Igb25seSB3b3JrcyBkdXJpbmcgdXBkYXRlc1xuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICBoYXNFcnJvcnModmFsdWU6IGFueSwgLi4uYXJnczogYW55W10pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhIHZhbHVlIGhhcyBiZWVuIG1vZGlmaWVkIGR1cmluZyBhbiB1cGRhdGUgb3BlcmF0aW9uLlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSB2YWx1ZSBoYXMgbm90IGNoYW5nZWQgYnkgY29tcGFyaW5nIGl0IHdpdGggdGhlIHByZXZpb3VzIHZhbHVlIHVzaW5nIGRlZXAgZXF1YWxpdHkuXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZSAtIFRoZSBuZXcgdmFsdWUgdG8gdmFsaWRhdGVcbiAgICogQHBhcmFtIHthbnl9IG9sZFZhbHVlIC0gVGhlIG9yaWdpbmFsIHZhbHVlIHRvIGNvbXBhcmUgYWdhaW5zdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIC0gT3B0aW9uYWwgY3VzdG9tIGVycm9yIG1lc3NhZ2UgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHRcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfSBBbiBlcnJvciBtZXNzYWdlIGlmIHZhbGlkYXRpb24gZmFpbHMsIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAgICovXG4gIHB1YmxpYyB1cGRhdGVIYXNFcnJvcnMoXG4gICAgdmFsdWU6IGFueSxcbiAgICBvbGRWYWx1ZTogYW55LFxuICAgIG1lc3NhZ2U/OiBzdHJpbmcsXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybjtcblxuICAgIHJldHVybiBpc0VxdWFsKHZhbHVlLCBvbGRWYWx1ZSlcbiAgICAgID8gdW5kZWZpbmVkXG4gICAgICA6IHRoaXMuZ2V0TWVzc2FnZShtZXNzYWdlIHx8IHRoaXMubWVzc2FnZSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IHZhbGlkYXRvciwgVmFsaWRhdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVXBkYXRlVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgdmFsaWRhdG9yIHRoYXQgZW5zdXJlcyB0aW1lc3RhbXAgdmFsdWVzIGFyZSBvbmx5IHVwZGF0ZWQgd2l0aCBuZXdlciB0aW1lc3RhbXBzLlxuICogQHN1bW1hcnkgVmFsaWRhdGVzIHRoZSB1cGRhdGUgb2YgYSB0aW1lc3RhbXAgYnkgY29tcGFyaW5nIHRoZSBuZXcgdGltZXN0YW1wIHdpdGggdGhlIG9sZCBvbmUsIGVuc3VyaW5nIHRoZSBuZXcgdGltZXN0YW1wIGlzIG1vcmUgcmVjZW50LlxuICogQHBhcmFtIHtEYXRlfHN0cmluZ3xudW1iZXJ9IHZhbHVlIC0gVGhlIHRpbWVzdGFtcCB2YWx1ZSB0byB2YWxpZGF0ZVxuICogQHBhcmFtIHtEYXRlfHN0cmluZ3xudW1iZXJ9IG9sZFZhbHVlIC0gVGhlIHByZXZpb3VzIHRpbWVzdGFtcCB0byBjb21wYXJlIGFnYWluc3RcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBPcHRpb25hbCBjdXN0b20gZXJyb3IgbWVzc2FnZVxuICogQGNsYXNzIFRpbWVzdGFtcFZhbGlkYXRvclxuICogQGV4YW1wbGVcbiAqIC8vIFVzaW5nIFRpbWVzdGFtcFZhbGlkYXRvciB3aXRoIGEgdGltZXN0YW1wIHByb3BlcnR5XG4gKiBjbGFzcyBEb2N1bWVudCB7XG4gKiAgIEB0aW1lc3RhbXAoKVxuICogICB1cGRhdGVkQXQ6IERhdGU7XG4gKiAgIFxuICogICB0aXRsZTogc3RyaW5nO1xuICogICBcbiAqICAgY29uc3RydWN0b3IodGl0bGU6IHN0cmluZykge1xuICogICAgIHRoaXMudGl0bGUgPSB0aXRsZTtcbiAqICAgICB0aGlzLnVwZGF0ZWRBdCA9IG5ldyBEYXRlKCk7XG4gKiAgIH1cbiAqIH1cbiAqIFxuICogLy8gVGhpcyB3aWxsIHRyaWdnZXIgdmFsaWRhdGlvbiBlcnJvciB3aGVuIHRyeWluZyB0byB1cGRhdGUgd2l0aCBhbiBvbGRlciB0aW1lc3RhbXBcbiAqIGNvbnN0IGRvYyA9IG5ldyBEb2N1bWVudCgnTXkgRG9jdW1lbnQnKTtcbiAqIGNvbnN0IG9sZERhdGUgPSBuZXcgRGF0ZSgyMDIwLCAwLCAxKTtcbiAqIGRvYy51cGRhdGVkQXQgPSBvbGREYXRlOyAvLyBXaWxsIGJlIHByZXZlbnRlZCBieSBUaW1lc3RhbXBWYWxpZGF0b3JcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVXBkYXRlVmFsaWRhdGlvbktleXMuVElNRVNUQU1QKVxuZXhwb3J0IGNsYXNzIFRpbWVzdGFtcFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvciB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHN1cGVyKERFRkFVTFRfRVJST1JfTUVTU0FHRVMuVElNRVNUQU1QLklOVkFMSUQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgYmFzZSB2YWxpZGF0b3IncyBoYXNFcnJvcnMgbWV0aG9kLlxuICAgKiBAc3VtbWFyeSBUaGlzIG1ldGhvZCBpcyByZXF1aXJlZCBieSB0aGUgVmFsaWRhdG9yIGludGVyZmFjZSBidXQgbm90IHVzZWQgaW4gdGhpcyB2YWxpZGF0b3IgYXMgdmFsaWRhdGlvbiBvbmx5IGhhcHBlbnMgZHVyaW5nIHVwZGF0ZXMuXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZSAtIFRoZSB0aW1lc3RhbXAgdmFsdWUgdG8gdmFsaWRhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH0gQWx3YXlzIHJldHVybnMgdW5kZWZpbmVkIGFzIHRoaXMgdmFsaWRhdG9yIG9ubHkgd29ya3MgZHVyaW5nIHVwZGF0ZXNcbiAgICovXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgaGFzRXJyb3JzKHZhbHVlOiBhbnksIC4uLmFyZ3M6IGFueVtdKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgdGhhdCBhIHRpbWVzdGFtcCBpcyBuZXdlciB0aGFuIGl0cyBwcmV2aW91cyB2YWx1ZS5cbiAgICogQHN1bW1hcnkgQ2hlY2tzIGlmIGEgdGltZXN0YW1wIGhhcyBiZWVuIHVwZGF0ZWQgd2l0aCBhIG1vcmUgcmVjZW50IHZhbHVlIGJ5IGNvbnZlcnRpbmcgYm90aCB2YWx1ZXMgdG8gRGF0ZSBvYmplY3RzIGFuZCBjb21wYXJpbmcgdGhlbS5cbiAgICogQHBhcmFtIHtEYXRlfHN0cmluZ3xudW1iZXJ9IHZhbHVlIC0gVGhlIG5ldyB0aW1lc3RhbXAgdmFsdWUgdG8gdmFsaWRhdGVcbiAgICogQHBhcmFtIHtEYXRlfHN0cmluZ3xudW1iZXJ9IG9sZFZhbHVlIC0gVGhlIG9yaWdpbmFsIHRpbWVzdGFtcCB0byBjb21wYXJlIGFnYWluc3RcbiAgICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSAtIE9wdGlvbmFsIGN1c3RvbSBlcnJvciBtZXNzYWdlIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0XG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH0gQW4gZXJyb3IgbWVzc2FnZSBpZiB2YWxpZGF0aW9uIGZhaWxzIChuZXcgdGltZXN0YW1wIGlzIG5vdCBuZXdlciksIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAgICovXG4gIHB1YmxpYyB1cGRhdGVIYXNFcnJvcnMoXG4gICAgdmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudW1iZXIsXG4gICAgb2xkVmFsdWU6IERhdGUgfCBzdHJpbmcgfCBudW1iZXIsXG4gICAgbWVzc2FnZT86IHN0cmluZ1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICBtZXNzYWdlID0gbWVzc2FnZSB8fCB0aGlzLmdldE1lc3NhZ2UobWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UpO1xuXG4gICAgdHJ5IHtcbiAgICAgIHZhbHVlID0gbmV3IERhdGUodmFsdWUpO1xuICAgICAgb2xkVmFsdWUgPSBuZXcgRGF0ZShvbGRWYWx1ZSk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlIDw9IG9sZFZhbHVlID8gbWVzc2FnZSA6IHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiaW1wb3J0IHtcbiAgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyBhcyBEZWNvcmF0b3JNZXNzYWdlcyxcbiAgVmFsaWRhdG9yLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEFic3RyYWN0IGJhc2UgY2xhc3MgZm9yIHZhbGlkYXRvcnMgdGhhdCBjb21wYXJlIG5ldyB2YWx1ZXMgd2l0aCBvbGQgdmFsdWVzIGR1cmluZyB1cGRhdGVzLlxuICogQHN1bW1hcnkgQmFzZSBjbGFzcyBmb3IgYW4gVXBkYXRlIHZhbGlkYXRvciB0aGF0IHByb3ZpZGVzIGEgZnJhbWV3b3JrIGZvciBpbXBsZW1lbnRpbmcgdmFsaWRhdGlvbiBsb2dpYyB0aGF0IGNvbXBhcmVzIGEgbmV3IHZhbHVlIHdpdGggaXRzIHByZXZpb3VzIHN0YXRlLlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSAtIEVycm9yIG1lc3NhZ2UuIERlZmF1bHRzIHRvIHtAbGluayBEZWNvcmF0b3JNZXNzYWdlcyNERUZBVUxUfVxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2FjY2VwdGVkVHlwZXNdIC0gVGhlIGFjY2VwdGVkIHZhbHVlIHR5cGVzIGJ5IHRoZSBkZWNvcmF0b3JcbiAqIEBjbGFzcyBVcGRhdGVWYWxpZGF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBFeHRlbmRpbmcgVXBkYXRlVmFsaWRhdG9yIHRvIGNyZWF0ZSBhIGN1c3RvbSB2YWxpZGF0b3JcbiAqIGNsYXNzIE15Q3VzdG9tVmFsaWRhdG9yIGV4dGVuZHMgVXBkYXRlVmFsaWRhdG9yIHtcbiAqICAgY29uc3RydWN0b3IoKSB7XG4gKiAgICAgc3VwZXIoXCJDdXN0b20gdmFsaWRhdGlvbiBmYWlsZWRcIik7XG4gKiAgIH1cbiAqICAgXG4gKiAgIHB1YmxpYyB1cGRhdGVIYXNFcnJvcnModmFsdWU6IGFueSwgb2xkVmFsdWU6IGFueSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gKiAgICAgLy8gQ3VzdG9tIHZhbGlkYXRpb24gbG9naWNcbiAqICAgICBpZiAodmFsdWUgPT09IG9sZFZhbHVlKSB7XG4gKiAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlO1xuICogICAgIH1cbiAqICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICogICB9XG4gKiAgIFxuICogICBoYXNFcnJvcnModmFsdWU6IGFueSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gKiAgICAgcmV0dXJuIHVuZGVmaW5lZDsgLy8gTm90IHVzZWQgZm9yIHVwZGF0ZSB2YWxpZGF0b3JzXG4gKiAgIH1cbiAqIH1cbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBVcGRhdGVWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3Ige1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoXG4gICAgbWVzc2FnZTogc3RyaW5nID0gRGVjb3JhdG9yTWVzc2FnZXMuREVGQVVMVCxcbiAgICAuLi5hY2NlcHRlZFR5cGVzOiBzdHJpbmdbXVxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlLCAuLi5hY2NlcHRlZFR5cGVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQWJzdHJhY3QgbWV0aG9kIHRoYXQgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc2VzIHRvIHBlcmZvcm0gdXBkYXRlIHZhbGlkYXRpb24uXG4gICAqIEBzdW1tYXJ5IFZhbGlkYXRlcyBhIHZhbHVlIGJ5IGNvbXBhcmluZyBpdCB0byBpdHMgb2xkIHZlcnNpb24gdG8gZGV0ZXJtaW5lIGlmIHRoZSB1cGRhdGUgaXMgdmFsaWQuXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZSAtIFRoZSBuZXcgdmFsdWUgdG8gdmFsaWRhdGVcbiAgICogQHBhcmFtIHthbnl9IG9sZFZhbHVlIC0gVGhlIHByZXZpb3VzIHZhbHVlIHRvIGNvbXBhcmUgYWdhaW5zdFxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgdGhhdCBtYXkgYmUgbmVlZGVkIGZvciB2YWxpZGF0aW9uXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH0gQW4gZXJyb3IgbWVzc2FnZSBpZiB2YWxpZGF0aW9uIGZhaWxzLCB1bmRlZmluZWQgaWYgdmFsaWRhdGlvbiBwYXNzZXNcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCB1cGRhdGVIYXNFcnJvcnMoXG4gICAgdmFsdWU6IGFueSxcbiAgICBvbGRWYWx1ZTogYW55LFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbn1cbiIsImltcG9ydCB7XG4gIFZhbGlkYXRvcixcbiAgVmFsaWRhdGlvbixcbiAgVmFsaWRhdG9yRGVmaW5pdGlvbixcbiAgSVZhbGlkYXRvclJlZ2lzdHJ5LFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBVcGRhdGVWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSBrZXkgZm9yIHVwZGF0ZSB2YWxpZGF0aW9uIG1ldGFkYXRhLlxuICogQHN1bW1hcnkgQnVpbGRzIHRoZSBrZXkgdG8gc3RvcmUgYXMgbWV0YWRhdGEgdW5kZXIgUmVmbGVjdGlvbnMgZm9yIHVwZGF0ZSB2YWxpZGF0aW9uIGJ5IHByZWZpeGluZyB0aGUgcHJvdmlkZWQga2V5IHdpdGggdGhlIHVwZGF0ZSB2YWxpZGF0aW9uIHByZWZpeC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgLSBUaGUgYmFzZSBrZXkgdG8gYmUgcHJlZml4ZWRcbiAqIEByZXR1cm4ge3N0cmluZ30gVGhlIGNvbXBsZXRlIG1ldGFkYXRhIGtleSBmb3IgdXBkYXRlIHZhbGlkYXRpb25cbiAqIEBmdW5jdGlvbiB1cGRhdGVLZXlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5WYWxpZGF0aW9uLnVwZGF0ZUtleSA9IGZ1bmN0aW9uIChrZXk6IHN0cmluZykge1xuICByZXR1cm4gVXBkYXRlVmFsaWRhdGlvbktleXMuUkVGTEVDVCArIGtleTtcbn07XG5cbmRlY2xhcmUgbW9kdWxlIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCIge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50XG4gIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgZGVjbGFyZSBjbGFzcyBWYWxpZGF0aW9uIHtcbiAgICBwcml2YXRlIHN0YXRpYyBhY3RpbmdWYWxpZGF0b3JSZWdpc3RyeT87XG4gICAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpO1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIGFjdGluZyBWYWxpZGF0b3JSZWdpc3RyeVxuICAgICAqXG4gICAgICogQHBhcmFtIHtJVmFsaWRhdG9yUmVnaXN0cnl9IHZhbGlkYXRvclJlZ2lzdHJ5IHRoZSBuZXcgaW1wbGVtZW50YXRpb24gb2YgdGhlIHZhbGlkYXRvciBSZWdpc3RyeVxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb24oVmFsaWRhdG9yKTogVmFsaWRhdG9yfSBbbWlncmF0aW9uSGFuZGxlcl0gdGhlIG1ldGhvZCB0byBtYXAgdGhlIHZhbGlkYXRvciBpZiByZXF1aXJlZDtcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0UmVnaXN0cnkoXG4gICAgICB2YWxpZGF0b3JSZWdpc3RyeTogSVZhbGlkYXRvclJlZ2lzdHJ5PFZhbGlkYXRvcj4sXG4gICAgICBtaWdyYXRpb25IYW5kbGVyPzogKHZhbGlkYXRvcjogVmFsaWRhdG9yKSA9PiBWYWxpZGF0b3JcbiAgICApOiB2b2lkO1xuICAgIC8qKlxuICAgICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGN1cnJlbnQgVmFsaWRhdG9yUmVnaXN0cnlcbiAgICAgKlxuICAgICAqIEByZXR1cm4gSVZhbGlkYXRvclJlZ2lzdHJ5LCBkZWZhdWx0cyB0byB7QGxpbmsgVmFsaWRhdG9yUmVnaXN0cnl9XG4gICAgICovXG4gICAgcHJpdmF0ZSBzdGF0aWMgZ2V0UmVnaXN0cnk7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgUmV0cmlldmVzIGEgdmFsaWRhdG9yXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsaWRhdG9yS2V5IG9uZSBvZiB0aGUge0BsaW5rIFZhbGlkYXRpb25LZXlzfVxuICAgICAqIEByZXR1cm4ge1ZhbGlkYXRvciB8IHVuZGVmaW5lZH0gdGhlIHJlZ2lzdGVyZWQgVmFsaWRhdG9yIG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBpcyBub25vIG1hdGNoaW5nIHRoZSBwcm92aWRlZCBrZXlcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0PFQgZXh0ZW5kcyBWYWxpZGF0b3I+KHZhbGlkYXRvcktleTogc3RyaW5nKTogVCB8IHVuZGVmaW5lZDtcbiAgICAvKipcbiAgICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgdGhlIHByb3ZpZGVkIHZhbGlkYXRvcnMgb250byB0aGUgcmVnaXN0cnlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7VFtdIHwgVmFsaWRhdG9yRGVmaW5pdGlvbltdfSB2YWxpZGF0b3JcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVnaXN0ZXI8VCBleHRlbmRzIFZhbGlkYXRvcj4oXG4gICAgICAuLi52YWxpZGF0b3I6IChWYWxpZGF0b3JEZWZpbml0aW9uIHwgVClbXVxuICAgICk6IHZvaWQ7XG4gICAgLyoqXG4gICAgICogQHN1bW1hcnkgQnVpbGRzIHRoZSBrZXkgdG8gc3RvcmUgYXMgTWV0YWRhdGEgdW5kZXIgUmVmbGVjdGlvbnNcbiAgICAgKiBAZGVzY3JpcHRpb24gY29uY2F0ZW5hdGVzIHtAbGluayBWYWxpZGF0aW9uS2V5cyNSRUZMRUNUfSB3aXRoIHRoZSBwcm92aWRlZCBrZXlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAgICAgKi9cbiAgICBzdGF0aWMga2V5KGtleTogc3RyaW5nKTogc3RyaW5nO1xuXG4gICAgc3RhdGljIHVwZGF0ZUtleShrZXk6IHN0cmluZyk6IHN0cmluZztcbiAgfVxufVxuIiwiLyoqXG4gKiBAZGVzY3JpcHRpb24gRGF0YWJhc2Ugb3BlcmF0aW9uIGtleSBjb25zdGFudHNcbiAqIEBzdW1tYXJ5IEVudW0gZGVmaW5pbmcgQ1JVRCBvcGVyYXRpb25zIGFuZCB0aGVpciBsaWZlY3ljbGUgcGhhc2VzXG4gKiBAZW51bSB7c3RyaW5nfVxuICogQHJlYWRvbmx5XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGVudW0gT3BlcmF0aW9uS2V5cyB7XG4gIFJFRkxFQ1QgPSBcImRlY2FmLm1vZGVsLmRiLm9wZXJhdGlvbnMuXCIsXG4gIENSRUFURSA9IFwiY3JlYXRlXCIsXG4gIFJFQUQgPSBcInJlYWRcIixcbiAgVVBEQVRFID0gXCJ1cGRhdGVcIixcbiAgREVMRVRFID0gXCJkZWxldGVcIixcbiAgT04gPSBcIm9uLlwiLFxuICBBRlRFUiA9IFwiYWZ0ZXIuXCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFR5cGUgZm9yIGJhc2ljIENSVUQgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgVW5pb24gdHlwZSBvZiB0aGUgZm91ciBiYXNpYyBkYXRhYmFzZSBvcGVyYXRpb25zOiBjcmVhdGUsIHJlYWQsIHVwZGF0ZSwgZGVsZXRlXG4gKiBAdHlwZWRlZiB7c3RyaW5nfSBDcnVkT3BlcmF0aW9uc1xuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCB0eXBlIENydWRPcGVyYXRpb25zID1cbiAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICB8IE9wZXJhdGlvbktleXMuUkVBRFxuICB8IE9wZXJhdGlvbktleXMuVVBEQVRFXG4gIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEU7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEJ1bGsgZGF0YWJhc2Ugb3BlcmF0aW9uIGtleSBjb25zdGFudHNcbiAqIEBzdW1tYXJ5IEVudW0gZGVmaW5pbmcgYnVsayBDUlVEIG9wZXJhdGlvbnMgZm9yIGhhbmRsaW5nIG11bHRpcGxlIHJlY29yZHMgYXQgb25jZVxuICogQGVudW0ge3N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBlbnVtIEJ1bGtDcnVkT3BlcmF0aW9uS2V5cyB7XG4gIENSRUFURV9BTEwgPSBcImNyZWF0ZUFsbFwiLFxuICBSRUFEX0FMTCA9IFwicmVhZEFsbFwiLFxuICBVUERBVEVfQUxMID0gXCJ1cGRhdGVBbGxcIixcbiAgREVMRVRFX0FMTCA9IFwiZGVsZXRlQWxsXCIsXG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFR5cGUgZm9yIGJ1bGsgQ1JVRCBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBVbmlvbiB0eXBlIG9mIHRoZSBmb3VyIGJ1bGsgZGF0YWJhc2Ugb3BlcmF0aW9ucyBmb3IgaGFuZGxpbmcgbXVsdGlwbGUgcmVjb3JkcyBhdCBvbmNlXG4gKiBAdHlwZWRlZiB7c3RyaW5nfSBCdWxrQ3J1ZE9wZXJhdGlvbnNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgdHlwZSBCdWxrQ3J1ZE9wZXJhdGlvbnMgPVxuICB8IEJ1bGtDcnVkT3BlcmF0aW9uS2V5cy5DUkVBVEVfQUxMXG4gIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzLlJFQURfQUxMXG4gIHwgQnVsa0NydWRPcGVyYXRpb25LZXlzLlVQREFURV9BTExcbiAgfCBCdWxrQ3J1ZE9wZXJhdGlvbktleXMuREVMRVRFX0FMTDtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR3JvdXBlZCBDUlVEIG9wZXJhdGlvbnMgZm9yIGRlY29yYXRvciBtYXBwaW5nXG4gKiBAc3VtbWFyeSBNYXBzIG91dCBncm91cHMgb2YgQ1JVRCBvcGVyYXRpb25zIGZvciBlYXNpZXIgbWFwcGluZyBvZiBkZWNvcmF0b3JzXG4gKiBAY29uc3QgREJPcGVyYXRpb25zXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IERCT3BlcmF0aW9uczogUmVjb3JkPHN0cmluZywgQ3J1ZE9wZXJhdGlvbnNbXT4gPSB7XG4gIENSRUFURTogW09wZXJhdGlvbktleXMuQ1JFQVRFXSxcbiAgUkVBRDogW09wZXJhdGlvbktleXMuUkVBRF0sXG4gIFVQREFURTogW09wZXJhdGlvbktleXMuVVBEQVRFXSxcbiAgREVMRVRFOiBbT3BlcmF0aW9uS2V5cy5ERUxFVEVdLFxuICBDUkVBVEVfVVBEQVRFOiBbT3BlcmF0aW9uS2V5cy5DUkVBVEUsIE9wZXJhdGlvbktleXMuVVBEQVRFXSxcbiAgUkVBRF9DUkVBVEU6IFtPcGVyYXRpb25LZXlzLlJFQUQsIE9wZXJhdGlvbktleXMuQ1JFQVRFXSxcbiAgQUxMOiBbXG4gICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICBdLFxufTtcbiIsImltcG9ydCB7IE9wZXJhdGlvbkhhbmRsZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgT3BlcmF0aW9ucyB9IGZyb20gXCIuL09wZXJhdGlvbnNcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBSZWdpc3RyeSBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9uIGhhbmRsZXJzXG4gKiBAc3VtbWFyeSBNYW5hZ2VzIGFuZCBzdG9yZXMgb3BlcmF0aW9uIGhhbmRsZXJzIGZvciBkaWZmZXJlbnQgbW9kZWwgcHJvcGVydGllcyBhbmQgb3BlcmF0aW9uc1xuICogQGNsYXNzIE9wZXJhdGlvbnNSZWdpc3RyeVxuICogQHRlbXBsYXRlIE0gLSBNb2RlbCB0eXBlXG4gKiBAdGVtcGxhdGUgUiAtIFJlcG9zaXRvcnkgdHlwZVxuICogQHRlbXBsYXRlIFYgLSBNZXRhZGF0YSB0eXBlXG4gKiBAdGVtcGxhdGUgRiAtIFJlcG9zaXRvcnkgZmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gQ29udGV4dCB0eXBlXG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgcmVnaXN0cnkgYW5kIHJlZ2lzdGVyIGEgaGFuZGxlclxuICogY29uc3QgcmVnaXN0cnkgPSBuZXcgT3BlcmF0aW9uc1JlZ2lzdHJ5KCk7XG4gKiByZWdpc3RyeS5yZWdpc3RlcihteUhhbmRsZXIsIE9wZXJhdGlvbktleXMuQ1JFQVRFLCB0YXJnZXRNb2RlbCwgJ3Byb3BlcnR5TmFtZScpO1xuICpcbiAqIC8vIEdldCBoYW5kbGVycyBmb3IgYSBzcGVjaWZpYyBvcGVyYXRpb25cbiAqIGNvbnN0IGhhbmRsZXJzID0gcmVnaXN0cnkuZ2V0KHRhcmdldE1vZGVsLmNvbnN0cnVjdG9yLm5hbWUsICdwcm9wZXJ0eU5hbWUnLCAnb25DcmVhdGUnKTtcbiAqXG4gKiBAbWVybWFpZFxuICogY2xhc3NEaWFncmFtXG4gKiAgIGNsYXNzIE9wZXJhdGlvbnNSZWdpc3RyeSB7XG4gKiAgICAgLWNhY2hlOiBSZWNvcmR+c3RyaW5nLCBSZWNvcmR+c3RyaW5nfHN5bWJvbCwgUmVjb3JkfnN0cmluZywgUmVjb3JkfnN0cmluZywgT3BlcmF0aW9uSGFuZGxlcn5+fn5cbiAqICAgICArZ2V0KHRhcmdldCwgcHJvcEtleSwgb3BlcmF0aW9uLCBhY2N1bSlcbiAqICAgICArcmVnaXN0ZXIoaGFuZGxlciwgb3BlcmF0aW9uLCB0YXJnZXQsIHByb3BLZXkpXG4gKiAgIH1cbiAqL1xuZXhwb3J0IGNsYXNzIE9wZXJhdGlvbnNSZWdpc3RyeSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGU6IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgUmVjb3JkPFxuICAgICAgc3RyaW5nIHwgc3ltYm9sLFxuICAgICAgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgYW55LCBhbnksIGFueT4+PlxuICAgID5cbiAgPiA9IHt9O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG9wZXJhdGlvbiBoYW5kbGVycyBmb3IgYSBzcGVjaWZpYyB0YXJnZXQgYW5kIG9wZXJhdGlvblxuICAgKiBAc3VtbWFyeSBGaW5kcyBhbGwgcmVnaXN0ZXJlZCBoYW5kbGVycyBmb3IgYSBnaXZlbiB0YXJnZXQsIHByb3BlcnR5LCBhbmQgb3BlcmF0aW9uLCBpbmNsdWRpbmcgZnJvbSBwYXJlbnQgY2xhc3Nlc1xuICAgKiBAdGVtcGxhdGUgTSAtIE1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEB0ZW1wbGF0ZSBSIC0gUmVwb3NpdG9yeSB0eXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeVxuICAgKiBAdGVtcGxhdGUgViAtIE1ldGFkYXRhIHR5cGVcbiAgICogQHRlbXBsYXRlIEYgLSBSZXBvc2l0b3J5IGZsYWdzIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3NcbiAgICogQHRlbXBsYXRlIEMgLSBDb250ZXh0IHR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+fSB0YXJnZXQgLSBUaGUgdGFyZ2V0IGNsYXNzIG5hbWUgb3Igb2JqZWN0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wS2V5IC0gVGhlIHByb3BlcnR5IGtleSB0byBnZXQgaGFuZGxlcnMgZm9yXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGtleSB0byBnZXQgaGFuZGxlcnMgZm9yXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcltdfSBbYWNjdW1dIC0gQWNjdW11bGF0b3IgZm9yIHJlY3Vyc2l2ZSBjYWxsc1xuICAgKiBAcmV0dXJuIHtPcGVyYXRpb25IYW5kbGVyW10gfCB1bmRlZmluZWR9IEFycmF5IG9mIGhhbmRsZXJzIG9yIHVuZGVmaW5lZCBpZiBub25lIGZvdW5kXG4gICAqL1xuICBnZXQ8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWLFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gID4oXG4gICAgdGFyZ2V0OiBzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgIHByb3BLZXk6IHN0cmluZyxcbiAgICBvcGVyYXRpb246IHN0cmluZyxcbiAgICBhY2N1bT86IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz5bXVxuICApOiBPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+W10gfCB1bmRlZmluZWQge1xuICAgIGFjY3VtID0gYWNjdW0gfHwgW107XG4gICAgbGV0IG5hbWU7XG4gICAgdHJ5IHtcbiAgICAgIG5hbWUgPSB0eXBlb2YgdGFyZ2V0ID09PSBcInN0cmluZ1wiID8gdGFyZ2V0IDogdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICBhY2N1bS51bnNoaWZ0KFxuICAgICAgICAuLi5PYmplY3QudmFsdWVzKHRoaXMuY2FjaGVbbmFtZV1bcHJvcEtleV1bb3BlcmF0aW9uXSB8fCBbXSlcbiAgICAgICk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKFxuICAgICAgICB0eXBlb2YgdGFyZ2V0ID09PSBcInN0cmluZ1wiIHx8XG4gICAgICAgIHRhcmdldCA9PT0gT2JqZWN0LnByb3RvdHlwZSB8fFxuICAgICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YodGFyZ2V0KSA9PT0gT2JqZWN0LnByb3RvdHlwZVxuICAgICAgKVxuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgfVxuXG4gICAgbGV0IHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRhcmdldCk7XG4gICAgaWYgKHByb3RvLmNvbnN0cnVjdG9yLm5hbWUgPT09IG5hbWUpIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKTtcblxuICAgIHJldHVybiB0aGlzLmdldDxNLCBSLCBWLCBGLCBDPihwcm90bywgcHJvcEtleSwgb3BlcmF0aW9uLCBhY2N1bSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVycyBhbiBvcGVyYXRpb24gaGFuZGxlciBmb3IgYSBzcGVjaWZpYyB0YXJnZXQgYW5kIG9wZXJhdGlvblxuICAgKiBAc3VtbWFyeSBTdG9yZXMgYSBoYW5kbGVyIGluIHRoZSByZWdpc3RyeSBmb3IgYSBnaXZlbiB0YXJnZXQsIHByb3BlcnR5LCBhbmQgb3BlcmF0aW9uXG4gICAqIEB0ZW1wbGF0ZSBNIC0gTW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHRlbXBsYXRlIFIgLSBSZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIElSZXBvc2l0b3J5XG4gICAqIEB0ZW1wbGF0ZSBWIC0gTWV0YWRhdGEgdHlwZVxuICAgKiBAdGVtcGxhdGUgRiAtIFJlcG9zaXRvcnkgZmxhZ3MgZXh0ZW5kaW5nIFJlcG9zaXRvcnlGbGFnc1xuICAgKiBAdGVtcGxhdGUgQyAtIENvbnRleHQgdHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICAgKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXJ9IGhhbmRsZXIgLSBUaGUgaGFuZGxlciBmdW5jdGlvbiB0byByZWdpc3RlclxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXN9IG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb24ga2V5IHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgKiBAcGFyYW0ge019IHRhcmdldCAtIFRoZSB0YXJnZXQgbW9kZWwgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBzeW1ib2x9IHByb3BLZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIHJlZ2lzdGVyIHRoZSBoYW5kbGVyIGZvclxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgcmVnaXN0ZXI8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgICBWLFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gID4oXG4gICAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPixcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgdGFyZ2V0OiBNLFxuICAgIHByb3BLZXk6IHN0cmluZyB8IHN5bWJvbFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBuYW1lID0gdGFyZ2V0LmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgY29uc3QgaGFuZGxlck5hbWUgPSBPcGVyYXRpb25zLmdldEhhbmRsZXJOYW1lKGhhbmRsZXIpO1xuXG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdKSB0aGlzLmNhY2hlW25hbWVdID0ge307XG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldKSB0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldID0ge307XG4gICAgaWYgKCF0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl0pXG4gICAgICB0aGlzLmNhY2hlW25hbWVdW3Byb3BLZXldW29wZXJhdGlvbl0gPSB7fTtcbiAgICBpZiAodGhpcy5jYWNoZVtuYW1lXVtwcm9wS2V5XVtvcGVyYXRpb25dW2hhbmRsZXJOYW1lXSkgcmV0dXJuO1xuICAgIHRoaXMuY2FjaGVbbmFtZV1bcHJvcEtleV1bb3BlcmF0aW9uXVtoYW5kbGVyTmFtZV0gPSBoYW5kbGVyO1xuICB9XG59XG4iLCJpbXBvcnQgeyBIYXNoaW5nLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IE9wZXJhdGlvbkhhbmRsZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uc1JlZ2lzdHJ5IH0gZnJvbSBcIi4vT3BlcmF0aW9uc1JlZ2lzdHJ5XCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFN0YXRpYyB1dGlsaXR5IGNsYXNzIGZvciBkYXRhYmFzZSBvcGVyYXRpb24gbWFuYWdlbWVudFxuICogQHN1bW1hcnkgUHJvdmlkZXMgZnVuY3Rpb25hbGl0eSBmb3IgcmVnaXN0ZXJpbmcsIHJldHJpZXZpbmcsIGFuZCBtYW5hZ2luZyBkYXRhYmFzZSBvcGVyYXRpb24gaGFuZGxlcnNcbiAqIEBjbGFzcyBPcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgTSAtIE1vZGVsIHR5cGVcbiAqIEB0ZW1wbGF0ZSBSIC0gUmVwb3NpdG9yeSB0eXBlXG4gKiBAdGVtcGxhdGUgViAtIE1ldGFkYXRhIHR5cGVcbiAqIEB0ZW1wbGF0ZSBGIC0gUmVwb3NpdG9yeSBmbGFnc1xuICogQHRlbXBsYXRlIEMgLSBDb250ZXh0IHR5cGVcbiAqIEBleGFtcGxlXG4gKiAvLyBSZWdpc3RlciBhIGhhbmRsZXIgZm9yIGEgY3JlYXRlIG9wZXJhdGlvblxuICogT3BlcmF0aW9ucy5yZWdpc3RlcihteUhhbmRsZXIsIE9wZXJhdGlvbktleXMuQ1JFQVRFLCB0YXJnZXRNb2RlbCwgJ3Byb3BlcnR5TmFtZScpO1xuICogXG4gKiAvLyBHZXQgaGFuZGxlcnMgZm9yIGEgc3BlY2lmaWMgb3BlcmF0aW9uXG4gKiBjb25zdCBoYW5kbGVycyA9IE9wZXJhdGlvbnMuZ2V0KHRhcmdldE1vZGVsLmNvbnN0cnVjdG9yLm5hbWUsICdwcm9wZXJ0eU5hbWUnLCAnb25DcmVhdGUnKTtcbiAqIFxuICogQG1lcm1haWRcbiAqIGNsYXNzRGlhZ3JhbVxuICogICBjbGFzcyBPcGVyYXRpb25zIHtcbiAqICAgICAtcmVnaXN0cnk6IE9wZXJhdGlvbnNSZWdpc3RyeVxuICogICAgICtnZXRIYW5kbGVyTmFtZShoYW5kbGVyKVxuICogICAgICtrZXkoc3RyKVxuICogICAgICtnZXQodGFyZ2V0TmFtZSwgcHJvcEtleSwgb3BlcmF0aW9uKVxuICogICAgIC1nZXRPcFJlZ2lzdHJ5KClcbiAqICAgICArcmVnaXN0ZXIoaGFuZGxlciwgb3BlcmF0aW9uLCB0YXJnZXQsIHByb3BLZXkpXG4gKiAgIH1cbiAqICAgT3BlcmF0aW9ucyAtLT4gT3BlcmF0aW9uc1JlZ2lzdHJ5IDogdXNlc1xuICovXG5leHBvcnQgY2xhc3MgT3BlcmF0aW9ucyB7XG4gIHByaXZhdGUgc3RhdGljIHJlZ2lzdHJ5OiBPcGVyYXRpb25zUmVnaXN0cnk7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIGEgdW5pcXVlIG5hbWUgZm9yIGFuIG9wZXJhdGlvbiBoYW5kbGVyXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIG5hbWUgb2YgdGhlIGhhbmRsZXIgZnVuY3Rpb24gb3IgZ2VuZXJhdGVzIGEgaGFzaCBpZiBuYW1lIGlzIG5vdCBhdmFpbGFibGVcbiAgICogQHBhcmFtIHtPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBhbnksIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBoYW5kbGVyIGZ1bmN0aW9uIHRvIGdldCB0aGUgbmFtZSBmb3JcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgbmFtZSBvZiB0aGUgaGFuZGxlciBvciBhIGdlbmVyYXRlZCBoYXNoXG4gICAqL1xuICBzdGF0aWMgZ2V0SGFuZGxlck5hbWUoaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgYW55LCBhbnksIGFueT4pIHtcbiAgICBpZiAoaGFuZGxlci5uYW1lKSByZXR1cm4gaGFuZGxlci5uYW1lO1xuXG4gICAgY29uc29sZS53YXJuKFxuICAgICAgXCJIYW5kbGVyIG5hbWUgbm90IGRlZmluZWQuIEEgbmFtZSB3aWxsIGJlIGdlbmVyYXRlZCwgYnV0IHRoaXMgaXMgbm90IGRlc2lyYWJsZS4gcGxlYXNlIGF2b2lkIHVzaW5nIGFub255bW91cyBmdW5jdGlvbnNcIlxuICAgICk7XG4gICAgcmV0dXJuIEhhc2hpbmcuaGFzaChoYW5kbGVyLnRvU3RyaW5nKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZW5lcmF0ZXMgYSByZWZsZWN0aW9uIG1ldGFkYXRhIGtleVxuICAgKiBAc3VtbWFyeSBDcmVhdGVzIGEgZnVsbHkgcXVhbGlmaWVkIG1ldGFkYXRhIGtleSBieSBwcmVmaXhpbmcgd2l0aCB0aGUgcmVmbGVjdGlvbiBuYW1lc3BhY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFRoZSBvcGVyYXRpb24ga2V5IHN0cmluZyB0byBwcmVmaXhcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgZnVsbHkgcXVhbGlmaWVkIG1ldGFkYXRhIGtleVxuICAgKi9cbiAgc3RhdGljIGtleShzdHI6IHN0cmluZykge1xuICAgIHJldHVybiBPcGVyYXRpb25LZXlzLlJFRkxFQ1QgKyBzdHI7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBvcGVyYXRpb24gaGFuZGxlcnMgZm9yIGEgc3BlY2lmaWMgdGFyZ2V0IGFuZCBvcGVyYXRpb25cbiAgICogQHN1bW1hcnkgR2V0cyByZWdpc3RlcmVkIGhhbmRsZXJzIGZyb20gdGhlIG9wZXJhdGlvbnMgcmVnaXN0cnkgZm9yIGEgZ2l2ZW4gdGFyZ2V0LCBwcm9wZXJ0eSwgYW5kIG9wZXJhdGlvblxuICAgKiBAdGVtcGxhdGUgTSAtIE1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gICAqIEB0ZW1wbGF0ZSBSIC0gUmVwb3NpdG9yeSB0eXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeVxuICAgKiBAdGVtcGxhdGUgViAtIE1ldGFkYXRhIHR5cGUsIGRlZmF1bHRzIHRvIG9iamVjdFxuICAgKiBAdGVtcGxhdGUgRiAtIFJlcG9zaXRvcnkgZmxhZ3MgZXh0ZW5kaW5nIFJlcG9zaXRvcnlGbGFnc1xuICAgKiBAdGVtcGxhdGUgQyAtIENvbnRleHQgdHlwZSBleHRlbmRpbmcgQ29udGV4dDxGPlxuICAgKiBAcGFyYW0ge3N0cmluZyB8IFJlY29yZDxzdHJpbmcsIGFueT59IHRhcmdldE5hbWUgLSBUaGUgdGFyZ2V0IGNsYXNzIG5hbWUgb3Igb2JqZWN0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwcm9wS2V5IC0gVGhlIHByb3BlcnR5IGtleSB0byBnZXQgaGFuZGxlcnMgZm9yXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIGtleSB0byBnZXQgaGFuZGxlcnMgZm9yXG4gICAqIEByZXR1cm4ge2FueX0gVGhlIHJlZ2lzdGVyZWQgaGFuZGxlcnMgZm9yIHRoZSBzcGVjaWZpZWQgdGFyZ2V0LCBwcm9wZXJ0eSwgYW5kIG9wZXJhdGlvblxuICAgKi9cbiAgc3RhdGljIGdldDxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICAgIFYgPSBvYmplY3QsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID4oXG4gICAgdGFyZ2V0TmFtZTogc3RyaW5nIHwgUmVjb3JkPHN0cmluZywgYW55PixcbiAgICBwcm9wS2V5OiBzdHJpbmcsXG4gICAgb3BlcmF0aW9uOiBzdHJpbmdcbiAgKSB7XG4gICAgcmV0dXJuIE9wZXJhdGlvbnMucmVnaXN0cnkuZ2V0PE0sIFIsIFYsIEYsIEM+KFxuICAgICAgdGFyZ2V0TmFtZSxcbiAgICAgIHByb3BLZXksXG4gICAgICBvcGVyYXRpb25cbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIG9yIGluaXRpYWxpemVzIHRoZSBvcGVyYXRpb25zIHJlZ2lzdHJ5XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGV4aXN0aW5nIHJlZ2lzdHJ5IG9yIGNyZWF0ZXMgYSBuZXcgb25lIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICogQHJldHVybiB7T3BlcmF0aW9uc1JlZ2lzdHJ5fSBUaGUgb3BlcmF0aW9ucyByZWdpc3RyeSBpbnN0YW5jZVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0T3BSZWdpc3RyeSgpIHtcbiAgICBpZiAoIU9wZXJhdGlvbnMucmVnaXN0cnkpIE9wZXJhdGlvbnMucmVnaXN0cnkgPSBuZXcgT3BlcmF0aW9uc1JlZ2lzdHJ5KCk7XG4gICAgcmV0dXJuIE9wZXJhdGlvbnMucmVnaXN0cnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJlZ2lzdGVycyBhbiBvcGVyYXRpb24gaGFuZGxlciBmb3IgYSBzcGVjaWZpYyB0YXJnZXQgYW5kIG9wZXJhdGlvblxuICAgKiBAc3VtbWFyeSBBZGRzIGEgaGFuZGxlciB0byB0aGUgb3BlcmF0aW9ucyByZWdpc3RyeSBmb3IgYSBnaXZlbiB0YXJnZXQsIHByb3BlcnR5LCBhbmQgb3BlcmF0aW9uXG4gICAqIEB0ZW1wbGF0ZSBWIC0gTW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtPcGVyYXRpb25IYW5kbGVyPFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBoYW5kbGVyIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyXG4gICAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5c30gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiBrZXkgdG8gcmVnaXN0ZXIgdGhlIGhhbmRsZXIgZm9yXG4gICAqIEBwYXJhbSB7Vn0gdGFyZ2V0IC0gVGhlIHRhcmdldCBtb2RlbCBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZyB8IHN5bWJvbH0gcHJvcEtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gcmVnaXN0ZXIgdGhlIGhhbmRsZXIgZm9yXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgcmVnaXN0ZXI8ViBleHRlbmRzIE1vZGVsPihcbiAgICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPFYsIGFueSwgYW55PixcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgdGFyZ2V0OiBWLFxuICAgIHByb3BLZXk6IHN0cmluZyB8IHN5bWJvbFxuICApIHtcbiAgICBPcGVyYXRpb25zLmdldE9wUmVnaXN0cnkoKS5yZWdpc3RlcihcbiAgICAgIGhhbmRsZXIgYXMgYW55LFxuICAgICAgb3BlcmF0aW9uLFxuICAgICAgdGFyZ2V0LFxuICAgICAgcHJvcEtleVxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIElkT3BlcmF0aW9uSGFuZGxlcixcbiAgT3BlcmF0aW9uSGFuZGxlcixcbiAgU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyLFxuICBVcGRhdGVPcGVyYXRpb25IYW5kbGVyLFxufSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgREJPcGVyYXRpb25zLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25zIH0gZnJvbSBcIi4vT3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgYXBwbHkgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IHByb3BNZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSW50ZXJuYWwgZnVuY3Rpb24gdG8gcmVnaXN0ZXIgb3BlcmF0aW9uIGhhbmRsZXJzXG4gKiBAc3VtbWFyeSBSZWdpc3RlcnMgYW4gb3BlcmF0aW9uIGhhbmRsZXIgZm9yIGEgc3BlY2lmaWMgb3BlcmF0aW9uIGtleSBvbiBhIHRhcmdldCBwcm9wZXJ0eVxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzfSBvcCAtIFRoZSBvcGVyYXRpb24ga2V5IHRvIGhhbmRsZVxuICogQHBhcmFtIHtPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBhbnksIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBoYW5kbGVyIGZ1bmN0aW9uIHRvIHJlZ2lzdGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCByZWdpc3RlcnMgdGhlIGhhbmRsZXJcbiAqIEBmdW5jdGlvbiBoYW5kbGVcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZShcbiAgb3A6IE9wZXJhdGlvbktleXMsXG4gIGhhbmRsZXI6IE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIGFueSwgYW55LCBhbnk+XG4pIHtcbiAgcmV0dXJuICh0YXJnZXQ6IGFueSwgcHJvcGVydHlLZXk6IHN0cmluZykgPT4ge1xuICAgIE9wZXJhdGlvbnMucmVnaXN0ZXIoaGFuZGxlciwgb3AsIHRhcmdldCwgcHJvcGVydHlLZXkpO1xuICB9O1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIGNyZWF0ZSBhbmQgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGR1cmluZyBib3RoIGNyZWF0ZSBhbmQgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PiB8IFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gb25DcmVhdGVVcGRhdGVcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkNyZWF0ZVVwZGF0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjpcbiAgICB8IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+XG4gICAgfCBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGR1cmluZyB1cGRhdGUgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge1VwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIG9uVXBkYXRlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25VcGRhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5VUERBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyBjcmVhdGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgZHVyaW5nIGNyZWF0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7U3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCB1cG9uIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIG9uQ3JlYXRlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25DcmVhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuQ1JFQVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyByZWFkIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGR1cmluZyByZWFkIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtJZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gb25SZWFkXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gb25SZWFkPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBJZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YTogVlxuKSB7XG4gIHJldHVybiBvbihEQk9wZXJhdGlvbnMuUkVBRCwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgZGVsZXRlIG9wZXJhdGlvbnNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGR1cmluZyBkZWxldGUgb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge09wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIHVwb24gdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gb25EZWxldGVcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBvbkRlbGV0ZTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIG9uKERCT3BlcmF0aW9ucy5ERUxFVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIGFsbCBvcGVyYXRpb24gdHlwZXNcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBiZWhhdmlvciB0byBleGVjdXRlIGR1cmluZyBhbnkgZGF0YWJhc2Ugb3BlcmF0aW9uXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBvbkFueVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uQW55PFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gb24oREJPcGVyYXRpb25zLkFMTCwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEJhc2UgZGVjb3JhdG9yIGZvciBoYW5kbGluZyBkYXRhYmFzZSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBkdXJpbmcgc3BlY2lmaWVkIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzW10gfCBEQk9wZXJhdGlvbnN9IFtvcD1EQk9wZXJhdGlvbnMuQUxMXSAtIE9uZSBvciBtb3JlIG9wZXJhdGlvbiB0eXBlcyB0byBoYW5kbGVcbiAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgdXBvbiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBvblxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIHVzYWdlOlxuICogY2xhc3MgTXlNb2RlbCB7XG4gKiAgIEBvbihEQk9wZXJhdGlvbnMuQ1JFQVRFLCBteUhhbmRsZXIpXG4gKiAgIG15UHJvcGVydHk6IHN0cmluZztcbiAqIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9uPFYgPSBvYmplY3Q+KFxuICBvcDogT3BlcmF0aW9uS2V5c1tdID0gREJPcGVyYXRpb25zLkFMTCxcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvcGVyYXRpb24oT3BlcmF0aW9uS2V5cy5PTiwgb3AsIGhhbmRsZXIsIGRhdGEpO1xufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyBwb3N0LWNyZWF0ZSBhbmQgcG9zdC11cGRhdGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgYm90aCBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7U3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4gfCBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCBhZnRlciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBhZnRlckNyZWF0ZVVwZGF0ZVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyQ3JlYXRlVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOlxuICAgIHwgU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT5cbiAgICB8IFVwZGF0ZU9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55PixcbiAgZGF0YTogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuQ1JFQVRFX1VQREFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgcG9zdC11cGRhdGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCBhZnRlciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBhZnRlclVwZGF0ZVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyVXBkYXRlPFYgPSBvYmplY3Q+KFxuICBoYW5kbGVyOiBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE6IFZcbikge1xuICByZXR1cm4gYWZ0ZXIoREJPcGVyYXRpb25zLlVQREFURSwgaGFuZGxlciwgZGF0YSk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgcG9zdC1jcmVhdGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgY3JlYXRlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIGFmdGVyIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGFmdGVyQ3JlYXRlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJDcmVhdGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhOiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5DUkVBVEUsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWNvcmF0b3IgZm9yIGhhbmRsaW5nIHBvc3QtcmVhZCBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBhZnRlciByZWFkIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIGFmdGVyIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGFmdGVyUmVhZFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyUmVhZDxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5SRUFELCBoYW5kbGVyLCBkYXRhKTtcbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciBmb3IgaGFuZGxpbmcgcG9zdC1kZWxldGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgZGVsZXRlIG9wZXJhdGlvbnNcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBmb3IgbWV0YWRhdGEsIGRlZmF1bHRzIHRvIG9iamVjdFxuICogQHBhcmFtIHtTdGFuZGFyZE9wZXJhdGlvbkhhbmRsZXI8YW55LCBhbnksIFYsIGFueSwgYW55Pn0gaGFuZGxlciAtIFRoZSBtZXRob2QgY2FsbGVkIGFmdGVyIHRoZSBvcGVyYXRpb25cbiAqIEBwYXJhbSB7Vn0gW2RhdGFdIC0gT3B0aW9uYWwgbWV0YWRhdGEgdG8gcGFzcyB0byB0aGUgaGFuZGxlclxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGFmdGVyRGVsZXRlXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gYWZ0ZXJEZWxldGU8ViA9IG9iamVjdD4oXG4gIGhhbmRsZXI6IFN0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBhZnRlcihEQk9wZXJhdGlvbnMuREVMRVRFLCBoYW5kbGVyLCBkYXRhKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRGVjb3JhdG9yIGZvciBoYW5kbGluZyBwb3N0LW9wZXJhdGlvbiBmb3IgYWxsIG9wZXJhdGlvbiB0eXBlc1xuICogQHN1bW1hcnkgRGVmaW5lcyBhIGJlaGF2aW9yIHRvIGV4ZWN1dGUgYWZ0ZXIgYW55IGRhdGFiYXNlIG9wZXJhdGlvblxuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge1N0YW5kYXJkT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIG1ldGhvZCBjYWxsZWQgYWZ0ZXIgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtWfSBbZGF0YV0gLSBPcHRpb25hbCBtZXRhZGF0YSB0byBwYXNzIHRvIHRoZSBoYW5kbGVyXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gYWZ0ZXJBbnlcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZnRlckFueTxWID0gb2JqZWN0PihcbiAgaGFuZGxlcjogU3RhbmRhcmRPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGE/OiBWXG4pIHtcbiAgcmV0dXJuIGFmdGVyKERCT3BlcmF0aW9ucy5BTEwsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGRlY29yYXRvciBmb3IgaGFuZGxpbmcgcG9zdC1vcGVyYXRpb24gYmVoYXZpb3JzXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgYmVoYXZpb3IgdG8gZXhlY3V0ZSBhZnRlciBzcGVjaWZpZWQgZGF0YWJhc2Ugb3BlcmF0aW9uc1xuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YSwgZGVmYXVsdHMgdG8gb2JqZWN0XG4gKiBAcGFyYW0ge09wZXJhdGlvbktleXNbXSB8IERCT3BlcmF0aW9uc30gW29wPURCT3BlcmF0aW9ucy5BTExdIC0gT25lIG9yIG1vcmUgb3BlcmF0aW9uIHR5cGVzIHRvIGhhbmRsZVxuICogQHBhcmFtIHtPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT59IGhhbmRsZXIgLSBUaGUgbWV0aG9kIGNhbGxlZCBhZnRlciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1Z9IFtkYXRhXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBhZnRlclxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIHVzYWdlOlxuICogY2xhc3MgTXlNb2RlbCB7XG4gKiAgIEBhZnRlcihEQk9wZXJhdGlvbnMuQ1JFQVRFLCBteUhhbmRsZXIpXG4gKiAgIG15UHJvcGVydHk6IHN0cmluZztcbiAqIH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFmdGVyPFYgPSBvYmplY3Q+KFxuICBvcDogT3BlcmF0aW9uS2V5c1tdID0gREJPcGVyYXRpb25zLkFMTCxcbiAgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+LFxuICBkYXRhPzogVlxuKSB7XG4gIHJldHVybiBvcGVyYXRpb24oT3BlcmF0aW9uS2V5cy5BRlRFUiwgb3AsIGhhbmRsZXIsIGRhdGEpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb3JlIGRlY29yYXRvciBmYWN0b3J5IGZvciBvcGVyYXRpb24gaGFuZGxlcnNcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgZGVjb3JhdG9ycyB0aGF0IHJlZ2lzdGVyIGhhbmRsZXJzIGZvciBkYXRhYmFzZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhLCBkZWZhdWx0cyB0byBvYmplY3RcbiAqIEBwYXJhbSB7T3BlcmF0aW9uS2V5cy5PTiB8IE9wZXJhdGlvbktleXMuQUZURVJ9IGJhc2VPcCAtIFdoZXRoZXIgdGhlIGhhbmRsZXIgcnVucyBkdXJpbmcgb3IgYWZ0ZXIgdGhlIG9wZXJhdGlvblxuICogQHBhcmFtIHtPcGVyYXRpb25LZXlzW119IFtvcGVyYXRpb249REJPcGVyYXRpb25zLkFMTF0gLSBUaGUgc3BlY2lmaWMgb3BlcmF0aW9ucyB0byBoYW5kbGVcbiAqIEBwYXJhbSB7T3BlcmF0aW9uSGFuZGxlcjxhbnksIGFueSwgViwgYW55LCBhbnk+fSBoYW5kbGVyIC0gVGhlIGhhbmRsZXIgZnVuY3Rpb24gdG8gZXhlY3V0ZVxuICogQHBhcmFtIHtWfSBbZGF0YVRvQWRkXSAtIE9wdGlvbmFsIG1ldGFkYXRhIHRvIHBhc3MgdG8gdGhlIGhhbmRsZXJcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBvcGVyYXRpb25cbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBEZWNvcmF0b3IgYXMgQG9wZXJhdGlvblxuICogICBwYXJ0aWNpcGFudCBPcGVyYXRpb25zIGFzIE9wZXJhdGlvbnMgUmVnaXN0cnlcbiAqICAgcGFydGljaXBhbnQgSGFuZGxlclxuICpcbiAqICAgQ2xpZW50LT4+RGVjb3JhdG9yOiBBcHBseSB0byBwcm9wZXJ0eVxuICogICBEZWNvcmF0b3ItPj5PcGVyYXRpb25zOiBSZWdpc3RlciBoYW5kbGVyXG4gKiAgIERlY29yYXRvci0+PkRlY29yYXRvcjogU3RvcmUgbWV0YWRhdGFcbiAqXG4gKiAgIE5vdGUgb3ZlciBDbGllbnQsSGFuZGxlcjogTGF0ZXIsIGR1cmluZyBvcGVyYXRpb24gZXhlY3V0aW9uXG4gKiAgIENsaWVudC0+Pk9wZXJhdGlvbnM6IEV4ZWN1dGUgb3BlcmF0aW9uXG4gKiAgIE9wZXJhdGlvbnMtPj5IYW5kbGVyOiBDYWxsIHJlZ2lzdGVyZWQgaGFuZGxlclxuICogICBIYW5kbGVyLS0+Pk9wZXJhdGlvbnM6IFJldHVybiByZXN1bHRcbiAqICAgT3BlcmF0aW9ucy0tPj5DbGllbnQ6IFJldHVybiBmaW5hbCByZXN1bHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9wZXJhdGlvbjxWID0gb2JqZWN0PihcbiAgYmFzZU9wOiBPcGVyYXRpb25LZXlzLk9OIHwgT3BlcmF0aW9uS2V5cy5BRlRFUixcbiAgb3BlcmF0aW9uOiBPcGVyYXRpb25LZXlzW10gPSBEQk9wZXJhdGlvbnMuQUxMLFxuICBoYW5kbGVyOiBPcGVyYXRpb25IYW5kbGVyPGFueSwgYW55LCBWLCBhbnksIGFueT4sXG4gIGRhdGFUb0FkZD86IFZcbikge1xuICByZXR1cm4gKHRhcmdldDogb2JqZWN0LCBwcm9wZXJ0eUtleT86IGFueSkgPT4ge1xuICAgIGNvbnN0IG5hbWUgPSB0YXJnZXQuY29uc3RydWN0b3IubmFtZTtcbiAgICBjb25zdCBkZWNvcmF0b3JzID0gb3BlcmF0aW9uLnJlZHVjZSgoYWNjdW06IGFueVtdLCBvcCkgPT4ge1xuICAgICAgY29uc3QgY29tcG91bmRLZXkgPSBiYXNlT3AgKyBvcDtcbiAgICAgIGxldCBkYXRhID0gUmVmbGVjdC5nZXRNZXRhZGF0YShcbiAgICAgICAgT3BlcmF0aW9ucy5rZXkoY29tcG91bmRLZXkpLFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHByb3BlcnR5S2V5XG4gICAgICApO1xuICAgICAgaWYgKCFkYXRhKVxuICAgICAgICBkYXRhID0ge1xuICAgICAgICAgIG9wZXJhdGlvbjogb3AsXG4gICAgICAgICAgaGFuZGxlcnM6IHt9LFxuICAgICAgICB9O1xuXG4gICAgICBjb25zdCBoYW5kbGVyS2V5ID0gT3BlcmF0aW9ucy5nZXRIYW5kbGVyTmFtZShoYW5kbGVyKTtcblxuICAgICAgaWYgKFxuICAgICAgICAhZGF0YS5oYW5kbGVyc1tuYW1lXSB8fFxuICAgICAgICAhZGF0YS5oYW5kbGVyc1tuYW1lXVtwcm9wZXJ0eUtleV0gfHxcbiAgICAgICAgIShoYW5kbGVyS2V5IGluIGRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldKVxuICAgICAgKSB7XG4gICAgICAgIGRhdGEuaGFuZGxlcnNbbmFtZV0gPSBkYXRhLmhhbmRsZXJzW25hbWVdIHx8IHt9O1xuICAgICAgICBkYXRhLmhhbmRsZXJzW25hbWVdW3Byb3BlcnR5S2V5XSA9XG4gICAgICAgICAgZGF0YS5oYW5kbGVyc1tuYW1lXVtwcm9wZXJ0eUtleV0gfHwge307XG4gICAgICAgIGRhdGEuaGFuZGxlcnNbbmFtZV1bcHJvcGVydHlLZXldW2hhbmRsZXJLZXldID0ge1xuICAgICAgICAgIGRhdGE6IGRhdGFUb0FkZCxcbiAgICAgICAgfTtcblxuICAgICAgICBhY2N1bS5wdXNoKFxuICAgICAgICAgIGhhbmRsZShjb21wb3VuZEtleSBhcyBPcGVyYXRpb25LZXlzLCBoYW5kbGVyKSxcbiAgICAgICAgICBwcm9wTWV0YWRhdGEoT3BlcmF0aW9ucy5rZXkoY29tcG91bmRLZXkpLCBkYXRhKVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sIFtdKTtcbiAgICByZXR1cm4gYXBwbHkoLi4uZGVjb3JhdG9ycykodGFyZ2V0LCBwcm9wZXJ0eUtleSk7XG4gIH07XG59XG4iLCIvKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGVycm9yIGNsYXNzIGZvciB0aGUgcmVwb3NpdG9yeSBtb2R1bGVcbiAqIEBzdW1tYXJ5IEFic3RyYWN0IGJhc2UgZXJyb3IgY2xhc3MgdGhhdCBhbGwgb3RoZXIgZXJyb3IgdHlwZXMgZXh0ZW5kIGZyb20uIFByb3ZpZGVzIGNvbW1vbiBlcnJvciBoYW5kbGluZyBmdW5jdGlvbmFsaXR5LlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXJyb3JcbiAqIEBwYXJhbSB7c3RyaW5nfEVycm9yfSBtc2cgLSBUaGUgZXJyb3IgbWVzc2FnZSBvciBFcnJvciBvYmplY3RcbiAqIEBwYXJhbSB7bnVtYmVyfSBjb2RlIC0gVGhlIEhUVFAgc3RhdHVzIGNvZGUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgZXJyb3JcbiAqIEBjbGFzcyBCYXNlRXJyb3JcbiAqIEBleGFtcGxlXG4gKiAvLyBUaGlzIGlzIGFuIGFic3RyYWN0IGNsYXNzIGFuZCBzaG91bGQgbm90IGJlIGluc3RhbnRpYXRlZCBkaXJlY3RseVxuICogLy8gSW5zdGVhZCwgdXNlIG9uZSBvZiB0aGUgY29uY3JldGUgZXJyb3IgY2xhc3NlczpcbiAqIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0ludmFsaWQgZGF0YSBwcm92aWRlZCcpO1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICByZWFkb25seSBjb2RlITogbnVtYmVyO1xuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IobmFtZTogc3RyaW5nLCBtc2c6IHN0cmluZyB8IEVycm9yLCBjb2RlOiBudW1iZXIgPSA1MDApIHtcbiAgICBpZiAobXNnIGluc3RhbmNlb2YgQmFzZUVycm9yKSByZXR1cm4gbXNnO1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBgWyR7bmFtZX1dICR7bXNnIGluc3RhbmNlb2YgRXJyb3IgPyBtc2cubWVzc2FnZSA6IG1zZ31gO1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgIHRoaXMuY29kZSA9IGNvZGU7XG4gICAgaWYgKG1zZyBpbnN0YW5jZW9mIEVycm9yKSB0aGlzLnN0YWNrID0gbXNnLnN0YWNrO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIHZhbGlkYXRpb24gZmFpbHNcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBmYWlsdXJlIGluIHRoZSBNb2RlbCBkZXRhaWxzLCB0eXBpY2FsbHkgdGhyb3duIHdoZW4gZGF0YSB2YWxpZGF0aW9uIGZhaWxzXG4gKiBAcGFyYW0ge3N0cmluZ3xFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgRXJyb3Igb2JqZWN0XG4gKiBAcmV0dXJuIHtWYWxpZGF0aW9uRXJyb3J9IEEgbmV3IFZhbGlkYXRpb25FcnJvciBpbnN0YW5jZVxuICogQGNsYXNzIFZhbGlkYXRpb25FcnJvclxuICogQGV4YW1wbGVcbiAqIC8vIFRocm93IGEgdmFsaWRhdGlvbiBlcnJvciB3aGVuIGRhdGEgaXMgaW52YWxpZFxuICogaWYgKCFpc1ZhbGlkKGRhdGEpKSB7XG4gKiAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0ludmFsaWQgZGF0YSBmb3JtYXQnKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25FcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihWYWxpZGF0aW9uRXJyb3IubmFtZSwgbXNnLCA0MjIpO1xuICB9XG59XG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFcnJvciB0aHJvd24gZm9yIGludGVybmFsIHN5c3RlbSBmYWlsdXJlc1xuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhbiBpbnRlcm5hbCBmYWlsdXJlIChzaG91bGQgbWVhbiBhbiBlcnJvciBpbiBjb2RlKSB3aXRoIEhUVFAgNTAwIHN0YXR1cyBjb2RlXG4gKiBAcGFyYW0ge3N0cmluZ3xFcnJvcn0gbXNnIC0gVGhlIGVycm9yIG1lc3NhZ2Ugb3IgRXJyb3Igb2JqZWN0XG4gKiBAcmV0dXJuIHtJbnRlcm5hbEVycm9yfSBBIG5ldyBJbnRlcm5hbEVycm9yIGluc3RhbmNlXG4gKiBAY2xhc3MgSW50ZXJuYWxFcnJvclxuICogQGV4YW1wbGVcbiAqIC8vIFRocm93IGFuIGludGVybmFsIGVycm9yIHdoZW4gYW4gdW5leHBlY3RlZCBjb25kaXRpb24gb2NjdXJzXG4gKiB0cnkge1xuICogICAvLyBTb21lIG9wZXJhdGlvblxuICogfSBjYXRjaCAoZXJyb3IpIHtcbiAqICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoJ1VuZXhwZWN0ZWQgaW50ZXJuYWwgZXJyb3Igb2NjdXJyZWQnKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIEludGVybmFsRXJyb3IgZXh0ZW5kcyBCYXNlRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihtc2c6IHN0cmluZyB8IEVycm9yKSB7XG4gICAgc3VwZXIoSW50ZXJuYWxFcnJvci5uYW1lLCBtc2csIDUwMCk7XG4gIH1cbn1cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIHNlcmlhbGl6YXRpb24gb3IgZGVzZXJpYWxpemF0aW9uIGZhaWxzXG4gKiBAc3VtbWFyeSBSZXByZXNlbnRzIGEgZmFpbHVyZSBpbiB0aGUgTW9kZWwgZGUvc2VyaWFsaXphdGlvbiwgdHlwaWNhbGx5IHdoZW4gY29udmVydGluZyBiZXR3ZWVuIGRhdGEgZm9ybWF0c1xuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIEVycm9yIG9iamVjdFxuICogQHJldHVybiB7U2VyaWFsaXphdGlvbkVycm9yfSBBIG5ldyBTZXJpYWxpemF0aW9uRXJyb3IgaW5zdGFuY2VcbiAqIEBjbGFzcyBTZXJpYWxpemF0aW9uRXJyb3JcbiAqIEBleGFtcGxlXG4gKiAvLyBUaHJvdyBhIHNlcmlhbGl6YXRpb24gZXJyb3Igd2hlbiBKU09OIHBhcnNpbmcgZmFpbHNcbiAqIHRyeSB7XG4gKiAgIGNvbnN0IGRhdGEgPSBKU09OLnBhcnNlKGludmFsaWRKc29uKTtcbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoJ0ZhaWxlZCB0byBwYXJzZSBKU09OIGRhdGEnKTtcbiAqIH1cbiAqL1xuZXhwb3J0IGNsYXNzIFNlcmlhbGl6YXRpb25FcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihTZXJpYWxpemF0aW9uRXJyb3IubmFtZSwgbXNnLCA0MjIpO1xuICB9XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEVycm9yIHRocm93biB3aGVuIGEgcmVxdWVzdGVkIHJlc291cmNlIGlzIG5vdCBmb3VuZFxuICogQHN1bW1hcnkgUmVwcmVzZW50cyBhIGZhaWx1cmUgaW4gZmluZGluZyBhIG1vZGVsLCByZXN1bHRpbmcgaW4gYSA0MDQgSFRUUCBzdGF0dXMgY29kZVxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIEVycm9yIG9iamVjdFxuICogQHJldHVybiB7Tm90Rm91bmRFcnJvcn0gQSBuZXcgTm90Rm91bmRFcnJvciBpbnN0YW5jZVxuICogQGNsYXNzIE5vdEZvdW5kRXJyb3JcbiAqIEBleGFtcGxlXG4gKiAvLyBUaHJvdyBhIG5vdCBmb3VuZCBlcnJvciB3aGVuIGEgcmVjb3JkIGRvZXNuJ3QgZXhpc3RcbiAqIGNvbnN0IHVzZXIgPSBhd2FpdCByZXBvc2l0b3J5LmZpbmRCeUlkKGlkKTtcbiAqIGlmICghdXNlcikge1xuICogICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihgVXNlciB3aXRoIElEICR7aWR9IG5vdCBmb3VuZGApO1xuICogfVxuICovXG5leHBvcnQgY2xhc3MgTm90Rm91bmRFcnJvciBleHRlbmRzIEJhc2VFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1zZzogc3RyaW5nIHwgRXJyb3IpIHtcbiAgICBzdXBlcihOb3RGb3VuZEVycm9yLm5hbWUsIG1zZywgNDA0KTtcbiAgfVxufVxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRXJyb3IgdGhyb3duIHdoZW4gYSBjb25mbGljdCBvY2N1cnMgaW4gdGhlIHN0b3JhZ2VcbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgYSBjb25mbGljdCBpbiB0aGUgc3RvcmFnZSwgdHlwaWNhbGx5IHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBhIGR1cGxpY2F0ZSByZXNvdXJjZVxuICogQHBhcmFtIHtzdHJpbmd8RXJyb3J9IG1zZyAtIFRoZSBlcnJvciBtZXNzYWdlIG9yIEVycm9yIG9iamVjdFxuICogQHJldHVybiB7Q29uZmxpY3RFcnJvcn0gQSBuZXcgQ29uZmxpY3RFcnJvciBpbnN0YW5jZVxuICogQGNsYXNzIENvbmZsaWN0RXJyb3JcbiAqIEBleGFtcGxlXG4gKiAvLyBUaHJvdyBhIGNvbmZsaWN0IGVycm9yIHdoZW4gdHJ5aW5nIHRvIGNyZWF0ZSBhIGR1cGxpY2F0ZSByZWNvcmRcbiAqIGNvbnN0IGV4aXN0aW5nVXNlciA9IGF3YWl0IHJlcG9zaXRvcnkuZmluZEJ5RW1haWwoZW1haWwpO1xuICogaWYgKGV4aXN0aW5nVXNlcikge1xuICogICB0aHJvdyBuZXcgQ29uZmxpY3RFcnJvcihgVXNlciB3aXRoIGVtYWlsICR7ZW1haWx9IGFscmVhZHkgZXhpc3RzYCk7XG4gKiB9XG4gKi9cbmV4cG9ydCBjbGFzcyBDb25mbGljdEVycm9yIGV4dGVuZHMgQmFzZUVycm9yIHtcbiAgY29uc3RydWN0b3IobXNnOiBzdHJpbmcgfCBFcnJvcikge1xuICAgIHN1cGVyKENvbmZsaWN0RXJyb3IubmFtZSwgbXNnLCA0MDkpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBPcGVyYXRpb25zIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvT3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uSGFuZGxlciwgVXBkYXRlT3BlcmF0aW9uSGFuZGxlciB9IGZyb20gXCIuLi9vcGVyYXRpb25zL3R5cGVzXCI7XG5pbXBvcnQgeyBJUmVwb3NpdG9yeSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0lSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBEZWNvcmF0b3JNZXRhZGF0YSwgUmVmbGVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsLCBNb2RlbEtleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29udGV4dCBhcmd1bWVudHMgZm9yIHJlcG9zaXRvcnkgb3BlcmF0aW9ucy5cbiAqIEBzdW1tYXJ5IFJlcHJlc2VudHMgdGhlIGNvbnRleHQgYW5kIGFyZ3VtZW50cyBmb3IgcmVwb3NpdG9yeSBvcGVyYXRpb25zLlxuICogVGhpcyB0eXBlIGlzIHVzZWQgdG8gcGFzcyBjb250ZXh0IGFuZCBhcmd1bWVudHMgYmV0d2VlbiByZXBvc2l0b3J5IG1ldGhvZHMuXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGUsIGRlZmF1bHRzIHRvIFJlcG9zaXRvcnlGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlLCBkZWZhdWx0cyB0byBDb250ZXh0PEY+XG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBDb250ZXh0QXJnc1xuICogQHByb3BlcnR5IHtDfSBjb250ZXh0IC0gVGhlIG9wZXJhdGlvbiBjb250ZXh0XG4gKiBAcHJvcGVydHkge2FueVtdfSBhcmdzIC0gVGhlIG9wZXJhdGlvbiBhcmd1bWVudHNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgdHlwZSBDb250ZXh0QXJnczxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiA9IHtcbiAgY29udGV4dDogQztcbiAgYXJnczogYW55W107XG59O1xuXG4vKipcbiAqIEBzdW1tYXJ5IHJldHJpZXZlcyB0aGUgYXJndW1lbnRzIGZvciB0aGUgaGFuZGxlclxuICogQHBhcmFtIHthbnl9IGRlYyB0aGUgZGVjb3JhdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcCB0aGUgcHJvcGVydHkgbmFtZVxuICogQHBhcmFtIHt7fX0gbSB0aGUgbW9kZWxcbiAqIEBwYXJhbSB7e319IFthY2N1bV0gYWNjdW11bGF0b3IgdXNlZCBmb3IgaW50ZXJuYWwgcmVjdXJzaXZlbmVzc1xuICpcbiAqIEBmdW5jdGlvbiBnZXRIYW5kbGVyQXJnc1xuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzLlJlcG9zaXRvcnlcbiAqL1xuZXhwb3J0IGNvbnN0IGdldEhhbmRsZXJBcmdzID0gZnVuY3Rpb24gKFxuICBkZWM6IGFueSxcbiAgcHJvcDogc3RyaW5nLFxuICBtOiBDb25zdHJ1Y3Rvcjxhbnk+LFxuICBhY2N1bT86IFJlY29yZDxzdHJpbmcsIHsgYXJnczogc3RyaW5nW10gfT5cbik6IFJlY29yZDxzdHJpbmcsIHsgYXJnczogc3RyaW5nW10gfT4gfCB2b2lkIHtcbiAgY29uc3QgbmFtZSA9IG0uY29uc3RydWN0b3IubmFtZTtcbiAgaWYgKCFuYW1lKSB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkNvdWxkIG5vdCBkZXRlcm1pbmUgbW9kZWwgY2xhc3NcIik7XG4gIGFjY3VtID0gYWNjdW0gfHwge307XG5cbiAgaWYgKGRlYy5wcm9wcy5oYW5kbGVyc1tuYW1lXSAmJiBkZWMucHJvcHMuaGFuZGxlcnNbbmFtZV1bcHJvcF0pXG4gICAgYWNjdW0gPSB7IC4uLmRlYy5wcm9wcy5oYW5kbGVyc1tuYW1lXVtwcm9wXSwgLi4uYWNjdW0gfTtcblxuICBsZXQgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YobSk7XG4gIGlmIChwcm90byA9PT0gT2JqZWN0LnByb3RvdHlwZSkgcmV0dXJuIGFjY3VtO1xuICBpZiAocHJvdG8uY29uc3RydWN0b3IubmFtZSA9PT0gbmFtZSkgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xuXG4gIHJldHVybiBnZXRIYW5kbGVyQXJncyhkZWMsIHByb3AsIHByb3RvLCBhY2N1bSk7XG59O1xuXG4vKipcbiAqXG4gKiBAcGFyYW0ge0lSZXBvc2l0b3J5PFQ+fSByZXBvXG4gKiBAcGFyYW0gY29udGV4dFxuICogQHBhcmFtIHtUfSBtb2RlbFxuICogQHBhcmFtIG9wZXJhdGlvblxuICogQHBhcmFtIHByZWZpeFxuICpcbiAqIEBwYXJhbSBvbGRNb2RlbFxuICogQGZ1bmN0aW9uIGVuZm9yY2VEQlByb3BlcnR5RGVjb3JhdG9yc0FzeW5jXG4gKlxuICogQG1lbWJlck9mIGRiLWRlY29yYXRvcnMudXRpbHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGVuZm9yY2VEQkRlY29yYXRvcnM8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICBWIGV4dGVuZHMgb2JqZWN0ID0gb2JqZWN0LFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KFxuICByZXBvOiBSLFxuICBjb250ZXh0OiBDLFxuICBtb2RlbDogTSxcbiAgb3BlcmF0aW9uOiBzdHJpbmcsXG4gIHByZWZpeDogc3RyaW5nLFxuICBvbGRNb2RlbD86IE1cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBkZWNvcmF0b3JzOiBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YVtdPiB8IHVuZGVmaW5lZCA9XG4gICAgZ2V0RGJEZWNvcmF0b3JzKG1vZGVsLCBvcGVyYXRpb24sIHByZWZpeCk7XG5cbiAgaWYgKCFkZWNvcmF0b3JzKSByZXR1cm47XG5cbiAgZm9yIChjb25zdCBwcm9wIGluIGRlY29yYXRvcnMpIHtcbiAgICBjb25zdCBkZWNzOiBEZWNvcmF0b3JNZXRhZGF0YVtdID0gZGVjb3JhdG9yc1twcm9wXTtcbiAgICBmb3IgKGNvbnN0IGRlYyBvZiBkZWNzKSB7XG4gICAgICBjb25zdCB7IGtleSB9ID0gZGVjO1xuICAgICAgY29uc3QgaGFuZGxlcnM6IE9wZXJhdGlvbkhhbmRsZXI8TSwgUiwgViwgRiwgQz5bXSB8IHVuZGVmaW5lZCA9XG4gICAgICAgIE9wZXJhdGlvbnMuZ2V0PE0sIFIsIFYsIEYsIEM+KG1vZGVsLCBwcm9wLCBwcmVmaXggKyBrZXkpO1xuICAgICAgaWYgKCFoYW5kbGVycyB8fCAhaGFuZGxlcnMubGVuZ3RoKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgQ291bGQgbm90IGZpbmQgcmVnaXN0ZXJlZCBoYW5kbGVyIGZvciB0aGUgb3BlcmF0aW9uICR7cHJlZml4ICsga2V5fSB1bmRlciBwcm9wZXJ0eSAke3Byb3B9YFxuICAgICAgICApO1xuXG4gICAgICBjb25zdCBoYW5kbGVyQXJncyA9IGdldEhhbmRsZXJBcmdzKGRlYywgcHJvcCwgbW9kZWwgYXMgYW55KTtcblxuICAgICAgaWYgKCFoYW5kbGVyQXJncyB8fCBPYmplY3QudmFsdWVzKGhhbmRsZXJBcmdzKS5sZW5ndGggIT09IGhhbmRsZXJzLmxlbmd0aClcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJBcmdzIGFuZCBoYW5kbGVycyBsZW5ndGggZG8gbm90IG1hdGNoXCIpO1xuXG4gICAgICBsZXQgaGFuZGxlcjogT3BlcmF0aW9uSGFuZGxlcjxNLCBSLCBWLCBGLCBDPjtcbiAgICAgIGxldCBkYXRhOiBhbnk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhhbmRsZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGhhbmRsZXIgPSBoYW5kbGVyc1tpXTtcbiAgICAgICAgZGF0YSA9IE9iamVjdC52YWx1ZXMoaGFuZGxlckFyZ3MpW2ldO1xuXG4gICAgICAgIGNvbnN0IGFyZ3M6IGFueVtdID0gW2NvbnRleHQsIGRhdGEuZGF0YSwgcHJvcCwgbW9kZWxdO1xuXG4gICAgICAgIGlmIChvcGVyYXRpb24gPT09IE9wZXJhdGlvbktleXMuVVBEQVRFICYmIHByZWZpeCA9PT0gT3BlcmF0aW9uS2V5cy5PTikge1xuICAgICAgICAgIGlmICghb2xkTW9kZWwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc3Npbmcgb2xkIG1vZGVsIGZvciB1cGRhdGUgb3BlcmF0aW9uXCIpO1xuICAgICAgICAgIGFyZ3MucHVzaChvbGRNb2RlbCk7XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCAoaGFuZGxlciBhcyBVcGRhdGVPcGVyYXRpb25IYW5kbGVyPE0sIFIsIFYsIEYsIEM+KS5hcHBseShcbiAgICAgICAgICAgIHJlcG8sXG4gICAgICAgICAgICBhcmdzIGFzIFtDLCBWLCBrZXlvZiBNLCBNLCBNXVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgICAgICBjb25zdCBtc2cgPSBgRmFpbGVkIHRvIGV4ZWN1dGUgaGFuZGxlciAke2hhbmRsZXIubmFtZX0gZm9yICR7cHJvcH0gb24gJHttb2RlbC5jb25zdHJ1Y3Rvci5uYW1lfSBkdWUgdG8gZXJyb3I6ICR7ZX1gO1xuICAgICAgICAgIGlmIChjb250ZXh0LmdldChcImJyZWFrT25IYW5kbGVyRXJyb3JcIikpIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKG1zZyk7XG4gICAgICAgICAgY29uc29sZS5sb2cobXNnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFNwZWNpZmljIGZvciBEQiBEZWNvcmF0b3JzXG4gKiBAcGFyYW0ge1R9IG1vZGVsXG4gKiBAcGFyYW0ge3N0cmluZ30gb3BlcmF0aW9uIENSVUQge0BsaW5rIE9wZXJhdGlvbktleXN9XG4gKiBAcGFyYW0ge3N0cmluZ30gW2V4dHJhUHJlZml4XVxuICpcbiAqIEBmdW5jdGlvbiBnZXREYlByb3BlcnR5RGVjb3JhdG9yc1xuICpcbiAqIEBtZW1iZXJPZiBkYi1kZWNvcmF0b3JzLnV0aWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREYkRlY29yYXRvcnM8VCBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IFQsXG4gIG9wZXJhdGlvbjogc3RyaW5nLFxuICBleHRyYVByZWZpeD86IHN0cmluZ1xuKTogUmVjb3JkPHN0cmluZywgRGVjb3JhdG9yTWV0YWRhdGFbXT4gfCB1bmRlZmluZWQge1xuICBjb25zdCBkZWNvcmF0b3JzOiBSZWNvcmQ8c3RyaW5nLCBEZWNvcmF0b3JNZXRhZGF0YVtdPiB8IHVuZGVmaW5lZCA9XG4gICAgUmVmbGVjdGlvbi5nZXRBbGxQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICBtb2RlbCxcbiAgICAgIC8vIHVuZGVmaW5lZCxcbiAgICAgIE9wZXJhdGlvbktleXMuUkVGTEVDVCArIChleHRyYVByZWZpeCA/IGV4dHJhUHJlZml4IDogXCJcIilcbiAgICApO1xuICBpZiAoIWRlY29yYXRvcnMpIHJldHVybjtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKGRlY29yYXRvcnMpLnJlZHVjZShcbiAgICAoYWNjdW06IFJlY29yZDxzdHJpbmcsIERlY29yYXRvck1ldGFkYXRhW10+IHwgdW5kZWZpbmVkLCBkZWNvcmF0b3IpID0+IHtcbiAgICAgIGNvbnN0IGRlYyA9IGRlY29yYXRvcnNbZGVjb3JhdG9yXS5maWx0ZXIoKGQpID0+IGQua2V5ID09PSBvcGVyYXRpb24pO1xuICAgICAgaWYgKGRlYyAmJiBkZWMubGVuZ3RoKSB7XG4gICAgICAgIGlmICghYWNjdW0pIGFjY3VtID0ge307XG4gICAgICAgIGFjY3VtW2RlY29yYXRvcl0gPSBkZWM7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdW07XG4gICAgfSxcbiAgICB1bmRlZmluZWRcbiAgKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIGRlY29yYXRvcnMgZm9yIGFuIG9iamVjdCdzIHByb3BlcnRpZXMgcHJlZml4ZWQgYnkge0BwYXJhbSBwcmVmaXhlc30gcmVjdXJzaXZlbHlcbiAqIEBwYXJhbSBtb2RlbFxuICogQHBhcmFtIGFjY3VtXG4gKiBAcGFyYW0gcHJlZml4ZXNcbiAqXG4gKiBAZnVuY3Rpb24gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnMuUmVwb3NpdG9yeVxuICovXG5leHBvcnQgY29uc3QgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlID0gZnVuY3Rpb24gPFQgZXh0ZW5kcyBNb2RlbD4oXG4gIG1vZGVsOiBULFxuICBhY2N1bTogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSB8IHVuZGVmaW5lZCxcbiAgLi4ucHJlZml4ZXM6IHN0cmluZ1tdXG4pOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgYWNjdW11bGF0b3IgPSBhY2N1bSB8fCB7fTtcbiAgY29uc3QgbWVyZ2VEZWNvcmF0b3JzID0gZnVuY3Rpb24gKGRlY3M6IHsgW2luZGV4ZXI6IHN0cmluZ106IGFueVtdIH0pIHtcbiAgICBjb25zdCBwdXNoT3JTcXVhc2ggPSAoa2V5OiBzdHJpbmcsIC4uLnZhbHVlczogYW55W10pID0+IHtcbiAgICAgIHZhbHVlcy5mb3JFYWNoKCh2YWwpID0+IHtcbiAgICAgICAgbGV0IG1hdGNoOiBhbnk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAhKG1hdGNoID0gYWNjdW11bGF0b3Jba2V5XS5maW5kKChlKSA9PiBlLmtleSA9PT0gdmFsLmtleSkpIHx8XG4gICAgICAgICAgbWF0Y2gucHJvcHMub3BlcmF0aW9uICE9PSB2YWwucHJvcHMub3BlcmF0aW9uXG4gICAgICAgICkge1xuICAgICAgICAgIGFjY3VtdWxhdG9yW2tleV0ucHVzaCh2YWwpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwua2V5ID09PSBNb2RlbEtleXMuVFlQRSkgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IHsgaGFuZGxlcnMsIG9wZXJhdGlvbiB9ID0gdmFsLnByb3BzO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAhb3BlcmF0aW9uIHx8XG4gICAgICAgICAgIW9wZXJhdGlvbi5tYXRjaChcbiAgICAgICAgICAgIG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgIGBeKDo/JHtPcGVyYXRpb25LZXlzLk9OfXwke09wZXJhdGlvbktleXMuQUZURVJ9KSg6PyR7T3BlcmF0aW9uS2V5cy5DUkVBVEV9fCR7T3BlcmF0aW9uS2V5cy5SRUFEfXwke09wZXJhdGlvbktleXMuVVBEQVRFfXwke09wZXJhdGlvbktleXMuREVMRVRFfSkkYFxuICAgICAgICAgICAgKVxuICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgYWNjdW11bGF0b3Jba2V5XS5wdXNoKHZhbCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYWNjdW1IYW5kbGVycyA9IG1hdGNoLnByb3BzLmhhbmRsZXJzO1xuXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKGhhbmRsZXJzKS5mb3JFYWNoKChbY2xhenosIGhhbmRsZXJEZWZdKSA9PiB7XG4gICAgICAgICAgaWYgKCEoY2xhenogaW4gYWNjdW1IYW5kbGVycykpIHtcbiAgICAgICAgICAgIGFjY3VtSGFuZGxlcnNbY2xhenpdID0gaGFuZGxlckRlZjtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBPYmplY3QuZW50cmllcyhoYW5kbGVyRGVmIGFzIG9iamVjdCkuZm9yRWFjaChcbiAgICAgICAgICAgIChbaGFuZGxlclByb3AsIGhhbmRsZXJdKSA9PiB7XG4gICAgICAgICAgICAgIGlmICghKGhhbmRsZXJQcm9wIGluIGFjY3VtSGFuZGxlcnNbY2xhenpdKSkge1xuICAgICAgICAgICAgICAgIGFjY3VtSGFuZGxlcnNbY2xhenpdW2hhbmRsZXJQcm9wXSA9IGhhbmRsZXI7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgT2JqZWN0LmVudHJpZXMoaGFuZGxlciBhcyBvYmplY3QpLmZvckVhY2goXG4gICAgICAgICAgICAgICAgKFtoYW5kbGVyS2V5LCBhcmdzT2JqXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKCEoaGFuZGxlcktleSBpbiBhY2N1bUhhbmRsZXJzW2NsYXp6XVtoYW5kbGVyUHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGFjY3VtSGFuZGxlcnNbY2xhenpdW2hhbmRsZXJQcm9wXVtoYW5kbGVyS2V5XSA9IGFyZ3NPYmo7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICAgICAgYFNraXBwaW5nIGhhbmRsZXIgcmVnaXN0cmF0aW9uIGZvciAke2NsYXp6fSB1bmRlciBwcm9wICR7aGFuZGxlclByb3B9IGJlY2F1c2UgaGFuZGxlciBpcyB0aGUgc2FtZWBcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIE9iamVjdC5lbnRyaWVzKGRlY3MpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgYWNjdW11bGF0b3Jba2V5XSA9IGFjY3VtdWxhdG9yW2tleV0gfHwgW107XG4gICAgICBwdXNoT3JTcXVhc2goa2V5LCAuLi52YWx1ZSk7XG4gICAgfSk7XG4gIH07XG5cbiAgY29uc3QgZGVjczogeyBbaW5kZXhlcjogc3RyaW5nXTogYW55W10gfSB8IHVuZGVmaW5lZCA9XG4gICAgUmVmbGVjdGlvbi5nZXRBbGxQcm9wZXJ0eURlY29yYXRvcnMobW9kZWwsIC4uLnByZWZpeGVzKTtcbiAgaWYgKGRlY3MpIG1lcmdlRGVjb3JhdG9ycyhkZWNzKTtcblxuICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZGVsKSA9PT0gT2JqZWN0LnByb3RvdHlwZSkgcmV0dXJuIGFjY3VtdWxhdG9yO1xuXG4gIC8vIGNvbnN0IG5hbWUgPSBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lO1xuICBjb25zdCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihtb2RlbCk7XG4gIGlmICghcHJvdG8pIHJldHVybiBhY2N1bXVsYXRvcjtcbiAgLy8gaWYgKHByb3RvLmNvbnN0cnVjdG9yICYmIHByb3RvLmNvbnN0cnVjdG9yLm5hbWUgPT09IG5hbWUpXG4gIC8vICAgICBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90bylcbiAgcmV0dXJuIGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZShwcm90bywgYWNjdW11bGF0b3IsIC4uLnByZWZpeGVzKTtcbn07XG4iLCJpbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBEZWZhdWx0IGNvbmZpZ3VyYXRpb24gZmxhZ3MgZm9yIHJlcG9zaXRvcnkgb3BlcmF0aW9ucy5cbiAqIEBzdW1tYXJ5IFByb3ZpZGVzIGRlZmF1bHQgdmFsdWVzIGZvciByZXBvc2l0b3J5IG9wZXJhdGlvbiBmbGFncywgZXhjbHVkaW5nIHRoZSB0aW1lc3RhbXAgcHJvcGVydHkuXG4gKiBUaGVzZSBmbGFncyBjb250cm9sIGJlaGF2aW9yIHN1Y2ggYXMgY29udGV4dCBoYW5kbGluZywgdmFsaWRhdGlvbiwgZXJyb3IgaGFuZGxpbmcsIGFuZCBtb3JlLlxuICogQGNvbnN0IERlZmF1bHRSZXBvc2l0b3J5RmxhZ3NcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdFJlcG9zaXRvcnlGbGFnczogT21pdDxSZXBvc2l0b3J5RmxhZ3MsIFwidGltZXN0YW1wXCI+ID0ge1xuICBwYXJlbnRDb250ZXh0OiB1bmRlZmluZWQsXG4gIGNoaWxkQ29udGV4dHM6IFtdLFxuICBpZ25vcmVkVmFsaWRhdGlvblByb3BlcnRpZXM6IFtdLFxuICBjYWxsQXJnczogW10sXG4gIHdyaXRlT3BlcmF0aW9uOiBmYWxzZSxcbiAgYWZmZWN0ZWRUYWJsZXM6IFtdLFxuICBvcGVyYXRpb246IHVuZGVmaW5lZCxcbiAgYnJlYWtPbkhhbmRsZXJFcnJvcjogdHJ1ZSxcbiAgcmVidWlsZFdpdGhUcmFuc2llbnQ6IHRydWUsXG59O1xuIiwiaW1wb3J0IHsgQ29udGV4dEFyZ3MgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgQ29udGV4dHVhbCB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL0NvbnRleHR1YWxcIjtcbmltcG9ydCB7IE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9ucy9jb25zdGFudHNcIjtcbmltcG9ydCB7IENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERlZmF1bHRSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IE9iamVjdEFjY3VtdWxhdG9yIH0gZnJvbSBcInR5cGVkLW9iamVjdC1hY2N1bXVsYXRvclwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gRmFjdG9yeSB0eXBlIGZvciBjcmVhdGluZyBjb250ZXh0IGluc3RhbmNlcy5cbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBmdW5jdGlvbiB0eXBlIHRoYXQgY3JlYXRlcyBjb250ZXh0IGluc3RhbmNlcyB3aXRoIHNwZWNpZmljIHJlcG9zaXRvcnkgZmxhZ3MuXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGUgZXh0ZW5kaW5nIFJlcG9zaXRvcnlGbGFnc1xuICogQHR5cGVkZWYge0Z1bmN0aW9ufSBDb250ZXh0RmFjdG9yeVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCB0eXBlIENvbnRleHRGYWN0b3J5PEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3M+ID0gPEMgZXh0ZW5kcyBDb250ZXh0PEY+PihcbiAgYXJnOiBPbWl0PEYsIFwidGltZXN0YW1wXCI+XG4pID0+IEM7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlZmF1bHQgZmFjdG9yeSBmb3IgY3JlYXRpbmcgY29udGV4dCBpbnN0YW5jZXMuXG4gKiBAc3VtbWFyeSBBIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIG5ldyBDb250ZXh0IGluc3RhbmNlcyB3aXRoIHRoZSBwcm92aWRlZCByZXBvc2l0b3J5IGZsYWdzLlxuICogSXQgYXV0b21hdGljYWxseSBhZGRzIGEgdGltZXN0YW1wIHRvIHRoZSBjb250ZXh0IGFuZCByZXR1cm5zIGEgcHJvcGVybHkgdHlwZWQgY29udGV4dCBpbnN0YW5jZS5cbiAqIEBjb25zdCBEZWZhdWx0Q29udGV4dEZhY3RvcnlcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgY29uc3QgRGVmYXVsdENvbnRleHRGYWN0b3J5OiBDb250ZXh0RmFjdG9yeTxhbnk+ID0gPFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPixcbj4oXG4gIGFyZzogT21pdDxGLCBcInRpbWVzdGFtcFwiPlxuKSA9PiB7XG4gIHJldHVybiBuZXcgQ29udGV4dDxGPigpLmFjY3VtdWxhdGUoXG4gICAgT2JqZWN0LmFzc2lnbih7fSwgYXJnLCB7IHRpbWVzdGFtcDogbmV3IERhdGUoKSB9KSBhcyBGXG4gICkgYXMgQztcbn07XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEEgY29udGV4dCBtYW5hZ2VtZW50IGNsYXNzIGZvciBoYW5kbGluZyByZXBvc2l0b3J5IG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBUaGUgQ29udGV4dCBjbGFzcyBwcm92aWRlcyBhIG1lY2hhbmlzbSBmb3IgbWFuYWdpbmcgcmVwb3NpdG9yeSBvcGVyYXRpb25zIHdpdGggZmxhZ3MsXG4gKiBwYXJlbnQtY2hpbGQgcmVsYXRpb25zaGlwcywgYW5kIHN0YXRlIGFjY3VtdWxhdGlvbi4gSXQgYWxsb3dzIGZvciBoaWVyYXJjaGljYWwgY29udGV4dCBjaGFpbnNcbiAqIGFuZCBtYWludGFpbnMgb3BlcmF0aW9uLXNwZWNpZmljIGNvbmZpZ3VyYXRpb25zIHdoaWxlIHN1cHBvcnRpbmcgdHlwZSBzYWZldHkgdGhyb3VnaCBnZW5lcmljcy5cbiAqXG4gKiBAdGVtcGxhdGUgRiAtIFR5cGUgZXh0ZW5kaW5nIFJlcG9zaXRvcnlGbGFncyB0aGF0IGRlZmluZXMgdGhlIGNvbnRleHQgY29uZmlndXJhdGlvblxuICpcbiAqIEBwYXJhbSB7T2JqZWN0QWNjdW11bGF0b3I8Rj59IGNhY2hlIC0gVGhlIGludGVybmFsIGNhY2hlIHN0b3JpbmcgYWNjdW11bGF0ZWQgdmFsdWVzXG4gKlxuICogQGNsYXNzXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIENyZWF0aW5nIGEgbmV3IGNvbnRleHQgd2l0aCByZXBvc2l0b3J5IGZsYWdzXG4gKiBjb25zdCBjb250ZXh0ID0gbmV3IENvbnRleHQ8UmVwb3NpdG9yeUZsYWdzPigpO1xuICpcbiAqIC8vIEFjY3VtdWxhdGluZyB2YWx1ZXNcbiAqIGNvbnN0IGVucmljaGVkQ29udGV4dCA9IGNvbnRleHQuYWNjdW11bGF0ZSh7XG4gKiAgIHdyaXRlT3BlcmF0aW9uOiB0cnVlLFxuICogICBhZmZlY3RlZFRhYmxlczogWyd1c2VycyddLFxuICogICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMuQ1JFQVRFXG4gKiB9KTtcbiAqXG4gKiAvLyBBY2Nlc3NpbmcgdmFsdWVzXG4gKiBjb25zdCBpc1dyaXRlID0gZW5yaWNoZWRDb250ZXh0LmdldCgnd3JpdGVPcGVyYXRpb24nKTsgLy8gdHJ1ZVxuICogY29uc3QgdGFibGVzID0gZW5yaWNoZWRDb250ZXh0LmdldCgnYWZmZWN0ZWRUYWJsZXMnKTsgLy8gWyd1c2VycyddXG4gKiBgYGBcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IEN0eCBhcyBDb250ZXh0XG4gKiAgIHBhcnRpY2lwYW50IENhY2hlIGFzIE9iamVjdEFjY3VtdWxhdG9yXG4gKlxuICogICBDLT4+Q3R4OiBuZXcgQ29udGV4dCgpXG4gKiAgIEN0eC0+PkNhY2hlOiBjcmVhdGUgY2FjaGVcbiAqXG4gKiAgIEMtPj5DdHg6IGFjY3VtdWxhdGUodmFsdWUpXG4gKiAgIEN0eC0+PkNhY2hlOiBhY2N1bXVsYXRlKHZhbHVlKVxuICogICBDYWNoZS0tPj5DdHg6IHVwZGF0ZWQgY2FjaGVcbiAqICAgQ3R4LS0+PkM6IHVwZGF0ZWQgY29udGV4dFxuICpcbiAqICAgQy0+PkN0eDogZ2V0KGtleSlcbiAqICAgQ3R4LT4+Q2FjaGU6IGdldChrZXkpXG4gKiAgIGFsdCBLZXkgZXhpc3RzIGluIGNhY2hlXG4gKiAgICAgQ2FjaGUtLT4+Q3R4OiB2YWx1ZVxuICogICBlbHNlIEtleSBub3QgZm91bmRcbiAqICAgICBDdHgtPj5DdHg6IGNoZWNrIHBhcmVudCBjb250ZXh0XG4gKiAgICAgYWx0IFBhcmVudCBleGlzdHNcbiAqICAgICAgIEN0eC0+PlBhcmVudDogZ2V0KGtleSlcbiAqICAgICAgIFBhcmVudC0tPj5DdHg6IHZhbHVlXG4gKiAgICAgZWxzZSBObyBwYXJlbnRcbiAqICAgICAgIEN0eC0tPj5DOiB0aHJvdyBlcnJvclxuICogICAgIGVuZFxuICogICBlbmRcbiAqICAgQ3R4LS0+PkM6IHJlcXVlc3RlZCB2YWx1ZVxuICovXG5leHBvcnQgY2xhc3MgQ29udGV4dDxGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzPiB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcImNhY2hlXCIsIHtcbiAgICAgIHZhbHVlOiBuZXcgT2JqZWN0QWNjdW11bGF0b3I8Rj4oKSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3RhdGljIGZhY3Rvcnk6IENvbnRleHRGYWN0b3J5PGFueT4gPSBEZWZhdWx0Q29udGV4dEZhY3Rvcnk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjYWNoZTogRiAmIE9iamVjdEFjY3VtdWxhdG9yPEY+ID1cbiAgICBuZXcgT2JqZWN0QWNjdW11bGF0b3IoKSBhcyBGICYgT2JqZWN0QWNjdW11bGF0b3I8Rj47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBBY2N1bXVsYXRlcyBuZXcgdmFsdWVzIGludG8gdGhlIGNvbnRleHQuXG4gICAqIEBzdW1tYXJ5IE1lcmdlcyB0aGUgcHJvdmlkZWQgdmFsdWUgb2JqZWN0IHdpdGggdGhlIGV4aXN0aW5nIGNvbnRleHQgc3RhdGUsXG4gICAqIGNyZWF0aW5nIGEgbmV3IGltbXV0YWJsZSBjYWNoZSBzdGF0ZS5cbiAgICpcbiAgICogQHRlbXBsYXRlIEYgLSBjdXJyZW50IGFjY3VtdWxhdG9yIHR5cGVcbiAgICogQHRlbXBsYXRlIFYgLSBUeXBlIGV4dGVuZGluZyBvYmplY3QgZm9yIHRoZSB2YWx1ZXMgdG8gYWNjdW11bGF0ZVxuICAgKiBAcGFyYW0ge1Z9IHZhbHVlIC0gVGhlIG9iamVjdCBjb250YWluaW5nIHZhbHVlcyB0byBhY2N1bXVsYXRlXG4gICAqIEByZXR1cm5zIEEgbmV3IGNvbnRleHQgaW5zdGFuY2Ugd2l0aCBhY2N1bXVsYXRlZCB2YWx1ZXNcbiAgICovXG4gIGFjY3VtdWxhdGU8ViBleHRlbmRzIG9iamVjdD4odmFsdWU6IFYpIHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgXCJjYWNoZVwiLCB7XG4gICAgICB2YWx1ZTogdGhpcy5jYWNoZS5hY2N1bXVsYXRlKHZhbHVlKSxcbiAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzIGFzIHVua25vd24gYXMgQ29udGV4dDxGICYgVj47XG4gIH1cblxuICBnZXQgdGltZXN0YW1wKCkge1xuICAgIHJldHVybiB0aGlzLmNhY2hlLnRpbWVzdGFtcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgdmFsdWUgZnJvbSB0aGUgY29udGV4dCBieSBrZXkuXG4gICAqIEBzdW1tYXJ5IEF0dGVtcHRzIHRvIGdldCBhIHZhbHVlIGZyb20gdGhlIGN1cnJlbnQgY29udGV4dCdzIGNhY2hlLlxuICAgKiBJZiBub3QgZm91bmQsIHRyYXZlcnNlcyB1cCB0aGUgcGFyZW50IGNvbnRleHQgY2hhaW4uXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBLIC0gVHlwZSBleHRlbmRpbmcga2V5b2YgRiBmb3IgdGhlIGtleSB0byByZXRyaWV2ZVxuICAgKiBAdGVtcGxhdGUgRiAtIEFjY3VtdWxhdG9yIHR5cGVcbiAgICogQHBhcmFtIHtLfSBrZXkgLSBUaGUga2V5IHRvIHJldHJpZXZlIGZyb20gdGhlIGNvbnRleHRcbiAgICogQHJldHVybnMgVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUga2V5XG4gICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUga2V5IGlzIG5vdCBmb3VuZCBpbiB0aGUgY29udGV4dCBjaGFpblxuICAgKi9cbiAgZ2V0PEsgZXh0ZW5kcyBrZXlvZiBGPihrZXk6IEspOiBGW0tdIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KGtleSk7XG4gICAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgICAgaWYgKHRoaXMuY2FjaGUucGFyZW50Q29udGV4dCkgcmV0dXJuIHRoaXMuY2FjaGUucGFyZW50Q29udGV4dC5nZXQoa2V5KTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgY2hpbGQgY29udGV4dFxuICAgKiBAc3VtbWFyeSBHZW5lcmF0ZXMgYSBuZXcgY29udGV4dCBpbnN0YW5jZSB3aXRoIGN1cnJlbnQgY29udGV4dCBhcyBwYXJlbnRcbiAgICpcbiAgICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXN9IG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb24gdHlwZVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBbbW9kZWxdIC0gT3B0aW9uYWwgbW9kZWwgY29uc3RydWN0b3JcbiAgICogQHJldHVybnMge0N9IE5ldyBjaGlsZCBjb250ZXh0IGluc3RhbmNlXG4gICAqL1xuICBjaGlsZDxNIGV4dGVuZHMgTW9kZWwsIEMgZXh0ZW5kcyBDb250ZXh0PEY+PihcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbktleXMsXG4gICAgbW9kZWw/OiBDb25zdHJ1Y3RvcjxNPlxuICApOiBDIHtcbiAgICByZXR1cm4gQ29udGV4dC5jaGlsZEZyb208RiwgQz4oXG4gICAgICB0aGlzIGFzIHVua25vd24gYXMgQyxcbiAgICAgIHtcbiAgICAgICAgb3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgIGFmZmVjdGVkVGFibGVzOiBtb2RlbCA/IFttb2RlbF0gOiBbXSxcbiAgICAgIH0gYXMgdW5rbm93biBhcyBQYXJ0aWFsPEY+XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGNoaWxkIGNvbnRleHQgZnJvbSBhbm90aGVyIGNvbnRleHRcbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIGEgbmV3IGNvbnRleHQgaW5zdGFuY2Ugd2l0aCBwYXJlbnQgcmVmZXJlbmNlXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcgUmVwb3NpdG9yeSBGbGFnc1xuICAgKiBAdGVtcGxhdGUgQyAtIFR5cGUgZXh0ZW5kaW5nIENvbnRleHQ8Rj5cbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIHBhcmVudCBjb250ZXh0XG4gICAqIEBwYXJhbSB7UGFydGlhbDxGPn0gW292ZXJyaWRlc10gLSBPcHRpb25hbCBmbGFnIG92ZXJyaWRlc1xuICAgKiBAcmV0dXJucyB7Q30gTmV3IGNoaWxkIGNvbnRleHQgaW5zdGFuY2VcbiAgICovXG4gIHN0YXRpYyBjaGlsZEZyb208RiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncywgQyBleHRlbmRzIENvbnRleHQ8Rj4+KFxuICAgIGNvbnRleHQ6IEMsXG4gICAgb3ZlcnJpZGVzPzogUGFydGlhbDxGPlxuICApOiBDIHtcbiAgICByZXR1cm4gQ29udGV4dC5mYWN0b3J5KFxuICAgICAgT2JqZWN0LmFzc2lnbih7fSwgY29udGV4dC5jYWNoZSwgb3ZlcnJpZGVzIHx8IHt9KVxuICAgICkgYXMgdW5rbm93biBhcyBDO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IGNvbnRleHQgZnJvbSBvcGVyYXRpb24gcGFyYW1ldGVyc1xuICAgKiBAc3VtbWFyeSBHZW5lcmF0ZXMgYSBjb250ZXh0IGluc3RhbmNlIGZvciBzcGVjaWZpYyBvcGVyYXRpb25cbiAgICpcbiAgICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBSZXBvc2l0b3J5IEZsYWdzXG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAgICogQHBhcmFtIHtPcGVyYXRpb25LZXlzLkRFTEVURX0gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbiB0eXBlXG4gICAqIEBwYXJhbSB7UGFydGlhbDxGPn0gb3ZlcnJpZGVzIC0gRmxhZyBvdmVycmlkZXNcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHthbnl9IGFyZ3MgLSBPcGVyYXRpb24gYXJndW1lbnRzXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEM+fSBQcm9taXNlIHJlc29sdmluZyB0byBuZXcgY29udGV4dFxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGZyb208XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gICAgQyBleHRlbmRzIENvbnRleHQ8Rj4sXG4gID4oXG4gICAgb3BlcmF0aW9uOlxuICAgICAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLlJFQURcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgb3ZlcnJpZGVzOiBQYXJ0aWFsPEY+LFxuICAgIG1vZGVsOiBDb25zdHJ1Y3RvcjxNPixcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgLi4uYXJnczogYW55W11cbiAgKTogUHJvbWlzZTxDPiB7XG4gICAgcmV0dXJuIENvbnRleHQuZmFjdG9yeShcbiAgICAgIE9iamVjdC5hc3NpZ24oe30sIERlZmF1bHRSZXBvc2l0b3J5RmxhZ3MsIG92ZXJyaWRlcywge1xuICAgICAgICBvcGVyYXRpb246IG9wZXJhdGlvbixcbiAgICAgICAgbW9kZWw6IG1vZGVsLFxuICAgICAgfSlcbiAgICApIGFzIEM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGFyZ3VtZW50cyBmb3IgY29udGV4dCBvcGVyYXRpb25zXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBjb250ZXh0IGFyZ3Mgb2JqZWN0IHdpdGggdGhlIHNwZWNpZmllZCBvcGVyYXRpb24gcGFyYW1ldGVyc1xuICAgKlxuICAgKiBAdGVtcGxhdGUgRiAtIFR5cGUgZXh0ZW5kaW5nIHtAbGluayBSZXBvc2l0b3J5RmxhZ3N9XG4gICAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcge0BsaW5rIE1vZGVsfVxuICAgKiBAcGFyYW0ge09wZXJhdGlvbktleXMuREVMRVRFfSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIHR5cGVcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gbW9kZWwgLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIE9wZXJhdGlvbiBhcmd1bWVudHNcbiAgICogQHBhcmFtIHtDb250ZXh0dWFsPEY+fSBbY29udGV4dHVhbF0gLSBPcHRpb25hbCBjb250ZXh0dWFsIG9iamVjdFxuICAgKiBAcGFyYW0ge1BhcnRpYWw8Rj59IFtvdmVycmlkZXNdIC0gT3B0aW9uYWwgZmxhZyBvdmVycmlkZXNcbiAgICogQHJldHVybnMge1Byb21pc2U8Q29udGV4dEFyZ3M+fSBQcm9taXNlIHJlc29sdmluZyB0byBjb250ZXh0IGFyZ3VtZW50c1xuICAgKlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDIGFzIENvbnRleHRcbiAgICogICBwYXJ0aWNpcGFudCBNIGFzIE1vZGVsXG4gICAqICAgcGFydGljaXBhbnQgQSBhcyBBcmdzXG4gICAqXG4gICAqICAgQy0+PkM6IFJlY2VpdmUgb3BlcmF0aW9uIHJlcXVlc3RcbiAgICogICBDLT4+TTogVmFsaWRhdGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICogICBDLT4+QzogQ3JlYXRlIGNoaWxkIGNvbnRleHRcbiAgICogICBDLT4+QTogUHJvY2VzcyBvcGVyYXRpb24gYXJnc1xuICAgKiAgIEEtPj5DOiBSZXR1cm4gY29udGV4dCBhcmdzXG4gICAqICAgQy0+PkM6IEFwcGx5IG92ZXJyaWRlc1xuICAgKiAgIEMtPj5DOiBSZXR1cm4gZmluYWwgY29udGV4dFxuICAgKi9cbiAgc3RhdGljIGFzeW5jIGFyZ3M8XG4gICAgTSBleHRlbmRzIE1vZGVsLFxuICAgIEMgZXh0ZW5kcyBDb250ZXh0PEY+LFxuICAgIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MsXG4gID4oXG4gICAgb3BlcmF0aW9uOlxuICAgICAgfCBPcGVyYXRpb25LZXlzLkNSRUFURVxuICAgICAgfCBPcGVyYXRpb25LZXlzLlJFQURcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5VUERBVEVcbiAgICAgIHwgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgbW9kZWw6IENvbnN0cnVjdG9yPE0+LFxuICAgIGFyZ3M6IGFueVtdLFxuICAgIGNvbnRleHR1YWw/OiBDb250ZXh0dWFsPEY+LFxuICAgIG92ZXJyaWRlcz86IFBhcnRpYWw8Rj5cbiAgKTogUHJvbWlzZTxDb250ZXh0QXJnczxGLCBDPj4ge1xuICAgIGNvbnN0IGxhc3QgPSBhcmdzLnBvcCgpO1xuXG4gICAgYXN5bmMgZnVuY3Rpb24gZ2V0Q29udGV4dCgpIHtcbiAgICAgIGlmIChjb250ZXh0dWFsKVxuICAgICAgICByZXR1cm4gY29udGV4dHVhbC5jb250ZXh0KG9wZXJhdGlvbiwgb3ZlcnJpZGVzIHx8IHt9LCBtb2RlbCwgLi4uYXJncyk7XG4gICAgICByZXR1cm4gQ29udGV4dC5mcm9tKG9wZXJhdGlvbiwgb3ZlcnJpZGVzIHx8IHt9LCBtb2RlbCwgLi4uYXJncyk7XG4gICAgfVxuXG4gICAgbGV0IGM6IEM7XG4gICAgaWYgKGxhc3QpIHtcbiAgICAgIGlmIChsYXN0IGluc3RhbmNlb2YgQ29udGV4dCkge1xuICAgICAgICBjID0gbGFzdCBhcyBDO1xuICAgICAgICBhcmdzLnB1c2gobGFzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjID0gKGF3YWl0IGdldENvbnRleHQoKSkgYXMgQztcbiAgICAgICAgYXJncy5wdXNoKGxhc3QsIGMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjID0gKGF3YWl0IGdldENvbnRleHQoKSkgYXMgQztcbiAgICAgIGFyZ3MucHVzaChjKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBjb250ZXh0OiBjLCBhcmdzOiBhcmdzIH07XG4gIH1cbn1cbiIsImltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi9Db250ZXh0XCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgVXRpbCBtZXRob2QgdG8gY2hhbmdlIGEgbWV0aG9kIG9mIGFuIG9iamVjdCBwcmVmaXhpbmcgaXQgd2l0aCBhbm90aGVyXG4gKiBAcGFyYW0ge2FueX0gb2JqIFRoZSBCYXNlIE9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gYWZ0ZXIgVGhlIG9yaWdpbmFsIG1ldGhvZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gcHJlZml4IFRoZSBQcmVmaXggbWV0aG9kLiBUaGUgb3V0cHV0IHdpbGwgYmUgdXNlZCBhcyBhcmd1bWVudHMgaW4gdGhlIG9yaWdpbmFsIG1ldGhvZFxuICogQHBhcmFtIHtzdHJpbmd9IFthZnRlck5hbWVdIFdoZW4gdGhlIGFmdGVyIGZ1bmN0aW9uIGFubWUgY2Fubm90IGJlIGV4dHJhY3RlZCwgcGFzcyBpdCBoZXJlXG4gKlxuICogQGZ1bmN0aW9uIHByZWZpeE1ldGhvZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlZml4TWV0aG9kKFxuICBvYmo6IGFueSxcbiAgYWZ0ZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBwcmVmaXg6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBhZnRlck5hbWU/OiBzdHJpbmdcbikge1xuICBhc3luYyBmdW5jdGlvbiB3cmFwcGVyKHRoaXM6IGFueSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKHByZWZpeC5jYWxsKHRoaXMsIC4uLmFyZ3MpKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGFmdGVyLmFwcGx5KHRoaXMsIHJlc3VsdHMpKTtcbiAgfVxuICBjb25zdCB3cmFwcGVkID0gd3JhcHBlci5iaW5kKG9iaik7XG4gIGNvbnN0IG5hbWUgPSBhZnRlck5hbWUgPyBhZnRlck5hbWUgOiBhZnRlci5uYW1lO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkod3JhcHBlZCwgXCJuYW1lXCIsIHtcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IG5hbWUsXG4gIH0pO1xuICBvYmpbbmFtZV0gPSB3cmFwcGVkO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgbWV0aG9kIHRvIGNoYW5nZSBhIG1ldGhvZCBvZiBhbiBvYmplY3Qgc3VmZml4aW5nIGl0IHdpdGggYW5vdGhlclxuICogQHBhcmFtIHthbnl9IG9iaiBUaGUgQmFzZSBPYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGJlZm9yZSBUaGUgb3JpZ2luYWwgbWV0aG9kXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBzdWZmaXggVGhlIFByZWZpeCBtZXRob2QuIFRoZSBvdXRwdXQgd2lsbCBiZSB1c2VkIGFzIGFyZ3VtZW50cyBpbiB0aGUgb3JpZ2luYWwgbWV0aG9kXG4gKiBAcGFyYW0ge3N0cmluZ30gW2JlZm9yZU5hbWVdIFdoZW4gdGhlIGFmdGVyIGZ1bmN0aW9uIGFubWUgY2Fubm90IGJlIGV4dHJhY3RlZCwgcGFzcyBpdCBoZXJlXG4gKlxuICogQGZ1bmN0aW9uIHN1ZmZpeE1ldGhvZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9ycy5SZXBvc2l0b3J5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdWZmaXhNZXRob2QoXG4gIG9iajogYW55LFxuICBiZWZvcmU6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBzdWZmaXg6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBiZWZvcmVOYW1lPzogc3RyaW5nXG4pIHtcbiAgYXN5bmMgZnVuY3Rpb24gd3JhcHBlcih0aGlzOiBhbnksIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UucmVzb2x2ZShiZWZvcmUuY2FsbCh0aGlzLCAuLi5hcmdzKSk7XG4gICAgcmV0dXJuIHN1ZmZpeC5jYWxsKHRoaXMsIC4uLnJlc3VsdHMpO1xuICB9XG4gIGNvbnN0IHdyYXBwZWQgPSB3cmFwcGVyLmJpbmQob2JqKTtcbiAgY29uc3QgbmFtZSA9IGJlZm9yZU5hbWUgPyBiZWZvcmVOYW1lIDogYmVmb3JlLm5hbWU7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh3cmFwcGVkLCBcIm5hbWVcIiwge1xuICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICB2YWx1ZTogbmFtZSxcbiAgfSk7XG4gIG9ialtuYW1lXSA9IHdyYXBwZWQ7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgVXRpbCBtZXRob2QgdG8gd3JhcCBhIG1ldGhvZCBvZiBhbiBvYmplY3Qgd2l0aCBhZGRpdGlvbmFsIGxvZ2ljXG4gKlxuICogQHBhcmFtIHthbnl9IG9iaiBUaGUgQmFzZSBPYmplY3RcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGJlZm9yZSB0aGUgbWV0aG9kIHRvIGJlIHByZWZpeGVkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgdGhlIG1ldGhvZCB0byBiZSB3cmFwcGVkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBhZnRlciBUaGUgbWV0aG9kIHRvIGJlIHN1ZmZpeGVkXG4gKiBAcGFyYW0ge3N0cmluZ30gW21ldGhvZE5hbWVdIFdoZW4gdGhlIGFmdGVyIGZ1bmN0aW9uIGFubWUgY2Fubm90IGJlIGV4dHJhY3RlZCwgcGFzcyBpdCBoZXJlXG4gKlxuICogQGZ1bmN0aW9uIHdyYXBNZXRob2RXaXRoQ29udGV4dFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gd3JhcE1ldGhvZFdpdGhDb250ZXh0KFxuICBvYmo6IGFueSxcbiAgYmVmb3JlOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgbWV0aG9kOiAoLi4uYXJnczogYW55W10pID0+IGFueSxcbiAgYWZ0ZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gYW55LFxuICBtZXRob2ROYW1lPzogc3RyaW5nXG4pIHtcbiAgY29uc3QgbmFtZSA9IG1ldGhvZE5hbWUgPyBtZXRob2ROYW1lIDogbWV0aG9kLm5hbWU7XG4gIG9ialtuYW1lXSA9IG5ldyBQcm94eShvYmpbbmFtZV0sIHtcbiAgICBhcHBseTogYXN5bmMgKHRhcmdldCwgdGhpc0FyZywgYXJnQXJyYXkpID0+IHtcbiAgICAgIGxldCB0cmFuc2Zvcm1lZEFyZ3MgPSBiZWZvcmUuY2FsbCh0aGlzQXJnLCAuLi5hcmdBcnJheSk7XG4gICAgICBpZiAodHJhbnNmb3JtZWRBcmdzIGluc3RhbmNlb2YgUHJvbWlzZSlcbiAgICAgICAgdHJhbnNmb3JtZWRBcmdzID0gYXdhaXQgdHJhbnNmb3JtZWRBcmdzO1xuICAgICAgY29uc3QgY29udGV4dCA9IHRyYW5zZm9ybWVkQXJnc1t0cmFuc2Zvcm1lZEFyZ3MubGVuZ3RoIC0gMV0gYXMgYW55O1xuICAgICAgaWYgKCEoY29udGV4dCBpbnN0YW5jZW9mIENvbnRleHQpKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk1pc3NpbmcgYSBjb250ZXh0XCIpO1xuICAgICAgbGV0IHJlc3VsdHMgPSBhd2FpdCB0YXJnZXQuY2FsbCh0aGlzQXJnLCAuLi50cmFuc2Zvcm1lZEFyZ3MpO1xuICAgICAgaWYgKHJlc3VsdHMgaW5zdGFuY2VvZiBQcm9taXNlKSByZXN1bHRzID0gYXdhaXQgcmVzdWx0cztcbiAgICAgIHJlc3VsdHMgPSBhZnRlci5jYWxsKHRoaXNBcmcsIHJlc3VsdHMsIGNvbnRleHQpO1xuICAgICAgaWYgKHJlc3VsdHMgaW5zdGFuY2VvZiBQcm9taXNlKSByZXN1bHRzID0gYXdhaXQgcmVzdWx0cztcbiAgICAgIHJldHVybiByZXN1bHRzO1xuICAgIH0sXG4gIH0pO1xufVxuIiwiaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4uL21vZGVsL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdXRpbHNcIjtcbmltcG9ydCB7IE1vZGVsLCBNb2RlbEtleXMsIHNmIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L2Vycm9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBGaW5kcyB0aGUgcHJpbWFyeSBrZXkgYXR0cmlidXRlIGZvciBhIG1vZGVsXG4gKiBAc3VtbWFyeSBTZWFyY2hlcyBpbiBhbGwgdGhlIHByb3BlcnRpZXMgaW4gdGhlIG9iamVjdCBmb3IgYW4ge0BsaW5rIGlkfSBkZWNvcmF0ZWQgcHJvcGVydHkgYW5kIHJldHVybnMgdGhlIHByb3BlcnR5IGtleSBhbmQgbWV0YWRhdGFcbiAqIEBwYXJhbSB7TW9kZWx9IG1vZGVsIC0gVGhlIG1vZGVsIG9iamVjdCB0byBzZWFyY2ggZm9yIHByaW1hcnkga2V5XG4gKiBAcmV0dXJuIHtPYmplY3R9IEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBpZCBwcm9wZXJ0eSBuYW1lIGFuZCBpdHMgbWV0YWRhdGFcbiAqIEBmdW5jdGlvbiBmaW5kUHJpbWFyeUtleVxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgZmluZFByaW1hcnlLZXlcbiAqICAgcGFydGljaXBhbnQgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlXG4gKlxuICogICBDYWxsZXItPj5maW5kUHJpbWFyeUtleTogbW9kZWxcbiAqICAgZmluZFByaW1hcnlLZXktPj5nZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmU6IGdldCBkZWNvcmF0b3JzXG4gKiAgIGdldEFsbFByb3BlcnR5RGVjb3JhdG9yc1JlY3Vyc2l2ZS0tPj5maW5kUHJpbWFyeUtleTogZGVjb3JhdG9yc1xuICogICBmaW5kUHJpbWFyeUtleS0+PmZpbmRQcmltYXJ5S2V5OiBmaWx0ZXIgSUQgZGVjb3JhdG9yc1xuICogICBmaW5kUHJpbWFyeUtleS0+PmZpbmRQcmltYXJ5S2V5OiB2YWxpZGF0ZSBzaW5nbGUgSUQgcHJvcGVydHlcbiAqICAgZmluZFByaW1hcnlLZXktLT4+Q2FsbGVyOiB7aWQsIHByb3BzfVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUHJpbWFyeUtleTxNIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBNKSB7XG4gIGNvbnN0IGRlY29yYXRvcnMgPSBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUoXG4gICAgbW9kZWwsXG4gICAgdW5kZWZpbmVkLFxuICAgIERCS2V5cy5SRUZMRUNUICsgREJLZXlzLklEXG4gICk7XG4gIGNvbnN0IGlkRGVjb3JhdG9ycyA9IE9iamVjdC5lbnRyaWVzKGRlY29yYXRvcnMgYXMgb2JqZWN0KS5yZWR1Y2UoXG4gICAgKGFjY3VtOiB7IFtpbmRleGVyOiBzdHJpbmddOiBhbnlbXSB9LCBbcHJvcCwgZGVjc10pID0+IHtcbiAgICAgIGNvbnN0IGZpbHRlcmVkID0gKGRlY3MgYXMgeyBrZXk6IHN0cmluZyB9W10pLmZpbHRlcihcbiAgICAgICAgKGQpID0+IGQua2V5ICE9PSBNb2RlbEtleXMuVFlQRVxuICAgICAgKTtcbiAgICAgIGlmIChmaWx0ZXJlZCAmJiBmaWx0ZXJlZC5sZW5ndGgpIHtcbiAgICAgICAgYWNjdW1bcHJvcF0gPSBhY2N1bVtwcm9wXSB8fCBbXTtcbiAgICAgICAgYWNjdW1bcHJvcF0ucHVzaCguLi5maWx0ZXJlZCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYWNjdW07XG4gICAgfSxcbiAgICB7fVxuICApO1xuXG4gIGlmICghaWREZWNvcmF0b3JzIHx8ICFPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmxlbmd0aClcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIkNvdWxkIG5vdCBmaW5kIElEIGRlY29yYXRlZCBQcm9wZXJ0eVwiKTtcbiAgaWYgKE9iamVjdC5rZXlzKGlkRGVjb3JhdG9ycykubGVuZ3RoID4gMSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihzZihPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpLmpvaW4oXCIsIFwiKSkpO1xuICBjb25zdCBpZFByb3AgPSBPYmplY3Qua2V5cyhpZERlY29yYXRvcnMpWzBdO1xuICBpZiAoIWlkUHJvcCkgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJDb3VsZCBub3QgZmluZCBJRCBkZWNvcmF0ZWQgUHJvcGVydHlcIik7XG4gIHJldHVybiB7XG4gICAgaWQ6IGlkUHJvcCBhcyBrZXlvZiBNLFxuICAgIHByb3BzOiBpZERlY29yYXRvcnNbaWRQcm9wXVswXS5wcm9wcyxcbiAgfTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIHRoZSBwcmltYXJ5IGtleSB2YWx1ZSBmcm9tIGEgbW9kZWxcbiAqIEBzdW1tYXJ5IFNlYXJjaGVzIGZvciB0aGUgSUQtZGVjb3JhdGVkIHByb3BlcnR5IGluIHRoZSBtb2RlbCBhbmQgcmV0dXJucyBpdHMgdmFsdWVcbiAqIEBwYXJhbSB7TW9kZWx9IG1vZGVsIC0gVGhlIG1vZGVsIG9iamVjdCB0byBleHRyYWN0IHRoZSBJRCBmcm9tXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXR1cm5FbXB0eT1mYWxzZV0gLSBXaGV0aGVyIHRvIHJldHVybiB1bmRlZmluZWQgaWYgbm8gSUQgdmFsdWUgaXMgZm91bmRcbiAqIEByZXR1cm4ge3N0cmluZyB8IG51bWJlciB8IGJpZ2ludH0gVGhlIHByaW1hcnkga2V5IHZhbHVlXG4gKiBAZnVuY3Rpb24gZmluZE1vZGVsSWRcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IGZpbmRNb2RlbElkXG4gKiAgIHBhcnRpY2lwYW50IGZpbmRQcmltYXJ5S2V5XG4gKlxuICogICBDYWxsZXItPj5maW5kTW9kZWxJZDogbW9kZWwsIHJldHVybkVtcHR5XG4gKiAgIGZpbmRNb2RlbElkLT4+ZmluZFByaW1hcnlLZXk6IG1vZGVsXG4gKiAgIGZpbmRQcmltYXJ5S2V5LS0+PmZpbmRNb2RlbElkOiB7aWQsIHByb3BzfVxuICogICBmaW5kTW9kZWxJZC0+PmZpbmRNb2RlbElkOiBleHRyYWN0IG1vZGVsW2lkXVxuICogICBmaW5kTW9kZWxJZC0+PmZpbmRNb2RlbElkOiB2YWxpZGF0ZSBJRCBleGlzdHMgaWYgcmVxdWlyZWRcbiAqICAgZmluZE1vZGVsSWQtLT4+Q2FsbGVyOiBJRCB2YWx1ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kTW9kZWxJZDxNIGV4dGVuZHMgTW9kZWw+KFxuICBtb2RlbDogTSxcbiAgcmV0dXJuRW1wdHkgPSBmYWxzZVxuKTogc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50IHtcbiAgY29uc3QgaWRQcm9wID0gZmluZFByaW1hcnlLZXkobW9kZWwpLmlkO1xuICBjb25zdCBtb2RlbElkID0gbW9kZWxbaWRQcm9wXTtcbiAgaWYgKHR5cGVvZiBtb2RlbElkID09PSBcInVuZGVmaW5lZFwiICYmICFyZXR1cm5FbXB0eSlcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7aWRQcm9wIGFzIHN0cmluZ31gXG4gICAgKTtcbiAgcmV0dXJuIG1vZGVsSWQgYXMgc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50O1xufVxuIiwiaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgZW5mb3JjZURCRGVjb3JhdG9ycyB9IGZyb20gXCIuL3V0aWxzXCI7XG5pbXBvcnQgeyBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyB3cmFwTWV0aG9kV2l0aENvbnRleHQgfSBmcm9tIFwiLi93cmFwcGVyc1wiO1xuaW1wb3J0IHsgZmluZFByaW1hcnlLZXkgfSBmcm9tIFwiLi4vaWRlbnRpdHkvdXRpbHNcIjtcbmltcG9ydCB7IENvbnRleHQgfSBmcm9tIFwiLi9Db250ZXh0XCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5RmxhZ3MgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIHJlcG9zaXRvcnkgaW1wbGVtZW50YXRpb24gcHJvdmlkaW5nIENSVUQgb3BlcmF0aW9ucyBmb3IgbW9kZWxzLlxuICogQHN1bW1hcnkgVGhlIEJhc2VSZXBvc2l0b3J5IGNsYXNzIHNlcnZlcyBhcyBhIGZvdW5kYXRpb24gZm9yIHJlcG9zaXRvcnkgaW1wbGVtZW50YXRpb25zLCBwcm92aWRpbmdcbiAqIGFic3RyYWN0IGFuZCBjb25jcmV0ZSBtZXRob2RzIGZvciBjcmVhdGluZywgcmVhZGluZywgdXBkYXRpbmcsIGFuZCBkZWxldGluZyBtb2RlbCBpbnN0YW5jZXMuXG4gKiBJdCBoYW5kbGVzIG9wZXJhdGlvbiBsaWZlY3ljbGVzIGluY2x1ZGluZyBwcmVmaXggYW5kIHN1ZmZpeCBvcGVyYXRpb25zLCBhbmQgZW5mb3JjZXMgZGVjb3JhdG9ycy5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGUsIGRlZmF1bHRzIHRvIFJlcG9zaXRvcnlGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlLCBkZWZhdWx0cyB0byBDb250ZXh0PEY+XG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzXG4gKiBAY2xhc3MgQmFzZVJlcG9zaXRvcnlcbiAqIEBleGFtcGxlXG4gKiBjbGFzcyBVc2VyTW9kZWwgZXh0ZW5kcyBNb2RlbCB7XG4gKiAgIEBpZCgpXG4gKiAgIGlkOiBzdHJpbmc7XG4gKlxuICogICBAcmVxdWlyZWQoKVxuICogICBuYW1lOiBzdHJpbmc7XG4gKiB9XG4gKlxuICogY2xhc3MgVXNlclJlcG9zaXRvcnkgZXh0ZW5kcyBCYXNlUmVwb3NpdG9yeTxVc2VyTW9kZWw+IHtcbiAqICAgY29uc3RydWN0b3IoKSB7XG4gKiAgICAgc3VwZXIoVXNlck1vZGVsKTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgY3JlYXRlKG1vZGVsOiBVc2VyTW9kZWwpOiBQcm9taXNlPFVzZXJNb2RlbD4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uXG4gKiAgICAgcmV0dXJuIG1vZGVsO1xuICogICB9XG4gKlxuICogICBhc3luYyByZWFkKGtleTogc3RyaW5nKTogUHJvbWlzZTxVc2VyTW9kZWw+IHtcbiAqICAgICAvLyBJbXBsZW1lbnRhdGlvblxuICogICAgIHJldHVybiBuZXcgVXNlck1vZGVsKHsgaWQ6IGtleSwgbmFtZTogJ1VzZXInIH0pO1xuICogICB9XG4gKlxuICogICBhc3luYyB1cGRhdGUobW9kZWw6IFVzZXJNb2RlbCk6IFByb21pc2U8VXNlck1vZGVsPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb25cbiAqICAgICByZXR1cm4gbW9kZWw7XG4gKiAgIH1cbiAqXG4gKiAgIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZyk6IFByb21pc2U8VXNlck1vZGVsPiB7XG4gKiAgICAgLy8gSW1wbGVtZW50YXRpb25cbiAqICAgICBjb25zdCBtb2RlbCA9IGF3YWl0IHRoaXMucmVhZChrZXkpO1xuICogICAgIHJldHVybiBtb2RlbDtcbiAqICAgfVxuICogfVxuICpcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQyBhcyBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgUiBhcyBSZXBvc2l0b3J5XG4gKiAgIHBhcnRpY2lwYW50IFAgYXMgUHJlZml4IE1ldGhvZHNcbiAqICAgcGFydGljaXBhbnQgRCBhcyBEYXRhYmFzZVxuICogICBwYXJ0aWNpcGFudCBTIGFzIFN1ZmZpeCBNZXRob2RzXG4gKiAgIHBhcnRpY2lwYW50IFYgYXMgVmFsaWRhdG9ycy9EZWNvcmF0b3JzXG4gKlxuICogICBOb3RlIG92ZXIgQyxWOiBDcmVhdGUgT3BlcmF0aW9uXG4gKiAgIEMtPj5SOiBjcmVhdGUobW9kZWwpXG4gKiAgIFItPj5QOiBjcmVhdGVQcmVmaXgobW9kZWwpXG4gKiAgIFAtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKE9OKVxuICogICBQLT4+RDogRGF0YWJhc2Ugb3BlcmF0aW9uXG4gKiAgIEQtPj5TOiBjcmVhdGVTdWZmaXgobW9kZWwpXG4gKiAgIFMtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKEFGVEVSKVxuICogICBTLT4+QzogUmV0dXJuIG1vZGVsXG4gKlxuICogICBOb3RlIG92ZXIgQyxWOiBSZWFkIE9wZXJhdGlvblxuICogICBDLT4+UjogcmVhZChrZXkpXG4gKiAgIFItPj5QOiByZWFkUHJlZml4KGtleSlcbiAqICAgUC0+PlY6IGVuZm9yY2VEQkRlY29yYXRvcnMoT04pXG4gKiAgIFAtPj5EOiBEYXRhYmFzZSBvcGVyYXRpb25cbiAqICAgRC0+PlM6IHJlYWRTdWZmaXgobW9kZWwpXG4gKiAgIFMtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKEFGVEVSKVxuICogICBTLT4+QzogUmV0dXJuIG1vZGVsXG4gKlxuICogICBOb3RlIG92ZXIgQyxWOiBVcGRhdGUgT3BlcmF0aW9uXG4gKiAgIEMtPj5SOiB1cGRhdGUobW9kZWwpXG4gKiAgIFItPj5QOiB1cGRhdGVQcmVmaXgobW9kZWwpXG4gKiAgIFAtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKE9OKVxuICogICBQLT4+RDogRGF0YWJhc2Ugb3BlcmF0aW9uXG4gKiAgIEQtPj5TOiB1cGRhdGVTdWZmaXgobW9kZWwpXG4gKiAgIFMtPj5WOiBlbmZvcmNlREJEZWNvcmF0b3JzKEFGVEVSKVxuICogICBTLT4+QzogUmV0dXJuIG1vZGVsXG4gKlxuICogICBOb3RlIG92ZXIgQyxWOiBEZWxldGUgT3BlcmF0aW9uXG4gKiAgIEMtPj5SOiBkZWxldGUoa2V5KVxuICogICBSLT4+UDogZGVsZXRlUHJlZml4KGtleSlcbiAqICAgUC0+PlY6IGVuZm9yY2VEQkRlY29yYXRvcnMoT04pXG4gKiAgIFAtPj5EOiBEYXRhYmFzZSBvcGVyYXRpb25cbiAqICAgRC0+PlM6IGRlbGV0ZVN1ZmZpeChtb2RlbClcbiAqICAgUy0+PlY6IGVuZm9yY2VEQkRlY29yYXRvcnMoQUZURVIpXG4gKiAgIFMtPj5DOiBSZXR1cm4gbW9kZWxcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VSZXBvc2l0b3J5PFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4gaW1wbGVtZW50cyBJUmVwb3NpdG9yeTxNLCBGLCBDPlxue1xuICBwcml2YXRlIHJlYWRvbmx5IF9jbGFzcyE6IENvbnN0cnVjdG9yPE0+O1xuICBwcml2YXRlIF9wayE6IGtleW9mIE07XG4gIHByaXZhdGUgX3BrUHJvcHMhOiBhbnk7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSBtb2RlbCBjbGFzcyBjb25zdHJ1Y3Rvci5cbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBjb25zdHJ1Y3RvciBmb3IgdGhlIG1vZGVsIGNsYXNzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHJlcG9zaXRvcnkuXG4gICAqIFRocm93cyBhbiBlcnJvciBpZiBubyBjbGFzcyBkZWZpbml0aW9uIGlzIGZvdW5kLlxuICAgKiBAcmV0dXJuIHtDb25zdHJ1Y3RvcjxNPn0gVGhlIGNvbnN0cnVjdG9yIGZvciB0aGUgbW9kZWwgY2xhc3NcbiAgICovXG4gIGdldCBjbGFzcygpIHtcbiAgICBpZiAoIXRoaXMuX2NsYXNzKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYE5vIGNsYXNzIGRlZmluaXRpb24gZm91bmQgZm9yIHRoaXMgcmVwb3NpdG9yeWApO1xuICAgIHJldHVybiB0aGlzLl9jbGFzcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgcHJpbWFyeSBrZXkgcHJvcGVydHkgbmFtZSBvZiB0aGUgbW9kZWwuXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyB0aGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdGhhdCBzZXJ2ZXMgYXMgdGhlIHByaW1hcnkga2V5IGZvciB0aGUgbW9kZWwuXG4gICAqIElmIG5vdCBhbHJlYWR5IGRldGVybWluZWQsIGl0IGZpbmRzIHRoZSBwcmltYXJ5IGtleSB1c2luZyB0aGUgbW9kZWwncyBkZWNvcmF0b3JzLlxuICAgKiBAcmV0dXJuIFRoZSBuYW1lIG9mIHRoZSBwcmltYXJ5IGtleSBwcm9wZXJ0eVxuICAgKi9cbiAgZ2V0IHBrKCk6IGtleW9mIE0ge1xuICAgIGlmICghdGhpcy5fcGspIHtcbiAgICAgIGNvbnN0IHsgaWQsIHByb3BzIH0gPSBmaW5kUHJpbWFyeUtleShuZXcgdGhpcy5jbGFzcygpKTtcbiAgICAgIHRoaXMuX3BrID0gaWQ7XG4gICAgICB0aGlzLl9wa1Byb3BzID0gcHJvcHM7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9waztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgcHJpbWFyeSBrZXkgcHJvcGVydGllcy5cbiAgICogQHN1bW1hcnkgUmV0cmlldmVzIHRoZSBwcm9wZXJ0aWVzIGFzc29jaWF0ZWQgd2l0aCB0aGUgcHJpbWFyeSBrZXkgb2YgdGhlIG1vZGVsLlxuICAgKiBJZiBub3QgYWxyZWFkeSBkZXRlcm1pbmVkLCBpdCB0cmlnZ2VycyB0aGUgcGsgZ2V0dGVyIHRvIGZpbmQgdGhlIHByaW1hcnkga2V5IHByb3BlcnRpZXMuXG4gICAqIEByZXR1cm4ge2FueX0gVGhlIHByb3BlcnRpZXMgb2YgdGhlIHByaW1hcnkga2V5XG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0IHBrUHJvcHMoKTogYW55IHtcbiAgICBpZiAoIXRoaXMuX3BrUHJvcHMpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICAgIGNvbnN0IHBrID0gdGhpcy5waztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3BrUHJvcHM7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IoY2xheno/OiBDb25zdHJ1Y3RvcjxNPikge1xuICAgIGlmIChjbGF6eikgdGhpcy5fY2xhc3MgPSBjbGF6ejtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXRoaXMtYWxpYXNcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBbdGhpcy5jcmVhdGUsIHRoaXMucmVhZCwgdGhpcy51cGRhdGUsIHRoaXMuZGVsZXRlXS5mb3JFYWNoKChtKSA9PiB7XG4gICAgICBjb25zdCBuYW1lID0gbS5uYW1lO1xuICAgICAgd3JhcE1ldGhvZFdpdGhDb250ZXh0KFxuICAgICAgICBzZWxmLFxuICAgICAgICAoc2VsZiBhcyBhbnkpW25hbWUgKyBcIlByZWZpeFwiXSxcbiAgICAgICAgbSxcbiAgICAgICAgKHNlbGYgYXMgYW55KVtuYW1lICsgXCJTdWZmaXhcIl1cbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgbW9kZWwgaW5zdGFuY2UgaW4gdGhlIHJlcG9zaXRvcnkuXG4gICAqIEBzdW1tYXJ5IFBlcnNpc3RzIGEgbmV3IG1vZGVsIGluc3RhbmNlIHRvIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmUuXG4gICAqIFRoaXMgbWV0aG9kIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgY29uY3JldGUgcmVwb3NpdG9yeSBjbGFzc2VzLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIGNyZWF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBjcmVhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBjcmVhdGVkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBhYnN0cmFjdCBjcmVhdGUobW9kZWw6IE0sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgbXVsdGlwbGUgbW9kZWwgaW5zdGFuY2VzIGluIHRoZSByZXBvc2l0b3J5LlxuICAgKiBAc3VtbWFyeSBQZXJzaXN0cyBtdWx0aXBsZSBtb2RlbCBpbnN0YW5jZXMgdG8gdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZSBieSBjYWxsaW5nXG4gICAqIHRoZSBjcmVhdGUgbWV0aG9kIGZvciBlYWNoIG1vZGVsIGluIHRoZSBhcnJheS5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdG8gY3JlYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIGNyZWF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiBjcmVhdGVkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgYXN5bmMgY3JlYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKG1vZGVscy5tYXAoKG0pID0+IHRoaXMuY3JlYXRlKG0sIC4uLmFyZ3MpKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgbW9kZWwgZm9yIGNyZWF0aW9uIGFuZCBleGVjdXRlcyBwcmUtY3JlYXRpb24gb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIGEgbW9kZWwgYmVmb3JlIGl0IGlzIGNyZWF0ZWQgaW4gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogY3JlYXRpbmcgYSBjb250ZXh0LCBpbnN0YW50aWF0aW5nIGEgbmV3IG1vZGVsIGluc3RhbmNlLCBhbmQgZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzXG4gICAqIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYmVmb3JlIGNyZWF0aW9uLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHByZXBhcmUgZm9yIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIGNyZWF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSBwcmVwYXJlZCBtb2RlbCBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBjcmVhdGVQcmVmaXgobW9kZWw6IE0sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBtb2RlbCA9IG5ldyB0aGlzLmNsYXNzKG1vZGVsKTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICk7XG4gICAgcmV0dXJuIFttb2RlbCwgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBhIG1vZGVsIGFmdGVyIGNyZWF0aW9uIGFuZCBleGVjdXRlcyBwb3N0LWNyZWF0aW9uIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEZpbmFsaXplcyBhIG1vZGVsIGFmdGVyIGl0IGhhcyBiZWVuIGNyZWF0ZWQgaW4gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYWZ0ZXIgY3JlYXRpb24uXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdGhhdCB3YXMgY3JlYXRlZFxuICAgKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlU3VmZml4KG1vZGVsOiBNLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICApO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgbXVsdGlwbGUgbW9kZWxzIGZvciBjcmVhdGlvbiBhbmQgZXhlY3V0ZXMgcHJlLWNyZWF0aW9uIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBtdWx0aXBsZSBtb2RlbHMgYmVmb3JlIHRoZXkgYXJlIGNyZWF0ZWQgaW4gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogY3JlYXRpbmcgYSBjb250ZXh0LCBpbnN0YW50aWF0aW5nIG5ldyBtb2RlbCBpbnN0YW5jZXMsIGFuZCBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnNcbiAgICogdGhhdCBzaG91bGQgYmUgYXBwbGllZCBiZWZvcmUgY3JlYXRpb24gZm9yIGVhY2ggbW9kZWwuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRvIHByZXBhcmUgZm9yIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIGNyZWF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiAgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgcHJlcGFyZWQgbW9kZWxzIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGNyZWF0ZUFsbFByZWZpeChtb2RlbHM6IE1bXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcChhc3luYyAobSkgPT4ge1xuICAgICAgICBtID0gbmV3IHRoaXMuY2xhc3MobSk7XG4gICAgICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBtdWx0aXBsZSBtb2RlbHMgYWZ0ZXIgY3JlYXRpb24gYW5kIGV4ZWN1dGVzIHBvc3QtY3JlYXRpb24gb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgRmluYWxpemVzIG11bHRpcGxlIG1vZGVscyBhZnRlciB0aGV5IGhhdmUgYmVlbiBjcmVhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIGNyZWF0aW9uIGZvciBlYWNoIG1vZGVsLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIGFycmF5IG9mIG1vZGVsIGluc3RhbmNlcyB0aGF0IHdlcmUgY3JlYXRlZFxuICAgKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBhcnJheSBvZiBwcm9jZXNzZWQgbW9kZWwgaW5zdGFuY2VzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgY3JlYXRlQWxsU3VmZml4KG1vZGVsczogTVtdLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVscztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgbW9kZWwgaW5zdGFuY2UgZnJvbSB0aGUgcmVwb3NpdG9yeSBieSBpdHMgcHJpbWFyeSBrZXkuXG4gICAqIEBzdW1tYXJ5IEZldGNoZXMgYSBtb2RlbCBpbnN0YW5jZSBmcm9tIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmUgdXNpbmcgaXRzIHByaW1hcnkga2V5LlxuICAgKiBUaGlzIG1ldGhvZCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IGNvbmNyZXRlIHJlcG9zaXRvcnkgY2xhc3Nlcy5cbiAgICogQHBhcmFtIHtzdHJpbmcgfCBudW1iZXJ9IGtleSAtIFRoZSBwcmltYXJ5IGtleSBvZiB0aGUgbW9kZWwgdG8gcmV0cmlldmVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgcmVhZCBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHJldHJpZXZlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgYWJzdHJhY3QgcmVhZChrZXk6IHN0cmluZyB8IG51bWJlciwgLi4uYXJnczogYW55W10pOiBQcm9taXNlPE0+O1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIG11bHRpcGxlIG1vZGVsIGluc3RhbmNlcyBmcm9tIHRoZSByZXBvc2l0b3J5IGJ5IHRoZWlyIHByaW1hcnkga2V5cy5cbiAgICogQHN1bW1hcnkgRmV0Y2hlcyBtdWx0aXBsZSBtb2RlbCBpbnN0YW5jZXMgZnJvbSB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlIHVzaW5nIHRoZWlyIHByaW1hcnkga2V5c1xuICAgKiBieSBjYWxsaW5nIHRoZSByZWFkIG1ldGhvZCBmb3IgZWFjaCBrZXkgaW4gdGhlIGFycmF5LlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdIHwgbnVtYmVyW119IGtleXMgLSBUaGUgYXJyYXkgb2YgcHJpbWFyeSBrZXlzIG9mIHRoZSBtb2RlbHMgdG8gcmV0cmlldmVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgcmVhZCBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiByZXRyaWV2ZWQgbW9kZWwgaW5zdGFuY2VzXG4gICAqL1xuICBhc3luYyByZWFkQWxsKGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNW10+IHtcbiAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwoa2V5cy5tYXAoKGlkKSA9PiB0aGlzLnJlYWQoaWQsIC4uLmFyZ3MpKSk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByb2Nlc3NlcyBhIG1vZGVsIGFmdGVyIHJldHJpZXZhbCBhbmQgZXhlY3V0ZXMgcG9zdC1yZWFkIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEZpbmFsaXplcyBhIG1vZGVsIGFmdGVyIGl0IGhhcyBiZWVuIHJldHJpZXZlZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIHJlYWRpbmcuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdGhhdCB3YXMgcmV0cmlldmVkXG4gICAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSBjb250ZXh0IGZvciB0aGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBwcm9jZXNzZWQgbW9kZWwgaW5zdGFuY2VcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyByZWFkU3VmZml4KG1vZGVsOiBNLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGZvciByZWFkaW5nIGEgbW9kZWwgYW5kIGV4ZWN1dGVzIHByZS1yZWFkIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBhIGtleSBiZWZvcmUgYSBtb2RlbCBpcyByZWFkIGZyb20gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogY3JlYXRpbmcgYSBjb250ZXh0LCBpbnN0YW50aWF0aW5nIGEgbmV3IG1vZGVsIGluc3RhbmNlIHdpdGggdGhlIGtleSwgYW5kIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9yc1xuICAgKiB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGJlZm9yZSByZWFkaW5nLlxuICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIHByaW1hcnkga2V5IG9mIHRoZSBtb2RlbCB0byByZWFkXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHJlYWQgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUga2V5IGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRQcmVmaXgoa2V5OiBzdHJpbmcsIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLlJFQUQsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgbW9kZWw6IE0gPSBuZXcgdGhpcy5jbGFzcygpO1xuICAgIG1vZGVsW3RoaXMucGtdID0ga2V5IGFzIGFueTtcbiAgICBhd2FpdCBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgdGhpcyxcbiAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICBtb2RlbCxcbiAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICApO1xuICAgIHJldHVybiBba2V5LCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgZm9yIHJlYWRpbmcgbXVsdGlwbGUgbW9kZWxzIGFuZCBleGVjdXRlcyBwcmUtcmVhZCBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgbXVsdGlwbGUga2V5cyBiZWZvcmUgbW9kZWxzIGFyZSByZWFkIGZyb20gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogY3JlYXRpbmcgYSBjb250ZXh0LCBpbnN0YW50aWF0aW5nIG5ldyBtb2RlbCBpbnN0YW5jZXMgd2l0aCB0aGUga2V5cywgYW5kIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9yc1xuICAgKiB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGJlZm9yZSByZWFkaW5nIGZvciBlYWNoIGtleS5cbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBrZXlzIC0gVGhlIGFycmF5IG9mIHByaW1hcnkga2V5cyBvZiB0aGUgbW9kZWxzIHRvIHJlYWRcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgcmVhZCBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSBrZXlzIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRBbGxQcmVmaXgoa2V5czogc3RyaW5nW10gfCBudW1iZXJbXSwgLi4uYXJnczogYW55W10pIHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJnczxNLCBDLCBGPihcbiAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGtleXMubWFwKGFzeW5jIChrKSA9PiB7XG4gICAgICAgIGNvbnN0IG0gPSBuZXcgdGhpcy5jbGFzcygpO1xuICAgICAgICBtW3RoaXMucGtdID0gayBhcyBhbnk7XG4gICAgICAgIHJldHVybiBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuUkVBRCxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgICAgICk7XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIFtrZXlzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJvY2Vzc2VzIG11bHRpcGxlIG1vZGVscyBhZnRlciByZXRyaWV2YWwgYW5kIGV4ZWN1dGVzIHBvc3QtcmVhZCBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBGaW5hbGl6ZXMgbXVsdGlwbGUgbW9kZWxzIGFmdGVyIHRoZXkgaGF2ZSBiZWVuIHJldHJpZXZlZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIHJlYWRpbmcgZm9yIGVhY2ggbW9kZWwuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRoYXQgd2VyZSByZXRyaWV2ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgYXJyYXkgb2YgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHJlYWRBbGxTdWZmaXgobW9kZWxzOiBNW10sIGNvbnRleHQ6IEMpIHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+XG4gICAgICAgIGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5SRUFELFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVscztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gVXBkYXRlcyBhbiBleGlzdGluZyBtb2RlbCBpbnN0YW5jZSBpbiB0aGUgcmVwb3NpdG9yeS5cbiAgICogQHN1bW1hcnkgVXBkYXRlcyBhbiBleGlzdGluZyBtb2RlbCBpbnN0YW5jZSBpbiB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlLlxuICAgKiBUaGlzIG1ldGhvZCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IGNvbmNyZXRlIHJlcG9zaXRvcnkgY2xhc3Nlcy5cbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byB1cGRhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgdXBkYXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgdXBkYXRlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgYWJzdHJhY3QgdXBkYXRlKG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TT47XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBVcGRhdGVzIG11bHRpcGxlIG1vZGVsIGluc3RhbmNlcyBpbiB0aGUgcmVwb3NpdG9yeS5cbiAgICogQHN1bW1hcnkgVXBkYXRlcyBtdWx0aXBsZSBtb2RlbCBpbnN0YW5jZXMgaW4gdGhlIHVuZGVybHlpbmcgZGF0YSBzdG9yZSBieSBjYWxsaW5nXG4gICAqIHRoZSB1cGRhdGUgbWV0aG9kIGZvciBlYWNoIG1vZGVsIGluIHRoZSBhcnJheS5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdG8gdXBkYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHVwZGF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiB1cGRhdGVkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgYXN5bmMgdXBkYXRlQWxsKG1vZGVsczogTVtdLCAuLi5hcmdzOiBhbnkpOiBQcm9taXNlPE1bXT4ge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChtb2RlbHMubWFwKChtKSA9PiB0aGlzLnVwZGF0ZShtLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgYSBtb2RlbCBhZnRlciB1cGRhdGUgYW5kIGV4ZWN1dGVzIHBvc3QtdXBkYXRlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IEZpbmFsaXplcyBhIG1vZGVsIGFmdGVyIGl0IGhhcyBiZWVuIHVwZGF0ZWQgaW4gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYWZ0ZXIgdXBkYXRpbmcuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdGhhdCB3YXMgdXBkYXRlZFxuICAgKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE0+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlU3VmZml4KG1vZGVsOiBNLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICApO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgYSBtb2RlbCBmb3IgdXBkYXRlIGFuZCBleGVjdXRlcyBwcmUtdXBkYXRlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBhIG1vZGVsIGJlZm9yZSBpdCBpcyB1cGRhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgdmFsaWRhdGluZyB0aGUgcHJpbWFyeSBrZXksIHJldHJpZXZpbmcgdGhlIGV4aXN0aW5nIG1vZGVsLFxuICAgKiBhbmQgZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYmVmb3JlIHVwZGF0aW5nLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHByZXBhcmUgZm9yIHVwZGF0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSB1cGRhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgcHJlcGFyZWQgbW9kZWwgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlUHJlZml4KG1vZGVsOiBNLCAuLi5hcmdzOiBhbnlbXSkge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzPE0sIEMsIEY+KFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgaWQgPSBtb2RlbFt0aGlzLnBrXTtcbiAgICBpZiAoIWlkKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7dGhpcy5wayBhcyBzdHJpbmd9YFxuICAgICAgKTtcbiAgICBjb25zdCBvbGRNb2RlbCA9IGF3YWl0IHRoaXMucmVhZChpZCBhcyBzdHJpbmcpO1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OLFxuICAgICAgb2xkTW9kZWxcbiAgICApO1xuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBtdWx0aXBsZSBtb2RlbHMgZm9yIHVwZGF0ZSBhbmQgZXhlY3V0ZXMgcHJlLXVwZGF0ZSBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBQcm9jZXNzZXMgbXVsdGlwbGUgbW9kZWxzIGJlZm9yZSB0aGV5IGFyZSB1cGRhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgaW5zdGFudGlhdGluZyBuZXcgbW9kZWwgaW5zdGFuY2VzLCBhbmQgZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzXG4gICAqIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYmVmb3JlIHVwZGF0aW5nIGZvciBlYWNoIG1vZGVsLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIGFycmF5IG9mIG1vZGVsIGluc3RhbmNlcyB0byBwcmVwYXJlIGZvciB1cGRhdGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgdXBkYXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHByZXBhcmVkIG1vZGVscyBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyB1cGRhdGVBbGxQcmVmaXgobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+IHtcbiAgICAgICAgbSA9IG5ldyB0aGlzLmNsYXNzKG0pO1xuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIG07XG4gICAgICB9KVxuICAgICk7XG4gICAgcmV0dXJuIFttb2RlbHMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgbXVsdGlwbGUgbW9kZWxzIGFmdGVyIHVwZGF0ZSBhbmQgZXhlY3V0ZXMgcG9zdC11cGRhdGUgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgRmluYWxpemVzIG11bHRpcGxlIG1vZGVscyBhZnRlciB0aGV5IGhhdmUgYmVlbiB1cGRhdGVkIGluIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIHVwZGF0aW5nIGZvciBlYWNoIG1vZGVsLlxuICAgKiBAcGFyYW0ge01bXX0gbW9kZWxzIC0gVGhlIGFycmF5IG9mIG1vZGVsIGluc3RhbmNlcyB0aGF0IHdlcmUgdXBkYXRlZFxuICAgKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgY29udGV4dCBmb3IgdGhlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlPE1bXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBhcnJheSBvZiBwcm9jZXNzZWQgbW9kZWwgaW5zdGFuY2VzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgdXBkYXRlQWxsU3VmZml4KG1vZGVsczogTVtdLCBjb250ZXh0OiBDKSB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKChtKSA9PlxuICAgICAgICBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuVVBEQVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuQUZURVJcbiAgICAgICAgKVxuICAgICAgKVxuICAgICk7XG4gICAgcmV0dXJuIG1vZGVscztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gRGVsZXRlcyBhIG1vZGVsIGluc3RhbmNlIGZyb20gdGhlIHJlcG9zaXRvcnkgYnkgaXRzIHByaW1hcnkga2V5LlxuICAgKiBAc3VtbWFyeSBSZW1vdmVzIGEgbW9kZWwgaW5zdGFuY2UgZnJvbSB0aGUgdW5kZXJseWluZyBkYXRhIHN0b3JlIHVzaW5nIGl0cyBwcmltYXJ5IGtleS5cbiAgICogVGhpcyBtZXRob2QgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBjb25jcmV0ZSByZXBvc2l0b3J5IGNsYXNzZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nIHwgbnVtYmVyfSBrZXkgLSBUaGUgcHJpbWFyeSBrZXkgb2YgdGhlIG1vZGVsIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBkZWxldGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBkZWxldGVkIG1vZGVsIGluc3RhbmNlXG4gICAqL1xuICBhYnN0cmFjdCBkZWxldGUoa2V5OiBzdHJpbmcgfCBudW1iZXIsIC4uLmFyZ3M6IGFueVtdKTogUHJvbWlzZTxNPjtcblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIERlbGV0ZXMgbXVsdGlwbGUgbW9kZWwgaW5zdGFuY2VzIGZyb20gdGhlIHJlcG9zaXRvcnkgYnkgdGhlaXIgcHJpbWFyeSBrZXlzLlxuICAgKiBAc3VtbWFyeSBSZW1vdmVzIG11bHRpcGxlIG1vZGVsIGluc3RhbmNlcyBmcm9tIHRoZSB1bmRlcmx5aW5nIGRhdGEgc3RvcmUgdXNpbmcgdGhlaXIgcHJpbWFyeSBrZXlzXG4gICAqIGJ5IGNhbGxpbmcgdGhlIGRlbGV0ZSBtZXRob2QgZm9yIGVhY2gga2V5IGluIHRoZSBhcnJheS5cbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IG51bWJlcltdfSBrZXlzIC0gVGhlIGFycmF5IG9mIHByaW1hcnkga2V5cyBvZiB0aGUgbW9kZWxzIHRvIGRlbGV0ZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBkZWxldGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2U8TVtdPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgZGVsZXRlZCBtb2RlbCBpbnN0YW5jZXNcbiAgICovXG4gIGFzeW5jIGRlbGV0ZUFsbChrZXlzOiBzdHJpbmdbXSB8IG51bWJlcltdLCAuLi5hcmdzOiBhbnlbXSk6IFByb21pc2U8TVtdPiB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKGtleXMubWFwKChrKSA9PiB0aGlzLmRlbGV0ZShrLCAuLi5hcmdzKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgYSBtb2RlbCBhZnRlciBkZWxldGlvbiBhbmQgZXhlY3V0ZXMgcG9zdC1kZWxldGUgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgRmluYWxpemVzIGEgbW9kZWwgYWZ0ZXIgaXQgaGFzIGJlZW4gZGVsZXRlZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGVuZm9yY2luZyBhbnkgZGVjb3JhdG9ycyB0aGF0IHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIGRlbGV0aW9uLlxuICAgKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRoYXQgd2FzIGRlbGV0ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHByb2Nlc3NlZCBtb2RlbCBpbnN0YW5jZVxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZVN1ZmZpeChtb2RlbDogTSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgKTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGZvciBkZWxldGluZyBhIG1vZGVsIGFuZCBleGVjdXRlcyBwcmUtZGVsZXRlIG9wZXJhdGlvbnMuXG4gICAqIEBzdW1tYXJ5IFByb2Nlc3NlcyBhIGtleSBiZWZvcmUgYSBtb2RlbCBpcyBkZWxldGVkIGZyb20gdGhlIGRhdGEgc3RvcmUuIFRoaXMgaW5jbHVkZXNcbiAgICogY3JlYXRpbmcgYSBjb250ZXh0LCByZXRyaWV2aW5nIHRoZSBtb2RlbCB0byBiZSBkZWxldGVkLCBhbmQgZW5mb3JjaW5nIGFueSBkZWNvcmF0b3JzXG4gICAqIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgYmVmb3JlIGRlbGV0aW9uLlxuICAgKiBAcGFyYW0ge2FueX0ga2V5IC0gVGhlIHByaW1hcnkga2V5IG9mIHRoZSBtb2RlbCB0byBkZWxldGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgZGVsZXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGtleSBhbmQgY29udGV4dCBhcmd1bWVudHNcbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVQcmVmaXgoa2V5OiBhbnksIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBtb2RlbCA9IGF3YWl0IHRoaXMucmVhZChrZXksIC4uLmNvbnRleHRBcmdzLmFyZ3MpO1xuICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnM8TSwgdHlwZW9mIHRoaXMsIGFueSwgRiwgQz4oXG4gICAgICB0aGlzLFxuICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgIG1vZGVsLFxuICAgICAgT3BlcmF0aW9uS2V5cy5ERUxFVEUsXG4gICAgICBPcGVyYXRpb25LZXlzLk9OXG4gICAgKTtcbiAgICByZXR1cm4gW2tleSwgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGZvciBkZWxldGluZyBtdWx0aXBsZSBtb2RlbHMgYW5kIGV4ZWN1dGVzIHByZS1kZWxldGUgb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgUHJvY2Vzc2VzIG11bHRpcGxlIGtleXMgYmVmb3JlIG1vZGVscyBhcmUgZGVsZXRlZCBmcm9tIHRoZSBkYXRhIHN0b3JlLiBUaGlzIGluY2x1ZGVzXG4gICAqIGNyZWF0aW5nIGEgY29udGV4dCwgcmV0cmlldmluZyB0aGUgbW9kZWxzIHRvIGJlIGRlbGV0ZWQsIGFuZCBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnNcbiAgICogdGhhdCBzaG91bGQgYmUgYXBwbGllZCBiZWZvcmUgZGVsZXRpb24gZm9yIGVhY2ggbW9kZWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nW10gfCBudW1iZXJbXX0ga2V5cyAtIFRoZSBhcnJheSBvZiBwcmltYXJ5IGtleXMgb2YgdGhlIG1vZGVscyB0byBkZWxldGVcbiAgICogQHBhcmFtIHthbnlbXX0gYXJncyAtIEFkZGl0aW9uYWwgYXJndW1lbnRzIGZvciB0aGUgZGVsZXRlIG9wZXJhdGlvblxuICAgKiBAcmV0dXJuIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGtleXMgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgZGVsZXRlQWxsUHJlZml4KGtleXM6IHN0cmluZ1tdIHwgbnVtYmVyW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3M8TSwgQywgRj4oXG4gICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBtb2RlbHMgPSBhd2FpdCB0aGlzLnJlYWRBbGwoa2V5cywgLi4uY29udGV4dEFyZ3MuYXJncyk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBtb2RlbHMubWFwKGFzeW5jIChtKSA9PiB7XG4gICAgICAgIHJldHVybiBlbmZvcmNlREJEZWNvcmF0b3JzPE0sIHR5cGVvZiB0aGlzLCBhbnksIEYsIEM+KFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgY29udGV4dEFyZ3MuY29udGV4dCxcbiAgICAgICAgICBtLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuREVMRVRFLFxuICAgICAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICByZXR1cm4gW2tleXMsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgbXVsdGlwbGUgbW9kZWxzIGFmdGVyIGRlbGV0aW9uIGFuZCBleGVjdXRlcyBwb3N0LWRlbGV0ZSBvcGVyYXRpb25zLlxuICAgKiBAc3VtbWFyeSBGaW5hbGl6ZXMgbXVsdGlwbGUgbW9kZWxzIGFmdGVyIHRoZXkgaGF2ZSBiZWVuIGRlbGV0ZWQgZnJvbSB0aGUgZGF0YSBzdG9yZS4gVGhpcyBpbmNsdWRlc1xuICAgKiBlbmZvcmNpbmcgYW55IGRlY29yYXRvcnMgdGhhdCBzaG91bGQgYmUgYXBwbGllZCBhZnRlciBkZWxldGlvbiBmb3IgZWFjaCBtb2RlbC5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdGhhdCB3ZXJlIGRlbGV0ZWRcbiAgICogQHBhcmFtIHtDfSBjb250ZXh0IC0gVGhlIGNvbnRleHQgZm9yIHRoZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxNW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byB0aGUgYXJyYXkgb2YgcHJvY2Vzc2VkIG1vZGVsIGluc3RhbmNlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIGRlbGV0ZUFsbFN1ZmZpeChtb2RlbHM6IE1bXSwgY29udGV4dDogQykge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9yczxNLCB0eXBlb2YgdGhpcywgYW55LCBGLCBDPihcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkRFTEVURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLkFGVEVSXG4gICAgICAgIClcbiAgICAgIClcbiAgICApO1xuICAgIHJldHVybiBtb2RlbHM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIE1lcmdlcyB0d28gbW9kZWwgaW5zdGFuY2VzIGludG8gYSBuZXcgaW5zdGFuY2UuXG4gICAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBuZXcgbW9kZWwgaW5zdGFuY2UgYnkgY29tYmluaW5nIHByb3BlcnRpZXMgZnJvbSBhbiBvbGQgbW9kZWwgYW5kIGEgbmV3IG1vZGVsLlxuICAgKiBQcm9wZXJ0aWVzIGZyb20gdGhlIG5ldyBtb2RlbCBvdmVycmlkZSBwcm9wZXJ0aWVzIGZyb20gdGhlIG9sZCBtb2RlbCBpZiB0aGV5IGFyZSBkZWZpbmVkLlxuICAgKiBAcGFyYW0ge019IG9sZE1vZGVsIC0gVGhlIG9yaWdpbmFsIG1vZGVsIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbmV3IG1vZGVsIGluc3RhbmNlIHdpdGggdXBkYXRlZCBwcm9wZXJ0aWVzXG4gICAqIEByZXR1cm4ge019IEEgbmV3IG1vZGVsIGluc3RhbmNlIHdpdGggbWVyZ2VkIHByb3BlcnRpZXNcbiAgICovXG4gIHByb3RlY3RlZCBtZXJnZShvbGRNb2RlbDogTSwgbW9kZWw6IE0pOiBNIHtcbiAgICBjb25zdCBleHRyYWN0ID0gKG1vZGVsOiBNKSA9PlxuICAgICAgT2JqZWN0LmVudHJpZXMobW9kZWwpLnJlZHVjZSgoYWNjdW06IFJlY29yZDxzdHJpbmcsIGFueT4sIFtrZXksIHZhbF0pID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWwgIT09IFwidW5kZWZpbmVkXCIpIGFjY3VtW2tleV0gPSB2YWw7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sIHt9KTtcblxuICAgIHJldHVybiBuZXcgdGhpcy5jbGFzcyhPYmplY3QuYXNzaWduKHt9LCBleHRyYWN0KG9sZE1vZGVsKSwgZXh0cmFjdChtb2RlbCkpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgcmVwb3NpdG9yeS5cbiAgICogQHN1bW1hcnkgQ3JlYXRlcyBhIHN0cmluZyB0aGF0IGlkZW50aWZpZXMgdGhpcyByZXBvc2l0b3J5IGJ5IHRoZSBuYW1lIG9mIGl0cyBtb2RlbCBjbGFzcy5cbiAgICogQHJldHVybiB7c3RyaW5nfSBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgcmVwb3NpdG9yeVxuICAgKi9cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMuY2xhc3MubmFtZX0gUmVwb3NpdG9yeWA7XG4gIH1cbn1cbiIsImltcG9ydCB7IGVuZm9yY2VEQkRlY29yYXRvcnMgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgT3BlcmF0aW9uS2V5cyB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciwgVmFsaWRhdGlvbkVycm9yIH0gZnJvbSBcIi4vZXJyb3JzXCI7XG5pbXBvcnQgeyBCYXNlUmVwb3NpdG9yeSB9IGZyb20gXCIuL0Jhc2VSZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4vQ29udGV4dFwiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ29uY3JldGUgcmVwb3NpdG9yeSBpbXBsZW1lbnRhdGlvbiB3aXRoIHZhbGlkYXRpb24gc3VwcG9ydC5cbiAqIEBzdW1tYXJ5IFRoZSBSZXBvc2l0b3J5IGNsYXNzIGV4dGVuZHMgQmFzZVJlcG9zaXRvcnkgdG8gcHJvdmlkZSBhZGRpdGlvbmFsIHZhbGlkYXRpb25cbiAqIGZ1bmN0aW9uYWxpdHkuIEl0IG92ZXJyaWRlcyBwcmVmaXggbWV0aG9kcyB0byBwZXJmb3JtIG1vZGVsIHZhbGlkYXRpb24gYmVmb3JlIGRhdGFiYXNlXG4gKiBvcGVyYXRpb25zIGFuZCB0aHJvd3MgVmFsaWRhdGlvbkVycm9yIHdoZW4gdmFsaWRhdGlvbiBmYWlscy5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgRiAtIFRoZSByZXBvc2l0b3J5IGZsYWdzIHR5cGUsIGRlZmF1bHRzIHRvIFJlcG9zaXRvcnlGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlLCBkZWZhdWx0cyB0byBDb250ZXh0PEY+XG4gKiBAY2xhc3MgUmVwb3NpdG9yeVxuICogQGV4YW1wbGVcbiAqIGNsYXNzIFVzZXJNb2RlbCBleHRlbmRzIE1vZGVsIHtcbiAqICAgQGlkKClcbiAqICAgaWQ6IHN0cmluZztcbiAqXG4gKiAgIEByZXF1aXJlZCgpXG4gKiAgIEBtaW5MZW5ndGgoMylcbiAqICAgbmFtZTogc3RyaW5nO1xuICogfVxuICpcbiAqIGNsYXNzIFVzZXJSZXBvc2l0b3J5IGV4dGVuZHMgUmVwb3NpdG9yeTxVc2VyTW9kZWw+IHtcbiAqICAgY29uc3RydWN0b3IoKSB7XG4gKiAgICAgc3VwZXIoVXNlck1vZGVsKTtcbiAqICAgfVxuICpcbiAqICAgYXN5bmMgY3JlYXRlKG1vZGVsOiBVc2VyTW9kZWwpOiBQcm9taXNlPFVzZXJNb2RlbD4ge1xuICogICAgIC8vIEltcGxlbWVudGF0aW9uIHdpdGggYXV0b21hdGljIHZhbGlkYXRpb25cbiAqICAgICByZXR1cm4gbW9kZWw7XG4gKiAgIH1cbiAqIH1cbiAqXG4gKiAvLyBVc2luZyB0aGUgcmVwb3NpdG9yeVxuICogY29uc3QgcmVwbyA9IG5ldyBVc2VyUmVwb3NpdG9yeSgpO1xuICogdHJ5IHtcbiAqICAgY29uc3QgdXNlciA9IGF3YWl0IHJlcG8uY3JlYXRlKHsgbmFtZTogJ0pvJyB9KTsgLy8gV2lsbCB0aHJvdyBWYWxpZGF0aW9uRXJyb3JcbiAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gKiAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpOyAvLyBWYWxpZGF0aW9uRXJyb3I6IG5hbWUgbXVzdCBiZSBhdCBsZWFzdCAzIGNoYXJhY3RlcnNcbiAqIH1cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFJlcG9zaXRvcnk8XG4gIE0gZXh0ZW5kcyBNb2RlbCxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPiBleHRlbmRzIEJhc2VSZXBvc2l0b3J5PE0sIEYsIEM+IHtcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGNsYXp6PzogQ29uc3RydWN0b3I8TT4pIHtcbiAgICBzdXBlcihjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgbW9kZWwgZm9yIGNyZWF0aW9uIHdpdGggdmFsaWRhdGlvbi5cbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzIHRoZSBiYXNlIGNyZWF0ZVByZWZpeCBtZXRob2QgdG8gYWRkIHZhbGlkYXRpb24gY2hlY2tzLlxuICAgKiBDcmVhdGVzIGEgY29udGV4dCwgaW5zdGFudGlhdGVzIGEgbmV3IG1vZGVsLCBlbmZvcmNlcyBkZWNvcmF0b3JzLCBhbmQgdmFsaWRhdGVzXG4gICAqIHRoZSBtb2RlbCBiZWZvcmUgYWxsb3dpbmcgY3JlYXRpb24gdG8gcHJvY2VlZC5cbiAgICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSB0byBwcmVwYXJlIGZvciBjcmVhdGlvblxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzIC0gQWRkaXRpb25hbCBhcmd1bWVudHMgZm9yIHRoZSBjcmVhdGUgb3BlcmF0aW9uXG4gICAqIEByZXR1cm4gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgdmFsaWRhdGVkIG1vZGVsIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKiBAdGhyb3dzIHtWYWxpZGF0aW9uRXJyb3J9IElmIHRoZSBtb2RlbCBmYWlscyB2YWxpZGF0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlUHJlZml4KFxuICAgIG1vZGVsOiBNLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8W00sIC4uLmFueVtdXT4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgbW9kZWwgPSBuZXcgdGhpcy5jbGFzcyhtb2RlbCk7XG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLkNSRUFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT05cbiAgICApO1xuXG4gICAgY29uc3QgZXJyb3JzID0gYXdhaXQgUHJvbWlzZS5yZXNvbHZlKG1vZGVsLmhhc0Vycm9ycygpKTtcbiAgICBpZiAoZXJyb3JzKSB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGVycm9ycy50b1N0cmluZygpKTtcblxuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBtdWx0aXBsZSBtb2RlbHMgZm9yIGNyZWF0aW9uIHdpdGggdmFsaWRhdGlvbi5cbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzIHRoZSBiYXNlIGNyZWF0ZUFsbFByZWZpeCBtZXRob2QgdG8gYWRkIHZhbGlkYXRpb24gY2hlY2tzIGZvciBtdWx0aXBsZSBtb2RlbHMuXG4gICAqIENyZWF0ZXMgYSBjb250ZXh0LCBpbnN0YW50aWF0ZXMgbmV3IG1vZGVscywgZW5mb3JjZXMgZGVjb3JhdG9ycywgYW5kIHZhbGlkYXRlc1xuICAgKiBlYWNoIG1vZGVsIGJlZm9yZSBhbGxvd2luZyBjcmVhdGlvbiB0byBwcm9jZWVkLiBDb2xsZWN0cyB2YWxpZGF0aW9uIGVycm9ycyBmcm9tIGFsbCBtb2RlbHMuXG4gICAqIEBwYXJhbSB7TVtdfSBtb2RlbHMgLSBUaGUgYXJyYXkgb2YgbW9kZWwgaW5zdGFuY2VzIHRvIHByZXBhcmUgZm9yIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIGNyZWF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZTxhbnlbXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHZhbGlkYXRlZCBtb2RlbHMgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqIEB0aHJvd3Mge1ZhbGlkYXRpb25FcnJvcn0gSWYgYW55IG1vZGVsIGZhaWxzIHZhbGlkYXRpb24sIHdpdGggZGV0YWlscyBhYm91dCB3aGljaCBtb2RlbHMgZmFpbGVkXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgY3JlYXRlQWxsUHJlZml4KFxuICAgIG1vZGVsczogTVtdLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8YW55W10+IHtcbiAgICBjb25zdCBjb250ZXh0QXJncyA9IGF3YWl0IENvbnRleHQuYXJncyhcbiAgICAgIE9wZXJhdGlvbktleXMuQ1JFQVRFLFxuICAgICAgdGhpcy5jbGFzcyxcbiAgICAgIGFyZ3NcbiAgICApO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcChhc3luYyAobSkgPT4ge1xuICAgICAgICBtID0gbmV3IHRoaXMuY2xhc3MobSk7XG4gICAgICAgIGF3YWl0IGVuZm9yY2VEQkRlY29yYXRvcnMoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgICAgIG0sXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5DUkVBVEUsXG4gICAgICAgICAgT3BlcmF0aW9uS2V5cy5PTlxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gbTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIGNvbnN0IG1vZGVsc1ZhbGlkYXRpb24gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0pID0+IFByb21pc2UucmVzb2x2ZShtLmhhc0Vycm9ycygpKSlcbiAgICApO1xuXG4gICAgY29uc3QgZXJyb3JzID0gbW9kZWxzVmFsaWRhdGlvbi5yZWR1Y2UoXG4gICAgICAoYWNjdW06IHN0cmluZyB8IHVuZGVmaW5lZCwgZSwgaSkgPT4ge1xuICAgICAgICBpZiAoZSlcbiAgICAgICAgICBhY2N1bSA9XG4gICAgICAgICAgICB0eXBlb2YgYWNjdW0gPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgPyBhY2N1bSArIGBcXG4gLSAke2l9OiAke2UudG9TdHJpbmcoKX1gXG4gICAgICAgICAgICAgIDogYCAtICR7aX06ICR7ZS50b1N0cmluZygpfWA7XG4gICAgICAgIHJldHVybiBhY2N1bTtcbiAgICAgIH0sXG4gICAgICB1bmRlZmluZWRcbiAgICApO1xuXG4gICAgaWYgKGVycm9ycykgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihlcnJvcnMpO1xuICAgIHJldHVybiBbbW9kZWxzLCAuLi5jb250ZXh0QXJncy5hcmdzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUHJlcGFyZXMgYSBtb2RlbCBmb3IgdXBkYXRlIHdpdGggdmFsaWRhdGlvbi5cbiAgICogQHN1bW1hcnkgT3ZlcnJpZGVzIHRoZSBiYXNlIHVwZGF0ZVByZWZpeCBtZXRob2QgdG8gYWRkIHZhbGlkYXRpb24gY2hlY2tzLlxuICAgKiBDcmVhdGVzIGEgY29udGV4dCwgdmFsaWRhdGVzIHRoZSBwcmltYXJ5IGtleSwgcmV0cmlldmVzIHRoZSBleGlzdGluZyBtb2RlbCxcbiAgICogbWVyZ2VzIHRoZSBvbGQgYW5kIG5ldyBtb2RlbHMsIGVuZm9yY2VzIGRlY29yYXRvcnMsIGFuZCB2YWxpZGF0ZXMgdGhlIG1vZGVsXG4gICAqIGJlZm9yZSBhbGxvd2luZyB0aGUgdXBkYXRlIHRvIHByb2NlZWQuXG4gICAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgdG8gcHJlcGFyZSBmb3IgdXBkYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHVwZGF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSB2YWxpZGF0ZWQgbW9kZWwgYW5kIGNvbnRleHQgYXJndW1lbnRzXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IElmIHRoZSBtb2RlbCBkb2Vzbid0IGhhdmUgYSBwcmltYXJ5IGtleSB2YWx1ZVxuICAgKiBAdGhyb3dzIHtWYWxpZGF0aW9uRXJyb3J9IElmIHRoZSBtb2RlbCBmYWlscyB2YWxpZGF0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgb3ZlcnJpZGUgYXN5bmMgdXBkYXRlUHJlZml4KFxuICAgIG1vZGVsOiBNLFxuICAgIC4uLmFyZ3M6IGFueVtdXG4gICk6IFByb21pc2U8W00sIC4uLmFyZ3M6IGFueVtdXT4ge1xuICAgIGNvbnN0IGNvbnRleHRBcmdzID0gYXdhaXQgQ29udGV4dC5hcmdzKFxuICAgICAgT3BlcmF0aW9uS2V5cy5VUERBVEUsXG4gICAgICB0aGlzLmNsYXNzLFxuICAgICAgYXJnc1xuICAgICk7XG4gICAgY29uc3QgcGsgPSAobW9kZWwgYXMgYW55KVt0aGlzLnBrXTtcbiAgICBpZiAoIXBrKVxuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgIGBObyB2YWx1ZSBmb3IgdGhlIElkIGlzIGRlZmluZWQgdW5kZXIgdGhlIHByb3BlcnR5ICR7dGhpcy5wayBhcyBzdHJpbmd9YFxuICAgICAgKTtcblxuICAgIGNvbnN0IG9sZE1vZGVsOiBNID0gYXdhaXQgdGhpcy5yZWFkKHBrKTtcblxuICAgIG1vZGVsID0gdGhpcy5tZXJnZShvbGRNb2RlbCwgbW9kZWwpO1xuXG4gICAgYXdhaXQgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgIHRoaXMsXG4gICAgICBjb250ZXh0QXJncy5jb250ZXh0LFxuICAgICAgbW9kZWwsXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIE9wZXJhdGlvbktleXMuT04sXG4gICAgICBvbGRNb2RlbFxuICAgICk7XG5cbiAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBQcm9taXNlLnJlc29sdmUobW9kZWwuaGFzRXJyb3JzKG9sZE1vZGVsIGFzIGFueSkpO1xuICAgIGlmIChlcnJvcnMpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyb3JzLnRvU3RyaW5nKCkpO1xuICAgIHJldHVybiBbbW9kZWwsIC4uLmNvbnRleHRBcmdzLmFyZ3NdO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBtdWx0aXBsZSBtb2RlbHMgZm9yIHVwZGF0ZSB3aXRoIHZhbGlkYXRpb24uXG4gICAqIEBzdW1tYXJ5IE92ZXJyaWRlcyB0aGUgYmFzZSB1cGRhdGVBbGxQcmVmaXggbWV0aG9kIHRvIGFkZCB2YWxpZGF0aW9uIGNoZWNrcyBmb3IgbXVsdGlwbGUgbW9kZWxzLlxuICAgKiBDcmVhdGVzIGEgY29udGV4dCwgdmFsaWRhdGVzIHByaW1hcnkga2V5cywgcmV0cmlldmVzIGV4aXN0aW5nIG1vZGVscywgbWVyZ2VzIG9sZCBhbmQgbmV3IG1vZGVscyxcbiAgICogZW5mb3JjZXMgZGVjb3JhdG9ycywgYW5kIHZhbGlkYXRlcyBlYWNoIG1vZGVsIGJlZm9yZSBhbGxvd2luZyB1cGRhdGVzIHRvIHByb2NlZWQuXG4gICAqIENvbGxlY3RzIHZhbGlkYXRpb24gZXJyb3JzIGZyb20gYWxsIG1vZGVscy5cbiAgICogQHBhcmFtIHtNW119IG1vZGVscyAtIFRoZSBhcnJheSBvZiBtb2RlbCBpbnN0YW5jZXMgdG8gcHJlcGFyZSBmb3IgdXBkYXRlXG4gICAqIEBwYXJhbSB7YW55W119IGFyZ3MgLSBBZGRpdGlvbmFsIGFyZ3VtZW50cyBmb3IgdGhlIHVwZGF0ZSBvcGVyYXRpb25cbiAgICogQHJldHVybiBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBjb250YWluaW5nIHRoZSB2YWxpZGF0ZWQgbW9kZWxzIGFuZCBjb250ZXh0IGFyZ3VtZW50c1xuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBJZiBhbnkgbW9kZWwgZG9lc24ndCBoYXZlIGEgcHJpbWFyeSBrZXkgdmFsdWVcbiAgICogQHRocm93cyB7VmFsaWRhdGlvbkVycm9yfSBJZiBhbnkgbW9kZWwgZmFpbHMgdmFsaWRhdGlvbiwgd2l0aCBkZXRhaWxzIGFib3V0IHdoaWNoIG1vZGVscyBmYWlsZWRcbiAgICovXG4gIHByb3RlY3RlZCBvdmVycmlkZSBhc3luYyB1cGRhdGVBbGxQcmVmaXgobW9kZWxzOiBNW10sIC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgY29uc3QgY29udGV4dEFyZ3MgPSBhd2FpdCBDb250ZXh0LmFyZ3MoXG4gICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgIHRoaXMuY2xhc3MsXG4gICAgICBhcmdzXG4gICAgKTtcbiAgICBjb25zdCBpZHMgPSBtb2RlbHMubWFwKChtKSA9PiB7XG4gICAgICBjb25zdCBpZCA9IG1bdGhpcy5wa107XG4gICAgICBpZiAodHlwZW9mIGlkID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgTm8gdmFsdWUgZm9yIHRoZSBJZCBpcyBkZWZpbmVkIHVuZGVyIHRoZSBwcm9wZXJ0eSAke3RoaXMucGsgYXMgc3RyaW5nfWBcbiAgICAgICAgKTtcbiAgICAgIHJldHVybiBpZCBhcyBzdHJpbmc7XG4gICAgfSk7XG4gICAgY29uc3Qgb2xkTW9kZWxzOiBNW10gPSBhd2FpdCB0aGlzLnJlYWRBbGwoaWRzLCAuLi5jb250ZXh0QXJncy5hcmdzKTtcbiAgICBtb2RlbHMgPSBtb2RlbHMubWFwKChtLCBpKSA9PiB0aGlzLm1lcmdlKG9sZE1vZGVsc1tpXSwgbSkpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgbW9kZWxzLm1hcCgobSwgaSkgPT5cbiAgICAgICAgZW5mb3JjZURCRGVjb3JhdG9ycyhcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgIGNvbnRleHRBcmdzLmNvbnRleHQsXG4gICAgICAgICAgbSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLlVQREFURSxcbiAgICAgICAgICBPcGVyYXRpb25LZXlzLk9OLFxuICAgICAgICAgIG9sZE1vZGVsc1tpXVxuICAgICAgICApXG4gICAgICApXG4gICAgKTtcblxuICAgIGNvbnN0IG1vZGVsc1ZhbGlkYXRpb24gPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIG1vZGVscy5tYXAoKG0sIGkpID0+IFByb21pc2UucmVzb2x2ZShtLmhhc0Vycm9ycyhvbGRNb2RlbHNbaV0gYXMgYW55KSkpXG4gICAgKTtcblxuICAgIGNvbnN0IGVycm9ycyA9IG1vZGVsc1ZhbGlkYXRpb24ucmVkdWNlKFxuICAgICAgKGFjY3VtOiBzdHJpbmcgfCB1bmRlZmluZWQsIGUsIGkpID0+IHtcbiAgICAgICAgaWYgKGUpXG4gICAgICAgICAgYWNjdW0gPVxuICAgICAgICAgICAgdHlwZW9mIGFjY3VtID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgID8gYWNjdW0gKyBgXFxuIC0gJHtpfTogJHtlLnRvU3RyaW5nKCl9YFxuICAgICAgICAgICAgICA6IGAgLSAke2l9OiAke2UudG9TdHJpbmcoKX1gO1xuICAgICAgICByZXR1cm4gYWNjdW07XG4gICAgICB9LFxuICAgICAgdW5kZWZpbmVkXG4gICAgKTtcblxuICAgIGlmIChlcnJvcnMpIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoZXJyb3JzKTtcbiAgICByZXR1cm4gW21vZGVscywgLi4uY29udGV4dEFyZ3MuYXJnc107XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSByZWZsZWN0aW9uIGtleSBmb3IgZGF0YWJhc2Ugb3BlcmF0aW9ucy5cbiAgICogQHN1bW1hcnkgR2VuZXJhdGVzIGEga2V5IGZvciBzdG9yaW5nIG1ldGFkYXRhIGluIHRoZSByZWZsZWN0aW9uIHN5c3RlbSBieSBwcmVmaXhpbmdcbiAgICogdGhlIHByb3ZpZGVkIGtleSB3aXRoIHRoZSBkYXRhYmFzZSByZWZsZWN0aW9uIHByZWZpeC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGtleSAtIFRoZSBiYXNlIGtleSB0byBwcmVmaXhcbiAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgcHJlZml4ZWQgcmVmbGVjdGlvbiBrZXlcbiAgICovXG4gIHN0YXRpYyBrZXkoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gREJLZXlzLlJFRkxFQ1QgKyBrZXk7XG4gIH1cbn1cbiIsImltcG9ydCBcIi4vdmFsaWRhdGlvblwiO1xuaW1wb3J0IHtcbiAgZGF0ZSxcbiAgRGVjb3JhdGlvbixcbiAgTW9kZWwsXG4gIHByb3BNZXRhZGF0YSxcbiAgcmVxdWlyZWQsXG4gIHR5cGUsXG4gIFZhbGlkYXRpb24sXG59IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB7IERCS2V5cywgREVGQVVMVF9USU1FU1RBTVBfRk9STUFUIH0gZnJvbSBcIi4uL21vZGVsL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgREJPcGVyYXRpb25zLCBPcGVyYXRpb25LZXlzIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBhZnRlciwgb24sIG9uQ3JlYXRlVXBkYXRlIH0gZnJvbSBcIi4uL29wZXJhdGlvbnMvZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgSVJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vaW50ZXJmYWNlcy9JUmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgU2VyaWFsaXphdGlvbkVycm9yIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvZXJyb3JzXCI7XG5pbXBvcnQgeyBhcHBseSwgbWV0YWRhdGEgfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeVwiO1xuaW1wb3J0IHsgQ29udGV4dCB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L0NvbnRleHRcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnlGbGFncyB9IGZyb20gXCIuLi9yZXBvc2l0b3J5L3R5cGVzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFByZXZlbnRzIGEgcHJvcGVydHkgZnJvbSBiZWluZyBtb2RpZmllZCBhZnRlciBpbml0aWFsIGNyZWF0aW9uLlxuICogQHN1bW1hcnkgTWFya3MgdGhlIHByb3BlcnR5IGFzIHJlYWRvbmx5LCBjYXVzaW5nIHZhbGlkYXRpb24gZXJyb3JzIGlmIGF0dGVtcHRzIGFyZSBtYWRlIHRvIG1vZGlmeSBpdCBkdXJpbmcgdXBkYXRlcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gLSBUaGUgZXJyb3IgbWVzc2FnZSB0byBkaXNwbGF5IHdoZW4gdmFsaWRhdGlvbiBmYWlscy4gRGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUkVBRE9OTFkuSU5WQUxJRH1cbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciBmdW5jdGlvbiB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiByZWFkb25seVxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlYWRvbmx5KFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlJFQURPTkxZLklOVkFMSURcbikge1xuICBjb25zdCBrZXkgPSBWYWxpZGF0aW9uLnVwZGF0ZUtleShEQktleXMuUkVBRE9OTFkpO1xuICByZXR1cm4gRGVjb3JhdGlvbi5mb3Ioa2V5KVxuICAgIC5kZWZpbmUoXG4gICAgICBwcm9wTWV0YWRhdGEoa2V5LCB7XG4gICAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICB9KVxuICAgIClcbiAgICAuYXBwbHkoKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlciBmdW5jdGlvbiB0aGF0IHNldHMgYSB0aW1lc3RhbXAgcHJvcGVydHkgdG8gdGhlIGN1cnJlbnQgdGltZXN0YW1wLlxuICogQHN1bW1hcnkgVXBkYXRlcyBhIG1vZGVsIHByb3BlcnR5IHdpdGggdGhlIGN1cnJlbnQgdGltZXN0YW1wIGZyb20gdGhlIHJlcG9zaXRvcnkgY29udGV4dC5cbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXBvc2l0b3J5IHR5cGUgZXh0ZW5kaW5nIElSZXBvc2l0b3J5XG4gKiBAdGVtcGxhdGUgViAtIFRoZSBkYXRhIHR5cGUgZm9yIHRoZSBvcGVyYXRpb25cbiAqIEB0ZW1wbGF0ZSBGIC0gVGhlIHJlcG9zaXRvcnkgZmxhZ3MgdHlwZVxuICogQHRlbXBsYXRlIEMgLSBUaGUgY29udGV4dCB0eXBlXG4gKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgcmVwb3NpdG9yeSBjb250ZXh0IGNvbnRhaW5pbmcgdGhlIGN1cnJlbnQgdGltZXN0YW1wXG4gKiBAcGFyYW0ge1Z9IGRhdGEgLSBUaGUgZGF0YSBiZWluZyBwcm9jZXNzZWRcbiAqIEBwYXJhbSBrZXkgLSBUaGUgcHJvcGVydHkga2V5IHRvIHVwZGF0ZVxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBpbnN0YW5jZSBiZWluZyB1cGRhdGVkXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSB0aW1lc3RhbXAgaGFzIGJlZW4gc2V0XG4gKiBAZnVuY3Rpb24gdGltZXN0YW1wSGFuZGxlclxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB0aW1lc3RhbXBIYW5kbGVyPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgVixcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPih0aGlzOiBSLCBjb250ZXh0OiBDLCBkYXRhOiBWLCBrZXk6IGtleW9mIE0sIG1vZGVsOiBNKTogUHJvbWlzZTx2b2lkPiB7XG4gIChtb2RlbCBhcyBhbnkpW2tleV0gPSBjb250ZXh0LnRpbWVzdGFtcDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQXV0b21hdGljYWxseSBtYW5hZ2VzIHRpbWVzdGFtcCBwcm9wZXJ0aWVzIGZvciB0cmFja2luZyBjcmVhdGlvbiBhbmQgdXBkYXRlIHRpbWVzLlxuICogQHN1bW1hcnkgTWFya3MgdGhlIHByb3BlcnR5IGFzIGEgdGltZXN0YW1wLCBtYWtpbmcgaXQgcmVxdWlyZWQgYW5kIGVuc3VyaW5nIGl0J3MgYSB2YWxpZCBkYXRlLiBUaGUgcHJvcGVydHkgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHVwZGF0ZWQgd2l0aCB0aGUgY3VycmVudCB0aW1lc3RhbXAgZHVyaW5nIHNwZWNpZmllZCBvcGVyYXRpb25zLlxuICpcbiAqIERhdGUgRm9ybWF0OlxuICpcbiAqIDxwcmU+XG4gKiAgICAgIFVzaW5nIHNpbWlsYXIgZm9ybWF0dGluZyBhcyBNb21lbnQuanMsIENsYXNzIERhdGVUaW1lRm9ybWF0dGVyIChKYXZhKSwgYW5kIENsYXNzIFNpbXBsZURhdGVGb3JtYXQgKEphdmEpLFxuICogICAgICBJIGltcGxlbWVudGVkIGEgY29tcHJlaGVuc2l2ZSBzb2x1dGlvbiBmb3JtYXREYXRlKGRhdGUsIHBhdHRlcm5TdHIpIHdoZXJlIHRoZSBjb2RlIGlzIGVhc3kgdG8gcmVhZCBhbmQgbW9kaWZ5LlxuICogICAgICBZb3UgY2FuIGRpc3BsYXkgZGF0ZSwgdGltZSwgQU0vUE0sIGV0Yy5cbiAqXG4gKiAgICAgIERhdGUgYW5kIFRpbWUgUGF0dGVybnNcbiAqICAgICAgeXkgPSAyLWRpZ2l0IHllYXI7IHl5eXkgPSBmdWxsIHllYXJcbiAqICAgICAgTSA9IGRpZ2l0IG1vbnRoOyBNTSA9IDItZGlnaXQgbW9udGg7IE1NTSA9IHNob3J0IG1vbnRoIG5hbWU7IE1NTU0gPSBmdWxsIG1vbnRoIG5hbWVcbiAqICAgICAgRUVFRSA9IGZ1bGwgd2Vla2RheSBuYW1lOyBFRUUgPSBzaG9ydCB3ZWVrZGF5IG5hbWVcbiAqICAgICAgZCA9IGRpZ2l0IGRheTsgZGQgPSAyLWRpZ2l0IGRheVxuICogICAgICBoID0gaG91cnMgYW0vcG07IGhoID0gMi1kaWdpdCBob3VycyBhbS9wbTsgSCA9IGhvdXJzOyBISCA9IDItZGlnaXQgaG91cnNcbiAqICAgICAgbSA9IG1pbnV0ZXM7IG1tID0gMi1kaWdpdCBtaW51dGVzOyBhYWEgPSBBTS9QTVxuICogICAgICBzID0gc2Vjb25kczsgc3MgPSAyLWRpZ2l0IHNlY29uZHNcbiAqICAgICAgUyA9IG1pbGlzZWNvbmRzXG4gKiA8L3ByZT5cbiAqXG4gKiBAcGFyYW0ge09wZXJhdGlvbktleXNbXX0gb3BlcmF0aW9uIC0gVGhlIG9wZXJhdGlvbnMgdG8gYWN0IG9uLiBEZWZhdWx0cyB0byB7QGxpbmsgREJPcGVyYXRpb25zLkNSRUFURV9VUERBVEV9XG4gKiBAcGFyYW0ge3N0cmluZ30gW2Zvcm1hdF0gLSBUaGUgdGltZXN0YW1wIGZvcm1hdC4gRGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVH1cbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciBmdW5jdGlvbiB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiB0aW1lc3RhbXBcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAqICAgcGFydGljaXBhbnQgVCBhcyBUaW1lc3RhbXBEZWNvcmF0b3JcbiAqICAgcGFydGljaXBhbnQgViBhcyBWYWxpZGF0b3JcbiAqXG4gKiAgIEMtPj5NOiBDcmVhdGUvVXBkYXRlIG1vZGVsXG4gKiAgIE0tPj5UOiBQcm9jZXNzIHRpbWVzdGFtcCBwcm9wZXJ0eVxuICogICBULT4+TTogQXBwbHkgcmVxdWlyZWQgdmFsaWRhdGlvblxuICogICBULT4+TTogQXBwbHkgZGF0ZSBmb3JtYXQgdmFsaWRhdGlvblxuICpcbiAqICAgYWx0IFVwZGF0ZSBvcGVyYXRpb25cbiAqICAgICBULT4+VjogUmVnaXN0ZXIgdGltZXN0YW1wIHZhbGlkYXRvclxuICogICAgIFYtPj5NOiBWYWxpZGF0ZSB0aW1lc3RhbXAgaXMgbmV3ZXJcbiAqICAgZW5kXG4gKlxuICogICBULT4+TTogU2V0IGN1cnJlbnQgdGltZXN0YW1wXG4gKiAgIE0tPj5DOiBSZXR1cm4gdXBkYXRlZCBtb2RlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gdGltZXN0YW1wKFxuICBvcGVyYXRpb246IE9wZXJhdGlvbktleXNbXSA9IERCT3BlcmF0aW9ucy5DUkVBVEVfVVBEQVRFIGFzIHVua25vd24gYXMgT3BlcmF0aW9uS2V5c1tdLFxuICBmb3JtYXQ6IHN0cmluZyA9IERFRkFVTFRfVElNRVNUQU1QX0ZPUk1BVFxuKSB7XG4gIGNvbnN0IGtleSA9IFZhbGlkYXRpb24udXBkYXRlS2V5KERCS2V5cy5USU1FU1RBTVApO1xuXG4gIGNvbnN0IGRlY29yYXRvcnM6IGFueVtdID0gW1xuICAgIGRhdGUoZm9ybWF0LCBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlRJTUVTVEFNUC5EQVRFKSxcbiAgICByZXF1aXJlZChERUZBVUxUX0VSUk9SX01FU1NBR0VTLlRJTUVTVEFNUC5SRVFVSVJFRCksXG4gICAgb24ob3BlcmF0aW9uLCB0aW1lc3RhbXBIYW5kbGVyKSxcbiAgXTtcblxuICBpZiAob3BlcmF0aW9uLmluZGV4T2YoT3BlcmF0aW9uS2V5cy5VUERBVEUpICE9PSAtMSlcbiAgICBkZWNvcmF0b3JzLnB1c2goXG4gICAgICBwcm9wTWV0YWRhdGEoVmFsaWRhdGlvbi51cGRhdGVLZXkoREJLZXlzLlRJTUVTVEFNUCksIHtcbiAgICAgICAgbWVzc2FnZTogREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5USU1FU1RBTVAuSU5WQUxJRCxcbiAgICAgIH0pXG4gICAgKTtcbiAgcmV0dXJuIERlY29yYXRpb24uZm9yKGtleSlcbiAgICAuZGVmaW5lKC4uLmRlY29yYXRvcnMpXG4gICAgLmFwcGx5KCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIEhhbmRsZXIgZnVuY3Rpb24gdGhhdCBzZXJpYWxpemVzIGEgcHJvcGVydHkgdG8gSlNPTiBzdHJpbmcgZHVyaW5nIGNyZWF0ZSBhbmQgdXBkYXRlIG9wZXJhdGlvbnMuXG4gKiBAc3VtbWFyeSBDb252ZXJ0cyBhIGNvbXBsZXggb2JqZWN0IHByb3BlcnR5IHRvIGEgSlNPTiBzdHJpbmcgYmVmb3JlIHN0b3JpbmcgaXQgaW4gdGhlIGRhdGFiYXNlLlxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnlcbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIGRhdGEgdHlwZSBmb3IgdGhlIG9wZXJhdGlvblxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGVcbiAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSByZXBvc2l0b3J5IGNvbnRleHRcbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSBkYXRhIGJlaW5nIHByb2Nlc3NlZFxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2VyaWFsaXplXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIGJlaW5nIHByb2Nlc3NlZFxuICogQHJldHVybiB7UHJvbWlzZTx2b2lkPn0gQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgcHJvcGVydHkgaGFzIGJlZW4gc2VyaWFsaXplZFxuICogQGZ1bmN0aW9uIHNlcmlhbGl6ZU9uQ3JlYXRlVXBkYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNlcmlhbGl6ZU9uQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgVixcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPih0aGlzOiBSLCBjb250ZXh0OiBDLCBkYXRhOiBWLCBrZXk6IGtleW9mIE0sIG1vZGVsOiBNKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmICghbW9kZWxba2V5XSkgcmV0dXJuO1xuICB0cnkge1xuICAgIG1vZGVsW2tleV0gPSBKU09OLnN0cmluZ2lmeShtb2RlbFtrZXldKSBhcyBNW2tleW9mIE1dO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIHNlcmlhbGl6ZSAke2tleS50b1N0cmluZygpfSBwcm9wZXJ0eSBvZiBtb2RlbCAke21vZGVsLmNvbnN0cnVjdG9yLm5hbWV9OiBlYFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFuZGxlciBmdW5jdGlvbiB0aGF0IGRlc2VyaWFsaXplcyBhIHByb3BlcnR5IGZyb20gSlNPTiBzdHJpbmcgYWZ0ZXIgZGF0YWJhc2Ugb3BlcmF0aW9ucy5cbiAqIEBzdW1tYXJ5IENvbnZlcnRzIGEgSlNPTiBzdHJpbmcgcHJvcGVydHkgYmFjayB0byBpdHMgb3JpZ2luYWwgY29tcGxleCBvYmplY3QgZm9ybSBhZnRlciByZXRyaWV2aW5nIGl0IGZyb20gdGhlIGRhdGFiYXNlLlxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlcG9zaXRvcnkgdHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnlcbiAqIEB0ZW1wbGF0ZSBWIC0gVGhlIGRhdGEgdHlwZSBmb3IgdGhlIG9wZXJhdGlvblxuICogQHRlbXBsYXRlIEYgLSBUaGUgcmVwb3NpdG9yeSBmbGFncyB0eXBlXG4gKiBAdGVtcGxhdGUgQyAtIFRoZSBjb250ZXh0IHR5cGVcbiAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSByZXBvc2l0b3J5IGNvbnRleHRcbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIFRoZSBkYXRhIGJlaW5nIHByb2Nlc3NlZFxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gZGVzZXJpYWxpemVcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2UgYmVpbmcgcHJvY2Vzc2VkXG4gKiBAcmV0dXJuIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBwcm9wZXJ0eSBoYXMgYmVlbiBkZXNlcmlhbGl6ZWRcbiAqIEBmdW5jdGlvbiBzZXJpYWxpemVBZnRlckFsbFxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXJpYWxpemVBZnRlckFsbDxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoIW1vZGVsW2tleV0pIHJldHVybjtcbiAgaWYgKHR5cGVvZiBtb2RlbFtrZXldICE9PSBcInN0cmluZ1wiKSByZXR1cm47XG5cbiAgdHJ5IHtcbiAgICBtb2RlbFtrZXldID0gSlNPTi5wYXJzZShtb2RlbFtrZXldKTtcbiAgfSBjYXRjaCAoZTogdW5rbm93bikge1xuICAgIHRocm93IG5ldyBTZXJpYWxpemF0aW9uRXJyb3IoXG4gICAgICBgRmFpbGVkIHRvIGRlc2VyaWFsaXplICR7a2V5LnRvU3RyaW5nKCl9IHByb3BlcnR5IG9mIG1vZGVsICR7bW9kZWwuY29uc3RydWN0b3IubmFtZX06ICR7ZX1gXG4gICAgKTtcbiAgfVxufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBFbmFibGVzIGF1dG9tYXRpYyBKU09OIHNlcmlhbGl6YXRpb24gYW5kIGRlc2VyaWFsaXphdGlvbiBmb3IgY29tcGxleCBvYmplY3QgcHJvcGVydGllcy5cbiAqIEBzdW1tYXJ5IERlY29yYXRvciB0aGF0IGF1dG9tYXRpY2FsbHkgY29udmVydHMgY29tcGxleCBvYmplY3RzIHRvIEpTT04gc3RyaW5ncyBiZWZvcmUgc3RvcmluZyBpbiB0aGUgZGF0YWJhc2UgYW5kIGJhY2sgdG8gb2JqZWN0cyB3aGVuIHJldHJpZXZpbmcgdGhlbS5cbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciBmdW5jdGlvbiB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBzZXJpYWxpemVcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eSBEZWNvcmF0b3JzXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IEMgYXMgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IE0gYXMgTW9kZWxcbiAqICAgcGFydGljaXBhbnQgUyBhcyBTZXJpYWxpemVEZWNvcmF0b3JcbiAqICAgcGFydGljaXBhbnQgREIgYXMgRGF0YWJhc2VcbiAqXG4gKiAgIE5vdGUgb3ZlciBDLERCOiBDcmVhdGUvVXBkYXRlIEZsb3dcbiAqICAgQy0+Pk06IFNldCBjb21wbGV4IG9iamVjdCBwcm9wZXJ0eVxuICogICBNLT4+UzogUHJvY2VzcyBwcm9wZXJ0eSAoY3JlYXRlL3VwZGF0ZSlcbiAqICAgUy0+Pk06IENvbnZlcnQgdG8gSlNPTiBzdHJpbmdcbiAqICAgTS0+PkRCOiBTdG9yZSBzZXJpYWxpemVkIGRhdGFcbiAqXG4gKiAgIE5vdGUgb3ZlciBDLERCOiBSZXRyaWV2YWwgRmxvd1xuICogICBDLT4+TTogUmVxdWVzdCBtb2RlbFxuICogICBNLT4+REI6IEZldGNoIGRhdGFcbiAqICAgREItPj5NOiBSZXR1cm4gd2l0aCBzZXJpYWxpemVkIHByb3BlcnR5XG4gKiAgIE0tPj5TOiBQcm9jZXNzIHByb3BlcnR5IChhZnRlciBhbGwgb3BzKVxuICogICBTLT4+TTogUGFyc2UgSlNPTiBiYWNrIHRvIG9iamVjdFxuICogICBNLT4+QzogUmV0dXJuIG1vZGVsIHdpdGggZGVzZXJpYWxpemVkIHByb3BlcnR5XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemUoKSB7XG4gIHJldHVybiBhcHBseShcbiAgICBvbkNyZWF0ZVVwZGF0ZShzZXJpYWxpemVPbkNyZWF0ZVVwZGF0ZSksXG4gICAgYWZ0ZXIoREJPcGVyYXRpb25zLkFMTCwgc2VyaWFsaXplQWZ0ZXJBbGwpLFxuICAgIHR5cGUoW1N0cmluZy5uYW1lLCBPYmplY3QubmFtZV0pLFxuICAgIG1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5TRVJJQUxJWkUpLCB7fSlcbiAgKTtcbn1cbiIsImltcG9ydCB7IHByb3BNZXRhZGF0YSwgcmVxdWlyZWQgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyByZWFkb25seSB9IGZyb20gXCIuLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBEQktleXMgfSBmcm9tIFwiLi4vbW9kZWwvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IGFwcGx5IH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERlY29yYXRvciB0aGF0IG1hcmtzIGEgcHJvcGVydHkgYXMgYW4gSUQgZmllbGRcbiAqIEBzdW1tYXJ5IENyZWF0ZXMgYSBjb21wb3NpdGUgZGVjb3JhdG9yIHRoYXQgbWFya3MgYSBwcm9wZXJ0eSBhcyByZXF1aXJlZCwgcmVhZG9ubHksIGFuZCBhcyB0aGUgSUQgZmllbGQgZm9yIGRhdGFiYXNlIG9wZXJhdGlvbnNcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBpZFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlkKCkge1xuICByZXR1cm4gYXBwbHkoXG4gICAgcmVxdWlyZWQoKSxcbiAgICByZWFkb25seSgpLFxuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuSUQpLCB7fSlcbiAgKTtcbn1cbiIsImltcG9ydCB7XG4gIENvbmRpdGlvbmFsQXN5bmMsXG4gIERlY29yYXRvck1ldGFkYXRhQXN5bmMsXG4gIGdldFZhbGlkYXRpb25EZWNvcmF0b3JzLFxuICBNb2RlbCxcbiAgTW9kZWxDb25kaXRpb25hbEFzeW5jLFxuICBNb2RlbEVycm9yRGVmaW5pdGlvbixcbiAgTW9kZWxFcnJvcnMsXG4gIE1vZGVsS2V5cyxcbiAgdG9Db25kaXRpb25hbFByb21pc2UsXG4gIFZhbGlkYXRpb24sXG4gIFZhbGlkYXRpb25LZXlzLFxuICBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBVcGRhdGVWYWxpZGF0aW9uS2V5cywgVXBkYXRlVmFsaWRhdG9yIH0gZnJvbSBcIi4uL3ZhbGlkYXRpb25cIjtcbmltcG9ydCB7IGZpbmRNb2RlbElkIH0gZnJvbSBcIi4uL2lkZW50aXR5XCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uXG4gKiBSZXRyaWV2ZXMgdmFsaWRhdGlvbiBkZWNvcmF0b3IgZGVmaW5pdGlvbnMgZnJvbSBhIG1vZGVsIGZvciB1cGRhdGUgb3BlcmF0aW9ucywgaW5jbHVkaW5nXG4gKiBzdXBwb3J0IGZvciBzcGVjaWFsIGhhbmRsaW5nIG9mIGxpc3QgZGVjb3JhdG9ycy5cbiAqXG4gKiBAc3VtbWFyeVxuICogSXRlcmF0ZXMgb3ZlciB0aGUgbW9kZWwncyBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzIGFuZCBmaWx0ZXJzIG91dCB0aG9zZSBzcGVjaWZpZWQgaW4gdGhlXG4gKiBgcHJvcHNUb0lnbm9yZWAgYXJyYXkuIEZvciBlYWNoIHJlbWFpbmluZyBwcm9wZXJ0eSwgcmV0cmlldmVzIHZhbGlkYXRpb24gZGVjb3JhdG9ycyBzcGVjaWZpY1xuICogdG8gdXBkYXRlIG9wZXJhdGlvbnMgdXNpbmcgdGhlIGBVcGRhdGVWYWxpZGF0aW9uS2V5cy5SRUZMRUNUYCBrZXkuIEFkZGl0aW9uYWxseSwgaXQgZXhwbGljaXRseVxuICogY2hlY2tzIGZvciBhbmQgYXBwZW5kcyBhbnkgYExJU1RgIHR5cGUgZGVjb3JhdG9ycyB0byBlbnN1cmUgcHJvcGVyIHZhbGlkYXRpb24gb2YgY29sbGVjdGlvbiB0eXBlcy5cbiAqXG4gKiBAdGVtcGxhdGUgTSAtIEEgZ2VuZXJpYyBwYXJhbWV0ZXIgZXh0ZW5kaW5nIHRoZSBgTW9kZWxgIGNsYXNzLCByZXByZXNlbnRpbmcgdGhlIG1vZGVsIHR5cGUgYmVpbmcgaW5zcGVjdGVkLlxuICpcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgaW5zdGFuY2Ugd2hvc2UgcHJvcGVydGllcyBhcmUgYmVpbmcgaW5zcGVjdGVkIGZvciB1cGRhdGUtcmVsYXRlZCB2YWxpZGF0aW9ucy5cbiAqIEBwYXJhbSB7c3RyaW5nW119IHByb3BzVG9JZ25vcmUgLSBBIGxpc3Qgb2YgcHJvcGVydHkgbmFtZXMgdG8gZXhjbHVkZSBmcm9tIHRoZSB2YWxpZGF0aW9uIGRlY29yYXRvciByZXRyaWV2YWwgcHJvY2Vzcy5cbiAqXG4gKiBAcmV0dXJuIHtWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uW119IEFuIGFycmF5IG9mIHZhbGlkYXRpb24gZGVjb3JhdG9yIGRlZmluaXRpb25zLCBpbmNsdWRpbmcgYm90aFxuICogdXBkYXRlLXNwZWNpZmljIGFuZCBsaXN0LXR5cGUgZGVjb3JhdG9ycywgZXhjbHVkaW5nIHRob3NlIGZvciBpZ25vcmVkIHByb3BlcnRpZXMuXG4gKlxuICogQGZ1bmN0aW9uIGdldFZhbGlkYXRhYmxlVXBkYXRlUHJvcHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFZhbGlkYXRhYmxlVXBkYXRlUHJvcHM8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE0sXG4gIHByb3BzVG9JZ25vcmU6IHN0cmluZ1tdXG4pOiBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uW10ge1xuICBjb25zdCBkZWNvcmF0ZWRQcm9wZXJ0aWVzOiBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uW10gPSBbXTtcbiAgZm9yIChjb25zdCBwcm9wIGluIG1vZGVsKSB7XG4gICAgaWYgKFxuICAgICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZGVsLCBwcm9wKSAmJlxuICAgICAgIXByb3BzVG9JZ25vcmUuaW5jbHVkZXMocHJvcClcbiAgICApIHtcbiAgICAgIGNvbnN0IHZhbGlkYXRpb25Qcm9wZXJ0eURlZmluaXRpb24gPSBnZXRWYWxpZGF0aW9uRGVjb3JhdG9ycyhcbiAgICAgICAgbW9kZWwsXG4gICAgICAgIHByb3AsXG4gICAgICAgIFVwZGF0ZVZhbGlkYXRpb25LZXlzLlJFRkxFQ1RcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGxpc3REZWNvcmF0b3IgPSBnZXRWYWxpZGF0aW9uRGVjb3JhdG9ycyhcbiAgICAgICAgbW9kZWwsXG4gICAgICAgIHByb3BcbiAgICAgICkuZGVjb3JhdG9ycy5maW5kKCh7IGtleSB9KSA9PiBrZXkgPT09IFZhbGlkYXRpb25LZXlzLkxJU1QpO1xuXG4gICAgICBpZiAobGlzdERlY29yYXRvcilcbiAgICAgICAgdmFsaWRhdGlvblByb3BlcnR5RGVmaW5pdGlvbi5kZWNvcmF0b3JzLnB1c2gobGlzdERlY29yYXRvcik7XG5cbiAgICAgIGRlY29yYXRlZFByb3BlcnRpZXMucHVzaCh2YWxpZGF0aW9uUHJvcGVydHlEZWZpbml0aW9uKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZGVjb3JhdGVkUHJvcGVydGllcztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRGVjb3JhdG9yPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIEFzeW5jIGV4dGVuZHMgYm9vbGVhbiA9IGZhbHNlLFxuPihcbiAgbmV3TW9kZWw6IE0sXG4gIG9sZE1vZGVsOiBNLFxuICBwcm9wOiBzdHJpbmcsXG4gIGRlY29yYXRvcjogRGVjb3JhdG9yTWV0YWRhdGFBc3luYyxcbiAgYXN5bmM/OiBBc3luY1xuKTogQ29uZGl0aW9uYWxBc3luYzxBc3luYywgc3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IHZhbGlkYXRvcjogVXBkYXRlVmFsaWRhdG9yID0gVmFsaWRhdGlvbi5nZXQoXG4gICAgZGVjb3JhdG9yLmtleVxuICApIGFzIFVwZGF0ZVZhbGlkYXRvcjtcblxuICBpZiAoIXZhbGlkYXRvcikge1xuICAgIHRocm93IG5ldyBFcnJvcihgTWlzc2luZyB2YWxpZGF0b3IgZm9yICR7ZGVjb3JhdG9yLmtleX1gKTtcbiAgfVxuXG4gIC8vIFNraXAgdmFsaWRhdG9ycyB0aGF0IGFyZW4ndCBVcGRhdGVWYWxpZGF0b3JzXG4gIGlmICghdmFsaWRhdG9yLnVwZGF0ZUhhc0Vycm9ycykgcmV0dXJuIHRvQ29uZGl0aW9uYWxQcm9taXNlKHVuZGVmaW5lZCwgYXN5bmMpO1xuXG4gIC8vIHNraXAgYXN5bmMgZGVjb3JhdG9ycyBpZiB2YWxpZGF0ZURlY29yYXRvcnMgaXMgY2FsbGVkIHN5bmNocm9ub3VzbHkgKGFzeW5jID0gZmFsc2UpXG4gIGlmICghYXN5bmMgJiYgZGVjb3JhdG9yLnByb3BzLmFzeW5jKVxuICAgIHJldHVybiB0b0NvbmRpdGlvbmFsUHJvbWlzZSh1bmRlZmluZWQsIGFzeW5jKTtcblxuICBjb25zdCBkZWNvcmF0b3JQcm9wcyA9IE9iamVjdC52YWx1ZXMoZGVjb3JhdG9yLnByb3BzKSB8fCB7fTtcblxuICAvLyBjb25zdCBjb250ZXh0ID0gUGF0aFByb3h5RW5naW5lLmNyZWF0ZShvYmosIHtcbiAgLy8gICBpZ25vcmVVbmRlZmluZWQ6IHRydWUsXG4gIC8vICAgaWdub3JlTnVsbDogdHJ1ZSxcbiAgLy8gfSk7XG5cbiAgY29uc3QgbWF5YmVFcnJvciA9IHZhbGlkYXRvci51cGRhdGVIYXNFcnJvcnMoXG4gICAgKG5ld01vZGVsIGFzIGFueSlbcHJvcF0sXG4gICAgKG9sZE1vZGVsIGFzIGFueSlbcHJvcF0sXG4gICAgLi4uZGVjb3JhdG9yUHJvcHNcbiAgKTtcblxuICByZXR1cm4gdG9Db25kaXRpb25hbFByb21pc2UobWF5YmVFcnJvciwgYXN5bmMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVEZWNvcmF0b3JzPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIEFzeW5jIGV4dGVuZHMgYm9vbGVhbiA9IGZhbHNlLFxuPihcbiAgbmV3TW9kZWw6IE0sXG4gIG9sZE1vZGVsOiBNLFxuICBwcm9wOiBzdHJpbmcsXG4gIGRlY29yYXRvcnM6IERlY29yYXRvck1ldGFkYXRhQXN5bmNbXSxcbiAgYXN5bmM/OiBBc3luY1xuKTogQ29uZGl0aW9uYWxBc3luYzxBc3luYywgUmVjb3JkPHN0cmluZywgc3RyaW5nPj4gfCB1bmRlZmluZWQge1xuICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IFByb21pc2U8c3RyaW5nPj4gPSB7fTtcblxuICBmb3IgKGNvbnN0IGRlY29yYXRvciBvZiBkZWNvcmF0b3JzKSB7XG4gICAgLy8gc2tpcCBhc3luYyBkZWNvcmF0b3JzIGlmIHZhbGlkYXRlRGVjb3JhdG9ycyBpcyBjYWxsZWQgc3luY2hyb25vdXNseSAoYXN5bmMgPSBmYWxzZSlcbiAgICBpZiAoIWFzeW5jICYmIGRlY29yYXRvci5wcm9wcy5hc3luYykgY29udGludWU7XG5cbiAgICBsZXQgdmFsaWRhdGlvbkVycm9ycyA9IHZhbGlkYXRlRGVjb3JhdG9yKFxuICAgICAgbmV3TW9kZWwsXG4gICAgICBvbGRNb2RlbCxcbiAgICAgIHByb3AsXG4gICAgICBkZWNvcmF0b3IsXG4gICAgICBhc3luY1xuICAgICk7XG5cbiAgICAvKlxuICAgIElmIHRoZSBkZWNvcmF0b3IgaXMgYSBsaXN0LCBlYWNoIGVsZW1lbnQgbXVzdCBiZSBjaGVja2VkLlxuICAgIFdoZW4gJ2FzeW5jJyBpcyB0cnVlLCB0aGUgJ2Vycicgd2lsbCBhbHdheXMgYmUgYSBwZW5kaW5nIHByb21pc2UgaW5pdGlhbGx5LFxuICAgIHNvIHRoZSAnIWVycicgY2hlY2sgd2lsbCBldmFsdWF0ZSB0byBmYWxzZSAoZXZlbiBpZiB0aGUgcHJvbWlzZSBsYXRlciByZXNvbHZlcyB3aXRoIG5vIGVycm9ycylcbiAgICAqL1xuICAgIGlmIChkZWNvcmF0b3Iua2V5ID09PSBWYWxpZGF0aW9uS2V5cy5MSVNUICYmICghdmFsaWRhdGlvbkVycm9ycyB8fCBhc3luYykpIHtcbiAgICAgIGNvbnN0IG5ld1Byb3BWYWx1ZSA9IChuZXdNb2RlbCBhcyBhbnkpW3Byb3BdO1xuICAgICAgY29uc3Qgb2xkUHJvcFZhbHVlID0gKG9sZE1vZGVsIGFzIGFueSlbcHJvcF07XG5cbiAgICAgIGNvbnN0IG5ld1ZhbHVlcyA9XG4gICAgICAgIG5ld1Byb3BWYWx1ZSBpbnN0YW5jZW9mIFNldCA/IFsuLi5uZXdQcm9wVmFsdWVdIDogbmV3UHJvcFZhbHVlO1xuICAgICAgY29uc3Qgb2xkVmFsdWVzID1cbiAgICAgICAgb2xkUHJvcFZhbHVlIGluc3RhbmNlb2YgU2V0ID8gWy4uLm9sZFByb3BWYWx1ZV0gOiBvbGRQcm9wVmFsdWU7XG5cbiAgICAgIGlmIChuZXdWYWx1ZXMgJiYgbmV3VmFsdWVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3QgdHlwZXMgPVxuICAgICAgICAgIGRlY29yYXRvci5wcm9wcy5jbGFzcyB8fFxuICAgICAgICAgIGRlY29yYXRvci5wcm9wcy5jbGF6eiB8fFxuICAgICAgICAgIGRlY29yYXRvci5wcm9wcy5jdXN0b21UeXBlcztcblxuICAgICAgICBjb25zdCBhbGxvd2VkVHlwZXMgPSBbdHlwZXNdLmZsYXQoKS5tYXAoKHQpID0+IFN0cmluZyh0KS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgY29uc3QgZXJycyA9IG5ld1ZhbHVlcy5tYXAoKGNoaWxkVmFsdWU6IGFueSkgPT4ge1xuICAgICAgICAgIC8vIGZpbmQgYnkgaWQgc28gdGhlIGxpc3QgZWxlbWVudHMgb3JkZXIgZG9lc24ndCBtYXR0ZXJcbiAgICAgICAgICBjb25zdCBpZCA9IGZpbmRNb2RlbElkKGNoaWxkVmFsdWUgYXMgYW55LCB0cnVlKTtcbiAgICAgICAgICBpZiAoIWlkKSByZXR1cm4gXCJGYWlsZWQgdG8gZmluZCBtb2RlbCBpZFwiO1xuXG4gICAgICAgICAgY29uc3Qgb2xkTW9kZWwgPSBvbGRWYWx1ZXMuZmluZChcbiAgICAgICAgICAgIChlbDogYW55KSA9PiBpZCA9PT0gZmluZE1vZGVsSWQoZWwsIHRydWUpXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmIChNb2RlbC5pc01vZGVsKGNoaWxkVmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gY2hpbGRWYWx1ZS5oYXNFcnJvcnMob2xkTW9kZWwpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBhbGxvd2VkVHlwZXMuaW5jbHVkZXModHlwZW9mIGNoaWxkVmFsdWUpXG4gICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgOiBcIlZhbHVlIGhhcyBubyB2YWxpZGF0YWJsZSB0eXBlXCI7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChhc3luYykge1xuICAgICAgICAgIHZhbGlkYXRpb25FcnJvcnMgPSBQcm9taXNlLmFsbChlcnJzKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGFsbEVtcHR5ID0gcmVzdWx0LmV2ZXJ5KChyKSA9PiAhcik7XG4gICAgICAgICAgICByZXR1cm4gYWxsRW1wdHkgPyB1bmRlZmluZWQgOiByZXN1bHQ7XG4gICAgICAgICAgfSkgYXMgYW55O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IGFsbEVtcHR5ID0gZXJycy5ldmVyeSgocjogc3RyaW5nIHwgdW5kZWZpbmVkKSA9PiAhcik7XG4gICAgICAgICAgdmFsaWRhdGlvbkVycm9ycyA9IGVycnMubGVuZ3RoID4gMCAmJiAhYWxsRW1wdHkgPyBlcnJzIDogdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHZhbGlkYXRpb25FcnJvcnMpIChyZXN1bHQgYXMgYW55KVtkZWNvcmF0b3Iua2V5XSA9IHZhbGlkYXRpb25FcnJvcnM7XG4gIH1cblxuICBpZiAoIWFzeW5jKVxuICAgIHJldHVybiBPYmplY3Qua2V5cyhyZXN1bHQpLmxlbmd0aCA+IDAgPyAocmVzdWx0IGFzIGFueSkgOiB1bmRlZmluZWQ7XG5cbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKHJlc3VsdCk7XG4gIGNvbnN0IHByb21pc2VzID0gT2JqZWN0LnZhbHVlcyhyZXN1bHQpIGFzIFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPltdO1xuICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKHJlc29sdmVkVmFsdWVzKSA9PiB7XG4gICAgY29uc3QgcmVzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXNvbHZlZFZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgdmFsID0gcmVzb2x2ZWRWYWx1ZXNbaV07XG4gICAgICBpZiAodmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmVzW2tleXNbaV1dID0gdmFsO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocmVzKS5sZW5ndGggPiAwID8gcmVzIDogdW5kZWZpbmVkO1xuICB9KSBhcyBhbnk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRlcyBjaGFuZ2VzIGJldHdlZW4gdHdvIG1vZGVsIHZlcnNpb25zXG4gKiBAc3VtbWFyeSBDb21wYXJlcyBhbiBvbGQgYW5kIG5ldyBtb2RlbCB2ZXJzaW9uIHRvIHZhbGlkYXRlIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAcGFyYW0ge019IG9sZE1vZGVsIC0gVGhlIG9yaWdpbmFsIG1vZGVsIHZlcnNpb25cbiAqIEBwYXJhbSB7TX0gbmV3TW9kZWwgLSBUaGUgdXBkYXRlZCBtb2RlbCB2ZXJzaW9uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFzeW5jIC0gQSBmbGFnIGluZGljYXRpbmcgd2hldGhlciB2YWxpZGF0aW9uIHNob3VsZCBiZSBhc3luY2hyb25vdXMuXG4gKiBAcGFyYW0gey4uLnN0cmluZ1tdfSBleGNlcHRpb25zIC0gUHJvcGVydGllcyB0byBleGNsdWRlIGZyb20gdmFsaWRhdGlvblxuICogQHJldHVybiB7TW9kZWxFcnJvckRlZmluaXRpb258dW5kZWZpbmVkfSBFcnJvciBkZWZpbml0aW9uIGlmIHZhbGlkYXRpb24gZmFpbHMsIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAqIEBmdW5jdGlvbiB2YWxpZGF0ZUNvbXBhcmVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgdmFsaWRhdGVDb21wYXJlXG4gKiAgIHBhcnRpY2lwYW50IFJlZmxlY3Rpb25cbiAqICAgcGFydGljaXBhbnQgVmFsaWRhdGlvblxuICpcbiAqICAgQ2FsbGVyLT4+dmFsaWRhdGVDb21wYXJlOiBvbGRNb2RlbCwgbmV3TW9kZWwsIGV4Y2VwdGlvbnNcbiAqICAgdmFsaWRhdGVDb21wYXJlLT4+UmVmbGVjdGlvbjogZ2V0IGRlY29yYXRlZCBwcm9wZXJ0aWVzXG4gKiAgIFJlZmxlY3Rpb24tLT4+dmFsaWRhdGVDb21wYXJlOiBwcm9wZXJ0eSBkZWNvcmF0b3JzXG4gKiAgIGxvb3AgRm9yIGVhY2ggZGVjb3JhdGVkIHByb3BlcnR5XG4gKiAgICAgdmFsaWRhdGVDb21wYXJlLT4+VmFsaWRhdGlvbjogZ2V0IHZhbGlkYXRvclxuICogICAgIFZhbGlkYXRpb24tLT4+dmFsaWRhdGVDb21wYXJlOiB2YWxpZGF0b3JcbiAqICAgICB2YWxpZGF0ZUNvbXBhcmUtPj52YWxpZGF0ZUNvbXBhcmU6IHZhbGlkYXRlIHByb3BlcnR5IHVwZGF0ZVxuICogICBlbmRcbiAqICAgbG9vcCBGb3IgbmVzdGVkIG1vZGVsc1xuICogICAgIHZhbGlkYXRlQ29tcGFyZS0+PnZhbGlkYXRlQ29tcGFyZTogdmFsaWRhdGUgbmVzdGVkIG1vZGVsc1xuICogICBlbmRcbiAqICAgdmFsaWRhdGVDb21wYXJlLS0+PkNhbGxlcjogdmFsaWRhdGlvbiBlcnJvcnMgb3IgdW5kZWZpbmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUNvbXBhcmU8TSBleHRlbmRzIE1vZGVsPGFueT4+KFxuICBvbGRNb2RlbDogTSxcbiAgbmV3TW9kZWw6IE0sXG4gIGFzeW5jOiBib29sZWFuLFxuICAuLi5leGNlcHRpb25zOiBzdHJpbmdbXVxuKTogTW9kZWxDb25kaXRpb25hbEFzeW5jPE0+IHtcbiAgY29uc3QgZGVjb3JhdGVkUHJvcGVydGllczogVmFsaWRhdGlvblByb3BlcnR5RGVjb3JhdG9yRGVmaW5pdGlvbltdID1cbiAgICBnZXRWYWxpZGF0YWJsZVVwZGF0ZVByb3BzKG5ld01vZGVsLCBleGNlcHRpb25zKTtcblxuICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcblxuICBjb25zdCBuZXN0ZWRFcnJvcnM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgZm9yIChjb25zdCB7IHByb3AsIGRlY29yYXRvcnMgfSBvZiBkZWNvcmF0ZWRQcm9wZXJ0aWVzKSB7XG4gICAgY29uc3QgcHJvcEtleSA9IFN0cmluZyhwcm9wKTtcbiAgICBsZXQgcHJvcFZhbHVlID0gKG5ld01vZGVsIGFzIGFueSlbcHJvcF07XG5cbiAgICBpZiAoIWRlY29yYXRvcnM/Lmxlbmd0aCkgY29udGludWU7XG5cbiAgICAvLyBHZXQgdGhlIGRlZmF1bHQgdHlwZSB2YWxpZGF0b3JcbiAgICBjb25zdCBkZXNpZ25UeXBlRGVjID0gZGVjb3JhdG9ycy5maW5kKChkKSA9PlxuICAgICAgW01vZGVsS2V5cy5UWVBFLCBWYWxpZGF0aW9uS2V5cy5UWVBFXS5pbmNsdWRlcyhkLmtleSBhcyBhbnkpXG4gICAgKTtcbiAgICBpZiAoIWRlc2lnblR5cGVEZWMpIGNvbnRpbnVlO1xuXG4gICAgY29uc3QgZGVzaWduVHlwZSA9IGRlc2lnblR5cGVEZWMucHJvcHMubmFtZTtcblxuICAgIC8vIEhhbmRsZSBhcnJheSBvciBTZXQgdHlwZXMgYW5kIGVuZm9yY2UgdGhlIHByZXNlbmNlIG9mIEBsaXN0IGRlY29yYXRvclxuICAgIGlmIChbQXJyYXkubmFtZSwgU2V0Lm5hbWVdLmluY2x1ZGVzKGRlc2lnblR5cGUpKSB7XG4gICAgICBjb25zdCB7IGRlY29yYXRvcnMgfSA9IFJlZmxlY3Rpb24uZ2V0UHJvcGVydHlEZWNvcmF0b3JzKFxuICAgICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgICBuZXdNb2RlbCxcbiAgICAgICAgcHJvcEtleVxuICAgICAgKSBhcyB1bmtub3duIGFzIFZhbGlkYXRpb25Qcm9wZXJ0eURlY29yYXRvckRlZmluaXRpb247XG5cbiAgICAgIGlmICghZGVjb3JhdG9ycy5zb21lKChkKSA9PiBkLmtleSA9PT0gVmFsaWRhdGlvbktleXMuTElTVCkpIHtcbiAgICAgICAgcmVzdWx0W3Byb3BLZXldID0ge1xuICAgICAgICAgIFtWYWxpZGF0aW9uS2V5cy5UWVBFXTogYEFycmF5IG9yIFNldCBwcm9wZXJ0eSAnJHtwcm9wS2V5fScgcmVxdWlyZXMgYSBAbGlzdCBkZWNvcmF0b3JgLFxuICAgICAgICB9O1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBwcm9wVmFsdWUgJiZcbiAgICAgICAgIShBcnJheS5pc0FycmF5KHByb3BWYWx1ZSkgfHwgcHJvcFZhbHVlIGluc3RhbmNlb2YgU2V0KVxuICAgICAgKSB7XG4gICAgICAgIHJlc3VsdFtwcm9wS2V5XSA9IHtcbiAgICAgICAgICBbVmFsaWRhdGlvbktleXMuVFlQRV06IGBQcm9wZXJ0eSAnJHtTdHJpbmcocHJvcCl9JyBtdXN0IGJlIGVpdGhlciBhbiBhcnJheSBvciBhIFNldGAsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICAvLyBSZW1vdmUgZGVzaWduOnR5cGUgZGVjb3JhdG9yLCBzaW5jZSBAbGlzdCBkZWNvcmF0b3IgYWxyZWFkeSBlbnN1cmVzIHR5cGVcbiAgICAgIGZvciAobGV0IGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGlmIChkZWNvcmF0b3JzW2ldLmtleSA9PT0gTW9kZWxLZXlzLlRZUEUpIHtcbiAgICAgICAgICBkZWNvcmF0b3JzLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcHJvcFZhbHVlID0gcHJvcFZhbHVlIGluc3RhbmNlb2YgU2V0ID8gWy4uLnByb3BWYWx1ZV0gOiBwcm9wVmFsdWU7XG4gICAgfVxuXG4gICAgY29uc3QgcHJvcEVycm9yczogUmVjb3JkPHN0cmluZywgYW55PiA9XG4gICAgICB2YWxpZGF0ZURlY29yYXRvcnMobmV3TW9kZWwsIG9sZE1vZGVsLCBwcm9wS2V5LCBkZWNvcmF0b3JzLCBhc3luYykgfHwge307XG5cbiAgICAvLyBDaGVjayBmb3IgbmVzdGVkIHByb3BlcnRpZXMuXG4gICAgLy8gVG8gcHJldmVudCB1bm5lY2Vzc2FyeSBwcm9jZXNzaW5nLCBcInByb3BWYWx1ZVwiIG11c3QgYmUgZGVmaW5lZCBhbmQgdmFsaWRhdGFibGVcbiAgICBjb25zdCBpc0NvbnN0ciA9IE1vZGVsLmlzUHJvcGVydHlNb2RlbChuZXdNb2RlbCwgcHJvcEtleSk7XG4gICAgLy8gaWYgcHJvcFZhbHVlICE9PSB1bmRlZmluZWQsIG51bGxcbiAgICBpZiAocHJvcFZhbHVlICYmIGlzQ29uc3RyKSB7XG4gICAgICBjb25zdCBpbnN0YW5jZTogTW9kZWwgPSBwcm9wVmFsdWU7XG4gICAgICBjb25zdCBpc0ludmFsaWRNb2RlbCA9XG4gICAgICAgIHR5cGVvZiBpbnN0YW5jZSAhPT0gXCJvYmplY3RcIiB8fFxuICAgICAgICAhaW5zdGFuY2UuaGFzRXJyb3JzIHx8XG4gICAgICAgIHR5cGVvZiBpbnN0YW5jZS5oYXNFcnJvcnMgIT09IFwiZnVuY3Rpb25cIjtcblxuICAgICAgaWYgKGlzSW52YWxpZE1vZGVsKSB7XG4gICAgICAgIC8vIHByb3BFcnJvcnNbVmFsaWRhdGlvbktleXMuVFlQRV0gPVxuICAgICAgICAvLyAgIFwiTW9kZWwgc2hvdWxkIGJlIHZhbGlkYXRhYmxlIGJ1dCBpdCdzIG5vdC5cIjtcbiAgICAgICAgY29uc29sZS53YXJuKFwiTW9kZWwgc2hvdWxkIGJlIHZhbGlkYXRhYmxlIGJ1dCBpdCdzIG5vdC5cIik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXN0ZWRFcnJvcnNbcHJvcEtleV0gPSBpbnN0YW5jZS5oYXNFcnJvcnMoKG9sZE1vZGVsIGFzIGFueSlbcHJvcF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFkZCB0byB0aGUgcmVzdWx0IGlmIHdlIGhhdmUgYW55IGVycm9yc1xuICAgIC8vIEFzeW5jIG1vZGUgcmV0dXJucyBhIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byB1bmRlZmluZWQgd2hlbiBubyBlcnJvcnMgZXhpc3RcbiAgICBpZiAoT2JqZWN0LmtleXMocHJvcEVycm9ycykubGVuZ3RoID4gMCB8fCBhc3luYylcbiAgICAgIHJlc3VsdFtwcm9wS2V5XSA9IHByb3BFcnJvcnM7XG5cbiAgICAvLyBUaGVuIG1lcmdlIGFueSBuZXN0ZWQgZXJyb3JzXG4gICAgaWYgKCFhc3luYykge1xuICAgICAgT2JqZWN0LmVudHJpZXMobmVzdGVkRXJyb3JzW3Byb3BLZXldIHx8IHt9KS5mb3JFYWNoKChba2V5LCBlcnJvcl0pID0+IHtcbiAgICAgICAgaWYgKGVycm9yICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXN1bHRbYCR7cHJvcEtleX0uJHtrZXl9YF0gPSBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLy8gU3luY2hyb25vdXMgcmV0dXJuXG4gIGlmICghYXN5bmMpIHtcbiAgICByZXR1cm4gKFxuICAgICAgT2JqZWN0LmtleXMocmVzdWx0KS5sZW5ndGggPiAwXG4gICAgICAgID8gbmV3IE1vZGVsRXJyb3JEZWZpbml0aW9uKHJlc3VsdClcbiAgICAgICAgOiB1bmRlZmluZWRcbiAgICApIGFzIGFueTtcbiAgfVxuXG4gIGNvbnN0IG1lcmdlZDogYW55ID0gcmVzdWx0OyAvLyBUT0RPOiBhcHBseSBmaWx0ZXJpbmdcblxuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMobWVyZ2VkKTtcbiAgY29uc3QgcHJvbWlzZXMgPSBPYmplY3QudmFsdWVzKG1lcmdlZCk7XG4gIHJldHVybiBQcm9taXNlLmFsbFNldHRsZWQocHJvbWlzZXMpLnRoZW4oYXN5bmMgKHJlc3VsdHMpID0+IHtcbiAgICBjb25zdCByZXN1bHQ6IE1vZGVsRXJyb3JzID0ge307XG5cbiAgICBmb3IgKGNvbnN0IFtwYXJlbnRQcm9wLCBuZXN0ZWRFcnJQcm9taXNlXSBvZiBPYmplY3QuZW50cmllcyhuZXN0ZWRFcnJvcnMpKSB7XG4gICAgICBjb25zdCBuZXN0ZWRQcm9wRGVjRXJyb3JzID0gKGF3YWl0IG5lc3RlZEVyclByb21pc2UpIGFzIFJlY29yZDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICBhbnlcbiAgICAgID47XG5cbiAgICAgIGlmIChuZXN0ZWRQcm9wRGVjRXJyb3JzKVxuICAgICAgICBPYmplY3QuZW50cmllcyhuZXN0ZWRQcm9wRGVjRXJyb3JzKS5mb3JFYWNoKFxuICAgICAgICAgIChbbmVzdGVkUHJvcCwgbmVzdGVkUHJvcERlY0Vycm9yXSkgPT4ge1xuICAgICAgICAgICAgaWYgKG5lc3RlZFByb3BEZWNFcnJvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG5lc3RlZEtleSA9IFtwYXJlbnRQcm9wLCBuZXN0ZWRQcm9wXS5qb2luKFwiLlwiKTtcbiAgICAgICAgICAgICAgcmVzdWx0W25lc3RlZEtleV0gPSBuZXN0ZWRQcm9wRGVjRXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmVzdWx0cy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qga2V5ID0ga2V5c1tpXTtcbiAgICAgIGNvbnN0IHJlcyA9IHJlc3VsdHNbaV07XG5cbiAgICAgIGlmIChyZXMuc3RhdHVzID09PSBcImZ1bGZpbGxlZFwiICYmIHJlcy52YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIChyZXN1bHQgYXMgYW55KVtrZXldID0gcmVzLnZhbHVlO1xuICAgICAgfSBlbHNlIGlmIChyZXMuc3RhdHVzID09PSBcInJlamVjdGVkXCIpIHtcbiAgICAgICAgKHJlc3VsdCBhcyBhbnkpW2tleV0gPVxuICAgICAgICAgIHJlcy5yZWFzb24gaW5zdGFuY2VvZiBFcnJvclxuICAgICAgICAgICAgPyByZXMucmVhc29uLm1lc3NhZ2VcbiAgICAgICAgICAgIDogU3RyaW5nKHJlcy5yZWFzb24gfHwgXCJWYWxpZGF0aW9uIGZhaWxlZFwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocmVzdWx0KS5sZW5ndGggPiAwXG4gICAgICA/IG5ldyBNb2RlbEVycm9yRGVmaW5pdGlvbihyZXN1bHQpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfSkgYXMgYW55O1xufVxuIiwiaW1wb3J0IHsgREJLZXlzLCBEZWZhdWx0U2VwYXJhdG9yIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBhcHBseSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHtcbiAgSGFzaGluZyxcbiAgTW9kZWwsXG4gIHByb3BNZXRhZGF0YSxcbiAgdHlwZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgb25DcmVhdGUsIG9uQ3JlYXRlVXBkYXRlLCBvblVwZGF0ZSB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9lcnJvcnNcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9SZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvQ29udGV4dFwiO1xuaW1wb3J0IHsgQ3J1ZE9wZXJhdGlvbnMsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gSGFzaGVzIGEgcHJvcGVydHkgdmFsdWUgZHVyaW5nIGNyZWF0ZSBvciB1cGRhdGUgb3BlcmF0aW9uc1xuICogQHN1bW1hcnkgQ2FsbGJhY2sgZnVuY3Rpb24gdXNlZCBieSB0aGUgaGFzaCBkZWNvcmF0b3IgdG8gYXBwbHkgaGFzaGluZyB0byBhIHByb3BlcnR5IHZhbHVlXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFR5cGUgZXh0ZW5kaW5nIElSZXBvc2l0b3J5XG4gKiBAdGVtcGxhdGUgViAtIFR5cGUgZm9yIG1ldGFkYXRhXG4gKiBAdGVtcGxhdGUgRiAtIFR5cGUgZXh0ZW5kaW5nIFJlcG9zaXRvcnlGbGFnc1xuICogQHRlbXBsYXRlIEMgLSBUeXBlIGV4dGVuZGluZyBDb250ZXh0XG4gKiBAcGFyYW0ge0N9IGNvbnRleHQgLSBUaGUgb3BlcmF0aW9uIGNvbnRleHRcbiAqIEBwYXJhbSB7Vn0gZGF0YSAtIE1ldGFkYXRhIGZvciB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ga2V5IC0gVGhlIHByb3BlcnR5IGtleSB0byBoYXNoXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGJlaW5nIHByb2Nlc3NlZFxuICogQHBhcmFtIHtNfSBbb2xkTW9kZWxdIC0gVGhlIHByZXZpb3VzIG1vZGVsIHN0YXRlIChmb3IgdXBkYXRlcylcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAZnVuY3Rpb24gaGFzaE9uQ3JlYXRlVXBkYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hPbkNyZWF0ZVVwZGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYgZXh0ZW5kcyBvYmplY3QsXG4gIEYgZXh0ZW5kcyBSZXBvc2l0b3J5RmxhZ3MgPSBSZXBvc2l0b3J5RmxhZ3MsXG4gIEMgZXh0ZW5kcyBDb250ZXh0PEY+ID0gQ29udGV4dDxGPixcbj4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSwgb2xkTW9kZWw/OiBNKTogdm9pZCB7XG4gIGlmICh0eXBlb2YgbW9kZWxba2V5XSA9PT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuO1xuICBjb25zdCBoYXNoID0gSGFzaGluZy5oYXNoKChtb2RlbCBhcyBhbnkpW2tleV0pO1xuICBpZiAob2xkTW9kZWwgJiYgKG1vZGVsIGFzIGFueSlba2V5XSA9PT0gaGFzaCkgcmV0dXJuO1xuICBtb2RlbFtrZXldID0gaGFzaDtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGRlY29yYXRvciB0aGF0IGhhc2hlcyBhIHByb3BlcnR5IHZhbHVlXG4gKiBAc3VtbWFyeSBEZWNvcmF0b3IgdGhhdCBhdXRvbWF0aWNhbGx5IGhhc2hlcyBhIHByb3BlcnR5IHZhbHVlIGR1cmluZyBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gaGFzaFxuICogQGNhdGVnb3J5IFByb3BlcnR5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2goKSB7XG4gIHJldHVybiBhcHBseShcbiAgICBvbkNyZWF0ZVVwZGF0ZShoYXNoT25DcmVhdGVVcGRhdGUpLFxuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuSEFTSCksIHt9KVxuICApO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBNZXRhZGF0YSBmb3IgY29tcG9zZWQgcHJvcGVydHkgZGVjb3JhdG9yc1xuICogQHN1bW1hcnkgQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBwcm9wZXJ0eSBjb21wb3NpdGlvbiBmcm9tIG90aGVyIHByb3BlcnRpZXNcbiAqIEB0eXBlZGVmIHtPYmplY3R9IENvbXBvc2VkRnJvbU1ldGFkYXRhXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBhcmdzIC0gUHJvcGVydHkgbmFtZXMgdG8gY29tcG9zZSBmcm9tXG4gKiBAcHJvcGVydHkge3N0cmluZ30gc2VwYXJhdG9yIC0gQ2hhcmFjdGVyIHVzZWQgdG8gam9pbiB0aGUgY29tcG9zZWQgdmFsdWVzXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGhhc2hSZXN1bHQgLSBXaGV0aGVyIHRvIGhhc2ggdGhlIGNvbXBvc2VkIHJlc3VsdFxuICogQHByb3BlcnR5IHtcImtleXNcInxcInZhbHVlc1wifSB0eXBlIC0gV2hldGhlciB0byB1c2UgcHJvcGVydHkga2V5cyBvciB2YWx1ZXNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcHJlZml4XSAtIE9wdGlvbmFsIHByZWZpeCB0byBhZGQgdG8gdGhlIGNvbXBvc2VkIHZhbHVlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW3N1ZmZpeF0gLSBPcHRpb25hbCBzdWZmaXggdG8gYWRkIHRvIHRoZSBjb21wb3NlZCB2YWx1ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCB0eXBlIENvbXBvc2VkRnJvbU1ldGFkYXRhID0ge1xuICBhcmdzOiBzdHJpbmdbXTtcbiAgc2VwYXJhdG9yOiBzdHJpbmc7XG4gIGhhc2hSZXN1bHQ6IGJvb2xlYW47XG4gIHR5cGU6IFwia2V5c1wiIHwgXCJ2YWx1ZXNcIjtcbiAgcHJlZml4Pzogc3RyaW5nO1xuICBzdWZmaXg/OiBzdHJpbmc7XG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDb21wb3NlcyBhIHByb3BlcnR5IHZhbHVlIGZyb20gb3RoZXIgcHJvcGVydGllcyBkdXJpbmcgY3JlYXRlIG9yIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBDYWxsYmFjayBmdW5jdGlvbiB1c2VkIGJ5IGNvbXBvc2VkIGRlY29yYXRvcnMgdG8gZ2VuZXJhdGUgYSBwcm9wZXJ0eSB2YWx1ZSBmcm9tIG90aGVyIHByb3BlcnRpZXNcbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVHlwZSBleHRlbmRpbmcgSVJlcG9zaXRvcnlcbiAqIEB0ZW1wbGF0ZSBWIC0gVHlwZSBleHRlbmRpbmcgQ29tcG9zZWRGcm9tTWV0YWRhdGFcbiAqIEB0ZW1wbGF0ZSBGIC0gVHlwZSBleHRlbmRpbmcgUmVwb3NpdG9yeUZsYWdzXG4gKiBAdGVtcGxhdGUgQyAtIFR5cGUgZXh0ZW5kaW5nIENvbnRleHRcbiAqIEBwYXJhbSB7Q30gY29udGV4dCAtIFRoZSBvcGVyYXRpb24gY29udGV4dFxuICogQHBhcmFtIHtWfSBkYXRhIC0gTWV0YWRhdGEgZm9yIHRoZSBjb21wb3NpdGlvblxuICogQHBhcmFtIGtleSAtIFRoZSBwcm9wZXJ0eSBrZXkgdG8gc2V0IHRoZSBjb21wb3NlZCB2YWx1ZSBvblxuICogQHBhcmFtIHtNfSBtb2RlbCAtIFRoZSBtb2RlbCBiZWluZyBwcm9jZXNzZWRcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKiBAZnVuY3Rpb24gY29tcG9zZWRGcm9tQ3JlYXRlVXBkYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2VkRnJvbUNyZWF0ZVVwZGF0ZTxcbiAgTSBleHRlbmRzIE1vZGVsLFxuICBSIGV4dGVuZHMgSVJlcG9zaXRvcnk8TSwgRiwgQz4sXG4gIFYgZXh0ZW5kcyBDb21wb3NlZEZyb21NZXRhZGF0YSxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPih0aGlzOiBSLCBjb250ZXh0OiBDLCBkYXRhOiBWLCBrZXk6IGtleW9mIE0sIG1vZGVsOiBNKSB7XG4gIHRyeSB7XG4gICAgY29uc3QgeyBhcmdzLCB0eXBlLCBwcmVmaXgsIHN1ZmZpeCwgc2VwYXJhdG9yIH0gPSBkYXRhO1xuICAgIGNvbnN0IGNvbXBvc2VkID0gYXJncy5tYXAoKGFyZzogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoIShhcmcgaW4gbW9kZWwpKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgUHJvcGVydHkgJHthcmd9IG5vdCBmb3VuZCB0byBjb21wb3NlIGZyb21gKTtcbiAgICAgIGlmICh0eXBlID09PSBcImtleXNcIikgcmV0dXJuIGFyZztcbiAgICAgIGlmICh0eXBlb2YgKG1vZGVsIGFzIGFueSlbYXJnXSA9PT0gXCJ1bmRlZmluZWRcIilcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICAgICAgYFByb3BlcnR5ICR7YXJnc30gZG9lcyBub3QgY29udGFpbiBhIHZhbHVlIHRvIGNvbXBvc2UgZnJvbWBcbiAgICAgICAgKTtcbiAgICAgIHJldHVybiAoKG1vZGVsIGFzIGFueSlbYXJnXSBhcyBhbnkpLnRvU3RyaW5nKCk7XG4gICAgfSk7XG5cbiAgICBpZiAocHJlZml4KSBjb21wb3NlZC51bnNoaWZ0KHByZWZpeCk7XG4gICAgaWYgKHN1ZmZpeCkgY29tcG9zZWQucHVzaChzdWZmaXgpO1xuXG4gICAgKG1vZGVsIGFzIGFueSlba2V5XSA9IGNvbXBvc2VkLmpvaW4oc2VwYXJhdG9yKTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEZhaWxlZCB0byBjb21wb3NlIHZhbHVlOiAke2V9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIGRlY29yYXRvciB0aGF0IGNvbXBvc2VzIGEgcHJvcGVydHkgdmFsdWUgZnJvbSBvdGhlciBwcm9wZXJ0aWVzXG4gKiBAc3VtbWFyeSBCYXNlIGZ1bmN0aW9uIGZvciBjcmVhdGluZyBwcm9wZXJ0eSBjb21wb3NpdGlvbiBkZWNvcmF0b3JzXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzIC0gUHJvcGVydHkgbmFtZXMgdG8gY29tcG9zZSBmcm9tXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtoYXNoUmVzdWx0PWZhbHNlXSAtIFdoZXRoZXIgdG8gaGFzaCB0aGUgY29tcG9zZWQgcmVzdWx0XG4gKiBAcGFyYW0ge3N0cmluZ30gW3NlcGFyYXRvcj1EZWZhdWx0U2VwYXJhdG9yXSAtIENoYXJhY3RlciB1c2VkIHRvIGpvaW4gdGhlIGNvbXBvc2VkIHZhbHVlc1xuICogQHBhcmFtIHtcImtleXNcInxcInZhbHVlc1wifSBbdHlwZT1cInZhbHVlc1wiXSAtIFdoZXRoZXIgdG8gdXNlIHByb3BlcnR5IGtleXMgb3IgdmFsdWVzXG4gKiBAcGFyYW0ge3N0cmluZ30gW3ByZWZpeD1cIlwiXSAtIE9wdGlvbmFsIHByZWZpeCB0byBhZGQgdG8gdGhlIGNvbXBvc2VkIHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gW3N1ZmZpeD1cIlwiXSAtIE9wdGlvbmFsIHN1ZmZpeCB0byBhZGQgdG8gdGhlIGNvbXBvc2VkIHZhbHVlXG4gKiBAcmV0dXJuIHtQcm9wZXJ0eURlY29yYXRvcn0gQSBkZWNvcmF0b3IgdGhhdCBjYW4gYmUgYXBwbGllZCB0byBjbGFzcyBwcm9wZXJ0aWVzXG4gKiBAZnVuY3Rpb24gY29tcG9zZWRGcm9tXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHlEZWNvcmF0b3JzXG4gKi9cbmZ1bmN0aW9uIGNvbXBvc2VkRnJvbShcbiAgYXJnczogc3RyaW5nW10sXG4gIGhhc2hSZXN1bHQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgc2VwYXJhdG9yOiBzdHJpbmcgPSBEZWZhdWx0U2VwYXJhdG9yLFxuICB0eXBlOiBcImtleXNcIiB8IFwidmFsdWVzXCIgPSBcInZhbHVlc1wiLFxuICBwcmVmaXggPSBcIlwiLFxuICBzdWZmaXggPSBcIlwiXG4pIHtcbiAgY29uc3QgZGF0YTogQ29tcG9zZWRGcm9tTWV0YWRhdGEgPSB7XG4gICAgYXJnczogYXJncyxcbiAgICBoYXNoUmVzdWx0OiBoYXNoUmVzdWx0LFxuICAgIHNlcGFyYXRvcjogc2VwYXJhdG9yLFxuICAgIHR5cGU6IHR5cGUsXG4gICAgcHJlZml4OiBwcmVmaXgsXG4gICAgc3VmZml4OiBzdWZmaXgsXG4gIH07XG5cbiAgY29uc3QgZGVjb3JhdG9ycyA9IFtcbiAgICBvbkNyZWF0ZVVwZGF0ZShjb21wb3NlZEZyb21DcmVhdGVVcGRhdGUsIGRhdGEpLFxuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuQ09NUE9TRUQpLCBkYXRhKSxcbiAgXTtcbiAgaWYgKGhhc2hSZXN1bHQpIGRlY29yYXRvcnMucHVzaChoYXNoKCkpO1xuICByZXR1cm4gYXBwbHkoLi4uZGVjb3JhdG9ycyk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgdGhhdCBjb21wb3NlcyBhIHByb3BlcnR5IHZhbHVlIGZyb20gcHJvcGVydHkga2V5c1xuICogQHN1bW1hcnkgRGVjb3JhdG9yIHRoYXQgZ2VuZXJhdGVzIGEgcHJvcGVydHkgdmFsdWUgYnkgam9pbmluZyB0aGUgbmFtZXMgb2Ygb3RoZXIgcHJvcGVydGllc1xuICogQHBhcmFtIHtzdHJpbmdbXX0gYXJncyAtIFByb3BlcnR5IG5hbWVzIHRvIGNvbXBvc2UgZnJvbVxuICogQHBhcmFtIHtzdHJpbmd9IFtzZXBhcmF0b3I9RGVmYXVsdFNlcGFyYXRvcl0gLSBDaGFyYWN0ZXIgdXNlZCB0byBqb2luIHRoZSBwcm9wZXJ0eSBuYW1lc1xuICogQHBhcmFtIHtib29sZWFufSBbaGFzaD1mYWxzZV0gLSBXaGV0aGVyIHRvIGhhc2ggdGhlIGNvbXBvc2VkIHJlc3VsdFxuICogQHBhcmFtIHtzdHJpbmd9IFtwcmVmaXg9XCJcIl0gLSBPcHRpb25hbCBwcmVmaXggdG8gYWRkIHRvIHRoZSBjb21wb3NlZCB2YWx1ZVxuICogQHBhcmFtIHtzdHJpbmd9IFtzdWZmaXg9XCJcIl0gLSBPcHRpb25hbCBzdWZmaXggdG8gYWRkIHRvIHRoZSBjb21wb3NlZCB2YWx1ZVxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIGNvbXBvc2VkRnJvbUtleXNcbiAqIEBjYXRlZ29yeSBQcm9wZXJ0eURlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXBvc2VkRnJvbUtleXMoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBzZXBhcmF0b3I6IHN0cmluZyA9IERlZmF1bHRTZXBhcmF0b3IsXG4gIGhhc2g6IGJvb2xlYW4gPSBmYWxzZSxcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIHJldHVybiBjb21wb3NlZEZyb20oYXJncywgaGFzaCwgc2VwYXJhdG9yLCBcImtleXNcIiwgcHJlZml4LCBzdWZmaXgpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZGVjb3JhdG9yIHRoYXQgY29tcG9zZXMgYSBwcm9wZXJ0eSB2YWx1ZSBmcm9tIHByb3BlcnR5IHZhbHVlc1xuICogQHN1bW1hcnkgRGVjb3JhdG9yIHRoYXQgZ2VuZXJhdGVzIGEgcHJvcGVydHkgdmFsdWUgYnkgam9pbmluZyB0aGUgdmFsdWVzIG9mIG90aGVyIHByb3BlcnRpZXNcbiAqIEBwYXJhbSB7c3RyaW5nW119IGFyZ3MgLSBQcm9wZXJ0eSBuYW1lcyB3aG9zZSB2YWx1ZXMgd2lsbCBiZSBjb21wb3NlZFxuICogQHBhcmFtIHtzdHJpbmd9IFtzZXBhcmF0b3I9RGVmYXVsdFNlcGFyYXRvcl0gLSBDaGFyYWN0ZXIgdXNlZCB0byBqb2luIHRoZSBwcm9wZXJ0eSB2YWx1ZXNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2hhc2g9ZmFsc2VdIC0gV2hldGhlciB0byBoYXNoIHRoZSBjb21wb3NlZCByZXN1bHRcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcHJlZml4PVwiXCJdIC0gT3B0aW9uYWwgcHJlZml4IHRvIGFkZCB0byB0aGUgY29tcG9zZWQgdmFsdWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc3VmZml4PVwiXCJdIC0gT3B0aW9uYWwgc3VmZml4IHRvIGFkZCB0byB0aGUgY29tcG9zZWQgdmFsdWVcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGRlY29yYXRvciB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIGNsYXNzIHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBjb21wb3NlZFxuICogQGNhdGVnb3J5IFByb3BlcnR5RGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zZWQoXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBzZXBhcmF0b3I6IHN0cmluZyA9IERlZmF1bHRTZXBhcmF0b3IsXG4gIGhhc2g6IGJvb2xlYW4gPSBmYWxzZSxcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIHJldHVybiBjb21wb3NlZEZyb20oYXJncywgaGFzaCwgc2VwYXJhdG9yLCBcInZhbHVlc1wiLCBwcmVmaXgsIHN1ZmZpeCk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHVwZGF0ZXMgYSB2ZXJzaW9uIHByb3BlcnR5IGR1cmluZyBvcGVyYXRpb25zXG4gKiBAc3VtbWFyeSBGYWN0b3J5IGZ1bmN0aW9uIHRoYXQgZ2VuZXJhdGVzIGEgY2FsbGJhY2sgZm9yIGluY3JlbWVudGluZyB2ZXJzaW9uIG51bWJlcnNcbiAqIEBwYXJhbSB7Q3J1ZE9wZXJhdGlvbnN9IG9wZXJhdGlvbiAtIFRoZSB0eXBlIG9mIG9wZXJhdGlvbiAoQ1JFQVRFIG9yIFVQREFURSlcbiAqIEByZXR1cm4ge0Z1bmN0aW9ufSBBIGNhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgdXBkYXRlcyB0aGUgdmVyc2lvbiBwcm9wZXJ0eVxuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFIgLSBUeXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeVxuICogQHRlbXBsYXRlIFYgLSBUeXBlIGZvciBtZXRhZGF0YVxuICogQHRlbXBsYXRlIEYgLSBUeXBlIGV4dGVuZGluZyBSZXBvc2l0b3J5RmxhZ3NcbiAqIEB0ZW1wbGF0ZSBDIC0gVHlwZSBleHRlbmRpbmcgQ29udGV4dFxuICogQGZ1bmN0aW9uIHZlcnNpb25DcmVhdGVVcGRhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGItZGVjb3JhdG9yc1xuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgdmVyc2lvbkNyZWF0ZVVwZGF0ZVxuICpcbiAqICAgQ2FsbGVyLT4+dmVyc2lvbkNyZWF0ZVVwZGF0ZTogb3BlcmF0aW9uXG4gKiAgIHZlcnNpb25DcmVhdGVVcGRhdGUtLT4+Q2FsbGVyOiBjYWxsYmFjayBmdW5jdGlvblxuICogICBOb3RlIG92ZXIgQ2FsbGVyLHZlcnNpb25DcmVhdGVVcGRhdGU6IFdoZW4gY2FsbGJhY2sgaXMgZXhlY3V0ZWQ6XG4gKiAgIENhbGxlci0+PnZlcnNpb25DcmVhdGVVcGRhdGU6IGNvbnRleHQsIGRhdGEsIGtleSwgbW9kZWxcbiAqICAgYWx0IG9wZXJhdGlvbiBpcyBDUkVBVEVcbiAqICAgICB2ZXJzaW9uQ3JlYXRlVXBkYXRlLT4+dmVyc2lvbkNyZWF0ZVVwZGF0ZTogc2V0IHZlcnNpb24gdG8gMVxuICogICBlbHNlIG9wZXJhdGlvbiBpcyBVUERBVEVcbiAqICAgICB2ZXJzaW9uQ3JlYXRlVXBkYXRlLT4+dmVyc2lvbkNyZWF0ZVVwZGF0ZTogaW5jcmVtZW50IHZlcnNpb25cbiAqICAgZWxzZSBpbnZhbGlkIG9wZXJhdGlvblxuICogICAgIHZlcnNpb25DcmVhdGVVcGRhdGUtPj52ZXJzaW9uQ3JlYXRlVXBkYXRlOiB0aHJvdyBlcnJvclxuICogICBlbmRcbiAqICAgdmVyc2lvbkNyZWF0ZVVwZGF0ZS0tPj5DYWxsZXI6IHZvaWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcnNpb25DcmVhdGVVcGRhdGUob3BlcmF0aW9uOiBDcnVkT3BlcmF0aW9ucykge1xuICByZXR1cm4gZnVuY3Rpb24gdmVyc2lvbkNyZWF0ZVVwZGF0ZTxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICAgIFYgZXh0ZW5kcyBvYmplY3QsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSkge1xuICAgIHRyeSB7XG4gICAgICBzd2l0Y2ggKG9wZXJhdGlvbikge1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuQ1JFQVRFOlxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpW2tleV0gPSAxO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuVVBEQVRFOlxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpW2tleV0rKztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgSW52YWxpZCBvcGVyYXRpb246ICR7b3BlcmF0aW9ufWApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBGYWlsZWQgdG8gdXBkYXRlIHZlcnNpb246ICR7ZX1gKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgZm9yIHZlcnNpb25pbmcgYSBwcm9wZXJ0eSBpbiBhIG1vZGVsXG4gKiBAc3VtbWFyeSBUaGlzIGRlY29yYXRvciBhcHBsaWVzIG11bHRpcGxlIHN1Yi1kZWNvcmF0b3JzIHRvIGhhbmRsZSB2ZXJzaW9uIG1hbmFnZW1lbnQgZHVyaW5nIGNyZWF0ZSBhbmQgdXBkYXRlIG9wZXJhdGlvbnNcbiAqIEByZXR1cm4ge1Byb3BlcnR5RGVjb3JhdG9yfSBBIGNvbXBvc2l0ZSBkZWNvcmF0b3IgdGhhdCBzZXRzIHRoZSB0eXBlIHRvIE51bWJlciwgbWFuYWdlcyB2ZXJzaW9uIHVwZGF0ZXMsIGFuZCBhZGRzIHZlcnNpb25pbmcgbWV0YWRhdGFcbiAqIEBmdW5jdGlvbiB2ZXJzaW9uXG4gKiBAY2F0ZWdvcnkgUHJvcGVydHlEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2ZXJzaW9uKCkge1xuICByZXR1cm4gYXBwbHkoXG4gICAgdHlwZShOdW1iZXIubmFtZSksXG4gICAgb25DcmVhdGUodmVyc2lvbkNyZWF0ZVVwZGF0ZShPcGVyYXRpb25LZXlzLkNSRUFURSkpLFxuICAgIG9uVXBkYXRlKHZlcnNpb25DcmVhdGVVcGRhdGUoT3BlcmF0aW9uS2V5cy5VUERBVEUpKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLlZFUlNJT04pLCB0cnVlKVxuICApO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgZGVjb3JhdG9yIHRoYXQgbWFya3MgYSBwcm9wZXJ0eSBhcyB0cmFuc2llbnRcbiAqIEBzdW1tYXJ5IERlY29yYXRvciB0aGF0IGluZGljYXRlcyBhIHByb3BlcnR5IHNob3VsZCBub3QgYmUgcGVyc2lzdGVkIHRvIHRoZSBkYXRhYmFzZVxuICogQHJldHVybiB7UHJvcGVydHlEZWNvcmF0b3J9IEEgZGVjb3JhdG9yIHRoYXQgY2FuIGJlIGFwcGxpZWQgdG8gY2xhc3MgcHJvcGVydGllc1xuICogQGZ1bmN0aW9uIHRyYW5zaWVudFxuICogQGNhdGVnb3J5IFByb3BlcnR5RGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNpZW50KCkge1xuICByZXR1cm4gZnVuY3Rpb24gdHJhbnNpZW50KG1vZGVsOiBhbnksIGF0dHJpYnV0ZTogc3RyaW5nKSB7XG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLCB0cnVlKShtb2RlbCwgYXR0cmlidXRlKTtcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLlRSQU5TSUVOVCksIHRydWUpKG1vZGVsLmNvbnN0cnVjdG9yKTtcbiAgfTtcbn1cbiIsImltcG9ydCB7XG4gIE1vZGVsLFxuICBNb2RlbENvbmRpdGlvbmFsQXN5bmMsXG4gIHZhbGlkYXRlLFxufSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyB2YWxpZGF0ZUNvbXBhcmUgfSBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRlcyB0aGUgbW9kZWwgYW5kIGNoZWNrcyBmb3IgZXJyb3JzXG4gKiBAc3VtbWFyeSBWYWxpZGF0ZXMgdGhlIGN1cnJlbnQgbW9kZWwgc3RhdGUgYW5kIG9wdGlvbmFsbHkgY29tcGFyZXMgd2l0aCBhIHByZXZpb3VzIHZlcnNpb25cbiAqIEB0ZW1wbGF0ZSBNIC0gVHlwZSBleHRlbmRpbmcgTW9kZWxcbiAqIEBwYXJhbSB7TXxhbnl9IFtwcmV2aW91c1ZlcnNpb25dIC0gT3B0aW9uYWwgcHJldmlvdXMgdmVyc2lvbiBvZiB0aGUgbW9kZWwgZm9yIGNvbXBhcmlzb25cbiAqIEBwYXJhbSB7Li4uYW55W119IGV4Y2x1c2lvbnMgLSBQcm9wZXJ0aWVzIHRvIGV4Y2x1ZGUgZnJvbSB2YWxpZGF0aW9uXG4gKiBAcmV0dXJuIHtNb2RlbEVycm9yRGVmaW5pdGlvbnx1bmRlZmluZWR9IEVycm9yIGRlZmluaXRpb24gaWYgdmFsaWRhdGlvbiBmYWlscywgdW5kZWZpbmVkIG90aGVyd2lzZVxuICogQGZ1bmN0aW9uIGhhc0Vycm9yc1xuICogQG1lbWJlck9mIG1vZHVsZTpkYi1kZWNvcmF0b3JzXG4gKi9cbi8vIEB0cy1leHBlY3QtZXJyb3IgT3ZlcnJpZGluZyBNb2RlbCBwcm90b3R5cGUgbWV0aG9kIHdpdGggZHluYW1pYyBjb25kaXRpb25hbCByZXR1cm4gdHlwZS5cbk1vZGVsLnByb3RvdHlwZS5oYXNFcnJvcnMgPSBmdW5jdGlvbiA8TSBleHRlbmRzIE1vZGVsPGJvb2xlYW4+PihcbiAgdGhpczogTSxcbiAgcHJldmlvdXNWZXJzaW9uPzogTSB8IGFueSxcbiAgLi4uZXhjbHVzaW9uczogYW55W11cbik6IE1vZGVsQ29uZGl0aW9uYWxBc3luYzxNPiB7XG4gIGlmIChwcmV2aW91c1ZlcnNpb24gJiYgIShwcmV2aW91c1ZlcnNpb24gaW5zdGFuY2VvZiBNb2RlbCkpIHtcbiAgICBleGNsdXNpb25zLnVuc2hpZnQocHJldmlvdXNWZXJzaW9uKTtcbiAgICBwcmV2aW91c1ZlcnNpb24gPSB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBhc3luYyA9IHRoaXMuaXNBc3luYygpO1xuICBjb25zdCBlcnJzID0gdmFsaWRhdGUodGhpcywgYXN5bmMsIC4uLmV4Y2x1c2lvbnMpO1xuXG4gIGlmIChhc3luYykge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZXJycykudGhlbigocmVzb2x2ZWRFcnJzKSA9PiB7XG4gICAgICBpZiAocmVzb2x2ZWRFcnJzIHx8ICFwcmV2aW91c1ZlcnNpb24pIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmVkRXJycztcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWxpZGF0ZUNvbXBhcmUocHJldmlvdXNWZXJzaW9uLCB0aGlzLCBhc3luYywgLi4uZXhjbHVzaW9ucyk7XG4gICAgfSkgYXMgYW55O1xuICB9XG5cbiAgaWYgKGVycnMgfHwgIXByZXZpb3VzVmVyc2lvbikgcmV0dXJuIGVycnMgYXMgYW55O1xuXG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgT3ZlcnJpZGluZyBNb2RlbCBwcm90b3R5cGUgbWV0aG9kIHdpdGggZHluYW1pYyBjb25kaXRpb25hbCByZXR1cm4gdHlwZS5cbiAgcmV0dXJuIHZhbGlkYXRlQ29tcGFyZShwcmV2aW91c1ZlcnNpb24sIHRoaXMsIGFzeW5jLCAuLi5leGNsdXNpb25zKTtcbn07XG4iLCJpbXBvcnQge1xuICBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUsXG4gIFJlcG9zaXRvcnksXG4gIFNlcmlhbGl6YXRpb25FcnJvcixcbn0gZnJvbSBcIi4uL3JlcG9zaXRvcnlcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgREJLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENoZWNrcyBpZiBhIG1vZGVsIGlzIG1hcmtlZCBhcyB0cmFuc2llbnRcbiAqIEBzdW1tYXJ5IERldGVybWluZXMgd2hldGhlciBhIG1vZGVsIGNsYXNzIGhhcyBiZWVuIGRlY29yYXRlZCB3aXRoIHRoZSB0cmFuc2llbnQgZGVjb3JhdG9yXG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIGNoZWNrXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSBtb2RlbCBpcyB0cmFuc2llbnQsIGZhbHNlIG90aGVyd2lzZVxuICogQGZ1bmN0aW9uIGlzVHJhbnNpZW50XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHJhbnNpZW50PE0gZXh0ZW5kcyBNb2RlbD4obW9kZWw6IE0pIHtcbiAgcmV0dXJuICEhKFxuICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLlRSQU5TSUVOVCksIG1vZGVsLmNvbnN0cnVjdG9yKSB8fFxuICAgIFJlZmxlY3QuZ2V0TWV0YWRhdGEoXG4gICAgICBSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKSxcbiAgICAgIE1vZGVsLmdldChtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lKSBhcyBhbnlcbiAgICApXG4gICk7XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFNlcGFyYXRlcyB0cmFuc2llbnQgcHJvcGVydGllcyBmcm9tIGEgbW9kZWxcbiAqIEBzdW1tYXJ5IEV4dHJhY3RzIHByb3BlcnRpZXMgbWFya2VkIGFzIHRyYW5zaWVudCBpbnRvIGEgc2VwYXJhdGUgb2JqZWN0XG4gKiBAdGVtcGxhdGUgTSAtIFR5cGUgZXh0ZW5kaW5nIE1vZGVsXG4gKiBAcGFyYW0ge019IG1vZGVsIC0gVGhlIG1vZGVsIGluc3RhbmNlIHRvIHByb2Nlc3NcbiAqIEByZXR1cm4ge09iamVjdH0gT2JqZWN0IGNvbnRhaW5pbmcgdGhlIG1vZGVsIHdpdGhvdXQgdHJhbnNpZW50IHByb3BlcnRpZXMgYW5kIGEgc2VwYXJhdGUgdHJhbnNpZW50IG9iamVjdFxuICogQHByb3BlcnR5IHtNfSBtb2RlbCAtIFRoZSBtb2RlbCB3aXRoIHRyYW5zaWVudCBwcm9wZXJ0aWVzIHJlbW92ZWRcbiAqIEBwcm9wZXJ0eSB7UmVjb3JkPHN0cmluZywgYW55Pn0gW3RyYW5zaWVudF0gLSBPYmplY3QgY29udGFpbmluZyB0aGUgdHJhbnNpZW50IHByb3BlcnRpZXNcbiAqIEBmdW5jdGlvbiBtb2RlbFRvVHJhbnNpZW50XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2FsbGVyXG4gKiAgIHBhcnRpY2lwYW50IG1vZGVsVG9UcmFuc2llbnRcbiAqICAgcGFydGljaXBhbnQgaXNUcmFuc2llbnRcbiAqICAgcGFydGljaXBhbnQgZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlXG4gKlxuICogICBDYWxsZXItPj5tb2RlbFRvVHJhbnNpZW50OiBtb2RlbFxuICogICBtb2RlbFRvVHJhbnNpZW50LT4+aXNUcmFuc2llbnQ6IGNoZWNrIGlmIG1vZGVsIGlzIHRyYW5zaWVudFxuICogICBpc1RyYW5zaWVudC0tPj5tb2RlbFRvVHJhbnNpZW50OiB0cmFuc2llbnQgc3RhdHVzXG4gKiAgIGFsdCBtb2RlbCBpcyBub3QgdHJhbnNpZW50XG4gKiAgICAgbW9kZWxUb1RyYW5zaWVudC0tPj5DYWxsZXI6IHttb2RlbH1cbiAqICAgZWxzZSBtb2RlbCBpcyB0cmFuc2llbnRcbiAqICAgICBtb2RlbFRvVHJhbnNpZW50LT4+Z2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlOiBnZXQgdHJhbnNpZW50IHByb3BlcnRpZXNcbiAqICAgICBnZXRBbGxQcm9wZXJ0eURlY29yYXRvcnNSZWN1cnNpdmUtLT4+bW9kZWxUb1RyYW5zaWVudDogcHJvcGVydHkgZGVjb3JhdG9yc1xuICogICAgIG1vZGVsVG9UcmFuc2llbnQtPj5tb2RlbFRvVHJhbnNpZW50OiBzZXBhcmF0ZSBwcm9wZXJ0aWVzXG4gKiAgICAgbW9kZWxUb1RyYW5zaWVudC0+Pk1vZGVsLmJ1aWxkOiByZWJ1aWxkIG1vZGVsIHdpdGhvdXQgdHJhbnNpZW50IHByb3BzXG4gKiAgICAgbW9kZWxUb1RyYW5zaWVudC0tPj5DYWxsZXI6IHttb2RlbCwgdHJhbnNpZW50fVxuICogICBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsVG9UcmFuc2llbnQ8TSBleHRlbmRzIE1vZGVsPihcbiAgbW9kZWw6IE1cbik6IHsgbW9kZWw6IE07IHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4gfSB7XG4gIGlmICghaXNUcmFuc2llbnQobW9kZWwpKSByZXR1cm4geyBtb2RlbDogbW9kZWwgfTtcbiAgY29uc3QgZGVjczogUmVjb3JkPHN0cmluZywgYW55W10+ID0gZ2V0QWxsUHJvcGVydHlEZWNvcmF0b3JzUmVjdXJzaXZlKFxuICAgIG1vZGVsLFxuICAgIHVuZGVmaW5lZCxcbiAgICBSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKVxuICApIGFzIFJlY29yZDxzdHJpbmcsIGFueVtdPjtcblxuICBjb25zdCByZXN1bHQgPSBPYmplY3QuZW50cmllcyhkZWNzKS5yZWR1Y2UoXG4gICAgKFxuICAgICAgYWNjdW06IHsgbW9kZWw6IFJlY29yZDxzdHJpbmcsIGFueT47IHRyYW5zaWVudD86IFJlY29yZDxzdHJpbmcsIGFueT4gfSxcbiAgICAgIFtrLCB2YWxdXG4gICAgKSA9PiB7XG4gICAgICBjb25zdCB0cmFuc2llbnQgPSB2YWwuZmluZCgoZWwpID0+IGVsLmtleSA9PT0gXCJcIik7XG4gICAgICBpZiAodHJhbnNpZW50KSB7XG4gICAgICAgIGFjY3VtLnRyYW5zaWVudCA9IGFjY3VtLnRyYW5zaWVudCB8fCB7fTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhY2N1bS50cmFuc2llbnRba10gPSBtb2RlbFtrIGFzIGtleW9mIE1dO1xuICAgICAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFNlcmlhbGl6YXRpb25FcnJvcihcbiAgICAgICAgICAgIGBGYWlsZWQgdG8gc2VyaWFsaXplIHRyYW5zaWVudCBwcm9wZXJ0eSAke2t9OiAke2V9YFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFjY3VtLm1vZGVsID0gYWNjdW0ubW9kZWwgfHwge307XG4gICAgICAgIGFjY3VtLm1vZGVsW2tdID0gKG1vZGVsIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjY3VtO1xuICAgIH0sXG4gICAge30gYXMgeyBtb2RlbDogUmVjb3JkPHN0cmluZywgYW55PjsgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PiB9XG4gICk7XG4gIHJlc3VsdC5tb2RlbCA9IE1vZGVsLmJ1aWxkKHJlc3VsdC5tb2RlbCwgbW9kZWwuY29uc3RydWN0b3IubmFtZSk7XG4gIHJldHVybiByZXN1bHQgYXMgeyBtb2RlbDogTTsgdHJhbnNpZW50PzogUmVjb3JkPHN0cmluZywgYW55PiB9O1xufVxuIiwiZXhwb3J0ICogZnJvbSBcIi4vaWRlbnRpdHlcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2ludGVyZmFjZXNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL21vZGVsXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9vcGVyYXRpb25zXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9yZXBvc2l0b3J5XCI7XG5leHBvcnQgKiBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIERhdGFiYXNlIGRlY29yYXRvcnMgZm9yIFR5cGVTY3JpcHQgYXBwbGljYXRpb25zXG4gKiBAc3VtbWFyeSBBIGNvbXByZWhlbnNpdmUgbGlicmFyeSBwcm92aWRpbmcgZGVjb3JhdG9ycyBhbmQgdXRpbGl0aWVzIGZvciBkYXRhYmFzZSBvcGVyYXRpb25zLCBtb2RlbCBkZWZpbml0aW9ucywgdmFsaWRhdGlvbiwgYW5kIHJlcG9zaXRvcnkgcGF0dGVybnMgaW4gVHlwZVNjcmlwdCBhcHBsaWNhdGlvbnNcbiAqIEBtb2R1bGUgZGItZGVjb3JhdG9yc1xuICovXG5cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQ3VycmVudCB2ZXJzaW9uIG9mIHRoZSByZWZsZWN0aW9uIHBhY2thZ2VcbiAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgc2VtYW50aWMgdmVyc2lvbiBudW1iZXIgb2YgdGhlIHBhY2thZ2VcbiAqIEBjb25zdCBWRVJTSU9OXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRiLWRlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGNvbnN0IFZFUlNJT04gPSBcIiMjVkVSU0lPTiMjXCI7XG4iXSwibmFtZXMiOlsiTW9kZWxLZXlzIiwiUmVhZE9ubHlWYWxpZGF0b3IiLCJWYWxpZGF0b3IiLCJpc0VxdWFsIiwiX19kZWNvcmF0ZSIsInZhbGlkYXRvciIsIlRpbWVzdGFtcFZhbGlkYXRvciIsIkRlY29yYXRvck1lc3NhZ2VzIiwiVmFsaWRhdGlvbiIsIk9wZXJhdGlvbktleXMiLCJCdWxrQ3J1ZE9wZXJhdGlvbktleXMiLCJIYXNoaW5nIiwicHJvcE1ldGFkYXRhIiwiYXBwbHkiLCJSZWZsZWN0aW9uIiwiT2JqZWN0QWNjdW11bGF0b3IiLCJzZiIsIkRlY29yYXRpb24iLCJkYXRlIiwicmVxdWlyZWQiLCJ0eXBlIiwibWV0YWRhdGEiLCJnZXRWYWxpZGF0aW9uRGVjb3JhdG9ycyIsIlZhbGlkYXRpb25LZXlzIiwidG9Db25kaXRpb25hbFByb21pc2UiLCJNb2RlbCIsIk1vZGVsRXJyb3JEZWZpbml0aW9uIiwidmFsaWRhdGUiXSwibWFwcGluZ3MiOiI7Ozs7OztJQUVBOzs7OztJQUtHO0FBQ1UsVUFBQSxNQUFNLEdBQUc7SUFDcEIsSUFBQSxPQUFPLEVBQUUsQ0FBQSxFQUFH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
|