@decaf-ts/decorator-validation 1.5.12 → 1.6.1
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/dist/decorator-validation.cjs +2586 -0
- package/dist/decorator-validation.esm.cjs +2525 -0
- package/{dist/types → lib/esm}/index.d.ts +1 -1
- package/lib/esm/index.js +2 -3
- package/lib/esm/model/Model.js +1 -2
- package/lib/esm/model/ModelErrorDefinition.js +1 -2
- package/lib/esm/model/constants.js +1 -2
- package/lib/esm/model/construction.js +1 -2
- package/lib/esm/model/decorators.js +1 -2
- package/lib/esm/model/index.js +1 -2
- package/lib/esm/model/types.js +1 -2
- package/lib/esm/model/validation.js +1 -2
- package/lib/esm/utils/constants.js +1 -2
- package/lib/esm/utils/dates.js +1 -2
- package/lib/esm/utils/decorators.js +1 -2
- package/lib/esm/utils/hashing.js +1 -2
- package/lib/esm/utils/index.js +1 -2
- package/lib/esm/utils/registry.js +1 -2
- package/lib/esm/utils/serialization.js +1 -2
- package/lib/esm/utils/strings.js +1 -2
- package/lib/esm/utils/types.js +1 -2
- package/lib/esm/validation/Validation.js +1 -2
- package/lib/esm/validation/Validators/DateValidator.js +1 -2
- package/lib/esm/validation/Validators/EmailValidator.js +1 -2
- package/lib/esm/validation/Validators/ListValidator.js +1 -2
- package/lib/esm/validation/Validators/MaxLengthValidator.js +1 -2
- package/lib/esm/validation/Validators/MaxValidator.js +1 -2
- package/lib/esm/validation/Validators/MinLengthValidator.js +1 -2
- package/lib/esm/validation/Validators/MinValidator.js +1 -2
- package/lib/esm/validation/Validators/PasswordValidator.js +1 -2
- package/lib/esm/validation/Validators/PatternValidator.js +1 -2
- package/lib/esm/validation/Validators/RequiredValidator.js +1 -2
- package/lib/esm/validation/Validators/StepValidator.js +1 -2
- package/lib/esm/validation/Validators/TypeValidator.js +1 -2
- package/lib/esm/validation/Validators/URLValidator.js +1 -2
- package/lib/esm/validation/Validators/Validator.js +1 -2
- package/lib/esm/validation/Validators/ValidatorRegistry.js +1 -2
- package/lib/esm/validation/Validators/constants.js +1 -2
- package/lib/esm/validation/Validators/decorators.js +1 -2
- package/lib/esm/validation/Validators/index.js +1 -2
- package/lib/esm/validation/decorators.js +1 -2
- package/lib/esm/validation/index.js +1 -2
- package/lib/esm/validation/types.js +1 -2
- package/lib/index.cjs +2 -3
- package/lib/index.d.ts +42 -0
- package/lib/model/Model.cjs +1 -2
- package/lib/model/Model.d.ts +204 -0
- package/lib/model/ModelErrorDefinition.cjs +1 -2
- package/lib/model/ModelErrorDefinition.d.ts +22 -0
- package/lib/model/constants.cjs +1 -2
- package/lib/model/constants.d.ts +56 -0
- package/lib/model/construction.cjs +1 -2
- package/lib/model/construction.d.ts +29 -0
- package/lib/model/decorators.cjs +1 -2
- package/lib/model/decorators.d.ts +25 -0
- package/lib/model/index.cjs +1 -2
- package/lib/model/index.d.ts +7 -0
- package/lib/model/types.cjs +1 -2
- package/lib/model/types.d.ts +79 -0
- package/lib/model/validation.cjs +1 -2
- package/lib/model/validation.d.ts +14 -0
- package/lib/utils/constants.cjs +1 -2
- package/lib/utils/constants.d.ts +26 -0
- package/lib/utils/dates.cjs +1 -2
- package/lib/utils/dates.d.ts +76 -0
- package/lib/utils/decorators.cjs +1 -2
- package/lib/utils/decorators.d.ts +2 -0
- package/lib/utils/hashing.cjs +1 -2
- package/lib/utils/hashing.d.ts +38 -0
- package/lib/utils/index.cjs +1 -2
- package/lib/utils/index.d.ts +8 -0
- package/lib/utils/registry.cjs +1 -2
- package/lib/utils/registry.d.ts +68 -0
- package/lib/utils/serialization.cjs +1 -2
- package/lib/utils/serialization.d.ts +53 -0
- package/lib/utils/strings.cjs +1 -2
- package/lib/utils/strings.d.ts +25 -0
- package/lib/utils/types.cjs +1 -2
- package/lib/utils/types.d.ts +29 -0
- package/lib/validation/Validation.cjs +1 -2
- package/lib/validation/Validation.d.ts +51 -0
- package/lib/validation/Validators/DateValidator.cjs +1 -2
- package/lib/validation/Validators/DateValidator.d.ts +28 -0
- package/lib/validation/Validators/EmailValidator.cjs +1 -2
- package/lib/validation/Validators/EmailValidator.d.ts +28 -0
- package/lib/validation/Validators/ListValidator.cjs +1 -2
- package/lib/validation/Validators/ListValidator.d.ts +28 -0
- package/lib/validation/Validators/MaxLengthValidator.cjs +1 -2
- package/lib/validation/Validators/MaxLengthValidator.d.ts +29 -0
- package/lib/validation/Validators/MaxValidator.cjs +1 -2
- package/lib/validation/Validators/MaxValidator.d.ts +28 -0
- package/lib/validation/Validators/MinLengthValidator.cjs +1 -2
- package/lib/validation/Validators/MinLengthValidator.d.ts +29 -0
- package/lib/validation/Validators/MinValidator.cjs +1 -2
- package/lib/validation/Validators/MinValidator.d.ts +28 -0
- package/lib/validation/Validators/PasswordValidator.cjs +1 -2
- package/lib/validation/Validators/PasswordValidator.d.ts +28 -0
- package/lib/validation/Validators/PatternValidator.cjs +1 -2
- package/lib/validation/Validators/PatternValidator.d.ts +37 -0
- package/lib/validation/Validators/RequiredValidator.cjs +1 -2
- package/lib/validation/Validators/RequiredValidator.d.ts +28 -0
- package/lib/validation/Validators/StepValidator.cjs +1 -2
- package/lib/validation/Validators/StepValidator.d.ts +29 -0
- package/lib/validation/Validators/TypeValidator.cjs +1 -2
- package/lib/validation/Validators/TypeValidator.d.ts +25 -0
- package/lib/validation/Validators/URLValidator.cjs +1 -2
- package/lib/validation/Validators/URLValidator.d.ts +27 -0
- package/lib/validation/Validators/Validator.cjs +1 -2
- package/lib/validation/Validators/Validator.d.ts +41 -0
- package/lib/validation/Validators/ValidatorRegistry.cjs +1 -2
- package/lib/validation/Validators/ValidatorRegistry.d.ts +47 -0
- package/lib/validation/Validators/constants.cjs +1 -2
- package/lib/validation/Validators/constants.d.ts +97 -0
- package/lib/validation/Validators/decorators.cjs +1 -2
- package/lib/validation/Validators/decorators.d.ts +12 -0
- package/lib/validation/Validators/index.cjs +1 -2
- package/lib/validation/Validators/index.d.ts +17 -0
- package/lib/validation/decorators.cjs +1 -2
- package/lib/validation/decorators.d.ts +178 -0
- package/lib/validation/index.cjs +1 -2
- package/lib/validation/index.d.ts +4 -0
- package/lib/validation/types.cjs +1 -2
- package/lib/validation/types.d.ts +134 -0
- package/package.json +23 -36
- package/dist/decorator-validation.js +0 -2
- package/dist/decorator-validation.js.LICENSE.txt +0 -14
- package/dist/esm/decorator-validation.js +0 -2
- package/dist/esm/decorator-validation.js.LICENSE.txt +0 -14
- /package/{dist/types → lib/esm}/model/Model.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/ModelErrorDefinition.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/constants.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/construction.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/decorators.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/index.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/types.d.ts +0 -0
- /package/{dist/types → lib/esm}/model/validation.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/constants.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/dates.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/decorators.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/hashing.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/index.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/registry.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/serialization.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/strings.d.ts +0 -0
- /package/{dist/types → lib/esm}/utils/types.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validation.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/DateValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/EmailValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/ListValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/MaxLengthValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/MaxValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/MinLengthValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/MinValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/PasswordValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/PatternValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/RequiredValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/StepValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/TypeValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/URLValidator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/Validator.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/ValidatorRegistry.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/constants.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/decorators.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/Validators/index.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/decorators.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/index.d.ts +0 -0
- /package/{dist/types → lib/esm}/validation/types.d.ts +0 -0
|
@@ -0,0 +1,2525 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { apply, metadata, Reflection, isEqual } from '@decaf-ts/reflection';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @summary Defines the various Model keys used for reflection
|
|
6
|
+
*
|
|
7
|
+
* @property {string} REFLECT prefix to all other keys
|
|
8
|
+
* @property {string} TYPE type key
|
|
9
|
+
* @property {string} PARAMS method params key
|
|
10
|
+
* @property {string} RETURN method return key
|
|
11
|
+
* @property {string} MODEL model key
|
|
12
|
+
* @property {string} ANCHOR anchor key. will serve as a ghost property in the model
|
|
13
|
+
*
|
|
14
|
+
* @constant ModelKeys
|
|
15
|
+
* @memberOf module:decorator-validation.Model
|
|
16
|
+
* @category Model
|
|
17
|
+
*/
|
|
18
|
+
var ModelKeys;
|
|
19
|
+
(function (ModelKeys) {
|
|
20
|
+
ModelKeys["REFLECT"] = "decaf.model.";
|
|
21
|
+
ModelKeys["TYPE"] = "design:type";
|
|
22
|
+
ModelKeys["PARAMS"] = "design:paramtypes";
|
|
23
|
+
ModelKeys["RETURN"] = "design:returntype";
|
|
24
|
+
ModelKeys["MODEL"] = "model";
|
|
25
|
+
ModelKeys["ANCHOR"] = "__model";
|
|
26
|
+
ModelKeys["CONSTRUCTION"] = "constructed-by";
|
|
27
|
+
ModelKeys["ATTRIBUTE"] = "__attributes";
|
|
28
|
+
ModelKeys["HASHING"] = "hashing";
|
|
29
|
+
ModelKeys["SERIALIZATION"] = "serialization";
|
|
30
|
+
})(ModelKeys || (ModelKeys = {}));
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @summary The keys used for validation
|
|
34
|
+
*
|
|
35
|
+
* @property {string} REFLECT prefixes others
|
|
36
|
+
* @property {string} REQUIRED sets as required
|
|
37
|
+
* @property {string} MIN defines min value
|
|
38
|
+
* @property {string} MAX defines max value
|
|
39
|
+
* @property {string} STEP defines step
|
|
40
|
+
* @property {string} MIN_LENGTH defines min length
|
|
41
|
+
* @property {string} MAX_LENGTH defines max length
|
|
42
|
+
* @property {string} PATTERN defines pattern
|
|
43
|
+
* @property {string} EMAIL defines email
|
|
44
|
+
* @property {string} URL defines url
|
|
45
|
+
* @property {string} DATE defines date
|
|
46
|
+
* @property {string} TYPE defines type
|
|
47
|
+
* @property {string} PASSWORD defines password
|
|
48
|
+
* @property {string} LIST defines list
|
|
49
|
+
*
|
|
50
|
+
* @constant ValidationKeys
|
|
51
|
+
* @memberOf module:decorator-validation.Validation
|
|
52
|
+
* @category Validation
|
|
53
|
+
*/
|
|
54
|
+
const ValidationKeys = {
|
|
55
|
+
REFLECT: `${ModelKeys.REFLECT}validation.`,
|
|
56
|
+
VALIDATOR: "validator",
|
|
57
|
+
REQUIRED: "required",
|
|
58
|
+
MIN: "min",
|
|
59
|
+
MAX: "max",
|
|
60
|
+
STEP: "step",
|
|
61
|
+
MIN_LENGTH: "minlength",
|
|
62
|
+
MAX_LENGTH: "maxlength",
|
|
63
|
+
PATTERN: "pattern",
|
|
64
|
+
EMAIL: "email",
|
|
65
|
+
URL: "url",
|
|
66
|
+
DATE: "date",
|
|
67
|
+
TYPE: "type",
|
|
68
|
+
PASSWORD: "password",
|
|
69
|
+
LIST: "list",
|
|
70
|
+
FORMAT: "format",
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* @summary list of month names
|
|
74
|
+
* @description Stores month names. Can be changed for localization purposes
|
|
75
|
+
*
|
|
76
|
+
* @constant MONTH_NAMES
|
|
77
|
+
* @memberOf module:decorator-validation.Validation
|
|
78
|
+
* @category Validation
|
|
79
|
+
*/
|
|
80
|
+
const MONTH_NAMES = [
|
|
81
|
+
"January",
|
|
82
|
+
"February",
|
|
83
|
+
"March",
|
|
84
|
+
"April",
|
|
85
|
+
"May",
|
|
86
|
+
"June",
|
|
87
|
+
"July",
|
|
88
|
+
"August",
|
|
89
|
+
"September",
|
|
90
|
+
"October",
|
|
91
|
+
"November",
|
|
92
|
+
"December",
|
|
93
|
+
];
|
|
94
|
+
/**
|
|
95
|
+
* @summary list of names of days of the week
|
|
96
|
+
* @description Stores names for days of the week. Can be changed for localization purposes
|
|
97
|
+
*
|
|
98
|
+
* @constant DAYS_OF_WEEK_NAMES
|
|
99
|
+
* @memberOf module:decorator-validation.Validation
|
|
100
|
+
* @category Validation
|
|
101
|
+
*/
|
|
102
|
+
const DAYS_OF_WEEK_NAMES = [
|
|
103
|
+
"Sunday",
|
|
104
|
+
"Monday",
|
|
105
|
+
"Tuesday",
|
|
106
|
+
"Wednesday",
|
|
107
|
+
"Thursday",
|
|
108
|
+
"Friday",
|
|
109
|
+
"Saturday",
|
|
110
|
+
];
|
|
111
|
+
/**
|
|
112
|
+
* @summary Defines the default error messages
|
|
113
|
+
*
|
|
114
|
+
* @property {string} REQUIRED default error message
|
|
115
|
+
* @property {string} MIN default error message
|
|
116
|
+
* @property {string} MAX default error message
|
|
117
|
+
* @property {string} MIN_LENGTH default error message
|
|
118
|
+
* @property {string} MAX_LENGTH default error message
|
|
119
|
+
* @property {string} PATTERN default error message
|
|
120
|
+
* @property {string} EMAIL default error message
|
|
121
|
+
* @property {string} URL default error message
|
|
122
|
+
* @property {string} TYPE default error message
|
|
123
|
+
* @property {string} STEP default error message
|
|
124
|
+
* @property {string} DATE default error message
|
|
125
|
+
* @property {string} DEFAULT default error message
|
|
126
|
+
* @property {string} PASSWORD default error message
|
|
127
|
+
* @property {string} LIST default error message
|
|
128
|
+
* @property {string} LIST_INSIDE default error message
|
|
129
|
+
* @property {string} MODEL_NOT_FOUND default error message
|
|
130
|
+
*
|
|
131
|
+
* @constant DEFAULT_ERROR_MESSAGES
|
|
132
|
+
* @memberOf module:decorator-validation.Validation
|
|
133
|
+
* @category Validation
|
|
134
|
+
*/
|
|
135
|
+
const DEFAULT_ERROR_MESSAGES = {
|
|
136
|
+
REQUIRED: "This field is required",
|
|
137
|
+
MIN: "The minimum value is {0}",
|
|
138
|
+
MAX: "The maximum value is {0}",
|
|
139
|
+
MIN_LENGTH: "The minimum length is {0}",
|
|
140
|
+
MAX_LENGTH: "The maximum length is {0}",
|
|
141
|
+
PATTERN: "The value does not match the pattern",
|
|
142
|
+
EMAIL: "The value is not a valid email",
|
|
143
|
+
URL: "The value is not a valid URL",
|
|
144
|
+
TYPE: "Invalid type. Expected {0}, received {1}",
|
|
145
|
+
STEP: "Invalid value. Not a step of {0}",
|
|
146
|
+
DATE: "Invalid value. not a valid Date",
|
|
147
|
+
DEFAULT: "There is an Error",
|
|
148
|
+
PASSWORD: "Must be at least 8 characters and contain one of number, lower and upper case letters, and special character (@$!%*?&_-.,)",
|
|
149
|
+
LIST: "Invalid list of {0}",
|
|
150
|
+
MODEL_NOT_FOUND: "No model registered under {0}",
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* @summary Defines the various default regexp patterns used
|
|
154
|
+
*
|
|
155
|
+
* @enum DEFAULT_PATTERNS
|
|
156
|
+
* @memberOf module:decorator-validation.Validation
|
|
157
|
+
* @category Validation
|
|
158
|
+
*/
|
|
159
|
+
const DEFAULT_PATTERNS = {
|
|
160
|
+
EMAIL: /[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/,
|
|
161
|
+
URL: /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i,
|
|
162
|
+
PASSWORD: {
|
|
163
|
+
CHAR8_ONE_OF_EACH: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&_\-.,])[A-Za-z\d@$!%*?&_\-.,]{8,}$/g,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @summary Util function to provide string format functionality similar to C#'s string.format
|
|
169
|
+
*
|
|
170
|
+
* @param {string} string
|
|
171
|
+
* @param {Array<string | number>} [args] replacements made by order of appearance (replacement0 wil replace {0} and so on)
|
|
172
|
+
* @return {string} formatted string
|
|
173
|
+
*
|
|
174
|
+
* @function stringFormat
|
|
175
|
+
* @memberOf module:decorator-validation.Utils.Format
|
|
176
|
+
* @category Format
|
|
177
|
+
*/
|
|
178
|
+
function stringFormat(string, ...args) {
|
|
179
|
+
return string.replace(/{(\d+)}/g, function (match, number) {
|
|
180
|
+
return typeof args[number] !== "undefined"
|
|
181
|
+
? args[number].toString()
|
|
182
|
+
: "undefined";
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* @summary Util function to provide string format functionality similar to C#'s string.format
|
|
187
|
+
* @description alias for {@link stringFormat}
|
|
188
|
+
*
|
|
189
|
+
* @param {string} string
|
|
190
|
+
* @param {string} args replacements made by order of appearance (replacement0 wil replace {0} and so on)
|
|
191
|
+
* @return {string} formatted string
|
|
192
|
+
*
|
|
193
|
+
* @function sf
|
|
194
|
+
* @memberOf module:decorator-validation.Utils.Format
|
|
195
|
+
* @category Format
|
|
196
|
+
*/
|
|
197
|
+
const sf = stringFormat;
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* @summary Reverses the process from {@link formatDate}
|
|
201
|
+
*
|
|
202
|
+
* @param {string} date the date string to be converted back into date
|
|
203
|
+
* @param {string} format the date format
|
|
204
|
+
* @return {Date} the date from the format or the standard new Date({@prop date}) if the string couldn't be parsed (are you sure the format matches the string?)
|
|
205
|
+
*
|
|
206
|
+
* @function dateFromFormat
|
|
207
|
+
* @memberOf module:decorator-validation.Utils.Dates
|
|
208
|
+
* @category Format
|
|
209
|
+
*/
|
|
210
|
+
function dateFromFormat(date, format) {
|
|
211
|
+
let formatRegexp = format;
|
|
212
|
+
// Hour
|
|
213
|
+
if (formatRegexp.match(/hh/))
|
|
214
|
+
formatRegexp = formatRegexp.replace("hh", "(?<hour>\\d{2})");
|
|
215
|
+
else if (formatRegexp.match(/h/))
|
|
216
|
+
formatRegexp = formatRegexp.replace("h", "(?<hour>\\d{1,2})");
|
|
217
|
+
else if (formatRegexp.match(/HH/))
|
|
218
|
+
formatRegexp = formatRegexp.replace("HH", "(?<hour>\\d{2})");
|
|
219
|
+
else if (formatRegexp.match(/H/))
|
|
220
|
+
formatRegexp = formatRegexp.replace("H", "(?<hour>\\d{1,2})");
|
|
221
|
+
// Minutes
|
|
222
|
+
if (formatRegexp.match(/mm/))
|
|
223
|
+
formatRegexp = formatRegexp.replace("mm", "(?<minutes>\\d{2})");
|
|
224
|
+
else if (formatRegexp.match(/m/))
|
|
225
|
+
formatRegexp = formatRegexp.replace("m", "(?<minutes>\\d{1,2})");
|
|
226
|
+
// Seconds
|
|
227
|
+
if (formatRegexp.match(/ss/))
|
|
228
|
+
formatRegexp = formatRegexp.replace("ss", "(?<seconds>\\d{2})");
|
|
229
|
+
else if (formatRegexp.match(/s/))
|
|
230
|
+
formatRegexp = formatRegexp.replace("s", "(?<seconds>\\d{1,2})");
|
|
231
|
+
// Day
|
|
232
|
+
if (formatRegexp.match(/dd/))
|
|
233
|
+
formatRegexp = formatRegexp.replace("dd", "(?<day>\\d{2})");
|
|
234
|
+
else if (formatRegexp.match(/d/))
|
|
235
|
+
formatRegexp = formatRegexp.replace("d", "(?<day>\\d{1,2})");
|
|
236
|
+
// Day Of Week
|
|
237
|
+
if (formatRegexp.match(/EEEE/))
|
|
238
|
+
formatRegexp = formatRegexp.replace("EEEE", "(?<dayofweek>\\w+)");
|
|
239
|
+
// eslint-disable-next-line no-dupe-else-if
|
|
240
|
+
else if (formatRegexp.match(/EEEE/))
|
|
241
|
+
formatRegexp = formatRegexp.replace("EEE", "(?<dayofweek>\\w+)");
|
|
242
|
+
// Year
|
|
243
|
+
if (formatRegexp.match(/yyyy/))
|
|
244
|
+
formatRegexp = formatRegexp.replace("yyyy", "(?<year>\\d{4})");
|
|
245
|
+
else if (formatRegexp.match(/yy/))
|
|
246
|
+
formatRegexp = formatRegexp.replace("yy", "(?<year>\\d{2})");
|
|
247
|
+
// Month
|
|
248
|
+
if (formatRegexp.match(/MMMM/))
|
|
249
|
+
formatRegexp = formatRegexp.replace("MMMM", "(?<monthname>\\w+)");
|
|
250
|
+
else if (formatRegexp.match(/MMM/))
|
|
251
|
+
formatRegexp = formatRegexp.replace("MMM", "(?<monthnamesmall>\\w+)");
|
|
252
|
+
if (formatRegexp.match(/MM/))
|
|
253
|
+
formatRegexp = formatRegexp.replace("MM", "(?<month>\\d{2})");
|
|
254
|
+
else if (formatRegexp.match(/M/))
|
|
255
|
+
formatRegexp = formatRegexp.replace("M", "(?<month>\\d{1,2})");
|
|
256
|
+
// Milis and Am Pm
|
|
257
|
+
formatRegexp = formatRegexp
|
|
258
|
+
.replace("S", "(?<milis>\\d{1,3})")
|
|
259
|
+
.replace("aaa", "(?<ampm>\\w{2})");
|
|
260
|
+
const regexp = new RegExp(formatRegexp, "g");
|
|
261
|
+
const match = regexp.exec(date);
|
|
262
|
+
if (!match || !match.groups)
|
|
263
|
+
return new Date(date);
|
|
264
|
+
const safeParseInt = function (n) {
|
|
265
|
+
if (!n)
|
|
266
|
+
return 0;
|
|
267
|
+
const result = parseInt(n);
|
|
268
|
+
return isNaN(result) ? 0 : result;
|
|
269
|
+
};
|
|
270
|
+
const year = safeParseInt(match.groups.year);
|
|
271
|
+
const day = safeParseInt(match.groups.day);
|
|
272
|
+
const amPm = match.groups.ampm;
|
|
273
|
+
let hour = safeParseInt(match.groups.hour);
|
|
274
|
+
if (amPm)
|
|
275
|
+
hour = amPm === "PM" ? hour + 12 : hour;
|
|
276
|
+
const minutes = safeParseInt(match.groups.minutes);
|
|
277
|
+
const seconds = safeParseInt(match.groups.seconds);
|
|
278
|
+
const ms = safeParseInt(match.groups.milis);
|
|
279
|
+
const monthName = match.groups.monthname;
|
|
280
|
+
const monthNameSmall = match.groups.monthnamesmall;
|
|
281
|
+
let month = match.groups.month;
|
|
282
|
+
if (monthName)
|
|
283
|
+
month = MONTH_NAMES.indexOf(monthName);
|
|
284
|
+
else if (monthNameSmall) {
|
|
285
|
+
const m = MONTH_NAMES.find((m) => m.toLowerCase().startsWith(monthNameSmall.toLowerCase()));
|
|
286
|
+
if (!m)
|
|
287
|
+
return new Date(date);
|
|
288
|
+
month = MONTH_NAMES.indexOf(m);
|
|
289
|
+
}
|
|
290
|
+
else
|
|
291
|
+
month = safeParseInt(`${month}`);
|
|
292
|
+
return new Date(year, month - 1, day, hour, minutes, seconds, ms);
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* @summary Binds a date format to a string
|
|
296
|
+
* @param {Date} [date]
|
|
297
|
+
* @param {string} [format]
|
|
298
|
+
* @memberOf module:decorator-validation.Utils.Format
|
|
299
|
+
* @category Utilities
|
|
300
|
+
*/
|
|
301
|
+
function bindDateToString(date, format) {
|
|
302
|
+
if (!date)
|
|
303
|
+
return;
|
|
304
|
+
const func = () => formatDate(date, format);
|
|
305
|
+
Object.defineProperty(date, "toISOString", {
|
|
306
|
+
enumerable: false,
|
|
307
|
+
configurable: false,
|
|
308
|
+
value: func,
|
|
309
|
+
});
|
|
310
|
+
Object.defineProperty(date, "toString", {
|
|
311
|
+
enumerable: false,
|
|
312
|
+
configurable: false,
|
|
313
|
+
value: func,
|
|
314
|
+
});
|
|
315
|
+
// Object.setPrototypeOf(date, Date.prototype);
|
|
316
|
+
return date;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* @summary Helper function to be used instead of instanceOf Date
|
|
320
|
+
* @param date
|
|
321
|
+
* @memberOf module:decorator-validation.Utils.Dates
|
|
322
|
+
* @category Validation
|
|
323
|
+
*/
|
|
324
|
+
function isValidDate(date) {
|
|
325
|
+
return (date &&
|
|
326
|
+
Object.prototype.toString.call(date) === "[object Date]" &&
|
|
327
|
+
!Number.isNaN(date));
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* @summary Util function to pad numbers
|
|
331
|
+
* @param {number} num
|
|
332
|
+
*
|
|
333
|
+
* @return {string}
|
|
334
|
+
*
|
|
335
|
+
* @function twoDigitPad
|
|
336
|
+
* @memberOf module:decorator-validation.Utils.Format
|
|
337
|
+
* @category Format
|
|
338
|
+
*/
|
|
339
|
+
function twoDigitPad(num) {
|
|
340
|
+
return num < 10 ? "0" + num : num.toString();
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* @summary Date Format Handling
|
|
344
|
+
* @description Code from {@link https://stackoverflow.com/questions/3552461/how-to-format-a-javascript-date}
|
|
345
|
+
*
|
|
346
|
+
* <pre>
|
|
347
|
+
* Using similar formatting as Moment.js, Class DateTimeFormatter (Java), and Class SimpleDateFormat (Java),
|
|
348
|
+
* I implemented a comprehensive solution formatDate(date, patternStr) where the code is easy to read and modify.
|
|
349
|
+
* You can display date, time, AM/PM, etc.
|
|
350
|
+
*
|
|
351
|
+
* Date and Time Patterns
|
|
352
|
+
* yy = 2-digit year; yyyy = full year
|
|
353
|
+
* M = digit month; MM = 2-digit month; MMM = short month name; MMMM = full month name
|
|
354
|
+
* EEEE = full weekday name; EEE = short weekday name
|
|
355
|
+
* d = digit day; dd = 2-digit day
|
|
356
|
+
* h = hours am/pm; hh = 2-digit hours am/pm; H = hours; HH = 2-digit hours
|
|
357
|
+
* m = minutes; mm = 2-digit minutes; aaa = AM/PM
|
|
358
|
+
* s = seconds; ss = 2-digit seconds
|
|
359
|
+
* S = miliseconds
|
|
360
|
+
* </pre>
|
|
361
|
+
*
|
|
362
|
+
* @param {Date} date
|
|
363
|
+
* @param {string} [patternStr] defaults to 'yyyy/MM/dd'
|
|
364
|
+
* @return {string} the formatted date
|
|
365
|
+
*
|
|
366
|
+
* @function formatDate
|
|
367
|
+
* @memberOf module:decorator-validation.Utils.Dates
|
|
368
|
+
* @category Format
|
|
369
|
+
*/
|
|
370
|
+
function formatDate(date, patternStr = "yyyy/MM/dd") {
|
|
371
|
+
const day = date.getDate(), month = date.getMonth(), year = date.getFullYear(), hour = date.getHours(), minute = date.getMinutes(), second = date.getSeconds(), miliseconds = date.getMilliseconds(), h = hour % 12, hh = twoDigitPad(h), HH = twoDigitPad(hour), mm = twoDigitPad(minute), ss = twoDigitPad(second), aaa = hour < 12 ? "AM" : "PM", EEEE = DAYS_OF_WEEK_NAMES[date.getDay()], EEE = EEEE.substr(0, 3), dd = twoDigitPad(day), M = month + 1, MM = twoDigitPad(M), MMMM = MONTH_NAMES[month], MMM = MMMM.substr(0, 3), yyyy = year + "", yy = yyyy.substr(2, 2);
|
|
372
|
+
// checks to see if month name will be used
|
|
373
|
+
patternStr = patternStr
|
|
374
|
+
.replace("hh", hh)
|
|
375
|
+
.replace("h", h.toString())
|
|
376
|
+
.replace("HH", HH)
|
|
377
|
+
.replace("H", hour.toString())
|
|
378
|
+
.replace("mm", mm)
|
|
379
|
+
.replace("m", minute.toString())
|
|
380
|
+
.replace("ss", ss)
|
|
381
|
+
.replace("s", second.toString())
|
|
382
|
+
.replace("S", miliseconds.toString())
|
|
383
|
+
.replace("dd", dd)
|
|
384
|
+
.replace("d", day.toString())
|
|
385
|
+
.replace("EEEE", EEEE)
|
|
386
|
+
.replace("EEE", EEE)
|
|
387
|
+
.replace("yyyy", yyyy)
|
|
388
|
+
.replace("yy", yy)
|
|
389
|
+
.replace("aaa", aaa);
|
|
390
|
+
if (patternStr.indexOf("MMM") > -1) {
|
|
391
|
+
patternStr = patternStr.replace("MMMM", MMMM).replace("MMM", MMM);
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
patternStr = patternStr.replace("MM", MM).replace("M", M.toString());
|
|
395
|
+
}
|
|
396
|
+
return patternStr;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* @summary Parses a date from a specified format
|
|
400
|
+
* @param {string} format
|
|
401
|
+
* @param {string | Date | number} [v]
|
|
402
|
+
* @memberOf module:decorator-validation.Utils.Dates
|
|
403
|
+
* @category Format
|
|
404
|
+
*/
|
|
405
|
+
function parseDate(format, v) {
|
|
406
|
+
let value = undefined;
|
|
407
|
+
if (!v)
|
|
408
|
+
return undefined;
|
|
409
|
+
if (v instanceof Date)
|
|
410
|
+
try {
|
|
411
|
+
value = dateFromFormat(formatDate(v, format), format);
|
|
412
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
413
|
+
}
|
|
414
|
+
catch (e) {
|
|
415
|
+
throw new Error(sf("Could not convert date {0} to format: {1}", v.toString(), format));
|
|
416
|
+
}
|
|
417
|
+
else if (typeof v === "string") {
|
|
418
|
+
value = dateFromFormat(v, format);
|
|
419
|
+
}
|
|
420
|
+
else if (typeof v === "number") {
|
|
421
|
+
const d = new Date(v);
|
|
422
|
+
value = dateFromFormat(formatDate(d, format), format);
|
|
423
|
+
}
|
|
424
|
+
else if (isValidDate(v)) {
|
|
425
|
+
try {
|
|
426
|
+
const d = new Date(v);
|
|
427
|
+
value = dateFromFormat(formatDate(d, format), format);
|
|
428
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
429
|
+
}
|
|
430
|
+
catch (e) {
|
|
431
|
+
throw new Error(sf("Could not convert date {0} to format: {1}", v, format));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
throw new Error(`Invalid value provided ${v}`);
|
|
436
|
+
}
|
|
437
|
+
return bindDateToString(value, format);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function prop(key = ModelKeys.ATTRIBUTE) {
|
|
441
|
+
return (model, propertyKey) => {
|
|
442
|
+
let props;
|
|
443
|
+
if (Object.prototype.hasOwnProperty.call(model, key)) {
|
|
444
|
+
props = model[key];
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
props = model[key] = [];
|
|
448
|
+
}
|
|
449
|
+
if (!props.includes(propertyKey))
|
|
450
|
+
props.push(propertyKey);
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
function propMetadata(key, value) {
|
|
454
|
+
return apply(prop(), metadata(key, value));
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* @summary Mimics Java's String's Hash implementation
|
|
459
|
+
*
|
|
460
|
+
* @param {string | number | symbol | Date} obj
|
|
461
|
+
* @return {number} hash value of obj
|
|
462
|
+
*
|
|
463
|
+
* @function hashCode
|
|
464
|
+
* @memberOf module:decorator-validation.Utils.Hashing
|
|
465
|
+
* @category Hashing
|
|
466
|
+
*/
|
|
467
|
+
function hashCode(obj) {
|
|
468
|
+
obj = String(obj);
|
|
469
|
+
let hash = 0;
|
|
470
|
+
for (let i = 0; i < obj.length; i++) {
|
|
471
|
+
const character = obj.charCodeAt(i);
|
|
472
|
+
hash = (hash << 5) - hash + character;
|
|
473
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
474
|
+
}
|
|
475
|
+
return hash.toString();
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* @summary Hashes an object by combining the hash of all its properties
|
|
479
|
+
*
|
|
480
|
+
* @param {Record<string, any>} obj
|
|
481
|
+
* @return {string} the resulting hash
|
|
482
|
+
*
|
|
483
|
+
* @function hashObj
|
|
484
|
+
* @memberOf module:decorator-validation.Utils.Hashing
|
|
485
|
+
* @category Hashing
|
|
486
|
+
*/
|
|
487
|
+
function hashObj(obj) {
|
|
488
|
+
const hashReducer = function (h, el) {
|
|
489
|
+
const elHash = hashFunction(el);
|
|
490
|
+
if (typeof elHash === "string")
|
|
491
|
+
return hashFunction((h || "") + hashFunction(el));
|
|
492
|
+
h = h || 0;
|
|
493
|
+
h = (h << 5) - h + elHash;
|
|
494
|
+
return h & h;
|
|
495
|
+
};
|
|
496
|
+
const func = hashCode;
|
|
497
|
+
const hashFunction = function (value) {
|
|
498
|
+
if (typeof value === "undefined")
|
|
499
|
+
return "";
|
|
500
|
+
if (["string", "number", "symbol"].indexOf(typeof value) !== -1)
|
|
501
|
+
return func(value.toString());
|
|
502
|
+
if (value instanceof Date)
|
|
503
|
+
return func(value.getTime());
|
|
504
|
+
if (Array.isArray(value))
|
|
505
|
+
return value.reduce(hashReducer, undefined);
|
|
506
|
+
return Object.values(value).reduce(hashReducer, undefined);
|
|
507
|
+
};
|
|
508
|
+
const result = Object.values(obj).reduce(hashReducer, 0);
|
|
509
|
+
return (typeof result === "number" ? Math.abs(result) : result).toString();
|
|
510
|
+
}
|
|
511
|
+
const DefaultHashingMethod = "default";
|
|
512
|
+
class Hashing {
|
|
513
|
+
static { this.current = DefaultHashingMethod; }
|
|
514
|
+
static { this.cache = {
|
|
515
|
+
default: hashObj,
|
|
516
|
+
}; }
|
|
517
|
+
constructor() { }
|
|
518
|
+
static get(key) {
|
|
519
|
+
if (key in this.cache)
|
|
520
|
+
return this.cache[key];
|
|
521
|
+
throw new Error(`No hashing method registered under ${key}`);
|
|
522
|
+
}
|
|
523
|
+
static register(key, func, setDefault = false) {
|
|
524
|
+
if (key in this.cache)
|
|
525
|
+
throw new Error(`Hashing method ${key} already registered`);
|
|
526
|
+
this.cache[key] = func;
|
|
527
|
+
if (setDefault)
|
|
528
|
+
this.current = key;
|
|
529
|
+
}
|
|
530
|
+
static hash(obj, method, ...args) {
|
|
531
|
+
if (!method)
|
|
532
|
+
return this.get(this.current)(obj, ...args);
|
|
533
|
+
return this.get(method)(obj, ...args);
|
|
534
|
+
}
|
|
535
|
+
static setDefault(method) {
|
|
536
|
+
this.current = this.get(method);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* @summary Helper Class to hold the error results
|
|
542
|
+
* @description holds error results in an 'indexable' manner
|
|
543
|
+
* while still providing the same result on toString
|
|
544
|
+
*
|
|
545
|
+
* @param {ModelErrors} errors
|
|
546
|
+
*
|
|
547
|
+
* @class ModelErrorDefinition
|
|
548
|
+
*
|
|
549
|
+
* @category Model
|
|
550
|
+
*/
|
|
551
|
+
class ModelErrorDefinition {
|
|
552
|
+
constructor(errors) {
|
|
553
|
+
for (const prop in errors) {
|
|
554
|
+
if (Object.prototype.hasOwnProperty.call(errors, prop) && errors[prop])
|
|
555
|
+
Object.defineProperty(this, prop, {
|
|
556
|
+
enumerable: true,
|
|
557
|
+
configurable: false,
|
|
558
|
+
value: errors[prop],
|
|
559
|
+
writable: false,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* @summary Outputs the class to a nice readable string
|
|
565
|
+
*
|
|
566
|
+
* @override
|
|
567
|
+
*/
|
|
568
|
+
toString() {
|
|
569
|
+
const self = this;
|
|
570
|
+
return Object.keys(self)
|
|
571
|
+
.filter((k) => Object.prototype.hasOwnProperty.call(self, k) &&
|
|
572
|
+
typeof self[k] !== "function")
|
|
573
|
+
.reduce((accum, prop) => {
|
|
574
|
+
let propError = Object.keys(self[prop]).reduce((propAccum, key) => {
|
|
575
|
+
if (!propAccum)
|
|
576
|
+
propAccum = self[prop][key];
|
|
577
|
+
else
|
|
578
|
+
propAccum += `\n${self[prop][key]}`;
|
|
579
|
+
return propAccum;
|
|
580
|
+
}, undefined);
|
|
581
|
+
if (propError) {
|
|
582
|
+
propError = `${prop} - ${propError}`;
|
|
583
|
+
if (!accum)
|
|
584
|
+
accum = propError;
|
|
585
|
+
else
|
|
586
|
+
accum += `\n${propError}`;
|
|
587
|
+
}
|
|
588
|
+
return accum;
|
|
589
|
+
}, "");
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* @summary References the relevant JS primitives
|
|
595
|
+
*
|
|
596
|
+
* @property {string} STRING references the string primitive
|
|
597
|
+
* @property {string} NUMBER references the number primitive
|
|
598
|
+
* @property {string} BOOLEAN references the boolean primitive
|
|
599
|
+
* @property {string} BIGINT references the bigint primitive
|
|
600
|
+
*
|
|
601
|
+
* @constant Primitives
|
|
602
|
+
* @memberOf module:decorator-validation.Model
|
|
603
|
+
*/
|
|
604
|
+
var Primitives;
|
|
605
|
+
(function (Primitives) {
|
|
606
|
+
Primitives["STRING"] = "string";
|
|
607
|
+
Primitives["NUMBER"] = "number";
|
|
608
|
+
Primitives["BOOLEAN"] = "boolean";
|
|
609
|
+
Primitives["BIGINT"] = "bigint";
|
|
610
|
+
})(Primitives || (Primitives = {}));
|
|
611
|
+
/**
|
|
612
|
+
* @summary References the Reserved model names to ignore during Model rebuilding
|
|
613
|
+
*
|
|
614
|
+
* @property {string} STRING
|
|
615
|
+
* @property {string} OBJECT
|
|
616
|
+
* @property {string} NUMBER
|
|
617
|
+
* @property {string} BOOLEAN
|
|
618
|
+
* @property {string} BIGINT
|
|
619
|
+
* @property {string} DATE
|
|
620
|
+
*
|
|
621
|
+
* @constant ReservedModels
|
|
622
|
+
* @memberOf module:decorator-validation.Model
|
|
623
|
+
*/
|
|
624
|
+
var ReservedModels;
|
|
625
|
+
(function (ReservedModels) {
|
|
626
|
+
ReservedModels["STRING"] = "string";
|
|
627
|
+
ReservedModels["OBJECT"] = "object";
|
|
628
|
+
ReservedModels["NUMBER"] = "number";
|
|
629
|
+
ReservedModels["BOOLEAN"] = "boolean";
|
|
630
|
+
ReservedModels["BIGINT"] = "bigint";
|
|
631
|
+
ReservedModels["DATE"] = "date";
|
|
632
|
+
})(ReservedModels || (ReservedModels = {}));
|
|
633
|
+
/**
|
|
634
|
+
* @summary References the basic supported js types
|
|
635
|
+
*
|
|
636
|
+
* @property {string} string
|
|
637
|
+
* @property {string} array
|
|
638
|
+
* @property {string} number
|
|
639
|
+
* @property {string} boolean
|
|
640
|
+
* @property {string} symbol
|
|
641
|
+
* @property {string} function
|
|
642
|
+
* @property {string} object
|
|
643
|
+
* @property {string} undefined
|
|
644
|
+
* @property {string} null
|
|
645
|
+
* @property {string} BIGINT
|
|
646
|
+
*
|
|
647
|
+
* @constant jsTypes
|
|
648
|
+
* @memberOf module:decorator-validation.Model
|
|
649
|
+
*/
|
|
650
|
+
const jsTypes = [
|
|
651
|
+
"string",
|
|
652
|
+
"array",
|
|
653
|
+
"number",
|
|
654
|
+
"boolean",
|
|
655
|
+
"symbol",
|
|
656
|
+
"function",
|
|
657
|
+
"object",
|
|
658
|
+
"undefined",
|
|
659
|
+
"null",
|
|
660
|
+
"bigint",
|
|
661
|
+
];
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* @summary Duck typing for Validators
|
|
665
|
+
* @function isValidator
|
|
666
|
+
* @param val
|
|
667
|
+
*/
|
|
668
|
+
function isValidator(val) {
|
|
669
|
+
return val.constructor && val["hasErrors"];
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* @summary Base Implementation of a Validator Registry
|
|
673
|
+
*
|
|
674
|
+
* @prop {Validator[]} [validators] the initial validators to register
|
|
675
|
+
*
|
|
676
|
+
* @class ValidatorRegistry
|
|
677
|
+
* @implements IValidatorRegistry<T>
|
|
678
|
+
*
|
|
679
|
+
* @category Validation
|
|
680
|
+
*/
|
|
681
|
+
class ValidatorRegistry {
|
|
682
|
+
constructor(...validators) {
|
|
683
|
+
this.cache = {};
|
|
684
|
+
this.customKeyCache = {};
|
|
685
|
+
this.register(...validators);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* @summary retrieves the custom keys
|
|
689
|
+
*/
|
|
690
|
+
getCustomKeys() {
|
|
691
|
+
return Object.assign({}, this.customKeyCache);
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* @summary retrieves the registered validators keys
|
|
695
|
+
*/
|
|
696
|
+
getKeys() {
|
|
697
|
+
return Object.keys(this.cache);
|
|
698
|
+
}
|
|
699
|
+
/**
|
|
700
|
+
* @summary Retrieves a validator
|
|
701
|
+
*
|
|
702
|
+
* @param {string} validatorKey one of the {@link ValidationKeys}
|
|
703
|
+
* @return {Validator | undefined} the registered Validator or undefined if there is nono matching the provided key
|
|
704
|
+
*/
|
|
705
|
+
get(validatorKey) {
|
|
706
|
+
if (!(validatorKey in this.cache))
|
|
707
|
+
return undefined;
|
|
708
|
+
const classOrInstance = this.cache[validatorKey];
|
|
709
|
+
if (isValidator(classOrInstance))
|
|
710
|
+
return classOrInstance;
|
|
711
|
+
const constructor = classOrInstance.default || classOrInstance;
|
|
712
|
+
const instance = new constructor();
|
|
713
|
+
this.cache[validatorKey] = instance;
|
|
714
|
+
return instance;
|
|
715
|
+
}
|
|
716
|
+
/**
|
|
717
|
+
* @summary Registers the provided validators onto the registry
|
|
718
|
+
*
|
|
719
|
+
* @param {T[] | ValidatorDefinition[]} validator
|
|
720
|
+
*/
|
|
721
|
+
register(...validator) {
|
|
722
|
+
validator.forEach((v) => {
|
|
723
|
+
if (isValidator(v)) {
|
|
724
|
+
// const k =
|
|
725
|
+
if (v.validationKey in this.cache)
|
|
726
|
+
return;
|
|
727
|
+
this.cache[v.validationKey] = v;
|
|
728
|
+
}
|
|
729
|
+
else {
|
|
730
|
+
const { validationKey, validator, save } = v;
|
|
731
|
+
if (validationKey in this.cache)
|
|
732
|
+
return;
|
|
733
|
+
this.cache[validationKey] = validator;
|
|
734
|
+
if (!save)
|
|
735
|
+
return;
|
|
736
|
+
const obj = {};
|
|
737
|
+
obj[validationKey.toUpperCase()] = validationKey;
|
|
738
|
+
this.customKeyCache = Object.assign({}, this.customKeyCache, obj);
|
|
739
|
+
}
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* @summary Static class acting as a namespace for the Validation
|
|
746
|
+
*
|
|
747
|
+
* @class Validation
|
|
748
|
+
* @static
|
|
749
|
+
*
|
|
750
|
+
* @category Validation
|
|
751
|
+
*/
|
|
752
|
+
class Validation {
|
|
753
|
+
static { this.actingValidatorRegistry = undefined; }
|
|
754
|
+
constructor() { }
|
|
755
|
+
/**
|
|
756
|
+
* @summary Defines the acting ValidatorRegistry
|
|
757
|
+
*
|
|
758
|
+
* @param {IValidatorRegistry} validatorRegistry the new implementation of the validator Registry
|
|
759
|
+
* @param {function(Validator): Validator} [migrationHandler] the method to map the validator if required;
|
|
760
|
+
*/
|
|
761
|
+
static setRegistry(validatorRegistry, migrationHandler) {
|
|
762
|
+
if (migrationHandler && Validation.actingValidatorRegistry)
|
|
763
|
+
Validation.actingValidatorRegistry.getKeys().forEach((k) => {
|
|
764
|
+
const validator = validatorRegistry.get(k);
|
|
765
|
+
if (validator)
|
|
766
|
+
validatorRegistry.register(migrationHandler(validator));
|
|
767
|
+
});
|
|
768
|
+
Validation.actingValidatorRegistry = validatorRegistry;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* @summary Returns the current ValidatorRegistry
|
|
772
|
+
*
|
|
773
|
+
* @return IValidatorRegistry, defaults to {@link ValidatorRegistry}
|
|
774
|
+
*/
|
|
775
|
+
static getRegistry() {
|
|
776
|
+
if (!Validation.actingValidatorRegistry)
|
|
777
|
+
Validation.actingValidatorRegistry = new ValidatorRegistry();
|
|
778
|
+
return Validation.actingValidatorRegistry;
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* @summary Retrieves a validator
|
|
782
|
+
*
|
|
783
|
+
* @param {string} validatorKey one of the {@link ValidationKeys}
|
|
784
|
+
* @return {Validator | undefined} the registered Validator or undefined if there is nono matching the provided key
|
|
785
|
+
*/
|
|
786
|
+
static get(validatorKey) {
|
|
787
|
+
return Validation.getRegistry().get(validatorKey);
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* @summary Registers the provided validators onto the registry
|
|
791
|
+
*
|
|
792
|
+
* @param {T[] | ValidatorDefinition[]} validator
|
|
793
|
+
*/
|
|
794
|
+
static register(...validator) {
|
|
795
|
+
return Validation.getRegistry().register(...validator);
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* @summary Builds the key to store as Metadata under Reflections
|
|
799
|
+
* @description concatenates {@link ValidationKeys#REFLECT} with the provided key
|
|
800
|
+
*
|
|
801
|
+
* @param {string} key
|
|
802
|
+
*/
|
|
803
|
+
static key(key) {
|
|
804
|
+
return ValidationKeys.REFLECT + key;
|
|
805
|
+
}
|
|
806
|
+
/**
|
|
807
|
+
* @summary Returns all registered validation keys
|
|
808
|
+
*/
|
|
809
|
+
static keys() {
|
|
810
|
+
return this.getRegistry().getKeys();
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* @summary Analyses the decorations of the properties and validates the obj according to them
|
|
816
|
+
*
|
|
817
|
+
* @typedef T extends Model
|
|
818
|
+
* @prop {T} obj Model object to validate
|
|
819
|
+
* @prop {string[]} [propsToIgnore] object properties to ignore in the validation
|
|
820
|
+
*
|
|
821
|
+
* @function validate
|
|
822
|
+
* @memberOf module:decorator-validation.Validation
|
|
823
|
+
* @category Validation
|
|
824
|
+
*/
|
|
825
|
+
function validate(obj, ...propsToIgnore) {
|
|
826
|
+
const decoratedProperties = [];
|
|
827
|
+
for (const prop in obj)
|
|
828
|
+
if (Object.prototype.hasOwnProperty.call(obj, prop) &&
|
|
829
|
+
propsToIgnore.indexOf(prop) === -1)
|
|
830
|
+
decoratedProperties.push(Reflection.getPropertyDecorators(ValidationKeys.REFLECT, obj, prop));
|
|
831
|
+
let result = undefined;
|
|
832
|
+
for (const decoratedProperty of decoratedProperties) {
|
|
833
|
+
const { prop, decorators } = decoratedProperty;
|
|
834
|
+
if (!decorators || !decorators.length)
|
|
835
|
+
continue;
|
|
836
|
+
const defaultTypeDecorator = decorators[0];
|
|
837
|
+
// tries to find any type decorators or other decorators that already enforce type (the ones with the allowed types property defined). if so, skip the default type verification
|
|
838
|
+
if (decorators.find((d) => {
|
|
839
|
+
if (d.key === ValidationKeys.TYPE)
|
|
840
|
+
return true;
|
|
841
|
+
return !!d.props.types?.find((t) => t === defaultTypeDecorator.props.name);
|
|
842
|
+
})) {
|
|
843
|
+
decorators.shift(); // remove the design:type decorator, since the type will already be checked
|
|
844
|
+
}
|
|
845
|
+
let errs = undefined;
|
|
846
|
+
for (const decorator of decorators) {
|
|
847
|
+
const validator = Validation.get(decorator.key);
|
|
848
|
+
if (!validator) {
|
|
849
|
+
throw new Error(`Missing validator for ${decorator.key}`);
|
|
850
|
+
}
|
|
851
|
+
const decoratorProps = decorator.key === ModelKeys.TYPE
|
|
852
|
+
? [decorator.props]
|
|
853
|
+
: decorator.props || {};
|
|
854
|
+
const err = validator.hasErrors(obj[prop.toString()], decoratorProps);
|
|
855
|
+
if (err) {
|
|
856
|
+
errs = errs || {};
|
|
857
|
+
errs[decorator.key] = err;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
if (errs) {
|
|
861
|
+
result = result || {};
|
|
862
|
+
result[decoratedProperty.prop.toString()] = errs;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
// tests nested classes
|
|
866
|
+
for (const prop of Object.keys(obj).filter((k) => !result || !result[k])) {
|
|
867
|
+
let err;
|
|
868
|
+
// if a nested Model
|
|
869
|
+
const allDecorators = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, obj, prop).decorators;
|
|
870
|
+
const decorators = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, obj, prop).decorators.filter((d) => [ModelKeys.TYPE, ValidationKeys.TYPE].indexOf(d.key) !== -1);
|
|
871
|
+
if (!decorators || !decorators.length)
|
|
872
|
+
continue;
|
|
873
|
+
const dec = decorators.pop();
|
|
874
|
+
const clazz = dec.props.name
|
|
875
|
+
? [dec.props.name]
|
|
876
|
+
: Array.isArray(dec.props.customTypes)
|
|
877
|
+
? dec.props.customTypes
|
|
878
|
+
: [dec.props.customTypes];
|
|
879
|
+
const reserved = Object.values(ReservedModels).map((v) => v.toLowerCase());
|
|
880
|
+
for (const c of clazz) {
|
|
881
|
+
if (reserved.indexOf(c.toLowerCase()) === -1) {
|
|
882
|
+
const typeDecoratorKey = Array.isArray(obj[prop])
|
|
883
|
+
? ValidationKeys.LIST
|
|
884
|
+
: ValidationKeys.TYPE;
|
|
885
|
+
const types = allDecorators.find((d) => d.key === typeDecoratorKey) || {};
|
|
886
|
+
let allowedTypes = [];
|
|
887
|
+
if (types && types.props) {
|
|
888
|
+
const customTypes = Array.isArray(obj[prop])
|
|
889
|
+
? types.props.class
|
|
890
|
+
: types.props.customTypes;
|
|
891
|
+
if (customTypes)
|
|
892
|
+
allowedTypes = Array.isArray(customTypes)
|
|
893
|
+
? customTypes.map((t) => `${t}`.toLowerCase())
|
|
894
|
+
: [customTypes.toLowerCase()];
|
|
895
|
+
}
|
|
896
|
+
const validate = (prop, value) => {
|
|
897
|
+
if (typeof value === "object" || typeof value === "function")
|
|
898
|
+
return isModel(value)
|
|
899
|
+
? value.hasErrors()
|
|
900
|
+
: allowedTypes.includes(typeof value)
|
|
901
|
+
? undefined
|
|
902
|
+
: "Value has no validatable type";
|
|
903
|
+
};
|
|
904
|
+
switch (c) {
|
|
905
|
+
case Array.name:
|
|
906
|
+
case Set.name:
|
|
907
|
+
if (allDecorators.length) {
|
|
908
|
+
const listDec = allDecorators.find((d) => d.key === ValidationKeys.LIST);
|
|
909
|
+
if (listDec) {
|
|
910
|
+
err = (c === Array.name
|
|
911
|
+
? obj[prop]
|
|
912
|
+
: // If it's a Set
|
|
913
|
+
obj[prop].values())
|
|
914
|
+
.map((v) => validate(prop, v))
|
|
915
|
+
.filter((e) => !!e);
|
|
916
|
+
if (!err?.length) {
|
|
917
|
+
// if the result is an empty list...
|
|
918
|
+
err = undefined;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
break;
|
|
923
|
+
default:
|
|
924
|
+
try {
|
|
925
|
+
if (obj[prop])
|
|
926
|
+
err = validate(prop, obj[prop]);
|
|
927
|
+
}
|
|
928
|
+
catch (e) {
|
|
929
|
+
console.warn(sf("Model should be validatable but its not: " + e));
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
if (err) {
|
|
934
|
+
result = result || {};
|
|
935
|
+
result[prop] = err;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return result ? new ModelErrorDefinition(result) : undefined;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
let modelBuilderFunction;
|
|
943
|
+
let actingModelRegistry;
|
|
944
|
+
function isPropertyModel(target, attribute) {
|
|
945
|
+
if (isModel(target[attribute]))
|
|
946
|
+
return true;
|
|
947
|
+
const metadata = Reflect.getMetadata(ModelKeys.TYPE, target, attribute);
|
|
948
|
+
return Model.get(metadata.name) ? metadata.name : undefined;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* @summary For Serialization/deserialization purposes.
|
|
952
|
+
* @description Reads the {@link ModelKeys.ANCHOR} property of a {@link Model} to discover the class to instantiate
|
|
953
|
+
*
|
|
954
|
+
* @function isModel
|
|
955
|
+
* @memberOf module:decorator-validation.Validation
|
|
956
|
+
* @category Validation
|
|
957
|
+
*/
|
|
958
|
+
function isModel(target) {
|
|
959
|
+
try {
|
|
960
|
+
return target instanceof Model || !!Model.getMetadata(target);
|
|
961
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
962
|
+
}
|
|
963
|
+
catch (e) {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* @summary Util class to enable serialization and correct rebuilding
|
|
969
|
+
*
|
|
970
|
+
* @param {string} anchorKey defaults to {@link ModelKeys.ANCHOR}. The property name where the registered class name is stored;
|
|
971
|
+
* @param {function(Record<string, any>): boolean} [testFunction] method to test if the provided object is a Model Object. defaults to {@link isModel}
|
|
972
|
+
*
|
|
973
|
+
* @class ModelRegistryManager
|
|
974
|
+
* @implements ModelRegistry
|
|
975
|
+
*
|
|
976
|
+
* @category Model
|
|
977
|
+
*/
|
|
978
|
+
class ModelRegistryManager {
|
|
979
|
+
constructor(testFunction = isModel) {
|
|
980
|
+
this.cache = {};
|
|
981
|
+
this.testFunction = testFunction;
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* @summary register new Models
|
|
985
|
+
* @param {any} constructor
|
|
986
|
+
* @param {string} [name] when not defined, the name of the constructor will be used
|
|
987
|
+
*/
|
|
988
|
+
register(constructor, name) {
|
|
989
|
+
if (typeof constructor !== "function")
|
|
990
|
+
throw new Error("Model registering failed. Missing Class name or constructor");
|
|
991
|
+
name = name || constructor.name;
|
|
992
|
+
this.cache[name] = constructor;
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* @summary Gets a registered Model {@link ModelConstructor}
|
|
996
|
+
* @param {string} name
|
|
997
|
+
*/
|
|
998
|
+
get(name) {
|
|
999
|
+
try {
|
|
1000
|
+
return this.cache[name];
|
|
1001
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1002
|
+
}
|
|
1003
|
+
catch (e) {
|
|
1004
|
+
return undefined;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* @param {Record<string, any>} obj
|
|
1009
|
+
* @param {string} [clazz] when provided, it will attempt to find the matching constructor
|
|
1010
|
+
*
|
|
1011
|
+
* @throws Error If clazz is not found, or obj is not a {@link Model} meaning it has no {@link ModelKeys.ANCHOR} property
|
|
1012
|
+
*/
|
|
1013
|
+
build(obj = {}, clazz) {
|
|
1014
|
+
if (!clazz && !this.testFunction(obj))
|
|
1015
|
+
throw new Error("Provided obj is not a Model object");
|
|
1016
|
+
const name = clazz || Model.getMetadata(obj);
|
|
1017
|
+
if (!(name in this.cache))
|
|
1018
|
+
throw new Error(sf("Provided class {0} is not a registered Model object", name));
|
|
1019
|
+
return new this.cache[name](obj);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* @summary Bulk Registers Models
|
|
1024
|
+
* @description Useful when using bundlers that might not evaluate all the code at once
|
|
1025
|
+
*
|
|
1026
|
+
* @param {Array<Constructor<T>> | Array<{name: string, constructor: Constructor<T>}>} [models]
|
|
1027
|
+
*
|
|
1028
|
+
* @memberOf module:decorator-validation.Model
|
|
1029
|
+
* @category Model
|
|
1030
|
+
*/
|
|
1031
|
+
function bulkModelRegister(...models) {
|
|
1032
|
+
models.forEach((m) => {
|
|
1033
|
+
const constructor = (m.constructor ? m.constructor : m);
|
|
1034
|
+
Model.register(constructor, m.name);
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* @summary Abstract class representing a Validatable Model object
|
|
1039
|
+
* @description Meant to be used as a base class for all Model classes
|
|
1040
|
+
*
|
|
1041
|
+
* Model objects must:
|
|
1042
|
+
* - Have all their required properties marked with '!';
|
|
1043
|
+
* - Have all their optional properties marked as '?':
|
|
1044
|
+
*
|
|
1045
|
+
* @param {Model | {}} model base object from which to populate properties from
|
|
1046
|
+
*
|
|
1047
|
+
* @class Model
|
|
1048
|
+
* @abstract
|
|
1049
|
+
* @implements Validatable
|
|
1050
|
+
* @implements Serializable
|
|
1051
|
+
*
|
|
1052
|
+
* @example
|
|
1053
|
+
* class ClassName {
|
|
1054
|
+
* @required()
|
|
1055
|
+
* requiredPropertyName!: PropertyType;
|
|
1056
|
+
*
|
|
1057
|
+
* optionalPropertyName?: PropertyType;
|
|
1058
|
+
* }
|
|
1059
|
+
*/
|
|
1060
|
+
class Model {
|
|
1061
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1062
|
+
constructor(arg) { }
|
|
1063
|
+
/**
|
|
1064
|
+
* @summary Validates the object according to its decorated properties
|
|
1065
|
+
*
|
|
1066
|
+
* @param {any[]} [exceptions] properties in the object to be ignored for the validation. Marked as 'any' to allow for extension but expects strings
|
|
1067
|
+
*/
|
|
1068
|
+
hasErrors(...exceptions) {
|
|
1069
|
+
return validate(this, ...exceptions);
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* @summary Compare object equality recursively
|
|
1073
|
+
* @param {any} obj object to compare to
|
|
1074
|
+
* @param {string} [exceptions] property names to be excluded from the comparison
|
|
1075
|
+
*/
|
|
1076
|
+
equals(obj, ...exceptions) {
|
|
1077
|
+
return isEqual(this, obj, ...exceptions);
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* @summary Returns the serialized model according to the currently defined {@link Serializer}
|
|
1081
|
+
*/
|
|
1082
|
+
serialize() {
|
|
1083
|
+
return Model.serialize(this);
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* @summary Override the implementation for js's 'toString()' which sucks...
|
|
1087
|
+
* @override
|
|
1088
|
+
*/
|
|
1089
|
+
toString() {
|
|
1090
|
+
return this.constructor.name + ": " + JSON.stringify(this, undefined, 2);
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* @summary Defines a default implementation for object hash. Relies on a very basic implementation based on Java's string hash;
|
|
1094
|
+
*/
|
|
1095
|
+
hash() {
|
|
1096
|
+
return Model.hash(this);
|
|
1097
|
+
}
|
|
1098
|
+
/**
|
|
1099
|
+
* @summary Deserializes a Model
|
|
1100
|
+
* @param {string} str
|
|
1101
|
+
*
|
|
1102
|
+
* @throws {Error} If it fails to parse the string, or if it fails to build the model
|
|
1103
|
+
*/
|
|
1104
|
+
static deserialize(str) {
|
|
1105
|
+
const metadata = Reflect.getMetadata(Model.key(ModelKeys.SERIALIZATION), this.constructor);
|
|
1106
|
+
if (metadata && metadata.serializer)
|
|
1107
|
+
return Serialization.deserialize(str, metadata.serializer, ...(metadata.args || []));
|
|
1108
|
+
return Serialization.deserialize(str);
|
|
1109
|
+
}
|
|
1110
|
+
/**
|
|
1111
|
+
* @summary Repopulates the Object properties with the ones from the new object
|
|
1112
|
+
* @description Iterates all common properties of obj (if existing) and self, and copies them onto self
|
|
1113
|
+
*
|
|
1114
|
+
* @param {T} self
|
|
1115
|
+
* @param {T | Record<string, any>} [obj]
|
|
1116
|
+
*
|
|
1117
|
+
*/
|
|
1118
|
+
static fromObject(self, obj) {
|
|
1119
|
+
if (!obj)
|
|
1120
|
+
obj = {};
|
|
1121
|
+
for (const prop of Model.getAttributes(self)) {
|
|
1122
|
+
self[prop] = obj[prop] || undefined;
|
|
1123
|
+
}
|
|
1124
|
+
return self;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* @summary Repopulates the instance with the ones from the new Model Object
|
|
1128
|
+
* @description Iterates all common properties of obj (if existing) and self, and copies them onto self.
|
|
1129
|
+
* Is aware of nested Model Objects and rebuilds them also.
|
|
1130
|
+
* When List properties are decorated with {@link list}, they list items will also be rebuilt
|
|
1131
|
+
*
|
|
1132
|
+
* @param {T} self
|
|
1133
|
+
* @param {T | Record<string, any>} [obj]
|
|
1134
|
+
*
|
|
1135
|
+
*/
|
|
1136
|
+
static fromModel(self, obj) {
|
|
1137
|
+
if (!obj)
|
|
1138
|
+
obj = {};
|
|
1139
|
+
let decorators, dec;
|
|
1140
|
+
const props = Model.getAttributes(self);
|
|
1141
|
+
for (const prop of props) {
|
|
1142
|
+
self[prop] =
|
|
1143
|
+
obj[prop] || undefined;
|
|
1144
|
+
if (typeof self[prop] !== "object")
|
|
1145
|
+
continue;
|
|
1146
|
+
const propM = isPropertyModel(self, prop);
|
|
1147
|
+
if (propM) {
|
|
1148
|
+
try {
|
|
1149
|
+
self[prop] = Model.build(self[prop], typeof propM === "string" ? propM : undefined);
|
|
1150
|
+
}
|
|
1151
|
+
catch (e) {
|
|
1152
|
+
console.log(e);
|
|
1153
|
+
}
|
|
1154
|
+
continue;
|
|
1155
|
+
}
|
|
1156
|
+
const allDecorators = Reflection.getPropertyDecorators(ValidationKeys.REFLECT, self, prop).decorators;
|
|
1157
|
+
decorators = allDecorators.filter((d) => [ModelKeys.TYPE, ValidationKeys.TYPE].indexOf(d.key) !== -1);
|
|
1158
|
+
if (!decorators || !decorators.length)
|
|
1159
|
+
throw new Error(sf("failed to find decorators for property {0}", prop));
|
|
1160
|
+
dec = decorators.pop();
|
|
1161
|
+
const clazz = dec.props.name
|
|
1162
|
+
? [dec.props.name]
|
|
1163
|
+
: Array.isArray(dec.props.customTypes)
|
|
1164
|
+
? dec.props.customTypes
|
|
1165
|
+
: [dec.props.customTypes];
|
|
1166
|
+
const reserved = Object.values(ReservedModels).map((v) => v.toLowerCase());
|
|
1167
|
+
clazz.forEach((c) => {
|
|
1168
|
+
if (reserved.indexOf(c.toLowerCase()) === -1)
|
|
1169
|
+
try {
|
|
1170
|
+
switch (c) {
|
|
1171
|
+
case "Array":
|
|
1172
|
+
case "Set":
|
|
1173
|
+
if (allDecorators.length) {
|
|
1174
|
+
const listDec = allDecorators.find((d) => d.key === ValidationKeys.LIST);
|
|
1175
|
+
if (listDec) {
|
|
1176
|
+
const clazzName = listDec.props.clazz.find((t) => !jsTypes.includes(t.toLowerCase()));
|
|
1177
|
+
if (c === "Array")
|
|
1178
|
+
self[prop] = self[prop].map((el) => {
|
|
1179
|
+
return ["object", "function"].includes(typeof el) &&
|
|
1180
|
+
clazzName
|
|
1181
|
+
? Model.build(el, clazzName)
|
|
1182
|
+
: el;
|
|
1183
|
+
});
|
|
1184
|
+
if (c === "Set") {
|
|
1185
|
+
const s = new Set();
|
|
1186
|
+
for (const v of self[prop]) {
|
|
1187
|
+
if (["object", "function"].includes(typeof v) &&
|
|
1188
|
+
clazzName) {
|
|
1189
|
+
s.add(Model.build(v, clazzName));
|
|
1190
|
+
}
|
|
1191
|
+
else {
|
|
1192
|
+
s.add(v);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
self[prop] = s;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
break;
|
|
1200
|
+
default:
|
|
1201
|
+
if (self[prop])
|
|
1202
|
+
self[prop] = Model.build(self[prop], c);
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
catch (e) {
|
|
1206
|
+
console.log(e);
|
|
1207
|
+
// do nothing. we have no registry of this class
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
}
|
|
1211
|
+
return self;
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* @summary Sets the Global {@link ModelBuilderFunction}
|
|
1215
|
+
* @param {ModelBuilderFunction} [builder]
|
|
1216
|
+
*/
|
|
1217
|
+
static setBuilder(builder) {
|
|
1218
|
+
modelBuilderFunction = builder;
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* @summary Retrieves the current global {@link ModelBuilderFunction}
|
|
1222
|
+
*/
|
|
1223
|
+
static getBuilder() {
|
|
1224
|
+
return modelBuilderFunction;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Returns the current {@link ModelRegistryManager}
|
|
1228
|
+
*
|
|
1229
|
+
* @return ModelRegistry, defaults to {@link ModelRegistryManager}
|
|
1230
|
+
*/
|
|
1231
|
+
static getRegistry() {
|
|
1232
|
+
if (!actingModelRegistry)
|
|
1233
|
+
actingModelRegistry = new ModelRegistryManager();
|
|
1234
|
+
return actingModelRegistry;
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Returns the current actingModelRegistry
|
|
1238
|
+
*
|
|
1239
|
+
* @param {BuilderRegistry} modelRegistry the new implementation of Registry
|
|
1240
|
+
*/
|
|
1241
|
+
static setRegistry(modelRegistry) {
|
|
1242
|
+
actingModelRegistry = modelRegistry;
|
|
1243
|
+
}
|
|
1244
|
+
/**
|
|
1245
|
+
* @summary register new Models
|
|
1246
|
+
* @param {any} constructor
|
|
1247
|
+
* @param {string} [name] when not defined, the name of the constructor will be used
|
|
1248
|
+
*
|
|
1249
|
+
* @see ModelRegistry
|
|
1250
|
+
*/
|
|
1251
|
+
static register(constructor, name) {
|
|
1252
|
+
return Model.getRegistry().register(constructor, name);
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* @summary Gets a registered Model {@link ModelConstructor}
|
|
1256
|
+
* @param {string} name
|
|
1257
|
+
*
|
|
1258
|
+
* @see ModelRegistry
|
|
1259
|
+
*/
|
|
1260
|
+
static get(name) {
|
|
1261
|
+
return Model.getRegistry().get(name);
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* @param {Record<string, any>} obj
|
|
1265
|
+
* @param {string} [clazz] when provided, it will attempt to find the matching constructor
|
|
1266
|
+
*
|
|
1267
|
+
* @throws Error If clazz is not found, or obj is not a {@link Model} meaning it has no {@link ModelKeys.ANCHOR} property
|
|
1268
|
+
*
|
|
1269
|
+
* @see ModelRegistry
|
|
1270
|
+
*/
|
|
1271
|
+
static build(obj = {}, clazz) {
|
|
1272
|
+
return Model.getRegistry().build(obj, clazz);
|
|
1273
|
+
}
|
|
1274
|
+
static getMetadata(model) {
|
|
1275
|
+
const metadata = Reflect.getMetadata(Model.key(ModelKeys.MODEL), model.constructor);
|
|
1276
|
+
if (!metadata)
|
|
1277
|
+
throw new Error("could not find metadata for provided " + model.constructor.name);
|
|
1278
|
+
return metadata;
|
|
1279
|
+
}
|
|
1280
|
+
static getAttributes(model) {
|
|
1281
|
+
const result = [];
|
|
1282
|
+
let prototype = model instanceof Model
|
|
1283
|
+
? Object.getPrototypeOf(model)
|
|
1284
|
+
: model.prototype;
|
|
1285
|
+
while (prototype != null) {
|
|
1286
|
+
const props = prototype[ModelKeys.ATTRIBUTE];
|
|
1287
|
+
if (props) {
|
|
1288
|
+
result.push(...props);
|
|
1289
|
+
}
|
|
1290
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
1291
|
+
}
|
|
1292
|
+
return result;
|
|
1293
|
+
}
|
|
1294
|
+
static equals(obj1, obj2, ...exceptions) {
|
|
1295
|
+
return isEqual(obj1, obj2, ...exceptions);
|
|
1296
|
+
}
|
|
1297
|
+
static hasErrors(model, ...propsToIgnore) {
|
|
1298
|
+
return validate(model, ...propsToIgnore);
|
|
1299
|
+
}
|
|
1300
|
+
static serialize(model) {
|
|
1301
|
+
const metadata = Reflect.getMetadata(Model.key(ModelKeys.SERIALIZATION), model.constructor);
|
|
1302
|
+
if (metadata && metadata.serializer)
|
|
1303
|
+
return Serialization.serialize(this, metadata.serializer, ...(metadata.args || []));
|
|
1304
|
+
return Serialization.serialize(model);
|
|
1305
|
+
}
|
|
1306
|
+
static hash(model) {
|
|
1307
|
+
const metadata = Reflect.getMetadata(Model.key(ModelKeys.HASHING), model.constructor);
|
|
1308
|
+
if (metadata && metadata.algorithm)
|
|
1309
|
+
return Hashing.hash(model, metadata.algorithm, ...(metadata.args || []));
|
|
1310
|
+
return Hashing.hash(model);
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* @summary Builds the key to store as Metadata under Reflections
|
|
1314
|
+
* @description concatenates {@link ModelKeys#REFLECT} with the provided key
|
|
1315
|
+
* @param {string} str
|
|
1316
|
+
*/
|
|
1317
|
+
static key(str) {
|
|
1318
|
+
return ModelKeys.REFLECT + str;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
const DefaultSerializationMethod = "json";
|
|
1323
|
+
/**
|
|
1324
|
+
* @summary Concrete implementation of a {@link Serializer} in JSON format
|
|
1325
|
+
* @description JS's native JSON.stringify (used here) is not deterministic
|
|
1326
|
+
* and therefore should not be used for hashing purposes
|
|
1327
|
+
*
|
|
1328
|
+
* To keep dependencies low, we will not implement this, but we recommend
|
|
1329
|
+
* implementing a similar {@link JSONSerializer} using 'deterministic-json' libraries
|
|
1330
|
+
*
|
|
1331
|
+
* @class JSONSerializer
|
|
1332
|
+
* @implements Serializer
|
|
1333
|
+
*
|
|
1334
|
+
* @category Serialization
|
|
1335
|
+
*/
|
|
1336
|
+
class JSONSerializer {
|
|
1337
|
+
constructor() { }
|
|
1338
|
+
/**
|
|
1339
|
+
* @summary prepares the model for serialization
|
|
1340
|
+
* @description returns a shallow copy of the object, containing an enumerable {@link ModelKeys#ANCHOR} property
|
|
1341
|
+
* so the object can be recognized upon deserialization
|
|
1342
|
+
*
|
|
1343
|
+
* @param {T} model
|
|
1344
|
+
* @protected
|
|
1345
|
+
*/
|
|
1346
|
+
preSerialize(model) {
|
|
1347
|
+
// TODO: nested preserialization (so increase performance when deserializing)
|
|
1348
|
+
const toSerialize = Object.assign({}, model);
|
|
1349
|
+
const metadata = Model.getMetadata(model);
|
|
1350
|
+
toSerialize[ModelKeys.ANCHOR] = metadata || model.constructor.name;
|
|
1351
|
+
return toSerialize;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* @summary Rebuilds a model from a serialization
|
|
1355
|
+
* @param {string} str
|
|
1356
|
+
*
|
|
1357
|
+
* @throws {Error} If it fails to parse the string, or to build the model
|
|
1358
|
+
*/
|
|
1359
|
+
deserialize(str) {
|
|
1360
|
+
const deserialization = JSON.parse(str);
|
|
1361
|
+
const className = deserialization[ModelKeys.ANCHOR];
|
|
1362
|
+
if (!className)
|
|
1363
|
+
throw new Error("Could not find class reference in serialized model");
|
|
1364
|
+
const model = Model.build(deserialization, className);
|
|
1365
|
+
return model;
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* @summary Serializes a model
|
|
1369
|
+
* @param {T} model
|
|
1370
|
+
*
|
|
1371
|
+
* @throws {Error} if fails to serialize
|
|
1372
|
+
*/
|
|
1373
|
+
serialize(model) {
|
|
1374
|
+
return JSON.stringify(this.preSerialize(model));
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
class Serialization {
|
|
1378
|
+
static { this.current = DefaultSerializationMethod; }
|
|
1379
|
+
static { this.cache = {
|
|
1380
|
+
json: new JSONSerializer(),
|
|
1381
|
+
}; }
|
|
1382
|
+
constructor() { }
|
|
1383
|
+
static get(key) {
|
|
1384
|
+
if (key in this.cache)
|
|
1385
|
+
return this.cache[key];
|
|
1386
|
+
throw new Error(`No serialization method registered under ${key}`);
|
|
1387
|
+
}
|
|
1388
|
+
static register(key, func, setDefault = false) {
|
|
1389
|
+
if (key in this.cache)
|
|
1390
|
+
throw new Error(`Serialization method ${key} already registered`);
|
|
1391
|
+
this.cache[key] = new func();
|
|
1392
|
+
if (setDefault)
|
|
1393
|
+
this.current = key;
|
|
1394
|
+
}
|
|
1395
|
+
static serialize(obj, method, ...args) {
|
|
1396
|
+
if (!method)
|
|
1397
|
+
return this.get(this.current).serialize(obj, ...args);
|
|
1398
|
+
return this.get(method).serialize(obj, ...args);
|
|
1399
|
+
}
|
|
1400
|
+
static deserialize(obj, method, ...args) {
|
|
1401
|
+
if (!method)
|
|
1402
|
+
return this.get(this.current).deserialize(obj, ...args);
|
|
1403
|
+
return this.get(method).deserialize(obj, ...args);
|
|
1404
|
+
}
|
|
1405
|
+
static setDefault(method) {
|
|
1406
|
+
this.current = this.get(method);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
/******************************************************************************
|
|
1411
|
+
Copyright (c) Microsoft Corporation.
|
|
1412
|
+
|
|
1413
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
1414
|
+
purpose with or without fee is hereby granted.
|
|
1415
|
+
|
|
1416
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
1417
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
1418
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
1419
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
1420
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
1421
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
1422
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
1423
|
+
***************************************************************************** */
|
|
1424
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
1425
|
+
|
|
1426
|
+
|
|
1427
|
+
function __decorate(decorators, target, key, desc) {
|
|
1428
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
1429
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
1430
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
1431
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
function __metadata(metadataKey, metadataValue) {
|
|
1435
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
1439
|
+
var e = new Error(message);
|
|
1440
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1441
|
+
};
|
|
1442
|
+
|
|
1443
|
+
/**
|
|
1444
|
+
* @summary Base Implementation for Validators
|
|
1445
|
+
* @description Provides the underlying functionality for {@link Validator}s
|
|
1446
|
+
*
|
|
1447
|
+
* @param {string} validationKey the key to register the validator under
|
|
1448
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#DEFAULT}
|
|
1449
|
+
* @param {string[]} [acceptedTypes] defines the value types this validator can validate
|
|
1450
|
+
*
|
|
1451
|
+
* @class Validator
|
|
1452
|
+
* @abstract
|
|
1453
|
+
* @category Validators
|
|
1454
|
+
*/
|
|
1455
|
+
class Validator {
|
|
1456
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.DEFAULT, ...acceptedTypes) {
|
|
1457
|
+
this.message = message;
|
|
1458
|
+
if (acceptedTypes.length)
|
|
1459
|
+
this.acceptedTypes = acceptedTypes;
|
|
1460
|
+
if (this.acceptedTypes)
|
|
1461
|
+
this.hasErrors = this.checkTypeAndHasErrors(this.hasErrors.bind(this));
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* @summary builds the error message
|
|
1465
|
+
* @param {string} message
|
|
1466
|
+
* @param {any[]} args
|
|
1467
|
+
* @protected
|
|
1468
|
+
*/
|
|
1469
|
+
getMessage(message, ...args) {
|
|
1470
|
+
return sf(message, ...args);
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* @summary Validates type
|
|
1474
|
+
* @param {any} unbound
|
|
1475
|
+
* @private
|
|
1476
|
+
*/
|
|
1477
|
+
checkTypeAndHasErrors(unbound) {
|
|
1478
|
+
return function (value, ...args) {
|
|
1479
|
+
if (value === undefined || !this.acceptedTypes)
|
|
1480
|
+
return unbound(value, ...args);
|
|
1481
|
+
if (!Reflection.checkTypes(value, this.acceptedTypes))
|
|
1482
|
+
return this.getMessage(DEFAULT_ERROR_MESSAGES.TYPE, this.acceptedTypes.join(", "), typeof value);
|
|
1483
|
+
return unbound(value, ...args);
|
|
1484
|
+
}.bind(this);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
/**
|
|
1489
|
+
* @summary Marks the class as a validator for a certain key.
|
|
1490
|
+
* @description Registers the class in the {@link Validation} with the provided key
|
|
1491
|
+
*
|
|
1492
|
+
* @param {string} keys the validation key
|
|
1493
|
+
*
|
|
1494
|
+
* @function validator
|
|
1495
|
+
*
|
|
1496
|
+
* @category Decorators
|
|
1497
|
+
*/
|
|
1498
|
+
function validator(...keys) {
|
|
1499
|
+
return apply(((original) => {
|
|
1500
|
+
keys.forEach((k) => {
|
|
1501
|
+
Validation.register({
|
|
1502
|
+
validator: original,
|
|
1503
|
+
validationKey: k,
|
|
1504
|
+
save: true,
|
|
1505
|
+
});
|
|
1506
|
+
});
|
|
1507
|
+
return original;
|
|
1508
|
+
}), metadata(Validation.key(ValidationKeys.VALIDATOR), keys));
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
/**
|
|
1512
|
+
* @summary Date Validator
|
|
1513
|
+
*
|
|
1514
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#DATE}
|
|
1515
|
+
*
|
|
1516
|
+
* @class DateValidator
|
|
1517
|
+
* @extends Validator
|
|
1518
|
+
*
|
|
1519
|
+
* @category Validators
|
|
1520
|
+
*/
|
|
1521
|
+
let DateValidator = class DateValidator extends Validator {
|
|
1522
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.DATE) {
|
|
1523
|
+
super(message, Number.name, Date.name, String.name);
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* @summary Validates a model
|
|
1527
|
+
*
|
|
1528
|
+
* @param {Date | string} value
|
|
1529
|
+
* @param {DateValidatorOptions} [options]
|
|
1530
|
+
*
|
|
1531
|
+
* @return {string | undefined}
|
|
1532
|
+
*
|
|
1533
|
+
* @override
|
|
1534
|
+
*
|
|
1535
|
+
* @see Validator#hasErrors
|
|
1536
|
+
*/
|
|
1537
|
+
hasErrors(value, options = {}) {
|
|
1538
|
+
if (value === undefined)
|
|
1539
|
+
return;
|
|
1540
|
+
if (typeof value === "string")
|
|
1541
|
+
value = new Date(value);
|
|
1542
|
+
if (Number.isNaN(value.getDate())) {
|
|
1543
|
+
const { message = "" } = options;
|
|
1544
|
+
return this.getMessage(message || this.message);
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1548
|
+
DateValidator = __decorate([
|
|
1549
|
+
validator(ValidationKeys.DATE),
|
|
1550
|
+
__metadata("design:paramtypes", [String])
|
|
1551
|
+
], DateValidator);
|
|
1552
|
+
|
|
1553
|
+
const regexpParser = new RegExp("^/(.+)/([gimus]*)$");
|
|
1554
|
+
/**
|
|
1555
|
+
* @summary Pattern Validator
|
|
1556
|
+
*
|
|
1557
|
+
* @param {string} [key] defaults to {@link ValidationKeys#PATTERN}
|
|
1558
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#PATTERN}
|
|
1559
|
+
*
|
|
1560
|
+
* @class PatternValidator
|
|
1561
|
+
* @extends Validator
|
|
1562
|
+
*
|
|
1563
|
+
* @category Validators
|
|
1564
|
+
*/
|
|
1565
|
+
let PatternValidator = class PatternValidator extends Validator {
|
|
1566
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.PATTERN) {
|
|
1567
|
+
super(message, "string");
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* @summary parses and validates a pattern
|
|
1571
|
+
*
|
|
1572
|
+
* @param {string} pattern
|
|
1573
|
+
* @private
|
|
1574
|
+
*/
|
|
1575
|
+
getPattern(pattern) {
|
|
1576
|
+
if (!regexpParser.test(pattern))
|
|
1577
|
+
return new RegExp(pattern);
|
|
1578
|
+
const match = pattern.match(regexpParser);
|
|
1579
|
+
return new RegExp(match[1], match[2]);
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* @summary Validates a Model
|
|
1583
|
+
*
|
|
1584
|
+
* @param {string} value
|
|
1585
|
+
* @param {PatternValidatorOptions} options
|
|
1586
|
+
*
|
|
1587
|
+
* @return {string | undefined}
|
|
1588
|
+
*
|
|
1589
|
+
* @override
|
|
1590
|
+
*
|
|
1591
|
+
* @see Validator#hasErrors
|
|
1592
|
+
*/
|
|
1593
|
+
hasErrors(value, options) {
|
|
1594
|
+
if (!value)
|
|
1595
|
+
return;
|
|
1596
|
+
let { pattern } = options;
|
|
1597
|
+
if (!pattern)
|
|
1598
|
+
throw new Error("Missing Pattern");
|
|
1599
|
+
pattern = typeof pattern === "string" ? this.getPattern(pattern) : pattern;
|
|
1600
|
+
pattern.lastIndex = 0; // resets pattern position for repeat validation requests
|
|
1601
|
+
return !pattern.test(value)
|
|
1602
|
+
? this.getMessage(options.message || this.message)
|
|
1603
|
+
: undefined;
|
|
1604
|
+
}
|
|
1605
|
+
};
|
|
1606
|
+
PatternValidator = __decorate([
|
|
1607
|
+
validator(ValidationKeys.PATTERN),
|
|
1608
|
+
__metadata("design:paramtypes", [String])
|
|
1609
|
+
], PatternValidator);
|
|
1610
|
+
|
|
1611
|
+
/**
|
|
1612
|
+
* @summary Email Validator
|
|
1613
|
+
*
|
|
1614
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#EMAIL}
|
|
1615
|
+
*
|
|
1616
|
+
* @class EmailValidator
|
|
1617
|
+
* @extends PatternValidator
|
|
1618
|
+
*
|
|
1619
|
+
* @category Validators
|
|
1620
|
+
*/
|
|
1621
|
+
let EmailValidator = class EmailValidator extends PatternValidator {
|
|
1622
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.EMAIL) {
|
|
1623
|
+
super(message);
|
|
1624
|
+
}
|
|
1625
|
+
/**
|
|
1626
|
+
* @summary Validates a model
|
|
1627
|
+
*
|
|
1628
|
+
* @param {string} value
|
|
1629
|
+
* @param {PatternValidatorOptions} [options]
|
|
1630
|
+
*
|
|
1631
|
+
* @return {string | undefined}
|
|
1632
|
+
*
|
|
1633
|
+
* @override
|
|
1634
|
+
*
|
|
1635
|
+
* @see Validator#hasErrors
|
|
1636
|
+
*/
|
|
1637
|
+
hasErrors(value, options = {}) {
|
|
1638
|
+
return super.hasErrors(value, {
|
|
1639
|
+
...options,
|
|
1640
|
+
pattern: options?.pattern || DEFAULT_PATTERNS.EMAIL,
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
EmailValidator = __decorate([
|
|
1645
|
+
validator(ValidationKeys.EMAIL),
|
|
1646
|
+
__metadata("design:paramtypes", [String])
|
|
1647
|
+
], EmailValidator);
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* @summary List Validator
|
|
1651
|
+
*
|
|
1652
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#LIST}
|
|
1653
|
+
*
|
|
1654
|
+
* @class ListValidator
|
|
1655
|
+
* @extends Validator
|
|
1656
|
+
*
|
|
1657
|
+
* @category Validators
|
|
1658
|
+
*/
|
|
1659
|
+
let ListValidator = class ListValidator extends Validator {
|
|
1660
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.LIST) {
|
|
1661
|
+
super(message, Array.name, Set.name);
|
|
1662
|
+
}
|
|
1663
|
+
/**
|
|
1664
|
+
* @summary Validates a model
|
|
1665
|
+
*
|
|
1666
|
+
* @param {any[] | Set<any>} value
|
|
1667
|
+
* @param {ListValidatorOptions} options
|
|
1668
|
+
*
|
|
1669
|
+
* @return {string | undefined}
|
|
1670
|
+
*
|
|
1671
|
+
* @override
|
|
1672
|
+
*
|
|
1673
|
+
* @see Validator#hasErrors
|
|
1674
|
+
*/
|
|
1675
|
+
hasErrors(value, options) {
|
|
1676
|
+
if (!value || (Array.isArray(value) ? !value.length : !value.size))
|
|
1677
|
+
return;
|
|
1678
|
+
const clazz = Array.isArray(options.clazz)
|
|
1679
|
+
? options.clazz
|
|
1680
|
+
: [options.clazz];
|
|
1681
|
+
let val, isValid = true;
|
|
1682
|
+
for (let i = 0; i < (Array.isArray(value) ? value.length : value.size); i++) {
|
|
1683
|
+
val = value[i];
|
|
1684
|
+
switch (typeof val) {
|
|
1685
|
+
case "object":
|
|
1686
|
+
case "function":
|
|
1687
|
+
isValid = clazz.includes(val.constructor?.name);
|
|
1688
|
+
break;
|
|
1689
|
+
default:
|
|
1690
|
+
isValid = clazz.some((c) => typeof val === c.toLowerCase());
|
|
1691
|
+
break;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
return isValid
|
|
1695
|
+
? undefined
|
|
1696
|
+
: this.getMessage(options.message || this.message, clazz);
|
|
1697
|
+
}
|
|
1698
|
+
};
|
|
1699
|
+
ListValidator = __decorate([
|
|
1700
|
+
validator(ValidationKeys.LIST),
|
|
1701
|
+
__metadata("design:paramtypes", [String])
|
|
1702
|
+
], ListValidator);
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* @summary Maximum Length Validator
|
|
1706
|
+
* @description Validates strings and Arrays on their maximum length
|
|
1707
|
+
*
|
|
1708
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#MAX_LENGTH}
|
|
1709
|
+
*
|
|
1710
|
+
* @class MinLengthValidator
|
|
1711
|
+
* @extends Validator
|
|
1712
|
+
*
|
|
1713
|
+
* @category Validators
|
|
1714
|
+
*/
|
|
1715
|
+
let MaxLengthValidator = class MaxLengthValidator extends Validator {
|
|
1716
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.MAX_LENGTH) {
|
|
1717
|
+
super(message, String.name, Array.name);
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* @summary Validates a model
|
|
1721
|
+
*
|
|
1722
|
+
* @param {string} value
|
|
1723
|
+
* @param {MaxLengthValidatorOptions} options
|
|
1724
|
+
*
|
|
1725
|
+
* @return {string | undefined}
|
|
1726
|
+
*
|
|
1727
|
+
* @override
|
|
1728
|
+
*
|
|
1729
|
+
* @see Validator#hasErrors
|
|
1730
|
+
*/
|
|
1731
|
+
hasErrors(value, options) {
|
|
1732
|
+
if (typeof value === "undefined")
|
|
1733
|
+
return;
|
|
1734
|
+
return value.length > options.maxlength
|
|
1735
|
+
? this.getMessage(options.message || this.message, options.maxlength)
|
|
1736
|
+
: undefined;
|
|
1737
|
+
}
|
|
1738
|
+
};
|
|
1739
|
+
MaxLengthValidator = __decorate([
|
|
1740
|
+
validator(ValidationKeys.MAX_LENGTH),
|
|
1741
|
+
__metadata("design:paramtypes", [String])
|
|
1742
|
+
], MaxLengthValidator);
|
|
1743
|
+
|
|
1744
|
+
/**
|
|
1745
|
+
* @summary Max Validator
|
|
1746
|
+
*
|
|
1747
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#MAX}
|
|
1748
|
+
*
|
|
1749
|
+
* @class MaxValidator
|
|
1750
|
+
* @extends Validator
|
|
1751
|
+
*
|
|
1752
|
+
* @category Validators
|
|
1753
|
+
*/
|
|
1754
|
+
let MaxValidator = class MaxValidator extends Validator {
|
|
1755
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.MAX) {
|
|
1756
|
+
super(message, "number", "Date", "string");
|
|
1757
|
+
}
|
|
1758
|
+
/**
|
|
1759
|
+
* @summary Validates a Model
|
|
1760
|
+
*
|
|
1761
|
+
* @param {string} value
|
|
1762
|
+
* @param {MaxValidatorOptions} options
|
|
1763
|
+
*
|
|
1764
|
+
* @return {string | undefined}
|
|
1765
|
+
*
|
|
1766
|
+
* @override
|
|
1767
|
+
*
|
|
1768
|
+
* @see Validator#hasErrors
|
|
1769
|
+
*/
|
|
1770
|
+
hasErrors(value, options) {
|
|
1771
|
+
if (typeof value === "undefined")
|
|
1772
|
+
return;
|
|
1773
|
+
let { max } = options;
|
|
1774
|
+
if (value instanceof Date && !(max instanceof Date)) {
|
|
1775
|
+
max = new Date(max);
|
|
1776
|
+
if (Number.isNaN(max.getDate()))
|
|
1777
|
+
throw new Error("Invalid Max param defined");
|
|
1778
|
+
}
|
|
1779
|
+
return value > max
|
|
1780
|
+
? this.getMessage(options.message || this.message, max)
|
|
1781
|
+
: undefined;
|
|
1782
|
+
}
|
|
1783
|
+
};
|
|
1784
|
+
MaxValidator = __decorate([
|
|
1785
|
+
validator(ValidationKeys.MAX),
|
|
1786
|
+
__metadata("design:paramtypes", [String])
|
|
1787
|
+
], MaxValidator);
|
|
1788
|
+
|
|
1789
|
+
/**
|
|
1790
|
+
* @summary Minimum Length Validator
|
|
1791
|
+
* @description Validates strings and Arrays on their minimum length
|
|
1792
|
+
*
|
|
1793
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#MIN_LENGTH}
|
|
1794
|
+
*
|
|
1795
|
+
* @class MinLengthValidator
|
|
1796
|
+
* @extends Validator
|
|
1797
|
+
*
|
|
1798
|
+
* @category Validators
|
|
1799
|
+
*/
|
|
1800
|
+
let MinLengthValidator = class MinLengthValidator extends Validator {
|
|
1801
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.MIN_LENGTH) {
|
|
1802
|
+
super(message, String.name, Array.name);
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
*
|
|
1806
|
+
* @param {string | Array} value
|
|
1807
|
+
* @param {MinLengthValidatorOptions} options
|
|
1808
|
+
*
|
|
1809
|
+
* @return {string | undefined}
|
|
1810
|
+
*
|
|
1811
|
+
* @memberOf MinLengthValidator
|
|
1812
|
+
* @override
|
|
1813
|
+
*
|
|
1814
|
+
* @see Validator#hasErrors
|
|
1815
|
+
*/
|
|
1816
|
+
hasErrors(value, options) {
|
|
1817
|
+
if (typeof value === "undefined")
|
|
1818
|
+
return;
|
|
1819
|
+
return value.length < options.minlength
|
|
1820
|
+
? this.getMessage(options.message || this.message, options.minlength)
|
|
1821
|
+
: undefined;
|
|
1822
|
+
}
|
|
1823
|
+
};
|
|
1824
|
+
MinLengthValidator = __decorate([
|
|
1825
|
+
validator(ValidationKeys.MIN_LENGTH),
|
|
1826
|
+
__metadata("design:paramtypes", [String])
|
|
1827
|
+
], MinLengthValidator);
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* @summary Min Validator
|
|
1831
|
+
*
|
|
1832
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#MIN}
|
|
1833
|
+
*
|
|
1834
|
+
* @class MinValidator
|
|
1835
|
+
* @extends Validator
|
|
1836
|
+
*
|
|
1837
|
+
* @category Validators
|
|
1838
|
+
*/
|
|
1839
|
+
let MinValidator = class MinValidator extends Validator {
|
|
1840
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.MIN) {
|
|
1841
|
+
super(message, "number", "Date", "string");
|
|
1842
|
+
}
|
|
1843
|
+
/**
|
|
1844
|
+
* @summary Validates Model
|
|
1845
|
+
*
|
|
1846
|
+
* @param {string} value
|
|
1847
|
+
* @param {MaxValidatorOptions} options
|
|
1848
|
+
*
|
|
1849
|
+
* @return {string | undefined}
|
|
1850
|
+
*
|
|
1851
|
+
* @override
|
|
1852
|
+
*
|
|
1853
|
+
* @see Validator#hasErrors
|
|
1854
|
+
*/
|
|
1855
|
+
hasErrors(value, options) {
|
|
1856
|
+
if (typeof value === "undefined")
|
|
1857
|
+
return;
|
|
1858
|
+
let { min } = options;
|
|
1859
|
+
if (value instanceof Date && !(min instanceof Date)) {
|
|
1860
|
+
min = new Date(min);
|
|
1861
|
+
if (Number.isNaN(min.getDate()))
|
|
1862
|
+
throw new Error("Invalid Min param defined");
|
|
1863
|
+
}
|
|
1864
|
+
return value < min
|
|
1865
|
+
? this.getMessage(options.message || this.message, min)
|
|
1866
|
+
: undefined;
|
|
1867
|
+
}
|
|
1868
|
+
};
|
|
1869
|
+
MinValidator = __decorate([
|
|
1870
|
+
validator(ValidationKeys.MIN),
|
|
1871
|
+
__metadata("design:paramtypes", [String])
|
|
1872
|
+
], MinValidator);
|
|
1873
|
+
|
|
1874
|
+
/**
|
|
1875
|
+
* @summary Handles Password Validation
|
|
1876
|
+
*
|
|
1877
|
+
* @param {string} [errorMessage] defaults to {@link DEFAULT_ERROR_MESSAGES#PASSWORD}
|
|
1878
|
+
*
|
|
1879
|
+
* @class PasswordValidator
|
|
1880
|
+
* @extends PatternValidator
|
|
1881
|
+
*
|
|
1882
|
+
* @category Validators
|
|
1883
|
+
*/
|
|
1884
|
+
let PasswordValidator = class PasswordValidator extends PatternValidator {
|
|
1885
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.PASSWORD) {
|
|
1886
|
+
super(message);
|
|
1887
|
+
}
|
|
1888
|
+
/**
|
|
1889
|
+
* @summary Validates a model
|
|
1890
|
+
*
|
|
1891
|
+
* @param {string} value
|
|
1892
|
+
* @param {PatternValidatorOptions} [options={}]
|
|
1893
|
+
*
|
|
1894
|
+
* @return {string | undefined}
|
|
1895
|
+
*
|
|
1896
|
+
* @override
|
|
1897
|
+
*
|
|
1898
|
+
* @see PatternValidator#hasErrors
|
|
1899
|
+
*/
|
|
1900
|
+
hasErrors(value, options = {}) {
|
|
1901
|
+
return super.hasErrors(value, {
|
|
1902
|
+
...options,
|
|
1903
|
+
message: options.message || this.message,
|
|
1904
|
+
});
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
PasswordValidator = __decorate([
|
|
1908
|
+
validator(ValidationKeys.PASSWORD),
|
|
1909
|
+
__metadata("design:paramtypes", [Object])
|
|
1910
|
+
], PasswordValidator);
|
|
1911
|
+
|
|
1912
|
+
/**
|
|
1913
|
+
* @summary Required Validator
|
|
1914
|
+
*
|
|
1915
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#REQUIRED}
|
|
1916
|
+
*
|
|
1917
|
+
* @class RequiredValidator
|
|
1918
|
+
* @extends Validator
|
|
1919
|
+
*
|
|
1920
|
+
* @category Validators
|
|
1921
|
+
*/
|
|
1922
|
+
let RequiredValidator = class RequiredValidator extends Validator {
|
|
1923
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.REQUIRED) {
|
|
1924
|
+
super(message);
|
|
1925
|
+
}
|
|
1926
|
+
/**
|
|
1927
|
+
* @summary Validates a model
|
|
1928
|
+
*
|
|
1929
|
+
* @param {string} value
|
|
1930
|
+
* @param {ValidatorOptions} [options={}]
|
|
1931
|
+
*
|
|
1932
|
+
* @return {string | undefined}
|
|
1933
|
+
*
|
|
1934
|
+
* @override
|
|
1935
|
+
*
|
|
1936
|
+
* @see Validator#hasErrors
|
|
1937
|
+
*/
|
|
1938
|
+
hasErrors(value, options = {}) {
|
|
1939
|
+
switch (typeof value) {
|
|
1940
|
+
case "boolean":
|
|
1941
|
+
case "number":
|
|
1942
|
+
return typeof value === "undefined"
|
|
1943
|
+
? this.getMessage(options.message || this.message)
|
|
1944
|
+
: undefined;
|
|
1945
|
+
default:
|
|
1946
|
+
return !value
|
|
1947
|
+
? this.getMessage(options.message || this.message)
|
|
1948
|
+
: undefined;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
RequiredValidator = __decorate([
|
|
1953
|
+
validator(ValidationKeys.REQUIRED),
|
|
1954
|
+
__metadata("design:paramtypes", [String])
|
|
1955
|
+
], RequiredValidator);
|
|
1956
|
+
|
|
1957
|
+
/**
|
|
1958
|
+
* @summary Step Validator
|
|
1959
|
+
*
|
|
1960
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#STEP}
|
|
1961
|
+
*
|
|
1962
|
+
* @class StepValidator
|
|
1963
|
+
* @extends Validator
|
|
1964
|
+
*
|
|
1965
|
+
* @category Validators
|
|
1966
|
+
*/
|
|
1967
|
+
let StepValidator = class StepValidator extends Validator {
|
|
1968
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.STEP) {
|
|
1969
|
+
super(message, "number", "string");
|
|
1970
|
+
}
|
|
1971
|
+
/**
|
|
1972
|
+
* @summary Validates a model
|
|
1973
|
+
*
|
|
1974
|
+
* @param {string} value
|
|
1975
|
+
* @param {number} step
|
|
1976
|
+
* @param {StepValidatorOptions} options
|
|
1977
|
+
*
|
|
1978
|
+
* @return {string | undefined}
|
|
1979
|
+
*
|
|
1980
|
+
* @override
|
|
1981
|
+
*
|
|
1982
|
+
* @see Validator#hasErrors
|
|
1983
|
+
*/
|
|
1984
|
+
hasErrors(value, options) {
|
|
1985
|
+
if (typeof value === "undefined")
|
|
1986
|
+
return;
|
|
1987
|
+
return Number(value) % Number(options.step) !== 0
|
|
1988
|
+
? this.getMessage(options.message || this.message, options.step)
|
|
1989
|
+
: undefined;
|
|
1990
|
+
}
|
|
1991
|
+
};
|
|
1992
|
+
StepValidator = __decorate([
|
|
1993
|
+
validator(ValidationKeys.STEP),
|
|
1994
|
+
__metadata("design:paramtypes", [String])
|
|
1995
|
+
], StepValidator);
|
|
1996
|
+
|
|
1997
|
+
/**
|
|
1998
|
+
* @summary Required Validator
|
|
1999
|
+
*
|
|
2000
|
+
* @class RequiredValidator
|
|
2001
|
+
* @extends Validator
|
|
2002
|
+
*
|
|
2003
|
+
* @category Validators
|
|
2004
|
+
*/
|
|
2005
|
+
let TypeValidator = class TypeValidator extends Validator {
|
|
2006
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.TYPE) {
|
|
2007
|
+
super(message);
|
|
2008
|
+
}
|
|
2009
|
+
/**
|
|
2010
|
+
* @summary Validates a model
|
|
2011
|
+
* @param {string} value
|
|
2012
|
+
* @param {TypeValidatorOptions} options
|
|
2013
|
+
*
|
|
2014
|
+
* @return {string | undefined}
|
|
2015
|
+
*
|
|
2016
|
+
* @override
|
|
2017
|
+
*
|
|
2018
|
+
* @see Validator#hasErrors
|
|
2019
|
+
*/
|
|
2020
|
+
hasErrors(value, options) {
|
|
2021
|
+
if (value === undefined)
|
|
2022
|
+
return; // Don't try and enforce type if undefined
|
|
2023
|
+
const { types, message } = options;
|
|
2024
|
+
if (!Reflection.evaluateDesignTypes(value, types))
|
|
2025
|
+
return this.getMessage(message || this.message, typeof types === "string"
|
|
2026
|
+
? types
|
|
2027
|
+
: Array.isArray(types)
|
|
2028
|
+
? types.join(", ")
|
|
2029
|
+
: types.name, typeof value);
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
2032
|
+
TypeValidator = __decorate([
|
|
2033
|
+
validator(ValidationKeys.TYPE),
|
|
2034
|
+
__metadata("design:paramtypes", [String])
|
|
2035
|
+
], TypeValidator);
|
|
2036
|
+
Validation.register({
|
|
2037
|
+
validator: TypeValidator,
|
|
2038
|
+
validationKey: ModelKeys.TYPE,
|
|
2039
|
+
save: false,
|
|
2040
|
+
});
|
|
2041
|
+
|
|
2042
|
+
/**
|
|
2043
|
+
* @summary URL Validator
|
|
2044
|
+
* @description Pattern from {@link https://gist.github.com/dperini/729294}
|
|
2045
|
+
*
|
|
2046
|
+
* @class URLValidator
|
|
2047
|
+
* @extends PatternValidator
|
|
2048
|
+
*
|
|
2049
|
+
* @category Validators
|
|
2050
|
+
*/
|
|
2051
|
+
let URLValidator = class URLValidator extends PatternValidator {
|
|
2052
|
+
constructor(message = DEFAULT_ERROR_MESSAGES.URL) {
|
|
2053
|
+
super(message);
|
|
2054
|
+
}
|
|
2055
|
+
/**
|
|
2056
|
+
* @summary Validates a model
|
|
2057
|
+
*
|
|
2058
|
+
* @param {string} value
|
|
2059
|
+
* @param {PatternValidatorOptions} [options={}]
|
|
2060
|
+
*
|
|
2061
|
+
* @return {string | undefined}
|
|
2062
|
+
*
|
|
2063
|
+
* @override
|
|
2064
|
+
*
|
|
2065
|
+
* @see Validator#hasErrors
|
|
2066
|
+
*/
|
|
2067
|
+
hasErrors(value, options = {}) {
|
|
2068
|
+
return super.hasErrors(value, {
|
|
2069
|
+
...options,
|
|
2070
|
+
pattern: options.pattern || DEFAULT_PATTERNS.URL,
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
};
|
|
2074
|
+
URLValidator = __decorate([
|
|
2075
|
+
validator(ValidationKeys.URL),
|
|
2076
|
+
__metadata("design:paramtypes", [String])
|
|
2077
|
+
], URLValidator);
|
|
2078
|
+
|
|
2079
|
+
/**
|
|
2080
|
+
* @summary Marks the property as required.
|
|
2081
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#REQUIRED}
|
|
2082
|
+
*
|
|
2083
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#REQUIRED}
|
|
2084
|
+
*
|
|
2085
|
+
* @function required
|
|
2086
|
+
*
|
|
2087
|
+
* @category Decorators
|
|
2088
|
+
*/
|
|
2089
|
+
function required(message = DEFAULT_ERROR_MESSAGES.REQUIRED) {
|
|
2090
|
+
return propMetadata(Validation.key(ValidationKeys.REQUIRED), {
|
|
2091
|
+
message: message,
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
/**
|
|
2095
|
+
* @summary Defines a minimum value for the property
|
|
2096
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#MIN}
|
|
2097
|
+
*
|
|
2098
|
+
* @param {number | Date} value
|
|
2099
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#MIN}
|
|
2100
|
+
*
|
|
2101
|
+
* @function min
|
|
2102
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2103
|
+
* @category Decorators
|
|
2104
|
+
*/
|
|
2105
|
+
function min(value, message = DEFAULT_ERROR_MESSAGES.MIN) {
|
|
2106
|
+
return propMetadata(Validation.key(ValidationKeys.MIN), {
|
|
2107
|
+
[ValidationKeys.MIN]: value,
|
|
2108
|
+
message: message,
|
|
2109
|
+
types: [Number.name, Date.name],
|
|
2110
|
+
});
|
|
2111
|
+
}
|
|
2112
|
+
/**
|
|
2113
|
+
* @summary Defines a maximum value for the property
|
|
2114
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#MAX}
|
|
2115
|
+
*
|
|
2116
|
+
* @param {number | Date} value
|
|
2117
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#MAX}
|
|
2118
|
+
*
|
|
2119
|
+
* @function max
|
|
2120
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2121
|
+
* @category Decorators
|
|
2122
|
+
*/
|
|
2123
|
+
function max(value, message = DEFAULT_ERROR_MESSAGES.MAX) {
|
|
2124
|
+
return propMetadata(Validation.key(ValidationKeys.MAX), {
|
|
2125
|
+
[ValidationKeys.MAX]: value,
|
|
2126
|
+
message: message,
|
|
2127
|
+
types: [Number.name, Date.name],
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* @summary Defines a step value for the property
|
|
2132
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#STEP}
|
|
2133
|
+
*
|
|
2134
|
+
* @param {number} value
|
|
2135
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#STEP}
|
|
2136
|
+
*
|
|
2137
|
+
* @function step
|
|
2138
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2139
|
+
* @category Decorators
|
|
2140
|
+
*/
|
|
2141
|
+
function step(value, message = DEFAULT_ERROR_MESSAGES.STEP) {
|
|
2142
|
+
return propMetadata(Validation.key(ValidationKeys.STEP), {
|
|
2143
|
+
[ValidationKeys.STEP]: value,
|
|
2144
|
+
message: message,
|
|
2145
|
+
types: [Number.name],
|
|
2146
|
+
});
|
|
2147
|
+
}
|
|
2148
|
+
/**
|
|
2149
|
+
* @summary Defines a minimum length for the property
|
|
2150
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#MIN_LENGTH}
|
|
2151
|
+
*
|
|
2152
|
+
* @param {string} value
|
|
2153
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#MIN_LENGTH}
|
|
2154
|
+
*
|
|
2155
|
+
* @function minlength
|
|
2156
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2157
|
+
* @category Decorators
|
|
2158
|
+
*/
|
|
2159
|
+
function minlength(value, message = DEFAULT_ERROR_MESSAGES.MIN_LENGTH) {
|
|
2160
|
+
return propMetadata(Validation.key(ValidationKeys.MIN_LENGTH), {
|
|
2161
|
+
[ValidationKeys.MIN_LENGTH]: value,
|
|
2162
|
+
message: message,
|
|
2163
|
+
types: [String.name, Array.name, Set.name],
|
|
2164
|
+
});
|
|
2165
|
+
}
|
|
2166
|
+
/**
|
|
2167
|
+
* @summary Defines a maximum length for the property
|
|
2168
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#MAX_LENGTH}
|
|
2169
|
+
*
|
|
2170
|
+
* @param {string} value
|
|
2171
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#MAX_LENGTH}
|
|
2172
|
+
*
|
|
2173
|
+
* @function maxlength
|
|
2174
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2175
|
+
* @category Decorators
|
|
2176
|
+
*/
|
|
2177
|
+
function maxlength(value, message = DEFAULT_ERROR_MESSAGES.MAX_LENGTH) {
|
|
2178
|
+
return propMetadata(Validation.key(ValidationKeys.MAX_LENGTH), {
|
|
2179
|
+
[ValidationKeys.MAX_LENGTH]: value,
|
|
2180
|
+
message: message,
|
|
2181
|
+
types: [String.name, Array.name, Set.name],
|
|
2182
|
+
});
|
|
2183
|
+
}
|
|
2184
|
+
/**
|
|
2185
|
+
* @summary Defines a RegExp pattern the property must respect
|
|
2186
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#PATTERN}
|
|
2187
|
+
*
|
|
2188
|
+
* @param {string} value
|
|
2189
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#PATTERN}
|
|
2190
|
+
*
|
|
2191
|
+
* @function pattern
|
|
2192
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2193
|
+
* @category Decorators
|
|
2194
|
+
*/
|
|
2195
|
+
function pattern(value, message = DEFAULT_ERROR_MESSAGES.PATTERN) {
|
|
2196
|
+
return propMetadata(Validation.key(ValidationKeys.PATTERN), {
|
|
2197
|
+
[ValidationKeys.PATTERN]: typeof value === "string" ? value : value.toString(),
|
|
2198
|
+
message: message,
|
|
2199
|
+
types: [String.name],
|
|
2200
|
+
});
|
|
2201
|
+
}
|
|
2202
|
+
/**
|
|
2203
|
+
* @summary Defines the property as an email
|
|
2204
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#EMAIL}
|
|
2205
|
+
*
|
|
2206
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#EMAIL}
|
|
2207
|
+
*
|
|
2208
|
+
* @function email
|
|
2209
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2210
|
+
* @category Decorators
|
|
2211
|
+
*/
|
|
2212
|
+
function email(message = DEFAULT_ERROR_MESSAGES.EMAIL) {
|
|
2213
|
+
return propMetadata(Validation.key(ValidationKeys.EMAIL), {
|
|
2214
|
+
[ValidationKeys.PATTERN]: DEFAULT_PATTERNS.EMAIL,
|
|
2215
|
+
message: message,
|
|
2216
|
+
types: [String.name],
|
|
2217
|
+
});
|
|
2218
|
+
}
|
|
2219
|
+
/**
|
|
2220
|
+
* @summary Defines the property as an URL
|
|
2221
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#URL}
|
|
2222
|
+
*
|
|
2223
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#URL}
|
|
2224
|
+
*
|
|
2225
|
+
* @function url
|
|
2226
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2227
|
+
* @category Decorators
|
|
2228
|
+
*/
|
|
2229
|
+
function url(message = DEFAULT_ERROR_MESSAGES.URL) {
|
|
2230
|
+
return propMetadata(Validation.key(ValidationKeys.URL), {
|
|
2231
|
+
[ValidationKeys.PATTERN]: DEFAULT_PATTERNS.URL,
|
|
2232
|
+
message: message,
|
|
2233
|
+
types: [String.name],
|
|
2234
|
+
});
|
|
2235
|
+
}
|
|
2236
|
+
/**
|
|
2237
|
+
* @summary Enforces type verification
|
|
2238
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#TYPE}
|
|
2239
|
+
*
|
|
2240
|
+
* @param {string[] | string} types accepted types
|
|
2241
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#TYPE}
|
|
2242
|
+
*
|
|
2243
|
+
* @function type
|
|
2244
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2245
|
+
* @category Decorators
|
|
2246
|
+
*/
|
|
2247
|
+
function type(types, message = DEFAULT_ERROR_MESSAGES.TYPE) {
|
|
2248
|
+
return propMetadata(Validation.key(ValidationKeys.TYPE), {
|
|
2249
|
+
customTypes: types,
|
|
2250
|
+
message: message,
|
|
2251
|
+
});
|
|
2252
|
+
}
|
|
2253
|
+
/**
|
|
2254
|
+
* @summary Date Handler Decorator
|
|
2255
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#DATE}
|
|
2256
|
+
*
|
|
2257
|
+
* Will enforce serialization according to the selected format
|
|
2258
|
+
*
|
|
2259
|
+
* @param {string} format accepted format according to {@link formatDate}
|
|
2260
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#DATE}
|
|
2261
|
+
* @param {Constructor<Validator>} [validator] the Validator to be used. Defaults to {@link DateValidator}
|
|
2262
|
+
*
|
|
2263
|
+
* @function date
|
|
2264
|
+
*
|
|
2265
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2266
|
+
* @category Decorators
|
|
2267
|
+
*/
|
|
2268
|
+
function date(format = "dd/MM/yyyy", message = DEFAULT_ERROR_MESSAGES.DATE) {
|
|
2269
|
+
return (target, propertyKey) => {
|
|
2270
|
+
propMetadata(Validation.key(ValidationKeys.DATE), {
|
|
2271
|
+
[ValidationKeys.FORMAT]: format,
|
|
2272
|
+
message: message,
|
|
2273
|
+
types: [Date.name],
|
|
2274
|
+
})(target, propertyKey);
|
|
2275
|
+
const values = new WeakMap();
|
|
2276
|
+
Object.defineProperty(target, propertyKey, {
|
|
2277
|
+
configurable: false,
|
|
2278
|
+
set(newValue) {
|
|
2279
|
+
const descriptor = Object.getOwnPropertyDescriptor(this, propertyKey);
|
|
2280
|
+
if (!descriptor || descriptor.configurable)
|
|
2281
|
+
Object.defineProperty(this, propertyKey, {
|
|
2282
|
+
enumerable: true,
|
|
2283
|
+
configurable: false,
|
|
2284
|
+
get: () => values.get(this),
|
|
2285
|
+
set: (newValue) => {
|
|
2286
|
+
let val;
|
|
2287
|
+
try {
|
|
2288
|
+
val = parseDate(format, newValue);
|
|
2289
|
+
values.set(this, val);
|
|
2290
|
+
}
|
|
2291
|
+
catch (e) {
|
|
2292
|
+
console.error(sf("Failed to parse date: {0}", e.message || e));
|
|
2293
|
+
}
|
|
2294
|
+
},
|
|
2295
|
+
});
|
|
2296
|
+
this[propertyKey] = newValue;
|
|
2297
|
+
},
|
|
2298
|
+
get() {
|
|
2299
|
+
console.log("here");
|
|
2300
|
+
},
|
|
2301
|
+
});
|
|
2302
|
+
};
|
|
2303
|
+
}
|
|
2304
|
+
/**
|
|
2305
|
+
* @summary Password Handler Decorator
|
|
2306
|
+
* @description Validators to validate a decorated property must use key {@link ValidationKeys#PASSWORD}
|
|
2307
|
+
*
|
|
2308
|
+
* @param {RegExp} [pattern] defaults to {@link PasswordPatterns#CHAR8_ONE_OF_EACH}
|
|
2309
|
+
* @param {string} [message] the error message. Defaults to {@link DEFAULT_ERROR_MESSAGES#PASSWORD}
|
|
2310
|
+
* @param {Constructor<Validator>} [validator] Defaults to {@link PasswordValidator}
|
|
2311
|
+
*
|
|
2312
|
+
* @function password
|
|
2313
|
+
*
|
|
2314
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2315
|
+
* @category Decorators
|
|
2316
|
+
*/
|
|
2317
|
+
function password(pattern = DEFAULT_PATTERNS.PASSWORD.CHAR8_ONE_OF_EACH, message = DEFAULT_ERROR_MESSAGES.PASSWORD) {
|
|
2318
|
+
return propMetadata(Validation.key(ValidationKeys.PASSWORD), {
|
|
2319
|
+
[ValidationKeys.PATTERN]: pattern,
|
|
2320
|
+
message: message,
|
|
2321
|
+
types: [String.name],
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
/**
|
|
2325
|
+
* @summary List Decorator
|
|
2326
|
+
* @description Also sets the {@link type} to the provided collection
|
|
2327
|
+
*
|
|
2328
|
+
* @param {ModelConstructor} clazz
|
|
2329
|
+
* @param {string} [collection] The collection being used. defaults to Array
|
|
2330
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#LIST}
|
|
2331
|
+
* @param {Constructor<Validator>} [validator] defaults to {@link ListValidator}
|
|
2332
|
+
*
|
|
2333
|
+
* @function list
|
|
2334
|
+
*
|
|
2335
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2336
|
+
* @category Decorators
|
|
2337
|
+
*/
|
|
2338
|
+
function list(clazz, collection = "Array", message = DEFAULT_ERROR_MESSAGES.LIST) {
|
|
2339
|
+
return propMetadata(Validation.key(ValidationKeys.LIST), {
|
|
2340
|
+
clazz: Array.isArray(clazz) ? clazz.map((c) => c.name) : [clazz.name],
|
|
2341
|
+
type: collection,
|
|
2342
|
+
message: message,
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* @summary Set Decorator
|
|
2347
|
+
* @description Wrapper for {@link list} with the 'Set' Collection
|
|
2348
|
+
*
|
|
2349
|
+
* @param {ModelConstructor} clazz
|
|
2350
|
+
* @param {string} [message] defaults to {@link DEFAULT_ERROR_MESSAGES#LIST}
|
|
2351
|
+
* @param {Constructor<Validator>} [validator]
|
|
2352
|
+
*
|
|
2353
|
+
* @function set
|
|
2354
|
+
*
|
|
2355
|
+
* @memberOf module:decorator-validation.Decorators.Validation
|
|
2356
|
+
* @category Decorators
|
|
2357
|
+
*/
|
|
2358
|
+
function set(clazz, message = DEFAULT_ERROR_MESSAGES.LIST) {
|
|
2359
|
+
return list(clazz, "Set", message);
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
/**
|
|
2363
|
+
* @summary Helper Function to override constructors
|
|
2364
|
+
*
|
|
2365
|
+
* @param {Function} constructor
|
|
2366
|
+
* @param {any[]} [args]
|
|
2367
|
+
* @return {T} the new instance
|
|
2368
|
+
*
|
|
2369
|
+
* @function construct
|
|
2370
|
+
* @memberOf module:decorator-validation.Construction
|
|
2371
|
+
*/
|
|
2372
|
+
function construct(constructor, ...args) {
|
|
2373
|
+
const _constr = (...argz) => new constructor(...argz);
|
|
2374
|
+
_constr.prototype = constructor.prototype;
|
|
2375
|
+
return _constr(...args);
|
|
2376
|
+
}
|
|
2377
|
+
/**
|
|
2378
|
+
* @summary Recursively finds the last prototype before Object
|
|
2379
|
+
* @param {object} obj
|
|
2380
|
+
*
|
|
2381
|
+
* @function findLastProtoBeforeObject
|
|
2382
|
+
* @memberOf module:decorator-validation.Construction
|
|
2383
|
+
*/
|
|
2384
|
+
function findLastProtoBeforeObject(obj) {
|
|
2385
|
+
let prototype = Object.getPrototypeOf(obj);
|
|
2386
|
+
if (prototype === Object.prototype)
|
|
2387
|
+
return obj;
|
|
2388
|
+
while (prototype !== Object.prototype) {
|
|
2389
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
2390
|
+
if (prototype === Object.prototype)
|
|
2391
|
+
return prototype;
|
|
2392
|
+
if (Object.getPrototypeOf(prototype) === Object.prototype)
|
|
2393
|
+
return prototype;
|
|
2394
|
+
}
|
|
2395
|
+
throw new Error("Could not find proper prototype");
|
|
2396
|
+
}
|
|
2397
|
+
/**
|
|
2398
|
+
* @sumary binds the {@link Model} class as a root prototype of the provided instance
|
|
2399
|
+
*
|
|
2400
|
+
* @param {unknown} obj
|
|
2401
|
+
*
|
|
2402
|
+
* @function bindModelPrototype
|
|
2403
|
+
* @memberOf module:decorator-validation.Construction
|
|
2404
|
+
*/
|
|
2405
|
+
function bindModelPrototype(obj) {
|
|
2406
|
+
if (obj instanceof Model)
|
|
2407
|
+
return;
|
|
2408
|
+
function bindPrototype(objToOverride, prototype) {
|
|
2409
|
+
Object.setPrototypeOf(objToOverride, prototype);
|
|
2410
|
+
}
|
|
2411
|
+
const prototype = Object.getPrototypeOf(obj);
|
|
2412
|
+
if (prototype === Object.prototype) {
|
|
2413
|
+
return bindPrototype(obj, Model.prototype);
|
|
2414
|
+
}
|
|
2415
|
+
while (prototype !== Object.prototype) {
|
|
2416
|
+
const prot = Object.getPrototypeOf(prototype);
|
|
2417
|
+
if (prot === Object.prototype ||
|
|
2418
|
+
Object.getPrototypeOf(prot) === Object.prototype) {
|
|
2419
|
+
return bindPrototype(prototype, Model.prototype);
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
throw new Error("Could not find proper prototype to bind");
|
|
2423
|
+
}
|
|
2424
|
+
|
|
2425
|
+
/**
|
|
2426
|
+
* @summary Defines a class as a Model class
|
|
2427
|
+
* @description
|
|
2428
|
+
*
|
|
2429
|
+
* - Registers the class under the model registry so it can be easily rebuilt;
|
|
2430
|
+
* - Overrides the class constructor;
|
|
2431
|
+
* - Runs the global {@link ModelBuilderFunction} if defined;
|
|
2432
|
+
* - Runs the optional {@link InstanceCallback} if provided;
|
|
2433
|
+
*
|
|
2434
|
+
* @param {InstanceCallback} [instanceCallback] optional callback that will be called with the instance upon instantiation. defaults to undefined
|
|
2435
|
+
*
|
|
2436
|
+
* @function model
|
|
2437
|
+
*
|
|
2438
|
+
* @memberOf module:decorator-validation.Model
|
|
2439
|
+
*
|
|
2440
|
+
*/
|
|
2441
|
+
function model(instanceCallback) {
|
|
2442
|
+
return ((original) => {
|
|
2443
|
+
// the new constructor behaviour
|
|
2444
|
+
const newConstructor = function (...args) {
|
|
2445
|
+
const instance = construct(original, ...args);
|
|
2446
|
+
bindModelPrototype(instance);
|
|
2447
|
+
// run a builder function if defined with the first argument (The ModelArg)
|
|
2448
|
+
const builder = Model.getBuilder();
|
|
2449
|
+
if (builder)
|
|
2450
|
+
builder(instance, args.length ? args[0] : undefined);
|
|
2451
|
+
metadata(Model.key(ModelKeys.MODEL), original.name)(instance.constructor);
|
|
2452
|
+
if (instanceCallback)
|
|
2453
|
+
instanceCallback(instance, ...args);
|
|
2454
|
+
return instance;
|
|
2455
|
+
};
|
|
2456
|
+
// copy prototype so instanceof operator still works
|
|
2457
|
+
newConstructor.prototype = original.prototype;
|
|
2458
|
+
// Sets the proper constructor name for type verification
|
|
2459
|
+
Object.defineProperty(newConstructor, "name", {
|
|
2460
|
+
writable: false,
|
|
2461
|
+
enumerable: true,
|
|
2462
|
+
configurable: false,
|
|
2463
|
+
value: original.prototype.constructor.name,
|
|
2464
|
+
});
|
|
2465
|
+
metadata(Model.key(ModelKeys.MODEL), original.name)(original);
|
|
2466
|
+
Model.register(newConstructor, original.name);
|
|
2467
|
+
// return new constructor (will override original)
|
|
2468
|
+
return newConstructor;
|
|
2469
|
+
});
|
|
2470
|
+
}
|
|
2471
|
+
function hashedBy(algorithm, ...args) {
|
|
2472
|
+
return metadata(Model.key(ModelKeys.HASHING), {
|
|
2473
|
+
algorithm: algorithm,
|
|
2474
|
+
args: args,
|
|
2475
|
+
});
|
|
2476
|
+
}
|
|
2477
|
+
function serializedBy(serializer, ...args) {
|
|
2478
|
+
return metadata(Model.key(ModelKeys.SERIALIZATION), {
|
|
2479
|
+
serializer: serializer,
|
|
2480
|
+
args: args,
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
|
|
2484
|
+
/**
|
|
2485
|
+
* @module decorator-validation
|
|
2486
|
+
*/
|
|
2487
|
+
/**
|
|
2488
|
+
* @summary Model definition functionality
|
|
2489
|
+
* @description defines the base class and related functionality
|
|
2490
|
+
*
|
|
2491
|
+
* @namespace Model
|
|
2492
|
+
* @memberOf module:decorator-validation
|
|
2493
|
+
*/
|
|
2494
|
+
/**
|
|
2495
|
+
* @summary Holds all the supported decorators
|
|
2496
|
+
* @namespace Decorators
|
|
2497
|
+
* @memberOf module:decorator-validation
|
|
2498
|
+
*/
|
|
2499
|
+
/**
|
|
2500
|
+
* @summary Validation related functionality
|
|
2501
|
+
* @description Defines the Model validation apis and base classes for validators
|
|
2502
|
+
*
|
|
2503
|
+
* @namespace Validation
|
|
2504
|
+
* @memberOf module:decorator-validation
|
|
2505
|
+
*/
|
|
2506
|
+
/**
|
|
2507
|
+
* @namespace Dates
|
|
2508
|
+
* @memberOf module:decorator-validation
|
|
2509
|
+
*/
|
|
2510
|
+
/**
|
|
2511
|
+
* @namespace Hashing
|
|
2512
|
+
* @memberOf module:decorator-validation
|
|
2513
|
+
*/
|
|
2514
|
+
/**
|
|
2515
|
+
* @namespace Serialization
|
|
2516
|
+
* @memberOf module:decorator-validation
|
|
2517
|
+
*/
|
|
2518
|
+
/**
|
|
2519
|
+
* @namespace Format
|
|
2520
|
+
* @memberOf module:decorator-validation
|
|
2521
|
+
*/
|
|
2522
|
+
const VERSION = "1.6.1";
|
|
2523
|
+
|
|
2524
|
+
export { DAYS_OF_WEEK_NAMES, DEFAULT_ERROR_MESSAGES, DEFAULT_PATTERNS, DateValidator, DefaultHashingMethod, DefaultSerializationMethod, EmailValidator, Hashing, JSONSerializer, ListValidator, MONTH_NAMES, MaxLengthValidator, MaxValidator, MinLengthValidator, MinValidator, Model, ModelErrorDefinition, ModelKeys, ModelRegistryManager, PasswordValidator, PatternValidator, Primitives, RequiredValidator, ReservedModels, Serialization, StepValidator, TypeValidator, URLValidator, VERSION, Validation, ValidationKeys, Validator, ValidatorRegistry, bindDateToString, bindModelPrototype, bulkModelRegister, construct, date, dateFromFormat, email, findLastProtoBeforeObject, formatDate, hashCode, hashObj, hashedBy, isModel, isPropertyModel, isValidDate, isValidator, jsTypes, list, max, maxlength, min, minlength, model, parseDate, password, pattern, prop, propMetadata, regexpParser, required, serializedBy, set, sf, step, stringFormat, twoDigitPad, type, url, validate, validator };
|
|
2525
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdG9yLXZhbGlkYXRpb24uZXNtLmNqcyIsInNvdXJjZXMiOlsiLi4vc3JjL3V0aWxzL2NvbnN0YW50cy50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvY29uc3RhbnRzLnRzIiwiLi4vc3JjL3V0aWxzL3N0cmluZ3MudHMiLCIuLi9zcmMvdXRpbHMvZGF0ZXMudHMiLCIuLi9zcmMvdXRpbHMvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy91dGlscy9oYXNoaW5nLnRzIiwiLi4vc3JjL21vZGVsL01vZGVsRXJyb3JEZWZpbml0aW9uLnRzIiwiLi4vc3JjL21vZGVsL2NvbnN0YW50cy50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvVmFsaWRhdG9yUmVnaXN0cnkudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9WYWxpZGF0aW9uLnRzIiwiLi4vc3JjL21vZGVsL3ZhbGlkYXRpb24udHMiLCIuLi9zcmMvbW9kZWwvTW9kZWwudHMiLCIuLi9zcmMvdXRpbHMvc2VyaWFsaXphdGlvbi50cyIsIi4uL25vZGVfbW9kdWxlcy90c2xpYi90c2xpYi5lczYuanMiLCIuLi9zcmMvdmFsaWRhdGlvbi9WYWxpZGF0b3JzL1ZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvZGVjb3JhdG9ycy50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvRGF0ZVZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvUGF0dGVyblZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvRW1haWxWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9WYWxpZGF0b3JzL0xpc3RWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9WYWxpZGF0b3JzL01heExlbmd0aFZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvTWF4VmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9NaW5MZW5ndGhWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9WYWxpZGF0b3JzL01pblZhbGlkYXRvci50cyIsIi4uL3NyYy92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvUGFzc3dvcmRWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9WYWxpZGF0b3JzL1JlcXVpcmVkVmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9TdGVwVmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9UeXBlVmFsaWRhdG9yLnRzIiwiLi4vc3JjL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9VUkxWYWxpZGF0b3IudHMiLCIuLi9zcmMvdmFsaWRhdGlvbi9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL21vZGVsL2NvbnN0cnVjdGlvbi50cyIsIi4uL3NyYy9tb2RlbC9kZWNvcmF0b3JzLnRzIiwiLi4vc3JjL2luZGV4LnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgdmFyaW91cyBNb2RlbCBrZXlzIHVzZWQgZm9yIHJlZmxlY3Rpb25cbiAqXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkVGTEVDVCBwcmVmaXggdG8gYWxsIG90aGVyIGtleXNcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUWVBFIHR5cGUga2V5XG4gKiBAcHJvcGVydHkge3N0cmluZ30gUEFSQU1TIG1ldGhvZCBwYXJhbXMga2V5XG4gKiBAcHJvcGVydHkge3N0cmluZ30gUkVUVVJOIG1ldGhvZCByZXR1cm4ga2V5XG4gKiBAcHJvcGVydHkge3N0cmluZ30gTU9ERUwgbW9kZWwga2V5XG4gKiBAcHJvcGVydHkge3N0cmluZ30gQU5DSE9SIGFuY2hvciBrZXkuIHdpbGwgc2VydmUgYXMgYSBnaG9zdCBwcm9wZXJ0eSBpbiB0aGUgbW9kZWxcbiAqXG4gKiBAY29uc3RhbnQgTW9kZWxLZXlzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLk1vZGVsXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGVudW0gTW9kZWxLZXlzIHtcbiAgUkVGTEVDVCA9IFwiZGVjYWYubW9kZWwuXCIsXG4gIFRZUEUgPSBcImRlc2lnbjp0eXBlXCIsXG4gIFBBUkFNUyA9IFwiZGVzaWduOnBhcmFtdHlwZXNcIixcbiAgUkVUVVJOID0gXCJkZXNpZ246cmV0dXJudHlwZVwiLFxuICBNT0RFTCA9IFwibW9kZWxcIixcbiAgQU5DSE9SID0gXCJfX21vZGVsXCIsXG4gIENPTlNUUlVDVElPTiA9IFwiY29uc3RydWN0ZWQtYnlcIixcbiAgQVRUUklCVVRFID0gXCJfX2F0dHJpYnV0ZXNcIixcbiAgSEFTSElORyA9IFwiaGFzaGluZ1wiLFxuICBTRVJJQUxJWkFUSU9OID0gXCJzZXJpYWxpemF0aW9uXCIsXG59XG4iLCJpbXBvcnQgeyBNb2RlbEtleXMgfSBmcm9tIFwiLi4vLi4vdXRpbHMvY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgVGhlIGtleXMgdXNlZCBmb3IgdmFsaWRhdGlvblxuICpcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRUZMRUNUIHByZWZpeGVzIG90aGVyc1xuICogQHByb3BlcnR5IHtzdHJpbmd9IFJFUVVJUkVEIHNldHMgYXMgcmVxdWlyZWRcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBNSU4gZGVmaW5lcyBtaW4gdmFsdWVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBNQVggZGVmaW5lcyBtYXggdmFsdWVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTVEVQIGRlZmluZXMgc3RlcFxuICogQHByb3BlcnR5IHtzdHJpbmd9IE1JTl9MRU5HVEggZGVmaW5lcyBtaW4gbGVuZ3RoXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTUFYX0xFTkdUSCBkZWZpbmVzIG1heCBsZW5ndGhcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBQQVRURVJOIGRlZmluZXMgcGF0dGVyblxuICogQHByb3BlcnR5IHtzdHJpbmd9IEVNQUlMIGRlZmluZXMgZW1haWxcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBVUkwgZGVmaW5lcyB1cmxcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBEQVRFIGRlZmluZXMgZGF0ZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFRZUEUgZGVmaW5lcyB0eXBlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gUEFTU1dPUkQgZGVmaW5lcyBwYXNzd29yZFxuICogQHByb3BlcnR5IHtzdHJpbmd9IExJU1QgZGVmaW5lcyBsaXN0XG4gKlxuICogQGNvbnN0YW50IFZhbGlkYXRpb25LZXlzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBWYWxpZGF0aW9uS2V5cyA9IHtcbiAgUkVGTEVDVDogYCR7TW9kZWxLZXlzLlJFRkxFQ1R9dmFsaWRhdGlvbi5gLFxuICBWQUxJREFUT1I6IFwidmFsaWRhdG9yXCIsXG4gIFJFUVVJUkVEOiBcInJlcXVpcmVkXCIsXG4gIE1JTjogXCJtaW5cIixcbiAgTUFYOiBcIm1heFwiLFxuICBTVEVQOiBcInN0ZXBcIixcbiAgTUlOX0xFTkdUSDogXCJtaW5sZW5ndGhcIixcbiAgTUFYX0xFTkdUSDogXCJtYXhsZW5ndGhcIixcbiAgUEFUVEVSTjogXCJwYXR0ZXJuXCIsXG4gIEVNQUlMOiBcImVtYWlsXCIsXG4gIFVSTDogXCJ1cmxcIixcbiAgREFURTogXCJkYXRlXCIsXG4gIFRZUEU6IFwidHlwZVwiLFxuICBQQVNTV09SRDogXCJwYXNzd29yZFwiLFxuICBMSVNUOiBcImxpc3RcIixcbiAgRk9STUFUOiBcImZvcm1hdFwiLFxufSBhcyBjb25zdDtcblxuLyoqXG4gKiBAc3VtbWFyeSBsaXN0IG9mIG1vbnRoIG5hbWVzXG4gKiBAZGVzY3JpcHRpb24gU3RvcmVzIG1vbnRoIG5hbWVzLiBDYW4gYmUgY2hhbmdlZCBmb3IgbG9jYWxpemF0aW9uIHB1cnBvc2VzXG4gKlxuICogQGNvbnN0YW50IE1PTlRIX05BTUVTXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBNT05USF9OQU1FUyA9IFtcbiAgXCJKYW51YXJ5XCIsXG4gIFwiRmVicnVhcnlcIixcbiAgXCJNYXJjaFwiLFxuICBcIkFwcmlsXCIsXG4gIFwiTWF5XCIsXG4gIFwiSnVuZVwiLFxuICBcIkp1bHlcIixcbiAgXCJBdWd1c3RcIixcbiAgXCJTZXB0ZW1iZXJcIixcbiAgXCJPY3RvYmVyXCIsXG4gIFwiTm92ZW1iZXJcIixcbiAgXCJEZWNlbWJlclwiLFxuXTtcblxuLyoqXG4gKiBAc3VtbWFyeSBsaXN0IG9mIG5hbWVzIG9mIGRheXMgb2YgdGhlIHdlZWtcbiAqIEBkZXNjcmlwdGlvbiBTdG9yZXMgbmFtZXMgZm9yIGRheXMgb2YgdGhlIHdlZWsuIENhbiBiZSBjaGFuZ2VkIGZvciBsb2NhbGl6YXRpb24gcHVycG9zZXNcbiAqXG4gKiBAY29uc3RhbnQgREFZU19PRl9XRUVLX05BTUVTXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBEQVlTX09GX1dFRUtfTkFNRVMgPSBbXG4gIFwiU3VuZGF5XCIsXG4gIFwiTW9uZGF5XCIsXG4gIFwiVHVlc2RheVwiLFxuICBcIldlZG5lc2RheVwiLFxuICBcIlRodXJzZGF5XCIsXG4gIFwiRnJpZGF5XCIsXG4gIFwiU2F0dXJkYXlcIixcbl07XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgZGVmYXVsdCBlcnJvciBtZXNzYWdlc1xuICpcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBSRVFVSVJFRCBkZWZhdWx0IGVycm9yIG1lc3NhZ2VcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBNSU4gZGVmYXVsdCBlcnJvciBtZXNzYWdlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTUFYIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IE1JTl9MRU5HVEggZGVmYXVsdCBlcnJvciBtZXNzYWdlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTUFYX0xFTkdUSCBkZWZhdWx0IGVycm9yIG1lc3NhZ2VcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBQQVRURVJOIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IEVNQUlMIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFVSTCBkZWZhdWx0IGVycm9yIG1lc3NhZ2VcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBUWVBFIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFNURVAgZGVmYXVsdCBlcnJvciBtZXNzYWdlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gREFURSBkZWZhdWx0IGVycm9yIG1lc3NhZ2VcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBERUZBVUxUIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IFBBU1NXT1JEIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IExJU1QgZGVmYXVsdCBlcnJvciBtZXNzYWdlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTElTVF9JTlNJREUgZGVmYXVsdCBlcnJvciBtZXNzYWdlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTU9ERUxfTk9UX0ZPVU5EIGRlZmF1bHQgZXJyb3IgbWVzc2FnZVxuICpcbiAqIEBjb25zdGFudCBERUZBVUxUX0VSUk9SX01FU1NBR0VTXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0VSUk9SX01FU1NBR0VTOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICBSRVFVSVJFRDogXCJUaGlzIGZpZWxkIGlzIHJlcXVpcmVkXCIsXG4gIE1JTjogXCJUaGUgbWluaW11bSB2YWx1ZSBpcyB7MH1cIixcbiAgTUFYOiBcIlRoZSBtYXhpbXVtIHZhbHVlIGlzIHswfVwiLFxuICBNSU5fTEVOR1RIOiBcIlRoZSBtaW5pbXVtIGxlbmd0aCBpcyB7MH1cIixcbiAgTUFYX0xFTkdUSDogXCJUaGUgbWF4aW11bSBsZW5ndGggaXMgezB9XCIsXG4gIFBBVFRFUk46IFwiVGhlIHZhbHVlIGRvZXMgbm90IG1hdGNoIHRoZSBwYXR0ZXJuXCIsXG4gIEVNQUlMOiBcIlRoZSB2YWx1ZSBpcyBub3QgYSB2YWxpZCBlbWFpbFwiLFxuICBVUkw6IFwiVGhlIHZhbHVlIGlzIG5vdCBhIHZhbGlkIFVSTFwiLFxuICBUWVBFOiBcIkludmFsaWQgdHlwZS4gRXhwZWN0ZWQgezB9LCByZWNlaXZlZCB7MX1cIixcbiAgU1RFUDogXCJJbnZhbGlkIHZhbHVlLiBOb3QgYSBzdGVwIG9mIHswfVwiLFxuICBEQVRFOiBcIkludmFsaWQgdmFsdWUuIG5vdCBhIHZhbGlkIERhdGVcIixcbiAgREVGQVVMVDogXCJUaGVyZSBpcyBhbiBFcnJvclwiLFxuICBQQVNTV09SRDpcbiAgICBcIk11c3QgYmUgYXQgbGVhc3QgOCBjaGFyYWN0ZXJzIGFuZCBjb250YWluIG9uZSBvZiBudW1iZXIsIGxvd2VyIGFuZCB1cHBlciBjYXNlIGxldHRlcnMsIGFuZCBzcGVjaWFsIGNoYXJhY3RlciAoQCQhJSo/Jl8tLiwpXCIsXG4gIExJU1Q6IFwiSW52YWxpZCBsaXN0IG9mIHswfVwiLFxuICBNT0RFTF9OT1RfRk9VTkQ6IFwiTm8gbW9kZWwgcmVnaXN0ZXJlZCB1bmRlciB7MH1cIixcbn07XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgdmFyaW91cyBkZWZhdWx0IHJlZ2V4cCBwYXR0ZXJucyB1c2VkXG4gKlxuICogQGVudW0gREVGQVVMVF9QQVRURVJOU1xuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdGlvblxuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9QQVRURVJOUyA9IHtcbiAgRU1BSUw6XG4gICAgL1thLXpBLVowLTkhIyQlJicqKy89P15fYHt8fX4tXSsoPzpcXC5bYS16QS1aMC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKSpAKD86W2EtekEtWjAtOV0oPzpbYS16MC05LV0qW2EtekEtWjAtOV0pP1xcLikrW2EtekEtWjAtOV0oPzpbYS16QS1aMC05LV0qW2EtekEtWjAtOV0pPy8sXG4gIFVSTDogL14oPzooPzooPzpodHRwcz98ZnRwKTopP1xcL1xcLykoPzpcXFMrKD86OlxcUyopP0ApPyg/Oig/ISg/OjEwfDEyNykoPzpcXC5cXGR7MSwzfSl7M30pKD8hKD86MTY5XFwuMjU0fDE5MlxcLjE2OCkoPzpcXC5cXGR7MSwzfSl7Mn0pKD8hMTcyXFwuKD86MVs2LTldfDJcXGR8M1swLTFdKSg/OlxcLlxcZHsxLDN9KXsyfSkoPzpbMS05XVxcZD98MVxcZFxcZHwyWzAxXVxcZHwyMlswLTNdKSg/OlxcLig/OjE/XFxkezEsMn18MlswLTRdXFxkfDI1WzAtNV0pKXsyfSg/OlxcLig/OlsxLTldXFxkP3wxXFxkXFxkfDJbMC00XVxcZHwyNVswLTRdKSl8KD86KD86W2EtejAtOVxcdTAwYTEtXFx1ZmZmZl1bYS16MC05XFx1MDBhMS1cXHVmZmZmXy1dezAsNjJ9KT9bYS16MC05XFx1MDBhMS1cXHVmZmZmXVxcLikrKD86W2EtelxcdTAwYTEtXFx1ZmZmZl17Mix9XFwuPykpKD86OlxcZHsyLDV9KT8oPzpbLz8jXVxcUyopPyQvaSxcbiAgUEFTU1dPUkQ6IHtcbiAgICBDSEFSOF9PTkVfT0ZfRUFDSDpcbiAgICAgIC9eKD89LipbYS16XSkoPz0uKltBLVpdKSg/PS4qXFxkKSg/PS4qW0AkISUqPyZfXFwtLixdKVtBLVphLXpcXGRAJCElKj8mX1xcLS4sXXs4LH0kL2csXG4gIH0sXG59O1xuIiwiLyoqXG4gKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIHByb3ZpZGUgc3RyaW5nIGZvcm1hdCBmdW5jdGlvbmFsaXR5IHNpbWlsYXIgdG8gQyMncyBzdHJpbmcuZm9ybWF0XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZ1xuICogQHBhcmFtIHtBcnJheTxzdHJpbmcgfCBudW1iZXI+fSBbYXJnc10gcmVwbGFjZW1lbnRzIG1hZGUgYnkgb3JkZXIgb2YgYXBwZWFyYW5jZSAocmVwbGFjZW1lbnQwIHdpbCByZXBsYWNlIHswfSBhbmQgc28gb24pXG4gKiBAcmV0dXJuIHtzdHJpbmd9IGZvcm1hdHRlZCBzdHJpbmdcbiAqXG4gKiBAZnVuY3Rpb24gc3RyaW5nRm9ybWF0XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlV0aWxzLkZvcm1hdFxuICogQGNhdGVnb3J5IEZvcm1hdFxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RyaW5nRm9ybWF0KHN0cmluZzogc3RyaW5nLCAuLi5hcmdzOiAoc3RyaW5nIHwgbnVtYmVyKVtdKSB7XG4gIHJldHVybiBzdHJpbmcucmVwbGFjZSgveyhcXGQrKX0vZywgZnVuY3Rpb24gKG1hdGNoLCBudW1iZXIpIHtcbiAgICByZXR1cm4gdHlwZW9mIGFyZ3NbbnVtYmVyXSAhPT0gXCJ1bmRlZmluZWRcIlxuICAgICAgPyBhcmdzW251bWJlcl0udG9TdHJpbmcoKVxuICAgICAgOiBcInVuZGVmaW5lZFwiO1xuICB9KTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIHByb3ZpZGUgc3RyaW5nIGZvcm1hdCBmdW5jdGlvbmFsaXR5IHNpbWlsYXIgdG8gQyMncyBzdHJpbmcuZm9ybWF0XG4gKiBAZGVzY3JpcHRpb24gYWxpYXMgZm9yIHtAbGluayBzdHJpbmdGb3JtYXR9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MgcmVwbGFjZW1lbnRzIG1hZGUgYnkgb3JkZXIgb2YgYXBwZWFyYW5jZSAocmVwbGFjZW1lbnQwIHdpbCByZXBsYWNlIHswfSBhbmQgc28gb24pXG4gKiBAcmV0dXJuIHtzdHJpbmd9IGZvcm1hdHRlZCBzdHJpbmdcbiAqXG4gKiBAZnVuY3Rpb24gc2ZcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uVXRpbHMuRm9ybWF0XG4gKiBAY2F0ZWdvcnkgRm9ybWF0XG4gKi9cbmV4cG9ydCBjb25zdCBzZiA9IHN0cmluZ0Zvcm1hdDtcbiIsImltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcbmltcG9ydCB7XG4gIERBWVNfT0ZfV0VFS19OQU1FUyxcbiAgTU9OVEhfTkFNRVMsXG59IGZyb20gXCIuLi92YWxpZGF0aW9uL1ZhbGlkYXRvcnMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBzZiB9IGZyb20gXCIuL3N0cmluZ3NcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBSZXZlcnNlcyB0aGUgcHJvY2VzcyBmcm9tIHtAbGluayBmb3JtYXREYXRlfVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBkYXRlIHRoZSBkYXRlIHN0cmluZyB0byBiZSBjb252ZXJ0ZWQgYmFjayBpbnRvIGRhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgdGhlIGRhdGUgZm9ybWF0XG4gKiBAcmV0dXJuIHtEYXRlfSB0aGUgZGF0ZSBmcm9tIHRoZSBmb3JtYXQgb3IgdGhlIHN0YW5kYXJkIG5ldyBEYXRlKHtAcHJvcCBkYXRlfSkgaWYgdGhlIHN0cmluZyBjb3VsZG4ndCBiZSBwYXJzZWQgKGFyZSB5b3Ugc3VyZSB0aGUgZm9ybWF0IG1hdGNoZXMgdGhlIHN0cmluZz8pXG4gKlxuICogQGZ1bmN0aW9uIGRhdGVGcm9tRm9ybWF0XG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlV0aWxzLkRhdGVzXG4gKiBAY2F0ZWdvcnkgRm9ybWF0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkYXRlRnJvbUZvcm1hdChkYXRlOiBzdHJpbmcsIGZvcm1hdDogc3RyaW5nKSB7XG4gIGxldCBmb3JtYXRSZWdleHA6IHN0cmluZyA9IGZvcm1hdDtcblxuICAvLyBIb3VyXG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL2hoLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJoaFwiLCBcIig/PGhvdXI+XFxcXGR7Mn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL2gvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcImhcIiwgXCIoPzxob3VyPlxcXFxkezEsMn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL0hILykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJISFwiLCBcIig/PGhvdXI+XFxcXGR7Mn0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL0gvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIkhcIiwgXCIoPzxob3VyPlxcXFxkezEsMn0pXCIpO1xuXG4gIC8vIE1pbnV0ZXNcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvbW0vKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIm1tXCIsIFwiKD88bWludXRlcz5cXFxcZHsyfSlcIik7XG4gIGVsc2UgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvbS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwibVwiLCBcIig/PG1pbnV0ZXM+XFxcXGR7MSwyfSlcIik7XG5cbiAgLy8gU2Vjb25kc1xuICBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9zcy8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwic3NcIiwgXCIoPzxzZWNvbmRzPlxcXFxkezJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9zLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJzXCIsIFwiKD88c2Vjb25kcz5cXFxcZHsxLDJ9KVwiKTtcblxuICAvLyBEYXlcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgvZGQvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcImRkXCIsIFwiKD88ZGF5PlxcXFxkezJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9kLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJkXCIsIFwiKD88ZGF5PlxcXFxkezEsMn0pXCIpO1xuXG4gIC8vIERheSBPZiBXZWVrXG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL0VFRUUvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIkVFRUVcIiwgXCIoPzxkYXlvZndlZWs+XFxcXHcrKVwiKTtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWR1cGUtZWxzZS1pZlxuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL0VFRUUvKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIkVFRVwiLCBcIig/PGRheW9md2Vlaz5cXFxcdyspXCIpO1xuXG4gIC8vIFllYXJcbiAgaWYgKGZvcm1hdFJlZ2V4cC5tYXRjaCgveXl5eS8pKVxuICAgIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cC5yZXBsYWNlKFwieXl5eVwiLCBcIig/PHllYXI+XFxcXGR7NH0pXCIpO1xuICBlbHNlIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL3l5LykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJ5eVwiLCBcIig/PHllYXI+XFxcXGR7Mn0pXCIpO1xuXG4gIC8vIE1vbnRoXG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL01NTU0vKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIk1NTU1cIiwgXCIoPzxtb250aG5hbWU+XFxcXHcrKVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9NTU0vKSlcbiAgICBmb3JtYXRSZWdleHAgPSBmb3JtYXRSZWdleHAucmVwbGFjZShcIk1NTVwiLCBcIig/PG1vbnRobmFtZXNtYWxsPlxcXFx3KylcIik7XG4gIGlmIChmb3JtYXRSZWdleHAubWF0Y2goL01NLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJNTVwiLCBcIig/PG1vbnRoPlxcXFxkezJ9KVwiKTtcbiAgZWxzZSBpZiAoZm9ybWF0UmVnZXhwLm1hdGNoKC9NLykpXG4gICAgZm9ybWF0UmVnZXhwID0gZm9ybWF0UmVnZXhwLnJlcGxhY2UoXCJNXCIsIFwiKD88bW9udGg+XFxcXGR7MSwyfSlcIik7XG5cbiAgLy8gTWlsaXMgYW5kIEFtIFBtXG4gIGZvcm1hdFJlZ2V4cCA9IGZvcm1hdFJlZ2V4cFxuICAgIC5yZXBsYWNlKFwiU1wiLCBcIig/PG1pbGlzPlxcXFxkezEsM30pXCIpXG4gICAgLnJlcGxhY2UoXCJhYWFcIiwgXCIoPzxhbXBtPlxcXFx3ezJ9KVwiKTtcblxuICBjb25zdCByZWdleHAgPSBuZXcgUmVnRXhwKGZvcm1hdFJlZ2V4cCwgXCJnXCIpO1xuXG4gIGNvbnN0IG1hdGNoOiB7XG4gICAgZ3JvdXBzOiB7XG4gICAgICB5ZWFyPzogc3RyaW5nO1xuICAgICAgZGF5Pzogc3RyaW5nO1xuICAgICAgYW1wbT86IHN0cmluZztcbiAgICAgIGhvdXI/OiBzdHJpbmc7XG4gICAgICBtaW51dGVzPzogc3RyaW5nO1xuICAgICAgc2Vjb25kcz86IHN0cmluZztcbiAgICAgIG1pbGlzPzogc3RyaW5nO1xuICAgICAgbW9udGhuYW1lPzogc3RyaW5nO1xuICAgICAgbW9udGhuYW1lc21hbGw/OiBzdHJpbmc7XG4gICAgICBtb250aD86IHN0cmluZztcbiAgICB9O1xuICB9ID0gcmVnZXhwLmV4ZWMoZGF0ZSkgYXMgYW55O1xuXG4gIGlmICghbWF0Y2ggfHwgIW1hdGNoLmdyb3VwcykgcmV0dXJuIG5ldyBEYXRlKGRhdGUpO1xuXG4gIGNvbnN0IHNhZmVQYXJzZUludCA9IGZ1bmN0aW9uIChuPzogc3RyaW5nKSB7XG4gICAgaWYgKCFuKSByZXR1cm4gMDtcbiAgICBjb25zdCByZXN1bHQgPSBwYXJzZUludChuKTtcblxuICAgIHJldHVybiBpc05hTihyZXN1bHQpID8gMCA6IHJlc3VsdDtcbiAgfTtcblxuICBjb25zdCB5ZWFyID0gc2FmZVBhcnNlSW50KG1hdGNoLmdyb3Vwcy55ZWFyKTtcbiAgY29uc3QgZGF5ID0gc2FmZVBhcnNlSW50KG1hdGNoLmdyb3Vwcy5kYXkpO1xuXG4gIGNvbnN0IGFtUG0gPSBtYXRjaC5ncm91cHMuYW1wbTtcbiAgbGV0IGhvdXIgPSBzYWZlUGFyc2VJbnQobWF0Y2guZ3JvdXBzLmhvdXIpO1xuXG4gIGlmIChhbVBtKSBob3VyID0gYW1QbSA9PT0gXCJQTVwiID8gaG91ciArIDEyIDogaG91cjtcblxuICBjb25zdCBtaW51dGVzID0gc2FmZVBhcnNlSW50KG1hdGNoLmdyb3Vwcy5taW51dGVzKTtcbiAgY29uc3Qgc2Vjb25kcyA9IHNhZmVQYXJzZUludChtYXRjaC5ncm91cHMuc2Vjb25kcyk7XG4gIGNvbnN0IG1zID0gc2FmZVBhcnNlSW50KG1hdGNoLmdyb3Vwcy5taWxpcyk7XG5cbiAgY29uc3QgbW9udGhOYW1lID0gbWF0Y2guZ3JvdXBzLm1vbnRobmFtZTtcbiAgY29uc3QgbW9udGhOYW1lU21hbGwgPSBtYXRjaC5ncm91cHMubW9udGhuYW1lc21hbGw7XG4gIGxldCBtb250aDogbnVtYmVyIHwgc3RyaW5nID0gbWF0Y2guZ3JvdXBzLm1vbnRoIGFzIHN0cmluZztcbiAgaWYgKG1vbnRoTmFtZSkgbW9udGggPSBNT05USF9OQU1FUy5pbmRleE9mKG1vbnRoTmFtZSk7XG4gIGVsc2UgaWYgKG1vbnRoTmFtZVNtYWxsKSB7XG4gICAgY29uc3QgbSA9IE1PTlRIX05BTUVTLmZpbmQoKG0pID0+XG4gICAgICBtLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChtb250aE5hbWVTbWFsbC50b0xvd2VyQ2FzZSgpKVxuICAgICk7XG4gICAgaWYgKCFtKSByZXR1cm4gbmV3IERhdGUoZGF0ZSk7XG4gICAgbW9udGggPSBNT05USF9OQU1FUy5pbmRleE9mKG0pO1xuICB9IGVsc2UgbW9udGggPSBzYWZlUGFyc2VJbnQoYCR7bW9udGh9YCk7XG5cbiAgcmV0dXJuIG5ldyBEYXRlKHllYXIsIG1vbnRoIC0gMSwgZGF5LCBob3VyLCBtaW51dGVzLCBzZWNvbmRzLCBtcyk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgQmluZHMgYSBkYXRlIGZvcm1hdCB0byBhIHN0cmluZ1xuICogQHBhcmFtIHtEYXRlfSBbZGF0ZV1cbiAqIEBwYXJhbSB7c3RyaW5nfSBbZm9ybWF0XVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5VdGlscy5Gb3JtYXRcbiAqIEBjYXRlZ29yeSBVdGlsaXRpZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJpbmREYXRlVG9TdHJpbmcoZGF0ZTogRGF0ZSB8IHVuZGVmaW5lZCwgZm9ybWF0OiBzdHJpbmcpIHtcbiAgaWYgKCFkYXRlKSByZXR1cm47XG4gIGNvbnN0IGZ1bmMgPSAoKSA9PiBmb3JtYXREYXRlKGRhdGUsIGZvcm1hdCk7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYXRlLCBcInRvSVNPU3RyaW5nXCIsIHtcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIHZhbHVlOiBmdW5jLFxuICB9KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRhdGUsIFwidG9TdHJpbmdcIiwge1xuICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgdmFsdWU6IGZ1bmMsXG4gIH0pO1xuICAvLyBPYmplY3Quc2V0UHJvdG90eXBlT2YoZGF0ZSwgRGF0ZS5wcm90b3R5cGUpO1xuICByZXR1cm4gZGF0ZTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBIZWxwZXIgZnVuY3Rpb24gdG8gYmUgdXNlZCBpbnN0ZWFkIG9mIGluc3RhbmNlT2YgRGF0ZVxuICogQHBhcmFtIGRhdGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uVXRpbHMuRGF0ZXNcbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkRGF0ZShkYXRlOiBhbnkpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBkYXRlICYmXG4gICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGUpID09PSBcIltvYmplY3QgRGF0ZV1cIiAmJlxuICAgICFOdW1iZXIuaXNOYU4oZGF0ZSlcbiAgKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBVdGlsIGZ1bmN0aW9uIHRvIHBhZCBudW1iZXJzXG4gKiBAcGFyYW0ge251bWJlcn0gbnVtXG4gKlxuICogQHJldHVybiB7c3RyaW5nfVxuICpcbiAqIEBmdW5jdGlvbiB0d29EaWdpdFBhZFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5VdGlscy5Gb3JtYXRcbiAqIEBjYXRlZ29yeSBGb3JtYXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR3b0RpZ2l0UGFkKG51bTogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIG51bSA8IDEwID8gXCIwXCIgKyBudW0gOiBudW0udG9TdHJpbmcoKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEYXRlIEZvcm1hdCBIYW5kbGluZ1xuICogQGRlc2NyaXB0aW9uIENvZGUgZnJvbSB7QGxpbmsgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMzU1MjQ2MS9ob3ctdG8tZm9ybWF0LWEtamF2YXNjcmlwdC1kYXRlfVxuICpcbiAqIDxwcmU+XG4gKiAgICAgIFVzaW5nIHNpbWlsYXIgZm9ybWF0dGluZyBhcyBNb21lbnQuanMsIENsYXNzIERhdGVUaW1lRm9ybWF0dGVyIChKYXZhKSwgYW5kIENsYXNzIFNpbXBsZURhdGVGb3JtYXQgKEphdmEpLFxuICogICAgICBJIGltcGxlbWVudGVkIGEgY29tcHJlaGVuc2l2ZSBzb2x1dGlvbiBmb3JtYXREYXRlKGRhdGUsIHBhdHRlcm5TdHIpIHdoZXJlIHRoZSBjb2RlIGlzIGVhc3kgdG8gcmVhZCBhbmQgbW9kaWZ5LlxuICogICAgICBZb3UgY2FuIGRpc3BsYXkgZGF0ZSwgdGltZSwgQU0vUE0sIGV0Yy5cbiAqXG4gKiAgICAgIERhdGUgYW5kIFRpbWUgUGF0dGVybnNcbiAqICAgICAgeXkgPSAyLWRpZ2l0IHllYXI7IHl5eXkgPSBmdWxsIHllYXJcbiAqICAgICAgTSA9IGRpZ2l0IG1vbnRoOyBNTSA9IDItZGlnaXQgbW9udGg7IE1NTSA9IHNob3J0IG1vbnRoIG5hbWU7IE1NTU0gPSBmdWxsIG1vbnRoIG5hbWVcbiAqICAgICAgRUVFRSA9IGZ1bGwgd2Vla2RheSBuYW1lOyBFRUUgPSBzaG9ydCB3ZWVrZGF5IG5hbWVcbiAqICAgICAgZCA9IGRpZ2l0IGRheTsgZGQgPSAyLWRpZ2l0IGRheVxuICogICAgICBoID0gaG91cnMgYW0vcG07IGhoID0gMi1kaWdpdCBob3VycyBhbS9wbTsgSCA9IGhvdXJzOyBISCA9IDItZGlnaXQgaG91cnNcbiAqICAgICAgbSA9IG1pbnV0ZXM7IG1tID0gMi1kaWdpdCBtaW51dGVzOyBhYWEgPSBBTS9QTVxuICogICAgICBzID0gc2Vjb25kczsgc3MgPSAyLWRpZ2l0IHNlY29uZHNcbiAqICAgICAgUyA9IG1pbGlzZWNvbmRzXG4gKiA8L3ByZT5cbiAqXG4gKiBAcGFyYW0ge0RhdGV9IGRhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbcGF0dGVyblN0cl0gZGVmYXVsdHMgdG8gJ3l5eXkvTU0vZGQnXG4gKiBAcmV0dXJuIHtzdHJpbmd9IHRoZSBmb3JtYXR0ZWQgZGF0ZVxuICpcbiAqIEBmdW5jdGlvbiBmb3JtYXREYXRlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlV0aWxzLkRhdGVzXG4gKiBAY2F0ZWdvcnkgRm9ybWF0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JtYXREYXRlKGRhdGU6IERhdGUsIHBhdHRlcm5TdHI6IHN0cmluZyA9IFwieXl5eS9NTS9kZFwiKSB7XG4gIGNvbnN0IGRheTogbnVtYmVyID0gZGF0ZS5nZXREYXRlKCksXG4gICAgbW9udGg6IG51bWJlciA9IGRhdGUuZ2V0TW9udGgoKSxcbiAgICB5ZWFyOiBudW1iZXIgPSBkYXRlLmdldEZ1bGxZZWFyKCksXG4gICAgaG91cjogbnVtYmVyID0gZGF0ZS5nZXRIb3VycygpLFxuICAgIG1pbnV0ZTogbnVtYmVyID0gZGF0ZS5nZXRNaW51dGVzKCksXG4gICAgc2Vjb25kOiBudW1iZXIgPSBkYXRlLmdldFNlY29uZHMoKSxcbiAgICBtaWxpc2Vjb25kczogbnVtYmVyID0gZGF0ZS5nZXRNaWxsaXNlY29uZHMoKSxcbiAgICBoOiBudW1iZXIgPSBob3VyICUgMTIsXG4gICAgaGg6IHN0cmluZyA9IHR3b0RpZ2l0UGFkKGgpLFxuICAgIEhIOiBzdHJpbmcgPSB0d29EaWdpdFBhZChob3VyKSxcbiAgICBtbTogc3RyaW5nID0gdHdvRGlnaXRQYWQobWludXRlKSxcbiAgICBzczogc3RyaW5nID0gdHdvRGlnaXRQYWQoc2Vjb25kKSxcbiAgICBhYWE6IHN0cmluZyA9IGhvdXIgPCAxMiA/IFwiQU1cIiA6IFwiUE1cIixcbiAgICBFRUVFOiBzdHJpbmcgPSBEQVlTX09GX1dFRUtfTkFNRVNbZGF0ZS5nZXREYXkoKV0sXG4gICAgRUVFOiBzdHJpbmcgPSBFRUVFLnN1YnN0cigwLCAzKSxcbiAgICBkZDogc3RyaW5nID0gdHdvRGlnaXRQYWQoZGF5KSxcbiAgICBNOiBudW1iZXIgPSBtb250aCArIDEsXG4gICAgTU06IHN0cmluZyA9IHR3b0RpZ2l0UGFkKE0pLFxuICAgIE1NTU06IHN0cmluZyA9IE1PTlRIX05BTUVTW21vbnRoXSxcbiAgICBNTU06IHN0cmluZyA9IE1NTU0uc3Vic3RyKDAsIDMpLFxuICAgIHl5eXk6IHN0cmluZyA9IHllYXIgKyBcIlwiLFxuICAgIHl5OiBzdHJpbmcgPSB5eXl5LnN1YnN0cigyLCAyKTtcbiAgLy8gY2hlY2tzIHRvIHNlZSBpZiBtb250aCBuYW1lIHdpbGwgYmUgdXNlZFxuICBwYXR0ZXJuU3RyID0gcGF0dGVyblN0clxuICAgIC5yZXBsYWNlKFwiaGhcIiwgaGgpXG4gICAgLnJlcGxhY2UoXCJoXCIsIGgudG9TdHJpbmcoKSlcbiAgICAucmVwbGFjZShcIkhIXCIsIEhIKVxuICAgIC5yZXBsYWNlKFwiSFwiLCBob3VyLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJtbVwiLCBtbSlcbiAgICAucmVwbGFjZShcIm1cIiwgbWludXRlLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJzc1wiLCBzcylcbiAgICAucmVwbGFjZShcInNcIiwgc2Vjb25kLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJTXCIsIG1pbGlzZWNvbmRzLnRvU3RyaW5nKCkpXG4gICAgLnJlcGxhY2UoXCJkZFwiLCBkZClcbiAgICAucmVwbGFjZShcImRcIiwgZGF5LnRvU3RyaW5nKCkpXG5cbiAgICAucmVwbGFjZShcIkVFRUVcIiwgRUVFRSlcbiAgICAucmVwbGFjZShcIkVFRVwiLCBFRUUpXG4gICAgLnJlcGxhY2UoXCJ5eXl5XCIsIHl5eXkpXG4gICAgLnJlcGxhY2UoXCJ5eVwiLCB5eSlcbiAgICAucmVwbGFjZShcImFhYVwiLCBhYWEpO1xuICBpZiAocGF0dGVyblN0ci5pbmRleE9mKFwiTU1NXCIpID4gLTEpIHtcbiAgICBwYXR0ZXJuU3RyID0gcGF0dGVyblN0ci5yZXBsYWNlKFwiTU1NTVwiLCBNTU1NKS5yZXBsYWNlKFwiTU1NXCIsIE1NTSk7XG4gIH0gZWxzZSB7XG4gICAgcGF0dGVyblN0ciA9IHBhdHRlcm5TdHIucmVwbGFjZShcIk1NXCIsIE1NKS5yZXBsYWNlKFwiTVwiLCBNLnRvU3RyaW5nKCkpO1xuICB9XG4gIHJldHVybiBwYXR0ZXJuU3RyO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFBhcnNlcyBhIGRhdGUgZnJvbSBhIHNwZWNpZmllZCBmb3JtYXRcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXRcbiAqIEBwYXJhbSB7c3RyaW5nIHwgRGF0ZSB8IG51bWJlcn0gW3ZdXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlV0aWxzLkRhdGVzXG4gKiBAY2F0ZWdvcnkgRm9ybWF0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZURhdGUoZm9ybWF0OiBzdHJpbmcsIHY/OiBzdHJpbmcgfCBEYXRlIHwgbnVtYmVyKSB7XG4gIGxldCB2YWx1ZTogRGF0ZSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBpZiAoIXYpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgaWYgKHYgaW5zdGFuY2VvZiBEYXRlKVxuICAgIHRyeSB7XG4gICAgICB2YWx1ZSA9IGRhdGVGcm9tRm9ybWF0KGZvcm1hdERhdGUodiBhcyBEYXRlLCBmb3JtYXQpLCBmb3JtYXQpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBzZihcIkNvdWxkIG5vdCBjb252ZXJ0IGRhdGUgezB9IHRvIGZvcm1hdDogezF9XCIsIHYudG9TdHJpbmcoKSwgZm9ybWF0KVxuICAgICAgKTtcbiAgICB9XG4gIGVsc2UgaWYgKHR5cGVvZiB2ID09PSBcInN0cmluZ1wiKSB7XG4gICAgdmFsdWUgPSBkYXRlRnJvbUZvcm1hdCh2LCBmb3JtYXQpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB2ID09PSBcIm51bWJlclwiKSB7XG4gICAgY29uc3QgZCA9IG5ldyBEYXRlKHYpO1xuICAgIHZhbHVlID0gZGF0ZUZyb21Gb3JtYXQoZm9ybWF0RGF0ZShkLCBmb3JtYXQpLCBmb3JtYXQpO1xuICB9IGVsc2UgaWYgKGlzVmFsaWREYXRlKHYpKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGQgPSBuZXcgRGF0ZSh2KTtcbiAgICAgIHZhbHVlID0gZGF0ZUZyb21Gb3JtYXQoZm9ybWF0RGF0ZShkLCBmb3JtYXQpLCBmb3JtYXQpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgc2YoXCJDb3VsZCBub3QgY29udmVydCBkYXRlIHswfSB0byBmb3JtYXQ6IHsxfVwiLCB2LCBmb3JtYXQpXG4gICAgICApO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdmFsdWUgcHJvdmlkZWQgJHt2fWApO1xuICB9XG4gIHJldHVybiBiaW5kRGF0ZVRvU3RyaW5nKHZhbHVlLCBmb3JtYXQpO1xufVxuIiwiaW1wb3J0IHsgYXBwbHksIG1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBNb2RlbEtleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIHByb3Aoa2V5OiBzdHJpbmcgPSBNb2RlbEtleXMuQVRUUklCVVRFKSB7XG4gIHJldHVybiAobW9kZWw6IG9iamVjdCwgcHJvcGVydHlLZXk/OiBhbnkpOiB2b2lkID0+IHtcbiAgICBsZXQgcHJvcHM6IHN0cmluZ1tdO1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kZWwsIGtleSkpIHtcbiAgICAgIHByb3BzID0gKG1vZGVsIGFzIGFueSlba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvcHMgPSAobW9kZWwgYXMgYW55KVtrZXldID0gW107XG4gICAgfVxuICAgIGlmICghcHJvcHMuaW5jbHVkZXMocHJvcGVydHlLZXkgYXMgc3RyaW5nKSlcbiAgICAgIHByb3BzLnB1c2gocHJvcGVydHlLZXkgYXMgc3RyaW5nKTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByb3BNZXRhZGF0YTxWPihrZXk6IHN0cmluZywgdmFsdWU6IFYpIHtcbiAgcmV0dXJuIGFwcGx5KHByb3AoKSwgbWV0YWRhdGE8Vj4oa2V5LCB2YWx1ZSkpO1xufVxuIiwiLyoqXG4gKiBAc3VtbWFyeSBNaW1pY3MgSmF2YSdzIFN0cmluZydzIEhhc2ggaW1wbGVtZW50YXRpb25cbiAqXG4gKiBAcGFyYW0ge3N0cmluZyB8IG51bWJlciB8IHN5bWJvbCB8IERhdGV9IG9ialxuICogQHJldHVybiB7bnVtYmVyfSBoYXNoIHZhbHVlIG9mIG9ialxuICpcbiAqIEBmdW5jdGlvbiBoYXNoQ29kZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5VdGlscy5IYXNoaW5nXG4gKiBAY2F0ZWdvcnkgSGFzaGluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzaENvZGUob2JqOiBzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2wgfCBEYXRlKTogc3RyaW5nIHtcbiAgb2JqID0gU3RyaW5nKG9iaik7XG4gIGxldCBoYXNoID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjaGFyYWN0ZXIgPSBvYmouY2hhckNvZGVBdChpKTtcbiAgICBoYXNoID0gKGhhc2ggPDwgNSkgLSBoYXNoICsgY2hhcmFjdGVyO1xuICAgIGhhc2ggPSBoYXNoICYgaGFzaDsgLy8gQ29udmVydCB0byAzMmJpdCBpbnRlZ2VyXG4gIH1cbiAgcmV0dXJuIGhhc2gudG9TdHJpbmcoKTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIHRlaCB0eXBlIGZvciBhIEhhc2hpbmcgZnVuY3Rpb25cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uVXRpbHMuSGFzaGluZ1xuICogQGNhdGVnb3J5IEhhc2hpbmdcbiAqL1xuZXhwb3J0IHR5cGUgSGFzaGluZ0Z1bmN0aW9uID0gKHZhbHVlOiBhbnksIC4uLmFyZ3M6IGFueVtdKSA9PiBzdHJpbmc7XG5cbi8qKlxuICogQHN1bW1hcnkgSGFzaGVzIGFuIG9iamVjdCBieSBjb21iaW5pbmcgdGhlIGhhc2ggb2YgYWxsIGl0cyBwcm9wZXJ0aWVzXG4gKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmpcbiAqIEByZXR1cm4ge3N0cmluZ30gdGhlIHJlc3VsdGluZyBoYXNoXG4gKlxuICogQGZ1bmN0aW9uIGhhc2hPYmpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uVXRpbHMuSGFzaGluZ1xuICogQGNhdGVnb3J5IEhhc2hpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hPYmoob2JqOiBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgYW55W10pOiBzdHJpbmcge1xuICBjb25zdCBoYXNoUmVkdWNlciA9IGZ1bmN0aW9uIChoOiBudW1iZXIgfCBzdHJpbmcsIGVsOiBhbnkpOiBzdHJpbmcgfCBudW1iZXIge1xuICAgIGNvbnN0IGVsSGFzaCA9IGhhc2hGdW5jdGlvbihlbCk7XG5cbiAgICBpZiAodHlwZW9mIGVsSGFzaCA9PT0gXCJzdHJpbmdcIilcbiAgICAgIHJldHVybiBoYXNoRnVuY3Rpb24oKChoIGFzIHN0cmluZykgfHwgXCJcIikgKyBoYXNoRnVuY3Rpb24oZWwpKTtcblxuICAgIGggPSBoIHx8IDA7XG4gICAgaCA9ICgoaCBhcyBudW1iZXIpIDw8IDUpIC0gKGggYXMgbnVtYmVyKSArIGVsSGFzaDtcbiAgICByZXR1cm4gaCAmIGg7XG4gIH07XG5cbiAgY29uc3QgZnVuYzogSGFzaGluZ0Z1bmN0aW9uID0gaGFzaENvZGU7XG5cbiAgY29uc3QgaGFzaEZ1bmN0aW9uID0gZnVuY3Rpb24gKHZhbHVlOiBhbnkpOiBzdHJpbmcgfCBudW1iZXIge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHJldHVybiBcIlwiO1xuICAgIGlmIChbXCJzdHJpbmdcIiwgXCJudW1iZXJcIiwgXCJzeW1ib2xcIl0uaW5kZXhPZih0eXBlb2YgdmFsdWUpICE9PSAtMSlcbiAgICAgIHJldHVybiBmdW5jKHZhbHVlLnRvU3RyaW5nKCkpO1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHJldHVybiBmdW5jKHZhbHVlLmdldFRpbWUoKSk7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSByZXR1cm4gdmFsdWUucmVkdWNlKGhhc2hSZWR1Y2VyLCB1bmRlZmluZWQpO1xuICAgIHJldHVybiAoT2JqZWN0LnZhbHVlcyh2YWx1ZSkgYXMgKHN0cmluZyB8IG51bWJlcilbXSkucmVkdWNlKFxuICAgICAgaGFzaFJlZHVjZXIsXG4gICAgICB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBzdHJpbmcgfCBudW1iZXJcbiAgICApO1xuICB9O1xuXG4gIGNvbnN0IHJlc3VsdCA9IE9iamVjdC52YWx1ZXMob2JqKS5yZWR1Y2UoaGFzaFJlZHVjZXIsIDApO1xuXG4gIHJldHVybiAodHlwZW9mIHJlc3VsdCA9PT0gXCJudW1iZXJcIiA/IE1hdGguYWJzKHJlc3VsdCkgOiByZXN1bHQpLnRvU3RyaW5nKCk7XG59XG5cbmV4cG9ydCBjb25zdCBEZWZhdWx0SGFzaGluZ01ldGhvZCA9IFwiZGVmYXVsdFwiO1xuXG5leHBvcnQgY2xhc3MgSGFzaGluZyB7XG4gIHByaXZhdGUgc3RhdGljIGN1cnJlbnQ6IHN0cmluZyA9IERlZmF1bHRIYXNoaW5nTWV0aG9kO1xuXG4gIHByaXZhdGUgc3RhdGljIGNhY2hlOiBSZWNvcmQ8c3RyaW5nLCBIYXNoaW5nRnVuY3Rpb24+ID0ge1xuICAgIGRlZmF1bHQ6IGhhc2hPYmosXG4gIH07XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoa2V5IGluIHRoaXMuY2FjaGUpIHJldHVybiB0aGlzLmNhY2hlW2tleV07XG4gICAgdGhyb3cgbmV3IEVycm9yKGBObyBoYXNoaW5nIG1ldGhvZCByZWdpc3RlcmVkIHVuZGVyICR7a2V5fWApO1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZ1bmM6IEhhc2hpbmdGdW5jdGlvbixcbiAgICBzZXREZWZhdWx0ID0gZmFsc2VcbiAgKTogdm9pZCB7XG4gICAgaWYgKGtleSBpbiB0aGlzLmNhY2hlKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBIYXNoaW5nIG1ldGhvZCAke2tleX0gYWxyZWFkeSByZWdpc3RlcmVkYCk7XG4gICAgdGhpcy5jYWNoZVtrZXldID0gZnVuYztcbiAgICBpZiAoc2V0RGVmYXVsdCkgdGhpcy5jdXJyZW50ID0ga2V5O1xuICB9XG5cbiAgc3RhdGljIGhhc2gob2JqOiBhbnksIG1ldGhvZD86IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgICBpZiAoIW1ldGhvZCkgcmV0dXJuIHRoaXMuZ2V0KHRoaXMuY3VycmVudCkob2JqLCAuLi5hcmdzKTtcbiAgICByZXR1cm4gdGhpcy5nZXQobWV0aG9kKShvYmosIC4uLmFyZ3MpO1xuICB9XG5cbiAgc3RhdGljIHNldERlZmF1bHQobWV0aG9kOiBzdHJpbmcpIHtcbiAgICB0aGlzLmN1cnJlbnQgPSB0aGlzLmdldChtZXRob2QpO1xuICB9XG59XG4iLCJpbXBvcnQgeyBNb2RlbEVycm9ycyB9IGZyb20gXCIuLi92YWxpZGF0aW9uL3R5cGVzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgSGVscGVyIENsYXNzIHRvIGhvbGQgdGhlIGVycm9yIHJlc3VsdHNcbiAqIEBkZXNjcmlwdGlvbiBob2xkcyBlcnJvciByZXN1bHRzIGluIGFuICdpbmRleGFibGUnIG1hbm5lclxuICogd2hpbGUgc3RpbGwgcHJvdmlkaW5nIHRoZSBzYW1lIHJlc3VsdCBvbiB0b1N0cmluZ1xuICpcbiAqIEBwYXJhbSB7TW9kZWxFcnJvcnN9IGVycm9yc1xuICpcbiAqIEBjbGFzcyBNb2RlbEVycm9yRGVmaW5pdGlvblxuICpcbiAqIEBjYXRlZ29yeSBNb2RlbFxuICovXG5leHBvcnQgY2xhc3MgTW9kZWxFcnJvckRlZmluaXRpb24ge1xuICBbaW5kZXhlcjogc3RyaW5nXTpcbiAgICB8IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD5cbiAgICB8ICgoKSA9PiBzdHJpbmcgfCB1bmRlZmluZWQpO1xuXG4gIGNvbnN0cnVjdG9yKGVycm9yczogTW9kZWxFcnJvcnMpIHtcbiAgICBmb3IgKGNvbnN0IHByb3AgaW4gZXJyb3JzKSB7XG4gICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGVycm9ycywgcHJvcCkgJiYgZXJyb3JzW3Byb3BdKVxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcyBhcyBhbnksIHByb3AsIHtcbiAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgICAgdmFsdWU6IGVycm9yc1twcm9wXSxcbiAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBPdXRwdXRzIHRoZSBjbGFzcyB0byBhIG5pY2UgcmVhZGFibGUgc3RyaW5nXG4gICAqXG4gICAqIEBvdmVycmlkZVxuICAgKi9cbiAgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICBjb25zdCBzZWxmOiBhbnkgPSB0aGlzIGFzIGFueTtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMoc2VsZilcbiAgICAgIC5maWx0ZXIoXG4gICAgICAgIChrKSA9PlxuICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzZWxmLCBrKSAmJlxuICAgICAgICAgIHR5cGVvZiBzZWxmW2tdICE9PSBcImZ1bmN0aW9uXCJcbiAgICAgIClcbiAgICAgIC5yZWR1Y2UoKGFjY3VtOiBzdHJpbmcsIHByb3ApID0+IHtcbiAgICAgICAgbGV0IHByb3BFcnJvcjogc3RyaW5nIHwgdW5kZWZpbmVkID0gT2JqZWN0LmtleXMoc2VsZltwcm9wXSkucmVkdWNlKFxuICAgICAgICAgIChwcm9wQWNjdW06IHVuZGVmaW5lZCB8IHN0cmluZywga2V5KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXByb3BBY2N1bSkgcHJvcEFjY3VtID0gc2VsZltwcm9wXVtrZXldO1xuICAgICAgICAgICAgZWxzZSBwcm9wQWNjdW0gKz0gYFxcbiR7c2VsZltwcm9wXVtrZXldfWA7XG4gICAgICAgICAgICByZXR1cm4gcHJvcEFjY3VtO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgdW5kZWZpbmVkXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHByb3BFcnJvcikge1xuICAgICAgICAgIHByb3BFcnJvciA9IGAke3Byb3B9IC0gJHtwcm9wRXJyb3J9YDtcbiAgICAgICAgICBpZiAoIWFjY3VtKSBhY2N1bSA9IHByb3BFcnJvcjtcbiAgICAgICAgICBlbHNlIGFjY3VtICs9IGBcXG4ke3Byb3BFcnJvcn1gO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFjY3VtO1xuICAgICAgfSwgXCJcIik7XG4gIH1cbn1cbiIsIi8qKlxuICogQHN1bW1hcnkgUmVmZXJlbmNlcyB0aGUgcmVsZXZhbnQgSlMgcHJpbWl0aXZlc1xuICpcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBTVFJJTkcgcmVmZXJlbmNlcyB0aGUgc3RyaW5nIHByaW1pdGl2ZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IE5VTUJFUiByZWZlcmVuY2VzIHRoZSBudW1iZXIgcHJpbWl0aXZlXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQk9PTEVBTiByZWZlcmVuY2VzIHRoZSBib29sZWFuIHByaW1pdGl2ZVxuICogQHByb3BlcnR5IHtzdHJpbmd9IEJJR0lOVCByZWZlcmVuY2VzIHRoZSBiaWdpbnQgcHJpbWl0aXZlXG4gKlxuICogQGNvbnN0YW50IFByaW1pdGl2ZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uTW9kZWxcbiAqL1xuZXhwb3J0IGVudW0gUHJpbWl0aXZlcyB7XG4gIFNUUklORyA9IFwic3RyaW5nXCIsXG4gIE5VTUJFUiA9IFwibnVtYmVyXCIsXG4gIEJPT0xFQU4gPSBcImJvb2xlYW5cIixcbiAgQklHSU5UID0gXCJiaWdpbnRcIixcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZWZlcmVuY2VzIHRoZSBSZXNlcnZlZCBtb2RlbCBuYW1lcyB0byBpZ25vcmUgZHVyaW5nIE1vZGVsIHJlYnVpbGRpbmdcbiAqXG4gKiBAcHJvcGVydHkge3N0cmluZ30gU1RSSU5HXG4gKiBAcHJvcGVydHkge3N0cmluZ30gT0JKRUNUXG4gKiBAcHJvcGVydHkge3N0cmluZ30gTlVNQkVSXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQk9PTEVBTlxuICogQHByb3BlcnR5IHtzdHJpbmd9IEJJR0lOVFxuICogQHByb3BlcnR5IHtzdHJpbmd9IERBVEVcbiAqXG4gKiBAY29uc3RhbnQgUmVzZXJ2ZWRNb2RlbHNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uTW9kZWxcbiAqL1xuZXhwb3J0IGVudW0gUmVzZXJ2ZWRNb2RlbHMge1xuICBTVFJJTkcgPSBcInN0cmluZ1wiLFxuICBPQkpFQ1QgPSBcIm9iamVjdFwiLFxuICBOVU1CRVIgPSBcIm51bWJlclwiLFxuICBCT09MRUFOID0gXCJib29sZWFuXCIsXG4gIEJJR0lOVCA9IFwiYmlnaW50XCIsXG4gIERBVEUgPSBcImRhdGVcIixcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBSZWZlcmVuY2VzIHRoZSBiYXNpYyBzdXBwb3J0ZWQganMgdHlwZXNcbiAqXG4gKiBAcHJvcGVydHkge3N0cmluZ30gc3RyaW5nXG4gKiBAcHJvcGVydHkge3N0cmluZ30gYXJyYXlcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBudW1iZXJcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBib29sZWFuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gc3ltYm9sXG4gKiBAcHJvcGVydHkge3N0cmluZ30gZnVuY3Rpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBvYmplY3RcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB1bmRlZmluZWRcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBudWxsXG4gKiBAcHJvcGVydHkge3N0cmluZ30gQklHSU5UXG4gKlxuICogQGNvbnN0YW50IGpzVHlwZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uTW9kZWxcbiAqL1xuZXhwb3J0IGNvbnN0IGpzVHlwZXMgPSBbXG4gIFwic3RyaW5nXCIsXG4gIFwiYXJyYXlcIixcbiAgXCJudW1iZXJcIixcbiAgXCJib29sZWFuXCIsXG4gIFwic3ltYm9sXCIsXG4gIFwiZnVuY3Rpb25cIixcbiAgXCJvYmplY3RcIixcbiAgXCJ1bmRlZmluZWRcIixcbiAgXCJudWxsXCIsXG4gIFwiYmlnaW50XCIsXG5dO1xuIiwiaW1wb3J0IHsgVmFsaWRhdG9yRGVmaW5pdGlvbiB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgSVZhbGlkYXRvclJlZ2lzdHJ5IH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgdHlwZSB7IFZhbGlkYXRvciB9IGZyb20gXCIuL1ZhbGlkYXRvclwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IER1Y2sgdHlwaW5nIGZvciBWYWxpZGF0b3JzXG4gKiBAZnVuY3Rpb24gaXNWYWxpZGF0b3JcbiAqIEBwYXJhbSB2YWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRhdG9yKHZhbDogYW55KSB7XG4gIHJldHVybiB2YWwuY29uc3RydWN0b3IgJiYgdmFsW1wiaGFzRXJyb3JzXCJdO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IEJhc2UgSW1wbGVtZW50YXRpb24gb2YgYSBWYWxpZGF0b3IgUmVnaXN0cnlcbiAqXG4gKiBAcHJvcCB7VmFsaWRhdG9yW119IFt2YWxpZGF0b3JzXSB0aGUgaW5pdGlhbCB2YWxpZGF0b3JzIHRvIHJlZ2lzdGVyXG4gKlxuICogQGNsYXNzIFZhbGlkYXRvclJlZ2lzdHJ5XG4gKiBAaW1wbGVtZW50cyBJVmFsaWRhdG9yUmVnaXN0cnk8VD5cbiAqXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdGlvblxuICovXG5leHBvcnQgY2xhc3MgVmFsaWRhdG9yUmVnaXN0cnk8VCBleHRlbmRzIFZhbGlkYXRvcj5cbiAgaW1wbGVtZW50cyBJVmFsaWRhdG9yUmVnaXN0cnk8VD5cbntcbiAgcHJpdmF0ZSBjYWNoZTogYW55ID0ge307XG4gIHByaXZhdGUgY3VzdG9tS2V5Q2FjaGU6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG5cbiAgY29uc3RydWN0b3IoLi4udmFsaWRhdG9yczogKFZhbGlkYXRvckRlZmluaXRpb24gfCBWYWxpZGF0b3IpW10pIHtcbiAgICB0aGlzLmN1c3RvbUtleUNhY2hlID0ge307XG4gICAgdGhpcy5yZWdpc3RlciguLi52YWxpZGF0b3JzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSByZXRyaWV2ZXMgdGhlIGN1c3RvbSBrZXlzXG4gICAqL1xuICBnZXRDdXN0b21LZXlzKCk6IHsgW2luZGV4ZXI6IHN0cmluZ106IHN0cmluZyB9IHtcbiAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5jdXN0b21LZXlDYWNoZSk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgcmV0cmlldmVzIHRoZSByZWdpc3RlcmVkIHZhbGlkYXRvcnMga2V5c1xuICAgKi9cbiAgZ2V0S2V5cygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuY2FjaGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJldHJpZXZlcyBhIHZhbGlkYXRvclxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsaWRhdG9yS2V5IG9uZSBvZiB0aGUge0BsaW5rIFZhbGlkYXRpb25LZXlzfVxuICAgKiBAcmV0dXJuIHtWYWxpZGF0b3IgfCB1bmRlZmluZWR9IHRoZSByZWdpc3RlcmVkIFZhbGlkYXRvciBvciB1bmRlZmluZWQgaWYgdGhlcmUgaXMgbm9ubyBtYXRjaGluZyB0aGUgcHJvdmlkZWQga2V5XG4gICAqL1xuICBnZXQ8VCBleHRlbmRzIFZhbGlkYXRvcj4odmFsaWRhdG9yS2V5OiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoISh2YWxpZGF0b3JLZXkgaW4gdGhpcy5jYWNoZSkpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBjbGFzc09ySW5zdGFuY2UgPSB0aGlzLmNhY2hlW3ZhbGlkYXRvcktleV07XG4gICAgaWYgKGlzVmFsaWRhdG9yKGNsYXNzT3JJbnN0YW5jZSkpIHJldHVybiBjbGFzc09ySW5zdGFuY2UgYXMgVDtcbiAgICBjb25zdCBjb25zdHJ1Y3RvciA9IGNsYXNzT3JJbnN0YW5jZS5kZWZhdWx0IHx8IGNsYXNzT3JJbnN0YW5jZTtcbiAgICBjb25zdCBpbnN0YW5jZSA9IG5ldyBjb25zdHJ1Y3RvcigpO1xuICAgIHRoaXMuY2FjaGVbdmFsaWRhdG9yS2V5XSA9IGluc3RhbmNlO1xuICAgIHJldHVybiBpbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZWdpc3RlcnMgdGhlIHByb3ZpZGVkIHZhbGlkYXRvcnMgb250byB0aGUgcmVnaXN0cnlcbiAgICpcbiAgICogQHBhcmFtIHtUW10gfCBWYWxpZGF0b3JEZWZpbml0aW9uW119IHZhbGlkYXRvclxuICAgKi9cbiAgcmVnaXN0ZXI8VCBleHRlbmRzIFZhbGlkYXRvcj4oXG4gICAgLi4udmFsaWRhdG9yOiAoVmFsaWRhdG9yRGVmaW5pdGlvbiB8IFQpW11cbiAgKTogdm9pZCB7XG4gICAgdmFsaWRhdG9yLmZvckVhY2goKHYpID0+IHtcbiAgICAgIGlmIChpc1ZhbGlkYXRvcih2KSkge1xuICAgICAgICAvLyBjb25zdCBrID1cblxuICAgICAgICBpZiAoKHYgYXMgVmFsaWRhdG9yRGVmaW5pdGlvbikudmFsaWRhdGlvbktleSBpbiB0aGlzLmNhY2hlKSByZXR1cm47XG4gICAgICAgIHRoaXMuY2FjaGVbKHYgYXMgVmFsaWRhdG9yRGVmaW5pdGlvbikudmFsaWRhdGlvbktleV0gPSB2O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgeyB2YWxpZGF0aW9uS2V5LCB2YWxpZGF0b3IsIHNhdmUgfSA9IHYgYXMgVmFsaWRhdG9yRGVmaW5pdGlvbjtcbiAgICAgICAgaWYgKHZhbGlkYXRpb25LZXkgaW4gdGhpcy5jYWNoZSkgcmV0dXJuO1xuICAgICAgICB0aGlzLmNhY2hlW3ZhbGlkYXRpb25LZXldID0gdmFsaWRhdG9yO1xuICAgICAgICBpZiAoIXNhdmUpIHJldHVybjtcbiAgICAgICAgY29uc3Qgb2JqOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgICAgIG9ialt2YWxpZGF0aW9uS2V5LnRvVXBwZXJDYXNlKCldID0gdmFsaWRhdGlvbktleTtcblxuICAgICAgICB0aGlzLmN1c3RvbUtleUNhY2hlID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5jdXN0b21LZXlDYWNoZSwgb2JqKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSBcIi4vVmFsaWRhdG9ycy9WYWxpZGF0b3JcIjtcbmltcG9ydCB7IElWYWxpZGF0b3JSZWdpc3RyeSwgVmFsaWRhdG9yRGVmaW5pdGlvbiB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBWYWxpZGF0b3JSZWdpc3RyeSB9IGZyb20gXCIuL1ZhbGlkYXRvcnMvVmFsaWRhdG9yUmVnaXN0cnlcIjtcbmltcG9ydCB7IFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4vVmFsaWRhdG9ycy9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBTdGF0aWMgY2xhc3MgYWN0aW5nIGFzIGEgbmFtZXNwYWNlIGZvciB0aGUgVmFsaWRhdGlvblxuICpcbiAqIEBjbGFzcyBWYWxpZGF0aW9uXG4gKiBAc3RhdGljXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRpb25cbiAqL1xuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb24ge1xuICBwcml2YXRlIHN0YXRpYyBhY3RpbmdWYWxpZGF0b3JSZWdpc3RyeT86IElWYWxpZGF0b3JSZWdpc3RyeTxWYWxpZGF0b3I+ID1cbiAgICB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIGFjdGluZyBWYWxpZGF0b3JSZWdpc3RyeVxuICAgKlxuICAgKiBAcGFyYW0ge0lWYWxpZGF0b3JSZWdpc3RyeX0gdmFsaWRhdG9yUmVnaXN0cnkgdGhlIG5ldyBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgdmFsaWRhdG9yIFJlZ2lzdHJ5XG4gICAqIEBwYXJhbSB7ZnVuY3Rpb24oVmFsaWRhdG9yKTogVmFsaWRhdG9yfSBbbWlncmF0aW9uSGFuZGxlcl0gdGhlIG1ldGhvZCB0byBtYXAgdGhlIHZhbGlkYXRvciBpZiByZXF1aXJlZDtcbiAgICovXG4gIHN0YXRpYyBzZXRSZWdpc3RyeShcbiAgICB2YWxpZGF0b3JSZWdpc3RyeTogSVZhbGlkYXRvclJlZ2lzdHJ5PFZhbGlkYXRvcj4sXG4gICAgbWlncmF0aW9uSGFuZGxlcj86ICh2YWxpZGF0b3I6IFZhbGlkYXRvcikgPT4gVmFsaWRhdG9yXG4gICkge1xuICAgIGlmIChtaWdyYXRpb25IYW5kbGVyICYmIFZhbGlkYXRpb24uYWN0aW5nVmFsaWRhdG9yUmVnaXN0cnkpXG4gICAgICBWYWxpZGF0aW9uLmFjdGluZ1ZhbGlkYXRvclJlZ2lzdHJ5LmdldEtleXMoKS5mb3JFYWNoKChrOiBzdHJpbmcpID0+IHtcbiAgICAgICAgY29uc3QgdmFsaWRhdG9yID0gdmFsaWRhdG9yUmVnaXN0cnkuZ2V0KGspO1xuICAgICAgICBpZiAodmFsaWRhdG9yKSB2YWxpZGF0b3JSZWdpc3RyeS5yZWdpc3RlcihtaWdyYXRpb25IYW5kbGVyKHZhbGlkYXRvcikpO1xuICAgICAgfSk7XG4gICAgVmFsaWRhdGlvbi5hY3RpbmdWYWxpZGF0b3JSZWdpc3RyeSA9IHZhbGlkYXRvclJlZ2lzdHJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIGN1cnJlbnQgVmFsaWRhdG9yUmVnaXN0cnlcbiAgICpcbiAgICogQHJldHVybiBJVmFsaWRhdG9yUmVnaXN0cnksIGRlZmF1bHRzIHRvIHtAbGluayBWYWxpZGF0b3JSZWdpc3RyeX1cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldFJlZ2lzdHJ5KCkge1xuICAgIGlmICghVmFsaWRhdGlvbi5hY3RpbmdWYWxpZGF0b3JSZWdpc3RyeSlcbiAgICAgIFZhbGlkYXRpb24uYWN0aW5nVmFsaWRhdG9yUmVnaXN0cnkgPSBuZXcgVmFsaWRhdG9yUmVnaXN0cnkoKTtcbiAgICByZXR1cm4gVmFsaWRhdGlvbi5hY3RpbmdWYWxpZGF0b3JSZWdpc3RyeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgYSB2YWxpZGF0b3JcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbGlkYXRvcktleSBvbmUgb2YgdGhlIHtAbGluayBWYWxpZGF0aW9uS2V5c31cbiAgICogQHJldHVybiB7VmFsaWRhdG9yIHwgdW5kZWZpbmVkfSB0aGUgcmVnaXN0ZXJlZCBWYWxpZGF0b3Igb3IgdW5kZWZpbmVkIGlmIHRoZXJlIGlzIG5vbm8gbWF0Y2hpbmcgdGhlIHByb3ZpZGVkIGtleVxuICAgKi9cbiAgc3RhdGljIGdldDxUIGV4dGVuZHMgVmFsaWRhdG9yPih2YWxpZGF0b3JLZXk6IHN0cmluZyk6IFQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBWYWxpZGF0aW9uLmdldFJlZ2lzdHJ5KCkuZ2V0KHZhbGlkYXRvcktleSk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgUmVnaXN0ZXJzIHRoZSBwcm92aWRlZCB2YWxpZGF0b3JzIG9udG8gdGhlIHJlZ2lzdHJ5XG4gICAqXG4gICAqIEBwYXJhbSB7VFtdIHwgVmFsaWRhdG9yRGVmaW5pdGlvbltdfSB2YWxpZGF0b3JcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlcjxUIGV4dGVuZHMgVmFsaWRhdG9yPihcbiAgICAuLi52YWxpZGF0b3I6IChWYWxpZGF0b3JEZWZpbml0aW9uIHwgVClbXVxuICApOiB2b2lkIHtcbiAgICByZXR1cm4gVmFsaWRhdGlvbi5nZXRSZWdpc3RyeSgpLnJlZ2lzdGVyKC4uLnZhbGlkYXRvcik7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgQnVpbGRzIHRoZSBrZXkgdG8gc3RvcmUgYXMgTWV0YWRhdGEgdW5kZXIgUmVmbGVjdGlvbnNcbiAgICogQGRlc2NyaXB0aW9uIGNvbmNhdGVuYXRlcyB7QGxpbmsgVmFsaWRhdGlvbktleXMjUkVGTEVDVH0gd2l0aCB0aGUgcHJvdmlkZWQga2V5XG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBrZXlcbiAgICovXG4gIHN0YXRpYyBrZXkoa2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gVmFsaWRhdGlvbktleXMuUkVGTEVDVCArIGtleTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIGFsbCByZWdpc3RlcmVkIHZhbGlkYXRpb24ga2V5c1xuICAgKi9cbiAgc3RhdGljIGtleXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0UmVnaXN0cnkoKS5nZXRLZXlzKCk7XG4gIH1cbn1cbiIsImltcG9ydCB7IE1vZGVsRXJyb3JEZWZpbml0aW9uIH0gZnJvbSBcIi4vTW9kZWxFcnJvckRlZmluaXRpb25cIjtcbmltcG9ydCB7IERlY29yYXRvck1ldGFkYXRhLCBSZWZsZWN0aW9uIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5pbXBvcnQgeyBNb2RlbEtleXMgfSBmcm9tIFwiLi4vdXRpbHMvY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBzZiB9IGZyb20gXCIuLi91dGlscy9zdHJpbmdzXCI7XG5pbXBvcnQgeyBSZXNlcnZlZE1vZGVscyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgVmFsaWRhdGFibGUgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgaXNNb2RlbCwgTW9kZWwgfSBmcm9tIFwiLi9Nb2RlbFwiO1xuaW1wb3J0IHsgVmFsaWRhdGlvbiB9IGZyb20gXCIuLi92YWxpZGF0aW9uL1ZhbGlkYXRpb25cIjtcbmltcG9ydCB7IFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4uL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9jb25zdGFudHNcIjtcbmltcG9ydCB7XG4gIE1vZGVsRXJyb3JzLFxuICBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uLFxufSBmcm9tIFwiLi4vdmFsaWRhdGlvbi90eXBlc1wiO1xuaW1wb3J0IHsgVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi92YWxpZGF0aW9uL3R5cGVzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgQW5hbHlzZXMgdGhlIGRlY29yYXRpb25zIG9mIHRoZSBwcm9wZXJ0aWVzIGFuZCB2YWxpZGF0ZXMgdGhlIG9iaiBhY2NvcmRpbmcgdG8gdGhlbVxuICpcbiAqIEB0eXBlZGVmIFQgZXh0ZW5kcyBNb2RlbFxuICogQHByb3Age1R9IG9iaiBNb2RlbCBvYmplY3QgdG8gdmFsaWRhdGVcbiAqIEBwcm9wIHtzdHJpbmdbXX0gW3Byb3BzVG9JZ25vcmVdIG9iamVjdCBwcm9wZXJ0aWVzIHRvIGlnbm9yZSBpbiB0aGUgdmFsaWRhdGlvblxuICpcbiAqIEBmdW5jdGlvbiB2YWxpZGF0ZVxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdGlvblxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGU8VCBleHRlbmRzIE1vZGVsPihcbiAgb2JqOiBULFxuICAuLi5wcm9wc1RvSWdub3JlOiBzdHJpbmdbXVxuKTogTW9kZWxFcnJvckRlZmluaXRpb24gfCB1bmRlZmluZWQge1xuICBjb25zdCBkZWNvcmF0ZWRQcm9wZXJ0aWVzOiBWYWxpZGF0aW9uUHJvcGVydHlEZWNvcmF0b3JEZWZpbml0aW9uW10gPSBbXTtcbiAgZm9yIChjb25zdCBwcm9wIGluIG9iailcbiAgICBpZiAoXG4gICAgICBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSAmJlxuICAgICAgcHJvcHNUb0lnbm9yZS5pbmRleE9mKHByb3ApID09PSAtMVxuICAgIClcbiAgICAgIGRlY29yYXRlZFByb3BlcnRpZXMucHVzaChcbiAgICAgICAgUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICAgICAgVmFsaWRhdGlvbktleXMuUkVGTEVDVCxcbiAgICAgICAgICBvYmosXG4gICAgICAgICAgcHJvcFxuICAgICAgICApIGFzIFZhbGlkYXRpb25Qcm9wZXJ0eURlY29yYXRvckRlZmluaXRpb25cbiAgICAgICk7XG5cbiAgbGV0IHJlc3VsdDogTW9kZWxFcnJvcnMgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG5cbiAgZm9yIChjb25zdCBkZWNvcmF0ZWRQcm9wZXJ0eSBvZiBkZWNvcmF0ZWRQcm9wZXJ0aWVzKSB7XG4gICAgY29uc3QgeyBwcm9wLCBkZWNvcmF0b3JzIH0gPSBkZWNvcmF0ZWRQcm9wZXJ0eTtcblxuICAgIGlmICghZGVjb3JhdG9ycyB8fCAhZGVjb3JhdG9ycy5sZW5ndGgpIGNvbnRpbnVlO1xuXG4gICAgY29uc3QgZGVmYXVsdFR5cGVEZWNvcmF0b3I6IERlY29yYXRvck1ldGFkYXRhID0gZGVjb3JhdG9yc1swXTtcblxuICAgIC8vIHRyaWVzIHRvIGZpbmQgYW55IHR5cGUgZGVjb3JhdG9ycyBvciBvdGhlciBkZWNvcmF0b3JzIHRoYXQgYWxyZWFkeSBlbmZvcmNlIHR5cGUgKHRoZSBvbmVzIHdpdGggdGhlIGFsbG93ZWQgdHlwZXMgcHJvcGVydHkgZGVmaW5lZCkuIGlmIHNvLCBza2lwIHRoZSBkZWZhdWx0IHR5cGUgdmVyaWZpY2F0aW9uXG4gICAgaWYgKFxuICAgICAgZGVjb3JhdG9ycy5maW5kKChkKSA9PiB7XG4gICAgICAgIGlmIChkLmtleSA9PT0gVmFsaWRhdGlvbktleXMuVFlQRSkgcmV0dXJuIHRydWU7XG4gICAgICAgIHJldHVybiAhIWQucHJvcHMudHlwZXM/LmZpbmQoXG4gICAgICAgICAgKHQpID0+IHQgPT09IGRlZmF1bHRUeXBlRGVjb3JhdG9yLnByb3BzLm5hbWVcbiAgICAgICAgKTtcbiAgICAgIH0pXG4gICAgKSB7XG4gICAgICBkZWNvcmF0b3JzLnNoaWZ0KCk7IC8vIHJlbW92ZSB0aGUgZGVzaWduOnR5cGUgZGVjb3JhdG9yLCBzaW5jZSB0aGUgdHlwZSB3aWxsIGFscmVhZHkgYmUgY2hlY2tlZFxuICAgIH1cblxuICAgIGxldCBlcnJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgZm9yIChjb25zdCBkZWNvcmF0b3Igb2YgZGVjb3JhdG9ycykge1xuICAgICAgY29uc3QgdmFsaWRhdG9yID0gVmFsaWRhdGlvbi5nZXQoZGVjb3JhdG9yLmtleSk7XG4gICAgICBpZiAoIXZhbGlkYXRvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1pc3NpbmcgdmFsaWRhdG9yIGZvciAke2RlY29yYXRvci5rZXl9YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRlY29yYXRvclByb3BzID1cbiAgICAgICAgZGVjb3JhdG9yLmtleSA9PT0gTW9kZWxLZXlzLlRZUEVcbiAgICAgICAgICA/IFtkZWNvcmF0b3IucHJvcHNdXG4gICAgICAgICAgOiBkZWNvcmF0b3IucHJvcHMgfHwge307XG5cbiAgICAgIGNvbnN0IGVycjogc3RyaW5nIHwgdW5kZWZpbmVkID0gdmFsaWRhdG9yLmhhc0Vycm9ycyhcbiAgICAgICAgKG9iaiBhcyBhbnkpW3Byb3AudG9TdHJpbmcoKV0sXG4gICAgICAgIGRlY29yYXRvclByb3BzIGFzIFZhbGlkYXRvck9wdGlvbnNcbiAgICAgICk7XG5cbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgZXJycyA9IGVycnMgfHwge307XG4gICAgICAgIGVycnNbZGVjb3JhdG9yLmtleV0gPSBlcnI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVycnMpIHtcbiAgICAgIHJlc3VsdCA9IHJlc3VsdCB8fCB7fTtcbiAgICAgIHJlc3VsdFtkZWNvcmF0ZWRQcm9wZXJ0eS5wcm9wLnRvU3RyaW5nKCldID0gZXJycztcbiAgICB9XG4gIH1cblxuICAvLyB0ZXN0cyBuZXN0ZWQgY2xhc3Nlc1xuICBmb3IgKGNvbnN0IHByb3Agb2YgT2JqZWN0LmtleXMob2JqKS5maWx0ZXIoKGspID0+ICFyZXN1bHQgfHwgIXJlc3VsdFtrXSkpIHtcbiAgICBsZXQgZXJyOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgLy8gaWYgYSBuZXN0ZWQgTW9kZWxcbiAgICBjb25zdCBhbGxEZWNvcmF0b3JzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgb2JqLFxuICAgICAgcHJvcFxuICAgICkuZGVjb3JhdG9ycztcbiAgICBjb25zdCBkZWNvcmF0b3JzID0gUmVmbGVjdGlvbi5nZXRQcm9wZXJ0eURlY29yYXRvcnMoXG4gICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgb2JqLFxuICAgICAgcHJvcFxuICAgICkuZGVjb3JhdG9ycy5maWx0ZXIoXG4gICAgICAoZDogeyBrZXk6IHN0cmluZyB9KSA9PlxuICAgICAgICBbTW9kZWxLZXlzLlRZUEUsIFZhbGlkYXRpb25LZXlzLlRZUEUgYXMgc3RyaW5nXS5pbmRleE9mKGQua2V5KSAhPT0gLTFcbiAgICApO1xuICAgIGlmICghZGVjb3JhdG9ycyB8fCAhZGVjb3JhdG9ycy5sZW5ndGgpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGRlYyA9IGRlY29yYXRvcnMucG9wKCkgYXMgRGVjb3JhdG9yTWV0YWRhdGE7XG4gICAgY29uc3QgY2xhenogPSBkZWMucHJvcHMubmFtZVxuICAgICAgPyBbZGVjLnByb3BzLm5hbWVdXG4gICAgICA6IEFycmF5LmlzQXJyYXkoZGVjLnByb3BzLmN1c3RvbVR5cGVzKVxuICAgICAgICA/IGRlYy5wcm9wcy5jdXN0b21UeXBlc1xuICAgICAgICA6IFtkZWMucHJvcHMuY3VzdG9tVHlwZXNdO1xuICAgIGNvbnN0IHJlc2VydmVkID0gT2JqZWN0LnZhbHVlcyhSZXNlcnZlZE1vZGVscykubWFwKCh2KSA9PlxuICAgICAgdi50b0xvd2VyQ2FzZSgpXG4gICAgKSBhcyBzdHJpbmdbXTtcblxuICAgIGZvciAoY29uc3QgYyBvZiBjbGF6eikge1xuICAgICAgaWYgKHJlc2VydmVkLmluZGV4T2YoYy50b0xvd2VyQ2FzZSgpKSA9PT0gLTEpIHtcbiAgICAgICAgY29uc3QgdHlwZURlY29yYXRvcktleSA9IEFycmF5LmlzQXJyYXkoKG9iaiBhcyBhbnkpW3Byb3BdKVxuICAgICAgICAgID8gVmFsaWRhdGlvbktleXMuTElTVFxuICAgICAgICAgIDogVmFsaWRhdGlvbktleXMuVFlQRTtcbiAgICAgICAgY29uc3QgdHlwZXM6IGFueSA9XG4gICAgICAgICAgYWxsRGVjb3JhdG9ycy5maW5kKFxuICAgICAgICAgICAgKGQ6IHsga2V5OiBzdHJpbmcgfSkgPT4gZC5rZXkgPT09IHR5cGVEZWNvcmF0b3JLZXlcbiAgICAgICAgICApIHx8IHt9O1xuICAgICAgICBsZXQgYWxsb3dlZFR5cGVzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBpZiAodHlwZXMgJiYgdHlwZXMucHJvcHMpIHtcbiAgICAgICAgICBjb25zdCBjdXN0b21UeXBlcyA9IEFycmF5LmlzQXJyYXkoKG9iaiBhcyBhbnkpW3Byb3BdKVxuICAgICAgICAgICAgPyB0eXBlcy5wcm9wcy5jbGFzc1xuICAgICAgICAgICAgOiB0eXBlcy5wcm9wcy5jdXN0b21UeXBlcztcbiAgICAgICAgICBpZiAoY3VzdG9tVHlwZXMpXG4gICAgICAgICAgICBhbGxvd2VkVHlwZXMgPSBBcnJheS5pc0FycmF5KGN1c3RvbVR5cGVzKVxuICAgICAgICAgICAgICA/IGN1c3RvbVR5cGVzLm1hcCgodCkgPT4gYCR7dH1gLnRvTG93ZXJDYXNlKCkpXG4gICAgICAgICAgICAgIDogW2N1c3RvbVR5cGVzLnRvTG93ZXJDYXNlKCldO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdmFsaWRhdGUgPSAocHJvcDogc3RyaW5nLCB2YWx1ZTogYW55KTogYW55ID0+IHtcbiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiKVxuICAgICAgICAgICAgcmV0dXJuIGlzTW9kZWwodmFsdWUpXG4gICAgICAgICAgICAgID8gKHZhbHVlIGFzIE1vZGVsKS5oYXNFcnJvcnMoKVxuICAgICAgICAgICAgICA6IGFsbG93ZWRUeXBlcy5pbmNsdWRlcyh0eXBlb2YgdmFsdWUpXG4gICAgICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICA6IFwiVmFsdWUgaGFzIG5vIHZhbGlkYXRhYmxlIHR5cGVcIjtcbiAgICAgICAgfTtcblxuICAgICAgICBzd2l0Y2ggKGMpIHtcbiAgICAgICAgICBjYXNlIEFycmF5Lm5hbWU6XG4gICAgICAgICAgY2FzZSBTZXQubmFtZTpcbiAgICAgICAgICAgIGlmIChhbGxEZWNvcmF0b3JzLmxlbmd0aCkge1xuICAgICAgICAgICAgICBjb25zdCBsaXN0RGVjID0gYWxsRGVjb3JhdG9ycy5maW5kKFxuICAgICAgICAgICAgICAgIChkOiB7IGtleTogc3RyaW5nIH0pID0+IGQua2V5ID09PSBWYWxpZGF0aW9uS2V5cy5MSVNUXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIGlmIChsaXN0RGVjKSB7XG4gICAgICAgICAgICAgICAgZXJyID0gKFxuICAgICAgICAgICAgICAgICAgYyA9PT0gQXJyYXkubmFtZVxuICAgICAgICAgICAgICAgICAgICA/IChvYmogYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF1cbiAgICAgICAgICAgICAgICAgICAgOiAvLyBJZiBpdCdzIGEgU2V0XG4gICAgICAgICAgICAgICAgICAgICAgKG9iaiBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXS52YWx1ZXMoKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgIC5tYXAoKHY6IFZhbGlkYXRhYmxlKSA9PiB2YWxpZGF0ZShwcm9wLCB2KSlcbiAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGU6IGFueSkgPT4gISFlKSBhcyBhbnk7XG4gICAgICAgICAgICAgICAgaWYgKCFlcnI/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlc3VsdCBpcyBhbiBlbXB0eSBsaXN0Li4uXG4gICAgICAgICAgICAgICAgICBlcnIgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgaWYgKChvYmogYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0pXG4gICAgICAgICAgICAgICAgZXJyID0gdmFsaWRhdGUocHJvcCwgKG9iaiBhcyBhbnkpW3Byb3BdKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICBjb25zb2xlLndhcm4oc2YoXCJNb2RlbCBzaG91bGQgYmUgdmFsaWRhdGFibGUgYnV0IGl0cyBub3Q6IFwiICsgZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZXJyKSB7XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdCB8fCB7fTtcbiAgICAgICAgcmVzdWx0W3Byb3BdID0gZXJyIGFzIGFueTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0ID8gbmV3IE1vZGVsRXJyb3JEZWZpbml0aW9uKHJlc3VsdCkgOiB1bmRlZmluZWQ7XG59XG4iLCJpbXBvcnQgeyBTZXJpYWxpemF0aW9uIH0gZnJvbSBcIi4uL3V0aWxzL3NlcmlhbGl6YXRpb25cIjtcbmltcG9ydCB7IEJ1aWxkZXJSZWdpc3RyeSB9IGZyb20gXCIuLi91dGlscy9yZWdpc3RyeVwiO1xuaW1wb3J0IHsgTW9kZWxFcnJvckRlZmluaXRpb24gfSBmcm9tIFwiLi9Nb2RlbEVycm9yRGVmaW5pdGlvblwiO1xuaW1wb3J0IHtcbiAgQ29tcGFyYWJsZSxcbiAgQ29uc3RydWN0b3IsXG4gIEhhc2hhYmxlLFxuICBNb2RlbEFyZyxcbiAgTW9kZWxCdWlsZGVyRnVuY3Rpb24sXG4gIE1vZGVsQ29uc3RydWN0b3IsXG4gIFNlcmlhbGl6YWJsZSxcbiAgVmFsaWRhdGFibGUsXG59IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBEZWNvcmF0b3JNZXRhZGF0YSwgaXNFcXVhbCwgUmVmbGVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgdmFsaWRhdGUgfSBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBIYXNoaW5nIH0gZnJvbSBcIi4uL3V0aWxzL2hhc2hpbmdcIjtcbmltcG9ydCB7IE1vZGVsS2V5cyB9IGZyb20gXCIuLi91dGlscy9jb25zdGFudHNcIjtcbmltcG9ydCB7IFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4uL3ZhbGlkYXRpb24vVmFsaWRhdG9ycy9jb25zdGFudHNcIjtcbmltcG9ydCB7IHNmIH0gZnJvbSBcIi4uL3V0aWxzL3N0cmluZ3NcIjtcbmltcG9ydCB7IGpzVHlwZXMsIFJlc2VydmVkTW9kZWxzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5cbmxldCBtb2RlbEJ1aWxkZXJGdW5jdGlvbjogTW9kZWxCdWlsZGVyRnVuY3Rpb24gfCB1bmRlZmluZWQ7XG5sZXQgYWN0aW5nTW9kZWxSZWdpc3RyeTogQnVpbGRlclJlZ2lzdHJ5PGFueT47XG5cbmV4cG9ydCBmdW5jdGlvbiBpc1Byb3BlcnR5TW9kZWw8TSBleHRlbmRzIE1vZGVsPihcbiAgdGFyZ2V0OiBNLFxuICBhdHRyaWJ1dGU6IHN0cmluZ1xuKTogYm9vbGVhbiB8IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChpc01vZGVsKCh0YXJnZXQgYXMgUmVjb3JkPHN0cmluZywgYW55PilbYXR0cmlidXRlXSkpIHJldHVybiB0cnVlO1xuICBjb25zdCBtZXRhZGF0YSA9IFJlZmxlY3QuZ2V0TWV0YWRhdGEoTW9kZWxLZXlzLlRZUEUsIHRhcmdldCwgYXR0cmlidXRlKTtcbiAgcmV0dXJuIE1vZGVsLmdldChtZXRhZGF0YS5uYW1lKSA/IG1ldGFkYXRhLm5hbWUgOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRm9yIFNlcmlhbGl6YXRpb24vZGVzZXJpYWxpemF0aW9uIHB1cnBvc2VzLlxuICogQGRlc2NyaXB0aW9uIFJlYWRzIHRoZSB7QGxpbmsgTW9kZWxLZXlzLkFOQ0hPUn0gcHJvcGVydHkgb2YgYSB7QGxpbmsgTW9kZWx9IHRvIGRpc2NvdmVyIHRoZSBjbGFzcyB0byBpbnN0YW50aWF0ZVxuICpcbiAqIEBmdW5jdGlvbiBpc01vZGVsXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBWYWxpZGF0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vZGVsKHRhcmdldDogUmVjb3JkPHN0cmluZywgYW55Pikge1xuICB0cnkge1xuICAgIHJldHVybiB0YXJnZXQgaW5zdGFuY2VvZiBNb2RlbCB8fCAhIU1vZGVsLmdldE1ldGFkYXRhKHRhcmdldCBhcyBhbnkpO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogQHN1bW1hcnkgTW9kZWxSZWdpc3RyeSBJbnRlcmZhY2VcbiAqXG4gKiBAaW50ZXJmYWNlIE1vZGVsUmVnaXN0cnlcbiAqIEBleHRlbmRzIEJ1aWxkZXJSZWdpc3RyeTxNb2RlbD5cbiAqXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IHR5cGUgTW9kZWxSZWdpc3RyeTxUIGV4dGVuZHMgTW9kZWw+ID0gQnVpbGRlclJlZ2lzdHJ5PFQ+O1xuXG4vKipcbiAqIEBzdW1tYXJ5IFV0aWwgY2xhc3MgdG8gZW5hYmxlIHNlcmlhbGl6YXRpb24gYW5kIGNvcnJlY3QgcmVidWlsZGluZ1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhbmNob3JLZXkgZGVmYXVsdHMgdG8ge0BsaW5rIE1vZGVsS2V5cy5BTkNIT1J9LiBUaGUgcHJvcGVydHkgbmFtZSB3aGVyZSB0aGUgcmVnaXN0ZXJlZCBjbGFzcyBuYW1lIGlzIHN0b3JlZDtcbiAqIEBwYXJhbSB7ZnVuY3Rpb24oUmVjb3JkPHN0cmluZywgYW55Pik6IGJvb2xlYW59IFt0ZXN0RnVuY3Rpb25dIG1ldGhvZCB0byB0ZXN0IGlmIHRoZSBwcm92aWRlZCBvYmplY3QgaXMgYSBNb2RlbCBPYmplY3QuIGRlZmF1bHRzIHRvIHtAbGluayBpc01vZGVsfVxuICpcbiAqIEBjbGFzcyBNb2RlbFJlZ2lzdHJ5TWFuYWdlclxuICogQGltcGxlbWVudHMgTW9kZWxSZWdpc3RyeVxuICpcbiAqIEBjYXRlZ29yeSBNb2RlbFxuICovXG5leHBvcnQgY2xhc3MgTW9kZWxSZWdpc3RyeU1hbmFnZXI8VCBleHRlbmRzIE1vZGVsPiBpbXBsZW1lbnRzIE1vZGVsUmVnaXN0cnk8VD4ge1xuICBwcml2YXRlIGNhY2hlOiBSZWNvcmQ8c3RyaW5nLCBNb2RlbENvbnN0cnVjdG9yPFQ+PiA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IHRlc3RGdW5jdGlvbjogKG9iajogb2JqZWN0KSA9PiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHRlc3RGdW5jdGlvbjogKG9iajogUmVjb3JkPHN0cmluZywgYW55PikgPT4gYm9vbGVhbiA9IGlzTW9kZWwpIHtcbiAgICB0aGlzLnRlc3RGdW5jdGlvbiA9IHRlc3RGdW5jdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSByZWdpc3RlciBuZXcgTW9kZWxzXG4gICAqIEBwYXJhbSB7YW55fSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge3N0cmluZ30gW25hbWVdIHdoZW4gbm90IGRlZmluZWQsIHRoZSBuYW1lIG9mIHRoZSBjb25zdHJ1Y3RvciB3aWxsIGJlIHVzZWRcbiAgICovXG4gIHJlZ2lzdGVyKGNvbnN0cnVjdG9yOiBNb2RlbENvbnN0cnVjdG9yPFQ+LCBuYW1lPzogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciAhPT0gXCJmdW5jdGlvblwiKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIk1vZGVsIHJlZ2lzdGVyaW5nIGZhaWxlZC4gTWlzc2luZyBDbGFzcyBuYW1lIG9yIGNvbnN0cnVjdG9yXCJcbiAgICAgICk7XG4gICAgbmFtZSA9IG5hbWUgfHwgY29uc3RydWN0b3IubmFtZTtcbiAgICB0aGlzLmNhY2hlW25hbWVdID0gY29uc3RydWN0b3I7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgR2V0cyBhIHJlZ2lzdGVyZWQgTW9kZWwge0BsaW5rIE1vZGVsQ29uc3RydWN0b3J9XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAqL1xuICBnZXQobmFtZTogc3RyaW5nKTogTW9kZWxDb25zdHJ1Y3RvcjxUPiB8IHVuZGVmaW5lZCB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLmNhY2hlW25hbWVdO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmpcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtjbGF6el0gd2hlbiBwcm92aWRlZCwgaXQgd2lsbCBhdHRlbXB0IHRvIGZpbmQgdGhlIG1hdGNoaW5nIGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEB0aHJvd3MgRXJyb3IgSWYgY2xhenogaXMgbm90IGZvdW5kLCBvciBvYmogaXMgbm90IGEge0BsaW5rIE1vZGVsfSBtZWFuaW5nIGl0IGhhcyBubyB7QGxpbmsgTW9kZWxLZXlzLkFOQ0hPUn0gcHJvcGVydHlcbiAgICovXG4gIGJ1aWxkKG9iajogUmVjb3JkPHN0cmluZywgYW55PiA9IHt9LCBjbGF6ej86IHN0cmluZyk6IFQge1xuICAgIGlmICghY2xhenogJiYgIXRoaXMudGVzdEZ1bmN0aW9uKG9iaikpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcm92aWRlZCBvYmogaXMgbm90IGEgTW9kZWwgb2JqZWN0XCIpO1xuICAgIGNvbnN0IG5hbWUgPSBjbGF6eiB8fCBNb2RlbC5nZXRNZXRhZGF0YShvYmogYXMgYW55KTtcbiAgICBpZiAoIShuYW1lIGluIHRoaXMuY2FjaGUpKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBzZihcIlByb3ZpZGVkIGNsYXNzIHswfSBpcyBub3QgYSByZWdpc3RlcmVkIE1vZGVsIG9iamVjdFwiLCBuYW1lKVxuICAgICAgKTtcbiAgICByZXR1cm4gbmV3IHRoaXMuY2FjaGVbbmFtZV0ob2JqKTtcbiAgfVxufVxuXG4vKipcbiAqIEBzdW1tYXJ5IEJ1bGsgUmVnaXN0ZXJzIE1vZGVsc1xuICogQGRlc2NyaXB0aW9uIFVzZWZ1bCB3aGVuIHVzaW5nIGJ1bmRsZXJzIHRoYXQgbWlnaHQgbm90IGV2YWx1YXRlIGFsbCB0aGUgY29kZSBhdCBvbmNlXG4gKlxuICogQHBhcmFtIHtBcnJheTxDb25zdHJ1Y3RvcjxUPj4gfCBBcnJheTx7bmFtZTogc3RyaW5nLCBjb25zdHJ1Y3RvcjogQ29uc3RydWN0b3I8VD59Pn0gW21vZGVsc11cbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLk1vZGVsXG4gKiBAY2F0ZWdvcnkgTW9kZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1bGtNb2RlbFJlZ2lzdGVyPFQgZXh0ZW5kcyBNb2RlbD4oXG4gIC4uLm1vZGVsczogKENvbnN0cnVjdG9yPFQ+IHwgeyBuYW1lOiBzdHJpbmc7IGNvbnN0cnVjdG9yOiBDb25zdHJ1Y3RvcjxUPiB9KVtdXG4pIHtcbiAgbW9kZWxzLmZvckVhY2goXG4gICAgKG06IENvbnN0cnVjdG9yPFQ+IHwgeyBuYW1lOiBzdHJpbmc7IGNvbnN0cnVjdG9yOiBDb25zdHJ1Y3RvcjxUPiB9KSA9PiB7XG4gICAgICBjb25zdCBjb25zdHJ1Y3RvcjogQ29uc3RydWN0b3I8VD4gPSAoXG4gICAgICAgIG0uY29uc3RydWN0b3IgPyBtLmNvbnN0cnVjdG9yIDogbVxuICAgICAgKSBhcyBDb25zdHJ1Y3RvcjxUPjtcbiAgICAgIE1vZGVsLnJlZ2lzdGVyKGNvbnN0cnVjdG9yLCAobSBhcyBDb25zdHJ1Y3RvcjxUPikubmFtZSk7XG4gICAgfVxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IEFic3RyYWN0IGNsYXNzIHJlcHJlc2VudGluZyBhIFZhbGlkYXRhYmxlIE1vZGVsIG9iamVjdFxuICogQGRlc2NyaXB0aW9uIE1lYW50IHRvIGJlIHVzZWQgYXMgYSBiYXNlIGNsYXNzIGZvciBhbGwgTW9kZWwgY2xhc3Nlc1xuICpcbiAqIE1vZGVsIG9iamVjdHMgbXVzdDpcbiAqICAtIEhhdmUgYWxsIHRoZWlyIHJlcXVpcmVkIHByb3BlcnRpZXMgbWFya2VkIHdpdGggJyEnO1xuICogIC0gSGF2ZSBhbGwgdGhlaXIgb3B0aW9uYWwgcHJvcGVydGllcyBtYXJrZWQgYXMgJz8nOlxuICpcbiAqIEBwYXJhbSB7TW9kZWwgfCB7fX0gbW9kZWwgYmFzZSBvYmplY3QgZnJvbSB3aGljaCB0byBwb3B1bGF0ZSBwcm9wZXJ0aWVzIGZyb21cbiAqXG4gKiBAY2xhc3MgTW9kZWxcbiAqIEBhYnN0cmFjdFxuICogQGltcGxlbWVudHMgVmFsaWRhdGFibGVcbiAqIEBpbXBsZW1lbnRzIFNlcmlhbGl6YWJsZVxuICpcbiAqIEBleGFtcGxlXG4gKiAgICAgIGNsYXNzIENsYXNzTmFtZSB7XG4gKiAgICAgICAgICBAcmVxdWlyZWQoKVxuICogICAgICAgICAgcmVxdWlyZWRQcm9wZXJ0eU5hbWUhOiBQcm9wZXJ0eVR5cGU7XG4gKlxuICogICAgICAgICAgb3B0aW9uYWxQcm9wZXJ0eU5hbWU/OiBQcm9wZXJ0eVR5cGU7XG4gKiAgICAgIH1cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIE1vZGVsXG4gIGltcGxlbWVudHMgVmFsaWRhdGFibGUsIFNlcmlhbGl6YWJsZSwgSGFzaGFibGUsIENvbXBhcmFibGU8TW9kZWw+XG57XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKGFyZz86IE1vZGVsQXJnPE1vZGVsPikge31cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIHRoZSBvYmplY3QgYWNjb3JkaW5nIHRvIGl0cyBkZWNvcmF0ZWQgcHJvcGVydGllc1xuICAgKlxuICAgKiBAcGFyYW0ge2FueVtdfSBbZXhjZXB0aW9uc10gcHJvcGVydGllcyBpbiB0aGUgb2JqZWN0IHRvIGJlIGlnbm9yZWQgZm9yIHRoZSB2YWxpZGF0aW9uLiBNYXJrZWQgYXMgJ2FueScgdG8gYWxsb3cgZm9yIGV4dGVuc2lvbiBidXQgZXhwZWN0cyBzdHJpbmdzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKC4uLmV4Y2VwdGlvbnM6IGFueVtdKTogTW9kZWxFcnJvckRlZmluaXRpb24gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB2YWxpZGF0ZSh0aGlzLCAuLi5leGNlcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBDb21wYXJlIG9iamVjdCBlcXVhbGl0eSByZWN1cnNpdmVseVxuICAgKiBAcGFyYW0ge2FueX0gb2JqIG9iamVjdCB0byBjb21wYXJlIHRvXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbZXhjZXB0aW9uc10gcHJvcGVydHkgbmFtZXMgdG8gYmUgZXhjbHVkZWQgZnJvbSB0aGUgY29tcGFyaXNvblxuICAgKi9cbiAgcHVibGljIGVxdWFscyhvYmo6IGFueSwgLi4uZXhjZXB0aW9uczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gaXNFcXVhbCh0aGlzLCBvYmosIC4uLmV4Y2VwdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHNlcmlhbGl6ZWQgbW9kZWwgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50bHkgZGVmaW5lZCB7QGxpbmsgU2VyaWFsaXplcn1cbiAgICovXG4gIHNlcmlhbGl6ZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiBNb2RlbC5zZXJpYWxpemUodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgT3ZlcnJpZGUgdGhlIGltcGxlbWVudGF0aW9uIGZvciBqcydzICd0b1N0cmluZygpJyB3aGljaCBzdWNrcy4uLlxuICAgKiBAb3ZlcnJpZGVcbiAgICovXG4gIHB1YmxpYyB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLm5hbWUgKyBcIjogXCIgKyBKU09OLnN0cmluZ2lmeSh0aGlzLCB1bmRlZmluZWQsIDIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IERlZmluZXMgYSBkZWZhdWx0IGltcGxlbWVudGF0aW9uIGZvciBvYmplY3QgaGFzaC4gUmVsaWVzIG9uIGEgdmVyeSBiYXNpYyBpbXBsZW1lbnRhdGlvbiBiYXNlZCBvbiBKYXZhJ3Mgc3RyaW5nIGhhc2g7XG4gICAqL1xuICBwdWJsaWMgaGFzaCgpOiBzdHJpbmcge1xuICAgIHJldHVybiBNb2RlbC5oYXNoKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IERlc2VyaWFsaXplcyBhIE1vZGVsXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIGl0IGZhaWxzIHRvIHBhcnNlIHRoZSBzdHJpbmcsIG9yIGlmIGl0IGZhaWxzIHRvIGJ1aWxkIHRoZSBtb2RlbFxuICAgKi9cbiAgc3RhdGljIGRlc2VyaWFsaXplKHN0cjogc3RyaW5nKSB7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgTW9kZWwua2V5KE1vZGVsS2V5cy5TRVJJQUxJWkFUSU9OKSxcbiAgICAgIHRoaXMuY29uc3RydWN0b3JcbiAgICApO1xuXG4gICAgaWYgKG1ldGFkYXRhICYmIG1ldGFkYXRhLnNlcmlhbGl6ZXIpXG4gICAgICByZXR1cm4gU2VyaWFsaXphdGlvbi5kZXNlcmlhbGl6ZShcbiAgICAgICAgc3RyLFxuICAgICAgICBtZXRhZGF0YS5zZXJpYWxpemVyLFxuICAgICAgICAuLi4obWV0YWRhdGEuYXJncyB8fCBbXSlcbiAgICAgICk7XG4gICAgcmV0dXJuIFNlcmlhbGl6YXRpb24uZGVzZXJpYWxpemUoc3RyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZXBvcHVsYXRlcyB0aGUgT2JqZWN0IHByb3BlcnRpZXMgd2l0aCB0aGUgb25lcyBmcm9tIHRoZSBuZXcgb2JqZWN0XG4gICAqIEBkZXNjcmlwdGlvbiBJdGVyYXRlcyBhbGwgY29tbW9uIHByb3BlcnRpZXMgb2Ygb2JqIChpZiBleGlzdGluZykgYW5kIHNlbGYsIGFuZCBjb3BpZXMgdGhlbSBvbnRvIHNlbGZcbiAgICpcbiAgICogQHBhcmFtIHtUfSBzZWxmXG4gICAqIEBwYXJhbSB7VCB8IFJlY29yZDxzdHJpbmcsIGFueT59IFtvYmpdXG4gICAqXG4gICAqL1xuICBzdGF0aWMgZnJvbU9iamVjdDxUIGV4dGVuZHMgTW9kZWw+KFxuICAgIHNlbGY6IFQsXG4gICAgb2JqPzogVCB8IFJlY29yZDxzdHJpbmcsIGFueT5cbiAgKTogVCB7XG4gICAgaWYgKCFvYmopIG9iaiA9IHt9O1xuICAgIGZvciAoY29uc3QgcHJvcCBvZiBNb2RlbC5nZXRBdHRyaWJ1dGVzKHNlbGYpKSB7XG4gICAgICAoc2VsZiBhcyBhbnkpW3Byb3BdID0gKG9iaiBhcyBhbnkpW3Byb3BdIHx8IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIHNlbGY7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgUmVwb3B1bGF0ZXMgdGhlIGluc3RhbmNlIHdpdGggdGhlIG9uZXMgZnJvbSB0aGUgbmV3IE1vZGVsIE9iamVjdFxuICAgKiBAZGVzY3JpcHRpb24gSXRlcmF0ZXMgYWxsIGNvbW1vbiBwcm9wZXJ0aWVzIG9mIG9iaiAoaWYgZXhpc3RpbmcpIGFuZCBzZWxmLCBhbmQgY29waWVzIHRoZW0gb250byBzZWxmLlxuICAgKiBJcyBhd2FyZSBvZiBuZXN0ZWQgTW9kZWwgT2JqZWN0cyBhbmQgcmVidWlsZHMgdGhlbSBhbHNvLlxuICAgKiBXaGVuIExpc3QgcHJvcGVydGllcyBhcmUgZGVjb3JhdGVkIHdpdGgge0BsaW5rIGxpc3R9LCB0aGV5IGxpc3QgaXRlbXMgd2lsbCBhbHNvIGJlIHJlYnVpbHRcbiAgICpcbiAgICogQHBhcmFtIHtUfSBzZWxmXG4gICAqIEBwYXJhbSB7VCB8IFJlY29yZDxzdHJpbmcsIGFueT59IFtvYmpdXG4gICAqXG4gICAqL1xuICBzdGF0aWMgZnJvbU1vZGVsPFQgZXh0ZW5kcyBNb2RlbD4oc2VsZjogVCwgb2JqPzogVCB8IFJlY29yZDxzdHJpbmcsIGFueT4pOiBUIHtcbiAgICBpZiAoIW9iaikgb2JqID0ge307XG5cbiAgICBsZXQgZGVjb3JhdG9yczogRGVjb3JhdG9yTWV0YWRhdGFbXSwgZGVjOiBEZWNvcmF0b3JNZXRhZGF0YTtcblxuICAgIGNvbnN0IHByb3BzID0gTW9kZWwuZ2V0QXR0cmlidXRlcyhzZWxmKTtcblxuICAgIGZvciAoY29uc3QgcHJvcCBvZiBwcm9wcykge1xuICAgICAgKHNlbGYgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0gPVxuICAgICAgICAob2JqIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdIHx8IHVuZGVmaW5lZDtcbiAgICAgIGlmICh0eXBlb2YgKHNlbGYgYXMgYW55KVtwcm9wXSAhPT0gXCJvYmplY3RcIikgY29udGludWU7XG4gICAgICBjb25zdCBwcm9wTSA9IGlzUHJvcGVydHlNb2RlbChzZWxmLCBwcm9wKTtcbiAgICAgIGlmIChwcm9wTSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIChzZWxmIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdID0gTW9kZWwuYnVpbGQoXG4gICAgICAgICAgICAoc2VsZiBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXSxcbiAgICAgICAgICAgIHR5cGVvZiBwcm9wTSA9PT0gXCJzdHJpbmdcIiA/IHByb3BNIDogdW5kZWZpbmVkXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgY29uc29sZS5sb2coZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGFsbERlY29yYXRvcnM6IERlY29yYXRvck1ldGFkYXRhW10gPVxuICAgICAgICBSZWZsZWN0aW9uLmdldFByb3BlcnR5RGVjb3JhdG9ycyhcbiAgICAgICAgICBWYWxpZGF0aW9uS2V5cy5SRUZMRUNULFxuICAgICAgICAgIHNlbGYsXG4gICAgICAgICAgcHJvcFxuICAgICAgICApLmRlY29yYXRvcnM7XG4gICAgICBkZWNvcmF0b3JzID0gYWxsRGVjb3JhdG9ycy5maWx0ZXIoXG4gICAgICAgIChkOiBEZWNvcmF0b3JNZXRhZGF0YSkgPT5cbiAgICAgICAgICBbTW9kZWxLZXlzLlRZUEUsIFZhbGlkYXRpb25LZXlzLlRZUEUgYXMgc3RyaW5nXS5pbmRleE9mKGQua2V5KSAhPT0gLTFcbiAgICAgICk7XG4gICAgICBpZiAoIWRlY29yYXRvcnMgfHwgIWRlY29yYXRvcnMubGVuZ3RoKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3Ioc2YoXCJmYWlsZWQgdG8gZmluZCBkZWNvcmF0b3JzIGZvciBwcm9wZXJ0eSB7MH1cIiwgcHJvcCkpO1xuICAgICAgZGVjID0gZGVjb3JhdG9ycy5wb3AoKSBhcyBEZWNvcmF0b3JNZXRhZGF0YTtcbiAgICAgIGNvbnN0IGNsYXp6ID0gZGVjLnByb3BzLm5hbWVcbiAgICAgICAgPyBbZGVjLnByb3BzLm5hbWVdXG4gICAgICAgIDogQXJyYXkuaXNBcnJheShkZWMucHJvcHMuY3VzdG9tVHlwZXMpXG4gICAgICAgICAgPyBkZWMucHJvcHMuY3VzdG9tVHlwZXNcbiAgICAgICAgICA6IFtkZWMucHJvcHMuY3VzdG9tVHlwZXNdO1xuICAgICAgY29uc3QgcmVzZXJ2ZWQgPSBPYmplY3QudmFsdWVzKFJlc2VydmVkTW9kZWxzKS5tYXAoKHYpID0+XG4gICAgICAgIHYudG9Mb3dlckNhc2UoKVxuICAgICAgKSBhcyBzdHJpbmdbXTtcblxuICAgICAgY2xhenouZm9yRWFjaCgoYykgPT4ge1xuICAgICAgICBpZiAocmVzZXJ2ZWQuaW5kZXhPZihjLnRvTG93ZXJDYXNlKCkpID09PSAtMSlcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgc3dpdGNoIChjKSB7XG4gICAgICAgICAgICAgIGNhc2UgXCJBcnJheVwiOlxuICAgICAgICAgICAgICBjYXNlIFwiU2V0XCI6XG4gICAgICAgICAgICAgICAgaWYgKGFsbERlY29yYXRvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICBjb25zdCBsaXN0RGVjID0gYWxsRGVjb3JhdG9ycy5maW5kKFxuICAgICAgICAgICAgICAgICAgICAoZCkgPT4gZC5rZXkgPT09IFZhbGlkYXRpb25LZXlzLkxJU1RcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICBpZiAobGlzdERlYykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjbGF6ek5hbWUgPSAobGlzdERlYy5wcm9wcy5jbGF6eiBhcyBzdHJpbmdbXSkuZmluZChcbiAgICAgICAgICAgICAgICAgICAgICAodDogc3RyaW5nKSA9PiAhanNUeXBlcy5pbmNsdWRlcyh0LnRvTG93ZXJDYXNlKCkpXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjID09PSBcIkFycmF5XCIpXG4gICAgICAgICAgICAgICAgICAgICAgKHNlbGYgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0gPSAoXG4gICAgICAgICAgICAgICAgICAgICAgICBzZWxmIGFzIFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICAgICAgICAgICAgICAgICAgICApW3Byb3BdLm1hcCgoZWw6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFtcIm9iamVjdFwiLCBcImZ1bmN0aW9uXCJdLmluY2x1ZGVzKHR5cGVvZiBlbCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhenpOYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gTW9kZWwuYnVpbGQoZWwsIGNsYXp6TmFtZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgOiBlbDtcbiAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGMgPT09IFwiU2V0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzID0gbmV3IFNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgdiBvZiAoc2VsZiBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBbXCJvYmplY3RcIiwgXCJmdW5jdGlvblwiXS5pbmNsdWRlcyh0eXBlb2YgdikgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhenpOYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcy5hZGQoTW9kZWwuYnVpbGQodiwgY2xhenpOYW1lKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICBzLmFkZCh2KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgKHNlbGYgYXMgUmVjb3JkPHN0cmluZywgYW55PilbcHJvcF0gPSBzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGlmICgoc2VsZiBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVtwcm9wXSlcbiAgICAgICAgICAgICAgICAgIChzZWxmIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW3Byb3BdID0gTW9kZWwuYnVpbGQoXG4gICAgICAgICAgICAgICAgICAgIChzZWxmIGFzIGFueSlbcHJvcF0sXG4gICAgICAgICAgICAgICAgICAgIGNcbiAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhlKTtcbiAgICAgICAgICAgIC8vIGRvIG5vdGhpbmcuIHdlIGhhdmUgbm8gcmVnaXN0cnkgb2YgdGhpcyBjbGFzc1xuICAgICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gc2VsZjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBTZXRzIHRoZSBHbG9iYWwge0BsaW5rIE1vZGVsQnVpbGRlckZ1bmN0aW9ufVxuICAgKiBAcGFyYW0ge01vZGVsQnVpbGRlckZ1bmN0aW9ufSBbYnVpbGRlcl1cbiAgICovXG4gIHN0YXRpYyBzZXRCdWlsZGVyKGJ1aWxkZXI/OiBNb2RlbEJ1aWxkZXJGdW5jdGlvbikge1xuICAgIG1vZGVsQnVpbGRlckZ1bmN0aW9uID0gYnVpbGRlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZXRyaWV2ZXMgdGhlIGN1cnJlbnQgZ2xvYmFsIHtAbGluayBNb2RlbEJ1aWxkZXJGdW5jdGlvbn1cbiAgICovXG4gIHN0YXRpYyBnZXRCdWlsZGVyKCk6IE1vZGVsQnVpbGRlckZ1bmN0aW9uIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gbW9kZWxCdWlsZGVyRnVuY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCB7QGxpbmsgTW9kZWxSZWdpc3RyeU1hbmFnZXJ9XG4gICAqXG4gICAqIEByZXR1cm4gTW9kZWxSZWdpc3RyeSwgZGVmYXVsdHMgdG8ge0BsaW5rIE1vZGVsUmVnaXN0cnlNYW5hZ2VyfVxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0UmVnaXN0cnkoKSB7XG4gICAgaWYgKCFhY3RpbmdNb2RlbFJlZ2lzdHJ5KSBhY3RpbmdNb2RlbFJlZ2lzdHJ5ID0gbmV3IE1vZGVsUmVnaXN0cnlNYW5hZ2VyKCk7XG4gICAgcmV0dXJuIGFjdGluZ01vZGVsUmVnaXN0cnk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBhY3RpbmdNb2RlbFJlZ2lzdHJ5XG4gICAqXG4gICAqIEBwYXJhbSB7QnVpbGRlclJlZ2lzdHJ5fSBtb2RlbFJlZ2lzdHJ5IHRoZSBuZXcgaW1wbGVtZW50YXRpb24gb2YgUmVnaXN0cnlcbiAgICovXG4gIHN0YXRpYyBzZXRSZWdpc3RyeShtb2RlbFJlZ2lzdHJ5OiBCdWlsZGVyUmVnaXN0cnk8YW55Pikge1xuICAgIGFjdGluZ01vZGVsUmVnaXN0cnkgPSBtb2RlbFJlZ2lzdHJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHJlZ2lzdGVyIG5ldyBNb2RlbHNcbiAgICogQHBhcmFtIHthbnl9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbbmFtZV0gd2hlbiBub3QgZGVmaW5lZCwgdGhlIG5hbWUgb2YgdGhlIGNvbnN0cnVjdG9yIHdpbGwgYmUgdXNlZFxuICAgKlxuICAgKiBAc2VlIE1vZGVsUmVnaXN0cnlcbiAgICovXG4gIHN0YXRpYyByZWdpc3RlcjxUIGV4dGVuZHMgTW9kZWw+KFxuICAgIGNvbnN0cnVjdG9yOiBNb2RlbENvbnN0cnVjdG9yPFQ+LFxuICAgIG5hbWU/OiBzdHJpbmdcbiAgKTogdm9pZCB7XG4gICAgcmV0dXJuIE1vZGVsLmdldFJlZ2lzdHJ5KCkucmVnaXN0ZXIoY29uc3RydWN0b3IsIG5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IEdldHMgYSByZWdpc3RlcmVkIE1vZGVsIHtAbGluayBNb2RlbENvbnN0cnVjdG9yfVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgKlxuICAgKiBAc2VlIE1vZGVsUmVnaXN0cnlcbiAgICovXG4gIHN0YXRpYyBnZXQ8VCBleHRlbmRzIE1vZGVsPihuYW1lOiBzdHJpbmcpOiBNb2RlbENvbnN0cnVjdG9yPFQ+IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gTW9kZWwuZ2V0UmVnaXN0cnkoKS5nZXQobmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCBhbnk+fSBvYmpcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtjbGF6el0gd2hlbiBwcm92aWRlZCwgaXQgd2lsbCBhdHRlbXB0IHRvIGZpbmQgdGhlIG1hdGNoaW5nIGNvbnN0cnVjdG9yXG4gICAqXG4gICAqIEB0aHJvd3MgRXJyb3IgSWYgY2xhenogaXMgbm90IGZvdW5kLCBvciBvYmogaXMgbm90IGEge0BsaW5rIE1vZGVsfSBtZWFuaW5nIGl0IGhhcyBubyB7QGxpbmsgTW9kZWxLZXlzLkFOQ0hPUn0gcHJvcGVydHlcbiAgICpcbiAgICogQHNlZSBNb2RlbFJlZ2lzdHJ5XG4gICAqL1xuICBzdGF0aWMgYnVpbGQ8VCBleHRlbmRzIE1vZGVsPihcbiAgICBvYmo6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fSxcbiAgICBjbGF6ej86IHN0cmluZ1xuICApOiBUIHtcbiAgICByZXR1cm4gTW9kZWwuZ2V0UmVnaXN0cnkoKS5idWlsZChvYmosIGNsYXp6KTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRNZXRhZGF0YTxWIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBWKSB7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgTW9kZWwua2V5KE1vZGVsS2V5cy5NT0RFTCksXG4gICAgICBtb2RlbC5jb25zdHJ1Y3RvclxuICAgICk7XG4gICAgaWYgKCFtZXRhZGF0YSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJjb3VsZCBub3QgZmluZCBtZXRhZGF0YSBmb3IgcHJvdmlkZWQgXCIgKyBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lXG4gICAgICApO1xuICAgIHJldHVybiBtZXRhZGF0YTtcbiAgfVxuXG4gIHN0YXRpYyBnZXRBdHRyaWJ1dGVzPFYgZXh0ZW5kcyBNb2RlbD4obW9kZWw6IENvbnN0cnVjdG9yPFY+IHwgVikge1xuICAgIGNvbnN0IHJlc3VsdDogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgcHJvdG90eXBlID1cbiAgICAgIG1vZGVsIGluc3RhbmNlb2YgTW9kZWxcbiAgICAgICAgPyBPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kZWwpXG4gICAgICAgIDogKG1vZGVsIGFzIGFueSkucHJvdG90eXBlO1xuICAgIHdoaWxlIChwcm90b3R5cGUgIT0gbnVsbCkge1xuICAgICAgY29uc3QgcHJvcHM6IHN0cmluZ1tdID0gcHJvdG90eXBlW01vZGVsS2V5cy5BVFRSSUJVVEVdO1xuICAgICAgaWYgKHByb3BzKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKC4uLnByb3BzKTtcbiAgICAgIH1cbiAgICAgIHByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90b3R5cGUpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgc3RhdGljIGVxdWFsczxWIGV4dGVuZHMgTW9kZWw+KG9iajE6IFYsIG9iajI6IFYsIC4uLmV4Y2VwdGlvbnM6IGFueVtdKSB7XG4gICAgcmV0dXJuIGlzRXF1YWwob2JqMSwgb2JqMiwgLi4uZXhjZXB0aW9ucyk7XG4gIH1cblxuICBzdGF0aWMgaGFzRXJyb3JzPFYgZXh0ZW5kcyBNb2RlbD4obW9kZWw6IFYsIC4uLnByb3BzVG9JZ25vcmU6IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIHZhbGlkYXRlKG1vZGVsLCAuLi5wcm9wc1RvSWdub3JlKTtcbiAgfVxuXG4gIHN0YXRpYyBzZXJpYWxpemU8ViBleHRlbmRzIE1vZGVsPihtb2RlbDogVikge1xuICAgIGNvbnN0IG1ldGFkYXRhID0gUmVmbGVjdC5nZXRNZXRhZGF0YShcbiAgICAgIE1vZGVsLmtleShNb2RlbEtleXMuU0VSSUFMSVpBVElPTiksXG4gICAgICBtb2RlbC5jb25zdHJ1Y3RvclxuICAgICk7XG5cbiAgICBpZiAobWV0YWRhdGEgJiYgbWV0YWRhdGEuc2VyaWFsaXplcilcbiAgICAgIHJldHVybiBTZXJpYWxpemF0aW9uLnNlcmlhbGl6ZShcbiAgICAgICAgdGhpcyxcbiAgICAgICAgbWV0YWRhdGEuc2VyaWFsaXplcixcbiAgICAgICAgLi4uKG1ldGFkYXRhLmFyZ3MgfHwgW10pXG4gICAgICApO1xuICAgIHJldHVybiBTZXJpYWxpemF0aW9uLnNlcmlhbGl6ZShtb2RlbCk7XG4gIH1cblxuICBzdGF0aWMgaGFzaDxWIGV4dGVuZHMgTW9kZWw+KG1vZGVsOiBWKSB7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBSZWZsZWN0LmdldE1ldGFkYXRhKFxuICAgICAgTW9kZWwua2V5KE1vZGVsS2V5cy5IQVNISU5HKSxcbiAgICAgIG1vZGVsLmNvbnN0cnVjdG9yXG4gICAgKTtcblxuICAgIGlmIChtZXRhZGF0YSAmJiBtZXRhZGF0YS5hbGdvcml0aG0pXG4gICAgICByZXR1cm4gSGFzaGluZy5oYXNoKG1vZGVsLCBtZXRhZGF0YS5hbGdvcml0aG0sIC4uLihtZXRhZGF0YS5hcmdzIHx8IFtdKSk7XG4gICAgcmV0dXJuIEhhc2hpbmcuaGFzaChtb2RlbCk7XG4gIH1cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IEJ1aWxkcyB0aGUga2V5IHRvIHN0b3JlIGFzIE1ldGFkYXRhIHVuZGVyIFJlZmxlY3Rpb25zXG4gICAqIEBkZXNjcmlwdGlvbiBjb25jYXRlbmF0ZXMge0BsaW5rIE1vZGVsS2V5cyNSRUZMRUNUfSB3aXRoIHRoZSBwcm92aWRlZCBrZXlcbiAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgKi9cbiAgc3RhdGljIGtleShzdHI6IHN0cmluZykge1xuICAgIHJldHVybiBNb2RlbEtleXMuUkVGTEVDVCArIHN0cjtcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29uc3RydWN0b3IgfSBmcm9tIFwiLi4vbW9kZWwvdHlwZXNcIjtcbmltcG9ydCB7IFNlcmlhbGl6ZXIgfSBmcm9tIFwiLi90eXBlc1wiO1xuaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWwvTW9kZWxcIjtcbmltcG9ydCB7IE1vZGVsS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuXG5leHBvcnQgY29uc3QgRGVmYXVsdFNlcmlhbGl6YXRpb25NZXRob2QgPSBcImpzb25cIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBDb25jcmV0ZSBpbXBsZW1lbnRhdGlvbiBvZiBhIHtAbGluayBTZXJpYWxpemVyfSBpbiBKU09OIGZvcm1hdFxuICogQGRlc2NyaXB0aW9uIEpTJ3MgbmF0aXZlIEpTT04uc3RyaW5naWZ5ICh1c2VkIGhlcmUpIGlzIG5vdCBkZXRlcm1pbmlzdGljXG4gKiBhbmQgdGhlcmVmb3JlIHNob3VsZCBub3QgYmUgdXNlZCBmb3IgaGFzaGluZyBwdXJwb3Nlc1xuICpcbiAqIFRvIGtlZXAgZGVwZW5kZW5jaWVzIGxvdywgd2Ugd2lsbCBub3QgaW1wbGVtZW50IHRoaXMsIGJ1dCB3ZSByZWNvbW1lbmRcbiAqIGltcGxlbWVudGluZyBhIHNpbWlsYXIge0BsaW5rIEpTT05TZXJpYWxpemVyfSB1c2luZyAnZGV0ZXJtaW5pc3RpYy1qc29uJyBsaWJyYXJpZXNcbiAqXG4gKiBAY2xhc3MgSlNPTlNlcmlhbGl6ZXJcbiAqIEBpbXBsZW1lbnRzIFNlcmlhbGl6ZXJcbiAqXG4gKiBAY2F0ZWdvcnkgU2VyaWFsaXphdGlvblxuICovXG5leHBvcnQgY2xhc3MgSlNPTlNlcmlhbGl6ZXI8VCBleHRlbmRzIE1vZGVsPiBpbXBsZW1lbnRzIFNlcmlhbGl6ZXI8VD4ge1xuICBjb25zdHJ1Y3RvcigpIHt9XG4gIC8qKlxuICAgKiBAc3VtbWFyeSBwcmVwYXJlcyB0aGUgbW9kZWwgZm9yIHNlcmlhbGl6YXRpb25cbiAgICogQGRlc2NyaXB0aW9uIHJldHVybnMgYSBzaGFsbG93IGNvcHkgb2YgdGhlIG9iamVjdCwgY29udGFpbmluZyBhbiBlbnVtZXJhYmxlIHtAbGluayBNb2RlbEtleXMjQU5DSE9SfSBwcm9wZXJ0eVxuICAgKiBzbyB0aGUgb2JqZWN0IGNhbiBiZSByZWNvZ25pemVkIHVwb24gZGVzZXJpYWxpemF0aW9uXG4gICAqXG4gICAqIEBwYXJhbSB7VH0gbW9kZWxcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcHJvdGVjdGVkIHByZVNlcmlhbGl6ZShtb2RlbDogVCkge1xuICAgIC8vIFRPRE86IG5lc3RlZCBwcmVzZXJpYWxpemF0aW9uIChzbyBpbmNyZWFzZSBwZXJmb3JtYW5jZSB3aGVuIGRlc2VyaWFsaXppbmcpXG4gICAgY29uc3QgdG9TZXJpYWxpemU6IFJlY29yZDxzdHJpbmcsIGFueT4gPSBPYmplY3QuYXNzaWduKHt9LCBtb2RlbCk7XG4gICAgY29uc3QgbWV0YWRhdGEgPSBNb2RlbC5nZXRNZXRhZGF0YShtb2RlbCk7XG4gICAgdG9TZXJpYWxpemVbTW9kZWxLZXlzLkFOQ0hPUl0gPSBtZXRhZGF0YSB8fCBtb2RlbC5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIHJldHVybiB0b1NlcmlhbGl6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBSZWJ1aWxkcyBhIG1vZGVsIGZyb20gYSBzZXJpYWxpemF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIGl0IGZhaWxzIHRvIHBhcnNlIHRoZSBzdHJpbmcsIG9yIHRvIGJ1aWxkIHRoZSBtb2RlbFxuICAgKi9cbiAgZGVzZXJpYWxpemUoc3RyOiBzdHJpbmcpOiBUIHtcbiAgICBjb25zdCBkZXNlcmlhbGl6YXRpb24gPSBKU09OLnBhcnNlKHN0cik7XG4gICAgY29uc3QgY2xhc3NOYW1lID0gZGVzZXJpYWxpemF0aW9uW01vZGVsS2V5cy5BTkNIT1JdO1xuICAgIGlmICghY2xhc3NOYW1lKVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgY2xhc3MgcmVmZXJlbmNlIGluIHNlcmlhbGl6ZWQgbW9kZWxcIik7XG4gICAgY29uc3QgbW9kZWw6IFQgPSBNb2RlbC5idWlsZChkZXNlcmlhbGl6YXRpb24sIGNsYXNzTmFtZSkgYXMgdW5rbm93biBhcyBUO1xuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBTZXJpYWxpemVzIGEgbW9kZWxcbiAgICogQHBhcmFtIHtUfSBtb2RlbFxuICAgKlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgZmFpbHMgdG8gc2VyaWFsaXplXG4gICAqL1xuICBzZXJpYWxpemUobW9kZWw6IFQpOiBzdHJpbmcge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLnByZVNlcmlhbGl6ZShtb2RlbCkpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTZXJpYWxpemF0aW9uIHtcbiAgcHJpdmF0ZSBzdGF0aWMgY3VycmVudDogc3RyaW5nID0gRGVmYXVsdFNlcmlhbGl6YXRpb25NZXRob2Q7XG5cbiAgcHJpdmF0ZSBzdGF0aWMgY2FjaGU6IFJlY29yZDxzdHJpbmcsIFNlcmlhbGl6ZXI8YW55Pj4gPSB7XG4gICAganNvbjogbmV3IEpTT05TZXJpYWxpemVyKCksXG4gIH07XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHt9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoa2V5IGluIHRoaXMuY2FjaGUpIHJldHVybiB0aGlzLmNhY2hlW2tleV07XG4gICAgdGhyb3cgbmV3IEVycm9yKGBObyBzZXJpYWxpemF0aW9uIG1ldGhvZCByZWdpc3RlcmVkIHVuZGVyICR7a2V5fWApO1xuICB9XG5cbiAgc3RhdGljIHJlZ2lzdGVyKFxuICAgIGtleTogc3RyaW5nLFxuICAgIGZ1bmM6IENvbnN0cnVjdG9yPFNlcmlhbGl6ZXI8YW55Pj4sXG4gICAgc2V0RGVmYXVsdCA9IGZhbHNlXG4gICk6IHZvaWQge1xuICAgIGlmIChrZXkgaW4gdGhpcy5jYWNoZSlcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU2VyaWFsaXphdGlvbiBtZXRob2QgJHtrZXl9IGFscmVhZHkgcmVnaXN0ZXJlZGApO1xuICAgIHRoaXMuY2FjaGVba2V5XSA9IG5ldyBmdW5jKCk7XG4gICAgaWYgKHNldERlZmF1bHQpIHRoaXMuY3VycmVudCA9IGtleTtcbiAgfVxuXG4gIHN0YXRpYyBzZXJpYWxpemUob2JqOiBhbnksIG1ldGhvZD86IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgICBpZiAoIW1ldGhvZCkgcmV0dXJuIHRoaXMuZ2V0KHRoaXMuY3VycmVudCkuc2VyaWFsaXplKG9iaiwgLi4uYXJncyk7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KG1ldGhvZCkuc2VyaWFsaXplKG9iaiwgLi4uYXJncyk7XG4gIH1cblxuICBzdGF0aWMgZGVzZXJpYWxpemUob2JqOiBzdHJpbmcsIG1ldGhvZD86IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgICBpZiAoIW1ldGhvZCkgcmV0dXJuIHRoaXMuZ2V0KHRoaXMuY3VycmVudCkuZGVzZXJpYWxpemUob2JqLCAuLi5hcmdzKTtcbiAgICByZXR1cm4gdGhpcy5nZXQobWV0aG9kKS5kZXNlcmlhbGl6ZShvYmosIC4uLmFyZ3MpO1xuICB9XG5cbiAgc3RhdGljIHNldERlZmF1bHQobWV0aG9kOiBzdHJpbmcpIHtcbiAgICB0aGlzLmN1cnJlbnQgPSB0aGlzLmdldChtZXRob2QpO1xuICB9XG59XG4iLCIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UsIFN1cHByZXNzZWRFcnJvciwgU3ltYm9sLCBJdGVyYXRvciAqL1xyXG5cclxudmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbihkLCBiKSB7XHJcbiAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XHJcbiAgICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxyXG4gICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XHJcbiAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4dGVuZHMoZCwgYikge1xyXG4gICAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcclxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XHJcbiAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xyXG4gICAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XHJcbiAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDAgJiYgT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHMsIHBbaV0pKVxyXG4gICAgICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICAgICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XHJcbiAgICB2YXIgYyA9IGFyZ3VtZW50cy5sZW5ndGgsIHIgPSBjIDwgMyA/IHRhcmdldCA6IGRlc2MgPT09IG51bGwgPyBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0YXJnZXQsIGtleSkgOiBkZXNjLCBkO1xyXG4gICAgaWYgKHR5cGVvZiBSZWZsZWN0ID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBSZWZsZWN0LmRlY29yYXRlID09PSBcImZ1bmN0aW9uXCIpIHIgPSBSZWZsZWN0LmRlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKTtcclxuICAgIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XHJcbiAgICByZXR1cm4gYyA+IDMgJiYgciAmJiBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHIpLCByO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wYXJhbShwYXJhbUluZGV4LCBkZWNvcmF0b3IpIHtcclxuICAgIHJldHVybiBmdW5jdGlvbiAodGFyZ2V0LCBrZXkpIHsgZGVjb3JhdG9yKHRhcmdldCwga2V5LCBwYXJhbUluZGV4KTsgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19lc0RlY29yYXRlKGN0b3IsIGRlc2NyaXB0b3JJbiwgZGVjb3JhdG9ycywgY29udGV4dEluLCBpbml0aWFsaXplcnMsIGV4dHJhSW5pdGlhbGl6ZXJzKSB7XHJcbiAgICBmdW5jdGlvbiBhY2NlcHQoZikgeyBpZiAoZiAhPT0gdm9pZCAwICYmIHR5cGVvZiBmICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJGdW5jdGlvbiBleHBlY3RlZFwiKTsgcmV0dXJuIGY7IH1cclxuICAgIHZhciBraW5kID0gY29udGV4dEluLmtpbmQsIGtleSA9IGtpbmQgPT09IFwiZ2V0dGVyXCIgPyBcImdldFwiIDoga2luZCA9PT0gXCJzZXR0ZXJcIiA/IFwic2V0XCIgOiBcInZhbHVlXCI7XHJcbiAgICB2YXIgdGFyZ2V0ID0gIWRlc2NyaXB0b3JJbiAmJiBjdG9yID8gY29udGV4dEluW1wic3RhdGljXCJdID8gY3RvciA6IGN0b3IucHJvdG90eXBlIDogbnVsbDtcclxuICAgIHZhciBkZXNjcmlwdG9yID0gZGVzY3JpcHRvckluIHx8ICh0YXJnZXQgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgY29udGV4dEluLm5hbWUpIDoge30pO1xyXG4gICAgdmFyIF8sIGRvbmUgPSBmYWxzZTtcclxuICAgIGZvciAodmFyIGkgPSBkZWNvcmF0b3JzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgdmFyIGNvbnRleHQgPSB7fTtcclxuICAgICAgICBmb3IgKHZhciBwIGluIGNvbnRleHRJbikgY29udGV4dFtwXSA9IHAgPT09IFwiYWNjZXNzXCIgPyB7fSA6IGNvbnRleHRJbltwXTtcclxuICAgICAgICBmb3IgKHZhciBwIGluIGNvbnRleHRJbi5hY2Nlc3MpIGNvbnRleHQuYWNjZXNzW3BdID0gY29udGV4dEluLmFjY2Vzc1twXTtcclxuICAgICAgICBjb250ZXh0LmFkZEluaXRpYWxpemVyID0gZnVuY3Rpb24gKGYpIHsgaWYgKGRvbmUpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgYWRkIGluaXRpYWxpemVycyBhZnRlciBkZWNvcmF0aW9uIGhhcyBjb21wbGV0ZWRcIik7IGV4dHJhSW5pdGlhbGl6ZXJzLnB1c2goYWNjZXB0KGYgfHwgbnVsbCkpOyB9O1xyXG4gICAgICAgIHZhciByZXN1bHQgPSAoMCwgZGVjb3JhdG9yc1tpXSkoa2luZCA9PT0gXCJhY2Nlc3NvclwiID8geyBnZXQ6IGRlc2NyaXB0b3IuZ2V0LCBzZXQ6IGRlc2NyaXB0b3Iuc2V0IH0gOiBkZXNjcmlwdG9yW2tleV0sIGNvbnRleHQpO1xyXG4gICAgICAgIGlmIChraW5kID09PSBcImFjY2Vzc29yXCIpIHtcclxuICAgICAgICAgICAgaWYgKHJlc3VsdCA9PT0gdm9pZCAwKSBjb250aW51ZTtcclxuICAgICAgICAgICAgaWYgKHJlc3VsdCA9PT0gbnVsbCB8fCB0eXBlb2YgcmVzdWx0ICE9PSBcIm9iamVjdFwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiT2JqZWN0IGV4cGVjdGVkXCIpO1xyXG4gICAgICAgICAgICBpZiAoXyA9IGFjY2VwdChyZXN1bHQuZ2V0KSkgZGVzY3JpcHRvci5nZXQgPSBfO1xyXG4gICAgICAgICAgICBpZiAoXyA9IGFjY2VwdChyZXN1bHQuc2V0KSkgZGVzY3JpcHRvci5zZXQgPSBfO1xyXG4gICAgICAgICAgICBpZiAoXyA9IGFjY2VwdChyZXN1bHQuaW5pdCkpIGluaXRpYWxpemVycy51bnNoaWZ0KF8pO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNlIGlmIChfID0gYWNjZXB0KHJlc3VsdCkpIHtcclxuICAgICAgICAgICAgaWYgKGtpbmQgPT09IFwiZmllbGRcIikgaW5pdGlhbGl6ZXJzLnVuc2hpZnQoXyk7XHJcbiAgICAgICAgICAgIGVsc2UgZGVzY3JpcHRvcltrZXldID0gXztcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAodGFyZ2V0KSBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBjb250ZXh0SW4ubmFtZSwgZGVzY3JpcHRvcik7XHJcbiAgICBkb25lID0gdHJ1ZTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3J1bkluaXRpYWxpemVycyh0aGlzQXJnLCBpbml0aWFsaXplcnMsIHZhbHVlKSB7XHJcbiAgICB2YXIgdXNlVmFsdWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMjtcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5pdGlhbGl6ZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgdmFsdWUgPSB1c2VWYWx1ZSA/IGluaXRpYWxpemVyc1tpXS5jYWxsKHRoaXNBcmcsIHZhbHVlKSA6IGluaXRpYWxpemVyc1tpXS5jYWxsKHRoaXNBcmcpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHVzZVZhbHVlID8gdmFsdWUgOiB2b2lkIDA7XHJcbn07XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19wcm9wS2V5KHgpIHtcclxuICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzeW1ib2xcIiA/IHggOiBcIlwiLmNvbmNhdCh4KTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NldEZ1bmN0aW9uTmFtZShmLCBuYW1lLCBwcmVmaXgpIHtcclxuICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gXCJzeW1ib2xcIikgbmFtZSA9IG5hbWUuZGVzY3JpcHRpb24gPyBcIltcIi5jb25jYXQobmFtZS5kZXNjcmlwdGlvbiwgXCJdXCIpIDogXCJcIjtcclxuICAgIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZiwgXCJuYW1lXCIsIHsgY29uZmlndXJhYmxlOiB0cnVlLCB2YWx1ZTogcHJlZml4ID8gXCJcIi5jb25jYXQocHJlZml4LCBcIiBcIiwgbmFtZSkgOiBuYW1lIH0pO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fbWV0YWRhdGEobWV0YWRhdGFLZXksIG1ldGFkYXRhVmFsdWUpIHtcclxuICAgIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XHJcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cclxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cclxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxyXG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcclxuICAgIH0pO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19nZW5lcmF0b3IodGhpc0FyZywgYm9keSkge1xyXG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZyA9IE9iamVjdC5jcmVhdGUoKHR5cGVvZiBJdGVyYXRvciA9PT0gXCJmdW5jdGlvblwiID8gSXRlcmF0b3IgOiBPYmplY3QpLnByb3RvdHlwZSk7XHJcbiAgICByZXR1cm4gZy5uZXh0ID0gdmVyYigwKSwgZ1tcInRocm93XCJdID0gdmVyYigxKSwgZ1tcInJldHVyblwiXSA9IHZlcmIoMiksIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcclxuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xyXG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcclxuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xyXG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XHJcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcclxuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xyXG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XHJcbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCB2YXIgX19jcmVhdGVCaW5kaW5nID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xyXG4gICAgaWYgKGsyID09PSB1bmRlZmluZWQpIGsyID0gaztcclxuICAgIHZhciBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihtLCBrKTtcclxuICAgIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XHJcbiAgICAgICAgZGVzYyA9IHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIG1ba107IH0gfTtcclxuICAgIH1cclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XHJcbn0pIDogKGZ1bmN0aW9uKG8sIG0sIGssIGsyKSB7XHJcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xyXG4gICAgb1trMl0gPSBtW2tdO1xyXG59KTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2V4cG9ydFN0YXIobSwgbykge1xyXG4gICAgZm9yICh2YXIgcCBpbiBtKSBpZiAocCAhPT0gXCJkZWZhdWx0XCIgJiYgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvLCBwKSkgX19jcmVhdGVCaW5kaW5nKG8sIG0sIHApO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX192YWx1ZXMobykge1xyXG4gICAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcclxuICAgIGlmIChtKSByZXR1cm4gbS5jYWxsKG8pO1xyXG4gICAgaWYgKG8gJiYgdHlwZW9mIG8ubGVuZ3RoID09PSBcIm51bWJlclwiKSByZXR1cm4ge1xyXG4gICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgaWYgKG8gJiYgaSA+PSBvLmxlbmd0aCkgbyA9IHZvaWQgMDtcclxuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG8gJiYgb1tpKytdLCBkb25lOiAhbyB9O1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHMgPyBcIk9iamVjdCBpcyBub3QgaXRlcmFibGUuXCIgOiBcIlN5bWJvbC5pdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3JlYWQobywgbikge1xyXG4gICAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xyXG4gICAgaWYgKCFtKSByZXR1cm4gbztcclxuICAgIHZhciBpID0gbS5jYWxsKG8pLCByLCBhciA9IFtdLCBlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgICB3aGlsZSAoKG4gPT09IHZvaWQgMCB8fCBuLS0gPiAwKSAmJiAhKHIgPSBpLm5leHQoKSkuZG9uZSkgYXIucHVzaChyLnZhbHVlKTtcclxuICAgIH1cclxuICAgIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxyXG4gICAgZmluYWxseSB7XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZpbmFsbHkgeyBpZiAoZSkgdGhyb3cgZS5lcnJvcjsgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xyXG4gICAgZm9yICh2YXIgYXIgPSBbXSwgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspXHJcbiAgICAgICAgYXIgPSBhci5jb25jYXQoX19yZWFkKGFyZ3VtZW50c1tpXSkpO1xyXG4gICAgcmV0dXJuIGFyO1xyXG59XHJcblxyXG4vKiogQGRlcHJlY2F0ZWQgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXlzKCkge1xyXG4gICAgZm9yICh2YXIgcyA9IDAsIGkgPSAwLCBpbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBpbDsgaSsrKSBzICs9IGFyZ3VtZW50c1tpXS5sZW5ndGg7XHJcbiAgICBmb3IgKHZhciByID0gQXJyYXkocyksIGsgPSAwLCBpID0gMDsgaSA8IGlsOyBpKyspXHJcbiAgICAgICAgZm9yICh2YXIgYSA9IGFyZ3VtZW50c1tpXSwgaiA9IDAsIGpsID0gYS5sZW5ndGg7IGogPCBqbDsgaisrLCBrKyspXHJcbiAgICAgICAgICAgIHJba10gPSBhW2pdO1xyXG4gICAgcmV0dXJuIHI7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5KHRvLCBmcm9tLCBwYWNrKSB7XHJcbiAgICBpZiAocGFjayB8fCBhcmd1bWVudHMubGVuZ3RoID09PSAyKSBmb3IgKHZhciBpID0gMCwgbCA9IGZyb20ubGVuZ3RoLCBhcjsgaSA8IGw7IGkrKykge1xyXG4gICAgICAgIGlmIChhciB8fCAhKGkgaW4gZnJvbSkpIHtcclxuICAgICAgICAgICAgaWYgKCFhcikgYXIgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmcm9tLCAwLCBpKTtcclxuICAgICAgICAgICAgYXJbaV0gPSBmcm9tW2ldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0by5jb25jYXQoYXIgfHwgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZnJvbSkpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19hd2FpdCh2KSB7XHJcbiAgICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XHJcbiAgICBpZiAoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jSXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgdmFyIGcgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSksIGksIHEgPSBbXTtcclxuICAgIHJldHVybiBpID0gT2JqZWN0LmNyZWF0ZSgodHlwZW9mIEFzeW5jSXRlcmF0b3IgPT09IFwiZnVuY3Rpb25cIiA/IEFzeW5jSXRlcmF0b3IgOiBPYmplY3QpLnByb3RvdHlwZSksIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiwgYXdhaXRSZXR1cm4pLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XHJcbiAgICBmdW5jdGlvbiBhd2FpdFJldHVybihmKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZiwgcmVqZWN0KTsgfTsgfVxyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlmIChnW25dKSB7IGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IGlmIChmKSBpW25dID0gZihpW25dKTsgfSB9XHJcbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XHJcbiAgICBmdW5jdGlvbiBzdGVwKHIpIHsgci52YWx1ZSBpbnN0YW5jZW9mIF9fYXdhaXQgPyBQcm9taXNlLnJlc29sdmUoci52YWx1ZS52KS50aGVuKGZ1bGZpbGwsIHJlamVjdCkgOiBzZXR0bGUocVswXVsyXSwgcik7IH1cclxuICAgIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cclxuICAgIGZ1bmN0aW9uIHNldHRsZShmLCB2KSB7IGlmIChmKHYpLCBxLnNoaWZ0KCksIHEubGVuZ3RoKSByZXN1bWUocVswXVswXSwgcVswXVsxXSk7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNEZWxlZ2F0b3Iobykge1xyXG4gICAgdmFyIGksIHA7XHJcbiAgICByZXR1cm4gaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIsIGZ1bmN0aW9uIChlKSB7IHRocm93IGU7IH0pLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9LCBpO1xyXG4gICAgZnVuY3Rpb24gdmVyYihuLCBmKSB7IGlbbl0gPSBvW25dID8gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIChwID0gIXApID8geyB2YWx1ZTogX19hd2FpdChvW25dKHYpKSwgZG9uZTogZmFsc2UgfSA6IGYgPyBmKHYpIDogdjsgfSA6IGY7IH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNWYWx1ZXMobykge1xyXG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcclxuICAgIHZhciBtID0gb1tTeW1ib2wuYXN5bmNJdGVyYXRvcl0sIGk7XHJcbiAgICByZXR1cm4gbSA/IG0uY2FsbChvKSA6IChvID0gdHlwZW9mIF9fdmFsdWVzID09PSBcImZ1bmN0aW9uXCIgPyBfX3ZhbHVlcyhvKSA6IG9bU3ltYm9sLml0ZXJhdG9yXSgpLCBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaSk7XHJcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XHJcbiAgICBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCBkLCB2KSB7IFByb21pc2UucmVzb2x2ZSh2KS50aGVuKGZ1bmN0aW9uKHYpIHsgcmVzb2x2ZSh7IHZhbHVlOiB2LCBkb25lOiBkIH0pOyB9LCByZWplY3QpOyB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX21ha2VUZW1wbGF0ZU9iamVjdChjb29rZWQsIHJhdykge1xyXG4gICAgaWYgKE9iamVjdC5kZWZpbmVQcm9wZXJ0eSkgeyBPYmplY3QuZGVmaW5lUHJvcGVydHkoY29va2VkLCBcInJhd1wiLCB7IHZhbHVlOiByYXcgfSk7IH0gZWxzZSB7IGNvb2tlZC5yYXcgPSByYXc7IH1cclxuICAgIHJldHVybiBjb29rZWQ7XHJcbn07XHJcblxyXG52YXIgX19zZXRNb2R1bGVEZWZhdWx0ID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCB2KSB7XHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgXCJkZWZhdWx0XCIsIHsgZW51bWVyYWJsZTogdHJ1ZSwgdmFsdWU6IHYgfSk7XHJcbn0pIDogZnVuY3Rpb24obywgdikge1xyXG4gICAgb1tcImRlZmF1bHRcIl0gPSB2O1xyXG59O1xyXG5cclxudmFyIG93bktleXMgPSBmdW5jdGlvbihvKSB7XHJcbiAgICBvd25LZXlzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMgfHwgZnVuY3Rpb24gKG8pIHtcclxuICAgICAgICB2YXIgYXIgPSBbXTtcclxuICAgICAgICBmb3IgKHZhciBrIGluIG8pIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgaykpIGFyW2FyLmxlbmd0aF0gPSBrO1xyXG4gICAgICAgIHJldHVybiBhcjtcclxuICAgIH07XHJcbiAgICByZXR1cm4gb3duS2V5cyhvKTtcclxufTtcclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2ltcG9ydFN0YXIobW9kKSB7XHJcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xyXG4gICAgdmFyIHJlc3VsdCA9IHt9O1xyXG4gICAgaWYgKG1vZCAhPSBudWxsKSBmb3IgKHZhciBrID0gb3duS2V5cyhtb2QpLCBpID0gMDsgaSA8IGsubGVuZ3RoOyBpKyspIGlmIChrW2ldICE9PSBcImRlZmF1bHRcIikgX19jcmVhdGVCaW5kaW5nKHJlc3VsdCwgbW9kLCBrW2ldKTtcclxuICAgIF9fc2V0TW9kdWxlRGVmYXVsdChyZXN1bHQsIG1vZCk7XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnREZWZhdWx0KG1vZCkge1xyXG4gICAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XHJcbiAgICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBnZXR0ZXJcIik7XHJcbiAgICBpZiAodHlwZW9mIHN0YXRlID09PSBcImZ1bmN0aW9uXCIgPyByZWNlaXZlciAhPT0gc3RhdGUgfHwgIWYgOiAhc3RhdGUuaGFzKHJlY2VpdmVyKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCByZWFkIHByaXZhdGUgbWVtYmVyIGZyb20gYW4gb2JqZWN0IHdob3NlIGNsYXNzIGRpZCBub3QgZGVjbGFyZSBpdFwiKTtcclxuICAgIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcclxuICAgIGlmIChraW5kID09PSBcIm1cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgbWV0aG9kIGlzIG5vdCB3cml0YWJsZVwiKTtcclxuICAgIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIHNldHRlclwiKTtcclxuICAgIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XHJcbiAgICByZXR1cm4gKGtpbmQgPT09IFwiYVwiID8gZi5jYWxsKHJlY2VpdmVyLCB2YWx1ZSkgOiBmID8gZi52YWx1ZSA9IHZhbHVlIDogc3RhdGUuc2V0KHJlY2VpdmVyLCB2YWx1ZSkpLCB2YWx1ZTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRJbihzdGF0ZSwgcmVjZWl2ZXIpIHtcclxuICAgIGlmIChyZWNlaXZlciA9PT0gbnVsbCB8fCAodHlwZW9mIHJlY2VpdmVyICE9PSBcIm9iamVjdFwiICYmIHR5cGVvZiByZWNlaXZlciAhPT0gXCJmdW5jdGlvblwiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCB1c2UgJ2luJyBvcGVyYXRvciBvbiBub24tb2JqZWN0XCIpO1xyXG4gICAgcmV0dXJuIHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgPT09IHN0YXRlIDogc3RhdGUuaGFzKHJlY2VpdmVyKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fYWRkRGlzcG9zYWJsZVJlc291cmNlKGVudiwgdmFsdWUsIGFzeW5jKSB7XHJcbiAgICBpZiAodmFsdWUgIT09IG51bGwgJiYgdmFsdWUgIT09IHZvaWQgMCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHZhbHVlICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3QgZXhwZWN0ZWQuXCIpO1xyXG4gICAgICAgIHZhciBkaXNwb3NlLCBpbm5lcjtcclxuICAgICAgICBpZiAoYXN5bmMpIHtcclxuICAgICAgICAgICAgaWYgKCFTeW1ib2wuYXN5bmNEaXNwb3NlKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmFzeW5jRGlzcG9zZSBpcyBub3QgZGVmaW5lZC5cIik7XHJcbiAgICAgICAgICAgIGRpc3Bvc2UgPSB2YWx1ZVtTeW1ib2wuYXN5bmNEaXNwb3NlXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGRpc3Bvc2UgPT09IHZvaWQgMCkge1xyXG4gICAgICAgICAgICBpZiAoIVN5bWJvbC5kaXNwb3NlKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3ltYm9sLmRpc3Bvc2UgaXMgbm90IGRlZmluZWQuXCIpO1xyXG4gICAgICAgICAgICBkaXNwb3NlID0gdmFsdWVbU3ltYm9sLmRpc3Bvc2VdO1xyXG4gICAgICAgICAgICBpZiAoYXN5bmMpIGlubmVyID0gZGlzcG9zZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHR5cGVvZiBkaXNwb3NlICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3Qgbm90IGRpc3Bvc2FibGUuXCIpO1xyXG4gICAgICAgIGlmIChpbm5lcikgZGlzcG9zZSA9IGZ1bmN0aW9uKCkgeyB0cnkgeyBpbm5lci5jYWxsKHRoaXMpOyB9IGNhdGNoIChlKSB7IHJldHVybiBQcm9taXNlLnJlamVjdChlKTsgfSB9O1xyXG4gICAgICAgIGVudi5zdGFjay5wdXNoKHsgdmFsdWU6IHZhbHVlLCBkaXNwb3NlOiBkaXNwb3NlLCBhc3luYzogYXN5bmMgfSk7XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmIChhc3luYykge1xyXG4gICAgICAgIGVudi5zdGFjay5wdXNoKHsgYXN5bmM6IHRydWUgfSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdmFsdWU7XHJcblxyXG59XHJcblxyXG52YXIgX1N1cHByZXNzZWRFcnJvciA9IHR5cGVvZiBTdXBwcmVzc2VkRXJyb3IgPT09IFwiZnVuY3Rpb25cIiA/IFN1cHByZXNzZWRFcnJvciA6IGZ1bmN0aW9uIChlcnJvciwgc3VwcHJlc3NlZCwgbWVzc2FnZSkge1xyXG4gICAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7XHJcbiAgICByZXR1cm4gZS5uYW1lID0gXCJTdXBwcmVzc2VkRXJyb3JcIiwgZS5lcnJvciA9IGVycm9yLCBlLnN1cHByZXNzZWQgPSBzdXBwcmVzc2VkLCBlO1xyXG59O1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIF9fZGlzcG9zZVJlc291cmNlcyhlbnYpIHtcclxuICAgIGZ1bmN0aW9uIGZhaWwoZSkge1xyXG4gICAgICAgIGVudi5lcnJvciA9IGVudi5oYXNFcnJvciA/IG5ldyBfU3VwcHJlc3NlZEVycm9yKGUsIGVudi5lcnJvciwgXCJBbiBlcnJvciB3YXMgc3VwcHJlc3NlZCBkdXJpbmcgZGlzcG9zYWwuXCIpIDogZTtcclxuICAgICAgICBlbnYuaGFzRXJyb3IgPSB0cnVlO1xyXG4gICAgfVxyXG4gICAgdmFyIHIsIHMgPSAwO1xyXG4gICAgZnVuY3Rpb24gbmV4dCgpIHtcclxuICAgICAgICB3aGlsZSAociA9IGVudi5zdGFjay5wb3AoKSkge1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFyLmFzeW5jICYmIHMgPT09IDEpIHJldHVybiBzID0gMCwgZW52LnN0YWNrLnB1c2gociksIFByb21pc2UucmVzb2x2ZSgpLnRoZW4obmV4dCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoci5kaXNwb3NlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHIuZGlzcG9zZS5jYWxsKHIudmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChyLmFzeW5jKSByZXR1cm4gcyB8PSAyLCBQcm9taXNlLnJlc29sdmUocmVzdWx0KS50aGVuKG5leHQsIGZ1bmN0aW9uKGUpIHsgZmFpbChlKTsgcmV0dXJuIG5leHQoKTsgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbHNlIHMgfD0gMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgZmFpbChlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocyA9PT0gMSkgcmV0dXJuIGVudi5oYXNFcnJvciA/IFByb21pc2UucmVqZWN0KGVudi5lcnJvcikgOiBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgICAgICBpZiAoZW52Lmhhc0Vycm9yKSB0aHJvdyBlbnYuZXJyb3I7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbmV4dCgpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gX19yZXdyaXRlUmVsYXRpdmVJbXBvcnRFeHRlbnNpb24ocGF0aCwgcHJlc2VydmVKc3gpIHtcclxuICAgIGlmICh0eXBlb2YgcGF0aCA9PT0gXCJzdHJpbmdcIiAmJiAvXlxcLlxcLj9cXC8vLnRlc3QocGF0aCkpIHtcclxuICAgICAgICByZXR1cm4gcGF0aC5yZXBsYWNlKC9cXC4odHN4KSR8KCg/OlxcLmQpPykoKD86XFwuW14uL10rPyk/KVxcLihbY21dPyl0cyQvaSwgZnVuY3Rpb24gKG0sIHRzeCwgZCwgZXh0LCBjbSkge1xyXG4gICAgICAgICAgICByZXR1cm4gdHN4ID8gcHJlc2VydmVKc3ggPyBcIi5qc3hcIiA6IFwiLmpzXCIgOiBkICYmICghZXh0IHx8ICFjbSkgPyBtIDogKGQgKyBleHQgKyBcIi5cIiArIGNtLnRvTG93ZXJDYXNlKCkgKyBcImpzXCIpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHBhdGg7XHJcbn1cclxuXHJcbmV4cG9ydCBkZWZhdWx0IHtcclxuICAgIF9fZXh0ZW5kczogX19leHRlbmRzLFxyXG4gICAgX19hc3NpZ246IF9fYXNzaWduLFxyXG4gICAgX19yZXN0OiBfX3Jlc3QsXHJcbiAgICBfX2RlY29yYXRlOiBfX2RlY29yYXRlLFxyXG4gICAgX19wYXJhbTogX19wYXJhbSxcclxuICAgIF9fZXNEZWNvcmF0ZTogX19lc0RlY29yYXRlLFxyXG4gICAgX19ydW5Jbml0aWFsaXplcnM6IF9fcnVuSW5pdGlhbGl6ZXJzLFxyXG4gICAgX19wcm9wS2V5OiBfX3Byb3BLZXksXHJcbiAgICBfX3NldEZ1bmN0aW9uTmFtZTogX19zZXRGdW5jdGlvbk5hbWUsXHJcbiAgICBfX21ldGFkYXRhOiBfX21ldGFkYXRhLFxyXG4gICAgX19hd2FpdGVyOiBfX2F3YWl0ZXIsXHJcbiAgICBfX2dlbmVyYXRvcjogX19nZW5lcmF0b3IsXHJcbiAgICBfX2NyZWF0ZUJpbmRpbmc6IF9fY3JlYXRlQmluZGluZyxcclxuICAgIF9fZXhwb3J0U3RhcjogX19leHBvcnRTdGFyLFxyXG4gICAgX192YWx1ZXM6IF9fdmFsdWVzLFxyXG4gICAgX19yZWFkOiBfX3JlYWQsXHJcbiAgICBfX3NwcmVhZDogX19zcHJlYWQsXHJcbiAgICBfX3NwcmVhZEFycmF5czogX19zcHJlYWRBcnJheXMsXHJcbiAgICBfX3NwcmVhZEFycmF5OiBfX3NwcmVhZEFycmF5LFxyXG4gICAgX19hd2FpdDogX19hd2FpdCxcclxuICAgIF9fYXN5bmNHZW5lcmF0b3I6IF9fYXN5bmNHZW5lcmF0b3IsXHJcbiAgICBfX2FzeW5jRGVsZWdhdG9yOiBfX2FzeW5jRGVsZWdhdG9yLFxyXG4gICAgX19hc3luY1ZhbHVlczogX19hc3luY1ZhbHVlcyxcclxuICAgIF9fbWFrZVRlbXBsYXRlT2JqZWN0OiBfX21ha2VUZW1wbGF0ZU9iamVjdCxcclxuICAgIF9faW1wb3J0U3RhcjogX19pbXBvcnRTdGFyLFxyXG4gICAgX19pbXBvcnREZWZhdWx0OiBfX2ltcG9ydERlZmF1bHQsXHJcbiAgICBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0OiBfX2NsYXNzUHJpdmF0ZUZpZWxkR2V0LFxyXG4gICAgX19jbGFzc1ByaXZhdGVGaWVsZFNldDogX19jbGFzc1ByaXZhdGVGaWVsZFNldCxcclxuICAgIF9fY2xhc3NQcml2YXRlRmllbGRJbjogX19jbGFzc1ByaXZhdGVGaWVsZEluLFxyXG4gICAgX19hZGREaXNwb3NhYmxlUmVzb3VyY2U6IF9fYWRkRGlzcG9zYWJsZVJlc291cmNlLFxyXG4gICAgX19kaXNwb3NlUmVzb3VyY2VzOiBfX2Rpc3Bvc2VSZXNvdXJjZXMsXHJcbiAgICBfX3Jld3JpdGVSZWxhdGl2ZUltcG9ydEV4dGVuc2lvbjogX19yZXdyaXRlUmVsYXRpdmVJbXBvcnRFeHRlbnNpb24sXHJcbn07XHJcbiIsImltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHNmIH0gZnJvbSBcIi4uLy4uL3V0aWxzL3N0cmluZ3NcIjtcbmltcG9ydCB7IFJlZmxlY3Rpb24gfSBmcm9tIFwiQGRlY2FmLXRzL3JlZmxlY3Rpb25cIjtcbmltcG9ydCB7IFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBCYXNlIEltcGxlbWVudGF0aW9uIGZvciBWYWxpZGF0b3JzXG4gKiBAZGVzY3JpcHRpb24gUHJvdmlkZXMgdGhlIHVuZGVybHlpbmcgZnVuY3Rpb25hbGl0eSBmb3Ige0BsaW5rIFZhbGlkYXRvcn1zXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbGlkYXRpb25LZXkgdGhlIGtleSB0byByZWdpc3RlciB0aGUgdmFsaWRhdG9yIHVuZGVyXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNERUZBVUxUfVxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2FjY2VwdGVkVHlwZXNdIGRlZmluZXMgdGhlIHZhbHVlIHR5cGVzIHRoaXMgdmFsaWRhdG9yIGNhbiB2YWxpZGF0ZVxuICpcbiAqIEBjbGFzcyBWYWxpZGF0b3JcbiAqIEBhYnN0cmFjdFxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFZhbGlkYXRvcjxWIGV4dGVuZHMgVmFsaWRhdG9yT3B0aW9ucyA9IFZhbGlkYXRvck9wdGlvbnM+IHtcbiAgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nO1xuICByZWFkb25seSBhY2NlcHRlZFR5cGVzPzogc3RyaW5nW107XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuREVGQVVMVCxcbiAgICAuLi5hY2NlcHRlZFR5cGVzOiBzdHJpbmdbXVxuICApIHtcbiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuXG4gICAgaWYgKGFjY2VwdGVkVHlwZXMubGVuZ3RoKSB0aGlzLmFjY2VwdGVkVHlwZXMgPSBhY2NlcHRlZFR5cGVzO1xuICAgIGlmICh0aGlzLmFjY2VwdGVkVHlwZXMpXG4gICAgICB0aGlzLmhhc0Vycm9ycyA9IHRoaXMuY2hlY2tUeXBlQW5kSGFzRXJyb3JzKHRoaXMuaGFzRXJyb3JzLmJpbmQodGhpcykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IGJ1aWxkcyB0aGUgZXJyb3IgbWVzc2FnZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICAgKiBAcGFyYW0ge2FueVtdfSBhcmdzXG4gICAqIEBwcm90ZWN0ZWRcbiAgICovXG4gIHByb3RlY3RlZCBnZXRNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgICByZXR1cm4gc2YobWVzc2FnZSwgLi4uYXJncyk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIHR5cGVcbiAgICogQHBhcmFtIHthbnl9IHVuYm91bmRcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgY2hlY2tUeXBlQW5kSGFzRXJyb3JzKFxuICAgIHVuYm91bmQ6ICh2YWx1ZTogYW55LCAuLi5hcmdzOiBhbnlbXSkgPT4gc3RyaW5nIHwgdW5kZWZpbmVkXG4gICkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoXG4gICAgICB0aGlzOiBWYWxpZGF0b3IsXG4gICAgICB2YWx1ZTogYW55LFxuICAgICAgLi4uYXJnczogYW55W11cbiAgICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgIXRoaXMuYWNjZXB0ZWRUeXBlcylcbiAgICAgICAgcmV0dXJuIHVuYm91bmQodmFsdWUsIC4uLmFyZ3MpO1xuICAgICAgaWYgKCFSZWZsZWN0aW9uLmNoZWNrVHlwZXModmFsdWUsIHRoaXMuYWNjZXB0ZWRUeXBlcykpXG4gICAgICAgIHJldHVybiB0aGlzLmdldE1lc3NhZ2UoXG4gICAgICAgICAgREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5UWVBFLFxuICAgICAgICAgIHRoaXMuYWNjZXB0ZWRUeXBlcy5qb2luKFwiLCBcIiksXG4gICAgICAgICAgdHlwZW9mIHZhbHVlXG4gICAgICAgICk7XG4gICAgICByZXR1cm4gdW5ib3VuZCh2YWx1ZSwgLi4uYXJncyk7XG4gICAgfS5iaW5kKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFZhbGlkYXRlcyBhbiBhdHRyaWJ1dGVcbiAgICogQHBhcmFtIHthbnl9IHZhbHVlXG4gICAqIEBwYXJhbSB7VmFsaWRhdG9yT3B0aW9uc30gW29wdGlvbnNdIFZhbGlkYXRlIG9wdGlvbnMgZm9yIGN1c3RvbWl6aW5nIHRoZSBtb2RlbCB2YWxpZGF0aW9uIGJlaGF2aW9yXG4gICAqXG4gICAqIEBhYnN0cmFjdFxuICAgKlxuICAgKiBAc2VlIE1vZGVsI2hhc0Vycm9yc1xuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGhhc0Vycm9ycyh2YWx1ZTogYW55LCBvcHRpb25zPzogVik6IHN0cmluZyB8IHVuZGVmaW5lZDtcbn1cbiIsImltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gXCIuL1ZhbGlkYXRvclwiO1xuaW1wb3J0IHsgVmFsaWRhdGlvbiB9IGZyb20gXCIuLi9WYWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciB9IGZyb20gXCIuLi8uLi9tb2RlbC90eXBlc1wiO1xuaW1wb3J0IHsgVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IGFwcGx5LCBtZXRhZGF0YSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHsgVmFsaWRhdG9yRGVmaW5pdGlvbiB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IE1hcmtzIHRoZSBjbGFzcyBhcyBhIHZhbGlkYXRvciBmb3IgYSBjZXJ0YWluIGtleS5cbiAqIEBkZXNjcmlwdGlvbiBSZWdpc3RlcnMgdGhlIGNsYXNzIGluIHRoZSB7QGxpbmsgVmFsaWRhdGlvbn0gd2l0aCB0aGUgcHJvdmlkZWQga2V5XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGtleXMgdGhlIHZhbGlkYXRpb24ga2V5XG4gKlxuICogQGZ1bmN0aW9uIHZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0b3I8VCBleHRlbmRzIFZhbGlkYXRvcj4oLi4ua2V5czogc3RyaW5nW10pIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgICgob3JpZ2luYWw6IENvbnN0cnVjdG9yPFQ+KSA9PiB7XG4gICAgICBrZXlzLmZvckVhY2goKGs6IHN0cmluZykgPT4ge1xuICAgICAgICBWYWxpZGF0aW9uLnJlZ2lzdGVyKHtcbiAgICAgICAgICB2YWxpZGF0b3I6IG9yaWdpbmFsLFxuICAgICAgICAgIHZhbGlkYXRpb25LZXk6IGssXG4gICAgICAgICAgc2F2ZTogdHJ1ZSxcbiAgICAgICAgfSBhcyBWYWxpZGF0b3JEZWZpbml0aW9uKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIG9yaWdpbmFsO1xuICAgIH0pIGFzIENsYXNzRGVjb3JhdG9yLFxuICAgIG1ldGFkYXRhKFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLlZBTElEQVRPUiksIGtleXMpXG4gICk7XG59XG4iLCJpbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tIFwiLi9WYWxpZGF0b3JcIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyB2YWxpZGF0b3IgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBEYXRlVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IERhdGUgVmFsaWRhdG9yXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNEQVRFfVxuICpcbiAqIEBjbGFzcyBEYXRlVmFsaWRhdG9yXG4gKiBAZXh0ZW5kcyBWYWxpZGF0b3JcbiAqXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5AdmFsaWRhdG9yKFZhbGlkYXRpb25LZXlzLkRBVEUpXG5leHBvcnQgY2xhc3MgRGF0ZVZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvcjxEYXRlVmFsaWRhdG9yT3B0aW9ucz4ge1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLkRBVEUpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBOdW1iZXIubmFtZSwgRGF0ZS5uYW1lLCBTdHJpbmcubmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIGEgbW9kZWxcbiAgICpcbiAgICogQHBhcmFtIHtEYXRlIHwgc3RyaW5nfSB2YWx1ZVxuICAgKiBAcGFyYW0ge0RhdGVWYWxpZGF0b3JPcHRpb25zfSBbb3B0aW9uc11cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKlxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHNlZSBWYWxpZGF0b3IjaGFzRXJyb3JzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKFxuICAgIHZhbHVlOiBEYXRlIHwgc3RyaW5nLFxuICAgIG9wdGlvbnM6IERhdGVWYWxpZGF0b3JPcHRpb25zID0ge31cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikgdmFsdWUgPSBuZXcgRGF0ZSh2YWx1ZSk7XG5cbiAgICBpZiAoTnVtYmVyLmlzTmFOKHZhbHVlLmdldERhdGUoKSkpIHtcbiAgICAgIGNvbnN0IHsgbWVzc2FnZSA9IFwiXCIgfSA9IG9wdGlvbnM7XG4gICAgICByZXR1cm4gdGhpcy5nZXRNZXNzYWdlKG1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlKTtcbiAgICB9XG4gIH1cbn1cbiIsImltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gXCIuL1ZhbGlkYXRvclwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHZhbGlkYXRvciB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbmV4cG9ydCBjb25zdCByZWdleHBQYXJzZXI6IFJlZ0V4cCA9IG5ldyBSZWdFeHAoXCJeLyguKykvKFtnaW11c10qKSRcIik7XG5cbi8qKlxuICogQHN1bW1hcnkgUGF0dGVybiBWYWxpZGF0b3JcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW2tleV0gZGVmYXVsdHMgdG8ge0BsaW5rIFZhbGlkYXRpb25LZXlzI1BBVFRFUk59XG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIGRlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI1BBVFRFUk59XG4gKlxuICogQGNsYXNzIFBhdHRlcm5WYWxpZGF0b3JcbiAqIEBleHRlbmRzIFZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVmFsaWRhdGlvbktleXMuUEFUVEVSTilcbmV4cG9ydCBjbGFzcyBQYXR0ZXJuVmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yPFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zPiB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUEFUVEVSTikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIFwic3RyaW5nXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IHBhcnNlcyBhbmQgdmFsaWRhdGVzIGEgcGF0dGVyblxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcGF0dGVyblxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBnZXRQYXR0ZXJuKHBhdHRlcm46IHN0cmluZyk6IFJlZ0V4cCB7XG4gICAgaWYgKCFyZWdleHBQYXJzZXIudGVzdChwYXR0ZXJuKSkgcmV0dXJuIG5ldyBSZWdFeHAocGF0dGVybik7XG4gICAgY29uc3QgbWF0Y2g6IGFueSA9IHBhdHRlcm4ubWF0Y2gocmVnZXhwUGFyc2VyKTtcbiAgICByZXR1cm4gbmV3IFJlZ0V4cChtYXRjaFsxXSwgbWF0Y2hbMl0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFZhbGlkYXRlcyBhIE1vZGVsXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1BhdHRlcm5WYWxpZGF0b3JPcHRpb25zfSBvcHRpb25zXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAgICpcbiAgICogQG92ZXJyaWRlXG4gICAqXG4gICAqIEBzZWUgVmFsaWRhdG9yI2hhc0Vycm9yc1xuICAgKi9cbiAgcHVibGljIGhhc0Vycm9ycyhcbiAgICB2YWx1ZTogc3RyaW5nLFxuICAgIG9wdGlvbnM6IFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuO1xuXG4gICAgbGV0IHsgcGF0dGVybiB9ID0gb3B0aW9ucztcbiAgICBpZiAoIXBhdHRlcm4pIHRocm93IG5ldyBFcnJvcihcIk1pc3NpbmcgUGF0dGVyblwiKTtcbiAgICBwYXR0ZXJuID0gdHlwZW9mIHBhdHRlcm4gPT09IFwic3RyaW5nXCIgPyB0aGlzLmdldFBhdHRlcm4ocGF0dGVybikgOiBwYXR0ZXJuO1xuICAgIHBhdHRlcm4ubGFzdEluZGV4ID0gMDsgLy8gcmVzZXRzIHBhdHRlcm4gcG9zaXRpb24gZm9yIHJlcGVhdCB2YWxpZGF0aW9uIHJlcXVlc3RzXG4gICAgcmV0dXJuICFwYXR0ZXJuLnRlc3QodmFsdWUpXG4gICAgICA/IHRoaXMuZ2V0TWVzc2FnZShvcHRpb25zLm1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cbn1cbiIsImltcG9ydCB7XG4gIERFRkFVTFRfRVJST1JfTUVTU0FHRVMsXG4gIERFRkFVTFRfUEFUVEVSTlMsXG4gIFZhbGlkYXRpb25LZXlzLFxufSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IFBhdHRlcm5WYWxpZGF0b3IgfSBmcm9tIFwiLi9QYXR0ZXJuVmFsaWRhdG9yXCI7XG5pbXBvcnQgeyB2YWxpZGF0b3IgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBQYXR0ZXJuVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IEVtYWlsIFZhbGlkYXRvclxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gZGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMjRU1BSUx9XG4gKlxuICogQGNsYXNzIEVtYWlsVmFsaWRhdG9yXG4gKiBAZXh0ZW5kcyBQYXR0ZXJuVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5FTUFJTClcbmV4cG9ydCBjbGFzcyBFbWFpbFZhbGlkYXRvciBleHRlbmRzIFBhdHRlcm5WYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLkVNQUlMKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIGEgbW9kZWxcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAqIEBwYXJhbSB7UGF0dGVyblZhbGlkYXRvck9wdGlvbnN9IFtvcHRpb25zXVxuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqXG4gICAqIEBvdmVycmlkZVxuICAgKlxuICAgKiBAc2VlIFZhbGlkYXRvciNoYXNFcnJvcnNcbiAgICovXG4gIHB1YmxpYyBoYXNFcnJvcnMoXG4gICAgdmFsdWU6IHN0cmluZyxcbiAgICBvcHRpb25zOiBQYXR0ZXJuVmFsaWRhdG9yT3B0aW9ucyA9IHt9XG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHN1cGVyLmhhc0Vycm9ycyh2YWx1ZSwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHBhdHRlcm46IG9wdGlvbnM/LnBhdHRlcm4gfHwgREVGQVVMVF9QQVRURVJOUy5FTUFJTCxcbiAgICB9KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSBcIi4vVmFsaWRhdG9yXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VSUk9SX01FU1NBR0VTLCBWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgdmFsaWRhdG9yIH0gZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTGlzdFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBMaXN0IFZhbGlkYXRvclxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gZGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMjTElTVH1cbiAqXG4gKiBAY2xhc3MgTGlzdFZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5MSVNUKVxuZXhwb3J0IGNsYXNzIExpc3RWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3I8TGlzdFZhbGlkYXRvck9wdGlvbnM+IHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5MSVNUKSB7XG4gICAgc3VwZXIobWVzc2FnZSwgQXJyYXkubmFtZSwgU2V0Lm5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFZhbGlkYXRlcyBhIG1vZGVsXG4gICAqXG4gICAqIEBwYXJhbSB7YW55W10gfCBTZXQ8YW55Pn0gdmFsdWVcbiAgICogQHBhcmFtIHtMaXN0VmFsaWRhdG9yT3B0aW9uc30gb3B0aW9uc1xuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqXG4gICAqIEBvdmVycmlkZVxuICAgKlxuICAgKiBAc2VlIFZhbGlkYXRvciNoYXNFcnJvcnNcbiAgICovXG4gIGhhc0Vycm9ycyhcbiAgICB2YWx1ZTogYW55W10gfCBTZXQ8YW55PixcbiAgICBvcHRpb25zOiBMaXN0VmFsaWRhdG9yT3B0aW9uc1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICghdmFsdWUgfHwgKEFycmF5LmlzQXJyYXkodmFsdWUpID8gIXZhbHVlLmxlbmd0aCA6ICF2YWx1ZS5zaXplKSkgcmV0dXJuO1xuXG4gICAgY29uc3QgY2xhenogPSBBcnJheS5pc0FycmF5KG9wdGlvbnMuY2xhenopXG4gICAgICA/IG9wdGlvbnMuY2xhenpcbiAgICAgIDogW29wdGlvbnMuY2xhenpdO1xuICAgIGxldCB2YWw6IGFueSxcbiAgICAgIGlzVmFsaWQgPSB0cnVlO1xuICAgIGZvciAoXG4gICAgICBsZXQgaSA9IDA7XG4gICAgICBpIDwgKEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubGVuZ3RoIDogdmFsdWUuc2l6ZSk7XG4gICAgICBpKytcbiAgICApIHtcbiAgICAgIHZhbCA9ICh2YWx1ZSBhcyBhbnkpW2ldO1xuICAgICAgc3dpdGNoICh0eXBlb2YgdmFsKSB7XG4gICAgICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgaXNWYWxpZCA9IGNsYXp6LmluY2x1ZGVzKCh2YWwgYXMgb2JqZWN0KS5jb25zdHJ1Y3Rvcj8ubmFtZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgaXNWYWxpZCA9IGNsYXp6LnNvbWUoKGM6IHN0cmluZykgPT4gdHlwZW9mIHZhbCA9PT0gYy50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaXNWYWxpZFxuICAgICAgPyB1bmRlZmluZWRcbiAgICAgIDogdGhpcy5nZXRNZXNzYWdlKG9wdGlvbnMubWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UsIGNsYXp6KTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSBcIi4vVmFsaWRhdG9yXCI7XG5pbXBvcnQgeyBWYWxpZGF0aW9uS2V5cywgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgdmFsaWRhdG9yIH0gZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTWF4TGVuZ3RoVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IE1heGltdW0gTGVuZ3RoIFZhbGlkYXRvclxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRlcyBzdHJpbmdzIGFuZCBBcnJheXMgb24gdGhlaXIgbWF4aW11bSBsZW5ndGhcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIGRlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI01BWF9MRU5HVEh9XG4gKlxuICogQGNsYXNzIE1pbkxlbmd0aFZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5NQVhfTEVOR1RIKVxuZXhwb3J0IGNsYXNzIE1heExlbmd0aFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvcjxNYXhMZW5ndGhWYWxpZGF0b3JPcHRpb25zPiB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuTUFYX0xFTkdUSCkge1xuICAgIHN1cGVyKG1lc3NhZ2UsIFN0cmluZy5uYW1lLCBBcnJheS5uYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSBtb2RlbFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICogQHBhcmFtIHtNYXhMZW5ndGhWYWxpZGF0b3JPcHRpb25zfSBvcHRpb25zXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAgICpcbiAgICogQG92ZXJyaWRlXG4gICAqXG4gICAqIEBzZWUgVmFsaWRhdG9yI2hhc0Vycm9yc1xuICAgKi9cbiAgcHVibGljIGhhc0Vycm9ycyhcbiAgICB2YWx1ZTogc3RyaW5nIHwgYW55W10sXG4gICAgb3B0aW9uczogTWF4TGVuZ3RoVmFsaWRhdG9yT3B0aW9uc1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHJldHVybjtcbiAgICByZXR1cm4gdmFsdWUubGVuZ3RoID4gb3B0aW9ucy5tYXhsZW5ndGhcbiAgICAgID8gdGhpcy5nZXRNZXNzYWdlKG9wdGlvbnMubWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UsIG9wdGlvbnMubWF4bGVuZ3RoKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cbn1cbiIsImltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gXCIuL1ZhbGlkYXRvclwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHZhbGlkYXRvciB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IE1heFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBNYXggVmFsaWRhdG9yXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNNQVh9XG4gKlxuICogQGNsYXNzIE1heFZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5NQVgpXG5leHBvcnQgY2xhc3MgTWF4VmFsaWRhdG9yIGV4dGVuZHMgVmFsaWRhdG9yPE1heFZhbGlkYXRvck9wdGlvbnM+IHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5NQVgpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBcIm51bWJlclwiLCBcIkRhdGVcIiwgXCJzdHJpbmdcIik7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIGEgTW9kZWxcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAqIEBwYXJhbSB7TWF4VmFsaWRhdG9yT3B0aW9uc30gb3B0aW9uc1xuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqXG4gICAqIEBvdmVycmlkZVxuICAgKlxuICAgKiBAc2VlIFZhbGlkYXRvciNoYXNFcnJvcnNcbiAgICovXG4gIHB1YmxpYyBoYXNFcnJvcnMoXG4gICAgdmFsdWU6IG51bWJlciB8IERhdGUgfCBzdHJpbmcsXG4gICAgb3B0aW9uczogTWF4VmFsaWRhdG9yT3B0aW9uc1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHJldHVybjtcblxuICAgIGxldCB7IG1heCB9ID0gb3B0aW9ucztcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlICYmICEobWF4IGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgIG1heCA9IG5ldyBEYXRlKG1heCk7XG4gICAgICBpZiAoTnVtYmVyLmlzTmFOKG1heC5nZXREYXRlKCkpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIE1heCBwYXJhbSBkZWZpbmVkXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZSA+IG1heFxuICAgICAgPyB0aGlzLmdldE1lc3NhZ2Uob3B0aW9ucy5tZXNzYWdlIHx8IHRoaXMubWVzc2FnZSwgbWF4KVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIH1cbn1cbiIsImltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gXCIuL1ZhbGlkYXRvclwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHZhbGlkYXRvciB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IE1pbkxlbmd0aFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBNaW5pbXVtIExlbmd0aCBWYWxpZGF0b3JcbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0ZXMgc3RyaW5ncyBhbmQgQXJyYXlzIG9uIHRoZWlyIG1pbmltdW0gbGVuZ3RoXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNNSU5fTEVOR1RIfVxuICpcbiAqIEBjbGFzcyBNaW5MZW5ndGhWYWxpZGF0b3JcbiAqIEBleHRlbmRzIFZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVmFsaWRhdGlvbktleXMuTUlOX0xFTkdUSClcbmV4cG9ydCBjbGFzcyBNaW5MZW5ndGhWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3I8TWluTGVuZ3RoVmFsaWRhdG9yT3B0aW9ucz4ge1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLk1JTl9MRU5HVEgpIHtcbiAgICBzdXBlcihtZXNzYWdlLCBTdHJpbmcubmFtZSwgQXJyYXkubmFtZSk7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmcgfCBBcnJheX0gdmFsdWVcbiAgICogQHBhcmFtIHtNaW5MZW5ndGhWYWxpZGF0b3JPcHRpb25zfSBvcHRpb25zXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAgICpcbiAgICogQG1lbWJlck9mIE1pbkxlbmd0aFZhbGlkYXRvclxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHNlZSBWYWxpZGF0b3IjaGFzRXJyb3JzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKFxuICAgIHZhbHVlOiBzdHJpbmcgfCBhbnlbXSxcbiAgICBvcHRpb25zOiBNaW5MZW5ndGhWYWxpZGF0b3JPcHRpb25zXG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJ1bmRlZmluZWRcIikgcmV0dXJuO1xuICAgIHJldHVybiB2YWx1ZS5sZW5ndGggPCBvcHRpb25zLm1pbmxlbmd0aFxuICAgICAgPyB0aGlzLmdldE1lc3NhZ2Uob3B0aW9ucy5tZXNzYWdlIHx8IHRoaXMubWVzc2FnZSwgb3B0aW9ucy5taW5sZW5ndGgpXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSBcIi4vVmFsaWRhdG9yXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VSUk9SX01FU1NBR0VTLCBWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgdmFsaWRhdG9yIH0gZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTWluVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IE1pbiBWYWxpZGF0b3JcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIGRlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI01JTn1cbiAqXG4gKiBAY2xhc3MgTWluVmFsaWRhdG9yXG4gKiBAZXh0ZW5kcyBWYWxpZGF0b3JcbiAqXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5AdmFsaWRhdG9yKFZhbGlkYXRpb25LZXlzLk1JTilcbmV4cG9ydCBjbGFzcyBNaW5WYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3I8TWluVmFsaWRhdG9yT3B0aW9ucz4ge1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLk1JTikge1xuICAgIHN1cGVyKG1lc3NhZ2UsIFwibnVtYmVyXCIsIFwiRGF0ZVwiLCBcInN0cmluZ1wiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgTW9kZWxcbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAqIEBwYXJhbSB7TWF4VmFsaWRhdG9yT3B0aW9uc30gb3B0aW9uc1xuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqXG4gICAqIEBvdmVycmlkZVxuICAgKlxuICAgKiBAc2VlIFZhbGlkYXRvciNoYXNFcnJvcnNcbiAgICovXG4gIHB1YmxpYyBoYXNFcnJvcnMoXG4gICAgdmFsdWU6IG51bWJlciB8IERhdGUgfCBzdHJpbmcsXG4gICAgb3B0aW9uczogTWluVmFsaWRhdG9yT3B0aW9uc1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHJldHVybjtcblxuICAgIGxldCB7IG1pbiB9ID0gb3B0aW9ucztcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlICYmICEobWluIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgIG1pbiA9IG5ldyBEYXRlKG1pbik7XG4gICAgICBpZiAoTnVtYmVyLmlzTmFOKG1pbi5nZXREYXRlKCkpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIE1pbiBwYXJhbSBkZWZpbmVkXCIpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUgPCBtaW5cbiAgICAgID8gdGhpcy5nZXRNZXNzYWdlKG9wdGlvbnMubWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UsIG1pbilcbiAgICAgIDogdW5kZWZpbmVkO1xuICB9XG59XG4iLCJpbXBvcnQgeyBQYXR0ZXJuVmFsaWRhdG9yIH0gZnJvbSBcIi4vUGF0dGVyblZhbGlkYXRvclwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHZhbGlkYXRvciB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgSGFuZGxlcyBQYXNzd29yZCBWYWxpZGF0aW9uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFtlcnJvck1lc3NhZ2VdIGRlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI1BBU1NXT1JEfVxuICpcbiAqIEBjbGFzcyBQYXNzd29yZFZhbGlkYXRvclxuICogQGV4dGVuZHMgUGF0dGVyblZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVmFsaWRhdGlvbktleXMuUEFTU1dPUkQpXG5leHBvcnQgY2xhc3MgUGFzc3dvcmRWYWxpZGF0b3IgZXh0ZW5kcyBQYXR0ZXJuVmFsaWRhdG9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZSA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUEFTU1dPUkQpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSBtb2RlbFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICogQHBhcmFtIHtQYXR0ZXJuVmFsaWRhdG9yT3B0aW9uc30gW29wdGlvbnM9e31dXG4gICAqXG4gICAqIEByZXR1cm4ge3N0cmluZyB8IHVuZGVmaW5lZH1cbiAgICpcbiAgICogQG92ZXJyaWRlXG4gICAqXG4gICAqIEBzZWUgUGF0dGVyblZhbGlkYXRvciNoYXNFcnJvcnNcbiAgICovXG4gIHB1YmxpYyBoYXNFcnJvcnMoXG4gICAgdmFsdWU6IHN0cmluZyxcbiAgICBvcHRpb25zOiBQYXR0ZXJuVmFsaWRhdG9yT3B0aW9ucyA9IHt9XG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHN1cGVyLmhhc0Vycm9ycyh2YWx1ZSwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG1lc3NhZ2U6IG9wdGlvbnMubWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UsXG4gICAgfSk7XG4gIH1cbn1cbiIsImltcG9ydCB7IFZhbGlkYXRvciB9IGZyb20gXCIuL1ZhbGlkYXRvclwiO1xuaW1wb3J0IHsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUywgVmFsaWRhdGlvbktleXMgfSBmcm9tIFwiLi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHZhbGlkYXRvciB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tIFwiLi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAc3VtbWFyeSBSZXF1aXJlZCBWYWxpZGF0b3JcbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIGRlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI1JFUVVJUkVEfVxuICpcbiAqIEBjbGFzcyBSZXF1aXJlZFZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5SRVFVSVJFRClcbmV4cG9ydCBjbGFzcyBSZXF1aXJlZFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUkVRVUlSRUQpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSBtb2RlbFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICogQHBhcmFtIHtWYWxpZGF0b3JPcHRpb25zfSBbb3B0aW9ucz17fV1cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKlxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHNlZSBWYWxpZGF0b3IjaGFzRXJyb3JzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKFxuICAgIHZhbHVlOiBhbnksXG4gICAgb3B0aW9uczogVmFsaWRhdG9yT3B0aW9ucyA9IHt9XG4gICk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgc3dpdGNoICh0eXBlb2YgdmFsdWUpIHtcbiAgICAgIGNhc2UgXCJib29sZWFuXCI6XG4gICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCJcbiAgICAgICAgICA/IHRoaXMuZ2V0TWVzc2FnZShvcHRpb25zLm1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuICF2YWx1ZVxuICAgICAgICAgID8gdGhpcy5nZXRNZXNzYWdlKG9wdGlvbnMubWVzc2FnZSB8fCB0aGlzLm1lc3NhZ2UpXG4gICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG59XG4iLCJpbXBvcnQgeyBWYWxpZGF0b3IgfSBmcm9tIFwiLi9WYWxpZGF0b3JcIjtcbmltcG9ydCB7IERFRkFVTFRfRVJST1JfTUVTU0FHRVMsIFZhbGlkYXRpb25LZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyB2YWxpZGF0b3IgfSBmcm9tIFwiLi9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBTdGVwVmFsaWRhdG9yT3B0aW9ucyB9IGZyb20gXCIuLi90eXBlc1wiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFN0ZXAgVmFsaWRhdG9yXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNTVEVQfVxuICpcbiAqIEBjbGFzcyBTdGVwVmFsaWRhdG9yXG4gKiBAZXh0ZW5kcyBWYWxpZGF0b3JcbiAqXG4gKiBAY2F0ZWdvcnkgVmFsaWRhdG9yc1xuICovXG5AdmFsaWRhdG9yKFZhbGlkYXRpb25LZXlzLlNURVApXG5leHBvcnQgY2xhc3MgU3RlcFZhbGlkYXRvciBleHRlbmRzIFZhbGlkYXRvcjxTdGVwVmFsaWRhdG9yT3B0aW9ucz4ge1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlNURVApIHtcbiAgICBzdXBlcihtZXNzYWdlLCBcIm51bWJlclwiLCBcInN0cmluZ1wiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAc3VtbWFyeSBWYWxpZGF0ZXMgYSBtb2RlbFxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHN0ZXBcbiAgICogQHBhcmFtIHtTdGVwVmFsaWRhdG9yT3B0aW9uc30gb3B0aW9uc1xuICAgKlxuICAgKiBAcmV0dXJuIHtzdHJpbmcgfCB1bmRlZmluZWR9XG4gICAqXG4gICAqIEBvdmVycmlkZVxuICAgKlxuICAgKiBAc2VlIFZhbGlkYXRvciNoYXNFcnJvcnNcbiAgICovXG4gIHB1YmxpYyBoYXNFcnJvcnMoXG4gICAgdmFsdWU6IG51bWJlciB8IHN0cmluZyxcbiAgICBvcHRpb25zOiBTdGVwVmFsaWRhdG9yT3B0aW9uc1xuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHJldHVybjtcbiAgICByZXR1cm4gTnVtYmVyKHZhbHVlKSAlIE51bWJlcihvcHRpb25zLnN0ZXApICE9PSAwXG4gICAgICA/IHRoaXMuZ2V0TWVzc2FnZShvcHRpb25zLm1lc3NhZ2UgfHwgdGhpcy5tZXNzYWdlLCBvcHRpb25zLnN0ZXApXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgfVxufVxuIiwiaW1wb3J0IHsgVmFsaWRhdG9yIH0gZnJvbSBcIi4vVmFsaWRhdG9yXCI7XG5pbXBvcnQgeyBERUZBVUxUX0VSUk9SX01FU1NBR0VTLCBWYWxpZGF0aW9uS2V5cyB9IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgdmFsaWRhdG9yIH0gZnJvbSBcIi4vZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgVmFsaWRhdGlvbiB9IGZyb20gXCIuLi9WYWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBUeXBlVmFsaWRhdG9yT3B0aW9ucywgVmFsaWRhdG9yRGVmaW5pdGlvbiB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgTW9kZWxLZXlzIH0gZnJvbSBcIi4uLy4uL3V0aWxzL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUmVmbGVjdGlvbiB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IFJlcXVpcmVkIFZhbGlkYXRvclxuICpcbiAqIEBjbGFzcyBSZXF1aXJlZFZhbGlkYXRvclxuICogQGV4dGVuZHMgVmFsaWRhdG9yXG4gKlxuICogQGNhdGVnb3J5IFZhbGlkYXRvcnNcbiAqL1xuQHZhbGlkYXRvcihWYWxpZGF0aW9uS2V5cy5UWVBFKVxuZXhwb3J0IGNsYXNzIFR5cGVWYWxpZGF0b3IgZXh0ZW5kcyBWYWxpZGF0b3I8VHlwZVZhbGlkYXRvck9wdGlvbnM+IHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5UWVBFKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogQHN1bW1hcnkgVmFsaWRhdGVzIGEgbW9kZWxcbiAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAqIEBwYXJhbSB7VHlwZVZhbGlkYXRvck9wdGlvbnN9IG9wdGlvbnNcbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKlxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHNlZSBWYWxpZGF0b3IjaGFzRXJyb3JzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKFxuICAgIHZhbHVlOiBhbnksXG4gICAgb3B0aW9uczogVHlwZVZhbGlkYXRvck9wdGlvbnNcbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuOyAvLyBEb24ndCB0cnkgYW5kIGVuZm9yY2UgdHlwZSBpZiB1bmRlZmluZWRcbiAgICBjb25zdCB7IHR5cGVzLCBtZXNzYWdlIH0gPSBvcHRpb25zO1xuICAgIGlmICghUmVmbGVjdGlvbi5ldmFsdWF0ZURlc2lnblR5cGVzKHZhbHVlLCB0eXBlcykpXG4gICAgICByZXR1cm4gdGhpcy5nZXRNZXNzYWdlKFxuICAgICAgICBtZXNzYWdlIHx8IHRoaXMubWVzc2FnZSxcbiAgICAgICAgdHlwZW9mIHR5cGVzID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgPyB0eXBlc1xuICAgICAgICAgIDogQXJyYXkuaXNBcnJheSh0eXBlcylcbiAgICAgICAgICAgID8gdHlwZXMuam9pbihcIiwgXCIpXG4gICAgICAgICAgICA6IHR5cGVzLm5hbWUsXG4gICAgICAgIHR5cGVvZiB2YWx1ZVxuICAgICAgKTtcbiAgfVxufVxuXG5WYWxpZGF0aW9uLnJlZ2lzdGVyKHtcbiAgdmFsaWRhdG9yOiBUeXBlVmFsaWRhdG9yLFxuICB2YWxpZGF0aW9uS2V5OiBNb2RlbEtleXMuVFlQRSxcbiAgc2F2ZTogZmFsc2UsXG59IGFzIFZhbGlkYXRvckRlZmluaXRpb24pO1xuIiwiaW1wb3J0IHtcbiAgVmFsaWRhdGlvbktleXMsXG4gIERFRkFVTFRfRVJST1JfTUVTU0FHRVMsXG4gIERFRkFVTFRfUEFUVEVSTlMsXG59IGZyb20gXCIuL2NvbnN0YW50c1wiO1xuaW1wb3J0IHsgUGF0dGVyblZhbGlkYXRvciB9IGZyb20gXCIuL1BhdHRlcm5WYWxpZGF0b3JcIjtcbmltcG9ydCB7IHZhbGlkYXRvciB9IGZyb20gXCIuL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IFBhdHRlcm5WYWxpZGF0b3JPcHRpb25zIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgVVJMIFZhbGlkYXRvclxuICogQGRlc2NyaXB0aW9uIFBhdHRlcm4gZnJvbSB7QGxpbmsgaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vZHBlcmluaS83MjkyOTR9XG4gKlxuICogQGNsYXNzIFVSTFZhbGlkYXRvclxuICogQGV4dGVuZHMgUGF0dGVyblZhbGlkYXRvclxuICpcbiAqIEBjYXRlZ29yeSBWYWxpZGF0b3JzXG4gKi9cbkB2YWxpZGF0b3IoVmFsaWRhdGlvbktleXMuVVJMKVxuZXhwb3J0IGNsYXNzIFVSTFZhbGlkYXRvciBleHRlbmRzIFBhdHRlcm5WYWxpZGF0b3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlVSTCkge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBzdW1tYXJ5IFZhbGlkYXRlcyBhIG1vZGVsXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1BhdHRlcm5WYWxpZGF0b3JPcHRpb25zfSBbb3B0aW9ucz17fV1cbiAgICpcbiAgICogQHJldHVybiB7c3RyaW5nIHwgdW5kZWZpbmVkfVxuICAgKlxuICAgKiBAb3ZlcnJpZGVcbiAgICpcbiAgICogQHNlZSBWYWxpZGF0b3IjaGFzRXJyb3JzXG4gICAqL1xuICBwdWJsaWMgaGFzRXJyb3JzKFxuICAgIHZhbHVlOiBzdHJpbmcsXG4gICAgb3B0aW9uczogUGF0dGVyblZhbGlkYXRvck9wdGlvbnMgPSB7fVxuICApOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBzdXBlci5oYXNFcnJvcnModmFsdWUsIHtcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgICBwYXR0ZXJuOiBvcHRpb25zLnBhdHRlcm4gfHwgREVGQVVMVF9QQVRURVJOUy5VUkwsXG4gICAgfSk7XG4gIH1cbn1cbiIsImltcG9ydCBcInJlZmxlY3QtbWV0YWRhdGFcIjtcbmltcG9ydCB7IFZhbGlkYXRpb25NZXRhZGF0YSB9IGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQge1xuICBERUZBVUxUX0VSUk9SX01FU1NBR0VTLFxuICBERUZBVUxUX1BBVFRFUk5TLFxuICBWYWxpZGF0aW9uS2V5cyxcbn0gZnJvbSBcIi4vVmFsaWRhdG9ycy9jb25zdGFudHNcIjtcbmltcG9ydCB7IHNmIH0gZnJvbSBcIi4uL3V0aWxzL3N0cmluZ3NcIjtcbmltcG9ydCB7IE1vZGVsQ29uc3RydWN0b3IgfSBmcm9tIFwiLi4vbW9kZWwvdHlwZXNcIjtcbmltcG9ydCB7IHBhcnNlRGF0ZSB9IGZyb20gXCIuLi91dGlscy9kYXRlc1wiO1xuaW1wb3J0IHsgcHJvcE1ldGFkYXRhIH0gZnJvbSBcIi4uL3V0aWxzL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IFZhbGlkYXRpb24gfSBmcm9tIFwiLi9WYWxpZGF0aW9uXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgTWFya3MgdGhlIHByb3BlcnR5IGFzIHJlcXVpcmVkLlxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRvcnMgdG8gdmFsaWRhdGUgYSBkZWNvcmF0ZWQgcHJvcGVydHkgbXVzdCB1c2Uga2V5IHtAbGluayBWYWxpZGF0aW9uS2V5cyNSRVFVSVJFRH1cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNSRVFVSVJFRH1cbiAqXG4gKiBAZnVuY3Rpb24gcmVxdWlyZWRcbiAqXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZWQobWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5SRVFVSVJFRCkge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT4oXG4gICAgVmFsaWRhdGlvbi5rZXkoVmFsaWRhdGlvbktleXMuUkVRVUlSRUQpLFxuICAgIHtcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgfVxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBtaW5pbXVtIHZhbHVlIGZvciB0aGUgcHJvcGVydHlcbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0b3JzIHRvIHZhbGlkYXRlIGEgZGVjb3JhdGVkIHByb3BlcnR5IG11c3QgdXNlIGtleSB7QGxpbmsgVmFsaWRhdGlvbktleXMjTUlOfVxuICpcbiAqIEBwYXJhbSB7bnVtYmVyIHwgRGF0ZX0gdmFsdWVcbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gdGhlIGVycm9yIG1lc3NhZ2UuIERlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI01JTn1cbiAqXG4gKiBAZnVuY3Rpb24gbWluXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLkRlY29yYXRvcnMuVmFsaWRhdGlvblxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbihcbiAgdmFsdWU6IG51bWJlciB8IERhdGUgfCBzdHJpbmcsXG4gIG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuTUlOXG4pIHtcbiAgcmV0dXJuIHByb3BNZXRhZGF0YTxWYWxpZGF0aW9uTWV0YWRhdGE+KFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLk1JTiksIHtcbiAgICBbVmFsaWRhdGlvbktleXMuTUlOXTogdmFsdWUsXG4gICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICB0eXBlczogW051bWJlci5uYW1lLCBEYXRlLm5hbWVdLFxuICB9KTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBEZWZpbmVzIGEgbWF4aW11bSB2YWx1ZSBmb3IgdGhlIHByb3BlcnR5XG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdG9ycyB0byB2YWxpZGF0ZSBhIGRlY29yYXRlZCBwcm9wZXJ0eSBtdXN0IHVzZSBrZXkge0BsaW5rIFZhbGlkYXRpb25LZXlzI01BWH1cbiAqXG4gKiBAcGFyYW0ge251bWJlciB8IERhdGV9IHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNNQVh9XG4gKlxuICogQGZ1bmN0aW9uIG1heFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5EZWNvcmF0b3JzLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXgoXG4gIHZhbHVlOiBudW1iZXIgfCBEYXRlIHwgc3RyaW5nLFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLk1BWFxuKSB7XG4gIHJldHVybiBwcm9wTWV0YWRhdGE8VmFsaWRhdGlvbk1ldGFkYXRhPihWYWxpZGF0aW9uLmtleShWYWxpZGF0aW9uS2V5cy5NQVgpLCB7XG4gICAgW1ZhbGlkYXRpb25LZXlzLk1BWF06IHZhbHVlLFxuICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgdHlwZXM6IFtOdW1iZXIubmFtZSwgRGF0ZS5uYW1lXSxcbiAgfSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIHN0ZXAgdmFsdWUgZm9yIHRoZSBwcm9wZXJ0eVxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRvcnMgdG8gdmFsaWRhdGUgYSBkZWNvcmF0ZWQgcHJvcGVydHkgbXVzdCB1c2Uga2V5IHtAbGluayBWYWxpZGF0aW9uS2V5cyNTVEVQfVxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSB0aGUgZXJyb3IgbWVzc2FnZS4gRGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMjU1RFUH1cbiAqXG4gKiBAZnVuY3Rpb24gc3RlcFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5EZWNvcmF0b3JzLlZhbGlkYXRpb25cbiAqIEBjYXRlZ29yeSBEZWNvcmF0b3JzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGVwKFxuICB2YWx1ZTogbnVtYmVyLFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLlNURVBcbikge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT4oVmFsaWRhdGlvbi5rZXkoVmFsaWRhdGlvbktleXMuU1RFUCksIHtcbiAgICBbVmFsaWRhdGlvbktleXMuU1RFUF06IHZhbHVlLFxuICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgdHlwZXM6IFtOdW1iZXIubmFtZV0sXG4gIH0pO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBtaW5pbXVtIGxlbmd0aCBmb3IgdGhlIHByb3BlcnR5XG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdG9ycyB0byB2YWxpZGF0ZSBhIGRlY29yYXRlZCBwcm9wZXJ0eSBtdXN0IHVzZSBrZXkge0BsaW5rIFZhbGlkYXRpb25LZXlzI01JTl9MRU5HVEh9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNNSU5fTEVOR1RIfVxuICpcbiAqIEBmdW5jdGlvbiBtaW5sZW5ndGhcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uRGVjb3JhdG9ycy5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbWlubGVuZ3RoKFxuICB2YWx1ZTogbnVtYmVyLFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLk1JTl9MRU5HVEhcbikge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT4oXG4gICAgVmFsaWRhdGlvbi5rZXkoVmFsaWRhdGlvbktleXMuTUlOX0xFTkdUSCksXG4gICAge1xuICAgICAgW1ZhbGlkYXRpb25LZXlzLk1JTl9MRU5HVEhdOiB2YWx1ZSxcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICB0eXBlczogW1N0cmluZy5uYW1lLCBBcnJheS5uYW1lLCBTZXQubmFtZV0sXG4gICAgfVxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBtYXhpbXVtIGxlbmd0aCBmb3IgdGhlIHByb3BlcnR5XG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdG9ycyB0byB2YWxpZGF0ZSBhIGRlY29yYXRlZCBwcm9wZXJ0eSBtdXN0IHVzZSBrZXkge0BsaW5rIFZhbGlkYXRpb25LZXlzI01BWF9MRU5HVEh9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNNQVhfTEVOR1RIfVxuICpcbiAqIEBmdW5jdGlvbiBtYXhsZW5ndGhcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uRGVjb3JhdG9ycy5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbWF4bGVuZ3RoKFxuICB2YWx1ZTogbnVtYmVyLFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLk1BWF9MRU5HVEhcbikge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhPFZhbGlkYXRpb25NZXRhZGF0YT4oXG4gICAgVmFsaWRhdGlvbi5rZXkoVmFsaWRhdGlvbktleXMuTUFYX0xFTkdUSCksXG4gICAge1xuICAgICAgW1ZhbGlkYXRpb25LZXlzLk1BWF9MRU5HVEhdOiB2YWx1ZSxcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICB0eXBlczogW1N0cmluZy5uYW1lLCBBcnJheS5uYW1lLCBTZXQubmFtZV0sXG4gICAgfVxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgYSBSZWdFeHAgcGF0dGVybiB0aGUgcHJvcGVydHkgbXVzdCByZXNwZWN0XG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdG9ycyB0byB2YWxpZGF0ZSBhIGRlY29yYXRlZCBwcm9wZXJ0eSBtdXN0IHVzZSBrZXkge0BsaW5rIFZhbGlkYXRpb25LZXlzI1BBVFRFUk59XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNQQVRURVJOfVxuICpcbiAqIEBmdW5jdGlvbiBwYXR0ZXJuXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLkRlY29yYXRvcnMuVmFsaWRhdGlvblxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm4oXG4gIHZhbHVlOiBSZWdFeHAgfCBzdHJpbmcsXG4gIG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUEFUVEVSTlxuKSB7XG4gIHJldHVybiBwcm9wTWV0YWRhdGE8VmFsaWRhdGlvbk1ldGFkYXRhPihcbiAgICBWYWxpZGF0aW9uLmtleShWYWxpZGF0aW9uS2V5cy5QQVRURVJOKSxcbiAgICB7XG4gICAgICBbVmFsaWRhdGlvbktleXMuUEFUVEVSTl06XG4gICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlIDogdmFsdWUudG9TdHJpbmcoKSxcbiAgICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gICAgICB0eXBlczogW1N0cmluZy5uYW1lXSxcbiAgICB9XG4gICk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyB0aGUgcHJvcGVydHkgYXMgYW4gZW1haWxcbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0b3JzIHRvIHZhbGlkYXRlIGEgZGVjb3JhdGVkIHByb3BlcnR5IG11c3QgdXNlIGtleSB7QGxpbmsgVmFsaWRhdGlvbktleXMjRU1BSUx9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSB0aGUgZXJyb3IgbWVzc2FnZS4gRGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMjRU1BSUx9XG4gKlxuICogQGZ1bmN0aW9uIGVtYWlsXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLkRlY29yYXRvcnMuVmFsaWRhdGlvblxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVtYWlsKG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuRU1BSUwpIHtcbiAgcmV0dXJuIHByb3BNZXRhZGF0YTxWYWxpZGF0aW9uTWV0YWRhdGE+KFxuICAgIFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLkVNQUlMKSxcbiAgICB7XG4gICAgICBbVmFsaWRhdGlvbktleXMuUEFUVEVSTl06IERFRkFVTFRfUEFUVEVSTlMuRU1BSUwsXG4gICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgdHlwZXM6IFtTdHJpbmcubmFtZV0sXG4gICAgfVxuICApO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERlZmluZXMgdGhlIHByb3BlcnR5IGFzIGFuIFVSTFxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRvcnMgdG8gdmFsaWRhdGUgYSBkZWNvcmF0ZWQgcHJvcGVydHkgbXVzdCB1c2Uga2V5IHtAbGluayBWYWxpZGF0aW9uS2V5cyNVUkx9XG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSB0aGUgZXJyb3IgbWVzc2FnZS4gRGVmYXVsdHMgdG8ge0BsaW5rIERFRkFVTFRfRVJST1JfTUVTU0FHRVMjVVJMfVxuICpcbiAqIEBmdW5jdGlvbiB1cmxcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uRGVjb3JhdG9ycy5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gdXJsKG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuVVJMKSB7XG4gIHJldHVybiBwcm9wTWV0YWRhdGE8VmFsaWRhdGlvbk1ldGFkYXRhPihWYWxpZGF0aW9uLmtleShWYWxpZGF0aW9uS2V5cy5VUkwpLCB7XG4gICAgW1ZhbGlkYXRpb25LZXlzLlBBVFRFUk5dOiBERUZBVUxUX1BBVFRFUk5TLlVSTCxcbiAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgIHR5cGVzOiBbU3RyaW5nLm5hbWVdLFxuICB9KTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBFbmZvcmNlcyB0eXBlIHZlcmlmaWNhdGlvblxuICogQGRlc2NyaXB0aW9uIFZhbGlkYXRvcnMgdG8gdmFsaWRhdGUgYSBkZWNvcmF0ZWQgcHJvcGVydHkgbXVzdCB1c2Uga2V5IHtAbGluayBWYWxpZGF0aW9uS2V5cyNUWVBFfVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nW10gfCBzdHJpbmd9IHR5cGVzIGFjY2VwdGVkIHR5cGVzXG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNUWVBFfVxuICpcbiAqIEBmdW5jdGlvbiB0eXBlXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLkRlY29yYXRvcnMuVmFsaWRhdGlvblxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGUoXG4gIHR5cGVzOiBzdHJpbmdbXSB8IHN0cmluZyxcbiAgbWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5UWVBFXG4pIHtcbiAgcmV0dXJuIHByb3BNZXRhZGF0YTxWYWxpZGF0aW9uTWV0YWRhdGE+KFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLlRZUEUpLCB7XG4gICAgY3VzdG9tVHlwZXM6IHR5cGVzLFxuICAgIG1lc3NhZ2U6IG1lc3NhZ2UsXG4gIH0pO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IERhdGUgSGFuZGxlciBEZWNvcmF0b3JcbiAqIEBkZXNjcmlwdGlvbiBWYWxpZGF0b3JzIHRvIHZhbGlkYXRlIGEgZGVjb3JhdGVkIHByb3BlcnR5IG11c3QgdXNlIGtleSB7QGxpbmsgVmFsaWRhdGlvbktleXMjREFURX1cbiAqXG4gKiBXaWxsIGVuZm9yY2Ugc2VyaWFsaXphdGlvbiBhY2NvcmRpbmcgdG8gdGhlIHNlbGVjdGVkIGZvcm1hdFxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgYWNjZXB0ZWQgZm9ybWF0IGFjY29yZGluZyB0byB7QGxpbmsgZm9ybWF0RGF0ZX1cbiAqIEBwYXJhbSB7c3RyaW5nfSBbbWVzc2FnZV0gdGhlIGVycm9yIG1lc3NhZ2UuIERlZmF1bHRzIHRvIHtAbGluayBERUZBVUxUX0VSUk9SX01FU1NBR0VTI0RBVEV9XG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPFZhbGlkYXRvcj59IFt2YWxpZGF0b3JdIHRoZSBWYWxpZGF0b3IgdG8gYmUgdXNlZC4gRGVmYXVsdHMgdG8ge0BsaW5rIERhdGVWYWxpZGF0b3J9XG4gKlxuICogQGZ1bmN0aW9uIGRhdGVcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLkRlY29yYXRvcnMuVmFsaWRhdGlvblxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRhdGUoXG4gIGZvcm1hdDogc3RyaW5nID0gXCJkZC9NTS95eXl5XCIsXG4gIG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuREFURVxuKSB7XG4gIHJldHVybiAodGFyZ2V0OiBSZWNvcmQ8c3RyaW5nLCBhbnk+LCBwcm9wZXJ0eUtleT86IGFueSk6IGFueSA9PiB7XG4gICAgcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLkRBVEUpLCB7XG4gICAgICBbVmFsaWRhdGlvbktleXMuRk9STUFUXTogZm9ybWF0LFxuICAgICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICAgIHR5cGVzOiBbRGF0ZS5uYW1lXSxcbiAgICB9KSh0YXJnZXQsIHByb3BlcnR5S2V5KTtcblxuICAgIGNvbnN0IHZhbHVlcyA9IG5ldyBXZWFrTWFwKCk7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBwcm9wZXJ0eUtleSwge1xuICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgIHNldCh0aGlzOiBhbnksIG5ld1ZhbHVlOiBzdHJpbmcgfCBEYXRlKSB7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRoaXMsIHByb3BlcnR5S2V5KTtcbiAgICAgICAgaWYgKCFkZXNjcmlwdG9yIHx8IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlKVxuICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBwcm9wZXJ0eUtleSwge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICBnZXQ6ICgpID0+IHZhbHVlcy5nZXQodGhpcyksXG4gICAgICAgICAgICBzZXQ6IChuZXdWYWx1ZTogc3RyaW5nIHwgRGF0ZSB8IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICBsZXQgdmFsOiBEYXRlIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhbCA9IHBhcnNlRGF0ZShmb3JtYXQsIG5ld1ZhbHVlKTtcbiAgICAgICAgICAgICAgICB2YWx1ZXMuc2V0KHRoaXMsIHZhbCk7XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3Ioc2YoXCJGYWlsZWQgdG8gcGFyc2UgZGF0ZTogezB9XCIsIGUubWVzc2FnZSB8fCBlKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIHRoaXNbcHJvcGVydHlLZXldID0gbmV3VmFsdWU7XG4gICAgICB9LFxuICAgICAgZ2V0KCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcImhlcmVcIik7XG4gICAgICB9LFxuICAgIH0pO1xuICB9O1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFBhc3N3b3JkIEhhbmRsZXIgRGVjb3JhdG9yXG4gKiBAZGVzY3JpcHRpb24gVmFsaWRhdG9ycyB0byB2YWxpZGF0ZSBhIGRlY29yYXRlZCBwcm9wZXJ0eSBtdXN0IHVzZSBrZXkge0BsaW5rIFZhbGlkYXRpb25LZXlzI1BBU1NXT1JEfVxuICpcbiAqIEBwYXJhbSB7UmVnRXhwfSBbcGF0dGVybl0gZGVmYXVsdHMgdG8ge0BsaW5rIFBhc3N3b3JkUGF0dGVybnMjQ0hBUjhfT05FX09GX0VBQ0h9XG4gKiBAcGFyYW0ge3N0cmluZ30gW21lc3NhZ2VdIHRoZSBlcnJvciBtZXNzYWdlLiBEZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNQQVNTV09SRH1cbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8VmFsaWRhdG9yPn0gW3ZhbGlkYXRvcl0gRGVmYXVsdHMgdG8ge0BsaW5rIFBhc3N3b3JkVmFsaWRhdG9yfVxuICpcbiAqIEBmdW5jdGlvbiBwYXNzd29yZFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uRGVjb3JhdG9ycy5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFzc3dvcmQoXG4gIHBhdHRlcm46IFJlZ0V4cCA9IERFRkFVTFRfUEFUVEVSTlMuUEFTU1dPUkQuQ0hBUjhfT05FX09GX0VBQ0gsXG4gIG1lc3NhZ2U6IHN0cmluZyA9IERFRkFVTFRfRVJST1JfTUVTU0FHRVMuUEFTU1dPUkRcbikge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLlBBU1NXT1JEKSwge1xuICAgIFtWYWxpZGF0aW9uS2V5cy5QQVRURVJOXTogcGF0dGVybixcbiAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgIHR5cGVzOiBbU3RyaW5nLm5hbWVdLFxuICB9KTtcbn1cblxuLyoqXG4gKiBAc3VtbWFyeSBMaXN0IERlY29yYXRvclxuICogQGRlc2NyaXB0aW9uIEFsc28gc2V0cyB0aGUge0BsaW5rIHR5cGV9IHRvIHRoZSBwcm92aWRlZCBjb2xsZWN0aW9uXG4gKlxuICogQHBhcmFtIHtNb2RlbENvbnN0cnVjdG9yfSBjbGF6elxuICogQHBhcmFtIHtzdHJpbmd9IFtjb2xsZWN0aW9uXSBUaGUgY29sbGVjdGlvbiBiZWluZyB1c2VkLiBkZWZhdWx0cyB0byBBcnJheVxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNMSVNUfVxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxWYWxpZGF0b3I+fSBbdmFsaWRhdG9yXSBkZWZhdWx0cyB0byB7QGxpbmsgTGlzdFZhbGlkYXRvcn1cbiAqXG4gKiBAZnVuY3Rpb24gbGlzdFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uRGVjb3JhdG9ycy5WYWxpZGF0aW9uXG4gKiBAY2F0ZWdvcnkgRGVjb3JhdG9yc1xuICovXG5leHBvcnQgZnVuY3Rpb24gbGlzdChcbiAgY2xheno6IE1vZGVsQ29uc3RydWN0b3I8YW55PiB8IE1vZGVsQ29uc3RydWN0b3I8YW55PltdLFxuICBjb2xsZWN0aW9uOiBcIkFycmF5XCIgfCBcIlNldFwiID0gXCJBcnJheVwiLFxuICBtZXNzYWdlOiBzdHJpbmcgPSBERUZBVUxUX0VSUk9SX01FU1NBR0VTLkxJU1Rcbikge1xuICByZXR1cm4gcHJvcE1ldGFkYXRhKFZhbGlkYXRpb24ua2V5KFZhbGlkYXRpb25LZXlzLkxJU1QpLCB7XG4gICAgY2xheno6IEFycmF5LmlzQXJyYXkoY2xhenopID8gY2xhenoubWFwKChjKSA9PiBjLm5hbWUpIDogW2NsYXp6Lm5hbWVdLFxuICAgIHR5cGU6IGNvbGxlY3Rpb24sXG4gICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgfSk7XG59XG5cbi8qKlxuICogQHN1bW1hcnkgU2V0IERlY29yYXRvclxuICogQGRlc2NyaXB0aW9uIFdyYXBwZXIgZm9yIHtAbGluayBsaXN0fSB3aXRoIHRoZSAnU2V0JyBDb2xsZWN0aW9uXG4gKlxuICogQHBhcmFtIHtNb2RlbENvbnN0cnVjdG9yfSBjbGF6elxuICogQHBhcmFtIHtzdHJpbmd9IFttZXNzYWdlXSBkZWZhdWx0cyB0byB7QGxpbmsgREVGQVVMVF9FUlJPUl9NRVNTQUdFUyNMSVNUfVxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxWYWxpZGF0b3I+fSBbdmFsaWRhdG9yXVxuICpcbiAqIEBmdW5jdGlvbiBzZXRcbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLkRlY29yYXRvcnMuVmFsaWRhdGlvblxuICogQGNhdGVnb3J5IERlY29yYXRvcnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldChcbiAgY2xheno6IE1vZGVsQ29uc3RydWN0b3I8YW55PixcbiAgbWVzc2FnZTogc3RyaW5nID0gREVGQVVMVF9FUlJPUl9NRVNTQUdFUy5MSVNUXG4pIHtcbiAgcmV0dXJuIGxpc3QoY2xhenosIFwiU2V0XCIsIG1lc3NhZ2UpO1xufVxuIiwiaW1wb3J0IHsgTW9kZWwgfSBmcm9tIFwiLi9Nb2RlbFwiO1xuXG4vKipcbiAqIEBzdW1tYXJ5IEhlbHBlciBGdW5jdGlvbiB0byBvdmVycmlkZSBjb25zdHJ1Y3RvcnNcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHthbnlbXX0gW2FyZ3NdXG4gKiBAcmV0dXJuIHtUfSB0aGUgbmV3IGluc3RhbmNlXG4gKlxuICogQGZ1bmN0aW9uIGNvbnN0cnVjdFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvbi5Db25zdHJ1Y3Rpb25cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbnN0cnVjdDxUIGV4dGVuZHMgTW9kZWw+KFxuICBjb25zdHJ1Y3RvcjogYW55LFxuICAuLi5hcmdzOiBhbnlbXVxuKTogVCB7XG4gIGNvbnN0IF9jb25zdHIgPSAoLi4uYXJnejogYW55W10pID0+IG5ldyBjb25zdHJ1Y3RvciguLi5hcmd6KTtcbiAgX2NvbnN0ci5wcm90b3R5cGUgPSBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gIHJldHVybiBfY29uc3RyKC4uLmFyZ3MpO1xufVxuXG4vKipcbiAqIEBzdW1tYXJ5IFJlY3Vyc2l2ZWx5IGZpbmRzIHRoZSBsYXN0IHByb3RvdHlwZSBiZWZvcmUgT2JqZWN0XG4gKiBAcGFyYW0ge29iamVjdH0gb2JqXG4gKlxuICogQGZ1bmN0aW9uIGZpbmRMYXN0UHJvdG9CZWZvcmVPYmplY3RcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uQ29uc3RydWN0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kTGFzdFByb3RvQmVmb3JlT2JqZWN0KG9iajogb2JqZWN0KTogb2JqZWN0IHtcbiAgbGV0IHByb3RvdHlwZTogYW55ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iaik7XG4gIGlmIChwcm90b3R5cGUgPT09IE9iamVjdC5wcm90b3R5cGUpIHJldHVybiBvYmo7XG4gIHdoaWxlIChwcm90b3R5cGUgIT09IE9iamVjdC5wcm90b3R5cGUpIHtcbiAgICBwcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG90eXBlKTtcbiAgICBpZiAocHJvdG90eXBlID09PSBPYmplY3QucHJvdG90eXBlKSByZXR1cm4gcHJvdG90eXBlO1xuICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG90eXBlKSA9PT0gT2JqZWN0LnByb3RvdHlwZSkgcmV0dXJuIHByb3RvdHlwZTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgZmluZCBwcm9wZXIgcHJvdG90eXBlXCIpO1xufVxuXG4vKipcbiAqIEBzdW1hcnkgYmluZHMgdGhlIHtAbGluayBNb2RlbH0gY2xhc3MgYXMgYSByb290IHByb3RvdHlwZSBvZiB0aGUgcHJvdmlkZWQgaW5zdGFuY2VcbiAqXG4gKiBAcGFyYW0ge3Vua25vd259IG9ialxuICpcbiAqIEBmdW5jdGlvbiBiaW5kTW9kZWxQcm90b3R5cGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uQ29uc3RydWN0aW9uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiaW5kTW9kZWxQcm90b3R5cGUob2JqOiB1bmtub3duKSB7XG4gIGlmIChvYmogaW5zdGFuY2VvZiBNb2RlbCkgcmV0dXJuO1xuXG4gIGZ1bmN0aW9uIGJpbmRQcm90b3R5cGUob2JqVG9PdmVycmlkZTogdW5rbm93biwgcHJvdG90eXBlOiBvYmplY3QpIHtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2Yob2JqVG9PdmVycmlkZSwgcHJvdG90eXBlKTtcbiAgfVxuXG4gIGNvbnN0IHByb3RvdHlwZTogYW55ID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKG9iaik7XG4gIGlmIChwcm90b3R5cGUgPT09IE9iamVjdC5wcm90b3R5cGUpIHtcbiAgICByZXR1cm4gYmluZFByb3RvdHlwZShvYmosIE1vZGVsLnByb3RvdHlwZSk7XG4gIH1cbiAgd2hpbGUgKHByb3RvdHlwZSAhPT0gT2JqZWN0LnByb3RvdHlwZSkge1xuICAgIGNvbnN0IHByb3QgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG90eXBlKTtcbiAgICBpZiAoXG4gICAgICBwcm90ID09PSBPYmplY3QucHJvdG90eXBlIHx8XG4gICAgICBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdCkgPT09IE9iamVjdC5wcm90b3R5cGVcbiAgICApIHtcbiAgICAgIHJldHVybiBiaW5kUHJvdG90eXBlKHByb3RvdHlwZSwgTW9kZWwucHJvdG90eXBlKTtcbiAgICB9XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKFwiQ291bGQgbm90IGZpbmQgcHJvcGVyIHByb3RvdHlwZSB0byBiaW5kXCIpO1xufVxuIiwiaW1wb3J0IHsgYmluZE1vZGVsUHJvdG90eXBlLCBjb25zdHJ1Y3QgfSBmcm9tIFwiLi9jb25zdHJ1Y3Rpb25cIjtcbmltcG9ydCB7IE1vZGVsS2V5cyB9IGZyb20gXCIuLi91dGlscy9jb25zdGFudHNcIjtcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSBcIi4vTW9kZWxcIjtcbmltcG9ydCB7IG1ldGFkYXRhIH0gZnJvbSBcIkBkZWNhZi10cy9yZWZsZWN0aW9uXCI7XG5cbi8qKlxuICogQHN1bW1hcnkgZGVmaW5lcyB0aGUgdHBlIG9zIGFuIEluc3RhbmNlQ2FsbGJhY2sgZnVuY3Rpb25cbiAqXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uLk1vZGVsXG4gKi9cbmV4cG9ydCB0eXBlIEluc3RhbmNlQ2FsbGJhY2sgPSAoaW5zdGFuY2U6IGFueSwgLi4uYXJnczogYW55W10pID0+IHZvaWQ7XG5cbi8qKlxuICogQHN1bW1hcnkgRGVmaW5lcyBhIGNsYXNzIGFzIGEgTW9kZWwgY2xhc3NcbiAqIEBkZXNjcmlwdGlvblxuICpcbiAqIC0gUmVnaXN0ZXJzIHRoZSBjbGFzcyB1bmRlciB0aGUgbW9kZWwgcmVnaXN0cnkgc28gaXQgY2FuIGJlIGVhc2lseSByZWJ1aWx0O1xuICogLSBPdmVycmlkZXMgdGhlIGNsYXNzIGNvbnN0cnVjdG9yO1xuICogLSBSdW5zIHRoZSBnbG9iYWwge0BsaW5rIE1vZGVsQnVpbGRlckZ1bmN0aW9ufSBpZiBkZWZpbmVkO1xuICogLSBSdW5zIHRoZSBvcHRpb25hbCB7QGxpbmsgSW5zdGFuY2VDYWxsYmFja30gaWYgcHJvdmlkZWQ7XG4gKlxuICogQHBhcmFtIHtJbnN0YW5jZUNhbGxiYWNrfSBbaW5zdGFuY2VDYWxsYmFja10gb3B0aW9uYWwgY2FsbGJhY2sgdGhhdCB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBpbnN0YW5jZSB1cG9uIGluc3RhbnRpYXRpb24uIGRlZmF1bHRzIHRvIHVuZGVmaW5lZFxuICpcbiAqIEBmdW5jdGlvbiBtb2RlbFxuICpcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb24uTW9kZWxcbiAqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtb2RlbChpbnN0YW5jZUNhbGxiYWNrPzogSW5zdGFuY2VDYWxsYmFjaykge1xuICByZXR1cm4gKChvcmlnaW5hbDogYW55KSA9PiB7XG4gICAgLy8gdGhlIG5ldyBjb25zdHJ1Y3RvciBiZWhhdmlvdXJcbiAgICBjb25zdCBuZXdDb25zdHJ1Y3RvcjogYW55ID0gZnVuY3Rpb24gKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgICBjb25zdCBpbnN0YW5jZTogUmV0dXJuVHlwZTx0eXBlb2Ygb3JpZ2luYWw+ID0gY29uc3RydWN0KFxuICAgICAgICBvcmlnaW5hbCxcbiAgICAgICAgLi4uYXJnc1xuICAgICAgKTtcbiAgICAgIGJpbmRNb2RlbFByb3RvdHlwZShpbnN0YW5jZSk7XG4gICAgICAvLyBydW4gYSBidWlsZGVyIGZ1bmN0aW9uIGlmIGRlZmluZWQgd2l0aCB0aGUgZmlyc3QgYXJndW1lbnQgKFRoZSBNb2RlbEFyZylcbiAgICAgIGNvbnN0IGJ1aWxkZXIgPSBNb2RlbC5nZXRCdWlsZGVyKCk7XG4gICAgICBpZiAoYnVpbGRlcikgYnVpbGRlcihpbnN0YW5jZSwgYXJncy5sZW5ndGggPyBhcmdzWzBdIDogdW5kZWZpbmVkKTtcblxuICAgICAgbWV0YWRhdGEoTW9kZWwua2V5KE1vZGVsS2V5cy5NT0RFTCksIG9yaWdpbmFsLm5hbWUpKGluc3RhbmNlLmNvbnN0cnVjdG9yKTtcblxuICAgICAgaWYgKGluc3RhbmNlQ2FsbGJhY2spIGluc3RhbmNlQ2FsbGJhY2soaW5zdGFuY2UsIC4uLmFyZ3MpO1xuXG4gICAgICByZXR1cm4gaW5zdGFuY2U7XG4gICAgfTtcblxuICAgIC8vIGNvcHkgcHJvdG90eXBlIHNvIGluc3RhbmNlb2Ygb3BlcmF0b3Igc3RpbGwgd29ya3NcbiAgICBuZXdDb25zdHJ1Y3Rvci5wcm90b3R5cGUgPSBvcmlnaW5hbC5wcm90b3R5cGU7XG4gICAgLy8gU2V0cyB0aGUgcHJvcGVyIGNvbnN0cnVjdG9yIG5hbWUgZm9yIHR5cGUgdmVyaWZpY2F0aW9uXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG5ld0NvbnN0cnVjdG9yLCBcIm5hbWVcIiwge1xuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICB2YWx1ZTogb3JpZ2luYWwucHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUsXG4gICAgfSk7XG5cbiAgICBtZXRhZGF0YShNb2RlbC5rZXkoTW9kZWxLZXlzLk1PREVMKSwgb3JpZ2luYWwubmFtZSkob3JpZ2luYWwpO1xuXG4gICAgTW9kZWwucmVnaXN0ZXIobmV3Q29uc3RydWN0b3IsIG9yaWdpbmFsLm5hbWUpO1xuXG4gICAgLy8gcmV0dXJuIG5ldyBjb25zdHJ1Y3RvciAod2lsbCBvdmVycmlkZSBvcmlnaW5hbClcbiAgICByZXR1cm4gbmV3Q29uc3RydWN0b3I7XG4gIH0pIGFzIGFueTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc2hlZEJ5KGFsZ29yaXRobTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSkge1xuICByZXR1cm4gbWV0YWRhdGEoTW9kZWwua2V5KE1vZGVsS2V5cy5IQVNISU5HKSwge1xuICAgIGFsZ29yaXRobTogYWxnb3JpdGhtLFxuICAgIGFyZ3M6IGFyZ3MsXG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplZEJ5KHNlcmlhbGl6ZXI6IHN0cmluZywgLi4uYXJnczogYW55W10pIHtcbiAgcmV0dXJuIG1ldGFkYXRhKE1vZGVsLmtleShNb2RlbEtleXMuU0VSSUFMSVpBVElPTiksIHtcbiAgICBzZXJpYWxpemVyOiBzZXJpYWxpemVyLFxuICAgIGFyZ3M6IGFyZ3MsXG4gIH0pO1xufVxuIiwiLyoqXG4gKiBAbW9kdWxlIGRlY29yYXRvci12YWxpZGF0aW9uXG4gKi9cblxuLyoqXG4gKiBAc3VtbWFyeSBNb2RlbCBkZWZpbml0aW9uIGZ1bmN0aW9uYWxpdHlcbiAqIEBkZXNjcmlwdGlvbiBkZWZpbmVzIHRoZSBiYXNlIGNsYXNzIGFuZCByZWxhdGVkIGZ1bmN0aW9uYWxpdHlcbiAqXG4gKiBAbmFtZXNwYWNlIE1vZGVsXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKi9cblxuLyoqXG4gKiBAc3VtbWFyeSBIb2xkcyBhbGwgdGhlIHN1cHBvcnRlZCBkZWNvcmF0b3JzXG4gKiBAbmFtZXNwYWNlIERlY29yYXRvcnNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqL1xuXG4vKipcbiAqIEBzdW1tYXJ5IFZhbGlkYXRpb24gcmVsYXRlZCBmdW5jdGlvbmFsaXR5XG4gKiBAZGVzY3JpcHRpb24gRGVmaW5lcyB0aGUgTW9kZWwgdmFsaWRhdGlvbiBhcGlzIGFuZCBiYXNlIGNsYXNzZXMgZm9yIHZhbGlkYXRvcnNcbiAqXG4gKiBAbmFtZXNwYWNlIFZhbGlkYXRpb25cbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqL1xuXG4vKipcbiAqIEBuYW1lc3BhY2UgRGF0ZXNcbiAqIEBtZW1iZXJPZiBtb2R1bGU6ZGVjb3JhdG9yLXZhbGlkYXRpb25cbiAqL1xuXG4vKipcbiAqIEBuYW1lc3BhY2UgSGFzaGluZ1xuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvblxuICovXG5cbi8qKlxuICogQG5hbWVzcGFjZSBTZXJpYWxpemF0aW9uXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmRlY29yYXRvci12YWxpZGF0aW9uXG4gKi9cblxuLyoqXG4gKiBAbmFtZXNwYWNlIEZvcm1hdFxuICogQG1lbWJlck9mIG1vZHVsZTpkZWNvcmF0b3ItdmFsaWRhdGlvblxuICovXG5cbmV4cG9ydCAqIGZyb20gXCIuL3V0aWxzXCI7XG5leHBvcnQgKiBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9tb2RlbFwiO1xuXG5leHBvcnQgY29uc3QgVkVSU0lPTiA9IFwiIyNWRVJTSU9OIyNcIjtcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7Ozs7Ozs7Ozs7OztBQWFHO0lBQ1M7QUFBWixDQUFBLFVBQVksU0FBUyxFQUFBO0FBQ25CLElBQUEsU0FBQSxDQUFBLFNBQUEsQ0FBQSxHQUFBLGNBQXdCO0FBQ3hCLElBQUEsU0FBQSxDQUFBLE1BQUEsQ0FBQSxHQUFBLGFBQW9CO0FBQ3BCLElBQUEsU0FBQSxDQUFBLFFBQUEsQ0FBQSxHQUFBLG1CQUE0QjtBQUM1QixJQUFBLFNBQUEsQ0FBQSxRQUFBLENBQUEsR0FBQSxtQkFBNEI7QUFDNUIsSUFBQSxTQUFBLENBQUEsT0FBQSxDQUFBLEdBQUEsT0FBZTtBQUNmLElBQUEsU0FBQSxDQUFBLFFBQUEsQ0FBQSxHQUFBLFNBQWtCO0FBQ2xCLElBQUEsU0FBQSxDQUFBLGNBQUEsQ0FBQSxHQUFBLGdCQUErQjtBQUMvQixJQUFBLFNBQUEsQ0FBQSxXQUFBLENBQUEsR0FBQSxjQUEwQjtBQUMxQixJ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QU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtBQUNoQixTQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRTtBQUN6QixTQUFBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtBQUNoQixTQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRTtBQUM1QixTQUFBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtBQUNoQixTQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRTtBQUM5QixTQUFBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtBQUNoQixTQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLFFBQVEsRUFBRTtBQUM5QixTQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUUsV0FBVyxDQUFDLFFBQVEsRUFBRTtBQUNuQyxTQUFBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtBQUNoQixTQUFBLE9BQU8sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLFFBQVEsRUFBRTtBQUUzQixTQUFBLE9BQU8sQ0FBQyxNQUFNLEVBQUUsSUFBSTtBQUNwQixTQUFBLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRztBQUNsQixTQUFBLE9BQU8sQ0FBQyxNQUFNLEVBQUUsSUFBSTtBQUNwQixTQUFBLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRTtBQUNoQixTQUFBLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDO0lBQ3RCLElBQUksVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEVBQUU7QUFDbEMsUUFBQSxVQUFVLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUM7O1NBQzVEO0FBQ0wsUUFBQSxVQUFVLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFB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
|