1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.Arn = exports.ArnFormat = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const cfn_fn_1 = require("./cfn-fn");
|
8 | const token_1 = require("./token");
|
9 | const util_1 = require("./util");
|
10 | /**
|
11 | * An enum representing the various ARN formats that different services use.
|
12 | */
|
13 | var ArnFormat;
|
14 | (function (ArnFormat) {
|
15 | /**
|
16 | * This represents a format where there is no 'resourceName' part.
|
17 | * This format is used for S3 resources,
|
18 | * like 'arn:aws:s3:::bucket'.
|
19 | * Everything after the last colon is considered the 'resource',
|
20 | * even if it contains slashes,
|
21 | * like in 'arn:aws:s3:::bucket/object.zip'.
|
22 | */
|
23 | ArnFormat["NO_RESOURCE_NAME"] = "arn:aws:service:region:account:resource";
|
24 | /**
|
25 | * This represents a format where the 'resource' and 'resourceName'
|
26 | * parts are separated with a colon.
|
27 | * Like in: 'arn:aws:service:region:account:resource:resourceName'.
|
28 | * Everything after the last colon is considered the 'resourceName',
|
29 | * even if it contains slashes,
|
30 | * like in 'arn:aws:apigateway:region:account:resource:/test/mydemoresource/*'.
|
31 | */
|
32 | ArnFormat["COLON_RESOURCE_NAME"] = "arn:aws:service:region:account:resource:resourceName";
|
33 | /**
|
34 | * This represents a format where the 'resource' and 'resourceName'
|
35 | * parts are separated with a slash.
|
36 | * Like in: 'arn:aws:service:region:account:resource/resourceName'.
|
37 | * Everything after the separating slash is considered the 'resourceName',
|
38 | * even if it contains colons,
|
39 | * like in 'arn:aws:cognito-sync:region:account:identitypool/us-east-1:1a1a1a1a-ffff-1111-9999-12345678:bla'.
|
40 | */
|
41 | ArnFormat["SLASH_RESOURCE_NAME"] = "arn:aws:service:region:account:resource/resourceName";
|
42 | /**
|
43 | * This represents a format where the 'resource' and 'resourceName'
|
44 | * parts are seperated with a slash,
|
45 | * but there is also an additional slash after the colon separating 'account' from 'resource'.
|
46 | * Like in: 'arn:aws:service:region:account:/resource/resourceName'.
|
47 | * Note that the leading slash is _not_ included in the parsed 'resource' part.
|
48 | */
|
49 | ArnFormat["SLASH_RESOURCE_SLASH_RESOURCE_NAME"] = "arn:aws:service:region:account:/resource/resourceName";
|
50 | })(ArnFormat = exports.ArnFormat || (exports.ArnFormat = {}));
|
51 | class Arn {
|
52 | constructor() { }
|
53 | /**
|
54 | * Creates an ARN from components.
|
55 | *
|
56 | * If `partition`, `region` or `account` are not specified, the stack's
|
57 | * partition, region and account will be used.
|
58 | *
|
59 | * If any component is the empty string, an empty string will be inserted
|
60 | * into the generated ARN at the location that component corresponds to.
|
61 | *
|
62 | * The ARN will be formatted as follows:
|
63 | *
|
64 | * arn:{partition}:{service}:{region}:{account}:{resource}{sep}{resource-name}
|
65 | *
|
66 | * The required ARN pieces that are omitted will be taken from the stack that
|
67 | * the 'scope' is attached to. If all ARN pieces are supplied, the supplied scope
|
68 | * can be 'undefined'.
|
69 | */
|
70 | static format(components, stack) {
|
71 | try {
|
72 | jsiiDeprecationWarnings._aws_cdk_core_ArnComponents(components);
|
73 | jsiiDeprecationWarnings._aws_cdk_core_Stack(stack);
|
74 | }
|
75 | catch (error) {
|
76 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
77 | Error.captureStackTrace(error, this.format);
|
78 | }
|
79 | throw error;
|
80 | }
|
81 | const partition = components.partition ?? stack?.partition;
|
82 | const region = components.region ?? stack?.region;
|
83 | const account = components.account ?? stack?.account;
|
84 | // Catch both 'null' and 'undefined'
|
85 | if (partition == null || region == null || account == null) {
|
86 | throw new Error(`Arn.format: partition (${partition}), region (${region}), and account (${account}) must all be passed if stack is not passed.`);
|
87 | }
|
88 | const sep = components.sep ?? (components.arnFormat === ArnFormat.COLON_RESOURCE_NAME ? ':' : '/');
|
89 | const values = [
|
90 | 'arn', ':', partition, ':', components.service, ':', region, ':', account, ':',
|
91 | ...(components.arnFormat === ArnFormat.SLASH_RESOURCE_SLASH_RESOURCE_NAME ? ['/'] : []),
|
92 | components.resource,
|
93 | ];
|
94 | if (sep !== '/' && sep !== ':' && sep !== '') {
|
95 | throw new Error('resourcePathSep may only be ":", "/" or an empty string');
|
96 | }
|
97 | if (components.resourceName != null) {
|
98 | values.push(sep);
|
99 | values.push(components.resourceName);
|
100 | }
|
101 | return values.join('');
|
102 | }
|
103 | /**
|
104 | * Given an ARN, parses it and returns components.
|
105 | *
|
106 | * IF THE ARN IS A CONCRETE STRING...
|
107 | *
|
108 | * ...it will be parsed and validated. The separator (`sep`) will be set to '/'
|
109 | * if the 6th component includes a '/', in which case, `resource` will be set
|
110 | * to the value before the '/' and `resourceName` will be the rest. In case
|
111 | * there is no '/', `resource` will be set to the 6th components and
|
112 | * `resourceName` will be set to the rest of the string.
|
113 | *
|
114 | * IF THE ARN IS A TOKEN...
|
115 | *
|
116 | * ...it cannot be validated, since we don't have the actual value yet at the
|
117 | * time of this function call. You will have to supply `sepIfToken` and
|
118 | * whether or not ARNs of the expected format usually have resource names
|
119 | * in order to parse it properly. The resulting `ArnComponents` object will
|
120 | * contain tokens for the subexpressions of the ARN, not string literals.
|
121 | *
|
122 | * If the resource name could possibly contain the separator char, the actual
|
123 | * resource name cannot be properly parsed. This only occurs if the separator
|
124 | * char is '/', and happens for example for S3 object ARNs, IAM Role ARNs,
|
125 | * IAM OIDC Provider ARNs, etc. To properly extract the resource name from a
|
126 | * Tokenized ARN, you must know the resource type and call
|
127 | * `Arn.extractResourceName`.
|
128 | *
|
129 | * @param arn The ARN to parse
|
130 | * @param sepIfToken The separator used to separate resource from resourceName
|
131 | * @param hasName Whether there is a name component in the ARN at all. For
|
132 | * example, SNS Topics ARNs have the 'resource' component contain the topic
|
133 | * name, and no 'resourceName' component.
|
134 | *
|
135 | * @returns an ArnComponents object which allows access to the various
|
136 | * components of the ARN.
|
137 | *
|
138 | * @returns an ArnComponents object which allows access to the various
|
139 | * components of the ARN.
|
140 | *
|
141 | * @deprecated use split instead
|
142 | */
|
143 | static parse(arn, sepIfToken = '/', hasName = true) {
|
144 | try {
|
145 | jsiiDeprecationWarnings.print("@aws-cdk/core.Arn#parse", "use split instead");
|
146 | }
|
147 | catch (error) {
|
148 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
149 | Error.captureStackTrace(error, this.parse);
|
150 | }
|
151 | throw error;
|
152 | }
|
153 | let arnFormat;
|
154 | if (!hasName) {
|
155 | arnFormat = ArnFormat.NO_RESOURCE_NAME;
|
156 | }
|
157 | else {
|
158 | arnFormat = sepIfToken === '/' ? ArnFormat.SLASH_RESOURCE_NAME : ArnFormat.COLON_RESOURCE_NAME;
|
159 | }
|
160 | return this.split(arn, arnFormat);
|
161 | }
|
162 | /**
|
163 | * Splits the provided ARN into its components.
|
164 | * Works both if 'arn' is a string like 'arn:aws:s3:::bucket',
|
165 | * and a Token representing a dynamic CloudFormation expression
|
166 | * (in which case the returned components will also be dynamic CloudFormation expressions,
|
167 | * encoded as Tokens).
|
168 | *
|
169 | * @param arn the ARN to split into its components
|
170 | * @param arnFormat the expected format of 'arn' - depends on what format the service 'arn' represents uses
|
171 | */
|
172 | static split(arn, arnFormat) {
|
173 | try {
|
174 | jsiiDeprecationWarnings._aws_cdk_core_ArnFormat(arnFormat);
|
175 | }
|
176 | catch (error) {
|
177 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
178 | Error.captureStackTrace(error, this.split);
|
179 | }
|
180 | throw error;
|
181 | }
|
182 | const components = parseArnShape(arn);
|
183 | if (components === 'token') {
|
184 | return parseTokenArn(arn, arnFormat);
|
185 | }
|
186 | const [, partition, service, region, account, resourceTypeOrName, ...rest] = components;
|
187 | let resource;
|
188 | let resourceName;
|
189 | let sep;
|
190 | let resourcePartStartIndex = 0;
|
191 | let detectedArnFormat;
|
192 | let slashIndex = resourceTypeOrName.indexOf('/');
|
193 | if (slashIndex === 0) {
|
194 | // new-style ARNs are of the form 'arn:aws:s4:us-west-1:12345:/resource-type/resource-name'
|
195 | slashIndex = resourceTypeOrName.indexOf('/', 1);
|
196 | resourcePartStartIndex = 1;
|
197 | detectedArnFormat = ArnFormat.SLASH_RESOURCE_SLASH_RESOURCE_NAME;
|
198 | }
|
199 | if (slashIndex !== -1) {
|
200 | // the slash is only a separator if ArnFormat is not NO_RESOURCE_NAME
|
201 | if (arnFormat === ArnFormat.NO_RESOURCE_NAME) {
|
202 | sep = undefined;
|
203 | slashIndex = -1;
|
204 | detectedArnFormat = ArnFormat.NO_RESOURCE_NAME;
|
205 | }
|
206 | else {
|
207 | sep = '/';
|
208 | detectedArnFormat = resourcePartStartIndex === 0
|
209 | ? ArnFormat.SLASH_RESOURCE_NAME
|
210 | // need to repeat this here, as otherwise the compiler thinks 'detectedArnFormat' is not initialized in all paths
|
211 | : ArnFormat.SLASH_RESOURCE_SLASH_RESOURCE_NAME;
|
212 | }
|
213 | }
|
214 | else if (rest.length > 0) {
|
215 | sep = ':';
|
216 | slashIndex = -1;
|
217 | detectedArnFormat = ArnFormat.COLON_RESOURCE_NAME;
|
218 | }
|
219 | else {
|
220 | sep = undefined;
|
221 | detectedArnFormat = ArnFormat.NO_RESOURCE_NAME;
|
222 | }
|
223 | if (slashIndex !== -1) {
|
224 | resource = resourceTypeOrName.substring(resourcePartStartIndex, slashIndex);
|
225 | resourceName = resourceTypeOrName.substring(slashIndex + 1);
|
226 | }
|
227 | else {
|
228 | resource = resourceTypeOrName;
|
229 | }
|
230 | if (rest.length > 0) {
|
231 | if (!resourceName) {
|
232 | resourceName = '';
|
233 | }
|
234 | else {
|
235 | resourceName += ':';
|
236 | }
|
237 | resourceName += rest.join(':');
|
238 | }
|
239 | // "|| undefined" will cause empty strings to be treated as "undefined".
|
240 | // Optional ARN attributes (e.g. region, account) should return as empty string
|
241 | // if they are provided as such.
|
242 | return util_1.filterUndefined({
|
243 | service: service || undefined,
|
244 | resource: resource || undefined,
|
245 | partition: partition || undefined,
|
246 | region,
|
247 | account,
|
248 | resourceName,
|
249 | sep,
|
250 | arnFormat: detectedArnFormat,
|
251 | });
|
252 | }
|
253 | /**
|
254 | * Extract the full resource name from an ARN
|
255 | *
|
256 | * Necessary for resource names (paths) that may contain the separator, like
|
257 | * `arn:aws:iam::111111111111:role/path/to/role/name`.
|
258 | *
|
259 | * Only works if we statically know the expected `resourceType` beforehand, since we're going
|
260 | * to use that to split the string on ':<resourceType>/' (and take the right-hand side).
|
261 | *
|
262 | * We can't extract the 'resourceType' from the ARN at hand, because CloudFormation Expressions
|
263 | * only allow literals in the 'separator' argument to `{ Fn::Split }`, and so it can't be
|
264 | * `{ Fn::Select: [5, { Fn::Split: [':', ARN] }}`.
|
265 | *
|
266 | * Only necessary for ARN formats for which the type-name separator is `/`.
|
267 | */
|
268 | static extractResourceName(arn, resourceType) {
|
269 | const components = parseArnShape(arn);
|
270 | if (components === 'token') {
|
271 | return cfn_fn_1.Fn.select(1, cfn_fn_1.Fn.split(`:${resourceType}/`, arn));
|
272 | }
|
273 | // Apparently we could just parse this right away. Validate that we got the right
|
274 | // resource type (to notify authors of incorrect assumptions right away).
|
275 | const parsed = Arn.split(arn, ArnFormat.SLASH_RESOURCE_NAME);
|
276 | if (!token_1.Token.isUnresolved(parsed.resource) && parsed.resource !== resourceType) {
|
277 | throw new Error(`Expected resource type '${resourceType}' in ARN, got '${parsed.resource}' in '${arn}'`);
|
278 | }
|
279 | if (!parsed.resourceName) {
|
280 | throw new Error(`Expected resource name in ARN, didn't find one: '${arn}'`);
|
281 | }
|
282 | return parsed.resourceName;
|
283 | }
|
284 | }
|
285 | exports.Arn = Arn;
|
286 | _a = JSII_RTTI_SYMBOL_1;
|
287 | Arn[_a] = { fqn: "@aws-cdk/core.Arn", version: "1.204.0" };
|
288 | /**
|
289 | * Given a Token evaluating to ARN, parses it and returns components.
|
290 | *
|
291 | * The ARN cannot be validated, since we don't have the actual value yet
|
292 | * at the time of this function call. You will have to know the separator
|
293 | * and the type of ARN.
|
294 | *
|
295 | * The resulting `ArnComponents` object will contain tokens for the
|
296 | * subexpressions of the ARN, not string literals.
|
297 | *
|
298 | * WARNING: this function cannot properly parse the complete final
|
299 | * 'resourceName' part if it contains colons,
|
300 | * like 'arn:aws:cognito-sync:region:account:identitypool/us-east-1:1a1a1a1a-ffff-1111-9999-12345678:bla'.
|
301 | *
|
302 | * @param arnToken The input token that contains an ARN
|
303 | * @param arnFormat the expected format of 'arn' - depends on what format the service the ARN represents uses
|
304 | */
|
305 | function parseTokenArn(arnToken, arnFormat) {
|
306 | // ARN looks like:
|
307 | // arn:partition:service:region:account:resource
|
308 | // arn:partition:service:region:account:resource:resourceName
|
309 | // arn:partition:service:region:account:resource/resourceName
|
310 | // arn:partition:service:region:account:/resource/resourceName
|
311 | const components = cfn_fn_1.Fn.split(':', arnToken);
|
312 | const partition = cfn_fn_1.Fn.select(1, components).toString();
|
313 | const service = cfn_fn_1.Fn.select(2, components).toString();
|
314 | const region = cfn_fn_1.Fn.select(3, components).toString();
|
315 | const account = cfn_fn_1.Fn.select(4, components).toString();
|
316 | let resource;
|
317 | let resourceName;
|
318 | let sep;
|
319 | if (arnFormat === ArnFormat.NO_RESOURCE_NAME || arnFormat === ArnFormat.COLON_RESOURCE_NAME) {
|
320 | // we know that the 'resource' part will always be the 6th segment in this case
|
321 | resource = cfn_fn_1.Fn.select(5, components);
|
322 | if (arnFormat === ArnFormat.COLON_RESOURCE_NAME) {
|
323 | resourceName = cfn_fn_1.Fn.select(6, components);
|
324 | sep = ':';
|
325 | }
|
326 | else {
|
327 | resourceName = undefined;
|
328 | sep = undefined;
|
329 | }
|
330 | }
|
331 | else {
|
332 | // we know that the 'resource' and 'resourceName' parts are separated by slash here,
|
333 | // so we split the 6th segment from the colon-separated ones with a slash
|
334 | const lastComponents = cfn_fn_1.Fn.split('/', cfn_fn_1.Fn.select(5, components));
|
335 | if (arnFormat === ArnFormat.SLASH_RESOURCE_NAME) {
|
336 | resource = cfn_fn_1.Fn.select(0, lastComponents);
|
337 | resourceName = cfn_fn_1.Fn.select(1, lastComponents);
|
338 | }
|
339 | else {
|
340 | // arnFormat is ArnFormat.SLASH_RESOURCE_SLASH_RESOURCE_NAME,
|
341 | // which means there's an extra slash there at the beginning that we need to skip
|
342 | resource = cfn_fn_1.Fn.select(1, lastComponents);
|
343 | resourceName = cfn_fn_1.Fn.select(2, lastComponents);
|
344 | }
|
345 | sep = '/';
|
346 | }
|
347 | return { partition, service, region, account, resource, resourceName, sep, arnFormat };
|
348 | }
|
349 | /**
|
350 | * Validate that a string is either unparseable or looks mostly like an ARN
|
351 | */
|
352 | function parseArnShape(arn) {
|
353 | // assume anything that starts with 'arn:' is an ARN,
|
354 | // so we can report better errors
|
355 | const looksLikeArn = arn.startsWith('arn:');
|
356 | if (!looksLikeArn) {
|
357 | if (token_1.Token.isUnresolved(arn)) {
|
358 | return 'token';
|
359 | }
|
360 | else {
|
361 | throw new Error(`ARNs must start with "arn:" and have at least 6 components: ${arn}`);
|
362 | }
|
363 | }
|
364 | // If the ARN merely contains Tokens, but otherwise *looks* mostly like an ARN,
|
365 | // it's a string of the form 'arn:${partition}:service:${region}:${account}:resource/xyz'.
|
366 | // Parse fields out to the best of our ability.
|
367 | // Tokens won't contain ":", so this won't break them.
|
368 | const components = arn.split(':');
|
369 | const partition = components.length > 1 ? components[1] : undefined;
|
370 | if (!partition) {
|
371 | throw new Error('The `partition` component (2nd component) of an ARN is required: ' + arn);
|
372 | }
|
373 | const service = components.length > 2 ? components[2] : undefined;
|
374 | if (!service) {
|
375 | throw new Error('The `service` component (3rd component) of an ARN is required: ' + arn);
|
376 | }
|
377 | const resource = components.length > 5 ? components[5] : undefined;
|
378 | if (!resource) {
|
379 | throw new Error('The `resource` component (6th component) of an ARN is required: ' + arn);
|
380 | }
|
381 | // Region can be missing in global ARNs (such as used by IAM)
|
382 | // Account can be missing in some ARN types (such as used for S3 buckets)
|
383 | return components;
|
384 | }
|
385 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYXJuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHFDQUE4QjtBQUU5QixtQ0FBZ0M7QUFDaEMsaUNBQXlDO0FBRXpDOztHQUVHO0FBQ0gsSUFBWSxTQXVDWDtBQXZDRCxXQUFZLFNBQVM7SUFDbkI7Ozs7Ozs7T0FPRztJQUNILHlFQUE0RCxDQUFBO0lBRTVEOzs7Ozs7O09BT0c7SUFDSCx5RkFBNEUsQ0FBQTtJQUU1RTs7Ozs7OztPQU9HO0lBQ0gseUZBQTRFLENBQUE7SUFFNUU7Ozs7OztPQU1HO0lBQ0gseUdBQTRGLENBQUE7QUFDOUYsQ0FBQyxFQXZDVyxTQUFTLEdBQVQsaUJBQVMsS0FBVCxpQkFBUyxRQXVDcEI7QUFtRUQsTUFBYSxHQUFHO0lBd05kLGlCQUF5QjtJQXZOekI7Ozs7Ozs7Ozs7Ozs7Ozs7T0FnQkc7SUFDSSxNQUFNLENBQUMsTUFBTSxDQUFDLFVBQXlCLEVBQUUsS0FBYTs7Ozs7Ozs7Ozs7UUFDM0QsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLFNBQVMsSUFBSSxLQUFLLEVBQUUsU0FBUyxDQUFDO1FBQzNELE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLElBQUksS0FBSyxFQUFFLE1BQU0sQ0FBQztRQUNsRCxNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxJQUFJLEtBQUssRUFBRSxPQUFPLENBQUM7UUFFckQsb0NBQW9DO1FBQ3BDLElBQUksU0FBUyxJQUFJLElBQUksSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLE9BQU8sSUFBSSxJQUFJLEVBQUU7WUFDMUQsTUFBTSxJQUFJLEtBQUssQ0FBQywwQkFBMEIsU0FBUyxjQUFjLE1BQU0sbUJBQW1CLE9BQU8sOENBQThDLENBQUMsQ0FBQztTQUNsSjtRQUVELE1BQU0sR0FBRyxHQUFHLFVBQVUsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxtQkFB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QUErRTtJQUMvRSwwRkFBMEY7SUFDMUYsK0NBQStDO0lBQy9DLHNEQUFzRDtJQUN0RCxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBRWxDLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNwRSxJQUFJLENBQUMsU0FBUyxFQUFFO1FBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsR0FBRyxHQUFHLENBQUMsQ0FBQztLQUM1RjtJQUVELE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNsRSxJQUFJLENBQUMsT0FBTyxFQUFFO1FBQ1osTUFBTSxJQUFJLEtBQUssQ0FBQyxpRUFBaUUsR0FBRyxHQUFHLENBQUMsQ0FBQztLQUMxRjtJQUVELE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUNuRSxJQUFJLENBQUMsUUFBUSxFQUFFO1FBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQyxrRUFBa0UsR0FBRyxHQUFHLENBQUMsQ0FBQztLQUMzRjtJQUVELDZEQUE2RDtJQUU3RCx5RUFBeUU7SUFFekUsT0FBTyxVQUFVLENBQUM7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEZuIH0gZnJvbSAnLi9jZm4tZm4nO1xuaW1wb3J0IHsgU3RhY2sgfSBmcm9tICcuL3N0YWNrJztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5pbXBvcnQgeyBmaWx0ZXJVbmRlZmluZWQgfSBmcm9tICcuL3V0aWwnO1xuXG4vKipcbiAqIEFuIGVudW0gcmVwcmVzZW50aW5nIHRoZSB2YXJpb3VzIEFSTiBmb3JtYXRzIHRoYXQgZGlmZmVyZW50IHNlcnZpY2VzIHVzZS5cbiAqL1xuZXhwb3J0IGVudW0gQXJuRm9ybWF0IHtcbiAgLyoqXG4gICAqIFRoaXMgcmVwcmVzZW50cyBhIGZvcm1hdCB3aGVyZSB0aGVyZSBpcyBubyAncmVzb3VyY2VOYW1lJyBwYXJ0LlxuICAgKiBUaGlzIGZvcm1hdCBpcyB1c2VkIGZvciBTMyByZXNvdXJjZXMsXG4gICAqIGxpa2UgJ2Fybjphd3M6czM6OjpidWNrZXQnLlxuICAgKiBFdmVyeXRoaW5nIGFmdGVyIHRoZSBsYXN0IGNvbG9uIGlzIGNvbnNpZGVyZWQgdGhlICdyZXNvdXJjZScsXG4gICAqIGV2ZW4gaWYgaXQgY29udGFpbnMgc2xhc2hlcyxcbiAgICogbGlrZSBpbiAnYXJuOmF3czpzMzo6OmJ1Y2tldC9vYmplY3QuemlwJy5cbiAgICovXG4gIE5PX1JFU09VUkNFX05BTUUgPSAnYXJuOmF3czpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50OnJlc291cmNlJyxcblxuICAvKipcbiAgICogVGhpcyByZXByZXNlbnRzIGEgZm9ybWF0IHdoZXJlIHRoZSAncmVzb3VyY2UnIGFuZCAncmVzb3VyY2VOYW1lJ1xuICAgKiBwYXJ0cyBhcmUgc2VwYXJhdGVkIHdpdGggYSBjb2xvbi5cbiAgICogTGlrZSBpbjogJ2Fybjphd3M6c2VydmljZTpyZWdpb246YWNjb3VudDpyZXNvdXJjZTpyZXNvdXJjZU5hbWUnLlxuICAgKiBFdmVyeXRoaW5nIGFmdGVyIHRoZSBsYXN0IGNvbG9uIGlzIGNvbnNpZGVyZWQgdGhlICdyZXNvdXJjZU5hbWUnLFxuICAgKiBldmVuIGlmIGl0IGNvbnRhaW5zIHNsYXNoZXMsXG4gICAqIGxpa2UgaW4gJ2Fybjphd3M6YXBpZ2F0ZXdheTpyZWdpb246YWNjb3VudDpyZXNvdXJjZTovdGVzdC9teWRlbW9yZXNvdXJjZS8qJy5cbiAgICovXG4gIENPTE9OX1JFU09VUkNFX05BTUUgPSAnYXJuOmF3czpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50OnJlc291cmNlOnJlc291cmNlTmFtZScsXG5cbiAgLyoqXG4gICAqIFRoaXMgcmVwcmVzZW50cyBhIGZvcm1hdCB3aGVyZSB0aGUgJ3Jlc291cmNlJyBhbmQgJ3Jlc291cmNlTmFtZSdcbiAgICogcGFydHMgYXJlIHNlcGFyYXRlZCB3aXRoIGEgc2xhc2guXG4gICAqIExpa2UgaW46ICdhcm46YXdzOnNlcnZpY2U6cmVnaW9uOmFjY291bnQ6cmVzb3VyY2UvcmVzb3VyY2VOYW1lJy5cbiAgICogRXZlcnl0aGluZyBhZnRlciB0aGUgc2VwYXJhdGluZyBzbGFzaCBpcyBjb25zaWRlcmVkIHRoZSAncmVzb3VyY2VOYW1lJyxcbiAgICogZXZlbiBpZiBpdCBjb250YWlucyBjb2xvbnMsXG4gICAqIGxpa2UgaW4gJ2Fybjphd3M6Y29nbml0by1zeW5jOnJlZ2lvbjphY2NvdW50OmlkZW50aXR5cG9vbC91cy1lYXN0LTE6MWExYTFhMWEtZmZmZi0xMTExLTk5OTktMTIzNDU2Nzg6YmxhJy5cbiAgICovXG4gIFNMQVNIX1JFU09VUkNFX05BTUUgPSAnYXJuOmF3czpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50OnJlc291cmNlL3Jlc291cmNlTmFtZScsXG5cbiAgLyoqXG4gICAqIFRoaXMgcmVwcmVzZW50cyBhIGZvcm1hdCB3aGVyZSB0aGUgJ3Jlc291cmNlJyBhbmQgJ3Jlc291cmNlTmFtZSdcbiAgICogcGFydHMgYXJlIHNlcGVyYXRlZCB3aXRoIGEgc2xhc2gsXG4gICAqIGJ1dCB0aGVyZSBpcyBhbHNvIGFuIGFkZGl0aW9uYWwgc2xhc2ggYWZ0ZXIgdGhlIGNvbG9uIHNlcGFyYXRpbmcgJ2FjY291bnQnIGZyb20gJ3Jlc291cmNlJy5cbiAgICogTGlrZSBpbjogJ2Fybjphd3M6c2VydmljZTpyZWdpb246YWNjb3VudDovcmVzb3VyY2UvcmVzb3VyY2VOYW1lJy5cbiAgICogTm90ZSB0aGF0IHRoZSBsZWFkaW5nIHNsYXNoIGlzIF9ub3RfIGluY2x1ZGVkIGluIHRoZSBwYXJzZWQgJ3Jlc291cmNlJyBwYXJ0LlxuICAgKi9cbiAgU0xBU0hfUkVTT1VSQ0VfU0xBU0hfUkVTT1VSQ0VfTkFNRSA9ICdhcm46YXdzOnNlcnZpY2U6cmVnaW9uOmFjY291bnQ6L3Jlc291cmNlL3Jlc291cmNlTmFtZScsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXJuQ29tcG9uZW50cyB7XG4gIC8qKlxuICAgKiBUaGUgcGFydGl0aW9uIHRoYXQgdGhlIHJlc291cmNlIGlzIGluLiBGb3Igc3RhbmRhcmQgQVdTIHJlZ2lvbnMsIHRoZVxuICAgKiBwYXJ0aXRpb24gaXMgYXdzLiBJZiB5b3UgaGF2ZSByZXNvdXJjZXMgaW4gb3RoZXIgcGFydGl0aW9ucywgdGhlXG4gICAqIHBhcnRpdGlvbiBpcyBhd3MtcGFydGl0aW9ubmFtZS4gRm9yIGV4YW1wbGUsIHRoZSBwYXJ0aXRpb24gZm9yIHJlc291cmNlc1xuICAgKiBpbiB0aGUgQ2hpbmEgKEJlaWppbmcpIHJlZ2lvbiBpcyBhd3MtY24uXG4gICAqXG4gICAqIEBkZWZhdWx0IFRoZSBBV1MgcGFydGl0aW9uIHRoZSBzdGFjayBpcyBkZXBsb3llZCB0by5cbiAgICovXG4gIHJlYWRvbmx5IHBhcnRpdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHNlcnZpY2UgbmFtZXNwYWNlIHRoYXQgaWRlbnRpZmllcyB0aGUgQVdTIHByb2R1Y3QgKGZvciBleGFtcGxlLFxuICAgKiAnczMnLCAnaWFtJywgJ2NvZGVwaXBsaW5lJykuXG4gICAqL1xuICByZWFkb25seSBzZXJ2aWNlOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByZWdpb24gdGhlIHJlc291cmNlIHJlc2lkZXMgaW4uIE5vdGUgdGhhdCB0aGUgQVJOcyBmb3Igc29tZSByZXNvdXJjZXNcbiAgICogZG8gbm90IHJlcXVpcmUgYSByZWdpb24sIHNvIHRoaXMgY29tcG9uZW50IG1pZ2h0IGJlIG9taXR0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IFRoZSByZWdpb24gdGhlIHN0YWNrIGlzIGRlcGxveWVkIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgSUQgb2YgdGhlIEFXUyBhY2NvdW50IHRoYXQgb3ducyB0aGUgcmVzb3VyY2UsIHdpdGhvdXQgdGhlIGh5cGhlbnMuXG4gICAqIEZvciBleGFtcGxlLCAxMjM0NTY3ODkwMTIuIE5vdGUgdGhhdCB0aGUgQVJOcyBmb3Igc29tZSByZXNvdXJjZXMgZG9uJ3RcbiAgICogcmVxdWlyZSBhbiBhY2NvdW50IG51bWJlciwgc28gdGhpcyBjb21wb25lbnQgbWlnaHQgYmUgb21pdHRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgVGhlIGFjY291bnQgdGhlIHN0YWNrIGlzIGRlcGxveWVkIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgYWNjb3VudD86IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgdHlwZSAoZS5nLiBcInRhYmxlXCIsIFwiYXV0b1NjYWxpbmdHcm91cFwiLCBcImNlcnRpZmljYXRlXCIpLlxuICAgKiBGb3Igc29tZSByZXNvdXJjZSB0eXBlcywgZS5nLiBTMyBidWNrZXRzLCB0aGlzIGZpZWxkIGRlZmluZXMgdGhlIGJ1Y2tldCBuYW1lLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2U6IHN0cmluZztcblxuICAvKipcbiAgICogU2VwYXJhdG9yIGJldHdlZW4gcmVzb3VyY2UgdHlwZSBhbmQgdGhlIHJlc291cmNlLlxuICAgKlxuICAgKiBDYW4gYmUgZWl0aGVyICcvJywgJzonIG9yIGFuIGVtcHR5IHN0cmluZy4gV2lsbCBvbmx5IGJlIHVzZWQgaWYgcmVzb3VyY2VOYW1lIGlzIGRlZmluZWQuXG4gICAqIEBkZWZhdWx0ICcvJ1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYXJuRm9ybWF0IGluc3RlYWRcbiAgICovXG4gIHJlYWRvbmx5IHNlcD86IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgbmFtZSBvciBwYXRoIHdpdGhpbiB0aGUgcmVzb3VyY2UgKGkuZS4gUzMgYnVja2V0IG9iamVjdCBrZXkpIG9yXG4gICAqIGEgd2lsZGNhcmQgc3VjaCBhcyBgYFwiKlwiYGAuIFRoaXMgaXMgc2VydmljZS1kZXBlbmRlbnQuXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzcGVjaWZpYyBBUk4gZm9ybWF0IHRvIHVzZSBmb3IgdGhpcyBBUk4gdmFsdWUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdXNlcyB2YWx1ZSBvZiBgc2VwYCBhcyB0aGUgc2VwYXJhdG9yIGZvciBmb3JtYXR0aW5nLFxuICAgKiAgIGBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRWAgaWYgdGhhdCBwcm9wZXJ0eSB3YXMgYWxzbyBub3QgcHJvdmlkZWRcbiAgICovXG4gIHJlYWRvbmx5IGFybkZvcm1hdD86IEFybkZvcm1hdDtcbn1cblxuZXhwb3J0IGNsYXNzIEFybiB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIEFSTiBmcm9tIGNvbXBvbmVudHMuXG4gICAqXG4gICAqIElmIGBwYXJ0aXRpb25gLCBgcmVnaW9uYCBvciBgYWNjb3VudGAgYXJlIG5vdCBzcGVjaWZpZWQsIHRoZSBzdGFjaydzXG4gICAqIHBhcnRpdGlvbiwgcmVnaW9uIGFuZCBhY2NvdW50IHdpbGwgYmUgdXNlZC5cbiAgICpcbiAgICogSWYgYW55IGNvbXBvbmVudCBpcyB0aGUgZW1wdHkgc3RyaW5nLCBhbiBlbXB0eSBzdHJpbmcgd2lsbCBiZSBpbnNlcnRlZFxuICAgKiBpbnRvIHRoZSBnZW5lcmF0ZWQgQVJOIGF0IHRoZSBsb2NhdGlvbiB0aGF0IGNvbXBvbmVudCBjb3JyZXNwb25kcyB0by5cbiAgICpcbiAgICogVGhlIEFSTiB3aWxsIGJlIGZvcm1hdHRlZCBhcyBmb2xsb3dzOlxuICAgKlxuICAgKiAgIGFybjp7cGFydGl0aW9ufTp7c2VydmljZX06e3JlZ2lvbn06e2FjY291bnR9OntyZXNvdXJjZX17c2VwfXtyZXNvdXJjZS1uYW1lfVxuICAgKlxuICAgKiBUaGUgcmVxdWlyZWQgQVJOIHBpZWNlcyB0aGF0IGFyZSBvbWl0dGVkIHdpbGwgYmUgdGFrZW4gZnJvbSB0aGUgc3RhY2sgdGhhdFxuICAgKiB0aGUgJ3Njb3BlJyBpcyBhdHRhY2hlZCB0by4gSWYgYWxsIEFSTiBwaWVjZXMgYXJlIHN1cHBsaWVkLCB0aGUgc3VwcGxpZWQgc2NvcGVcbiAgICogY2FuIGJlICd1bmRlZmluZWQnLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmb3JtYXQoY29tcG9uZW50czogQXJuQ29tcG9uZW50cywgc3RhY2s/OiBTdGFjayk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydGl0aW9uID0gY29tcG9uZW50cy5wYXJ0aXRpb24gPz8gc3RhY2s/LnBhcnRpdGlvbjtcbiAgICBjb25zdCByZWdpb24gPSBjb21wb25lbnRzLnJlZ2lvbiA/PyBzdGFjaz8ucmVnaW9uO1xuICAgIGNvbnN0IGFjY291bnQgPSBjb21wb25lbnRzLmFjY291bnQgPz8gc3RhY2s/LmFjY291bnQ7XG5cbiAgICAvLyBDYXRjaCBib3RoICdudWxsJyBhbmQgJ3VuZGVmaW5lZCdcbiAgICBpZiAocGFydGl0aW9uID09IG51bGwgfHwgcmVnaW9uID09IG51bGwgfHwgYWNjb3VudCA9PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEFybi5mb3JtYXQ6IHBhcnRpdGlvbiAoJHtwYXJ0aXRpb259KSwgcmVnaW9uICgke3JlZ2lvbn0pLCBhbmQgYWNjb3VudCAoJHthY2NvdW50fSkgbXVzdCBhbGwgYmUgcGFzc2VkIGlmIHN0YWNrIGlzIG5vdCBwYXNzZWQuYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2VwID0gY29tcG9uZW50cy5zZXAgPz8gKGNvbXBvbmVudHMuYXJuRm9ybWF0ID09PSBBcm5Gb3JtYXQuQ09MT05fUkVTT1VSQ0VfTkFNRSA/ICc6JyA6ICcvJyk7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSBbXG4gICAgICAnYXJuJywgJzonLCBwYXJ0aXRpb24sICc6JywgY29tcG9uZW50cy5zZXJ2aWNlLCAnOicsIHJlZ2lvbiwgJzonLCBhY2NvdW50LCAnOicsXG4gICAgICAuLi4oY29tcG9uZW50cy5hcm5Gb3JtYXQgPT09IEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9TTEFTSF9SRVNPVVJDRV9OQU1FID8gWycvJ10gOiBbXSksXG4gICAgICBjb21wb25lbnRzLnJlc291cmNlLFxuICAgIF07XG5cbiAgICBpZiAoc2VwICE9PSAnLycgJiYgc2VwICE9PSAnOicgJiYgc2VwICE9PSAnJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZXNvdXJjZVBhdGhTZXAgbWF5IG9ubHkgYmUgXCI6XCIsIFwiL1wiIG9yIGFuIGVtcHR5IHN0cmluZycpO1xuICAgIH1cblxuICAgIGlmIChjb21wb25lbnRzLnJlc291cmNlTmFtZSAhPSBudWxsKSB7XG4gICAgICB2YWx1ZXMucHVzaChzZXApO1xuICAgICAgdmFsdWVzLnB1c2goY29tcG9uZW50cy5yZXNvdXJjZU5hbWUpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZXMuam9pbignJyk7XG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYW4gQVJOLCBwYXJzZXMgaXQgYW5kIHJldHVybnMgY29tcG9uZW50cy5cbiAgICpcbiAgICogSUYgVEhFIEFSTiBJUyBBIENPTkNSRVRFIFNUUklORy4uLlxuICAgKlxuICAgKiAuLi5pdCB3aWxsIGJlIHBhcnNlZCBhbmQgdmFsaWRhdGVkLiBUaGUgc2VwYXJhdG9yIChgc2VwYCkgd2lsbCBiZSBzZXQgdG8gJy8nXG4gICAqIGlmIHRoZSA2dGggY29tcG9uZW50IGluY2x1ZGVzIGEgJy8nLCBpbiB3aGljaCBjYXNlLCBgcmVzb3VyY2VgIHdpbGwgYmUgc2V0XG4gICAqIHRvIHRoZSB2YWx1ZSBiZWZvcmUgdGhlICcvJyBhbmQgYHJlc291cmNlTmFtZWAgd2lsbCBiZSB0aGUgcmVzdC4gSW4gY2FzZVxuICAgKiB0aGVyZSBpcyBubyAnLycsIGByZXNvdXJjZWAgd2lsbCBiZSBzZXQgdG8gdGhlIDZ0aCBjb21wb25lbnRzIGFuZFxuICAgKiBgcmVzb3VyY2VOYW1lYCB3aWxsIGJlIHNldCB0byB0aGUgcmVzdCBvZiB0aGUgc3RyaW5nLlxuICAgKlxuICAgKiBJRiBUSEUgQVJOIElTIEEgVE9LRU4uLi5cbiAgICpcbiAgICogLi4uaXQgY2Fubm90IGJlIHZhbGlkYXRlZCwgc2luY2Ugd2UgZG9uJ3QgaGF2ZSB0aGUgYWN0dWFsIHZhbHVlIHlldCBhdCB0aGVcbiAgICogdGltZSBvZiB0aGlzIGZ1bmN0aW9uIGNhbGwuIFlvdSB3aWxsIGhhdmUgdG8gc3VwcGx5IGBzZXBJZlRva2VuYCBhbmRcbiAgICogd2hldGhlciBvciBub3QgQVJOcyBvZiB0aGUgZXhwZWN0ZWQgZm9ybWF0IHVzdWFsbHkgaGF2ZSByZXNvdXJjZSBuYW1lc1xuICAgKiBpbiBvcmRlciB0byBwYXJzZSBpdCBwcm9wZXJseS4gVGhlIHJlc3VsdGluZyBgQXJuQ29tcG9uZW50c2Agb2JqZWN0IHdpbGxcbiAgICogY29udGFpbiB0b2tlbnMgZm9yIHRoZSBzdWJleHByZXNzaW9ucyBvZiB0aGUgQVJOLCBub3Qgc3RyaW5nIGxpdGVyYWxzLlxuICAgKlxuICAgKiBJZiB0aGUgcmVzb3VyY2UgbmFtZSBjb3VsZCBwb3NzaWJseSBjb250YWluIHRoZSBzZXBhcmF0b3IgY2hhciwgdGhlIGFjdHVhbFxuICAgKiByZXNvdXJjZSBuYW1lIGNhbm5vdCBiZSBwcm9wZXJseSBwYXJzZWQuIFRoaXMgb25seSBvY2N1cnMgaWYgdGhlIHNlcGFyYXRvclxuICAgKiBjaGFyIGlzICcvJywgYW5kIGhhcHBlbnMgZm9yIGV4YW1wbGUgZm9yIFMzIG9iamVjdCBBUk5zLCBJQU0gUm9sZSBBUk5zLFxuICAgKiBJQU0gT0lEQyBQcm92aWRlciBBUk5zLCBldGMuIFRvIHByb3Blcmx5IGV4dHJhY3QgdGhlIHJlc291cmNlIG5hbWUgZnJvbSBhXG4gICAqIFRva2VuaXplZCBBUk4sIHlvdSBtdXN0IGtub3cgdGhlIHJlc291cmNlIHR5cGUgYW5kIGNhbGxcbiAgICogYEFybi5leHRyYWN0UmVzb3VyY2VOYW1lYC5cbiAgICpcbiAgICogQHBhcmFtIGFybiBUaGUgQVJOIHRvIHBhcnNlXG4gICAqIEBwYXJhbSBzZXBJZlRva2VuIFRoZSBzZXBhcmF0b3IgdXNlZCB0byBzZXBhcmF0ZSByZXNvdXJjZSBmcm9tIHJlc291cmNlTmFtZVxuICAgKiBAcGFyYW0gaGFzTmFtZSBXaGV0aGVyIHRoZXJlIGlzIGEgbmFtZSBjb21wb25lbnQgaW4gdGhlIEFSTiBhdCBhbGwuIEZvclxuICAgKiBleGFtcGxlLCBTTlMgVG9waWNzIEFSTnMgaGF2ZSB0aGUgJ3Jlc291cmNlJyBjb21wb25lbnQgY29udGFpbiB0aGUgdG9waWNcbiAgICogbmFtZSwgYW5kIG5vICdyZXNvdXJjZU5hbWUnIGNvbXBvbmVudC5cbiAgICpcbiAgICogQHJldHVybnMgYW4gQXJuQ29tcG9uZW50cyBvYmplY3Qgd2hpY2ggYWxsb3dzIGFjY2VzcyB0byB0aGUgdmFyaW91c1xuICAgKiBjb21wb25lbnRzIG9mIHRoZSBBUk4uXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIEFybkNvbXBvbmVudHMgb2JqZWN0IHdoaWNoIGFsbG93cyBhY2Nlc3MgdG8gdGhlIHZhcmlvdXNcbiAgICogICAgICBjb21wb25lbnRzIG9mIHRoZSBBUk4uXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBzcGxpdCBpbnN0ZWFkXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHBhcnNlKGFybjogc3RyaW5nLCBzZXBJZlRva2VuOiBzdHJpbmcgPSAnLycsIGhhc05hbWU6IGJvb2xlYW4gPSB0cnVlKTogQXJuQ29tcG9uZW50cyB7XG4gICAgbGV0IGFybkZvcm1hdDogQXJuRm9ybWF0O1xuICAgIGlmICghaGFzTmFtZSkge1xuICAgICAgYXJuRm9ybWF0ID0gQXJuRm9ybWF0Lk5PX1JFU09VUkNFX05BTUU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGFybkZvcm1hdCA9IHNlcElmVG9rZW4gPT09ICcvJyA/IEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FIDogQXJuRm9ybWF0LkNPTE9OX1JFU09VUkNFX05BTUU7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNwbGl0KGFybiwgYXJuRm9ybWF0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdHMgdGhlIHByb3ZpZGVkIEFSTiBpbnRvIGl0cyBjb21wb25lbnRzLlxuICAgKiBXb3JrcyBib3RoIGlmICdhcm4nIGlzIGEgc3RyaW5nIGxpa2UgJ2Fybjphd3M6czM6OjpidWNrZXQnLFxuICAgKiBhbmQgYSBUb2tlbiByZXByZXNlbnRpbmcgYSBkeW5hbWljIENsb3VkRm9ybWF0aW9uIGV4cHJlc3Npb25cbiAgICogKGluIHdoaWNoIGNhc2UgdGhlIHJldHVybmVkIGNvbXBvbmVudHMgd2lsbCBhbHNvIGJlIGR5bmFtaWMgQ2xvdWRGb3JtYXRpb24gZXhwcmVzc2lvbnMsXG4gICAqIGVuY29kZWQgYXMgVG9rZW5zKS5cbiAgICpcbiAgICogQHBhcmFtIGFybiB0aGUgQVJOIHRvIHNwbGl0IGludG8gaXRzIGNvbXBvbmVudHNcbiAgICogQHBhcmFtIGFybkZvcm1hdCB0aGUgZXhwZWN0ZWQgZm9ybWF0IG9mICdhcm4nIC0gZGVwZW5kcyBvbiB3aGF0IGZvcm1hdCB0aGUgc2VydmljZSAnYXJuJyByZXByZXNlbnRzIHVzZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgc3BsaXQoYXJuOiBzdHJpbmcsIGFybkZvcm1hdDogQXJuRm9ybWF0KTogQXJuQ29tcG9uZW50cyB7XG4gICAgY29uc3QgY29tcG9uZW50cyA9IHBhcnNlQXJuU2hhcGUoYXJuKTtcbiAgICBpZiAoY29tcG9uZW50cyA9PT0gJ3Rva2VuJykge1xuICAgICAgcmV0dXJuIHBhcnNlVG9rZW5Bcm4oYXJuLCBhcm5Gb3JtYXQpO1xuICAgIH1cblxuICAgIGNvbnN0IFssIHBhcnRpdGlvbiwgc2VydmljZSwgcmVnaW9uLCBhY2NvdW50LCByZXNvdXJjZVR5cGVPck5hbWUsIC4uLnJlc3RdID0gY29tcG9uZW50cztcblxuICAgIGxldCByZXNvdXJjZTogc3RyaW5nO1xuICAgIGxldCByZXNvdXJjZU5hbWU6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBsZXQgc2VwOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgbGV0IHJlc291cmNlUGFydFN0YXJ0SW5kZXggPSAwO1xuICAgIGxldCBkZXRlY3RlZEFybkZvcm1hdDogQXJuRm9ybWF0O1xuXG4gICAgbGV0IHNsYXNoSW5kZXggPSByZXNvdXJjZVR5cGVPck5hbWUuaW5kZXhPZignLycpO1xuICAgIGlmIChzbGFzaEluZGV4ID09PSAwKSB7XG4gICAgICAvLyBuZXctc3R5bGUgQVJOcyBhcmUgb2YgdGhlIGZvcm0gJ2Fybjphd3M6czQ6dXMtd2VzdC0xOjEyMzQ1Oi9yZXNvdXJjZS10eXBlL3Jlc291cmNlLW5hbWUnXG4gICAgICBzbGFzaEluZGV4ID0gcmVzb3VyY2VUeXBlT3JOYW1lLmluZGV4T2YoJy8nLCAxKTtcbiAgICAgIHJlc291cmNlUGFydFN0YXJ0SW5kZXggPSAxO1xuICAgICAgZGV0ZWN0ZWRBcm5Gb3JtYXQgPSBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfU0xBU0hfUkVTT1VSQ0VfTkFNRTtcbiAgICB9XG4gICAgaWYgKHNsYXNoSW5kZXggIT09IC0xKSB7XG4gICAgICAvLyB0aGUgc2xhc2ggaXMgb25seSBhIHNlcGFyYXRvciBpZiBBcm5Gb3JtYXQgaXMgbm90IE5PX1JFU09VUkNFX05BTUVcbiAgICAgIGlmIChhcm5Gb3JtYXQgPT09IEFybkZvcm1hdC5OT19SRVNPVVJDRV9OQU1FKSB7XG4gICAgICAgIHNlcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgc2xhc2hJbmRleCA9IC0xO1xuICAgICAgICBkZXRlY3RlZEFybkZvcm1hdCA9IEFybkZvcm1hdC5OT19SRVNPVVJDRV9OQU1FO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2VwID0gJy8nO1xuICAgICAgICBkZXRlY3RlZEFybkZvcm1hdCA9IHJlc291cmNlUGFydFN0YXJ0SW5kZXggPT09IDBcbiAgICAgICAgICA/IEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FXG4gICAgICAgICAgLy8gbmVlZCB0byByZXBlYXQgdGhpcyBoZXJlLCBhcyBvdGhlcndpc2UgdGhlIGNvbXBpbGVyIHRoaW5rcyAnZGV0ZWN0ZWRBcm5Gb3JtYXQnIGlzIG5vdCBpbml0aWFsaXplZCBpbiBhbGwgcGF0aHNcbiAgICAgICAgICA6IEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9TTEFTSF9SRVNPVVJDRV9OQU1FO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocmVzdC5sZW5ndGggPiAwKSB7XG4gICAgICBzZXAgPSAnOic7XG4gICAgICBzbGFzaEluZGV4ID0gLTE7XG4gICAgICBkZXRlY3RlZEFybkZvcm1hdCA9IEFybkZvcm1hdC5DT0xPTl9SRVNPVVJDRV9OQU1FO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXAgPSB1bmRlZmluZWQ7XG4gICAgICBkZXRlY3RlZEFybkZvcm1hdCA9IEFybkZvcm1hdC5OT19SRVNPVVJDRV9OQU1FO1xuICAgIH1cblxuICAgIGlmIChzbGFzaEluZGV4ICE9PSAtMSkge1xuICAgICAgcmVzb3VyY2UgPSByZXNvdXJjZVR5cGVPck5hbWUuc3Vic3RyaW5nKHJlc291cmNlUGFydFN0YXJ0SW5kZXgsIHNsYXNoSW5kZXgpO1xuICAgICAgcmVzb3VyY2VOYW1lID0gcmVzb3VyY2VUeXBlT3JOYW1lLnN1YnN0cmluZyhzbGFzaEluZGV4ICsgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc291cmNlID0gcmVzb3VyY2VUeXBlT3JOYW1lO1xuICAgIH1cblxuICAgIGlmIChyZXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICghcmVzb3VyY2VOYW1lKSB7XG4gICAgICAgIHJlc291cmNlTmFtZSA9ICcnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb3VyY2VOYW1lICs9ICc6JztcbiAgICAgIH1cblxuICAgICAgcmVzb3VyY2VOYW1lICs9IHJlc3Quam9pbignOicpO1xuICAgIH1cblxuICAgIC8vIFwifHwgdW5kZWZpbmVkXCIgd2lsbCBjYXVzZSBlbXB0eSBzdHJpbmdzIHRvIGJlIHRyZWF0ZWQgYXMgXCJ1bmRlZmluZWRcIi5cbiAgICAvLyBPcHRpb25hbCBBUk4gYXR0cmlidXRlcyAoZS5nLiByZWdpb24sIGFjY291bnQpIHNob3VsZCByZXR1cm4gYXMgZW1wdHkgc3RyaW5nXG4gICAgLy8gaWYgdGhleSBhcmUgcHJvdmlkZWQgYXMgc3VjaC5cbiAgICByZXR1cm4gZmlsdGVyVW5kZWZpbmVkKHtcbiAgICAgIHNlcnZpY2U6IHNlcnZpY2UgfHwgdW5kZWZpbmVkLFxuICAgICAgcmVzb3VyY2U6IHJlc291cmNlIHx8IHVuZGVmaW5lZCxcbiAgICAgIHBhcnRpdGlvbjogcGFydGl0aW9uIHx8IHVuZGVmaW5lZCxcbiAgICAgIHJlZ2lvbixcbiAgICAgIGFjY291bnQsXG4gICAgICByZXNvdXJjZU5hbWUsXG4gICAgICBzZXAsXG4gICAgICBhcm5Gb3JtYXQ6IGRldGVjdGVkQXJuRm9ybWF0LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3QgdGhlIGZ1bGwgcmVzb3VyY2UgbmFtZSBmcm9tIGFuIEFSTlxuICAgKlxuICAgKiBOZWNlc3NhcnkgZm9yIHJlc291cmNlIG5hbWVzIChwYXRocykgdGhhdCBtYXkgY29udGFpbiB0aGUgc2VwYXJhdG9yLCBsaWtlXG4gICAqIGBhcm46YXdzOmlhbTo6MTExMTExMTExMTExOnJvbGUvcGF0aC90by9yb2xlL25hbWVgLlxuICAgKlxuICAgKiBPbmx5IHdvcmtzIGlmIHdlIHN0YXRpY2FsbHkga25vdyB0aGUgZXhwZWN0ZWQgYHJlc291cmNlVHlwZWAgYmVmb3JlaGFuZCwgc2luY2Ugd2UncmUgZ29pbmdcbiAgICogdG8gdXNlIHRoYXQgdG8gc3BsaXQgdGhlIHN0cmluZyBvbiAnOjxyZXNvdXJjZVR5cGU+LycgKGFuZCB0YWtlIHRoZSByaWdodC1oYW5kIHNpZGUpLlxuICAgKlxuICAgKiBXZSBjYW4ndCBleHRyYWN0IHRoZSAncmVzb3VyY2VUeXBlJyBmcm9tIHRoZSBBUk4gYXQgaGFuZCwgYmVjYXVzZSBDbG91ZEZvcm1hdGlvbiBFeHByZXNzaW9uc1xuICAgKiBvbmx5IGFsbG93IGxpdGVyYWxzIGluIHRoZSAnc2VwYXJhdG9yJyBhcmd1bWVudCB0byBgeyBGbjo6U3BsaXQgfWAsIGFuZCBzbyBpdCBjYW4ndCBiZVxuICAgKiBgeyBGbjo6U2VsZWN0OiBbNSwgeyBGbjo6U3BsaXQ6IFsnOicsIEFSTl0gfX1gLlxuICAgKlxuICAgKiBPbmx5IG5lY2Vzc2FyeSBmb3IgQVJOIGZvcm1hdHMgZm9yIHdoaWNoIHRoZSB0eXBlLW5hbWUgc2VwYXJhdG9yIGlzIGAvYC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZXh0cmFjdFJlc291cmNlTmFtZShhcm46IHN0cmluZywgcmVzb3VyY2VUeXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNvbXBvbmVudHMgPSBwYXJzZUFyblNoYXBlKGFybik7XG4gICAgaWYgKGNvbXBvbmVudHMgPT09ICd0b2tlbicpIHtcbiAgICAgIHJldHVybiBGbi5zZWxlY3QoMSwgRm4uc3BsaXQoYDoke3Jlc291cmNlVHlwZX0vYCwgYXJuKSk7XG4gICAgfVxuXG4gICAgLy8gQXBwYXJlbnRseSB3ZSBjb3VsZCBqdXN0IHBhcnNlIHRoaXMgcmlnaHQgYXdheS4gVmFsaWRhdGUgdGhhdCB3ZSBnb3QgdGhlIHJpZ2h0XG4gICAgLy8gcmVzb3VyY2UgdHlwZSAodG8gbm90aWZ5IGF1dGhvcnMgb2YgaW5jb3JyZWN0IGFzc3VtcHRpb25zIHJpZ2h0IGF3YXkpLlxuICAgIGNvbnN0IHBhcnNlZCA9IEFybi5zcGxpdChhcm4sIEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FKTtcbiAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChwYXJzZWQucmVzb3VyY2UpICYmIHBhcnNlZC5yZXNvdXJjZSAhPT0gcmVzb3VyY2VUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIHJlc291cmNlIHR5cGUgJyR7cmVzb3VyY2VUeXBlfScgaW4gQVJOLCBnb3QgJyR7cGFyc2VkLnJlc291cmNlfScgaW4gJyR7YXJufSdgKTtcbiAgICB9XG4gICAgaWYgKCFwYXJzZWQucmVzb3VyY2VOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIHJlc291cmNlIG5hbWUgaW4gQVJOLCBkaWRuJ3QgZmluZCBvbmU6ICcke2Fybn0nYCk7XG4gICAgfVxuICAgIHJldHVybiBwYXJzZWQucmVzb3VyY2VOYW1lO1xuICB9XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHsgfVxufVxuXG4vKipcbiAqIEdpdmVuIGEgVG9rZW4gZXZhbHVhdGluZyB0byBBUk4sIHBhcnNlcyBpdCBhbmQgcmV0dXJucyBjb21wb25lbnRzLlxuICpcbiAqIFRoZSBBUk4gY2Fubm90IGJlIHZhbGlkYXRlZCwgc2luY2Ugd2UgZG9uJ3QgaGF2ZSB0aGUgYWN0dWFsIHZhbHVlIHlldFxuICogYXQgdGhlIHRpbWUgb2YgdGhpcyBmdW5jdGlvbiBjYWxsLiBZb3Ugd2lsbCBoYXZlIHRvIGtub3cgdGhlIHNlcGFyYXRvclxuICogYW5kIHRoZSB0eXBlIG9mIEFSTi5cbiAqXG4gKiBUaGUgcmVzdWx0aW5nIGBBcm5Db21wb25lbnRzYCBvYmplY3Qgd2lsbCBjb250YWluIHRva2VucyBmb3IgdGhlXG4gKiBzdWJleHByZXNzaW9ucyBvZiB0aGUgQVJOLCBub3Qgc3RyaW5nIGxpdGVyYWxzLlxuICpcbiAqIFdBUk5JTkc6IHRoaXMgZnVuY3Rpb24gY2Fubm90IHByb3Blcmx5IHBhcnNlIHRoZSBjb21wbGV0ZSBmaW5hbFxuICogJ3Jlc291cmNlTmFtZScgcGFydCBpZiBpdCBjb250YWlucyBjb2xvbnMsXG4gKiBsaWtlICdhcm46YXdzOmNvZ25pdG8tc3luYzpyZWdpb246YWNjb3VudDppZGVudGl0eXBvb2wvdXMtZWFzdC0xOjFhMWExYTFhLWZmZmYtMTExMS05OTk5LTEyMzQ1Njc4OmJsYScuXG4gKlxuICogQHBhcmFtIGFyblRva2VuIFRoZSBpbnB1dCB0b2tlbiB0aGF0IGNvbnRhaW5zIGFuIEFSTlxuICogQHBhcmFtIGFybkZvcm1hdCB0aGUgZXhwZWN0ZWQgZm9ybWF0IG9mICdhcm4nIC0gZGVwZW5kcyBvbiB3aGF0IGZvcm1hdCB0aGUgc2VydmljZSB0aGUgQVJOIHJlcHJlc2VudHMgdXNlc1xuICovXG5mdW5jdGlvbiBwYXJzZVRva2VuQXJuKGFyblRva2VuOiBzdHJpbmcsIGFybkZvcm1hdDogQXJuRm9ybWF0KTogQXJuQ29tcG9uZW50cyB7XG4gIC8vIEFSTiBsb29rcyBsaWtlOlxuICAvLyBhcm46cGFydGl0aW9uOnNlcnZpY2U6cmVnaW9uOmFjY291bnQ6cmVzb3VyY2VcbiAgLy8gYXJuOnBhcnRpdGlvbjpzZXJ2aWNlOnJlZ2lvbjphY2NvdW50OnJlc291cmNlOnJlc291cmNlTmFtZVxuICAvLyBhcm46cGFydGl0aW9uOnNlcnZpY2U6cmVnaW9uOmFjY291bnQ6cmVzb3VyY2UvcmVzb3VyY2VOYW1lXG4gIC8vIGFybjpwYXJ0aXRpb246c2VydmljZTpyZWdpb246YWNjb3VudDovcmVzb3VyY2UvcmVzb3VyY2VOYW1lXG5cbiAgY29uc3QgY29tcG9uZW50cyA9IEZuLnNwbGl0KCc6JywgYXJuVG9rZW4pO1xuXG4gIGNvbnN0IHBhcnRpdGlvbiA9IEZuLnNlbGVjdCgxLCBjb21wb25lbnRzKS50b1N0cmluZygpO1xuICBjb25zdCBzZXJ2aWNlID0gRm4uc2VsZWN0KDIsIGNvbXBvbmVudHMpLnRvU3RyaW5nKCk7XG4gIGNvbnN0IHJlZ2lvbiA9IEZuLnNlbGVjdCgzLCBjb21wb25lbnRzKS50b1N0cmluZygpO1xuICBjb25zdCBhY2NvdW50ID0gRm4uc2VsZWN0KDQsIGNvbXBvbmVudHMpLnRvU3RyaW5nKCk7XG4gIGxldCByZXNvdXJjZTogc3RyaW5nO1xuICBsZXQgcmVzb3VyY2VOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGxldCBzZXA6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBpZiAoYXJuRm9ybWF0ID09PSBBcm5Gb3JtYXQuTk9fUkVTT1VSQ0VfTkFNRSB8fCBhcm5Gb3JtYXQgPT09IEFybkZvcm1hdC5DT0xPTl9SRVNPVVJDRV9OQU1FKSB7XG4gICAgLy8gd2Uga25vdyB0aGF0IHRoZSAncmVzb3VyY2UnIHBhcnQgd2lsbCBhbHdheXMgYmUgdGhlIDZ0aCBzZWdtZW50IGluIHRoaXMgY2FzZVxuICAgIHJlc291cmNlID0gRm4uc2VsZWN0KDUsIGNvbXBvbmVudHMpO1xuICAgIGlmIChhcm5Gb3JtYXQgPT09IEFybkZvcm1hdC5DT0xPTl9SRVNPVVJDRV9OQU1FKSB7XG4gICAgICByZXNvdXJjZU5hbWUgPSBGbi5zZWxlY3QoNiwgY29tcG9uZW50cyk7XG4gICAgICBzZXAgPSAnOic7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc291cmNlTmFtZSA9IHVuZGVmaW5lZDtcbiAgICAgIHNlcCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gd2Uga25vdyB0aGF0IHRoZSAncmVzb3VyY2UnIGFuZCAncmVzb3VyY2VOYW1lJyBwYXJ0cyBhcmUgc2VwYXJhdGVkIGJ5IHNsYXNoIGhlcmUsXG4gICAgLy8gc28gd2Ugc3BsaXQgdGhlIDZ0aCBzZWdtZW50IGZyb20gdGhlIGNvbG9uLXNlcGFyYXRlZCBvbmVzIHdpdGggYSBzbGFzaFxuICAgIGNvbnN0IGxhc3RDb21wb25lbnRzID0gRm4uc3BsaXQoJy8nLCBGbi5zZWxlY3QoNSwgY29tcG9uZW50cykpO1xuXG4gICAgaWYgKGFybkZvcm1hdCA9PT0gQXJuRm9ybWF0LlNMQVNIX1JFU09VUkNFX05BTUUpIHtcbiAgICAgIHJlc291cmNlID0gRm4uc2VsZWN0KDAsIGxhc3RDb21wb25lbnRzKTtcbiAgICAgIHJlc291cmNlTmFtZSA9IEZuLnNlbGVjdCgxLCBsYXN0Q29tcG9uZW50cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGFybkZvcm1hdCBpcyBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfU0xBU0hfUkVTT1VSQ0VfTkFNRSxcbiAgICAgIC8vIHdoaWNoIG1lYW5zIHRoZXJlJ3MgYW4gZXh0cmEgc2xhc2ggdGhlcmUgYXQgdGhlIGJlZ2lubmluZyB0aGF0IHdlIG5lZWQgdG8gc2tpcFxuICAgICAgcmVzb3VyY2UgPSBGbi5zZWxlY3QoMSwgbGFzdENvbXBvbmVudHMpO1xuICAgICAgcmVzb3VyY2VOYW1lID0gRm4uc2VsZWN0KDIsIGxhc3RDb21wb25lbnRzKTtcbiAgICB9XG4gICAgc2VwID0gJy8nO1xuICB9XG5cbiAgcmV0dXJuIHsgcGFydGl0aW9uLCBzZXJ2aWNlLCByZWdpb24sIGFjY291bnQsIHJlc291cmNlLCByZXNvdXJjZU5hbWUsIHNlcCwgYXJuRm9ybWF0IH07XG59XG5cbi8qKlxuICogVmFsaWRhdGUgdGhhdCBhIHN0cmluZyBpcyBlaXRoZXIgdW5wYXJzZWFibGUgb3IgbG9va3MgbW9zdGx5IGxpa2UgYW4gQVJOXG4gKi9cbmZ1bmN0aW9uIHBhcnNlQXJuU2hhcGUoYXJuOiBzdHJpbmcpOiAndG9rZW4nIHwgc3RyaW5nW10ge1xuICAvLyBhc3N1bWUgYW55dGhpbmcgdGhhdCBzdGFydHMgd2l0aCAnYXJuOicgaXMgYW4gQVJOLFxuICAvLyBzbyB3ZSBjYW4gcmVwb3J0IGJldHRlciBlcnJvcnNcbiAgY29uc3QgbG9va3NMaWtlQXJuID0gYXJuLnN0YXJ0c1dpdGgoJ2FybjonKTtcblxuICBpZiAoIWxvb2tzTGlrZUFybikge1xuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQoYXJuKSkge1xuICAgICAgcmV0dXJuICd0b2tlbic7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQVJOcyBtdXN0IHN0YXJ0IHdpdGggXCJhcm46XCIgYW5kIGhhdmUgYXQgbGVhc3QgNiBjb21wb25lbnRzOiAke2Fybn1gKTtcbiAgICB9XG4gIH1cblxuICAvLyBJZiB0aGUgQVJOIG1lcmVseSBjb250YWlucyBUb2tlbnMsIGJ1dCBvdGhlcndpc2UgKmxvb2tzKiBtb3N0bHkgbGlrZSBhbiBBUk4sXG4gIC8vIGl0J3MgYSBzdHJpbmcgb2YgdGhlIGZvcm0gJ2Fybjoke3BhcnRpdGlvbn06c2VydmljZToke3JlZ2lvbn06JHthY2NvdW50fTpyZXNvdXJjZS94eXonLlxuICAvLyBQYXJzZSBmaWVsZHMgb3V0IHRvIHRoZSBiZXN0IG9mIG91ciBhYmlsaXR5LlxuICAvLyBUb2tlbnMgd29uJ3QgY29udGFpbiBcIjpcIiwgc28gdGhpcyB3b24ndCBicmVhayB0aGVtLlxuICBjb25zdCBjb21wb25lbnRzID0gYXJuLnNwbGl0KCc6Jyk7XG5cbiAgY29uc3QgcGFydGl0aW9uID0gY29tcG9uZW50cy5sZW5ndGggPiAxID8gY29tcG9uZW50c1sxXSA6IHVuZGVmaW5lZDtcbiAgaWYgKCFwYXJ0aXRpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBgcGFydGl0aW9uYCBjb21wb25lbnQgKDJuZCBjb21wb25lbnQpIG9mIGFuIEFSTiBpcyByZXF1aXJlZDogJyArIGFybik7XG4gIH1cblxuICBjb25zdCBzZXJ2aWNlID0gY29tcG9uZW50cy5sZW5ndGggPiAyID8gY29tcG9uZW50c1syXSA6IHVuZGVmaW5lZDtcbiAgaWYgKCFzZXJ2aWNlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgYHNlcnZpY2VgIGNvbXBvbmVudCAoM3JkIGNvbXBvbmVudCkgb2YgYW4gQVJOIGlzIHJlcXVpcmVkOiAnICsgYXJuKTtcbiAgfVxuXG4gIGNvbnN0IHJlc291cmNlID0gY29tcG9uZW50cy5sZW5ndGggPiA1ID8gY29tcG9uZW50c1s1XSA6IHVuZGVmaW5lZDtcbiAgaWYgKCFyZXNvdXJjZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhlIGByZXNvdXJjZWAgY29tcG9uZW50ICg2dGggY29tcG9uZW50KSBvZiBhbiBBUk4gaXMgcmVxdWlyZWQ6ICcgKyBhcm4pO1xuICB9XG5cbiAgLy8gUmVnaW9uIGNhbiBiZSBtaXNzaW5nIGluIGdsb2JhbCBBUk5zIChzdWNoIGFzIHVzZWQgYnkgSUFNKVxuXG4gIC8vIEFjY291bnQgY2FuIGJlIG1pc3NpbmcgaW4gc29tZSBBUk4gdHlwZXMgKHN1Y2ggYXMgdXNlZCBmb3IgUzMgYnVja2V0cylcblxuICByZXR1cm4gY29tcG9uZW50cztcbn1cbiJdfQ== |
\ | No newline at end of file |