UNPKG

50.8 kBJavaScriptView Raw
1/**
2 * @fileoverview added by tsickle
3 * @suppress {checkTypes} checked by tsc
4 */
5import * as tslib_1 from "tslib";
6import { Injectable } from '@angular/core';
7import { Router } from '@angular/router';
8import { Storage } from '@ubud/storage';
9import { Config } from '../values/config';
10import { User } from '../models/user';
11import { forkJoin, from, Observable, of } from 'rxjs';
12import { catchError, map, switchMap, tap } from 'rxjs/operators';
13import { plainToClass } from 'class-transformer';
14import { HttpClient } from '@angular/common/http';
15import { Location } from '@angular/common';
16import { fromPromise } from 'rxjs-compat/observable/fromPromise';
17var NacoService = /** @class */ (function () {
18 function NacoService(config, router, storage, http, location) {
19 this.config = config;
20 this.router = router;
21 this.storage = storage;
22 this.http = http;
23 this.location = location;
24 this.VERSION = 'v1';
25 this.signature = null;
26 this.user = null;
27 this.refreshToken = null;
28 this.clientSecret = null;
29 if (this.config.clientSecret) {
30 this.setClientSecret(this.config.clientSecret);
31 }
32 }
33 /**
34 * @param {?} user
35 * @return {?}
36 */
37 NacoService.prototype.setUser = /**
38 * @param {?} user
39 * @return {?}
40 */
41 function (user) {
42 this.user = user;
43 };
44 /**
45 * @return {?}
46 */
47 NacoService.prototype.getUser = /**
48 * @return {?}
49 */
50 function () {
51 var _this = this;
52 if (null !== this.user) {
53 return of(this.user);
54 }
55 var /** @type {?} */ uri = this.getUri('/users/me');
56 return from(this.getSignature()).pipe(switchMap(function (signature) {
57 if (!signature) {
58 return _this.refreshUser(_this.config.scopes);
59 }
60 var /** @type {?} */ options = {
61 headers: {
62 Authorization: signature.type + " " + signature.token,
63 },
64 };
65 return _this.http.get(uri, options).pipe(map(function (res) {
66 if (res.data) {
67 return res.data;
68 }
69 throw new Error('There are no body to be transformed');
70 }), map(function (data) {
71 var /** @type {?} */ authUser = plainToClass(User, data);
72 _this.setUser(authUser);
73 return authUser;
74 }), catchError(function (e) {
75 if (401 === e.status) {
76 return _this.refreshUser(signature.scopes);
77 }
78 return of(null);
79 }));
80 }));
81 };
82 /**
83 * @param {?} user
84 * @return {?}
85 */
86 NacoService.prototype.getProfilePicture = /**
87 * @param {?} user
88 * @return {?}
89 */
90 function (user) {
91 return this.config.endpoint + '/users/' + user + '/picture';
92 };
93 /**
94 * @return {?}
95 */
96 NacoService.prototype.getSignature = /**
97 * @return {?}
98 */
99 function () {
100 if (this.signature) {
101 return Promise.resolve(this.signature);
102 }
103 return this.storage.get('signature');
104 };
105 /**
106 * @param {?} signature
107 * @return {?}
108 */
109 NacoService.prototype.setSignature = /**
110 * @param {?} signature
111 * @return {?}
112 */
113 function (signature) {
114 this.signature = signature;
115 this.storage.set('signature', signature);
116 };
117 /**
118 * @param {?} secret
119 * @return {?}
120 */
121 NacoService.prototype.setClientSecret = /**
122 * @param {?} secret
123 * @return {?}
124 */
125 function (secret) {
126 this.clientSecret = secret;
127 };
128 /**
129 * @param {?} refreshToken
130 * @return {?}
131 */
132 NacoService.prototype.setRefreshToken = /**
133 * @param {?} refreshToken
134 * @return {?}
135 */
136 function (refreshToken) {
137 this.refreshToken = refreshToken;
138 this.storage.set('refresh_token', refreshToken);
139 };
140 /**
141 * @param {?=} scopes
142 * @return {?}
143 */
144 NacoService.prototype.refreshUser = /**
145 * @param {?=} scopes
146 * @return {?}
147 */
148 function (scopes) {
149 var _this = this;
150 this.setUser(null);
151 this.setSignature(null);
152 return forkJoin(this.getRefreshToken(), this.getClientSecret()).pipe(switchMap(function (results) {
153 var /** @type {?} */ refreshToken = results[0];
154 var /** @type {?} */ clientSecret = results[1];
155 if (refreshToken && clientSecret) {
156 return _this.refreshWithRefreshToken(clientSecret, refreshToken.token, scopes);
157 }
158 return _this.refreshWithSilentAuth(scopes);
159 }));
160 };
161 /**
162 * @param {?} clientSecret
163 * @param {?} refreshToken
164 * @param {?=} scopes
165 * @return {?}
166 */
167 NacoService.prototype.refreshWithRefreshToken = /**
168 * @param {?} clientSecret
169 * @param {?} refreshToken
170 * @param {?=} scopes
171 * @return {?}
172 */
173 function (clientSecret, refreshToken, scopes) {
174 var _this = this;
175 var /** @type {?} */ request = this.http.post(this.getUri('/tokens'), {
176 grant_type: 'refresh_token',
177 scopes: scopes || this.config.scopes,
178 client_id: this.config.clientId,
179 client_secret: clientSecret,
180 refresh_token: refreshToken,
181 });
182 return request.pipe(tap(function (tokens) {
183 if (tokens && tokens.data) {
184 _this.setSignature({
185 expiresIn: tokens.data.expires_in,
186 type: tokens.data.token_type,
187 token: tokens.data.access_token,
188 scopes: decodeURIComponent(tokens.data.scopes || _this.config.scopes),
189 });
190 _this.setRefreshToken({
191 type: tokens.data.token_type,
192 token: tokens.data.refresh_token,
193 });
194 }
195 }), map(function (tokens) { return tokens && tokens.data; }), switchMap(function (hasToken) {
196 if (hasToken) {
197 return _this.getUser();
198 }
199 return of(null);
200 }));
201 };
202 /**
203 * @param {?=} scopes
204 * @return {?}
205 */
206 NacoService.prototype.refreshWithSilentAuth = /**
207 * @param {?=} scopes
208 * @return {?}
209 */
210 function (scopes) {
211 var _this = this;
212 return new Observable(function (observer) {
213 var /** @type {?} */ redirectUri = _this.getCurrentOrigin('auth/silent');
214 var /** @type {?} */ uri = _this.login(scopes || _this.config.scopes, redirectUri, true, 'token', false);
215 var /** @type {?} */ iframe = document.createElement('iframe');
216 iframe.setAttribute('src', uri);
217 iframe.style.display = 'none';
218 iframe.addEventListener('load', function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
219 var e_1, _a, queryString, queryParts, params, queryParts_1, queryParts_1_1, item, itemParts, user, e_2;
220 return tslib_1.__generator(this, function (_b) {
221 switch (_b.label) {
222 case 0:
223 _b.trys.push([0, 5, , 6]);
224 queryString = iframe.contentWindow.location.search.substring(1);
225 iframe.parentNode.removeChild(iframe);
226 if (!queryString) return [3 /*break*/, 4];
227 queryParts = queryString.split('&');
228 params = {};
229 try {
230 for (queryParts_1 = tslib_1.__values(queryParts), queryParts_1_1 = queryParts_1.next(); !queryParts_1_1.done; queryParts_1_1 = queryParts_1.next()) {
231 item = queryParts_1_1.value;
232 itemParts = item.split('=');
233 params[itemParts[0]] = itemParts[1];
234 }
235 }
236 catch (e_1_1) { e_1 = { error: e_1_1 }; }
237 finally {
238 try {
239 if (queryParts_1_1 && !queryParts_1_1.done && (_a = queryParts_1.return)) _a.call(queryParts_1);
240 }
241 finally { if (e_1) throw e_1.error; }
242 }
243 if (!params.hasOwnProperty('access_token')) return [3 /*break*/, 2];
244 this.setSignature({
245 token: params['access_token'],
246 type: params['token_type'],
247 expiresIn: params['expires_in'],
248 scopes: decodeURIComponent(params['scopes'] || this.config.scopes),
249 });
250 return [4 /*yield*/, this.getUser().toPromise()];
251 case 1:
252 user = _b.sent();
253 if (user) {
254 this.setUser(user);
255 }
256 observer.next(user);
257 return [3 /*break*/, 3];
258 case 2:
259 observer.next(null);
260 _b.label = 3;
261 case 3: return [2 /*return*/];
262 case 4:
263 observer.next(null);
264 return [3 /*break*/, 6];
265 case 5:
266 e_2 = _b.sent();
267 observer.next(null);
268 return [3 /*break*/, 6];
269 case 6: return [2 /*return*/];
270 }
271 });
272 }); }, false);
273 document.body.appendChild(iframe);
274 });
275 };
276 /**
277 * @param {?} code
278 * @param {?} redirectUri
279 * @param {?=} scopes
280 * @return {?}
281 */
282 NacoService.prototype.getAccessTokenFromAuthCode = /**
283 * @param {?} code
284 * @param {?} redirectUri
285 * @param {?=} scopes
286 * @return {?}
287 */
288 function (code, redirectUri, scopes) {
289 var _this = this;
290 return fromPromise(this.getState()).pipe(switchMap(function (state) {
291 var /** @type {?} */ params = {
292 code: code,
293 grant_type: 'authorization_code',
294 scopes: scopes || _this.config.scopes,
295 client_id: _this.config.clientId,
296 client_secret: _this.config.clientSecret,
297 redirect_uri: redirectUri,
298 };
299 if (state) {
300 params["state"] = state;
301 }
302 return _this.http.post(_this.getUri('/tokens'), params);
303 }), map(function (res) {
304 if (res.data) {
305 return res.data;
306 }
307 throw new Error('There are no body to be transformed');
308 }));
309 };
310 /**
311 * @param {?} scopes
312 * @param {?=} redirectUri
313 * @param {?=} silent
314 * @param {?=} responseType
315 * @param {?=} needState
316 * @return {?}
317 */
318 NacoService.prototype.login = /**
319 * @param {?} scopes
320 * @param {?=} redirectUri
321 * @param {?=} silent
322 * @param {?=} responseType
323 * @param {?=} needState
324 * @return {?}
325 */
326 function (scopes, redirectUri, silent, responseType, needState) {
327 if (silent === void 0) { silent = false; }
328 if (responseType === void 0) { responseType = 'token'; }
329 if (needState === void 0) { needState = true; }
330 if (!redirectUri) {
331 redirectUri = this.router.url;
332 }
333 var /** @type {?} */ params = {
334 response_type: responseType,
335 scopes: scopes,
336 client: this.config.clientId,
337 silent: silent,
338 continue: encodeURIComponent(redirectUri),
339 };
340 if (needState) {
341 var /** @type {?} */ state = this.generateState();
342 this.storage.set('state', state);
343 params.state = state;
344 }
345 var /** @type {?} */ query = this.buildQueryString(params);
346 return this.config.endpoint + '/auth?' + query;
347 };
348 /**
349 * @param {?=} redirectUri
350 * @return {?}
351 */
352 NacoService.prototype.logout = /**
353 * @param {?=} redirectUri
354 * @return {?}
355 */
356 function (redirectUri) {
357 var _this = this;
358 this.signature = null;
359 this.user = null;
360 this.refreshToken = null;
361 return new Promise(function (resolve) {
362 var /** @type {?} */ clear = [_this.storage.remove('signature'), _this.storage.remove('user'), _this.storage.remove('refresh_token')];
363 Promise.all(clear).then(function () {
364 var /** @type {?} */ endpoint = _this.config.endpoint + '/auth/logout';
365 if (redirectUri) {
366 endpoint += '?continue=' + encodeURIComponent(redirectUri);
367 }
368 resolve(endpoint);
369 });
370 });
371 };
372 /**
373 * @return {?}
374 */
375 NacoService.prototype.getState = /**
376 * @return {?}
377 */
378 function () {
379 return this.storage.get('state');
380 };
381 /**
382 * @param {?} route
383 * @return {?}
384 */
385 NacoService.prototype.buildNestedUri = /**
386 * @param {?} route
387 * @return {?}
388 */
389 function (route) {
390 var _this = this;
391 var /** @type {?} */ uri = '';
392 if (route.routeConfig && route.routeConfig.path) {
393 var /** @type {?} */ routePath = route.routeConfig.path;
394 for (var /** @type {?} */ key in route.params) {
395 if (key) {
396 var /** @type {?} */ re = new RegExp(':' + key);
397 routePath = routePath.replace(re, route.params[key]);
398 }
399 }
400 uri += '/' + routePath;
401 }
402 if (route.children) {
403 route.children.forEach(function (item) {
404 uri += _this.buildNestedUri(item);
405 });
406 }
407 return uri;
408 };
409 /**
410 * @return {?}
411 */
412 NacoService.prototype.getRefreshToken = /**
413 * @return {?}
414 */
415 function () {
416 if (null !== this.refreshToken) {
417 return Promise.resolve(this.refreshToken);
418 }
419 return this.storage.get('refresh_token');
420 };
421 /**
422 * @return {?}
423 */
424 NacoService.prototype.getClientSecret = /**
425 * @return {?}
426 */
427 function () {
428 if (null !== this.clientSecret) {
429 return Promise.resolve(this.clientSecret);
430 }
431 return this.storage.get('client_secret');
432 };
433 /**
434 * @param {?} path
435 * @return {?}
436 */
437 NacoService.prototype.getUri = /**
438 * @param {?} path
439 * @return {?}
440 */
441 function (path) {
442 return this.config.endpoint + '/api/' + this.VERSION + path;
443 };
444 /**
445 * @param {?=} path
446 * @return {?}
447 */
448 NacoService.prototype.getCurrentOrigin = /**
449 * @param {?=} path
450 * @return {?}
451 */
452 function (path) {
453 return window.location.origin + this.location.prepareExternalUrl(path || '');
454 };
455 /**
456 * @return {?}
457 */
458 NacoService.prototype.generateState = /**
459 * @return {?}
460 */
461 function () {
462 var /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
463 var /** @type {?} */ text = '';
464 for (var /** @type {?} */ i = 0; i < 5; i++) {
465 text += possible.charAt(Math.floor(Math.random() * possible.length));
466 }
467 return text;
468 };
469 /**
470 * @param {?} params
471 * @return {?}
472 */
473 NacoService.prototype.buildQueryString = /**
474 * @param {?} params
475 * @return {?}
476 */
477 function (params) {
478 var /** @type {?} */ queryParams = Object.keys(params).map(function (key) {
479 return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
480 });
481 return queryParams.join('&');
482 };
483 /**
484 * @param {?} route
485 * @param {?=} responseType
486 * @return {?}
487 */
488 NacoService.prototype.goToAccountEndpoint = /**
489 * @param {?} route
490 * @param {?=} responseType
491 * @return {?}
492 */
493 function (route, responseType) {
494 var _this = this;
495 var /** @type {?} */ ltrim = function (text) { return text.replace(/^\/+/, ''); };
496 var /** @type {?} */ next = this.getCurrentOrigin('/' + ltrim(this.buildNestedUri(route.root)));
497 this.storage.set('naco_intended_url', next).then(function () {
498 _this.redirect(_this.login(_this.config.scopes, _this.getCurrentOrigin('/auth'), false, responseType || _this.config.responseType, true));
499 });
500 };
501 /**
502 * @return {?}
503 */
504 NacoService.prototype.goToIntendedUrl = /**
505 * @return {?}
506 */
507 function () {
508 var _this = this;
509 this.storage.get('naco_intended_url').then(function (url) {
510 _this.storage.remove('naco_intended_url');
511 _this.redirect(url || '/');
512 });
513 };
514 /**
515 * @param {?} url
516 * @return {?}
517 */
518 NacoService.prototype.redirect = /**
519 * @param {?} url
520 * @return {?}
521 */
522 function (url) {
523 window.location.href = url;
524 };
525 NacoService.decorators = [
526 { type: Injectable },
527 ];
528 /** @nocollapse */
529 NacoService.ctorParameters = function () { return [
530 { type: Config },
531 { type: Router },
532 { type: Storage },
533 { type: HttpClient },
534 { type: Location }
535 ]; };
536 return NacoService;
537}());
538export { NacoService };
539function NacoService_tsickle_Closure_declarations() {
540 /** @type {?} */
541 NacoService.prototype.VERSION;
542 /** @type {?} */
543 NacoService.prototype.signature;
544 /** @type {?} */
545 NacoService.prototype.user;
546 /** @type {?} */
547 NacoService.prototype.refreshToken;
548 /** @type {?} */
549 NacoService.prototype.clientSecret;
550 /** @type {?} */
551 NacoService.prototype.config;
552 /** @type {?} */
553 NacoService.prototype.router;
554 /** @type {?} */
555 NacoService.prototype.storage;
556 /** @type {?} */
557 NacoService.prototype.http;
558 /** @type {?} */
559 NacoService.prototype.location;
560}
561
562//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFjby5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5ha2VyL25hY28vIiwic291cmNlcyI6WyJkb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFrQyxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFZLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVoRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxVQUFVLEVBQXFCLE1BQU0sc0JBQXNCLENBQUM7QUFDckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQzs7eUJBWS9DLE1BQWMsRUFDZCxNQUFjLEVBQ2QsT0FBZ0IsRUFDaEIsSUFBZ0IsRUFDaEIsUUFBa0I7UUFKbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLFdBQU0sR0FBTixNQUFNLENBQVE7UUFDZCxZQUFPLEdBQVAsT0FBTyxDQUFTO1FBQ2hCLFNBQUksR0FBSixJQUFJLENBQVk7UUFDaEIsYUFBUSxHQUFSLFFBQVEsQ0FBVTt1QkFaTixJQUFJO3lCQUVRLElBQUk7b0JBQ2QsSUFBSTs0QkFDUyxJQUFJOzRCQUNQLElBQUk7UUFTdEMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRTtZQUMxQixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDbEQ7Ozs7OztJQUdFLDZCQUFPOzs7O2NBQUMsSUFBaUI7UUFDNUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7Ozs7O0lBR2QsNkJBQU87Ozs7O1FBQ1YsSUFBSSxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksRUFBRTtZQUNwQixPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDeEI7UUFFRCxxQkFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUVyQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQ2pDLFNBQVMsQ0FBQyxVQUFDLFNBQTJCO1lBQ2xDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ1osT0FBTyxLQUFJLENBQUMsV0FBVyxDQUFDLEtBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7YUFDL0M7WUFFRCxxQkFBTSxPQUFPLEdBQUc7Z0JBQ1osT0FBTyxFQUFFO29CQUNMLGFBQWEsRUFBSyxTQUFTLENBQUMsSUFBSSxTQUFJLFNBQVMsQ0FBQyxLQUFPO2lCQUN4RDthQUNKLENBQUM7WUFFRixPQUFPLEtBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFNLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQ3hDLEdBQUcsQ0FBQyxVQUFDLEdBQVE7Z0JBQ1QsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFO29CQUNWLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQztpQkFDbkI7Z0JBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO2FBQzFELENBQUMsRUFDRixHQUFHLENBQUMsVUFBQyxJQUFTO2dCQUNWLHFCQUFNLFFBQVEsR0FBUSxZQUFZLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO2dCQUUvQyxLQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUV2QixPQUFPLFFBQVEsQ0FBQzthQUNuQixDQUFDLEVBQ0YsVUFBVSxDQUFDLFVBQUMsQ0FBb0I7Z0JBQzVCLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUU7b0JBQ2xCLE9BQU8sS0FBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7aUJBQzdDO2dCQUVELE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO2FBQ25CLENBQUMsQ0FDTCxDQUFDO1NBQ0wsQ0FBQyxDQUNMLENBQUM7Ozs7OztJQUdDLHVDQUFpQjs7OztjQUFDLElBQVk7UUFDakMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxTQUFTLEdBQUcsSUFBSSxHQUFHLFVBQVUsQ0FBQzs7Ozs7SUFHekQsa0NBQVk7Ozs7UUFDZixJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDaEIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUMxQztRQUVELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7Ozs7OztJQUdsQyxrQ0FBWTs7OztjQUFDLFNBQTJCO1FBQzNDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBRTNCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQzs7Ozs7O0lBR3RDLHFDQUFlOzs7O2NBQUMsTUFBYztRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQzs7Ozs7O0lBR3hCLHFDQUFlOzs7O2NBQUMsWUFBdUI7UUFDMUMsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxFQUFFLFlBQVksQ0FBQyxDQUFDOzs7Ozs7SUFHN0MsaUNBQVc7Ozs7Y0FBQyxNQUFlOztRQUM5QixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFeEIsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FDaEUsU0FBUyxDQUFDLFVBQUMsT0FBWTtZQUNuQixxQkFBTSxZQUFZLEdBQWMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNDLHFCQUFNLFlBQVksR0FBVyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFFeEMsSUFBSSxZQUFZLElBQUksWUFBWSxFQUFFO2dCQUM5QixPQUFPLEtBQUksQ0FBQyx1QkFBdUIsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQzthQUNqRjtZQUVELE9BQU8sS0FBSSxDQUFDLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQzdDLENBQUMsQ0FDTCxDQUFDOzs7Ozs7OztJQUdDLDZDQUF1Qjs7Ozs7O2NBQUMsWUFBb0IsRUFBRSxZQUFvQixFQUFFLE1BQWU7O1FBQ3RGLHFCQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQ25ELFVBQVUsRUFBRSxlQUFlO1lBQzNCLE1BQU0sRUFBRSxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNO1lBQ3BDLFNBQVMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVE7WUFDL0IsYUFBYSxFQUFFLFlBQVk7WUFDM0IsYUFBYSxFQUFFLFlBQVk7U0FDOUIsQ0FBQyxDQUFDO1FBRUgsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUNmLEdBQUcsQ0FBQyxVQUFDLE1BQVc7WUFDWixJQUFJLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFO2dCQUN2QixLQUFJLENBQUMsWUFBWSxDQUFDO29CQUNkLFNBQVMsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVU7b0JBQ2pDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVU7b0JBQzVCLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVk7b0JBQy9CLE1BQU0sRUFBRSxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztpQkFDdkUsQ0FBQyxDQUFDO2dCQUVILEtBQUksQ0FBQyxlQUFlLENBQUM7b0JBQ2pCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVU7b0JBQzVCLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWE7aUJBQ25DLENBQUMsQ0FBQzthQUNOO1NBQ0osQ0FBQyxFQUNGLEdBQUcsQ0FBQyxVQUFDLE1BQVcsSUFBSyxPQUFBLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFyQixDQUFxQixDQUFDLEVBQzNDLFNBQVMsQ0FBQyxVQUFDLFFBQWlCO1lBQ3hCLElBQUksUUFBUSxFQUFFO2dCQUNWLE9BQU8sS0FBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO2FBQ3pCO1lBRUQsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDbkIsQ0FBQyxDQUNMLENBQUM7Ozs7OztJQUdDLDJDQUFxQjs7OztjQUFDLE1BQWU7O1FBQ3hDLE9BQU8sSUFBSSxVQUFVLENBQWMsVUFBQyxRQUErQjtZQUMvRCxxQkFBTSxXQUFXLEdBQUcsS0FBSSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3pELHFCQUFNLEdBQUcsR0FBRyxLQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUV4RixxQkFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUNoRCxNQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztZQUNoQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7WUFFOUIsTUFBTSxDQUFDLGdCQUFnQixDQUNuQixNQUFNLEVBQ047Ozs7Ozs0QkFFYyxXQUFXLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFFdEUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7aUNBRWxDLFdBQVcsRUFBWCx3QkFBVzs0QkFDTCxVQUFVLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQzs0QkFDcEMsTUFBTSxHQUFHLEVBQUUsQ0FBQzs7Z0NBRWxCLEtBQW1CLGVBQUEsaUJBQUEsVUFBVSxDQUFBLG9HQUFFO29DQUFwQixJQUFJO29DQUNMLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO29DQUVsQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lDQUN2Qzs7Ozs7Ozs7O2lDQUVHLE1BQU0sQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLEVBQXJDLHdCQUFxQzs0QkFDckMsSUFBSSxDQUFDLFlBQVksQ0FBQztnQ0FDZCxLQUFLLEVBQUUsTUFBTSxDQUFDLGNBQWMsQ0FBQztnQ0FDN0IsSUFBSSxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUM7Z0NBQzFCLFNBQVMsRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDO2dDQUMvQixNQUFNLEVBQUUsa0JBQWtCLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDOzZCQUNyRSxDQUFDLENBQUM7NEJBRVUscUJBQU0sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFBOzs0QkFBdkMsSUFBSSxHQUFHLFNBQWdDOzRCQUU3QyxJQUFJLElBQUksRUFBRTtnQ0FDTixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDOzZCQUN0Qjs0QkFFRCxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDOzs7NEJBRXBCLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7O2dDQUd4QixzQkFBTzs7NEJBR1gsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzs7Ozs0QkFFcEIsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQzs7Ozs7aUJBRTNCLEVBQ0QsS0FBSyxDQUNSLENBQUM7WUFFRixRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUNyQyxDQUFDLENBQUM7Ozs7Ozs7O0lBR0EsZ0RBQTBCOzs7Ozs7Y0FBQyxJQUFZLEVBQUUsV0FBbUIsRUFBRSxNQUFlOztRQUNoRixPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQ3BDLFNBQVMsQ0FBQyxVQUFDLEtBQWM7WUFDckIscUJBQU0sTUFBTSxHQUFXO2dCQUNuQixJQUFJLE1BQUE7Z0JBQ0osVUFBVSxFQUFFLG9CQUFvQjtnQkFDaEMsTUFBTSxFQUFFLE1BQU0sSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU07Z0JBQ3BDLFNBQVMsRUFBRSxLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVE7Z0JBQy9CLGFBQWEsRUFBRSxLQUFJLENBQUMsTUFBTSxDQUFDLFlBQVk7Z0JBQ3ZDLFlBQVksRUFBRSxXQUFXO2FBQzVCLENBQUM7WUFFRixJQUFJLEtBQUssRUFBRTtnQkFDUCxNQUFNLFlBQVMsS0FBSyxDQUFDO2FBQ3hCO1lBRUQsT0FBTyxLQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1NBQ3pELENBQUMsRUFDRixHQUFHLENBQUMsVUFBQyxHQUFRO1lBQ1QsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFO2dCQUNWLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQzthQUNuQjtZQUVELE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztTQUMxRCxDQUFDLENBQ0wsQ0FBQzs7Ozs7Ozs7OztJQUdDLDJCQUFLOzs7Ozs7OztjQUNSLE1BQWMsRUFDZCxXQUFvQixFQUNwQixNQUF1QixFQUN2QixZQUF3QyxFQUN4QyxTQUF5QjtRQUZ6Qix1QkFBQSxFQUFBLGNBQXVCO1FBQ3ZCLDZCQUFBLEVBQUEsc0JBQXdDO1FBQ3hDLDBCQUFBLEVBQUEsZ0JBQXlCO1FBRXpCLElBQUksQ0FBQyxXQUFXLEVBQUU7WUFDZCxXQUFXLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7U0FDakM7UUFFRCxxQkFBTSxNQUFNLEdBQVE7WUFDaEIsYUFBYSxFQUFFLFlBQVk7WUFDM0IsTUFBTSxFQUFFLE1BQU07WUFDZCxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRO1lBQzVCLE1BQU0sRUFBRSxNQUFNO1lBQ2QsUUFBUSxFQUFFLGtCQUFrQixDQUFDLFdBQVcsQ0FBQztTQUM1QyxDQUFDO1FBRUYsSUFBSSxTQUFTLEVBQUU7WUFDWCxxQkFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBRW5DLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNqQyxNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztTQUN4QjtRQUVELHFCQUFNLEtBQUssR0FBVyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEQsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxRQUFRLEdBQUcsS0FBSyxDQUFDOzs7Ozs7SUFHNUMsNEJBQU07Ozs7Y0FBQyxXQUFvQjs7UUFDOUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUM7UUFDdEIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFFekIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFBLE9BQU87WUFDdEIscUJBQU0sS0FBSyxHQUFHLENBQUMsS0FBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsS0FBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsS0FBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQztZQUVwSCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQztnQkFDcEIscUJBQUksUUFBUSxHQUFHLEtBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxHQUFHLGNBQWMsQ0FBQztnQkFFckQsSUFBSSxXQUFXLEVBQUU7b0JBQ2IsUUFBUSxJQUFJLFlBQVksR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztpQkFDOUQ7Z0JBRUQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO2FBQ3JCLENBQUMsQ0FBQztTQUNOLENBQUMsQ0FBQzs7Ozs7SUFHQSw4QkFBUTs7OztRQUNYLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7Ozs7OztJQUc5QixvQ0FBYzs7OztjQUFDLEtBQTZCOztRQUMvQyxxQkFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBRWIsSUFBSSxLQUFLLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFO1lBQzdDLHFCQUFJLFNBQVMsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQztZQUV2QyxLQUFLLHFCQUFNLEdBQUcsSUFBSSxLQUFLLENBQUMsTUFBTSxFQUFFO2dCQUM1QixJQUFJLEdBQUcsRUFBRTtvQkFDTCxxQkFBTSxFQUFFLEdBQUcsSUFBSSxNQUFNLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDO29CQUVqQyxTQUFTLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2lCQUN4RDthQUNKO1lBRUQsR0FBRyxJQUFJLEdBQUcsR0FBRyxTQUFTLENBQUM7U0FDMUI7UUFFRCxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUU7WUFDaEIsS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBQyxJQUE0QjtnQkFDaEQsR0FBRyxJQUFJLEtBQUksQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDcEMsQ0FBQyxDQUFDO1NBQ047UUFFRCxPQUFPLEdBQUcsQ0FBQzs7Ozs7SUFHUCxxQ0FBZTs7OztRQUNuQixJQUFJLElBQUksS0FBSyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQzVCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDN0M7UUFFRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDOzs7OztJQUdyQyxxQ0FBZTs7OztRQUNuQixJQUFJLElBQUksS0FBSyxJQUFJLENBQUMsWUFBWSxFQUFFO1lBQzVCLE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7U0FDN0M7UUFFRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDOzs7Ozs7SUFHckMsNEJBQU07Ozs7Y0FBQyxJQUFZO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDOzs7Ozs7SUFHekQsc0NBQWdCOzs7O2NBQUMsSUFBYTtRQUNqQyxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsa0JBQWtCLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDOzs7OztJQUd6RSxtQ0FBYTs7OztRQUNqQixxQkFBTSxRQUFRLEdBQUcsZ0VBQWdFLENBQUM7UUFDbEYscUJBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVkLEtBQUsscUJBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3hCLElBQUksSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1NBQ3hFO1FBRUQsT0FBTyxJQUFJLENBQUM7Ozs7OztJQUdSLHNDQUFnQjs7OztjQUFDLE1BQWM7UUFDbkMscUJBQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQUMsR0FBVztZQUNwRCxPQUFPLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztTQUMxRSxDQUFDLENBQUM7UUFFSCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7Ozs7Ozs7SUFHMUIseUNBQW1COzs7OztjQUFDLEtBQTZCLEVBQUUsWUFBK0I7O1FBQ3JGLHFCQUFNLEtBQUssR0FBRyxVQUFBLElBQUksSUFBSSxPQUFBLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxFQUF4QixDQUF3QixDQUFDO1FBRS9DLHFCQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFakYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzdDLEtBQUksQ0FBQyxRQUFRLENBQ1QsS0FBSSxDQUFDLEtBQUssQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxLQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLFlBQVksSUFBSSxLQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FDeEgsQ0FBQztTQUNMLENBQUMsQ0FBQzs7Ozs7SUFHQSxxQ0FBZTs7Ozs7UUFDbEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQVMsbUJBQW1CLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBQSxHQUFHO1lBQ2xELEtBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDekMsS0FBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUM7U0FDN0IsQ0FBQyxDQUFDOzs7Ozs7SUFHQSw4QkFBUTs7OztjQUFDLEdBQVc7UUFDdkIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDOzs7Z0JBallsQyxVQUFVOzs7O2dCQVZGLE1BQU07Z0JBRjBCLE1BQU07Z0JBQ3RDLE9BQU87Z0JBT1AsVUFBVTtnQkFDVixRQUFROztzQkFWakI7O1NBY2EsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIFBhcmFtcywgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL21vZGVscy91c2VyJztcbmltcG9ydCB7IGZvcmtKb2luLCBmcm9tLCBPYnNlcnZhYmxlLCBPYnNlcnZlciwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFNpZ25hdHVyZSB9IGZyb20gJy4uL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgbWFwLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IHBsYWluVG9DbGFzcyB9IGZyb20gJ2NsYXNzLXRyYW5zZm9ybWVyJztcbmltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgZnJvbVByb21pc2UgfSBmcm9tICdyeGpzLWNvbXBhdC9vYnNlcnZhYmxlL2Zyb21Qcm9taXNlJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5hY29TZXJ2aWNlIHtcbiAgICBwdWJsaWMgcmVhZG9ubHkgVkVSU0lPTiA9ICd2MSc7XG5cbiAgICBwcml2YXRlIHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSB1c2VyOiBVc2VyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgY2xpZW50U2VjcmV0OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJvdGVjdGVkIGNvbmZpZzogQ29uZmlnLFxuICAgICAgICBwcm90ZWN0ZWQgcm91dGVyOiBSb3V0ZXIsXG4gICAgICAgIHByb3RlY3RlZCBzdG9yYWdlOiBTdG9yYWdlLFxuICAgICAgICBwcm90ZWN0ZWQgaHR0cDogSHR0cENsaWVudCxcbiAgICAgICAgcHJvdGVjdGVkIGxvY2F0aW9uOiBMb2NhdGlvbixcbiAgICApIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmNsaWVudFNlY3JldCkge1xuICAgICAgICAgICAgdGhpcy5zZXRDbGllbnRTZWNyZXQodGhpcy5jb25maWcuY2xpZW50U2VjcmV0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzZXRVc2VyKHVzZXI6IFVzZXIgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFVzZXIoKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy51c2VyKSB7XG4gICAgICAgICAgICByZXR1cm4gb2YodGhpcy51c2VyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHVyaSA9IHRoaXMuZ2V0VXJpKCcvdXNlcnMvbWUnKTtcblxuICAgICAgICByZXR1cm4gZnJvbSh0aGlzLmdldFNpZ25hdHVyZSgpKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChzaWduYXR1cmU6IFNpZ25hdHVyZSB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoVXNlcih0aGlzLmNvbmZpZy5zY29wZXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGAke3NpZ25hdHVyZS50eXBlfSAke3NpZ25hdHVyZS50b2tlbn1gLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5odHRwLmdldDxhbnk+KHVyaSwgb3B0aW9ucykucGlwZShcbiAgICAgICAgICAgICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcy5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGFyZSBubyBib2R5IHRvIGJlIHRyYW5zZm9ybWVkJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBtYXAoKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV0aFVzZXI6IGFueSA9IHBsYWluVG9DbGFzcyhVc2VyLCBkYXRhKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRVc2VyKGF1dGhVc2VyKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF1dGhVc2VyO1xuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoZTogSHR0cEVycm9yUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICg0MDEgPT09IGUuc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFVzZXIoc2lnbmF0dXJlLnNjb3Blcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRQcm9maWxlUGljdHVyZSh1c2VyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL3VzZXJzLycgKyB1c2VyICsgJy9waWN0dXJlJztcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0U2lnbmF0dXJlKCk6IFByb21pc2U8U2lnbmF0dXJlIHwgbnVsbD4ge1xuICAgICAgICBpZiAodGhpcy5zaWduYXR1cmUpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5zaWduYXR1cmUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ3NpZ25hdHVyZScpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRTaWduYXR1cmUoc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuXG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3NpZ25hdHVyZScsIHNpZ25hdHVyZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldENsaWVudFNlY3JldChzZWNyZXQ6IHN0cmluZyk6IHZvaWQge1xuICAgICAgICB0aGlzLmNsaWVudFNlY3JldCA9IHNlY3JldDtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0UmVmcmVzaFRva2VuKHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVmcmVzaFRva2VuID0gcmVmcmVzaFRva2VuO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdyZWZyZXNoX3Rva2VuJywgcmVmcmVzaFRva2VuKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFVzZXIoc2NvcGVzPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICB0aGlzLnNldFVzZXIobnVsbCk7XG4gICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKG51bGwpO1xuXG4gICAgICAgIHJldHVybiBmb3JrSm9pbih0aGlzLmdldFJlZnJlc2hUb2tlbigpLCB0aGlzLmdldENsaWVudFNlY3JldCgpKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChyZXN1bHRzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSA9IHJlc3VsdHNbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgY2xpZW50U2VjcmV0OiBzdHJpbmcgPSByZXN1bHRzWzFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hUb2tlbiAmJiBjbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFdpdGhSZWZyZXNoVG9rZW4oY2xpZW50U2VjcmV0LCByZWZyZXNoVG9rZW4udG9rZW4sIHNjb3Blcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFdpdGhTaWxlbnRBdXRoKHNjb3Blcyk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFdpdGhSZWZyZXNoVG9rZW4oY2xpZW50U2VjcmV0OiBzdHJpbmcsIHJlZnJlc2hUb2tlbjogc3RyaW5nLCBzY29wZXM/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLmh0dHAucG9zdCh0aGlzLmdldFVyaSgnL3Rva2VucycpLCB7XG4gICAgICAgICAgICBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgICAgICBzY29wZXM6IHNjb3BlcyB8fCB0aGlzLmNvbmZpZy5zY29wZXMsXG4gICAgICAgICAgICBjbGllbnRfaWQ6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgY2xpZW50X3NlY3JldDogY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVxdWVzdC5waXBlKFxuICAgICAgICAgICAgdGFwKCh0b2tlbnM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0b2tlbnMgJiYgdG9rZW5zLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTaWduYXR1cmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0luOiB0b2tlbnMuZGF0YS5leHBpcmVzX2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogdG9rZW5zLmRhdGEudG9rZW5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbnMuZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZXM6IGRlY29kZVVSSUNvbXBvbmVudCh0b2tlbnMuZGF0YS5zY29wZXMgfHwgdGhpcy5jb25maWcuc2NvcGVzKSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRSZWZyZXNoVG9rZW4oe1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogdG9rZW5zLmRhdGEudG9rZW5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbnMuZGF0YS5yZWZyZXNoX3Rva2VuLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIG1hcCgodG9rZW5zOiBhbnkpID0+IHRva2VucyAmJiB0b2tlbnMuZGF0YSksXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKGhhc1Rva2VuOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1Rva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmdldFVzZXIoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFdpdGhTaWxlbnRBdXRoKHNjb3Blcz86IHN0cmluZyk6IE9ic2VydmFibGU8VXNlciB8IG51bGw+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPigob2JzZXJ2ZXI6IE9ic2VydmVyPFVzZXIgfCBudWxsPikgPT4ge1xuICAgICAgICAgICAgY29uc3QgcmVkaXJlY3RVcmkgPSB0aGlzLmdldEN1cnJlbnRPcmlnaW4oJ2F1dGgvc2lsZW50Jyk7XG4gICAgICAgICAgICBjb25zdCB1cmkgPSB0aGlzLmxvZ2luKHNjb3BlcyB8fCB0aGlzLmNvbmZpZy5zY29wZXMsIHJlZGlyZWN0VXJpLCB0cnVlLCAndG9rZW4nLCBmYWxzZSk7XG5cbiAgICAgICAgICAgIGNvbnN0IGlmcmFtZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpO1xuICAgICAgICAgICAgaWZyYW1lLnNldEF0dHJpYnV0ZSgnc3JjJywgdXJpKTtcbiAgICAgICAgICAgIGlmcmFtZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuXG4gICAgICAgICAgICBpZnJhbWUuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAnbG9hZCcsXG4gICAgICAgICAgICAgICAgYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcXVlcnlTdHJpbmcgPSBpZnJhbWUuY29udGVudFdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc3Vic3RyaW5nKDEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZnJhbWUucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChpZnJhbWUpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWVyeVBhcnRzID0gcXVlcnlTdHJpbmcuc3BsaXQoJyYnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXMgPSB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBxdWVyeVBhcnRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1QYXJ0cyA9IGl0ZW0uc3BsaXQoJz0nKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXNbaXRlbVBhcnRzWzBdXSA9IGl0ZW1QYXJ0c1sxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW1zLmhhc093blByb3BlcnR5KCdhY2Nlc3NfdG9rZW4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFNpZ25hdHVyZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogcGFyYW1zWydhY2Nlc3NfdG9rZW4nXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHBhcmFtc1sndG9rZW5fdHlwZSddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0luOiBwYXJhbXNbJ2V4cGlyZXNfaW4nXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlczogZGVjb2RlVVJJQ29tcG9uZW50KHBhcmFtc1snc2NvcGVzJ10gfHwgdGhpcy5jb25maWcuc2NvcGVzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuZ2V0VXNlcigpLnRvUHJvbWlzZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIodXNlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KHVzZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoaWZyYW1lKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEFjY2Vzc1Rva2VuRnJvbUF1dGhDb2RlKGNvZGU6IHN0cmluZywgcmVkaXJlY3RVcmk6IHN0cmluZywgc2NvcGVzPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuZ2V0U3RhdGUoKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoc3RhdGU/OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJhbXM6IFBhcmFtcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgY29kZSxcbiAgICAgICAgICAgICAgICAgICAgZ3JhbnRfdHlwZTogJ2F1dGhvcml6YXRpb25fY29kZScsXG4gICAgICAgICAgICAgICAgICAgIHNjb3Blczogc2NvcGVzIHx8IHRoaXMuY29uZmlnLnNjb3BlcyxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50X2lkOiB0aGlzLmNvbmZpZy5jbGllbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgY2xpZW50X3NlY3JldDogdGhpcy5jb25maWcuY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgICAgICAgICByZWRpcmVjdF91cmk6IHJlZGlyZWN0VXJpLFxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBpZiAoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyYW1zLnN0YXRlID0gc3RhdGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0KHRoaXMuZ2V0VXJpKCcvdG9rZW5zJyksIHBhcmFtcyk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIG1hcCgocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocmVzLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgYXJlIG5vIGJvZHkgdG8gYmUgdHJhbnNmb3JtZWQnKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dpbihcbiAgICAgICAgc2NvcGVzOiBzdHJpbmcsXG4gICAgICAgIHJlZGlyZWN0VXJpPzogc3RyaW5nLFxuICAgICAgICBzaWxlbnQ6IGJvb2xlYW4gPSBmYWxzZSxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAndG9rZW4nIHwgJ2NvZGUnID0gJ3Rva2VuJyxcbiAgICAgICAgbmVlZFN0YXRlOiBib29sZWFuID0gdHJ1ZSxcbiAgICApOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICByZWRpcmVjdFVyaSA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhcmFtczogYW55ID0ge1xuICAgICAgICAgICAgcmVzcG9uc2VfdHlwZTogcmVzcG9uc2VUeXBlLFxuICAgICAgICAgICAgc2NvcGVzOiBzY29wZXMsXG4gICAgICAgICAgICBjbGllbnQ6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgc2lsZW50OiBzaWxlbnQsXG4gICAgICAgICAgICBjb250aW51ZTogZW5jb2RlVVJJQ29tcG9uZW50KHJlZGlyZWN0VXJpKSxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobmVlZFN0YXRlKSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2VuZXJhdGVTdGF0ZSgpO1xuXG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdzdGF0ZScsIHN0YXRlKTtcbiAgICAgICAgICAgIHBhcmFtcy5zdGF0ZSA9IHN0YXRlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcXVlcnk6IHN0cmluZyA9IHRoaXMuYnVpbGRRdWVyeVN0cmluZyhwYXJhbXMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aD8nICsgcXVlcnk7XG4gICAgfVxuXG4gICAgcHVibGljIGxvZ291dChyZWRpcmVjdFVyaT86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gbnVsbDtcbiAgICAgICAgdGhpcy51c2VyID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZWZyZXNoVG9rZW4gPSBudWxsO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNsZWFyID0gW3RoaXMuc3RvcmFnZS5yZW1vdmUoJ3NpZ25hdHVyZScpLCB0aGlzLnN0b3JhZ2UucmVtb3ZlKCd1c2VyJyksIHRoaXMuc3RvcmFnZS5yZW1vdmUoJ3JlZnJlc2hfdG9rZW4nKV07XG5cbiAgICAgICAgICAgIFByb21pc2UuYWxsKGNsZWFyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgZW5kcG9pbnQgPSB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aC9sb2dvdXQnO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVuZHBvaW50ICs9ICc/Y29udGludWU9JyArIGVuY29kZVVSSUNvbXBvbmVudChyZWRpcmVjdFVyaSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbmRwb2ludCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFN0YXRlKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgnc3RhdGUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYnVpbGROZXN0ZWRVcmkocm91dGU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QpOiBzdHJpbmcge1xuICAgICAgICBsZXQgdXJpID0gJyc7XG5cbiAgICAgICAgaWYgKHJvdXRlLnJvdXRlQ29uZmlnICYmIHJvdXRlLnJvdXRlQ29uZmlnLnBhdGgpIHtcbiAgICAgICAgICAgIGxldCByb3V0ZVBhdGggPSByb3V0ZS5yb3V0ZUNvbmZpZy5wYXRoO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiByb3V0ZS5wYXJhbXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cCgnOicgKyBrZXkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJvdXRlUGF0aCA9IHJvdXRlUGF0aC5yZXBsYWNlKHJlLCByb3V0ZS5wYXJhbXNba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cmkgKz0gJy8nICsgcm91dGVQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJvdXRlLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICByb3V0ZS5jaGlsZHJlbi5mb3JFYWNoKChpdGVtOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gICAgICAgICAgICAgICAgdXJpICs9IHRoaXMuYnVpbGROZXN0ZWRVcmkoaXRlbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1cmk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWZyZXNoVG9rZW4oKTogUHJvbWlzZTxTaWduYXR1cmUgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLnJlZnJlc2hUb2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgncmVmcmVzaF90b2tlbicpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q2xpZW50U2VjcmV0KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy5jbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5jbGllbnRTZWNyZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ2NsaWVudF9zZWNyZXQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFVyaShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2FwaS8nICsgdGhpcy5WRVJTSU9OICsgcGF0aDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Q3VycmVudE9yaWdpbihwYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB0aGlzLmxvY2F0aW9uLnByZXBhcmVFeHRlcm5hbFVybChwYXRoIHx8ICcnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU3RhdGUoKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcG9zc2libGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICAgICAgICBsZXQgdGV4dCA9ICcnO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICB0ZXh0ICs9IHBvc3NpYmxlLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBwb3NzaWJsZS5sZW5ndGgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRRdWVyeVN0cmluZyhwYXJhbXM6IG9iamVjdCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocGFyYW1zKS5tYXAoKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXMuam9pbignJicpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnb1RvQWNjb3VudEVuZHBvaW50KHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90LCByZXNwb25zZVR5cGU/OiAndG9rZW4nIHwgJ2NvZGUnKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGx0cmltID0gdGV4dCA9PiB0ZXh0LnJlcGxhY2UoL15cXC8rLywgJycpO1xuXG4gICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLmdldEN1cnJlbnRPcmlnaW4oJy8nICsgbHRyaW0odGhpcy5idWlsZE5lc3RlZFVyaShyb3V0ZS5yb290KSkpO1xuXG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ25hY29faW50ZW5kZWRfdXJsJywgbmV4dCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnJlZGlyZWN0KFxuICAgICAgICAgICAgICAgIHRoaXMubG9naW4odGhpcy5jb25maWcuc2NvcGVzLCB0aGlzLmdldEN1cnJlbnRPcmlnaW4oJy9hdXRoJyksIGZhbHNlLCByZXNwb25zZVR5cGUgfHwgdGhpcy5jb25maWcucmVzcG9uc2VUeXBlLCB0cnVlKSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnb1RvSW50ZW5kZWRVcmwoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5nZXQ8c3RyaW5nPignbmFjb19pbnRlbmRlZF91cmwnKS50aGVuKHVybCA9PiB7XG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCduYWNvX2ludGVuZGVkX3VybCcpO1xuICAgICAgICAgICAgdGhpcy5yZWRpcmVjdCh1cmwgfHwgJy8nKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZGlyZWN0KHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsO1xuICAgIH1cbn1cbiJdfQ==
\No newline at end of file