system-calls.js
125 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "DEFAULT_ADB_EXEC_TIMEOUT", {
enumerable: true,
get: function () {
return _helpers.DEFAULT_ADB_EXEC_TIMEOUT;
}
});
exports.default = void 0;
require("source-map-support/register");
var _path = _interopRequireDefault(require("path"));
var _logger = _interopRequireDefault(require("../logger.js"));
var _bluebird = _interopRequireDefault(require("bluebird"));
var _appiumSupport = require("appium-support");
var _helpers = require("../helpers");
var _teen_process = require("teen_process");
var _asyncbox = require("asyncbox");
var _lodash = _interopRequireDefault(require("lodash"));
let systemCallMethods = {};
const DEFAULT_ADB_REBOOT_RETRIES = 90;
const LINKER_WARNING_REGEXP = /^WARNING: linker.+$/m;
const PROTOCOL_FAULT_ERROR_REGEXP = new RegExp('protocol fault \\(no status\\)', 'i');
const DEVICE_NOT_FOUND_ERROR_REGEXP = new RegExp(`error: device ('.+' )?not found`, 'i');
const DEVICE_CONNECTING_ERROR_REGEXP = new RegExp('error: device still connecting', 'i');
const CERTS_ROOT = '/system/etc/security/cacerts';
systemCallMethods.getSdkBinaryPath = async function getSdkBinaryPath(binaryName) {
if (this.sdkRoot) {
return await this.getBinaryFromSdkRoot(binaryName);
}
_logger.default.warn(`The ANDROID_HOME environment variable is not set to the Android SDK ` + `root directory path. ANDROID_HOME is required for compatibility ` + `with SDK 23+. Checking along PATH for ${binaryName}.`);
return await this.getBinaryFromPath(binaryName);
};
systemCallMethods.getBinaryNameForOS = _lodash.default.memoize(function getBinaryNameForOS(binaryName) {
if (!_appiumSupport.system.isWindows()) {
return binaryName;
}
if (['android', 'apksigner', 'apkanalyzer'].includes(binaryName)) {
return `${binaryName}.bat`;
}
if (!_path.default.extname(binaryName)) {
return `${binaryName}.exe`;
}
return binaryName;
});
systemCallMethods.getBinaryFromSdkRoot = async function getBinaryFromSdkRoot(binaryName) {
if (this.binaries[binaryName]) {
return this.binaries[binaryName];
}
const fullBinaryName = this.getBinaryNameForOS(binaryName);
const binaryLocs = ['platform-tools', 'emulator', 'tools', `tools${_path.default.sep}bin`].map(x => _path.default.resolve(this.sdkRoot, x, fullBinaryName));
let buildToolsDirs = await (0, _helpers.getBuildToolsDirs)(this.sdkRoot);
if (this.buildToolsVersion) {
buildToolsDirs = buildToolsDirs.filter(x => _path.default.basename(x) === this.buildToolsVersion);
if (_lodash.default.isEmpty(buildToolsDirs)) {
_logger.default.info(`Found no build tools whose version matches to '${this.buildToolsVersion}'`);
} else {
_logger.default.info(`Using build tools at '${buildToolsDirs}'`);
}
}
binaryLocs.push(..._lodash.default.flatten(buildToolsDirs.map(dir => [_path.default.resolve(dir, fullBinaryName), _path.default.resolve(dir, 'lib', fullBinaryName)])));
let binaryLoc = null;
for (const loc of binaryLocs) {
if (await _appiumSupport.fs.exists(loc)) {
binaryLoc = loc;
break;
}
}
if (_lodash.default.isNull(binaryLoc)) {
throw new Error(`Could not find '${fullBinaryName}' in ${JSON.stringify(binaryLocs)}. ` + `Do you have Android Build Tools ${this.buildToolsVersion ? `v ${this.buildToolsVersion} ` : ''}` + `installed at '${this.sdkRoot}'?`);
}
_logger.default.info(`Using '${fullBinaryName}' from '${binaryLoc}'`);
this.binaries[binaryName] = binaryLoc;
return binaryLoc;
};
systemCallMethods.getBinaryFromPath = async function getBinaryFromPath(binaryName) {
if (this.binaries[binaryName]) {
return this.binaries[binaryName];
}
const fullBinaryName = this.getBinaryNameForOS(binaryName);
try {
const binaryLoc = await _appiumSupport.fs.which(fullBinaryName);
_logger.default.info(`Using '${fullBinaryName}' from '${binaryLoc}'`);
this.binaries[binaryName] = binaryLoc;
return binaryLoc;
} catch (e) {
throw new Error(`Could not find '${fullBinaryName}' in PATH. Please set the ANDROID_HOME ` + `or ANDROID_SDK_ROOT environment variables to the correct Android SDK root directory path.`);
}
};
systemCallMethods.getConnectedDevices = async function getConnectedDevices() {
_logger.default.debug('Getting connected devices...');
let stdout;
try {
({
stdout
} = await (0, _teen_process.exec)(this.executable.path, [...this.executable.defaultArgs, 'devices']));
} catch (e) {
throw new Error(`Error while getting connected devices. Original error: ${e.message}`);
}
const listHeader = 'List of devices';
const startingIndex = stdout.indexOf(listHeader);
if (startingIndex < 0) {
throw new Error(`Unexpected output while trying to get devices: ${stdout}`);
}
stdout = stdout.slice(startingIndex);
let excludedLines = [listHeader, 'adb server', '* daemon'];
if (!this.allowOfflineDevices) {
excludedLines.push('offline');
}
const devices = stdout.split('\n').map(_lodash.default.trim).filter(line => line && !excludedLines.some(x => line.includes(x))).reduce((acc, line) => {
const [udid, state] = line.split(/\s+/);
acc.push({
udid,
state
});
return acc;
}, []);
if (_lodash.default.isEmpty(devices)) {
_logger.default.debug('No connected devices have been detected');
} else {
_logger.default.debug(`Connected devices: ${JSON.stringify(devices)}`);
}
return devices;
};
systemCallMethods.getDevicesWithRetry = async function getDevicesWithRetry(timeoutMs = 20000) {
const timer = new _appiumSupport.timing.Timer().start();
_logger.default.debug('Trying to find a connected android device');
const getDevices = async () => {
if (timer.getDuration().asMilliSeconds > timeoutMs) {
throw new Error(`Could not find a connected Android device in ${timer.getDuration().asMilliSeconds.toFixed(0)}ms.`);
}
try {
const devices = await this.getConnectedDevices();
if (devices.length > 0) {
return devices;
}
} catch (ign) {}
_logger.default.debug('Could not find devices, restarting adb server...');
await this.restartAdb();
await (0, _asyncbox.sleep)(200);
return await getDevices();
};
return await getDevices();
};
systemCallMethods.restartAdb = async function restartAdb() {
if (this.suppressKillServer) {
_logger.default.debug(`Not restarting abd since 'suppressKillServer' is on`);
return;
}
_logger.default.debug('Restarting adb');
try {
await this.killServer();
} catch (e) {
_logger.default.error(`Error killing ADB server, going to see if it's online anyway`);
}
};
systemCallMethods.killServer = async function killServer() {
_logger.default.debug(`Killing adb server on port '${this.adbPort}'`);
await this.adbExec(['kill-server'], {
exclusive: true
});
};
systemCallMethods.resetTelnetAuthToken = _lodash.default.memoize(async function resetTelnetAuthToken() {
const homeFolderPath = process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'];
if (!homeFolderPath) {
_logger.default.warn(`Cannot find the path to user home folder. Ignoring resetting of emulator's telnet authentication token`);
return false;
}
const dstPath = _path.default.resolve(homeFolderPath, '.emulator_console_auth_token');
_logger.default.debug(`Overriding ${dstPath} with an empty string to avoid telnet authentication for emulator commands`);
try {
await _appiumSupport.fs.writeFile(dstPath, '');
} catch (e) {
_logger.default.warn(`Error ${e.message} while resetting the content of ${dstPath}. Ignoring resetting of emulator's telnet authentication token`);
return false;
}
return true;
});
systemCallMethods.adbExecEmu = async function adbExecEmu(cmd) {
await this.verifyEmulatorConnected();
await this.resetTelnetAuthToken();
await this.adbExec(['emu', ...cmd]);
};
let isExecLocked = false;
systemCallMethods.adbExec = async function adbExec(cmd, opts = {}) {
if (!cmd) {
throw new Error('You need to pass in a command to adbExec()');
}
opts = _lodash.default.cloneDeep(opts);
opts.timeout = opts.timeout || this.adbExecTimeout || _helpers.DEFAULT_ADB_EXEC_TIMEOUT;
opts.timeoutCapName = opts.timeoutCapName || 'adbExecTimeout';
cmd = _lodash.default.isArray(cmd) ? cmd : [cmd];
let adbRetried = false;
const execFunc = async () => {
try {
const args = [...this.executable.defaultArgs, ...cmd];
_logger.default.debug(`Running '${this.executable.path} ${_appiumSupport.util.quote(args)}'`);
let {
stdout
} = await (0, _teen_process.exec)(this.executable.path, args, opts);
stdout = stdout.replace(LINKER_WARNING_REGEXP, '').trim();
return stdout;
} catch (e) {
const errText = `${e.message}, ${e.stdout}, ${e.stderr}`;
const protocolFaultError = PROTOCOL_FAULT_ERROR_REGEXP.test(errText);
const deviceNotFoundError = DEVICE_NOT_FOUND_ERROR_REGEXP.test(errText);
const deviceConnectingError = DEVICE_CONNECTING_ERROR_REGEXP.test(errText);
if (protocolFaultError || deviceNotFoundError || deviceConnectingError) {
_logger.default.info(`Error sending command, reconnecting device and retrying: ${cmd}`);
await (0, _asyncbox.sleep)(1000);
await this.getDevicesWithRetry();
if (adbRetried) {
adbRetried = true;
return await execFunc();
}
}
if (e.code === 0 && e.stdout) {
return e.stdout.replace(LINKER_WARNING_REGEXP, '').trim();
}
if (_lodash.default.isNull(e.code)) {
e.message = `Error executing adbExec. Original error: '${e.message}'. ` + `Try to increase the ${opts.timeout}ms adb execution timeout represented by '${opts.timeoutCapName}' capability`;
} else {
e.message = `Error executing adbExec. Original error: '${e.message}'; ` + `Stderr: '${(e.stderr || '').trim()}'; Code: '${e.code}'`;
}
throw e;
}
};
if (isExecLocked) {
_logger.default.debug('Waiting until the other exclusive ADB command is completed');
await (0, _asyncbox.waitForCondition)(() => !isExecLocked, {
waitMs: Number.MAX_SAFE_INTEGER,
intervalMs: 10
});
_logger.default.debug('Continuing with the current ADB command');
}
if (opts.exclusive) {
isExecLocked = true;
}
try {
return await execFunc();
} finally {
if (opts.exclusive) {
isExecLocked = false;
}
}
};
systemCallMethods.shell = async function shell(cmd, opts = {}) {
const {
privileged,
keepPrivileged
} = opts;
let shouldRestoreUser = false;
if (privileged) {
_logger.default.info(`'adb shell ${cmd}' requires root access. Attempting to gain root access now.`);
const {
wasAlreadyRooted,
isSuccessful
} = await this.root();
shouldRestoreUser = !wasAlreadyRooted;
if (wasAlreadyRooted) {
_logger.default.info('Device already had root access');
} else {
_logger.default.info(isSuccessful ? 'Root access successfully gained' : 'Could not gain root access');
}
}
let didCommandFail = false;
try {
try {
return await this.adbExec(_lodash.default.isArray(cmd) ? ['shell', ...cmd] : ['shell', cmd], opts);
} catch (err) {
didCommandFail = true;
throw err;
}
} finally {
if (privileged && shouldRestoreUser && (!keepPrivileged || didCommandFail)) {
const {
isSuccessful
} = await this.unroot();
_logger.default.debug(isSuccessful ? 'Returned device to unrooted state' : 'Could not return device to unrooted state');
}
}
};
systemCallMethods.createSubProcess = function createSubProcess(args = []) {
args = this.executable.defaultArgs.concat(args);
_logger.default.debug(`Creating ADB subprocess with args: ${JSON.stringify(args)}`);
return new _teen_process.SubProcess(this.getAdbPath(), args);
};
systemCallMethods.getAdbServerPort = function getAdbServerPort() {
return this.adbPort;
};
systemCallMethods.getEmulatorPort = async function getEmulatorPort() {
_logger.default.debug('Getting running emulator port');
if (this.emulatorPort !== null) {
return this.emulatorPort;
}
try {
let devices = await this.getConnectedDevices();
let port = this.getPortFromEmulatorString(devices[0].udid);
if (port) {
return port;
} else {
throw new Error(`Emulator port not found`);
}
} catch (e) {
throw new Error(`No devices connected. Original error: ${e.message}`);
}
};
systemCallMethods.getPortFromEmulatorString = function getPortFromEmulatorString(emStr) {
let portPattern = /emulator-(\d+)/;
if (portPattern.test(emStr)) {
return parseInt(portPattern.exec(emStr)[1], 10);
}
return false;
};
systemCallMethods.getConnectedEmulators = async function getConnectedEmulators() {
_logger.default.debug('Getting connected emulators');
try {
let devices = await this.getConnectedDevices();
let emulators = [];
for (let device of devices) {
let port = this.getPortFromEmulatorString(device.udid);
if (port) {
device.port = port;
emulators.push(device);
}
}
_logger.default.debug(`${_appiumSupport.util.pluralize('emulator', emulators.length, true)} connected`);
return emulators;
} catch (e) {
throw new Error(`Error getting emulators. Original error: ${e.message}`);
}
};
systemCallMethods.setEmulatorPort = function setEmulatorPort(emPort) {
this.emulatorPort = emPort;
};
systemCallMethods.setDeviceId = function setDeviceId(deviceId) {
_logger.default.debug(`Setting device id to ${deviceId}`);
this.curDeviceId = deviceId;
let argsHasDevice = this.executable.defaultArgs.indexOf('-s');
if (argsHasDevice !== -1) {
this.executable.defaultArgs.splice(argsHasDevice, 2);
}
this.executable.defaultArgs.push('-s', deviceId);
};
systemCallMethods.setDevice = function setDevice(deviceObj) {
let deviceId = deviceObj.udid;
let emPort = this.getPortFromEmulatorString(deviceId);
this.setEmulatorPort(emPort);
this.setDeviceId(deviceId);
};
systemCallMethods.getRunningAVD = async function getRunningAVD(avdName) {
_logger.default.debug(`Trying to find '${avdName}' emulator`);
try {
const emulators = await this.getConnectedEmulators();
for (const emulator of emulators) {
this.setEmulatorPort(emulator.port);
const runningAVDName = await this.sendTelnetCommand('avd name');
if (_lodash.default.toLower(avdName) === _lodash.default.toLower(runningAVDName)) {
_logger.default.debug(`Found emulator '${avdName}' on port ${emulator.port}`);
this.setDeviceId(emulator.udid);
return emulator;
}
}
_logger.default.debug(`Emulator '${avdName}' not running`);
return null;
} catch (e) {
throw new Error(`Error getting AVD. Original error: ${e.message}`);
}
};
systemCallMethods.getRunningAVDWithRetry = async function getRunningAVDWithRetry(avdName, timeoutMs = 20000) {
let runningAvd;
try {
await (0, _asyncbox.waitForCondition)(async () => {
try {
runningAvd = await this.getRunningAVD(avdName.replace('@', ''));
return runningAvd;
} catch (e) {
_logger.default.debug(e.message);
return false;
}
}, {
waitMs: timeoutMs,
intervalMs: 1000
});
} catch (e) {
throw new Error(`Error getting AVD with retry. Original error: ${e.message}`);
}
return runningAvd;
};
systemCallMethods.killAllEmulators = async function killAllEmulators() {
let cmd, args;
if (_appiumSupport.system.isWindows()) {
cmd = 'TASKKILL';
args = ['TASKKILL', '/IM', 'emulator.exe'];
} else {
cmd = '/usr/bin/killall';
args = ['-m', 'emulator*'];
}
try {
await (0, _teen_process.exec)(cmd, args);
} catch (e) {
throw new Error(`Error killing emulators. Original error: ${e.message}`);
}
};
systemCallMethods.killEmulator = async function killEmulator(avdName = null, timeout = 60000) {
if (_appiumSupport.util.hasValue(avdName)) {
_logger.default.debug(`Killing avd '${avdName}'`);
const device = await this.getRunningAVD(avdName);
if (!device) {
_logger.default.info(`No avd with name '${avdName}' running. Skipping kill step.`);
return false;
}
} else {
_logger.default.debug(`Killing avd with id '${this.curDeviceId}'`);
if (!(await this.isEmulatorConnected())) {
_logger.default.debug(`Emulator with id '${this.curDeviceId}' not connected. Skipping kill step`);
return false;
}
}
await this.adbExec(['emu', 'kill']);
_logger.default.debug(`Waiting up to ${timeout}ms until the emulator '${avdName ? avdName : this.curDeviceId}' is killed`);
try {
await (0, _asyncbox.waitForCondition)(async () => {
try {
return _appiumSupport.util.hasValue(avdName) ? !(await this.getRunningAVD(avdName)) : !(await this.isEmulatorConnected());
} catch (ign) {}
return false;
}, {
waitMs: timeout,
intervalMs: 2000
});
} catch (e) {
throw new Error(`The emulator '${avdName ? avdName : this.curDeviceId}' is still running after being killed ${timeout}ms ago`);
}
_logger.default.info(`Successfully killed the '${avdName ? avdName : this.curDeviceId}' emulator`);
return true;
};
systemCallMethods.launchAVD = async function launchAVD(avdName, avdArgs, language, country, avdLaunchTimeout = 60000, avdReadyTimeout = 60000, retryTimes = 1) {
_logger.default.debug(`Launching Emulator with AVD ${avdName}, launchTimeout ` + `${avdLaunchTimeout}ms and readyTimeout ${avdReadyTimeout}ms`);
let emulatorBinaryPath = await this.getSdkBinaryPath('emulator');
if (avdName[0] === '@') {
avdName = avdName.substr(1);
}
await this.checkAvdExist(avdName);
let launchArgs = ['-avd', avdName];
if (_lodash.default.isString(language)) {
_logger.default.debug(`Setting Android Device Language to ${language}`);
launchArgs.push('-prop', `persist.sys.language=${language.toLowerCase()}`);
}
if (_lodash.default.isString(country)) {
_logger.default.debug(`Setting Android Device Country to ${country}`);
launchArgs.push('-prop', `persist.sys.country=${country.toUpperCase()}`);
}
let locale;
if (_lodash.default.isString(language) && _lodash.default.isString(country)) {
locale = language.toLowerCase() + '-' + country.toUpperCase();
} else if (_lodash.default.isString(language)) {
locale = language.toLowerCase();
} else if (_lodash.default.isString(country)) {
locale = country;
}
if (_lodash.default.isString(locale)) {
_logger.default.debug(`Setting Android Device Locale to ${locale}`);
launchArgs.push('-prop', `persist.sys.locale=${locale}`);
}
if (!_lodash.default.isEmpty(avdArgs)) {
launchArgs.push(...(_lodash.default.isArray(avdArgs) ? avdArgs : avdArgs.split(' ')));
}
_logger.default.debug(`Running '${emulatorBinaryPath}' with args: ${JSON.stringify(launchArgs)}`);
let proc = new _teen_process.SubProcess(emulatorBinaryPath, launchArgs);
await proc.start(0);
proc.on('output', (stdout, stderr) => {
for (let line of (stdout || stderr || '').split('\n').filter(Boolean)) {
_logger.default.info(`[AVD OUTPUT] ${line}`);
}
});
proc.on('die', (code, signal) => {
_logger.default.warn(`Emulator avd ${avdName} exited with code ${code}${signal ? `, signal ${signal}` : ''}`);
});
await (0, _asyncbox.retry)(retryTimes, async () => await this.getRunningAVDWithRetry(avdName, avdLaunchTimeout));
await this.waitForEmulatorReady(avdReadyTimeout);
return proc;
};
systemCallMethods.getAdbVersion = _lodash.default.memoize(async function getAdbVersion() {
try {
let adbVersion = (await this.adbExec('version')).replace(/Android\sDebug\sBridge\sversion\s([\d.]*)[\s\w-]*/, '$1');
let parts = adbVersion.split('.');
return {
versionString: adbVersion,
versionFloat: parseFloat(adbVersion),
major: parseInt(parts[0], 10),
minor: parseInt(parts[1], 10),
patch: parts[2] ? parseInt(parts[2], 10) : undefined
};
} catch (e) {
throw new Error(`Error getting adb version. Original error: '${e.message}'; ` + `Stderr: '${(e.stderr || '').trim()}'; Code: '${e.code}'`);
}
});
systemCallMethods.checkAvdExist = async function checkAvdExist(avdName) {
let cmd, result;
try {
cmd = await this.getSdkBinaryPath('emulator');
result = await (0, _teen_process.exec)(cmd, ['-list-avds']);
} catch (e) {
let unknownOptionError = new RegExp('unknown option: -list-avds', 'i').test(e.stderr);
if (!unknownOptionError) {
throw new Error(`Error executing checkAvdExist. Original error: '${e.message}'; ` + `Stderr: '${(e.stderr || '').trim()}'; Code: '${e.code}'`);
}
const sdkVersion = await (0, _helpers.getSdkToolsVersion)();
let binaryName = 'android';
if (sdkVersion) {
if (sdkVersion.major >= 25) {
binaryName = 'avdmanager';
}
} else {
_logger.default.warn(`Defaulting binary name to '${binaryName}', because SDK version cannot be parsed`);
}
cmd = await this.getSdkBinaryPath(binaryName);
result = await (0, _teen_process.exec)(cmd, ['list', 'avd', '-c']);
}
if (result.stdout.indexOf(avdName) === -1) {
let existings = `(${result.stdout.trim().replace(/[\n]/g, '), (')})`;
throw new Error(`Avd '${avdName}' is not available. please select your avd name from one of these: '${existings}'`);
}
};
systemCallMethods.waitForEmulatorReady = async function waitForEmulatorReady(timeoutMs = 20000) {
try {
await (0, _asyncbox.waitForCondition)(async () => {
try {
if (!(await this.shell(['getprop', 'init.svc.bootanim'])).includes('stopped')) {
return false;
}
return /\d+\[\w+\]/.test(await this.shell(['pm', 'get-install-location']));
} catch (err) {
_logger.default.debug(`Waiting for emulator startup. Intermediate error: ${err.message}`);
return false;
}
}, {
waitMs: timeoutMs,
intervalMs: 3000
});
} catch (e) {
throw new Error(`Emulator is not ready within ${timeoutMs}ms`);
}
};
systemCallMethods.waitForDevice = async function waitForDevice(appDeviceReadyTimeout = 30) {
this.appDeviceReadyTimeout = appDeviceReadyTimeout;
const retries = 3;
const timeout = parseInt(this.appDeviceReadyTimeout, 10) / retries * 1000;
await (0, _asyncbox.retry)(retries, async () => {
try {
await this.adbExec('wait-for-device', {
timeout
});
await this.ping();
} catch (e) {
await this.restartAdb();
await this.getConnectedDevices();
throw new Error(`Error waiting for the device to be available. Original error: '${e.message}'`);
}
});
};
systemCallMethods.reboot = async function reboot(retries = DEFAULT_ADB_REBOOT_RETRIES) {
const {
wasAlreadyRooted
} = await this.root();
try {
await this.shell(['stop']);
await _bluebird.default.delay(2000);
await this.setDeviceProperty('sys.boot_completed', 0, {
privileged: false
});
await this.shell(['start']);
} catch (e) {
const {
message
} = e;
if (message.includes('must be root')) {
throw new Error(`Could not reboot device. Rebooting requires root access and ` + `attempt to get root access on device failed with error: '${message}'`);
}
throw e;
} finally {
if (!wasAlreadyRooted) {
await this.unroot();
}
}
const timer = new _appiumSupport.timing.Timer().start();
await (0, _asyncbox.retryInterval)(retries, 1000, async () => {
if ((await this.getDeviceProperty('sys.boot_completed')) === '1') {
return;
}
const msg = `Reboot is not completed after ${timer.getDuration().asMilliSeconds.toFixed(0)}ms`;
_logger.default.debug(msg);
throw new Error(msg);
});
};
systemCallMethods.changeUserPrivileges = async function changeUserPrivileges(isElevated) {
const cmd = isElevated ? 'root' : 'unroot';
const isRoot = await this.isRoot();
if (isRoot && isElevated || !isRoot && !isElevated) {
return {
isSuccessful: true,
wasAlreadyRooted: isRoot
};
}
let wasAlreadyRooted = isRoot;
try {
let {
stdout
} = await this.adbExec([cmd]);
if (stdout) {
if (stdout.includes('adbd cannot run as root')) {
return {
isSuccessful: false,
wasAlreadyRooted
};
}
if (stdout.includes('already running as root')) {
wasAlreadyRooted = true;
}
}
return {
isSuccessful: true,
wasAlreadyRooted
};
} catch (err) {
const {
stderr = '',
message
} = err;
_logger.default.warn(`Unable to ${cmd} adb daemon. Original error: '${message}'. Stderr: '${stderr}'. Continuing.`);
if (['closed', 'device offline', 'timeout expired'].some(x => stderr.toLowerCase().includes(x))) {
_logger.default.warn(`Attempt to 'adb ${cmd}' caused device to go offline. Restarting adb.`);
await this.restartAdb();
}
return {
isSuccessful: false,
wasAlreadyRooted
};
}
};
systemCallMethods.root = async function root() {
return await this.changeUserPrivileges(true);
};
systemCallMethods.unroot = async function unroot() {
return await this.changeUserPrivileges(false);
};
systemCallMethods.isRoot = async function isRoot() {
return (await this.shell(['whoami'])).trim() === 'root';
};
systemCallMethods.fileExists = async function fileExists(remotePath) {
const passFlag = '__PASS__';
const checkCmd = `[ -e '${remotePath.replace(/'/g, `\\'`)}' ] && echo ${passFlag}`;
try {
return _lodash.default.includes(await this.shell([checkCmd]), passFlag);
} catch (ign) {
return false;
}
};
systemCallMethods.ls = async function ls(remotePath, opts = []) {
try {
let args = ['ls', ...opts, remotePath];
let stdout = await this.shell(args);
let lines = stdout.split('\n');
return lines.map(l => l.trim()).filter(Boolean).filter(l => l.indexOf('No such file') === -1);
} catch (err) {
if (err.message.indexOf('No such file or directory') === -1) {
throw err;
}
return [];
}
};
systemCallMethods.fileSize = async function fileSize(remotePath) {
try {
const files = await this.ls(remotePath, ['-la']);
if (files.length !== 1) {
throw new Error(`Remote path is not a file`);
}
const match = /[rwxsStT\-+]{10}[\s\d]*\s[^\s]+\s+[^\s]+\s+(\d+)/.exec(files[0]);
if (!match || _lodash.default.isNaN(parseInt(match[1], 10))) {
throw new Error(`Unable to parse size from list output: '${files[0]}'`);
}
return parseInt(match[1], 10);
} catch (err) {
throw new Error(`Unable to get file size for '${remotePath}': ${err.message}`);
}
};
systemCallMethods.installMitmCertificate = async function installMitmCertificate(cert) {
const openSsl = await (0, _helpers.getOpenSslForOs)();
if (!_lodash.default.isBuffer(cert)) {
cert = Buffer.from(cert, 'base64');
}
const tmpRoot = await _appiumSupport.tempDir.openDir();
try {
const srcCert = _path.default.resolve(tmpRoot, 'source.cer');
await _appiumSupport.fs.writeFile(srcCert, cert);
let {
stdout
} = await (0, _teen_process.exec)(openSsl, ['x509', '-noout', '-hash', '-in', srcCert]);
const certHash = stdout.trim();
_logger.default.debug(`Got certificate hash: ${certHash}`);
_logger.default.debug('Preparing certificate content');
({
stdout
} = await (0, _teen_process.exec)(openSsl, ['x509', '-in', srcCert], {
isBuffer: true
}));
let dstCertContent = stdout;
({
stdout
} = await (0, _teen_process.exec)(openSsl, ['x509', '-in', srcCert, '-text', '-fingerprint', '-noout'], {
isBuffer: true
}));
dstCertContent = Buffer.concat([dstCertContent, stdout]);
const dstCert = _path.default.resolve(tmpRoot, `${certHash}.0`);
await _appiumSupport.fs.writeFile(dstCert, dstCertContent);
_logger.default.debug('Remounting /system in rw mode');
await (0, _asyncbox.retryInterval)(5, 2000, async () => await this.adbExec(['remount']));
_logger.default.debug(`Uploading the generated certificate from '${dstCert}' to '${CERTS_ROOT}'`);
await this.push(dstCert, CERTS_ROOT);
_logger.default.debug('Remounting /system to confirm changes');
await this.adbExec(['remount']);
} catch (err) {
throw new Error(`Cannot inject the custom certificate. ` + `Is the certificate properly encoded into base64-string? ` + `Do you have root permissions on the device? ` + `Original error: ${err.message}`);
} finally {
await _appiumSupport.fs.rimraf(tmpRoot);
}
};
systemCallMethods.isMitmCertificateInstalled = async function isMitmCertificateInstalled(cert) {
const openSsl = await (0, _helpers.getOpenSslForOs)();
if (!_lodash.default.isBuffer(cert)) {
cert = Buffer.from(cert, 'base64');
}
const tmpRoot = await _appiumSupport.tempDir.openDir();
let certHash;
try {
const tmpCert = _path.default.resolve(tmpRoot, 'source.cer');
await _appiumSupport.fs.writeFile(tmpCert, cert);
const {
stdout
} = await (0, _teen_process.exec)(openSsl, ['x509', '-noout', '-hash', '-in', tmpCert]);
certHash = stdout.trim();
} catch (err) {
throw new Error(`Cannot retrieve the certificate hash. ` + `Is the certificate properly encoded into base64-string? ` + `Original error: ${err.message}`);
} finally {
await _appiumSupport.fs.rimraf(tmpRoot);
}
const dstPath = _path.default.posix.resolve(CERTS_ROOT, `${certHash}.0`);
_logger.default.debug(`Checking if the certificate is already installed at '${dstPath}'`);
return await this.fileExists(dstPath);
};
var _default = systemCallMethods;
exports.default = _default;require('source-map-support').install();
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi90b29scy9zeXN0ZW0tY2FsbHMuanMiXSwibmFtZXMiOlsic3lzdGVtQ2FsbE1ldGhvZHMiLCJERUZBVUxUX0FEQl9SRUJPT1RfUkVUUklFUyIsIkxJTktFUl9XQVJOSU5HX1JFR0VYUCIsIlBST1RPQ09MX0ZBVUxUX0VSUk9SX1JFR0VYUCIsIlJlZ0V4cCIsIkRFVklDRV9OT1RfRk9VTkRfRVJST1JfUkVHRVhQIiwiREVWSUNFX0NPTk5FQ1RJTkdfRVJST1JfUkVHRVhQIiwiQ0VSVFNfUk9PVCIsImdldFNka0JpbmFyeVBhdGgiLCJiaW5hcnlOYW1lIiwic2RrUm9vdCIsImdldEJpbmFyeUZyb21TZGtSb290IiwibG9nIiwid2FybiIsImdldEJpbmFyeUZyb21QYXRoIiwiZ2V0QmluYXJ5TmFtZUZvck9TIiwiXyIsIm1lbW9pemUiLCJzeXN0ZW0iLCJpc1dpbmRvd3MiLCJpbmNsdWRlcyIsInBhdGgiLCJleHRuYW1lIiwiYmluYXJpZXMiLCJmdWxsQmluYXJ5TmFtZSIsImJpbmFyeUxvY3MiLCJzZXAiLCJtYXAiLCJ4IiwicmVzb2x2ZSIsImJ1aWxkVG9vbHNEaXJzIiwiYnVpbGRUb29sc1ZlcnNpb24iLCJmaWx0ZXIiLCJiYXNlbmFtZSIsImlzRW1wdHkiLCJpbmZvIiwicHVzaCIsImZsYXR0ZW4iLCJkaXIiLCJiaW5hcnlMb2MiLCJsb2MiLCJmcyIsImV4aXN0cyIsImlzTnVsbCIsIkVycm9yIiwiSlNPTiIsInN0cmluZ2lmeSIsIndoaWNoIiwiZSIsImdldENvbm5lY3RlZERldmljZXMiLCJkZWJ1ZyIsInN0ZG91dCIsImV4ZWN1dGFibGUiLCJkZWZhdWx0QXJncyIsIm1lc3NhZ2UiLCJsaXN0SGVhZGVyIiwic3RhcnRpbmdJbmRleCIsImluZGV4T2YiLCJzbGljZSIsImV4Y2x1ZGVkTGluZXMiLCJhbGxvd09mZmxpbmVEZXZpY2VzIiwiZGV2aWNlcyIsInNwbGl0IiwidHJpbSIsImxpbmUiLCJzb21lIiwicmVkdWNlIiwiYWNjIiwidWRpZCIsInN0YXRlIiwiZ2V0RGV2aWNlc1dpdGhSZXRyeSIsInRpbWVvdXRNcyIsInRpbWVyIiwidGltaW5nIiwiVGltZXIiLCJzdGFydCIsImdldERldmljZXMiLCJnZXREdXJhdGlvbiIsImFzTWlsbGlTZWNvbmRzIiwidG9GaXhlZCIsImxlbmd0aCIsImlnbiIsInJlc3RhcnRBZGIiLCJzdXBwcmVzc0tpbGxTZXJ2ZXIiLCJraWxsU2VydmVyIiwiZXJyb3IiLCJhZGJQb3J0IiwiYWRiRXhlYyIsImV4Y2x1c2l2ZSIsInJlc2V0VGVsbmV0QXV0aFRva2VuIiwiaG9tZUZvbGRlclBhdGgiLCJwcm9jZXNzIiwiZW52IiwicGxhdGZvcm0iLCJkc3RQYXRoIiwid3JpdGVGaWxlIiwiYWRiRXhlY0VtdSIsImNtZCIsInZlcmlmeUVtdWxhdG9yQ29ubmVjdGVkIiwiaXNFeGVjTG9ja2VkIiwib3B0cyIsImNsb25lRGVlcCIsInRpbWVvdXQiLCJhZGJFeGVjVGltZW91dCIsIkRFRkFVTFRfQURCX0VYRUNfVElNRU9VVCIsInRpbWVvdXRDYXBOYW1lIiwiaXNBcnJheSIsImFkYlJldHJpZWQiLCJleGVjRnVuYyIsImFyZ3MiLCJ1dGlsIiwicXVvdGUiLCJyZXBsYWNlIiwiZXJyVGV4dCIsInN0ZGVyciIsInByb3RvY29sRmF1bHRFcnJvciIsInRlc3QiLCJkZXZpY2VOb3RGb3VuZEVycm9yIiwiZGV2aWNlQ29ubmVjdGluZ0Vycm9yIiwiY29kZSIsIndhaXRNcyIsIk51bWJlciIsIk1BWF9TQUZFX0lOVEVHRVIiLCJpbnRlcnZhbE1zIiwic2hlbGwiLCJwcml2aWxlZ2VkIiwia2VlcFByaXZpbGVnZWQiLCJzaG91bGRSZXN0b3JlVXNlciIsIndhc0FscmVhZHlSb290ZWQiLCJpc1N1Y2Nlc3NmdWwiLCJyb290IiwiZGlkQ29tbWFuZEZhaWwiLCJlcnIiLCJ1bnJvb3QiLCJjcmVhdGVTdWJQcm9jZXNzIiwiY29uY2F0IiwiU3ViUHJvY2VzcyIsImdldEFkYlBhdGgiLCJnZXRBZGJTZXJ2ZXJQb3J0IiwiZ2V0RW11bGF0b3JQb3J0IiwiZW11bGF0b3JQb3J0IiwicG9ydCIsImdldFBvcnRGcm9tRW11bGF0b3JTdHJpbmciLCJlbVN0ciIsInBvcnRQYXR0ZXJuIiwicGFyc2VJbnQiLCJleGVjIiwiZ2V0Q29ubmVjdGVkRW11bGF0b3JzIiwiZW11bGF0b3JzIiwiZGV2aWNlIiwicGx1cmFsaXplIiwic2V0RW11bGF0b3JQb3J0IiwiZW1Qb3J0Iiwic2V0RGV2aWNlSWQiLCJkZXZpY2VJZCIsImN1ckRldmljZUlkIiwiYXJnc0hhc0RldmljZSIsInNwbGljZSIsInNldERldmljZSIsImRldmljZU9iaiIsImdldFJ1bm5pbmdBVkQiLCJhdmROYW1lIiwiZW11bGF0b3IiLCJydW5uaW5nQVZETmFtZSIsInNlbmRUZWxuZXRDb21tYW5kIiwidG9Mb3dlciIsImdldFJ1bm5pbmdBVkRXaXRoUmV0cnkiLCJydW5uaW5nQXZkIiwia2lsbEFsbEVtdWxhdG9ycyIsImtpbGxFbXVsYXRvciIsImhhc1ZhbHVlIiwiaXNFbXVsYXRvckNvbm5lY3RlZCIsImxhdW5jaEFWRCIsImF2ZEFyZ3MiLCJsYW5ndWFnZSIsImNvdW50cnkiLCJhdmRMYXVuY2hUaW1lb3V0IiwiYXZkUmVhZHlUaW1lb3V0IiwicmV0cnlUaW1lcyIsImVtdWxhdG9yQmluYXJ5UGF0aCIsInN1YnN0ciIsImNoZWNrQXZkRXhpc3QiLCJsYXVuY2hBcmdzIiwiaXNTdHJpbmciLCJ0b0xvd2VyQ2FzZSIsInRvVXBwZXJDYXNlIiwibG9jYWxlIiwicHJvYyIsIm9uIiwiQm9vbGVhbiIsInNpZ25hbCIsIndhaXRGb3JFbXVsYXRvclJlYWR5IiwiZ2V0QWRiVmVyc2lvbiIsImFkYlZlcnNpb24iLCJwYXJ0cyIsInZlcnNpb25TdHJpbmciLCJ2ZXJzaW9uRmxvYXQiLCJwYXJzZUZsb2F0IiwibWFqb3IiLCJtaW5vciIsInBhdGNoIiwidW5kZWZpbmVkIiwicmVzdWx0IiwidW5rbm93bk9wdGlvbkVycm9yIiwic2RrVmVyc2lvbiIsImV4aXN0aW5ncyIsIndhaXRGb3JEZXZpY2UiLCJhcHBEZXZpY2VSZWFkeVRpbWVvdXQiLCJyZXRyaWVzIiwicGluZyIsInJlYm9vdCIsIkIiLCJkZWxheSIsInNldERldmljZVByb3BlcnR5IiwiZ2V0RGV2aWNlUHJvcGVydHkiLCJtc2ciLCJjaGFuZ2VVc2VyUHJpdmlsZWdlcyIsImlzRWxldmF0ZWQiLCJpc1Jvb3QiLCJmaWxlRXhpc3RzIiwicmVtb3RlUGF0aCIsInBhc3NGbGFnIiwiY2hlY2tDbWQiLCJscyIsImxpbmVzIiwibCIsImZpbGVTaXplIiwiZmlsZXMiLCJtYXRjaCIsImlzTmFOIiwiaW5zdGFsbE1pdG1DZXJ0aWZpY2F0ZSIsImNlcnQiLCJvcGVuU3NsIiwiaXNCdWZmZXIiLCJCdWZmZXIiLCJmcm9tIiwidG1wUm9vdCIsInRlbXBEaXIiLCJvcGVuRGlyIiwic3JjQ2VydCIsImNlcnRIYXNoIiwiZHN0Q2VydENvbnRlbnQiLCJkc3RDZXJ0IiwicmltcmFmIiwiaXNNaXRtQ2VydGlmaWNhdGVJbnN0YWxsZWQiLCJ0bXBDZXJ0IiwicG9zaXgiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBS0E7O0FBQ0E7O0FBQ0E7O0FBR0EsSUFBSUEsaUJBQWlCLEdBQUcsRUFBeEI7QUFFQSxNQUFNQywwQkFBMEIsR0FBRyxFQUFuQztBQUVBLE1BQU1DLHFCQUFxQixHQUFHLHNCQUE5QjtBQUNBLE1BQU1DLDJCQUEyQixHQUFHLElBQUlDLE1BQUosQ0FBVyxnQ0FBWCxFQUE2QyxHQUE3QyxDQUFwQztBQUNBLE1BQU1DLDZCQUE2QixHQUFHLElBQUlELE1BQUosQ0FBWSxpQ0FBWixFQUE4QyxHQUE5QyxDQUF0QztBQUNBLE1BQU1FLDhCQUE4QixHQUFHLElBQUlGLE1BQUosQ0FBVyxnQ0FBWCxFQUE2QyxHQUE3QyxDQUF2QztBQUVBLE1BQU1HLFVBQVUsR0FBRyw4QkFBbkI7O0FBUUFQLGlCQUFpQixDQUFDUSxnQkFBbEIsR0FBcUMsZUFBZUEsZ0JBQWYsQ0FBaUNDLFVBQWpDLEVBQTZDO0FBQ2hGLE1BQUksS0FBS0MsT0FBVCxFQUFrQjtBQUNoQixXQUFPLE1BQU0sS0FBS0Msb0JBQUwsQ0FBMEJGLFVBQTFCLENBQWI7QUFDRDs7QUFDREcsa0JBQUlDLElBQUosQ0FBVSxzRUFBRCxHQUNOLGtFQURNLEdBRU4seUNBQXdDSixVQUFXLEdBRnREOztBQUdBLFNBQU8sTUFBTSxLQUFLSyxpQkFBTCxDQUF1QkwsVUFBdkIsQ0FBYjtBQUNELENBUkQ7O0FBaUJBVCxpQkFBaUIsQ0FBQ2Usa0JBQWxCLEdBQXVDQyxnQkFBRUMsT0FBRixDQUFVLFNBQVNGLGtCQUFULENBQTZCTixVQUE3QixFQUF5QztBQUN4RixNQUFJLENBQUNTLHNCQUFPQyxTQUFQLEVBQUwsRUFBeUI7QUFDdkIsV0FBT1YsVUFBUDtBQUNEOztBQUVELE1BQUksQ0FBQyxTQUFELEVBQVksV0FBWixFQUF5QixhQUF6QixFQUF3Q1csUUFBeEMsQ0FBaURYLFVBQWpELENBQUosRUFBa0U7QUFDaEUsV0FBUSxHQUFFQSxVQUFXLE1BQXJCO0FBQ0Q7O0FBQ0QsTUFBSSxDQUFDWSxjQUFLQyxPQUFMLENBQWFiLFVBQWIsQ0FBTCxFQUErQjtBQUM3QixXQUFRLEdBQUVBLFVBQVcsTUFBckI7QUFDRDs7QUFDRCxTQUFPQSxVQUFQO0FBQ0QsQ0Fac0MsQ0FBdkM7O0FBMkJBVCxpQkFBaUIsQ0FBQ1csb0JBQWxCLEdBQXlDLGVBQWVBLG9CQUFmLENBQXFDRixVQUFyQyxFQUFpRDtBQUN4RixNQUFJLEtBQUtjLFFBQUwsQ0FBY2QsVUFBZCxDQUFKLEVBQStCO0FBQzdCLFdBQU8sS0FBS2MsUUFBTCxDQUFjZCxVQUFkLENBQVA7QUFDRDs7QUFFRCxRQUFNZSxjQUFjLEdBQUcsS0FBS1Qsa0JBQUwsQ0FBd0JOLFVBQXhCLENBQXZCO0FBQ0EsUUFBTWdCLFVBQVUsR0FBRyxDQUFDLGdCQUFELEVBQW1CLFVBQW5CLEVBQStCLE9BQS9CLEVBQXlDLFFBQU9KLGNBQUtLLEdBQUksS0FBekQsRUFDaEJDLEdBRGdCLENBQ1hDLENBQUQsSUFBT1AsY0FBS1EsT0FBTCxDQUFhLEtBQUtuQixPQUFsQixFQUEyQmtCLENBQTNCLEVBQThCSixjQUE5QixDQURLLENBQW5CO0FBR0EsTUFBSU0sY0FBYyxHQUFHLE1BQU0sZ0NBQWtCLEtBQUtwQixPQUF2QixDQUEzQjs7QUFDQSxNQUFJLEtBQUtxQixpQkFBVCxFQUE0QjtBQUMxQkQsSUFBQUEsY0FBYyxHQUFHQSxjQUFjLENBQzVCRSxNQURjLENBQ05KLENBQUQsSUFBT1AsY0FBS1ksUUFBTCxDQUFjTCxDQUFkLE1BQXFCLEtBQUtHLGlCQUQxQixDQUFqQjs7QUFFQSxRQUFJZixnQkFBRWtCLE9BQUYsQ0FBVUosY0FBVixDQUFKLEVBQStCO0FBQzdCbEIsc0JBQUl1QixJQUFKLENBQVUsa0RBQWlELEtBQUtKLGlCQUFrQixHQUFsRjtBQUNELEtBRkQsTUFFTztBQUNMbkIsc0JBQUl1QixJQUFKLENBQVUseUJBQXdCTCxjQUFlLEdBQWpEO0FBQ0Q7QUFDRjs7QUFDREwsRUFBQUEsVUFBVSxDQUFDVyxJQUFYLENBQWdCLEdBQUlwQixnQkFBRXFCLE9BQUYsQ0FBVVAsY0FBYyxDQUN6Q0gsR0FEMkIsQ0FDdEJXLEdBQUQsSUFBUyxDQUNaakIsY0FBS1EsT0FBTCxDQUFhUyxHQUFiLEVBQWtCZCxjQUFsQixDQURZLEVBRVpILGNBQUtRLE9BQUwsQ0FBYVMsR0FBYixFQUFrQixLQUFsQixFQUF5QmQsY0FBekIsQ0FGWSxDQURjLENBQVYsQ0FBcEI7QUFPQSxNQUFJZSxTQUFTLEdBQUcsSUFBaEI7O0FBQ0EsT0FBSyxNQUFNQyxHQUFYLElBQWtCZixVQUFsQixFQUE4QjtBQUM1QixRQUFJLE1BQU1nQixrQkFBR0MsTUFBSCxDQUFVRixHQUFWLENBQVYsRUFBMEI7QUFDeEJELE1BQUFBLFNBQVMsR0FBR0MsR0FBWjtBQUNBO0FBQ0Q7QUFDRjs7QUFDRCxNQUFJeEIsZ0JBQUUyQixNQUFGLENBQVNKLFNBQVQsQ0FBSixFQUF5QjtBQUN2QixVQUFNLElBQUlLLEtBQUosQ0FBVyxtQkFBa0JwQixjQUFlLFFBQU9xQixJQUFJLENBQUNDLFNBQUwsQ0FBZXJCLFVBQWYsQ0FBMkIsSUFBcEUsR0FDYixtQ0FBa0MsS0FBS00saUJBQUwsR0FBMEIsS0FBSSxLQUFLQSxpQkFBa0IsR0FBckQsR0FBMEQsRUFBRyxFQURsRixHQUViLGlCQUFnQixLQUFLckIsT0FBUSxJQUYxQixDQUFOO0FBR0Q7O0FBQ0RFLGtCQUFJdUIsSUFBSixDQUFVLFVBQVNYLGNBQWUsV0FBVWUsU0FBVSxHQUF0RDs7QUFDQSxPQUFLaEIsUUFBTCxDQUFjZCxVQUFkLElBQTRCOEIsU0FBNUI7QUFDQSxTQUFPQSxTQUFQO0FBQ0QsQ0F6Q0Q7O0FBbURBdkMsaUJBQWlCLENBQUNjLGlCQUFsQixHQUFzQyxlQUFlQSxpQkFBZixDQUFrQ0wsVUFBbEMsRUFBOEM7QUFDbEYsTUFBSSxLQUFLYyxRQUFMLENBQWNkLFVBQWQsQ0FBSixFQUErQjtBQUM3QixXQUFPLEtBQUtjLFFBQUwsQ0FBY2QsVUFBZCxDQUFQO0FBQ0Q7O0FBRUQsUUFBTWUsY0FBYyxHQUFHLEtBQUtULGtCQUFMLENBQXdCTixVQUF4QixDQUF2Qjs7QUFDQSxNQUFJO0FBQ0YsVUFBTThCLFNBQVMsR0FBRyxNQUFNRSxrQkFBR00sS0FBSCxDQUFTdkIsY0FBVCxDQUF4Qjs7QUFDQVosb0JBQUl1QixJQUFKLENBQVUsVUFBU1gsY0FBZSxXQUFVZSxTQUFVLEdBQXREOztBQUNBLFNBQUtoQixRQUFMLENBQWNkLFVBQWQsSUFBNEI4QixTQUE1QjtBQUNBLFdBQU9BLFNBQVA7QUFDRCxHQUxELENBS0UsT0FBT1MsQ0FBUCxFQUFVO0FBQ1YsVUFBTSxJQUFJSixLQUFKLENBQVcsbUJBQWtCcEIsY0FBZSx5Q0FBbEMsR0FDYiwyRkFERyxDQUFOO0FBRUQ7QUFDRixDQWZEOztBQStCQXhCLGlCQUFpQixDQUFDaUQsbUJBQWxCLEdBQXdDLGVBQWVBLG1CQUFmLEdBQXNDO0FBQzVFckMsa0JBQUlzQyxLQUFKLENBQVUsOEJBQVY7O0FBQ0EsTUFBSUMsTUFBSjs7QUFDQSxNQUFJO0FBQ0YsS0FBQztBQUFDQSxNQUFBQTtBQUFELFFBQVcsTUFBTSx3QkFBSyxLQUFLQyxVQUFMLENBQWdCL0IsSUFBckIsRUFBMkIsQ0FBQyxHQUFHLEtBQUsrQixVQUFMLENBQWdCQyxXQUFwQixFQUFpQyxTQUFqQyxDQUEzQixDQUFsQjtBQUNELEdBRkQsQ0FFRSxPQUFPTCxDQUFQLEVBQVU7QUFDVixVQUFNLElBQUlKLEtBQUosQ0FBVywwREFBeURJLENBQUMsQ0FBQ00sT0FBUSxFQUE5RSxDQUFOO0FBQ0Q7O0FBQ0QsUUFBTUMsVUFBVSxHQUFHLGlCQUFuQjtBQUlBLFFBQU1DLGFBQWEsR0FBR0wsTUFBTSxDQUFDTSxPQUFQLENBQWVGLFVBQWYsQ0FBdEI7O0FBQ0EsTUFBSUMsYUFBYSxHQUFHLENBQXBCLEVBQXVCO0FBQ3JCLFVBQU0sSUFBSVosS0FBSixDQUFXLGtEQUFpRE8sTUFBTyxFQUFuRSxDQUFOO0FBQ0Q7O0FBRURBLEVBQUFBLE1BQU0sR0FBR0EsTUFBTSxDQUFDTyxLQUFQLENBQWFGLGFBQWIsQ0FBVDtBQUNBLE1BQUlHLGFBQWEsR0FBRyxDQUFDSixVQUFELEVBQWEsWUFBYixFQUEyQixVQUEzQixDQUFwQjs7QUFDQSxNQUFJLENBQUMsS0FBS0ssbUJBQVYsRUFBK0I7QUFDN0JELElBQUFBLGFBQWEsQ0FBQ3ZCLElBQWQsQ0FBbUIsU0FBbkI7QUFDRDs7QUFDRCxRQUFNeUIsT0FBTyxHQUFHVixNQUFNLENBQUNXLEtBQVAsQ0FBYSxJQUFiLEVBQ2JuQyxHQURhLENBQ1RYLGdCQUFFK0MsSUFETyxFQUViL0IsTUFGYSxDQUVMZ0MsSUFBRCxJQUFVQSxJQUFJLElBQUksQ0FBQ0wsYUFBYSxDQUFDTSxJQUFkLENBQW9CckMsQ0FBRCxJQUFPb0MsSUFBSSxDQUFDNUMsUUFBTCxDQUFjUSxDQUFkLENBQTFCLENBRmIsRUFHYnNDLE1BSGEsQ0FHTixDQUFDQyxHQUFELEVBQU1ILElBQU4sS0FBZTtBQUVyQixVQUFNLENBQUNJLElBQUQsRUFBT0MsS0FBUCxJQUFnQkwsSUFBSSxDQUFDRixLQUFMLENBQVcsS0FBWCxDQUF0QjtBQUNBSyxJQUFBQSxHQUFHLENBQUMvQixJQUFKLENBQVM7QUFBQ2dDLE1BQUFBLElBQUQ7QUFBT0MsTUFBQUE7QUFBUCxLQUFUO0FBQ0EsV0FBT0YsR0FBUDtBQUNELEdBUmEsRUFRWCxFQVJXLENBQWhCOztBQVNBLE1BQUluRCxnQkFBRWtCLE9BQUYsQ0FBVTJCLE9BQVYsQ0FBSixFQUF3QjtBQUN0QmpELG9CQUFJc0MsS0FBSixDQUFVLHlDQUFWO0FBQ0QsR0FGRCxNQUVPO0FBQ0x0QyxvQkFBSXNDLEtBQUosQ0FBVyxzQkFBcUJMLElBQUksQ0FBQ0MsU0FBTCxDQUFlZSxPQUFmLENBQXdCLEVBQXhEO0FBQ0Q7O0FBQ0QsU0FBT0EsT0FBUDtBQUNELENBckNEOztBQStDQTdELGlCQUFpQixDQUFDc0UsbUJBQWxCLEdBQXdDLGVBQWVBLG1CQUFmLENBQW9DQyxTQUFTLEdBQUcsS0FBaEQsRUFBdUQ7QUFDN0YsUUFBTUMsS0FBSyxHQUFHLElBQUlDLHNCQUFPQyxLQUFYLEdBQW1CQyxLQUFuQixFQUFkOztBQUNBL0Qsa0JBQUlzQyxLQUFKLENBQVUsMkNBQVY7O0FBQ0EsUUFBTTBCLFVBQVUsR0FBRyxZQUFZO0FBQzdCLFFBQUlKLEtBQUssQ0FBQ0ssV0FBTixHQUFvQkMsY0FBcEIsR0FBcUNQLFNBQXpDLEVBQW9EO0FBQ2xELFlBQU0sSUFBSTNCLEtBQUosQ0FBVyxnREFBK0M0QixLQUFLLENBQUNLLFdBQU4sR0FBb0JDLGNBQXBCLENBQW1DQyxPQUFuQyxDQUEyQyxDQUEzQyxDQUE4QyxLQUF4RyxDQUFOO0FBQ0Q7O0FBQ0QsUUFBSTtBQUNGLFlBQU1sQixPQUFPLEdBQUcsTUFBTSxLQUFLWixtQkFBTCxFQUF0Qjs7QUFDQSxVQUFJWSxPQUFPLENBQUNtQixNQUFSLEdBQWlCLENBQXJCLEVBQXdCO0FBQ3RCLGVBQU9uQixPQUFQO0FBQ0Q7QUFDRixLQUxELENBS0UsT0FBT29CLEdBQVAsRUFBWSxDQUFFOztBQUVoQnJFLG9CQUFJc0MsS0FBSixDQUFVLGtEQUFWOztBQUNBLFVBQU0sS0FBS2dDLFVBQUwsRUFBTjtBQUVBLFVBQU0scUJBQU0sR0FBTixDQUFOO0FBQ0EsV0FBTyxNQUFNTixVQUFVLEVBQXZCO0FBQ0QsR0FoQkQ7O0FBaUJBLFNBQU8sTUFBTUEsVUFBVSxFQUF2QjtBQUNELENBckJEOztBQTBCQTVFLGlCQUFpQixDQUFDa0YsVUFBbEIsR0FBK0IsZUFBZUEsVUFBZixHQUE2QjtBQUMxRCxNQUFJLEtBQUtDLGtCQUFULEVBQTZCO0FBQzNCdkUsb0JBQUlzQyxLQUFKLENBQVcscURBQVg7O0FBQ0E7QUFDRDs7QUFFRHRDLGtCQUFJc0MsS0FBSixDQUFVLGdCQUFWOztBQUNBLE1BQUk7QUFDRixVQUFNLEtBQUtrQyxVQUFMLEVBQU47QUFDRCxHQUZELENBRUUsT0FBT3BDLENBQVAsRUFBVTtBQUNWcEMsb0JBQUl5RSxLQUFKLENBQVcsOERBQVg7QUFDRDtBQUNGLENBWkQ7O0FBaUJBckYsaUJBQWlCLENBQUNvRixVQUFsQixHQUErQixlQUFlQSxVQUFmLEdBQTZCO0FBQzFEeEUsa0JBQUlzQyxLQUFKLENBQVcsK0JBQThCLEtBQUtvQyxPQUFRLEdBQXREOztBQUNBLFFBQU0sS0FBS0MsT0FBTCxDQUFhLENBQUMsYUFBRCxDQUFiLEVBQThCO0FBQ2xDQyxJQUFBQSxTQUFTLEVBQUU7QUFEdUIsR0FBOUIsQ0FBTjtBQUdELENBTEQ7O0FBYUF4RixpQkFBaUIsQ0FBQ3lGLG9CQUFsQixHQUF5Q3pFLGdCQUFFQyxPQUFGLENBQVUsZUFBZXdFLG9CQUFmLEdBQXVDO0FBR3hGLFFBQU1DLGNBQWMsR0FBR0MsT0FBTyxDQUFDQyxHQUFSLENBQWFELE9BQU8sQ0FBQ0UsUUFBUixLQUFxQixPQUF0QixHQUFpQyxhQUFqQyxHQUFpRCxNQUE3RCxDQUF2Qjs7QUFDQSxNQUFJLENBQUNILGNBQUwsRUFBcUI7QUFDbkI5RSxvQkFBSUMsSUFBSixDQUFVLHdHQUFWOztBQUNBLFdBQU8sS0FBUDtBQUNEOztBQUNELFFBQU1pRixPQUFPLEdBQUd6RSxjQUFLUSxPQUFMLENBQWE2RCxjQUFiLEVBQTZCLDhCQUE3QixDQUFoQjs7QUFDQTlFLGtCQUFJc0MsS0FBSixDQUFXLGNBQWE0QyxPQUFRLDRFQUFoQzs7QUFDQSxNQUFJO0FBQ0YsVUFBTXJELGtCQUFHc0QsU0FBSCxDQUFhRCxPQUFiLEVBQXNCLEVBQXRCLENBQU47QUFDRCxHQUZELENBRUUsT0FBTzlDLENBQVAsRUFBVTtBQUNWcEMsb0JBQUlDLElBQUosQ0FBVSxTQUFRbUMsQ0FBQyxDQUFDTSxPQUFRLG1DQUFrQ3dDLE9BQVEsZ0VBQXRFOztBQUNBLFdBQU8sS0FBUDtBQUNEOztBQUNELFNBQU8sSUFBUDtBQUNELENBakJ3QyxDQUF6Qzs7QUF3QkE5RixpQkFBaUIsQ0FBQ2dHLFVBQWxCLEdBQStCLGVBQWVBLFVBQWYsQ0FBMkJDLEdBQTNCLEVBQWdDO0FBQzdELFFBQU0sS0FBS0MsdUJBQUwsRUFBTjtBQUNBLFFBQU0sS0FBS1Qsb0JBQUwsRUFBTjtBQUNBLFFBQU0sS0FBS0YsT0FBTCxDQUFhLENBQUMsS0FBRCxFQUFRLEdBQUdVLEdBQVgsQ0FBYixDQUFOO0FBQ0QsQ0FKRDs7QUFNQSxJQUFJRSxZQUFZLEdBQUcsS0FBbkI7O0FBZ0JBbkcsaUJBQWlCLENBQUN1RixPQUFsQixHQUE0QixlQUFlQSxPQUFmLENBQXdCVSxHQUF4QixFQUE2QkcsSUFBSSxHQUFHLEVBQXBDLEVBQXdDO0FBQ2xFLE1BQUksQ0FBQ0gsR0FBTCxFQUFVO0FBQ1IsVUFBTSxJQUFJckQsS0FBSixDQUFVLDRDQUFWLENBQU47QUFDRDs7QUFFRHdELEVBQUFBLElBQUksR0FBR3BGLGdCQUFFcUYsU0FBRixDQUFZRCxJQUFaLENBQVA7QUFFQUEsRUFBQUEsSUFBSSxDQUFDRSxPQUFMLEdBQWVGLElBQUksQ0FBQ0UsT0FBTCxJQUFnQixLQUFLQyxjQUFyQixJQUF1Q0MsaUNBQXREO0FBQ0FKLEVBQUFBLElBQUksQ0FBQ0ssY0FBTCxHQUFzQkwsSUFBSSxDQUFDSyxjQUFMLElBQXVCLGdCQUE3QztBQUVBUixFQUFBQSxHQUFHLEdBQUdqRixnQkFBRTBGLE9BQUYsQ0FBVVQsR0FBVixJQUFpQkEsR0FBakIsR0FBdUIsQ0FBQ0EsR0FBRCxDQUE3QjtBQUNBLE1BQUlVLFVBQVUsR0FBRyxLQUFqQjs7QUFDQSxRQUFNQyxRQUFRLEdBQUcsWUFBWTtBQUMzQixRQUFJO0FBQ0YsWUFBTUMsSUFBSSxHQUFHLENBQUMsR0FBRyxLQUFLekQsVUFBTCxDQUFnQkMsV0FBcEIsRUFBaUMsR0FBRzRDLEdBQXBDLENBQWI7O0FBQ0FyRixzQkFBSXNDLEtBQUosQ0FBVyxZQUFXLEtBQUtFLFVBQUwsQ0FBZ0IvQixJQUFLLElBQUd5RixvQkFBS0MsS0FBTCxDQUFXRixJQUFYLENBQWlCLEdBQS9EOztBQUNBLFVBQUk7QUFBQzFELFFBQUFBO0FBQUQsVUFBVyxNQUFNLHdCQUFLLEtBQUtDLFVBQUwsQ0FBZ0IvQixJQUFyQixFQUEyQndGLElBQTNCLEVBQWlDVCxJQUFqQyxDQUFyQjtBQUdBakQsTUFBQUEsTUFBTSxHQUFHQSxNQUFNLENBQUM2RCxPQUFQLENBQWU5RyxxQkFBZixFQUFzQyxFQUF0QyxFQUEwQzZELElBQTFDLEVBQVQ7QUFDQSxhQUFPWixNQUFQO0FBQ0QsS0FSRCxDQVFFLE9BQU9ILENBQVAsRUFBVTtBQUNWLFlBQU1pRSxPQUFPLEdBQUksR0FBRWpFLENBQUMsQ0FBQ00sT0FBUSxLQUFJTixDQUFDLENBQUNHLE1BQU8sS0FBSUgsQ0FBQyxDQUFDa0UsTUFBTyxFQUF2RDtBQUNBLFlBQU1DLGtCQUFrQixHQUFHaEgsMkJBQTJCLENBQUNpSCxJQUE1QixDQUFpQ0gsT0FBakMsQ0FBM0I7QUFDQSxZQUFNSSxtQkFBbUIsR0FBR2hILDZCQUE2QixDQUFDK0csSUFBOUIsQ0FBbUNILE9BQW5DLENBQTVCO0FBQ0EsWUFBTUsscUJBQXFCLEdBQUdoSCw4QkFBOEIsQ0FBQzhHLElBQS9CLENBQW9DSCxPQUFwQyxDQUE5Qjs7QUFDQSxVQUFJRSxrQkFBa0IsSUFBSUUsbUJBQXRCLElBQTZDQyxxQkFBakQsRUFBd0U7QUFDdEUxRyx3QkFBSXVCLElBQUosQ0FBVSw0REFBMkQ4RCxHQUFJLEVBQXpFOztBQUNBLGNBQU0scUJBQU0sSUFBTixDQUFOO0FBQ0EsY0FBTSxLQUFLM0IsbUJBQUwsRUFBTjs7QUFHQSxZQUFJcUMsVUFBSixFQUFnQjtBQUNkQSxVQUFBQSxVQUFVLEdBQUcsSUFBYjtBQUNBLGlCQUFPLE1BQU1DLFFBQVEsRUFBckI7QUFDRDtBQUNGOztBQUVELFVBQUk1RCxDQUFDLENBQUN1RSxJQUFGLEtBQVcsQ0FBWCxJQUFnQnZFLENBQUMsQ0FBQ0csTUFBdEIsRUFBOEI7QUFDNUIsZUFBT0gsQ0FBQyxDQUFDRyxNQUFGLENBQVM2RCxPQUFULENBQWlCOUcscUJBQWpCLEVBQXdDLEVBQXhDLEVBQTRDNkQsSUFBNUMsRUFBUDtBQUNEOztBQUVELFVBQUkvQyxnQkFBRTJCLE1BQUYsQ0FBU0ssQ0FBQyxDQUFDdUUsSUFBWCxDQUFKLEVBQXNCO0FBQ3BCdkUsUUFBQUEsQ0FBQyxDQUFDTSxPQUFGLEdBQWEsNkNBQTRDTixDQUFDLENBQUNNLE9BQVEsS0FBdkQsR0FDVCx1QkFBc0I4QyxJQUFJLENBQUNFLE9BQVEsNENBQTJDRixJQUFJLENBQUNLLGNBQWUsY0FEckc7QUFFRCxPQUhELE1BR087QUFDTHpELFFBQUFBLENBQUMsQ0FBQ00sT0FBRixHQUFhLDZDQUE0Q04sQ0FBQyxDQUFDTSxPQUFRLEtBQXZELEdBQ1QsWUFBVyxDQUFDTixDQUFDLENBQUNrRSxNQUFGLElBQVksRUFBYixFQUFpQm5ELElBQWpCLEVBQXdCLGFBQVlmLENBQUMsQ0FBQ3VFLElBQUssR0FEekQ7QUFFRDs7QUFDRCxZQUFNdkUsQ0FBTjtBQUNEO0FBQ0YsR0F2Q0Q7O0FBeUNBLE1BQUltRCxZQUFKLEVBQWtCO0FBQ2hCdkYsb0JBQUlzQyxLQUFKLENBQVUsNERBQVY7O0FBQ0EsVUFBTSxnQ0FBaUIsTUFBTSxDQUFDaUQsWUFBeEIsRUFBc0M7QUFDMUNxQixNQUFBQSxNQUFNLEVBQUVDLE1BQU0sQ0FBQ0MsZ0JBRDJCO0FBRTFDQyxNQUFBQSxVQUFVLEVBQUU7QUFGOEIsS0FBdEMsQ0FBTjs7QUFJQS9HLG9CQUFJc0MsS0FBSixDQUFVLHlDQUFWO0FBQ0Q7O0FBQ0QsTUFBSWtELElBQUksQ0FBQ1osU0FBVCxFQUFvQjtBQUNsQlcsSUFBQUEsWUFBWSxHQUFHLElBQWY7QUFDRDs7QUFDRCxNQUFJO0FBQ0YsV0FBTyxNQUFNUyxRQUFRLEVBQXJCO0FBQ0QsR0FGRCxTQUVVO0FBQ1IsUUFBSVIsSUFBSSxDQUFDWixTQUFULEVBQW9CO0FBQ2xCVyxNQUFBQSxZQUFZLEdBQUcsS0FBZjtBQUNEO0FBQ0Y7QUFDRixDQXZFRDs7QUE4RkFuRyxpQkFBaUIsQ0FBQzRILEtBQWxCLEdBQTBCLGVBQWVBLEtBQWYsQ0FBc0IzQixHQUF0QixFQUEyQkcsSUFBSSxHQUFHLEVBQWxDLEVBQXNDO0FBQzlELFFBQU07QUFDSnlCLElBQUFBLFVBREk7QUFFSkMsSUFBQUE7QUFGSSxNQUdGMUIsSUFISjtBQU1BLE1BQUkyQixpQkFBaUIsR0FBRyxLQUF4Qjs7QUFDQSxNQUFJRixVQUFKLEVBQWdCO0FBQ2RqSCxvQkFBSXVCLElBQUosQ0FBVSxjQUFhOEQsR0FBSSw2REFBM0I7O0FBQ0EsVUFBTTtBQUFDK0IsTUFBQUEsZ0JBQUQ7QUFBbUJDLE1BQUFBO0FBQW5CLFFBQW1DLE1BQU0sS0FBS0MsSUFBTCxFQUEvQztBQUNBSCxJQUFBQSxpQkFBaUIsR0FBRyxDQUFDQyxnQkFBckI7O0FBQ0EsUUFBSUEsZ0JBQUosRUFBc0I7QUFDcEJwSCxzQkFBSXVCLElBQUosQ0FBUyxnQ0FBVDtBQUNELEtBRkQsTUFFTztBQUNMdkIsc0JBQUl1QixJQUFKLENBQVM4RixZQUFZLEdBQUcsaUNBQUgsR0FBdUMsNEJBQTVEO0FBQ0Q7QUFDRjs7QUFDRCxNQUFJRSxjQUFjLEdBQUcsS0FBckI7O0FBQ0EsTUFBSTtBQUNGLFFBQUk7QUFDRixhQUFPLE1BQU0sS0FBSzVDLE9BQUwsQ0FBYXZFLGdCQUFFMEYsT0FBRixDQUFVVCxHQUFWLElBQWlCLENBQUMsT0FBRCxFQUFVLEdBQUdBLEdBQWIsQ0FBakIsR0FBcUMsQ0FBQyxPQUFELEVBQVVBLEdBQVYsQ0FBbEQsRUFBa0VHLElBQWxFLENBQWI7QUFDRCxLQUZELENBRUUsT0FBT2dDLEdBQVAsRUFBWTtBQUNaRCxNQUFBQSxjQUFjLEdBQUcsSUFBakI7QUFDQSxZQUFNQyxHQUFOO0FBQ0Q7QUFDRixHQVBELFNBT1U7QUFFUixRQUFJUCxVQUFVLElBQUlFLGlCQUFkLEtBQW9DLENBQUNELGNBQUQsSUFBbUJLLGNBQXZELENBQUosRUFBNEU7QUFDMUUsWUFBTTtBQUFDRixRQUFBQTtBQUFELFVBQWlCLE1BQU0sS0FBS0ksTUFBTCxFQUE3Qjs7QUFDQXpILHNCQUFJc0MsS0FBSixDQUFVK0UsWUFBWSxHQUFHLG1DQUFILEdBQXlDLDJDQUEvRDtBQUNEO0FBQ0Y7QUFDRixDQWpDRDs7QUFtQ0FqSSxpQkFBaUIsQ0FBQ3NJLGdCQUFsQixHQUFxQyxTQUFTQSxnQkFBVCxDQUEyQnpCLElBQUksR0FBRyxFQUFsQyxFQUFzQztBQUV6RUEsRUFBQUEsSUFBSSxHQUFHLEtBQUt6RCxVQUFMLENBQWdCQyxXQUFoQixDQUE0QmtGLE1BQTVCLENBQW1DMUIsSUFBbkMsQ0FBUDs7QUFDQWpHLGtCQUFJc0MsS0FBSixDQUFXLHNDQUFxQ0wsSUFBSSxDQUFDQyxTQUFMLENBQWUrRCxJQUFmLENBQXFCLEVBQXJFOztBQUNBLFNBQU8sSUFBSTJCLHdCQUFKLENBQWUsS0FBS0MsVUFBTCxFQUFmLEVBQWtDNUIsSUFBbEMsQ0FBUDtBQUNELENBTEQ7O0FBWUE3RyxpQkFBaUIsQ0FBQzBJLGdCQUFsQixHQUFxQyxTQUFTQSxnQkFBVCxHQUE2QjtBQUNoRSxTQUFPLEtBQUtwRCxPQUFaO0FBQ0QsQ0FGRDs7QUFVQXRGLGlCQUFpQixDQUFDMkksZUFBbEIsR0FBb0MsZUFBZUEsZUFBZixHQUFrQztBQUNwRS9ILGtCQUFJc0MsS0FBSixDQUFVLCtCQUFWOztBQUNBLE1BQUksS0FBSzBGLFlBQUwsS0FBc0IsSUFBMUIsRUFBZ0M7QUFDOUIsV0FBTyxLQUFLQSxZQUFaO0FBQ0Q7O0FBQ0QsTUFBSTtBQUNGLFFBQUkvRSxPQUFPLEdBQUcsTUFBTSxLQUFLWixtQkFBTCxFQUFwQjtBQUNBLFFBQUk0RixJQUFJLEdBQUcsS0FBS0MseUJBQUwsQ0FBK0JqRixPQUFPLENBQUMsQ0FBRCxDQUFQLENBQVdPLElBQTFDLENBQVg7O0FBQ0EsUUFBSXlFLElBQUosRUFBVTtBQUNSLGFBQU9BLElBQVA7QUFDRCxLQUZELE1BRU87QUFDTCxZQUFNLElBQUlqRyxLQUFKLENBQVcseUJBQVgsQ0FBTjtBQUNEO0FBQ0YsR0FSRCxDQVFFLE9BQU9JLENBQVAsRUFBVTtBQUNWLFVBQU0sSUFBSUosS0FBSixDQUFXLHlDQUF3Q0ksQ0FBQyxDQUFDTSxPQUFRLEVBQTdELENBQU47QUFDRDtBQUNGLENBaEJEOztBQXlCQXRELGlCQUFpQixDQUFDOEkseUJBQWxCLEdBQThDLFNBQVNBLHlCQUFULENBQW9DQyxLQUFwQyxFQUEyQztBQUN2RixNQUFJQyxXQUFXLEdBQUcsZ0JBQWxCOztBQUNBLE1BQUlBLFdBQVcsQ0FBQzVCLElBQVosQ0FBaUIyQixLQUFqQixDQUFKLEVBQTZCO0FBQzNCLFdBQU9FLFFBQVEsQ0FBQ0QsV0FBVyxDQUFDRSxJQUFaLENBQWlCSCxLQUFqQixFQUF3QixDQUF4QixDQUFELEVBQTZCLEVBQTdCLENBQWY7QUFDRDs7QUFDRCxTQUFPLEtBQVA7QUFDRCxDQU5EOztBQWFBL0ksaUJBQWlCLENBQUNtSixxQkFBbEIsR0FBMEMsZUFBZUEscUJBQWYsR0FBd0M7QUFDaEZ2SSxrQkFBSXNDLEtBQUosQ0FBVSw2QkFBVjs7QUFDQSxNQUFJO0FBQ0YsUUFBSVcsT0FBTyxHQUFHLE1BQU0sS0FBS1osbUJBQUwsRUFBcEI7QUFDQSxRQUFJbUcsU0FBUyxHQUFHLEVBQWhCOztBQUNBLFNBQUssSUFBSUMsTUFBVCxJQUFtQnhGLE9BQW5CLEVBQTRCO0FBQzFCLFVBQUlnRixJQUFJLEdBQUcsS0FBS0MseUJBQUwsQ0FBK0JPLE1BQU0sQ0FBQ2pGLElBQXRDLENBQVg7O0FBQ0EsVUFBSXlFLElBQUosRUFBVTtBQUNSUSxRQUFBQSxNQUFNLENBQUNSLElBQVAsR0FBY0EsSUFBZDtBQUNBTyxRQUFBQSxTQUFTLENBQUNoSCxJQUFWLENBQWVpSCxNQUFmO0FBQ0Q7QUFDRjs7QUFDRHpJLG9CQUFJc0MsS0FBSixDQUFXLEdBQUU0RCxvQkFBS3dDLFNBQUwsQ0FBZSxVQUFmLEVBQTJCRixTQUFTLENBQUNwRSxNQUFyQyxFQUE2QyxJQUE3QyxDQUFtRCxZQUFoRTs7QUFDQSxXQUFPb0UsU0FBUDtBQUNELEdBWkQsQ0FZRSxPQUFPcEcsQ0FBUCxFQUFVO0FBQ1YsVUFBTSxJQUFJSixLQUFKLENBQVcsNENBQTJDSSxDQUFDLENBQUNNLE9BQVEsRUFBaEUsQ0FBTjtBQUNEO0FBQ0YsQ0FqQkQ7O0FBd0JBdEQsaUJBQWlCLENBQUN1SixlQUFsQixHQUFvQyxTQUFTQSxlQUFULENBQTBCQyxNQUExQixFQUFrQztBQUNwRSxPQUFLWixZQUFMLEdBQW9CWSxNQUFwQjtBQUNELENBRkQ7O0FBU0F4SixpQkFBaUIsQ0FBQ3lKLFdBQWxCLEdBQWdDLFNBQVNBLFdBQVQsQ0FBc0JDLFFBQXRCLEVBQWdDO0FBQzlEOUksa0JBQUlzQyxLQUFKLENBQVcsd0JBQXVCd0csUUFBUyxFQUEzQzs7QUFDQSxPQUFLQyxXQUFMLEdBQW1CRCxRQUFuQjtBQUNBLE1BQUlFLGFBQWEsR0FBRyxLQUFLeEcsVUFBTCxDQUFnQkMsV0FBaEIsQ0FBNEJJLE9BQTVCLENBQW9DLElBQXBDLENBQXBCOztBQUNBLE1BQUltRyxhQUFhLEtBQUssQ0FBQyxDQUF2QixFQUEwQjtBQUV4QixTQUFLeEcsVUFBTCxDQUFnQkMsV0FBaEIsQ0FBNEJ3RyxNQUE1QixDQUFtQ0QsYUFBbkMsRUFBa0QsQ0FBbEQ7QUFDRDs7QUFDRCxPQUFLeEcsVUFBTCxDQUFnQkMsV0FBaEIsQ0FBNEJqQixJQUE1QixDQUFpQyxJQUFqQyxFQUF1Q3NILFFBQXZDO0FBQ0QsQ0FURDs7QUFnQkExSixpQkFBaUIsQ0FBQzhKLFNBQWxCLEdBQThCLFNBQVNBLFNBQVQsQ0FBb0JDLFNBQXBCLEVBQStCO0FBQzNELE1BQUlMLFFBQVEsR0FBR0ssU0FBUyxDQUFDM0YsSUFBekI7QUFDQSxNQUFJb0YsTUFBTSxHQUFHLEtBQUtWLHlCQUFMLENBQStCWSxRQUEvQixDQUFiO0FBQ0EsT0FBS0gsZUFBTCxDQUFxQkMsTUFBckI7QUFDQSxPQUFLQyxXQUFMLENBQWlCQyxRQUFqQjtBQUNELENBTEQ7O0FBYUExSixpQkFBaUIsQ0FBQ2dLLGFBQWxCLEdBQWtDLGVBQWVBLGFBQWYsQ0FBOEJDLE9BQTlCLEVBQXVDO0FBQ3ZFckosa0JBQUlzQyxLQUFKLENBQVcsbUJBQWtCK0csT0FBUSxZQUFyQzs7QUFDQSxNQUFJO0FBQ0YsVUFBTWIsU0FBUyxHQUFHLE1BQU0sS0FBS0QscUJBQUwsRUFBeEI7O0FBQ0EsU0FBSyxNQUFNZSxRQUFYLElBQXVCZCxTQUF2QixFQUFrQztBQUNoQyxXQUFLRyxlQUFMLENBQXFCVyxRQUFRLENBQUNyQixJQUE5QjtBQUNBLFlBQU1zQixjQUFjLEdBQUcsTUFBTSxLQUFLQyxpQkFBTCxDQUF1QixVQUF2QixDQUE3Qjs7QUFDQSxVQUFJcEosZ0JBQUVxSixPQUFGLENBQVVKLE9BQVYsTUFBdUJqSixnQkFBRXFKLE9BQUYsQ0FBVUYsY0FBVixDQUEzQixFQUFzRDtBQUNwRHZKLHdCQUFJc0MsS0FBSixDQUFXLG1CQUFrQitHLE9BQVEsYUFBWUMsUUFBUSxDQUFDckIsSUFBSyxFQUEvRDs7QUFDQSxhQUFLWSxXQUFMLENBQWlCUyxRQUFRLENBQUM5RixJQUExQjtBQUNBLGVBQU84RixRQUFQO0FBQ0Q7QUFDRjs7QUFDRHRKLG9CQUFJc0MsS0FBSixDQUFXLGFBQVkrRyxPQUFRLGVBQS9COztBQUNBLFdBQU8sSUFBUDtBQUNELEdBYkQsQ0FhRSxPQUFPakgsQ0FBUCxFQUFVO0FBQ1YsVUFBTSxJQUFJSixLQUFKLENBQVcsc0NBQXFDSSxDQUFDLENBQUNNLE9BQVEsRUFBMUQsQ0FBTjtBQUNEO0FBQ0YsQ0FsQkQ7O0FBOEJBdEQsaUJBQWlCLENBQUNzSyxzQkFBbEIsR0FBMkMsZUFBZUEsc0JBQWYsQ0FBdUNMLE9BQXZDLEVBQWdEMUYsU0FBUyxHQUFHLEtBQTVELEVBQW1FO0FBQzVHLE1BQUlnRyxVQUFKOztBQUNBLE1BQUk7QUFDRixVQUFNLGdDQUFpQixZQUFZO0FBQ2pDLFVBQUk7QUFDRkEsUUFBQUEsVUFBVSxHQUFHLE1BQU0sS0FBS1AsYUFBTCxDQUFtQkMsT0FBTyxDQUFDakQsT0FBUixDQUFnQixHQUFoQixFQUFxQixFQUFyQixDQUFuQixDQUFuQjtBQUNBLGVBQU91RCxVQUFQO0FBQ0QsT0FIRCxDQUdFLE9BQU92SCxDQUFQLEVBQVU7QUFDVnBDLHdCQUFJc0MsS0FBSixDQUFVRixDQUFDLENBQUNNLE9BQVo7O0FBQ0EsZUFBTyxLQUFQO0FBQ0Q7QUFDRixLQVJLLEVBUUg7QUFDRGtFLE1BQUFBLE1BQU0sRUFBRWpELFNBRFA7QUFFRG9ELE1BQUFBLFVBQVUsRUFBRTtBQUZYLEtBUkcsQ0FBTjtBQVlELEdBYkQsQ0FhRSxPQUFPM0UsQ0FBUCxFQUFVO0FBQ1YsVUFBTSxJQUFJSixLQUFKLENBQVcsaURBQWdESSxDQUFDLENBQUNNLE9BQVEsRUFBckUsQ0FBTjtBQUNEOztBQUNELFNBQU9pSCxVQUFQO0FBQ0QsQ0FuQkQ7O0FBMEJBdkssaUJBQWlCLENBQUN3SyxnQkFBbEIsR0FBcUMsZUFBZUEsZ0JBQWYsR0FBbUM7QUFDdEUsTUFBSXZFLEdBQUosRUFBU1ksSUFBVDs7QUFDQSxNQUFJM0Ysc0JBQU9DLFNBQVAsRUFBSixFQUF3QjtBQUN0QjhFLElBQUFBLEdBQUcsR0FBRyxVQUFOO0FBQ0FZLElBQUFBLElBQUksR0FBRyxDQUFDLFVBQUQsRUFBYSxLQUFiLEVBQW9CLGNBQXBCLENBQVA7QUFDRCxHQUhELE1BR087QUFDTFosSUFBQUEsR0FBRyxHQUFHLGtCQUFOO0FBQ0FZLElBQUFBLElBQUksR0FBRyxDQUFDLElBQUQsRUFBTyxXQUFQLENBQVA7QUFDRDs7QUFDRCxNQUFJO0FBQ0YsVUFBTSx3QkFBS1osR0FBTCxFQUFVWSxJQUFWLENBQU47QUFDRCxHQUZELENBRUUsT0FBTzdELENBQVAsRUFBVTtBQUNWLFVBQU0sSUFBSUosS0FBSixDQUFXLDRDQUEyQ0ksQ0FBQyxDQUFDTSxPQUFRLEVBQWhFLENBQU47QUFDRDtBQUNGLENBZEQ7O0FBMkJBdEQsaUJBQWlCLENBQUN5SyxZQUFsQixHQUFpQyxlQUFlQSxZQUFmLENBQTZCUixPQUFPLEdBQUcsSUFBdkMsRUFBNkMzRCxPQUFPLEdBQUcsS0FBdkQsRUFBOEQ7QUFDN0YsTUFBSVEsb0JBQUs0RCxRQUFMLENBQWNULE9BQWQsQ0FBSixFQUE0QjtBQUMxQnJKLG9CQUFJc0MsS0FBSixDQUFXLGdCQUFlK0csT0FBUSxHQUFsQzs7QUFDQSxVQUFNWixNQUFNLEdBQUcsTUFBTSxLQUFLVyxhQUFMLENBQW1CQyxPQUFuQixDQUFyQjs7QUFDQSxRQUFJLENBQUNaLE1BQUwsRUFBYTtBQUNYekksc0JBQUl1QixJQUFKLENBQVUscUJBQW9COEgsT0FBUSxnQ0FBdEM7O0FBQ0EsYUFBTyxLQUFQO0FBQ0Q7QUFDRixHQVBELE1BT087QUFFTHJKLG9CQUFJc0MsS0FBSixDQUFXLHdCQUF1QixLQUFLeUcsV0FBWSxHQUFuRDs7QUFDQSxRQUFJLEVBQUMsTUFBTSxLQUFLZ0IsbUJBQUwsRUFBUCxDQUFKLEVBQXVDO0FBQ3JDL0osc0JBQUlzQyxLQUFKLENBQVcscUJBQW9CLEtBQUt5RyxXQUFZLHFDQUFoRDs7QUFDQSxhQUFPLEtBQVA7QUFDRDtBQUNGOztBQUNELFFBQU0sS0FBS3BFLE9BQUwsQ0FBYSxDQUFDLEtBQUQsRUFBUSxNQUFSLENBQWIsQ0FBTjs7QUFDQTNFLGtCQUFJc0MsS0FBSixDQUFXLGlCQUFnQm9ELE9BQVEsMEJBQXlCMkQsT0FBTyxHQUFHQSxPQUFILEdBQWEsS0FBS04sV0FBWSxhQUFqRzs7QUFDQSxNQUFJO0FBQ0YsVUFBTSxnQ0FBaUIsWUFBWTtBQUNqQyxVQUFJO0FBQ0YsZUFBTzdDLG9CQUFLNEQsUUFBTCxDQUFjVCxPQUFkLElBQ0gsRUFBQyxNQUFNLEtBQUtELGFBQUwsQ0FBbUJDLE9BQW5CLENBQVAsQ0FERyxHQUVILEVBQUMsTUFBTSxLQUFLVSxtQkFBTCxFQUFQLENBRko7QUFHRCxPQUpELENBSUUsT0FBTzFGLEdBQVAsRUFBWSxDQUFFOztBQUNoQixhQUFPLEtBQVA7QUFDRCxLQVBLLEVBT0g7QUFDRHVDLE1BQUFBLE1BQU0sRUFBRWxCLE9BRFA7QUFFRHFCLE1BQUFBLFVBQVUsRUFBRTtBQUZYLEtBUEcsQ0FBTjtBQVdELEdBWkQsQ0FZRSxPQUFPM0UsQ0FBUCxFQUFVO0FBQ1YsVUFBTSxJQUFJSixLQUFKLENBQVcsaUJBQWdCcUgsT0FBTyxHQUFHQSxPQUFILEdBQWEsS0FBS04sV0FBWSx5Q0FBd0NyRCxPQUFRLFFBQWhILENBQU47QUFDRDs7QUFDRDFGLGtCQUFJdUIsSUFBSixDQUFVLDRCQUEyQjhILE9BQU8sR0FBR0EsT0FBSCxHQUFhLEtBQUtOLFdBQVksWUFBMUU7O0FBQ0EsU0FBTyxJQUFQO0FBQ0QsQ0FuQ0Q7O0FBZ0RBM0osaUJBQWlCLENBQUM0SyxTQUFsQixHQUE4QixlQUFlQSxTQUFmLENBQTBCWCxPQUExQixFQUFtQ1ksT0FBbkMsRUFBNENDLFFBQTVDLEVBQXNEQyxPQUF0RCxFQUM1QkMsZ0JBQWdCLEdBQUcsS0FEUyxFQUNGQyxlQUFlLEdBQUcsS0FEaEIsRUFDdUJDLFVBQVUsR0FBRyxDQURwQyxFQUN1QztBQUNuRXRLLGtCQUFJc0MsS0FBSixDQUFXLCtCQUE4QitHLE9BQVEsa0JBQXZDLEdBQ0MsR0FBRWUsZ0JBQWlCLHVCQUFzQkMsZUFBZ0IsSUFEcEU7O0FBRUEsTUFBSUUsa0JBQWtCLEdBQUcsTUFBTSxLQUFLM0ssZ0JBQUwsQ0FBc0IsVUFBdEIsQ0FBL0I7O0FBQ0EsTUFBSXlKLE9BQU8sQ0FBQyxDQUFELENBQVAsS0FBZSxHQUFuQixFQUF3QjtBQUN0QkEsSUFBQUEsT0FBTyxHQUFHQSxPQUFPLENBQUNtQixNQUFSLENBQWUsQ0FBZixDQUFWO0FBQ0Q7O0FBQ0QsUUFBTSxLQUFLQyxhQUFMLENBQW1CcEIsT0FBbkIsQ0FBTjtBQUNBLE1BQUlxQixVQUFVLEdBQUcsQ0FBQyxNQUFELEVBQVNyQixPQUFULENBQWpCOztBQUNBLE1BQUlqSixnQkFBRXVLLFFBQUYsQ0FBV1QsUUFBWCxDQUFKLEVBQTBCO0FBQ3hCbEssb0JBQUlzQyxLQUFKLENBQVcsc0NBQXFDNEgsUUFBUyxFQUF6RDs7QUFDQVEsSUFBQUEsVUFBVSxDQUFDbEosSUFBWCxDQUFnQixPQUFoQixFQUEwQix3QkFBdUIwSSxRQUFRLENBQUNVLFdBQVQsRUFBdUIsRUFBeEU7QUFDRDs7QUFDRCxNQUFJeEssZ0JBQUV1SyxRQUFGLENBQVdSLE9BQVgsQ0FBSixFQUF5QjtBQUN2Qm5LLG9CQUFJc0MsS0FBSixDQUFXLHFDQUFvQzZILE9BQVEsRUFBdkQ7O0FBQ0FPLElBQUFBLFVBQVUsQ0FBQ2xKLElBQVgsQ0FBZ0IsT0FBaEIsRUFBMEIsdUJBQXNCMkksT0FBTyxDQUFDVSxXQUFSLEVBQXNCLEVBQXRFO0FBQ0Q7O0FBQ0QsTUFBSUMsTUFBSjs7QUFDQSxNQUFJMUssZ0JBQUV1SyxRQUFGLENBQVdULFFBQVgsS0FBd0I5SixnQkFBRXVLLFFBQUYsQ0FBV1IsT0FBWCxDQUE1QixFQUFpRDtBQUMvQ1csSUFBQUEsTUFBTSxHQUFHWixRQUFRLENBQUNVLFdBQVQsS0FBeUIsR0FBekIsR0FBK0JULE9BQU8sQ0FBQ1UsV0FBUixFQUF4QztBQUNELEdBRkQsTUFFTyxJQUFJekssZ0JBQUV1SyxRQUFGLENBQVdULFFBQVgsQ0FBSixFQUEwQjtBQUMvQlksSUFBQUEsTUFBTSxHQUFHWixRQUFRLENBQUNVLFdBQVQsRUFBVDtBQUNELEdBRk0sTUFFQSxJQUFJeEssZ0JBQUV1SyxRQUFGLENBQVdSLE9BQVgsQ0FBSixFQUF5QjtBQUM5QlcsSUFBQUEsTUFBTSxHQUFHWCxPQUFUO0FBQ0Q7O0FBQ0QsTUFBSS9KLGdCQUFFdUssUUFBRixDQUFXRyxNQUFYLENBQUosRUFBd0I7QUFDdEI5SyxvQkFBSXNDLEtBQUosQ0FBVyxvQ0FBbUN3SSxNQUFPLEVBQXJEOztBQUNBSixJQUFBQSxVQUFVLENBQUNsSixJQUFYLENBQWdCLE9BQWhCLEVBQTBCLHNCQUFxQnNKLE1BQU8sRUFBdEQ7QUFDRDs7QUFDRCxNQUFJLENBQUMxSyxnQkFBRWtCLE9BQUYsQ0FBVTJJLE9BQVYsQ0FBTCxFQUF5QjtBQUN2QlMsSUFBQUEsVUFBVSxDQUFDbEosSUFBWCxDQUFnQixJQUFJcEIsZ0JBQUUwRixPQUFGLENBQVVtRSxPQUFWLElBQXFCQSxPQUFyQixHQUErQkEsT0FBTyxDQUFDL0csS0FBUixDQUFjLEdBQWQsQ0FBbkMsQ0FBaEI7QUFDRDs7QUFDRGxELGtCQUFJc0MsS0FBSixDQUFXLFlBQVdpSSxrQkFBbUIsZ0JBQWV0SSxJQUFJLENBQUNDLFNBQUwsQ0FBZXdJLFVBQWYsQ0FBMkIsRUFBbkY7O0FBQ0EsTUFBSUssSUFBSSxHQUFHLElBQUluRCx3QkFBSixDQUFlMkMsa0JBQWYsRUFBbUNHLFVBQW5DLENBQVg7QUFDQSxRQUFNSyxJQUFJLENBQUNoSCxLQUFMLENBQVcsQ0FBWCxDQUFOO0FBQ0FnSCxFQUFBQSxJQUFJLENBQUNDLEVBQUwsQ0FBUSxRQUFSLEVBQWtCLENBQUN6SSxNQUFELEVBQVMrRCxNQUFULEtBQW9CO0FBQ3BDLFNBQUssSUFBSWxELElBQVQsSUFBaUIsQ0FBQ2IsTUFBTSxJQUFJK0QsTUFBVixJQUFvQixFQUFyQixFQUF5QnBELEtBQXpCLENBQStCLElBQS9CLEVBQXFDOUIsTUFBckMsQ0FBNEM2SixPQUE1QyxDQUFqQixFQUF1RTtBQUNyRWpMLHNCQUFJdUIsSUFBSixDQUFVLGdCQUFlNkIsSUFBSyxFQUE5QjtBQUNEO0FBQ0YsR0FKRDtBQUtBMkgsRUFBQUEsSUFBSSxDQUFDQyxFQUFMLENBQVEsS0FBUixFQUFlLENBQUNyRSxJQUFELEVBQU91RSxNQUFQLEtBQWtCO0FBQy9CbEwsb0JBQUlDLElBQUosQ0FBVSxnQkFBZW9KLE9BQVEscUJBQW9CMUMsSUFBSyxHQUFFdUUsTUFBTSxHQUFJLFlBQVdBLE1BQU8sRUFBdEIsR0FBMEIsRUFBRyxFQUEvRjtBQUNELEdBRkQ7QUFHQSxRQUFNLHFCQUFNWixVQUFOLEVBQWtCLFlBQVksTUFBTSxLQUFLWixzQkFBTCxDQUE0QkwsT0FBNUIsRUFBcUNlLGdCQUFyQyxDQUFwQyxDQUFOO0FBQ0EsUUFBTSxLQUFLZSxvQkFBTCxDQUEwQmQsZUFBMUIsQ0FBTjtBQUNBLFNBQU9VLElBQVA7QUFDRCxDQS9DRDs7QUFnRUEzTCxpQkFBaUIsQ0FBQ2dNLGFBQWxCLEdBQWtDaEwsZ0JBQUVDLE9BQUYsQ0FBVSxlQUFlK0ssYUFBZixHQUFnQztBQUMxRSxNQUFJO0FBQ0YsUUFBSUMsVUFBVSxHQUFHLENBQUMsTUFBTSxLQUFLMUcsT0FBTCxDQUFhLFNBQWIsQ0FBUCxFQUNkeUIsT0FEYyxDQUNOLG1EQURNLEVBQytDLElBRC9DLENBQWpCO0FBRUEsUUFBSWtGLEtBQUssR0FBR0QsVUFBVSxDQUFDbkksS0FBWCxDQUFpQixHQUFqQixDQUFaO0FBQ0EsV0FBTztBQUNMcUksTUFBQUEsYUFBYSxFQUFFRixVQURWO0FBRUxHLE1BQUFBLFlBQVksRUFBRUMsVUFBVSxDQUFDSixVQUFELENBRm5CO0FBR0xLLE1BQUFBLEtBQUssRUFBRXJELFFBQVEsQ0FBQ2lELEtBQUssQ0FBQyxDQUFELENBQU4sRUFBVyxFQUFYLENBSFY7QUFJTEssTUFBQUEsS0FBSyxFQUFFdEQsUUFBUSxDQUFDaUQsS0FBSyxDQUFDLENBQUQsQ0FBTixFQUFXLEVBQVgsQ0FKVjtBQUtMTSxNQUFBQSxLQUFLLEVBQUVOLEtBQUssQ0FBQyxDQUFELENBQUwsR0FBV2pELFFBQVEsQ0FBQ2lELEtBQUssQ0FBQyxDQUFELENBQU4sRUFBVyxFQUFYLENBQW5CLEdBQW9DTztBQUx0QyxLQUFQO0FBT0QsR0FYRCxDQVdFLE9BQU96SixDQUFQLEVBQVU7QUFDVixVQUFNLElBQUlKLEtBQUosQ0FBVywrQ0FBOENJLENBQUMsQ0FBQ00sT0FBUSxLQUF6RCxHQUNLLFlBQVcsQ0FBQ04sQ0FBQyxDQUFDa0UsTUFBRixJQUFZLEVBQWIsRUFBaUJuRCxJQUFqQixFQUF3QixhQUFZZixDQUFDLENBQUN1RSxJQUFLLEdBRHJFLENBQU47QUFFRDtBQUNGLENBaEJpQyxDQUFsQzs7QUF3QkF2SCxpQkFBaUIsQ0FBQ3FMLGFBQWxCLEdBQWtDLGVBQWVBLGFBQWYsQ0FBOEJwQixPQUE5QixFQUF1QztBQUN2RSxNQUFJaEUsR0FBSixFQUFTeUcsTUFBVDs7QUFDQSxNQUFJO0FBQ0Z6RyxJQUFBQSxHQUFHLEdBQUcsTUFBTSxLQUFLekYsZ0JBQUwsQ0FBc0IsVUFBdEIsQ0FBWjtBQUNBa00sSUFBQUEsTUFBTSxHQUFHLE1BQU0sd0JBQUt6RyxHQUFMLEVBQVUsQ0FBQyxZQUFELENBQVYsQ0FBZjtBQUNELEdBSEQsQ0FHRSxPQUFPakQsQ0FBUCxFQUFVO0FBQ1YsUUFBSTJKLGtCQUFrQixHQUFHLElBQUl2TSxNQUFKLENBQVcsNEJBQVgsRUFBeUMsR0FBekMsRUFBOENnSCxJQUE5QyxDQUFtRHBFLENBQUMsQ0FBQ2tFLE1BQXJELENBQXpCOztBQUNBLFFBQUksQ0FBQ3lGLGtCQUFMLEVBQXlCO0FBQ3ZCLFlBQU0sSUFBSS9KLEtBQUosQ0FBVyxtREFBa0RJLENBQUMsQ0FBQ00sT0FBUSxLQUE3RCxHQUNDLFlBQVcsQ0FBQ04sQ0FBQyxDQUFDa0UsTUFBRixJQUFZLEVBQWIsRUFBaUJuRCxJQUFqQixFQUF3QixhQUFZZixDQUFDLENBQUN1RSxJQUFLLEdBRGpFLENBQU47QUFHRDs7QUFDRCxVQUFNcUYsVUFBVSxHQUFHLE1BQU0sa0NBQXpCO0FBQ0EsUUFBSW5NLFVBQVUsR0FBRyxTQUFqQjs7QUFDQSxRQUFJbU0sVUFBSixFQUFnQjtBQUNkLFVBQUlBLFVBQVUsQ0FBQ04sS0FBWCxJQUFvQixFQUF4QixFQUE0QjtBQUMxQjdMLFFBQUFBLFVBQVUsR0FBRyxZQUFiO0FBQ0Q7QUFDRixLQUpELE1BSU87QUFDTEcsc0JBQUlDLElBQUosQ0FBVSw4QkFBNkJKLFVBQVcseUNBQWxEO0FBQ0Q7O0FBRUR3RixJQUFBQSxHQUFHLEdBQUcsTUFBTSxLQUFLekYsZ0JBQUwsQ0FBc0JDLFVBQXRCLENBQVo7QUFDQWlNLElBQUFBLE1BQU0sR0FBRyxNQUFNLHdCQUFLekcsR0FBTCxFQUFVLENBQUMsTUFBRCxFQUFTLEtBQVQsRUFBZ0IsSUFBaEIsQ0FBVixDQUFmO0FBQ0Q7O0FBQ0QsTUFBSXlHLE1BQU0sQ0FBQ3ZKLE1BQVAsQ0FBY00sT0FBZCxDQUFzQndHLE9BQXRCLE1BQW1DLENBQUMsQ0FBeEMsRUFBMkM7QUFDekMsUUFBSTRDLFNBQVMsR0FBSSxJQUFHSCxNQUFNLENBQUN2SixNQUFQLENBQWNZLElBQWQsR0FBcUJpRCxPQUFyQixDQUE2QixPQUE3QixFQUFzQyxNQUF0QyxDQUE4QyxHQUFsRTtBQUNBLFVBQU0sSUFBSXBFLEtBQUosQ0FBVyxRQUFPcUgsT0FBUSx1RUFBc0U0QyxTQUFVLEdBQTFHLENBQU47QUFDRDtBQUNGLENBN0JEOztBQXFDQTdNLGlCQUFpQixDQUFDK0wsb0JBQWxCLEdBQXlDLGVBQWVBLG9CQUFmLENBQXFDeEgsU0FBUyxHQUFHLEtBQWpELEVBQXdEO0FBQy9GLE1BQUk7QUFDRixVQUFNLGdDQUFpQixZQUFZO0FBQ2pDLFVBQUk7QUFDRixZQUFJLENBQUMsQ0FBQyxNQUFNLEtBQUtxRCxLQUFMLENBQVcsQ0FBQyxTQUFELEVBQVksbUJBQVosQ0FBWCxDQUFQLEVBQXFEeEcsUUFBckQsQ0FBOEQsU0FBOUQsQ0FBTCxFQUErRTtBQUM3RSxpQkFBTyxLQUFQO0FBQ0Q7O0FBSUQsZUFBTyxhQUFhZ0csSUFBYixDQUFrQixNQUFNLEtBQUtRLEtBQUwsQ0FBVyxDQUFDLElBQUQsRUFBTyxzQkFBUCxDQUFYLENBQXhCLENBQVA7QUFDRCxPQVJELENBUUUsT0FBT1EsR0FBUCxFQUFZO0FBQ1p4SCx3QkFBSXNDLEtBQUosQ0FBVyxxREFBb0RrRixHQUFHLENBQUM5RSxPQUFRLEVBQTNFOztBQUNBLGVBQU8sS0FBUDtBQUNEO0FBQ0YsS0FiSyxFQWFIO0FBQ0RrRSxNQUFBQSxNQUFNLEVBQUVqRCxTQURQO0FBRURvRCxNQUFBQSxVQUFVLEVBQUU7QUFGWCxLQWJHLENBQU47QUFpQkQsR0FsQkQsQ0FrQkUsT0FBTzNFLENBQVAsRUFBVTtBQUNWLFVBQU0sSUFBSUosS0FBSixDQUFXLGdDQUErQjJCLFNBQVUsSUFBcEQsQ0FBTjtBQUNEO0FBQ0YsQ0F0QkQ7O0FBOEJBdkUsaUJBQWlCLENBQUM4TSxhQUFsQixHQUFrQyxlQUFlQSxhQUFmLENBQThCQyxxQkFBcUIsR0FBRyxFQUF0RCxFQUEwRDtBQUMxRixPQUFLQSxxQkFBTCxHQUE2QkEscUJBQTdCO0FBQ0EsUUFBTUMsT0FBTyxHQUFHLENBQWhCO0FBQ0EsUUFBTTFHLE9BQU8sR0FBRzJDLFFBQVEsQ0FBQyxLQUFLOEQscUJBQU4sRUFBNkIsRUFBN0IsQ0FBUixHQUEyQ0MsT0FBM0MsR0FBcUQsSUFBckU7QUFDQSxRQUFNLHFCQUFNQSxPQUFOLEVBQWUsWUFBWTtBQUMvQixRQUFJO0FBQ0YsWUFBTSxLQUFLekgsT0FBTCxDQUFhLGlCQUFiLEVBQWdDO0FBQUNlLFFBQUFBO0FBQUQsT0FBaEMsQ0FBTjtBQUNBLFlBQU0sS0FBSzJHLElBQUwsRUFBTjtBQUNELEtBSEQsQ0FHRSxPQUFPakssQ0FBUCxFQUFVO0FBQ1YsWUFBTSxLQUFLa0MsVUFBTCxFQUFOO0FBQ0EsWUFBTSxLQUFLakMsbUJBQUwsRUFBTjtBQUNBLFlBQU0sSUFBSUwsS0FBSixDQUFXLGtFQUFpRUksQ0FBQyxDQUFDTSxPQUFRLEdBQXRGLENBQU47QUFDRDtBQUNGLEdBVEssQ0FBTjtBQVVELENBZEQ7O0FBc0JBdEQsaUJBQWlCLENBQUNrTixNQUFsQixHQUEyQixlQUFlQSxNQUFmLENBQXVCRixPQUFPLEdBQUcvTSwwQkFBakMsRUFBNkQ7QUFFdEYsUUFBTTtBQUFFK0gsSUFBQUE7QUFBRixNQUF1QixNQUFNLEtBQUtFLElBQUwsRUFBbkM7O0FBQ0EsTUFBSTtBQUVGLFVBQU0sS0FBS04sS0FBTCxDQUFXLENBQUMsTUFBRCxDQUFYLENBQU47QUFDQSxVQUFNdUYsa0JBQUVDLEtBQUYsQ0FBUSxJQUFSLENBQU47QUFDQSxVQUFNLEtBQUtDLGlCQUFMLENBQXVCLG9CQUF2QixFQUE2QyxDQUE3QyxFQUFnRDtBQUNwRHhGLE1BQUFBLFVBQVUsRUFBRTtBQUR3QyxLQUFoRCxDQUFOO0FBR0EsVUFBTSxLQUFLRCxLQUFMLENBQVcsQ0FBQyxPQUFELENBQVgsQ0FBTjtBQUNELEdBUkQsQ0FRRSxPQUFPNUUsQ0FBUCxFQUFVO0FBQ1YsVUFBTTtBQUFDTSxNQUFBQTtBQUFELFFBQVlOLENBQWxCOztBQUdBLFFBQUlNLE9BQU8sQ0FBQ2xDLFFBQVIsQ0FBaUIsY0FBakIsQ0FBSixFQUFzQztBQUNwQyxZQUFNLElBQUl3QixLQUFKLENBQVcsOERBQUQsR0FDYiw0REFBMkRVLE9BQVEsR0FEaEUsQ0FBTjtBQUVEOztBQUNELFVBQU1OLENBQU47QUFDRCxHQWpCRCxTQWlCVTtBQUVSLFFBQUksQ0FBQ2dGLGdCQUFMLEVBQXVCO0FBQ3JCLFlBQU0sS0FBS0ssTUFBTCxFQUFOO0FBQ0Q7QUFDRjs7QUFDRCxRQUFNN0QsS0FBSyxHQUFHLElBQUlDLHNCQUFPQyxLQUFYLEdBQW1CQyxLQUFuQixFQUFkO0FBQ0EsUUFBTSw2QkFBY3FJLE9BQWQsRUFBdUIsSUFBdkIsRUFBNkIsWUFBWTtBQUM3QyxRQUFJLENBQUMsTUFBTSxLQUFLTSxpQkFBTCxDQUF1QixvQkFBdkIsQ0FBUCxNQUF5RCxHQUE3RCxFQUFrRTtBQUNoRTtBQUNEOztBQUVELFVBQU1DLEdBQUcsR0FBSSxpQ0FBZ0MvSSxLQUFLLENBQUNLLFdBQU4sR0FBb0JDLGNBQXBCLENBQW1DQyxPQUFuQyxDQUEyQyxDQUEzQyxDQUE4QyxJQUEzRjs7QUFDQW5FLG9CQUFJc0MsS0FBSixDQUFVcUssR0FBVjs7QUFDQSxVQUFNLElBQUkzSyxLQUFKLENBQVUySyxHQUFWLENBQU47QUFDRCxHQVJLLENBQU47QUFTRCxDQXBDRDs7QUFpREF2TixpQkFBaUIsQ0FBQ3dOLG9CQUFsQixHQUF5QyxlQUFlQSxvQkFBZixDQUFxQ0MsVUFBckMsRUFBaUQ7QUFDeEYsUUFBTXhILEdBQUcsR0FBR3dILFVBQVUsR0FBRyxNQUFILEdBQVksUUFBbEM7QUFHQSxRQUFNQyxNQUFNLEdBQUcsTUFBTSxLQUFLQSxNQUFMLEVBQXJCOztBQUNBLE1BQUtBLE1BQU0sSUFBSUQsVUFBWCxJQUEyQixDQUFDQyxNQUFELElBQVcsQ0FBQ0QsVUFBM0MsRUFBd0Q7QUFDdEQsV0FBTztBQUFDeEYsTUFBQUEsWUFBWSxFQUFFLElBQWY7QUFBcUJELE1BQUFBLGdCQUFnQixFQUFFMEY7QUFBdkMsS0FBUDtBQUNEOztBQUVELE1BQUkxRixnQkFBZ0IsR0FBRzBGLE1BQXZCOztBQUNBLE1BQUk7QUFDRixRQUFJO0FBQUN2SyxNQUFBQTtBQUFELFFBQVcsTUFBTSxLQUFLb0MsT0FBTCxDQUFhLENBQUNVLEdBQUQsQ0FBYixDQUFyQjs7QUFHQSxRQUFJOUMsTUFBSixFQUFZO0FBQ1YsVUFBSUEsTUFBTSxDQUFDL0IsUUFBUCxDQUFnQix5QkFBaEIsQ0FBSixFQUFnRDtBQUM5QyxlQUFPO0FBQUM2RyxVQUFBQSxZQUFZLEVBQUUsS0FBZjtBQUFzQkQsVUFBQUE7QUFBdEIsU0FBUDtBQUNEOztBQUVELFVBQUk3RSxNQUFNLENBQUMvQixRQUFQLENBQWdCLHlCQUFoQixDQUFKLEVBQWdEO0FBQzlDNEcsUUFBQUEsZ0JBQWdCLEdBQUcsSUFBbkI7QUFDRDtBQUNGOztBQUNELFdBQU87QUFBQ0MsTUFBQUEsWUFBWSxFQUFFLElBQWY7QUFBcUJELE1BQUFBO0FBQXJCLEtBQVA7QUFDRCxHQWRELENBY0UsT0FBT0ksR0FBUCxFQUFZO0FBQ1osVUFBTTtBQUFDbEIsTUFBQUEsTUFBTSxHQUFHLEVBQVY7QUFBYzVELE1BQUFBO0FBQWQsUUFBeUI4RSxHQUEvQjs7QUFDQXhILG9CQUFJQyxJQUFKLENBQVUsYUFBWW9GLEdBQUksaUNBQWdDM0MsT0FBUSxlQUFjNEQsTUFBTyxnQkFBdkY7O0FBSUEsUUFBSSxDQUFDLFFBQUQsRUFBVyxnQkFBWCxFQUE2QixpQkFBN0IsRUFBZ0RqRCxJQUFoRCxDQUFzRHJDLENBQUQsSUFBT3NGLE1BQU0sQ0FBQ3NFLFdBQVAsR0FBcUJwSyxRQUFyQixDQUE4QlEsQ0FBOUIsQ0FBNUQsQ0FBSixFQUFtRztBQUNqR2hCLHNCQUFJQyxJQUFKLENBQVUsbUJBQWtCb0YsR0FBSSxnREFBaEM7O0FBQ0EsWUFBTSxLQUFLZixVQUFMLEVBQU47QUFDRDs7QUFFRCxXQUFPO0FBQUMrQyxNQUFBQSxZQUFZLEVBQUUsS0FBZjtBQUFzQkQsTUFBQUE7QUFBdEIsS0FBUDtBQUNEO0FBQ0YsQ0FyQ0Q7O0FBMkNBaEksaUJBQWlCLENBQUNrSSxJQUFsQixHQUF5QixlQUFlQSxJQUFmLEdBQXVCO0FBQzlDLFNBQU8sTUFBTSxLQUFLc0Ysb0JBQUwsQ0FBMEIsSUFBMUIsQ0FBYjtBQUNELENBRkQ7O0FBU0F4TixpQkFBaUIsQ0FBQ3FJLE1BQWxCLEdBQTJCLGVBQWVBLE1BQWYsR0FBeUI7QUFDbEQsU0FBTyxNQUFNLEtBQUttRixvQkFBTCxDQUEwQixLQUExQixDQUFiO0FBQ0QsQ0FGRDs7QUFXQXhOLGlCQUFpQixDQUFDME4sTUFBbEIsR0FBMkIsZUFBZUEsTUFBZixHQUF5QjtBQUNsRCxTQUFPLENBQUMsTUFBTSxLQUFLOUYsS0FBTCxDQUFXLENBQUMsUUFBRCxDQUFYLENBQVAsRUFBK0I3RCxJQUEvQixPQUEwQyxNQUFqRDtBQUNELENBRkQ7O0FBVUEvRCxpQkFBaUIsQ0FBQzJOLFVBQWxCLEdBQStCLGVBQWVBLFVBQWYsQ0FBMkJDLFVBQTNCLEVBQXVDO0FBQ3BFLFFBQU1DLFFBQVEsR0FBRyxVQUFqQjtBQUNBLFFBQU1DLFFBQVEsR0FBSSxTQUFRRixVQUFVLENBQUM1RyxPQUFYLENBQW1CLElBQW5CLEVBQTBCLEtBQTFCLENBQWdDLGVBQWM2RyxRQUFTLEVBQWpGOztBQUNBLE1BQUk7QUFDRixXQUFPN00sZ0JBQUVJLFFBQUYsQ0FBVyxNQUFNLEtBQUt3RyxLQUFMLENBQVcsQ0FBQ2tHLFFBQUQsQ0FBWCxDQUFqQixFQUF5Q0QsUUFBekMsQ0FBUDtBQUNELEdBRkQsQ0FFRSxPQUFPNUksR0FBUCxFQUFZO0FBQ1osV0FBTyxLQUFQO0FBQ0Q7QUFDRixDQVJEOztBQW1CQWpGLGlCQUFpQixDQUFDK04sRUFBbEIsR0FBdUIsZUFBZUEsRUFBZixDQUFtQkgsVUFBbkIsRUFBK0J4SCxJQUFJLEdBQUcsRUFBdEMsRUFBMEM7QUFDL0QsTUFBSTtBQUNGLFFBQUlTLElBQUksR0FBRyxDQUFDLElBQUQsRUFBTyxHQUFHVCxJQUFWLEVBQWdCd0gsVUFBaEIsQ0FBWDtBQUNBLFFBQUl6SyxNQUFNLEdBQUcsTUFBTSxLQUFLeUUsS0FBTCxDQUFXZixJQUFYLENBQW5CO0FBQ0EsUUFBSW1ILEtBQUssR0FBRzdLLE1BQU0sQ0FBQ1csS0FBUCxDQUFhLElBQWIsQ0FBWjtBQUNBLFdBQU9rSyxLQUFLLENBQUNyTSxHQUFOLENBQVdzTSxDQUFELElBQU9BLENBQUMsQ0FBQ2xLLElBQUYsRUFBakIsRUFDSi9CLE1BREksQ0FDRzZKLE9BREgsRUFFSjdKLE1BRkksQ0FFSWlNLENBQUQsSUFBT0EsQ0FBQyxDQUFDeEssT0FBRixDQUFVLGNBQVYsTUFBOEIsQ0FBQyxDQUZ6QyxDQUFQO0FBR0QsR0FQRCxDQU9FLE9BQU8yRSxHQUFQLEVBQVk7QUFDWixRQUFJQSxHQUFHLENBQUM5RSxPQUFKLENBQVlHLE9BQVosQ0FBb0IsMkJBQXBCLE1BQXFELENBQUMsQ0FBMUQsRUFBNkQ7QUFDM0QsWUFBTTJFLEdBQU47QUFDRDs7QUFDRCxXQUFPLEVBQVA7QUFDRDtBQUNGLENBZEQ7O0FBdUJBcEksaUJBQWlCLENBQUNrTyxRQUFsQixHQUE2QixlQUFlQSxRQUFmLENBQXlCTixVQUF6QixFQUFxQztBQUNoRSxNQUFJO0FBQ0YsVUFBTU8sS0FBSyxHQUFHLE1BQU0sS0FBS0osRUFBTCxDQUFRSCxVQUFSLEVBQW9CLENBQUMsS0FBRCxDQUFwQixDQUFwQjs7QUFDQSxRQUFJTyxLQUFLLENBQUNuSixNQUFOLEtBQWlCLENBQXJCLEVBQXdCO0FBQ3RCLFlBQU0sSUFBSXBDLEtBQUosQ0FBVywyQkFBWCxDQUFOO0FBQ0Q7O0FBRUQsVUFBTXdMLEtBQUssR0FBRyxtREFBbURsRixJQUFuRCxDQUF3RGlGLEtBQUssQ0FBQyxDQUFELENBQTdELENBQWQ7O0FBQ0EsUUFBSSxDQUFDQyxLQUFELElBQVVwTixnQkFBRXFOLEtBQUYsQ0FBUXBGLFFBQVEsQ0FBQ21GLEtBQUssQ0FBQyxDQUFELENBQU4sRUFBVyxFQUFYLENBQWhCLENBQWQsRUFBK0M7QUFDN0MsWUFBTSxJQUFJeEwsS0FBSixDQUFXLDJDQUEwQ3VMLEtBQUssQ0FBQyxDQUFELENBQUksR0FBOUQsQ0FBTjtBQUNEOztBQUNELFdBQU9sRixRQUFRLENBQUNtRixLQUFLLENBQUMsQ0FBRCxDQUFOLEVBQVcsRUFBWCxDQUFmO0FBQ0QsR0FYRCxDQVdFLE9BQU9oRyxHQUFQLEVBQVk7QUFDWixVQUFNLElBQUl4RixLQUFKLENBQVcsZ0NBQStCZ0wsVUFBVyxNQUFLeEYsR0FBRyxDQUFDOUUsT0FBUSxFQUF0RSxDQUFOO0FBQ0Q7QUFDRixDQWZEOztBQStCQXRELGlCQUFpQixDQUFDc08sc0JBQWxCLEdBQTJDLGVBQWVBLHNCQUFmLENBQXVDQyxJQUF2QyxFQUE2QztBQUN0RixRQUFNQyxPQUFPLEdBQUcsTUFBTSwrQkFBdEI7O0FBRUEsTUFBSSxDQUFDeE4sZ0JBQUV5TixRQUFGLENBQVdGLElBQVgsQ0FBTCxFQUF1QjtBQUNyQkEsSUFBQUEsSUFBSSxHQUFHRyxNQUFNLENBQUNDLElBQVAsQ0FBWUosSUFBWixFQUFrQixRQUFsQixDQUFQO0FBQ0Q7O0FBRUQsUUFBTUssT0FBTyxHQUFHLE1BQU1DLHVCQUFRQyxPQUFSLEVBQXRCOztBQUNBLE1BQUk7QUFDRixVQUFNQyxPQUFPLEdBQUcxTixjQUFLUSxPQUFMLENBQWErTSxPQUFiLEVBQXNCLFlBQXRCLENBQWhCOztBQUNBLFVBQU1uTSxrQkFBR3NELFNBQUgsQ0FBYWdKLE9BQWIsRUFBc0JSLElBQXRCLENBQU47QUFDQSxRQUFJO0FBQUNwTCxNQUFBQTtBQUFELFFBQVcsTUFBTSx3QkFBS3FMLE9BQUwsRUFBYyxDQUFDLE1BQUQsRUFBUyxRQUFULEVBQW1CLE9BQW5CLEVBQTRCLEtBQTVCLEVBQW1DTyxPQUFuQyxDQUFkLENBQXJCO0FBQ0EsVUFBTUMsUUFBUSxHQUFHN0wsTUFBTSxDQUFDWSxJQUFQLEVBQWpCOztBQUNBbkQsb0JBQUlzQyxLQUFKLENBQVcseUJBQXdCOEwsUUFBUyxFQUE1Qzs7QUFDQXBPLG9CQUFJc0MsS0FBSixDQUFVLCtCQUFWOztBQUNBLEtBQUM7QUFBQ0MsTUFBQUE7QUFBRCxRQUFXLE1BQU0sd0JBQUtxTCxPQUFMLEVBQWMsQ0FBQyxNQUFELEVBQVMsS0FBVCxFQUFnQk8sT0FBaEIsQ0FBZCxFQUF3QztBQUFDTixNQUFBQSxRQUFRLEVBQUU7QUFBWCxLQUF4QyxDQUFsQjtBQUNBLFFBQUlRLGNBQWMsR0FBRzlMLE1BQXJCO0FBQ0EsS0FBQztBQUFDQSxNQUFBQTtBQUFELFFBQVcsTUFBTSx3QkFBS3FMLE9BQUwsRUFBYyxDQUFDLE1BQUQsRUFDOUIsS0FEOEIsRUFDdkJPLE9BRHVCLEVBRTlCLE9BRjhCLEVBRzlCLGNBSDhCLEVBSTlCLFFBSjhCLENBQWQsRUFJTDtBQUFDTixNQUFBQSxRQUFRLEVBQUU7QUFBWCxLQUpLLENBQWxCO0FBS0FRLElBQUFBLGNBQWMsR0FBR1AsTUFBTSxDQUFDbkcsTUFBUCxDQUFjLENBQUMwRyxjQUFELEVBQWlCOUwsTUFBakIsQ0FBZCxDQUFqQjs7QUFDQSxVQUFNK0wsT0FBTyxHQUFHN04sY0FBS1EsT0FBTCxDQUFhK00sT0FBYixFQUF1QixHQUFFSSxRQUFTLElBQWxDLENBQWhCOztBQUNBLFVBQU12TSxrQkFBR3NELFNBQUgsQ0FBYW1KLE9BQWIsRUFBc0JELGNBQXRCLENBQU47O0FBQ0FyTyxvQkFBSXNDLEtBQUosQ0FBVSwrQkFBVjs7QUFFQSxVQUFNLDZCQUFjLENBQWQsRUFBaUIsSUFBakIsRUFBdUIsWUFBWSxNQUFNLEtBQUtxQyxPQUFMLENBQWEsQ0FBQyxTQUFELENBQWIsQ0FBekMsQ0FBTjs7QUFDQTNFLG9CQUFJc0MsS0FBSixDQUFXLDZDQUE0Q2dNLE9BQVEsU0FBUTNPLFVBQVcsR0FBbEY7O0FBQ0EsVUFBTSxLQUFLNkIsSUFBTCxDQUFVOE0sT0FBVixFQUFtQjNPLFVBQW5CLENBQU47O0FBQ0FLLG9CQUFJc0MsS0FBSixDQUFVLHVDQUFWOztBQUNBLFVBQU0sS0FBS3FDLE9BQUwsQ0FBYSxDQUFDLFNBQUQsQ0FBYixDQUFOO0FBQ0QsR0F4QkQsQ0F3QkUsT0FBTzZDLEdBQVAsRUFBWTtBQUNaLFVBQU0sSUFBSXhGLEtBQUosQ0FBVyx3Q0FBRCxHQUNDLDBEQURELEdBRUMsOENBRkQsR0FHQyxtQkFBa0J3RixHQUFHLENBQUM5RSxPQUFRLEVBSHpDLENBQU47QUFJRCxHQTdCRCxTQTZCVTtBQUNSLFVBQU1iLGtCQUFHME0sTUFBSCxDQUFVUCxPQUFWLENBQU47QUFDRDtBQUNGLENBeENEOztBQW1EQTVPLGlCQUFpQixDQUFDb1AsMEJBQWxCLEdBQStDLGVBQWVBLDBCQUFmLENBQTJDYixJQUEzQyxFQUFpRDtBQUM5RixRQUFNQyxPQUFPLEdBQUcsTUFBTSwrQkFBdEI7O0FBRUEsTUFBSSxDQUFDeE4sZ0JBQUV5TixRQUFGLENBQVdGLElBQVgsQ0FBTCxFQUF1QjtBQUNyQkEsSUFBQUEsSUFBSSxHQUFHRyxNQUFNLENBQUNDLElBQVAsQ0FBWUosSUFBWixFQUFrQixRQUFsQixDQUFQO0FBQ0Q7O0FBRUQsUUFBTUssT0FBTyxHQUFHLE1BQU1DLHVCQUFRQyxPQUFSLEVBQXRCO0FBQ0EsTUFBSUUsUUFBSjs7QUFDQSxNQUFJO0FBQ0YsVUFBTUssT0FBTyxHQUFHaE8sY0FBS1EsT0FBTCxDQUFhK00sT0FBYixFQUFzQixZQUF0QixDQUFoQjs7QUFDQSxVQUFNbk0sa0JBQUdzRCxTQUFILENBQWFzSixPQUFiLEVBQXNCZCxJQUF0QixDQUFOO0FBQ0EsVUFBTTtBQUFDcEwsTUFBQUE7QUFBRCxRQUFXLE1BQU0sd0JBQUtxTCxPQUFMLEVBQWMsQ0FBQyxNQUFELEVBQVMsUUFBVCxFQUFtQixPQUFuQixFQUE0QixLQUE1QixFQUFtQ2EsT0FBbkMsQ0FBZCxDQUF2QjtBQUNBTCxJQUFBQSxRQUFRLEdBQUc3TCxNQUFNLENBQUNZLElBQVAsRUFBWDtBQUNELEdBTEQsQ0FLRSxPQUFPcUUsR0FBUCxFQUFZO0FBQ1osVUFBTSxJQUFJeEYsS0FBSixDQUFXLHdDQUFELEdBQ0MsMERBREQsR0FFQyxtQkFBa0J3RixHQUFHLENBQUM5RSxPQUFRLEVBRnpDLENBQU47QUFHRCxHQVRELFNBU1U7QUFDUixVQUFNYixrQkFBRzBNLE1BQUgsQ0FBVVAsT0FBVixDQUFOO0FBQ0Q7O0FBQ0QsUUFBTTlJLE9BQU8sR0FBR3pFLGNBQUtpTyxLQUFMLENBQVd6TixPQUFYLENBQW1CdEIsVUFBbkIsRUFBZ0MsR0FBRXlPLFFBQVMsSUFBM0MsQ0FBaEI7O0FBQ0FwTyxrQkFBSXNDLEtBQUosQ0FBVyx3REFBdUQ0QyxPQUFRLEdBQTFFOztBQUNBLFNBQU8sTUFBTSxLQUFLNkgsVUFBTCxDQUFnQjdILE9BQWhCLENBQWI7QUFDRCxDQXhCRDs7ZUEwQmU5RixpQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGxvZyBmcm9tICcuLi9sb2dnZXIuanMnO1xuaW1wb3J0IEIgZnJvbSAnYmx1ZWJpcmQnO1xuaW1wb3J0IHsgc3lzdGVtLCBmcywgdXRpbCwgdGVtcERpciwgdGltaW5nIH0gZnJvbSAnYXBwaXVtLXN1cHBvcnQnO1xuaW1wb3J0IHtcbiAgZ2V0U2RrVG9vbHNWZXJzaW9uLFxuICBnZXRCdWlsZFRvb2xzRGlycyxcbiAgZ2V0T3BlblNzbEZvck9zLFxuICBERUZBVUxUX0FEQl9FWEVDX1RJTUVPVVQgfSBmcm9tICcuLi9oZWxwZXJzJztcbmltcG9ydCB7IGV4ZWMsIFN1YlByb2Nlc3MgfSBmcm9tICd0ZWVuX3Byb2Nlc3MnO1xuaW1wb3J0IHsgc2xlZXAsIHJldHJ5LCByZXRyeUludGVydmFsLCB3YWl0Rm9yQ29uZGl0aW9uIH0gZnJvbSAnYXN5bmNib3gnO1xuaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcblxuXG5sZXQgc3lzdGVtQ2FsbE1ldGhvZHMgPSB7fTtcblxuY29uc3QgREVGQVVMVF9BREJfUkVCT09UX1JFVFJJRVMgPSA5MDtcblxuY29uc3QgTElOS0VSX1dBUk5JTkdfUkVHRVhQID0gL15XQVJOSU5HOiBsaW5rZXIuKyQvbTtcbmNvbnN0IFBST1RPQ09MX0ZBVUxUX0VSUk9SX1JFR0VYUCA9IG5ldyBSZWdFeHAoJ3Byb3RvY29sIGZhdWx0IFxcXFwobm8gc3RhdHVzXFxcXCknLCAnaScpO1xuY29uc3QgREVWSUNFX05PVF9GT1VORF9FUlJPUl9SRUdFWFAgPSBuZXcgUmVnRXhwKGBlcnJvcjogZGV2aWNlICgnLisnICk/bm90IGZvdW5kYCwgJ2knKTtcbmNvbnN0IERFVklDRV9DT05ORUNUSU5HX0VSUk9SX1JFR0VYUCA9IG5ldyBSZWdFeHAoJ2Vycm9yOiBkZXZpY2Ugc3RpbGwgY29ubmVjdGluZycsICdpJyk7XG5cbmNvbnN0IENFUlRTX1JPT1QgPSAnL3N5c3RlbS9ldGMvc2VjdXJpdHkvY2FjZXJ0cyc7XG5cbi8qKlxuICogUmV0cmlldmUgZnVsbCBwYXRoIHRvIHRoZSBnaXZlbiBiaW5hcnkuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJpbmFyeU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgYmluYXJ5LlxuICogQHJldHVybiB7c3RyaW5nfSBGdWxsIHBhdGggdG8gdGhlIGdpdmVuIGJpbmFyeSBpbmNsdWRpbmcgY3VycmVudCBTREsgcm9vdC5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZ2V0U2RrQmluYXJ5UGF0aCA9IGFzeW5jIGZ1bmN0aW9uIGdldFNka0JpbmFyeVBhdGggKGJpbmFyeU5hbWUpIHtcbiAgaWYgKHRoaXMuc2RrUm9vdCkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLmdldEJpbmFyeUZyb21TZGtSb290KGJpbmFyeU5hbWUpO1xuICB9XG4gIGxvZy53YXJuKGBUaGUgQU5EUk9JRF9IT01FIGVudmlyb25tZW50IHZhcmlhYmxlIGlzIG5vdCBzZXQgdG8gdGhlIEFuZHJvaWQgU0RLIGAgK1xuICAgIGByb290IGRpcmVjdG9yeSBwYXRoLiBBTkRST0lEX0hPTUUgaXMgcmVxdWlyZWQgZm9yIGNvbXBhdGliaWxpdHkgYCArXG4gICAgYHdpdGggU0RLIDIzKy4gQ2hlY2tpbmcgYWxvbmcgUEFUSCBmb3IgJHtiaW5hcnlOYW1lfS5gKTtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuZ2V0QmluYXJ5RnJvbVBhdGgoYmluYXJ5TmFtZSk7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIGZ1bGwgYmluYXJ5IG5hbWUgZm9yIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0uXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJpbmFyeU5hbWUgLSBzaW1wbGUgYmluYXJ5IG5hbWUsIGZvciBleGFtcGxlICdhbmRyb2lkJy5cbiAqIEByZXR1cm4ge3N0cmluZ30gRm9ybWF0dGVkIGJpbmFyeSBuYW1lIGRlcGVuZGluZyBvbiB0aGUgY3VycmVudCBwbGF0Zm9ybSxcbiAqICAgICAgICAgICAgICAgICAgZm9yIGV4YW1wbGUsICdhbmRyb2lkLmJhdCcgb24gV2luZG93cy5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZ2V0QmluYXJ5TmFtZUZvck9TID0gXy5tZW1vaXplKGZ1bmN0aW9uIGdldEJpbmFyeU5hbWVGb3JPUyAoYmluYXJ5TmFtZSkge1xuICBpZiAoIXN5c3RlbS5pc1dpbmRvd3MoKSkge1xuICAgIHJldHVybiBiaW5hcnlOYW1lO1xuICB9XG5cbiAgaWYgKFsnYW5kcm9pZCcsICdhcGtzaWduZXInLCAnYXBrYW5hbHl6ZXInXS5pbmNsdWRlcyhiaW5hcnlOYW1lKSkge1xuICAgIHJldHVybiBgJHtiaW5hcnlOYW1lfS5iYXRgO1xuICB9XG4gIGlmICghcGF0aC5leHRuYW1lKGJpbmFyeU5hbWUpKSB7XG4gICAgcmV0dXJuIGAke2JpbmFyeU5hbWV9LmV4ZWA7XG4gIH1cbiAgcmV0dXJuIGJpbmFyeU5hbWU7XG59KTtcblxuLyoqXG4gKiBSZXRyaWV2ZSBmdWxsIHBhdGggdG8gdGhlIGdpdmVuIGJpbmFyeSBhbmQgY2FjaGVzIGl0IGludG8gYGJpbmFyaWVzYFxuICogcHJvcGVydHkgb2YgdGhlIGN1cnJlbnQgQURCIGluc3RhbmNlLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBiaW5hcnlOYW1lIC0gU2ltcGxlIG5hbWUgb2YgYSBiaW5hcnkgZmlsZS5cbiAqIEByZXR1cm4ge3N0cmluZ30gRnVsbCBwYXRoIHRvIHRoZSBnaXZlbiBiaW5hcnkuIFRoZSBtZXRob2QgdHJpZXNcbiAqICAgICAgICAgICAgICAgICAgdG8gZW51bWVyYXRlIGFsbCB0aGUga25vd24gbG9jYXRpb25zIHdoZXJlIHRoZSBiaW5hcnlcbiAqICAgICAgICAgICAgICAgICAgbWlnaHQgYmUgbG9jYXRlZCBhbmQgc3RvcHMgdGhlIHNlYXJjaCBhcyBzb29uIGFzIHRoZSBmaXJzdFxuICogICAgICAgICAgICAgICAgICBtYXRjaCBpcyBmb3VuZCBvbiB0aGUgbG9jYWwgZmlsZSBzeXN0ZW0uXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIGJpbmFyeSB3aXRoIGdpdmVuIG5hbWUgaXMgbm90IHByZXNlbnQgYXQgYW55XG4gKiAgICAgICAgICAgICAgICAgb2Yga25vd24gbG9jYXRpb25zIG9yIEFuZHJvaWQgU0RLIGlzIG5vdCBpbnN0YWxsZWQgb24gdGhlXG4gKiAgICAgICAgICAgICAgICAgbG9jYWwgZmlsZSBzeXN0ZW0uXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmdldEJpbmFyeUZyb21TZGtSb290ID0gYXN5bmMgZnVuY3Rpb24gZ2V0QmluYXJ5RnJvbVNka1Jvb3QgKGJpbmFyeU5hbWUpIHtcbiAgaWYgKHRoaXMuYmluYXJpZXNbYmluYXJ5TmFtZV0pIHtcbiAgICByZXR1cm4gdGhpcy5iaW5hcmllc1tiaW5hcnlOYW1lXTtcbiAgfVxuXG4gIGNvbnN0IGZ1bGxCaW5hcnlOYW1lID0gdGhpcy5nZXRCaW5hcnlOYW1lRm9yT1MoYmluYXJ5TmFtZSk7XG4gIGNvbnN0IGJpbmFyeUxvY3MgPSBbJ3BsYXRmb3JtLXRvb2xzJywgJ2VtdWxhdG9yJywgJ3Rvb2xzJywgYHRvb2xzJHtwYXRoLnNlcH1iaW5gXVxuICAgIC5tYXAoKHgpID0+IHBhdGgucmVzb2x2ZSh0aGlzLnNka1Jvb3QsIHgsIGZ1bGxCaW5hcnlOYW1lKSk7XG4gIC8vIGdldCBzdWJwYXRocyBmb3IgY3VycmVudGx5IGluc3RhbGxlZCBidWlsZCB0b29sIGRpcmVjdG9yaWVzXG4gIGxldCBidWlsZFRvb2xzRGlycyA9IGF3YWl0IGdldEJ1aWxkVG9vbHNEaXJzKHRoaXMuc2RrUm9vdCk7XG4gIGlmICh0aGlzLmJ1aWxkVG9vbHNWZXJzaW9uKSB7XG4gICAgYnVpbGRUb29sc0RpcnMgPSBidWlsZFRvb2xzRGlyc1xuICAgICAgLmZpbHRlcigoeCkgPT4gcGF0aC5iYXNlbmFtZSh4KSA9PT0gdGhpcy5idWlsZFRvb2xzVmVyc2lvbik7XG4gICAgaWYgKF8uaXNFbXB0eShidWlsZFRvb2xzRGlycykpIHtcbiAgICAgIGxvZy5pbmZvKGBGb3VuZCBubyBidWlsZCB0b29scyB3aG9zZSB2ZXJzaW9uIG1hdGNoZXMgdG8gJyR7dGhpcy5idWlsZFRvb2xzVmVyc2lvbn0nYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZy5pbmZvKGBVc2luZyBidWlsZCB0b29scyBhdCAnJHtidWlsZFRvb2xzRGlyc30nYCk7XG4gICAgfVxuICB9XG4gIGJpbmFyeUxvY3MucHVzaCguLi4oXy5mbGF0dGVuKGJ1aWxkVG9vbHNEaXJzXG4gICAgLm1hcCgoZGlyKSA9PiBbXG4gICAgICBwYXRoLnJlc29sdmUoZGlyLCBmdWxsQmluYXJ5TmFtZSksXG4gICAgICBwYXRoLnJlc29sdmUoZGlyLCAnbGliJywgZnVsbEJpbmFyeU5hbWUpLFxuICAgIF0pKVxuICApKTtcblxuICBsZXQgYmluYXJ5TG9jID0gbnVsbDtcbiAgZm9yIChjb25zdCBsb2Mgb2YgYmluYXJ5TG9jcykge1xuICAgIGlmIChhd2FpdCBmcy5leGlzdHMobG9jKSkge1xuICAgICAgYmluYXJ5TG9jID0gbG9jO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIGlmIChfLmlzTnVsbChiaW5hcnlMb2MpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDb3VsZCBub3QgZmluZCAnJHtmdWxsQmluYXJ5TmFtZX0nIGluICR7SlNPTi5zdHJpbmdpZnkoYmluYXJ5TG9jcyl9LiBgICtcbiAgICAgIGBEbyB5b3UgaGF2ZSBBbmRyb2lkIEJ1aWxkIFRvb2xzICR7dGhpcy5idWlsZFRvb2xzVmVyc2lvbiA/IGB2ICR7dGhpcy5idWlsZFRvb2xzVmVyc2lvbn0gYCA6ICcnfWAgK1xuICAgICAgYGluc3RhbGxlZCBhdCAnJHt0aGlzLnNka1Jvb3R9Jz9gKTtcbiAgfVxuICBsb2cuaW5mbyhgVXNpbmcgJyR7ZnVsbEJpbmFyeU5hbWV9JyBmcm9tICcke2JpbmFyeUxvY30nYCk7XG4gIHRoaXMuYmluYXJpZXNbYmluYXJ5TmFtZV0gPSBiaW5hcnlMb2M7XG4gIHJldHVybiBiaW5hcnlMb2M7XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIGZ1bGwgcGF0aCB0byBhIGJpbmFyeSBmaWxlIHVzaW5nIHRoZSBzdGFuZGFyZCBzeXN0ZW0gbG9va3VwIHRvb2wuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGJpbmFyeU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgYmluYXJ5LlxuICogQHJldHVybiB7c3RyaW5nfSBGdWxsIHBhdGggdG8gdGhlIGJpbmFyeSByZWNlaXZlZCBmcm9tICd3aGljaCcvJ3doZXJlJ1xuICogICAgICAgICAgICAgICAgICBvdXRwdXQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgbG9va3VwIHRvb2wgcmV0dXJucyBub24temVybyByZXR1cm4gY29kZS5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZ2V0QmluYXJ5RnJvbVBhdGggPSBhc3luYyBmdW5jdGlvbiBnZXRCaW5hcnlGcm9tUGF0aCAoYmluYXJ5TmFtZSkge1xuICBpZiAodGhpcy5iaW5hcmllc1tiaW5hcnlOYW1lXSkge1xuICAgIHJldHVybiB0aGlzLmJpbmFyaWVzW2JpbmFyeU5hbWVdO1xuICB9XG5cbiAgY29uc3QgZnVsbEJpbmFyeU5hbWUgPSB0aGlzLmdldEJpbmFyeU5hbWVGb3JPUyhiaW5hcnlOYW1lKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBiaW5hcnlMb2MgPSBhd2FpdCBmcy53aGljaChmdWxsQmluYXJ5TmFtZSk7XG4gICAgbG9nLmluZm8oYFVzaW5nICcke2Z1bGxCaW5hcnlOYW1lfScgZnJvbSAnJHtiaW5hcnlMb2N9J2ApO1xuICAgIHRoaXMuYmluYXJpZXNbYmluYXJ5TmFtZV0gPSBiaW5hcnlMb2M7XG4gICAgcmV0dXJuIGJpbmFyeUxvYztcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IGZpbmQgJyR7ZnVsbEJpbmFyeU5hbWV9JyBpbiBQQVRILiBQbGVhc2Ugc2V0IHRoZSBBTkRST0lEX0hPTUUgYCArXG4gICAgICBgb3IgQU5EUk9JRF9TREtfUk9PVCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gdGhlIGNvcnJlY3QgQW5kcm9pZCBTREsgcm9vdCBkaXJlY3RvcnkgcGF0aC5gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBEZXZpY2VcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB1ZGlkIC0gVGhlIGRldmljZSB1ZGlkLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IHN0YXRlIC0gQ3VycmVudCBkZXZpY2Ugc3RhdGUsIGFzIGl0IGlzIHZpc2libGUgaW5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9hZGIgZGV2aWNlcyAtbF8gb3V0cHV0LlxuICovXG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgZGV2aWNlcyB2aXNpYmxlIHRvIGFkYi5cbiAqXG4gKiBAcmV0dXJuIHtBcnJheS48RGV2aWNlPn0gVGhlIGxpc3Qgb2YgZGV2aWNlcyBvciBhbiBlbXB0eSBsaXN0IGlmXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgbm8gZGV2aWNlcyBhcmUgY29ubmVjdGVkLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBsaXN0aW5nIGRldmljZXMuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmdldENvbm5lY3RlZERldmljZXMgPSBhc3luYyBmdW5jdGlvbiBnZXRDb25uZWN0ZWREZXZpY2VzICgpIHtcbiAgbG9nLmRlYnVnKCdHZXR0aW5nIGNvbm5lY3RlZCBkZXZpY2VzLi4uJyk7XG4gIGxldCBzdGRvdXQ7XG4gIHRyeSB7XG4gICAgKHtzdGRvdXR9ID0gYXdhaXQgZXhlYyh0aGlzLmV4ZWN1dGFibGUucGF0aCwgWy4uLnRoaXMuZXhlY3V0YWJsZS5kZWZhdWx0QXJncywgJ2RldmljZXMnXSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3aGlsZSBnZXR0aW5nIGNvbm5lY3RlZCBkZXZpY2VzLiBPcmlnaW5hbCBlcnJvcjogJHtlLm1lc3NhZ2V9YCk7XG4gIH1cbiAgY29uc3QgbGlzdEhlYWRlciA9ICdMaXN0IG9mIGRldmljZXMnO1xuICAvLyBleHBlY3RpbmcgYWRiIGRldmljZXMgdG8gcmV0dXJuIG91dHB1dCBhc1xuICAvLyBMaXN0IG9mIGRldmljZXMgYXR0YWNoZWRcbiAgLy8gZW11bGF0b3ItNTU1NFx0ZGV2aWNlXG4gIGNvbnN0IHN0YXJ0aW5nSW5kZXggPSBzdGRvdXQuaW5kZXhPZihsaXN0SGVhZGVyKTtcbiAgaWYgKHN0YXJ0aW5nSW5kZXggPCAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkIG91dHB1dCB3aGlsZSB0cnlpbmcgdG8gZ2V0IGRldmljZXM6ICR7c3Rkb3V0fWApO1xuICB9XG4gIC8vIHNsaWNpbmcgb3V0cHV0IHdlIGNhcmUgYWJvdXRcbiAgc3Rkb3V0ID0gc3Rkb3V0LnNsaWNlKHN0YXJ0aW5nSW5kZXgpO1xuICBsZXQgZXhjbHVkZWRMaW5lcyA9IFtsaXN0SGVhZGVyLCAnYWRiIHNlcnZlcicsICcqIGRhZW1vbiddO1xuICBpZiAoIXRoaXMuYWxsb3dPZmZsaW5lRGV2aWNlcykge1xuICAgIGV4Y2x1ZGVkTGluZXMucHVzaCgnb2ZmbGluZScpO1xuICB9XG4gIGNvbnN0IGRldmljZXMgPSBzdGRvdXQuc3BsaXQoJ1xcbicpXG4gICAgLm1hcChfLnRyaW0pXG4gICAgLmZpbHRlcigobGluZSkgPT4gbGluZSAmJiAhZXhjbHVkZWRMaW5lcy5zb21lKCh4KSA9PiBsaW5lLmluY2x1ZGVzKHgpKSlcbiAgICAucmVkdWNlKChhY2MsIGxpbmUpID0+IHtcbiAgICAgIC8vIHN0YXRlIGlzIFwiZGV2aWNlXCIsIGFmYWljXG4gICAgICBjb25zdCBbdWRpZCwgc3RhdGVdID0gbGluZS5zcGxpdCgvXFxzKy8pO1xuICAgICAgYWNjLnB1c2goe3VkaWQsIHN0YXRlfSk7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIFtdKTtcbiAgaWYgKF8uaXNFbXB0eShkZXZpY2VzKSkge1xuICAgIGxvZy5kZWJ1ZygnTm8gY29ubmVjdGVkIGRldmljZXMgaGF2ZSBiZWVuIGRldGVjdGVkJyk7XG4gIH0gZWxzZSB7XG4gICAgbG9nLmRlYnVnKGBDb25uZWN0ZWQgZGV2aWNlczogJHtKU09OLnN0cmluZ2lmeShkZXZpY2VzKX1gKTtcbiAgfVxuICByZXR1cm4gZGV2aWNlcztcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGxpc3Qgb2YgZGV2aWNlcyB2aXNpYmxlIHRvIGFkYiB3aXRoaW4gdGhlIGdpdmVuIHRpbWVvdXQuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHRpbWVvdXRNcyAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gZ2V0IGF0IGxlYXN0XG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25lIGxpc3QgaXRlbS5cbiAqIEByZXR1cm4ge0FycmF5LjxEZXZpY2U+fSBUaGUgbGlzdCBvZiBjb25uZWN0ZWQgZGV2aWNlcy5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBubyBjb25uZWN0ZWQgZGV2aWNlcyBjYW4gYmUgZGV0ZWN0ZWQgd2l0aGluIHRoZSBnaXZlbiB0aW1lb3V0LlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5nZXREZXZpY2VzV2l0aFJldHJ5ID0gYXN5bmMgZnVuY3Rpb24gZ2V0RGV2aWNlc1dpdGhSZXRyeSAodGltZW91dE1zID0gMjAwMDApIHtcbiAgY29uc3QgdGltZXIgPSBuZXcgdGltaW5nLlRpbWVyKCkuc3RhcnQoKTtcbiAgbG9nLmRlYnVnKCdUcnlpbmcgdG8gZmluZCBhIGNvbm5lY3RlZCBhbmRyb2lkIGRldmljZScpO1xuICBjb25zdCBnZXREZXZpY2VzID0gYXN5bmMgKCkgPT4ge1xuICAgIGlmICh0aW1lci5nZXREdXJhdGlvbigpLmFzTWlsbGlTZWNvbmRzID4gdGltZW91dE1zKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIGEgY29ubmVjdGVkIEFuZHJvaWQgZGV2aWNlIGluICR7dGltZXIuZ2V0RHVyYXRpb24oKS5hc01pbGxpU2Vjb25kcy50b0ZpeGVkKDApfW1zLmApO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgZGV2aWNlcyA9IGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkRGV2aWNlcygpO1xuICAgICAgaWYgKGRldmljZXMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gZGV2aWNlcztcbiAgICAgIH1cbiAgICB9IGNhdGNoIChpZ24pIHt9XG5cbiAgICBsb2cuZGVidWcoJ0NvdWxkIG5vdCBmaW5kIGRldmljZXMsIHJlc3RhcnRpbmcgYWRiIHNlcnZlci4uLicpO1xuICAgIGF3YWl0IHRoaXMucmVzdGFydEFkYigpO1xuICAgIC8vIGNvb2wgZG93blxuICAgIGF3YWl0IHNsZWVwKDIwMCk7XG4gICAgcmV0dXJuIGF3YWl0IGdldERldmljZXMoKTtcbiAgfTtcbiAgcmV0dXJuIGF3YWl0IGdldERldmljZXMoKTtcbn07XG5cbi8qKlxuICogUmVzdGFydCBhZGIgc2VydmVyLCB1bmxlc3MgX3RoaXMuc3VwcHJlc3NLaWxsU2VydmVyXyBwcm9wZXJ0eSBpcyB0cnVlLlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5yZXN0YXJ0QWRiID0gYXN5bmMgZnVuY3Rpb24gcmVzdGFydEFkYiAoKSB7XG4gIGlmICh0aGlzLnN1cHByZXNzS2lsbFNlcnZlcikge1xuICAgIGxvZy5kZWJ1ZyhgTm90IHJlc3RhcnRpbmcgYWJkIHNpbmNlICdzdXBwcmVzc0tpbGxTZXJ2ZXInIGlzIG9uYCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbG9nLmRlYnVnKCdSZXN0YXJ0aW5nIGFkYicpO1xuICB0cnkge1xuICAgIGF3YWl0IHRoaXMua2lsbFNlcnZlcigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLmVycm9yKGBFcnJvciBraWxsaW5nIEFEQiBzZXJ2ZXIsIGdvaW5nIHRvIHNlZSBpZiBpdCdzIG9ubGluZSBhbnl3YXlgKTtcbiAgfVxufTtcblxuLyoqXG4gKiBLaWxsIGFkYiBzZXJ2ZXIuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmtpbGxTZXJ2ZXIgPSBhc3luYyBmdW5jdGlvbiBraWxsU2VydmVyICgpIHtcbiAgbG9nLmRlYnVnKGBLaWxsaW5nIGFkYiBzZXJ2ZXIgb24gcG9ydCAnJHt0aGlzLmFkYlBvcnR9J2ApO1xuICBhd2FpdCB0aGlzLmFkYkV4ZWMoWydraWxsLXNlcnZlciddLCB7XG4gICAgZXhjbHVzaXZlOiB0cnVlLFxuICB9KTtcbn07XG5cbi8qKlxuICogUmVzZXQgVGVsbmV0IGF1dGhlbnRpY2F0aW9uIHRva2VuLlxuICogQHNlZSB7QGxpbmsgaHR0cDovL3Rvb2xzLmFuZHJvaWQuY29tL3JlY2VudC9lbXVsYXRvcjI1MTZyZWxlYXNlbm90ZXN9IGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogQHJldHVybnMge2Jvb2xlYW59IElmIHRva2VuIHJlc2V0IHdhcyBzdWNjZXNzZnVsLlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5yZXNldFRlbG5ldEF1dGhUb2tlbiA9IF8ubWVtb2l6ZShhc3luYyBmdW5jdGlvbiByZXNldFRlbG5ldEF1dGhUb2tlbiAoKSB7XG4gIC8vIFRoZSBtZXRob2RzIGlzIHVzZWQgdG8gcmVtb3ZlIHRlbG5ldCBhdXRoIHRva2VuXG4gIC8vXG4gIGNvbnN0IGhvbWVGb2xkZXJQYXRoID0gcHJvY2Vzcy5lbnZbKHByb2Nlc3MucGxhdGZvcm0gPT09ICd3aW4zMicpID8gJ1VTRVJQUk9GSUxFJyA6ICdIT01FJ107XG4gIGlmICghaG9tZUZvbGRlclBhdGgpIHtcbiAgICBsb2cud2FybihgQ2Fubm90IGZpbmQgdGhlIHBhdGggdG8gdXNlciBob21lIGZvbGRlci4gSWdub3JpbmcgcmVzZXR0aW5nIG9mIGVtdWxhdG9yJ3MgdGVsbmV0IGF1dGhlbnRpY2F0aW9uIHRva2VuYCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGRzdFBhdGggPSBwYXRoLnJlc29sdmUoaG9tZUZvbGRlclBhdGgsICcuZW11bGF0b3JfY29uc29sZV9hdXRoX3Rva2VuJyk7XG4gIGxvZy5kZWJ1ZyhgT3ZlcnJpZGluZyAke2RzdFBhdGh9IHdpdGggYW4gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHRlbG5ldCBhdXRoZW50aWNhdGlvbiBmb3IgZW11bGF0b3IgY29tbWFuZHNgKTtcbiAgdHJ5IHtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUoZHN0UGF0aCwgJycpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbG9nLndhcm4oYEVycm9yICR7ZS5tZXNzYWdlfSB3aGlsZSByZXNldHRpbmcgdGhlIGNvbnRlbnQgb2YgJHtkc3RQYXRofS4gSWdub3JpbmcgcmVzZXR0aW5nIG9mIGVtdWxhdG9yJ3MgdGVsbmV0IGF1dGhlbnRpY2F0aW9uIHRva2VuYCk7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufSk7XG5cbi8qKlxuICogRXhlY3V0ZSB0aGUgZ2l2ZW4gZW11bGF0b3IgY29tbWFuZCB1c2luZyBfYWRiIGVtdV8gdG9vbC5cbiAqXG4gKiBAcGFyYW0ge0FycmF5LjxzdHJpbmc+fSBjbWQgLSBUaGUgYXJyYXkgb2YgcmVzdCBjb21tYW5kIGxpbmUgcGFyYW1ldGVycy5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuYWRiRXhlY0VtdSA9IGFzeW5jIGZ1bmN0aW9uIGFkYkV4ZWNFbXUgKGNtZCkge1xuICBhd2FpdCB0aGlzLnZlcmlmeUVtdWxhdG9yQ29ubmVjdGVkKCk7XG4gIGF3YWl0IHRoaXMucmVzZXRUZWxuZXRBdXRoVG9rZW4oKTtcbiAgYXdhaXQgdGhpcy5hZGJFeGVjKFsnZW11JywgLi4uY21kXSk7XG59O1xuXG5sZXQgaXNFeGVjTG9ja2VkID0gZmFsc2U7XG5cbi8qKlxuICogRXhlY3V0ZSB0aGUgZ2l2ZW4gYWRiIGNvbW1hbmQuXG4gKlxuICogQHBhcmFtIHtBcnJheS48c3RyaW5nPn0gY21kIC0gVGhlIGFycmF5IG9mIHJlc3QgY29tbWFuZCBsaW5lIHBhcmFtZXRlcnNcbiAqICAgICAgICAgICAgICAgICAgICAgIG9yIGEgc2luZ2xlIHN0cmluZyBwYXJhbWV0ZXIuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIEFkZGl0aW9uYWwgb3B0aW9ucyBtYXBwaW5nLiBTZWVcbiAqICAgICAgICAgICAgICAgICAgICAgICAge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vbm9kZS10ZWVuX3Byb2Nlc3N9XG4gKiAgICAgICAgICAgICAgICAgICAgICAgIGZvciBtb3JlIGRldGFpbHMuXG4gKiAgICAgICAgICAgICAgICAgICAgICAgIFlvdSBjYW4gYWxzbyBzZXQgdGhlIGFkZGl0aW9uYWwgYGV4Y2x1c2l2ZWAgcGFyYW1cbiAqICAgICAgICAgICAgICAgICAgICAgICAgdG8gYHRydWVgIHRoYXQgYXNzdXJlcyBubyBvdGhlciBwYXJhbGxlbCBhZGIgY29tbWFuZHNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgYXJlIGdvaW5nIHRvIGJlIGV4ZWN1dGVkIHdoaWxlIHRoZSBjdXJyZW50IG9uZSBpcyBydW5uaW5nXG4gKiBAcmV0dXJuIHtzdHJpbmd9IC0gQ29tbWFuZCdzIHN0ZG91dC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgY29tbWFuZCByZXR1cm5lZCBub24temVybyBleGl0IGNvZGUuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmFkYkV4ZWMgPSBhc3luYyBmdW5jdGlvbiBhZGJFeGVjIChjbWQsIG9wdHMgPSB7fSkge1xuICBpZiAoIWNtZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignWW91IG5lZWQgdG8gcGFzcyBpbiBhIGNvbW1hbmQgdG8gYWRiRXhlYygpJyk7XG4gIH1cblxuICBvcHRzID0gXy5jbG9uZURlZXAob3B0cyk7XG4gIC8vIHNldHRpbmcgZGVmYXVsdCB0aW1lb3V0IGZvciBlYWNoIGNvbW1hbmQgdG8gcHJldmVudCBpbmZpbml0ZSB3YWl0LlxuICBvcHRzLnRpbWVvdXQgPSBvcHRzLnRpbWVvdXQgfHwgdGhpcy5hZGJFeGVjVGltZW91dCB8fCBERUZBVUxUX0FEQl9FWEVDX1RJTUVPVVQ7XG4gIG9wdHMudGltZW91dENhcE5hbWUgPSBvcHRzLnRpbWVvdXRDYXBOYW1lIHx8ICdhZGJFeGVjVGltZW91dCc7IC8vIEZvciBlcnJvciBtZXNzYWdlXG5cbiAgY21kID0gXy5pc0FycmF5KGNtZCkgPyBjbWQgOiBbY21kXTtcbiAgbGV0IGFkYlJldHJpZWQgPSBmYWxzZTtcbiAgY29uc3QgZXhlY0Z1bmMgPSBhc3luYyAoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFyZ3MgPSBbLi4udGhpcy5leGVjdXRhYmxlLmRlZmF1bHRBcmdzLCAuLi5jbWRdO1xuICAgICAgbG9nLmRlYnVnKGBSdW5uaW5nICcke3RoaXMuZXhlY3V0YWJsZS5wYXRofSAke3V0aWwucXVvdGUoYXJncyl9J2ApO1xuICAgICAgbGV0IHtzdGRvdXR9ID0gYXdhaXQgZXhlYyh0aGlzLmV4ZWN1dGFibGUucGF0aCwgYXJncywgb3B0cyk7XG4gICAgICAvLyBzb21ldGltZXMgQURCIHByaW50cyBvdXQgd2VpcmQgc3Rkb3V0IHdhcm5pbmdzIHRoYXQgd2UgZG9uJ3Qgd2FudFxuICAgICAgLy8gdG8gaW5jbHVkZSBpbiBhbnkgb2YgdGhlIHJlc3BvbnNlIGRhdGEsIHNvIGxldCdzIHN0cmlwIGl0IG91dFxuICAgICAgc3Rkb3V0ID0gc3Rkb3V0LnJlcGxhY2UoTElOS0VSX1dBUk5JTkdfUkVHRVhQLCAnJykudHJpbSgpO1xuICAgICAgcmV0dXJuIHN0ZG91dDtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCBlcnJUZXh0ID0gYCR7ZS5tZXNzYWdlfSwgJHtlLnN0ZG91dH0sICR7ZS5zdGRlcnJ9YDtcbiAgICAgIGNvbnN0IHByb3RvY29sRmF1bHRFcnJvciA9IFBST1RPQ09MX0ZBVUxUX0VSUk9SX1JFR0VYUC50ZXN0KGVyclRleHQpO1xuICAgICAgY29uc3QgZGV2aWNlTm90Rm91bmRFcnJvciA9IERFVklDRV9OT1RfRk9VTkRfRVJST1JfUkVHRVhQLnRlc3QoZXJyVGV4dCk7XG4gICAgICBjb25zdCBkZXZpY2VDb25uZWN0aW5nRXJyb3IgPSBERVZJQ0VfQ09OTkVDVElOR19FUlJPUl9SRUdFWFAudGVzdChlcnJUZXh0KTtcbiAgICAgIGlmIChwcm90b2NvbEZhdWx0RXJyb3IgfHwgZGV2aWNlTm90Rm91bmRFcnJvciB8fCBkZXZpY2VDb25uZWN0aW5nRXJyb3IpIHtcbiAgICAgICAgbG9nLmluZm8oYEVycm9yIHNlbmRpbmcgY29tbWFuZCwgcmVjb25uZWN0aW5nIGRldmljZSBhbmQgcmV0cnlpbmc6ICR7Y21kfWApO1xuICAgICAgICBhd2FpdCBzbGVlcCgxMDAwKTtcbiAgICAgICAgYXdhaXQgdGhpcy5nZXREZXZpY2VzV2l0aFJldHJ5KCk7XG5cbiAgICAgICAgLy8gdHJ5IGFnYWluIG9uZSB0aW1lXG4gICAgICAgIGlmIChhZGJSZXRyaWVkKSB7XG4gICAgICAgICAgYWRiUmV0cmllZCA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGV4ZWNGdW5jKCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGUuY29kZSA9PT0gMCAmJiBlLnN0ZG91dCkge1xuICAgICAgICByZXR1cm4gZS5zdGRvdXQucmVwbGFjZShMSU5LRVJfV0FSTklOR19SRUdFWFAsICcnKS50cmltKCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChfLmlzTnVsbChlLmNvZGUpKSB7XG4gICAgICAgIGUubWVzc2FnZSA9IGBFcnJvciBleGVjdXRpbmcgYWRiRXhlYy4gT3JpZ2luYWwgZXJyb3I6ICcke2UubWVzc2FnZX0nLiBgICtcbiAgICAgICAgICBgVHJ5IHRvIGluY3JlYXNlIHRoZSAke29wdHMudGltZW91dH1tcyBhZGIgZXhlY3V0aW9uIHRpbWVvdXQgcmVwcmVzZW50ZWQgYnkgJyR7b3B0cy50aW1lb3V0Q2FwTmFtZX0nIGNhcGFiaWxpdHlgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZS5tZXNzYWdlID0gYEVycm9yIGV4ZWN1dGluZyBhZGJFeGVjLiBPcmlnaW5hbCBlcnJvcjogJyR7ZS5tZXNzYWdlfSc7IGAgK1xuICAgICAgICAgIGBTdGRlcnI6ICckeyhlLnN0ZGVyciB8fCAnJykudHJpbSgpfSc7IENvZGU6ICcke2UuY29kZX0nYDtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9O1xuXG4gIGlmIChpc0V4ZWNMb2NrZWQpIHtcbiAgICBsb2cuZGVidWcoJ1dhaXRpbmcgdW50aWwgdGhlIG90aGVyIGV4Y2x1c2l2ZSBBREIgY29tbWFuZCBpcyBjb21wbGV0ZWQnKTtcbiAgICBhd2FpdCB3YWl0Rm9yQ29uZGl0aW9uKCgpID0+ICFpc0V4ZWNMb2NrZWQsIHtcbiAgICAgIHdhaXRNczogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsXG4gICAgICBpbnRlcnZhbE1zOiAxMCxcbiAgICB9KTtcbiAgICBsb2cuZGVidWcoJ0NvbnRpbnVpbmcgd2l0aCB0aGUgY3VycmVudCBBREIgY29tbWFuZCcpO1xuICB9XG4gIGlmIChvcHRzLmV4Y2x1c2l2ZSkge1xuICAgIGlzRXhlY0xvY2tlZCA9IHRydWU7XG4gIH1cbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgZXhlY0Z1bmMoKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAob3B0cy5leGNsdXNpdmUpIHtcbiAgICAgIGlzRXhlY0xvY2tlZCA9IGZhbHNlO1xuICAgIH1cbiAgfVxufTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBTaGVsbEV4ZWNPcHRpb25zXG4gKiBAcHJvcGVydHkgez9zdHJpbmd9IHRpbWVvdXRDYXBOYW1lIFthZGJFeGVjVGltZW91dF0gLSB0aGUgbmFtZSBvZiB0aGUgY29ycmVzcG9uZGluZyBBcHBpdW0ncyB0aW1lb3V0IGNhcGFiaWxpdHlcbiAqICh1c2VkIGluIHRoZSBlcnJvciBtZXNzYWdlcykuXG4gKiBAcHJvcGVydHkgez9udW1iZXJ9IHRpbWVvdXQgW2FkYkV4ZWNUaW1lb3V0XSAtIGNvbW1hbmQgZXhlY3V0aW9uIHRpbWVvdXQuXG4gKiBAcHJvcGVydHkgez9ib29sZWFufSBwcml2aWxlZ2VkIFtmYWxzeV0gLSBXaGV0aGVyIHRvIHJ1biB0aGUgZ2l2ZW4gY29tbWFuZCBhcyByb290LlxuICogQHByb3BlcnR5IHs/Ym9vbGVhbn0ga2VlcFByaXZpbGVnZWQgW2ZhbHN5XSAtIFdoZXRoZXIgdG8ga2VlcCByb290IG1vZGUgYWZ0ZXIgY29tbWFuZCBleGVjdXRpb24gaXMgY29tcGxldGVkLlxuICpcbiAqIEFsbCBvdGhlciBwcm9wZXJ0aWVzIGFyZSB0aGUgc2FtZSBhcyBmb3IgYGV4ZWNgIGNhbGwgZnJvbSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2FwcGl1bS9ub2RlLXRlZW5fcHJvY2Vzc31cbiAqIG1vZHVsZVxuICovXG5cbi8qKlxuICogRXhlY3V0ZSB0aGUgZ2l2ZW4gY29tbWFuZCB1c2luZyBfYWRiIHNoZWxsXyBwcmVmaXguXG4gKlxuICogQHBhcmFtIHshQXJyYXkuPHN0cmluZz58c3RyaW5nfSBjbWQgLSBUaGUgYXJyYXkgb2YgcmVzdCBjb21tYW5kIGxpbmUgcGFyYW1ldGVycyBvciBhIHNpbmdsZVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZyBwYXJhbWV0ZXIuXG4gKiBAcGFyYW0gez9TaGVsbEV4ZWNPcHRpb25zfSBvcHRzIFt7fV0gLSBBZGRpdGlvbmFsIG9wdGlvbnMgbWFwcGluZy5cbiAqIEByZXR1cm4ge3N0cmluZ30gLSBDb21tYW5kJ3Mgc3Rkb3V0LlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBjb21tYW5kIHJldHVybmVkIG5vbi16ZXJvIGV4aXQgY29kZS5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuc2hlbGwgPSBhc3luYyBmdW5jdGlvbiBzaGVsbCAoY21kLCBvcHRzID0ge30pIHtcbiAgY29uc3Qge1xuICAgIHByaXZpbGVnZWQsXG4gICAga2VlcFByaXZpbGVnZWQsXG4gIH0gPSBvcHRzO1xuXG4gIC8vIElmIHRoZSBjb21tYW5kIHJlcXVpcmVzIHByaXZpbGVnZXMsIHJvb3QgdGhpcyBkZXZpY2VcbiAgbGV0IHNob3VsZFJlc3RvcmVVc2VyID0gZmFsc2U7XG4gIGlmIChwcml2aWxlZ2VkKSB7XG4gICAgbG9nLmluZm8oYCdhZGIgc2hlbGwgJHtjbWR9JyByZXF1aXJlcyByb290IGFjY2Vzcy4gQXR0ZW1wdGluZyB0byBnYWluIHJvb3QgYWNjZXNzIG5vdy5gKTtcbiAgICBjb25zdCB7d2FzQWxyZWFkeVJvb3RlZCwgaXNTdWNjZXNzZnVsfSA9IGF3YWl0IHRoaXMucm9vdCgpO1xuICAgIHNob3VsZFJlc3RvcmVVc2VyID0gIXdhc0FscmVhZHlSb290ZWQ7XG4gICAgaWYgKHdhc0FscmVhZHlSb290ZWQpIHtcbiAgICAgIGxvZy5pbmZvKCdEZXZpY2UgYWxyZWFkeSBoYWQgcm9vdCBhY2Nlc3MnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nLmluZm8oaXNTdWNjZXNzZnVsID8gJ1Jvb3QgYWNjZXNzIHN1Y2Nlc3NmdWxseSBnYWluZWQnIDogJ0NvdWxkIG5vdCBnYWluIHJvb3QgYWNjZXNzJyk7XG4gICAgfVxuICB9XG4gIGxldCBkaWRDb21tYW5kRmFpbCA9IGZhbHNlO1xuICB0cnkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5hZGJFeGVjKF8uaXNBcnJheShjbWQpID8gWydzaGVsbCcsIC4uLmNtZF0gOiBbJ3NoZWxsJywgY21kXSwgb3B0cyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBkaWRDb21tYW5kRmFpbCA9IHRydWU7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIC8vIFJldHVybiB0aGUgJ3Jvb3QnIHN0YXRlIHRvIHdoYXQgaXQgd2FzIGJlZm9yZSAnc2hlbGwnIHdhcyBjYWxsZWRcbiAgICBpZiAocHJpdmlsZWdlZCAmJiBzaG91bGRSZXN0b3JlVXNlciAmJiAoIWtlZXBQcml2aWxlZ2VkIHx8IGRpZENvbW1hbmRGYWlsKSkge1xuICAgICAgY29uc3Qge2lzU3VjY2Vzc2Z1bH0gPSBhd2FpdCB0aGlzLnVucm9vdCgpO1xuICAgICAgbG9nLmRlYnVnKGlzU3VjY2Vzc2Z1bCA/ICdSZXR1cm5lZCBkZXZpY2UgdG8gdW5yb290ZWQgc3RhdGUnIDogJ0NvdWxkIG5vdCByZXR1cm4gZGV2aWNlIHRvIHVucm9vdGVkIHN0YXRlJyk7XG4gICAgfVxuICB9XG59O1xuXG5zeXN0ZW1DYWxsTWV0aG9kcy5jcmVhdGVTdWJQcm9jZXNzID0gZnVuY3Rpb24gY3JlYXRlU3ViUHJvY2VzcyAoYXJncyA9IFtdKSB7XG4gIC8vIGFkZCB0aGUgZGVmYXVsdCBhcmd1bWVudHNcbiAgYXJncyA9IHRoaXMuZXhlY3V0YWJsZS5kZWZhdWx0QXJncy5jb25jYXQoYXJncyk7XG4gIGxvZy5kZWJ1ZyhgQ3JlYXRpbmcgQURCIHN1YnByb2Nlc3Mgd2l0aCBhcmdzOiAke0pTT04uc3RyaW5naWZ5KGFyZ3MpfWApO1xuICByZXR1cm4gbmV3IFN1YlByb2Nlc3ModGhpcy5nZXRBZGJQYXRoKCksIGFyZ3MpO1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgY3VycmVudCBhZGIgcG9ydC5cbiAqIEB0b2RvIGNhbiBwcm9iYWJseSBkZXByZWNhdGUgdGhpcyBub3cgdGhhdCB0aGUgbG9naWMgaXMganVzdCB0byByZWFkIHRoaXMuYWRiUG9ydFxuICogQHJldHVybiB7bnVtYmVyfSBUaGUgY3VycmVudCBhZGIgcG9ydCBudW1iZXIuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmdldEFkYlNlcnZlclBvcnQgPSBmdW5jdGlvbiBnZXRBZGJTZXJ2ZXJQb3J0ICgpIHtcbiAgcmV0dXJuIHRoaXMuYWRiUG9ydDtcbn07XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIGN1cnJlbnQgZW11bGF0b3IgcG9ydCBmcm9tIF9hZGIgZGV2aXZlc18gb3V0cHV0LlxuICpcbiAqIEByZXR1cm4ge251bWJlcn0gVGhlIGN1cnJlbnQgZW11bGF0b3IgcG9ydC5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGVyZSBhcmUgbm8gY29ubmVjdGVkIGRldmljZXMuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmdldEVtdWxhdG9yUG9ydCA9IGFzeW5jIGZ1bmN0aW9uIGdldEVtdWxhdG9yUG9ydCAoKSB7XG4gIGxvZy5kZWJ1ZygnR2V0dGluZyBydW5uaW5nIGVtdWxhdG9yIHBvcnQnKTtcbiAgaWYgKHRoaXMuZW11bGF0b3JQb3J0ICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIHRoaXMuZW11bGF0b3JQb3J0O1xuICB9XG4gIHRyeSB7XG4gICAgbGV0IGRldmljZXMgPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZERldmljZXMoKTtcbiAgICBsZXQgcG9ydCA9IHRoaXMuZ2V0UG9ydEZyb21FbXVsYXRvclN0cmluZyhkZXZpY2VzWzBdLnVkaWQpO1xuICAgIGlmIChwb3J0KSB7XG4gICAgICByZXR1cm4gcG9ydDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFbXVsYXRvciBwb3J0IG5vdCBmb3VuZGApO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgTm8gZGV2aWNlcyBjb25uZWN0ZWQuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgY3VycmVudCBlbXVsYXRvciBwb3J0IGJ5IHBhcnNpbmcgZW11bGF0b3IgbmFtZSBzdHJpbmcuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGVtU3RyIC0gRW11bGF0b3IgbmFtZSBzdHJpbmcuXG4gKiBAcmV0dXJuIHtudW1iZXJ8Ym9vbGVhbn0gRWl0aGVyIHRoZSBjdXJyZW50IGVtdWxhdG9yIHBvcnQgb3JcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBfZmFsc2VfIGlmIHBvcnQgbnVtYmVyIGNhbm5vdCBiZSBwYXJzZWQuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmdldFBvcnRGcm9tRW11bGF0b3JTdHJpbmcgPSBmdW5jdGlvbiBnZXRQb3J0RnJvbUVtdWxhdG9yU3RyaW5nIChlbVN0cikge1xuICBsZXQgcG9ydFBhdHRlcm4gPSAvZW11bGF0b3ItKFxcZCspLztcbiAgaWYgKHBvcnRQYXR0ZXJuLnRlc3QoZW1TdHIpKSB7XG4gICAgcmV0dXJuIHBhcnNlSW50KHBvcnRQYXR0ZXJuLmV4ZWMoZW1TdHIpWzFdLCAxMCk7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgbGlzdCBvZiBjdXJyZW50bHkgY29ubmVjdGVkIGVtdWxhdG9ycy5cbiAqXG4gKiBAcmV0dXJuIHtBcnJheS48RGV2aWNlPn0gVGhlIGxpc3Qgb2YgY29ubmVjdGVkIGRldmljZXMuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmdldENvbm5lY3RlZEVtdWxhdG9ycyA9IGFzeW5jIGZ1bmN0aW9uIGdldENvbm5lY3RlZEVtdWxhdG9ycyAoKSB7XG4gIGxvZy5kZWJ1ZygnR2V0dGluZyBjb25uZWN0ZWQgZW11bGF0b3JzJyk7XG4gIHRyeSB7XG4gICAgbGV0IGRldmljZXMgPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZERldmljZXMoKTtcbiAgICBsZXQgZW11bGF0b3JzID0gW107XG4gICAgZm9yIChsZXQgZGV2aWNlIG9mIGRldmljZXMpIHtcbiAgICAgIGxldCBwb3J0ID0gdGhpcy5nZXRQb3J0RnJvbUVtdWxhdG9yU3RyaW5nKGRldmljZS51ZGlkKTtcbiAgICAgIGlmIChwb3J0KSB7XG4gICAgICAgIGRldmljZS5wb3J0ID0gcG9ydDtcbiAgICAgICAgZW11bGF0b3JzLnB1c2goZGV2aWNlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgbG9nLmRlYnVnKGAke3V0aWwucGx1cmFsaXplKCdlbXVsYXRvcicsIGVtdWxhdG9ycy5sZW5ndGgsIHRydWUpfSBjb25uZWN0ZWRgKTtcbiAgICByZXR1cm4gZW11bGF0b3JzO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciBnZXR0aW5nIGVtdWxhdG9ycy4gT3JpZ2luYWwgZXJyb3I6ICR7ZS5tZXNzYWdlfWApO1xuICB9XG59O1xuXG4vKipcbiAqIFNldCBfZW11bGF0b3JQb3J0XyBwcm9wZXJ0eSBvZiB0aGUgY3VycmVudCBjbGFzcy5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gZW1Qb3J0IC0gVGhlIGVtdWxhdG9yIHBvcnQgdG8gYmUgc2V0LlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5zZXRFbXVsYXRvclBvcnQgPSBmdW5jdGlvbiBzZXRFbXVsYXRvclBvcnQgKGVtUG9ydCkge1xuICB0aGlzLmVtdWxhdG9yUG9ydCA9IGVtUG9ydDtcbn07XG5cbi8qKlxuICogU2V0IHRoZSBpZGVudGlmaWVyIG9mIHRoZSBjdXJyZW50IGRldmljZSAoX3RoaXMuY3VyRGV2aWNlSWRfKS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gLSBUaGUgZGV2aWNlIGlkZW50aWZpZXIuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLnNldERldmljZUlkID0gZnVuY3Rpb24gc2V0RGV2aWNlSWQgKGRldmljZUlkKSB7XG4gIGxvZy5kZWJ1ZyhgU2V0dGluZyBkZXZpY2UgaWQgdG8gJHtkZXZpY2VJZH1gKTtcbiAgdGhpcy5jdXJEZXZpY2VJZCA9IGRldmljZUlkO1xuICBsZXQgYXJnc0hhc0RldmljZSA9IHRoaXMuZXhlY3V0YWJsZS5kZWZhdWx0QXJncy5pbmRleE9mKCctcycpO1xuICBpZiAoYXJnc0hhc0RldmljZSAhPT0gLTEpIHtcbiAgICAvLyByZW1vdmUgdGhlIG9sZCBkZXZpY2UgaWQgZnJvbSB0aGUgYXJndW1lbnRzXG4gICAgdGhpcy5leGVjdXRhYmxlLmRlZmF1bHRBcmdzLnNwbGljZShhcmdzSGFzRGV2aWNlLCAyKTtcbiAgfVxuICB0aGlzLmV4ZWN1dGFibGUuZGVmYXVsdEFyZ3MucHVzaCgnLXMnLCBkZXZpY2VJZCk7XG59O1xuXG4vKipcbiAqIFNldCB0aGUgdGhlIGN1cnJlbnQgZGV2aWNlIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge0RldmljZX0gZGV2aWNlT2JqIC0gVGhlIGRldmljZSBvYmplY3QgdG8gYmUgc2V0LlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5zZXREZXZpY2UgPSBmdW5jdGlvbiBzZXREZXZpY2UgKGRldmljZU9iaikge1xuICBsZXQgZGV2aWNlSWQgPSBkZXZpY2VPYmoudWRpZDtcbiAgbGV0IGVtUG9ydCA9IHRoaXMuZ2V0UG9ydEZyb21FbXVsYXRvclN0cmluZyhkZXZpY2VJZCk7XG4gIHRoaXMuc2V0RW11bGF0b3JQb3J0KGVtUG9ydCk7XG4gIHRoaXMuc2V0RGV2aWNlSWQoZGV2aWNlSWQpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIG9iamVjdCBmb3IgdGhlIGN1cnJlbnRseSBydW5uaW5nIGVtdWxhdG9yLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhdmROYW1lIC0gRW11bGF0b3IgbmFtZS5cbiAqIEByZXR1cm4gez9EZXZpY2V9IEN1cnJlbnRseSBydW5uaW5nIGVtdWxhdG9yIG9yIF9udWxsXy5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZ2V0UnVubmluZ0FWRCA9IGFzeW5jIGZ1bmN0aW9uIGdldFJ1bm5pbmdBVkQgKGF2ZE5hbWUpIHtcbiAgbG9nLmRlYnVnKGBUcnlpbmcgdG8gZmluZCAnJHthdmROYW1lfScgZW11bGF0b3JgKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBlbXVsYXRvcnMgPSBhd2FpdCB0aGlzLmdldENvbm5lY3RlZEVtdWxhdG9ycygpO1xuICAgIGZvciAoY29uc3QgZW11bGF0b3Igb2YgZW11bGF0b3JzKSB7XG4gICAgICB0aGlzLnNldEVtdWxhdG9yUG9ydChlbXVsYXRvci5wb3J0KTtcbiAgICAgIGNvbnN0IHJ1bm5pbmdBVkROYW1lID0gYXdhaXQgdGhpcy5zZW5kVGVsbmV0Q29tbWFuZCgnYXZkIG5hbWUnKTtcbiAgICAgIGlmIChfLnRvTG93ZXIoYXZkTmFtZSkgPT09IF8udG9Mb3dlcihydW5uaW5nQVZETmFtZSkpIHtcbiAgICAgICAgbG9nLmRlYnVnKGBGb3VuZCBlbXVsYXRvciAnJHthdmROYW1lfScgb24gcG9ydCAke2VtdWxhdG9yLnBvcnR9YCk7XG4gICAgICAgIHRoaXMuc2V0RGV2aWNlSWQoZW11bGF0b3IudWRpZCk7XG4gICAgICAgIHJldHVybiBlbXVsYXRvcjtcbiAgICAgIH1cbiAgICB9XG4gICAgbG9nLmRlYnVnKGBFbXVsYXRvciAnJHthdmROYW1lfScgbm90IHJ1bm5pbmdgKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3IgZ2V0dGluZyBBVkQuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBHZXQgdGhlIG9iamVjdCBmb3IgdGhlIGN1cnJlbnRseSBydW5uaW5nIGVtdWxhdG9yLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBhdmROYW1lIC0gRW11bGF0b3IgbmFtZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB0aW1lb3V0TXMgWzIwMDAwXSAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiBtaWxsaXNlY29uZHNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvIHdhaXQgdW50aWwgYXQgbGVhc3Qgb25lIHJ1bm5pbmcgQVZEIG9iamVjdFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMgZGV0ZWN0ZWQuXG4gKiBAcmV0dXJuIHs/RGV2aWNlfSBDdXJyZW50bHkgcnVubmluZyBlbXVsYXRvciBvciBfbnVsbF8uXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgbm8gZGV2aWNlIGhhcyBiZWVuIGRldGVjdGVkIHdpdGhpbiB0aGUgdGltZW91dC5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZ2V0UnVubmluZ0FWRFdpdGhSZXRyeSA9IGFzeW5jIGZ1bmN0aW9uIGdldFJ1bm5pbmdBVkRXaXRoUmV0cnkgKGF2ZE5hbWUsIHRpbWVvdXRNcyA9IDIwMDAwKSB7XG4gIGxldCBydW5uaW5nQXZkO1xuICB0cnkge1xuICAgIGF3YWl0IHdhaXRGb3JDb25kaXRpb24oYXN5bmMgKCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcnVubmluZ0F2ZCA9IGF3YWl0IHRoaXMuZ2V0UnVubmluZ0FWRChhdmROYW1lLnJlcGxhY2UoJ0AnLCAnJykpO1xuICAgICAgICByZXR1cm4gcnVubmluZ0F2ZDtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbG9nLmRlYnVnKGUubWVzc2FnZSk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICB3YWl0TXM6IHRpbWVvdXRNcyxcbiAgICAgIGludGVydmFsTXM6IDEwMDAsXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgQVZEIHdpdGggcmV0cnkuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxuICByZXR1cm4gcnVubmluZ0F2ZDtcbn07XG5cbi8qKlxuICogU2h1dGRvd24gYWxsIHJ1bm5pbmcgZW11bGF0b3JzIGJ5IGtpbGxpbmcgdGhlaXIgcHJvY2Vzc2VzLlxuICpcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBraWxsaW5nIHRvb2wgcmV0dXJuZWQgbm9uLXplcm8gcmV0dXJuIGNvZGUuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmtpbGxBbGxFbXVsYXRvcnMgPSBhc3luYyBmdW5jdGlvbiBraWxsQWxsRW11bGF0b3JzICgpIHtcbiAgbGV0IGNtZCwgYXJncztcbiAgaWYgKHN5c3RlbS5pc1dpbmRvd3MoKSkge1xuICAgIGNtZCA9ICdUQVNLS0lMTCc7XG4gICAgYXJncyA9IFsnVEFTS0tJTEwnLCAnL0lNJywgJ2VtdWxhdG9yLmV4ZSddO1xuICB9IGVsc2Uge1xuICAgIGNtZCA9ICcvdXNyL2Jpbi9raWxsYWxsJztcbiAgICBhcmdzID0gWyctbScsICdlbXVsYXRvcionXTtcbiAgfVxuICB0cnkge1xuICAgIGF3YWl0IGV4ZWMoY21kLCBhcmdzKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3Iga2lsbGluZyBlbXVsYXRvcnMuIE9yaWdpbmFsIGVycm9yOiAke2UubWVzc2FnZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBLaWxsIGVtdWxhdG9yIHdpdGggdGhlIGdpdmVuIG5hbWUuIE5vIGVycm9yXG4gKiBpcyB0aHJvd24gaXMgZ2l2ZW4gYXZkIGRvZXMgbm90IGV4aXN0L2lzIG5vdCBydW5uaW5nLlxuICpcbiAqIEBwYXJhbSB7P3N0cmluZ30gYXZkTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBlbXVsYXRvciB0byBiZSBraWxsZWQuIElmIGVtcHR5LFxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhlIGN1cnJlbnQgZW11bGF0b3Igd2lsbCBiZSBraWxsZWQuXG4gKiBAcGFyYW0gez9udW1iZXJ9IHRpbWVvdXQgWzYwMDAwXSAtIFRoZSBhbW91bnQgb2YgdGltZSB0byB3YWl0IGJlZm9yZSB0aHJvd2luZ1xuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbiBleGNlcHRpb24gYWJvdXQgdW5zdWNjZXNzZnVsIGtpbGxpbmdcbiAqIEByZXR1cm4ge2Jvb2xlYW59IC0gVHJ1ZSBpZiB0aGUgZW11bGF0b3Igd2FzIGtpbGxlZCwgZmFsc2Ugb3RoZXJ3aXNlLlxuICogQHRocm93cyB7RXJyb3J9IGlmIHRoZXJlIHdhcyBhIGZhaWx1cmUgYnkga2lsbGluZyB0aGUgZW11bGF0b3JcbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMua2lsbEVtdWxhdG9yID0gYXN5bmMgZnVuY3Rpb24ga2lsbEVtdWxhdG9yIChhdmROYW1lID0gbnVsbCwgdGltZW91dCA9IDYwMDAwKSB7XG4gIGlmICh1dGlsLmhhc1ZhbHVlKGF2ZE5hbWUpKSB7XG4gICAgbG9nLmRlYnVnKGBLaWxsaW5nIGF2ZCAnJHthdmROYW1lfSdgKTtcbiAgICBjb25zdCBkZXZpY2UgPSBhd2FpdCB0aGlzLmdldFJ1bm5pbmdBVkQoYXZkTmFtZSk7XG4gICAgaWYgKCFkZXZpY2UpIHtcbiAgICAgIGxvZy5pbmZvKGBObyBhdmQgd2l0aCBuYW1lICcke2F2ZE5hbWV9JyBydW5uaW5nLiBTa2lwcGluZyBraWxsIHN0ZXAuYCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIGtpbGxpbmcgdGhlIGN1cnJlbnQgYXZkXG4gICAgbG9nLmRlYnVnKGBLaWxsaW5nIGF2ZCB3aXRoIGlkICcke3RoaXMuY3VyRGV2aWNlSWR9J2ApO1xuICAgIGlmICghYXdhaXQgdGhpcy5pc0VtdWxhdG9yQ29ubmVjdGVkKCkpIHtcbiAgICAgIGxvZy5kZWJ1ZyhgRW11bGF0b3Igd2l0aCBpZCAnJHt0aGlzLmN1ckRldmljZUlkfScgbm90IGNvbm5lY3RlZC4gU2tpcHBpbmcga2lsbCBzdGVwYCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIGF3YWl0IHRoaXMuYWRiRXhlYyhbJ2VtdScsICdraWxsJ10pO1xuICBsb2cuZGVidWcoYFdhaXRpbmcgdXAgdG8gJHt0aW1lb3V0fW1zIHVudGlsIHRoZSBlbXVsYXRvciAnJHthdmROYW1lID8gYXZkTmFtZSA6IHRoaXMuY3VyRGV2aWNlSWR9JyBpcyBraWxsZWRgKTtcbiAgdHJ5IHtcbiAgICBhd2FpdCB3YWl0Rm9yQ29uZGl0aW9uKGFzeW5jICgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB1dGlsLmhhc1ZhbHVlKGF2ZE5hbWUpXG4gICAgICAgICAgPyAhYXdhaXQgdGhpcy5nZXRSdW5uaW5nQVZEKGF2ZE5hbWUpXG4gICAgICAgICAgOiAhYXdhaXQgdGhpcy5pc0VtdWxhdG9yQ29ubmVjdGVkKCk7XG4gICAgICB9IGNhdGNoIChpZ24pIHt9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSwge1xuICAgICAgd2FpdE1zOiB0aW1lb3V0LFxuICAgICAgaW50ZXJ2YWxNczogMjAwMCxcbiAgICB9KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVGhlIGVtdWxhdG9yICcke2F2ZE5hbWUgPyBhdmROYW1lIDogdGhpcy5jdXJEZXZpY2VJZH0nIGlzIHN0aWxsIHJ1bm5pbmcgYWZ0ZXIgYmVpbmcga2lsbGVkICR7dGltZW91dH1tcyBhZ29gKTtcbiAgfVxuICBsb2cuaW5mbyhgU3VjY2Vzc2Z1bGx5IGtpbGxlZCB0aGUgJyR7YXZkTmFtZSA/IGF2ZE5hbWUgOiB0aGlzLmN1ckRldmljZUlkfScgZW11bGF0b3JgKTtcbiAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIFN0YXJ0IGFuIGVtdWxhdG9yIHdpdGggZ2l2ZW4gcGFyYW1ldGVycyBhbmQgd2FpdCB1bnRpbCBpdCBpcyBmdWxsIHN0YXJ0ZWQuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGF2ZE5hbWUgLSBUaGUgbmFtZSBvZiBhbiBleGlzdGluZyBlbXVsYXRvci5cbiAqIEBwYXJhbSB7QXJyYXkuPHN0cmluZz58c3RyaW5nfSBhdmRBcmdzIC0gQWRkaXRpb25hbCBlbXVsYXRvciBjb21tYW5kIGxpbmUgYXJndW1lbnQuXG4gKiBAcGFyYW0gez9zdHJpbmd9IGxhbmd1YWdlIC0gRW11bGF0b3Igc3lzdGVtIGxhbmd1YWdlLlxuICogQHBhcmFtIHs/Y291bnRyeX0gY291bnRyeSAtIEVtdWxhdG9yIHN5c3RlbSBjb3VudHJ5LlxuICogQHBhcmFtIHtudW1iZXJ9IGF2ZExhdW5jaFRpbWVvdXQgWzYwMDAwXSAtIEVtdWxhdG9yIHN0YXJ0dXAgdGltZW91dCBpbiBtaWxsaXNlY29uZHMuXG4gKiBAcGFyYW0ge251bWJlcn0gcmV0cnlUaW1lcyBbMV0gLSBUaGUgbWF4aW11bSBudW1iZXIgb2Ygc3RhcnR1cCByZXRyaWVzLlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBlbXVsYXRvciBmYWlscyB0byBzdGFydCB3aXRoaW4gdGhlIGdpdmVuIHRpbWVvdXQuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmxhdW5jaEFWRCA9IGFzeW5jIGZ1bmN0aW9uIGxhdW5jaEFWRCAoYXZkTmFtZSwgYXZkQXJncywgbGFuZ3VhZ2UsIGNvdW50cnksXG4gIGF2ZExhdW5jaFRpbWVvdXQgPSA2MDAwMCwgYXZkUmVhZHlUaW1lb3V0ID0gNjAwMDAsIHJldHJ5VGltZXMgPSAxKSB7XG4gIGxvZy5kZWJ1ZyhgTGF1bmNoaW5nIEVtdWxhdG9yIHdpdGggQVZEICR7YXZkTmFtZX0sIGxhdW5jaFRpbWVvdXQgYCArXG4gICAgICAgICAgICBgJHthdmRMYXVuY2hUaW1lb3V0fW1zIGFuZCByZWFkeVRpbWVvdXQgJHthdmRSZWFkeVRpbWVvdXR9bXNgKTtcbiAgbGV0IGVtdWxhdG9yQmluYXJ5UGF0aCA9IGF3YWl0IHRoaXMuZ2V0U2RrQmluYXJ5UGF0aCgnZW11bGF0b3InKTtcbiAgaWYgKGF2ZE5hbWVbMF0gPT09ICdAJykge1xuICAgIGF2ZE5hbWUgPSBhdmROYW1lLnN1YnN0cigxKTtcbiAgfVxuICBhd2FpdCB0aGlzLmNoZWNrQXZkRXhpc3QoYXZkTmFtZSk7XG4gIGxldCBsYXVuY2hBcmdzID0gWyctYXZkJywgYXZkTmFtZV07XG4gIGlmIChfLmlzU3RyaW5nKGxhbmd1YWdlKSkge1xuICAgIGxvZy5kZWJ1ZyhgU2V0dGluZyBBbmRyb2lkIERldmljZSBMYW5ndWFnZSB0byAke2xhbmd1YWdlfWApO1xuICAgIGxhdW5jaEFyZ3MucHVzaCgnLXByb3AnLCBgcGVyc2lzdC5zeXMubGFuZ3VhZ2U9JHtsYW5ndWFnZS50b0xvd2VyQ2FzZSgpfWApO1xuICB9XG4gIGlmIChfLmlzU3RyaW5nKGNvdW50cnkpKSB7XG4gICAgbG9nLmRlYnVnKGBTZXR0aW5nIEFuZHJvaWQgRGV2aWNlIENvdW50cnkgdG8gJHtjb3VudHJ5fWApO1xuICAgIGxhdW5jaEFyZ3MucHVzaCgnLXByb3AnLCBgcGVyc2lzdC5zeXMuY291bnRyeT0ke2NvdW50cnkudG9VcHBlckNhc2UoKX1gKTtcbiAgfVxuICBsZXQgbG9jYWxlO1xuICBpZiAoXy5pc1N0cmluZyhsYW5ndWFnZSkgJiYgXy5pc1N0cmluZyhjb3VudHJ5KSkge1xuICAgIGxvY2FsZSA9IGxhbmd1YWdlLnRvTG93ZXJDYXNlKCkgKyAnLScgKyBjb3VudHJ5LnRvVXBwZXJDYXNlKCk7XG4gIH0gZWxzZSBpZiAoXy5pc1N0cmluZyhsYW5ndWFnZSkpIHtcbiAgICBsb2NhbGUgPSBsYW5ndWFnZS50b0xvd2VyQ2FzZSgpO1xuICB9IGVsc2UgaWYgKF8uaXNTdHJpbmcoY291bnRyeSkpIHtcbiAgICBsb2NhbGUgPSBjb3VudHJ5O1xuICB9XG4gIGlmIChfLmlzU3RyaW5nKGxvY2FsZSkpIHtcbiAgICBsb2cuZGVidWcoYFNldHRpbmcgQW5kcm9pZCBEZXZpY2UgTG9jYWxlIHRvICR7bG9jYWxlfWApO1xuICAgIGxhdW5jaEFyZ3MucHVzaCgnLXByb3AnLCBgcGVyc2lzdC5zeXMubG9jYWxlPSR7bG9jYWxlfWApO1xuICB9XG4gIGlmICghXy5pc0VtcHR5KGF2ZEFyZ3MpKSB7XG4gICAgbGF1bmNoQXJncy5wdXNoKC4uLihfLmlzQXJyYXkoYXZkQXJncykgPyBhdmRBcmdzIDogYXZkQXJncy5zcGxpdCgnICcpKSk7XG4gIH1cbiAgbG9nLmRlYnVnKGBSdW5uaW5nICcke2VtdWxhdG9yQmluYXJ5UGF0aH0nIHdpdGggYXJnczogJHtKU09OLnN0cmluZ2lmeShsYXVuY2hBcmdzKX1gKTtcbiAgbGV0IHByb2MgPSBuZXcgU3ViUHJvY2VzcyhlbXVsYXRvckJpbmFyeVBhdGgsIGxhdW5jaEFyZ3MpO1xuICBhd2FpdCBwcm9jLnN0YXJ0KDApO1xuICBwcm9jLm9uKCdvdXRwdXQnLCAoc3Rkb3V0LCBzdGRlcnIpID0+IHtcbiAgICBmb3IgKGxldCBsaW5lIG9mIChzdGRvdXQgfHwgc3RkZXJyIHx8ICcnKS5zcGxpdCgnXFxuJykuZmlsdGVyKEJvb2xlYW4pKSB7XG4gICAgICBsb2cuaW5mbyhgW0FWRCBPVVRQVVRdICR7bGluZX1gKTtcbiAgICB9XG4gIH0pO1xuICBwcm9jLm9uKCdkaWUnLCAoY29kZSwgc2lnbmFsKSA9PiB7XG4gICAgbG9nLndhcm4oYEVtdWxhdG9yIGF2ZCAke2F2ZE5hbWV9IGV4aXRlZCB3aXRoIGNvZGUgJHtjb2RlfSR7c2lnbmFsID8gYCwgc2lnbmFsICR7c2lnbmFsfWAgOiAnJ31gKTtcbiAgfSk7XG4gIGF3YWl0IHJldHJ5KHJldHJ5VGltZXMsIGFzeW5jICgpID0+IGF3YWl0IHRoaXMuZ2V0UnVubmluZ0FWRFdpdGhSZXRyeShhdmROYW1lLCBhdmRMYXVuY2hUaW1lb3V0KSk7XG4gIGF3YWl0IHRoaXMud2FpdEZvckVtdWxhdG9yUmVhZHkoYXZkUmVhZHlUaW1lb3V0KTtcbiAgcmV0dXJuIHByb2M7XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEFEQlZlcnNpb25cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSB2ZXJzaW9uU3RyaW5nIC0gQURCIHZlcnNpb24gYXMgYSBzdHJpbmcuXG4gKiBAcHJvcGVydHkge2Zsb2F0fSB2ZXJzaW9uRmxvYXQgLSBWZXJzaW9uIG51bWJlciBhcyBmbG9hdCB2YWx1ZSAodXNlZnVsIGZvciBjb21wYXJpc29uKS5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBtYWpvciAtIE1ham9yIHZlcnNpb24gbnVtYmVyLlxuICogQHByb3BlcnR5IHtudW1iZXJ9IG1pbm9yIC0gTWlub3IgdmVyc2lvbiBudW1iZXIuXG4gKiBAcHJvcGVydHkge251bWJlcn0gcGF0Y2ggLSBQYXRjaCB2ZXJzaW9uIG51bWJlci5cbiAqL1xuXG4vKipcbiAqIEdldCB0aGUgYWRiIHZlcnNpb24uIFRoZSByZXN1bHQgb2YgdGhpcyBtZXRob2QgaXMgY2FjaGVkLlxuICpcbiAqIEByZXR1cm4ge0FEQlZlcnNpb259IFRoZSBjdXJyZW50IGFkYiB2ZXJzaW9uLlxuICogQHRocm93cyB7RXJyb3J9IElmIGl0IGlzIG5vdCBwb3NzaWJsZSB0byBwYXJzZSBhZGIgdmVyc2lvbi5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZ2V0QWRiVmVyc2lvbiA9IF8ubWVtb2l6ZShhc3luYyBmdW5jdGlvbiBnZXRBZGJWZXJzaW9uICgpIHtcbiAgdHJ5IHtcbiAgICBsZXQgYWRiVmVyc2lvbiA9IChhd2FpdCB0aGlzLmFkYkV4ZWMoJ3ZlcnNpb24nKSlcbiAgICAgIC5yZXBsYWNlKC9BbmRyb2lkXFxzRGVidWdcXHNCcmlkZ2VcXHN2ZXJzaW9uXFxzKFtcXGQuXSopW1xcc1xcdy1dKi8sICckMScpO1xuICAgIGxldCBwYXJ0cyA9IGFkYlZlcnNpb24uc3BsaXQoJy4nKTtcbiAgICByZXR1cm4ge1xuICAgICAgdmVyc2lvblN0cmluZzogYWRiVmVyc2lvbixcbiAgICAgIHZlcnNpb25GbG9hdDogcGFyc2VGbG9hdChhZGJWZXJzaW9uKSxcbiAgICAgIG1ham9yOiBwYXJzZUludChwYXJ0c1swXSwgMTApLFxuICAgICAgbWlub3I6IHBhcnNlSW50KHBhcnRzWzFdLCAxMCksXG4gICAgICBwYXRjaDogcGFydHNbMl0gPyBwYXJzZUludChwYXJ0c1syXSwgMTApIDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGdldHRpbmcgYWRiIHZlcnNpb24uIE9yaWdpbmFsIGVycm9yOiAnJHtlLm1lc3NhZ2V9JzsgYCArXG4gICAgICAgICAgICAgICAgICAgICAgICBgU3RkZXJyOiAnJHsoZS5zdGRlcnIgfHwgJycpLnRyaW0oKX0nOyBDb2RlOiAnJHtlLmNvZGV9J2ApO1xuICB9XG59KTtcblxuLyoqXG4gKiBDaGVjayBpZiBnaXZlbiBlbXVsYXRvciBleGlzdHMgaW4gdGhlIGxpc3Qgb2YgYXZhaWxhYmxlIGF2ZHMuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGF2ZE5hbWUgLSBUaGUgbmFtZSBvZiBlbXVsYXRvciB0byB2ZXJpZnkgZm9yIGV4aXN0ZW5jZS5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZW11bGF0b3Igd2l0aCBnaXZlbiBuYW1lIGRvZXMgbm90IGV4aXN0LlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5jaGVja0F2ZEV4aXN0ID0gYXN5bmMgZnVuY3Rpb24gY2hlY2tBdmRFeGlzdCAoYXZkTmFtZSkge1xuICBsZXQgY21kLCByZXN1bHQ7XG4gIHRyeSB7XG4gICAgY21kID0gYXdhaXQgdGhpcy5nZXRTZGtCaW5hcnlQYXRoKCdlbXVsYXRvcicpO1xuICAgIHJlc3VsdCA9IGF3YWl0IGV4ZWMoY21kLCBbJy1saXN0LWF2ZHMnXSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsZXQgdW5rbm93bk9wdGlvbkVycm9yID0gbmV3IFJlZ0V4cCgndW5rbm93biBvcHRpb246IC1saXN0LWF2ZHMnLCAnaScpLnRlc3QoZS5zdGRlcnIpO1xuICAgIGlmICghdW5rbm93bk9wdGlvbkVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVycm9yIGV4ZWN1dGluZyBjaGVja0F2ZEV4aXN0LiBPcmlnaW5hbCBlcnJvcjogJyR7ZS5tZXNzYWdlfSc7IGAgK1xuICAgICAgICAgICAgICAgICAgICAgIGBTdGRlcnI6ICckeyhlLnN0ZGVyciB8fCAnJykudHJpbSgpfSc7IENvZGU6ICcke2UuY29kZX0nYCk7XG5cbiAgICB9XG4gICAgY29uc3Qgc2RrVmVyc2lvbiA9IGF3YWl0IGdldFNka1Rvb2xzVmVyc2lvbigpO1xuICAgIGxldCBiaW5hcnlOYW1lID0gJ2FuZHJvaWQnO1xuICAgIGlmIChzZGtWZXJzaW9uKSB7XG4gICAgICBpZiAoc2RrVmVyc2lvbi5tYWpvciA+PSAyNSkge1xuICAgICAgICBiaW5hcnlOYW1lID0gJ2F2ZG1hbmFnZXInO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2cud2FybihgRGVmYXVsdGluZyBiaW5hcnkgbmFtZSB0byAnJHtiaW5hcnlOYW1lfScsIGJlY2F1c2UgU0RLIHZlcnNpb24gY2Fubm90IGJlIHBhcnNlZGApO1xuICAgIH1cbiAgICAvLyBJZiAtbGlzdC1hdmRzIG9wdGlvbiBpcyBub3QgYXZhaWxhYmxlLCB1c2UgYW5kcm9pZCBjb21tYW5kIGFzIGFuIGFsdGVybmF0aXZlXG4gICAgY21kID0gYXdhaXQgdGhpcy5nZXRTZGtCaW5hcnlQYXRoKGJpbmFyeU5hbWUpO1xuICAgIHJlc3VsdCA9IGF3YWl0IGV4ZWMoY21kLCBbJ2xpc3QnLCAnYXZkJywgJy1jJ10pO1xuICB9XG4gIGlmIChyZXN1bHQuc3Rkb3V0LmluZGV4T2YoYXZkTmFtZSkgPT09IC0xKSB7XG4gICAgbGV0IGV4aXN0aW5ncyA9IGAoJHtyZXN1bHQuc3Rkb3V0LnRyaW0oKS5yZXBsYWNlKC9bXFxuXS9nLCAnKSwgKCcpfSlgO1xuICAgIHRocm93IG5ldyBFcnJvcihgQXZkICcke2F2ZE5hbWV9JyBpcyBub3QgYXZhaWxhYmxlLiBwbGVhc2Ugc2VsZWN0IHlvdXIgYXZkIG5hbWUgZnJvbSBvbmUgb2YgdGhlc2U6ICcke2V4aXN0aW5nc30nYCk7XG4gIH1cbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGN1cnJlbnQgZW11bGF0b3IgaXMgcmVhZHkgdG8gYWNjZXB0IGZ1cnRoZXIgY29tbWFuZHMgKGJvb3RpbmcgY29tcGxldGVkKS5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gdGltZW91dE1zIFsyMDAwMF0gLSBUaGUgbWF4aW11bSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIHdhaXQuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIGVtdWxhdG9yIGlzIG5vdCByZWFkeSB3aXRoaW4gdGhlIGdpdmVuIHRpbWVvdXQuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLndhaXRGb3JFbXVsYXRvclJlYWR5ID0gYXN5bmMgZnVuY3Rpb24gd2FpdEZvckVtdWxhdG9yUmVhZHkgKHRpbWVvdXRNcyA9IDIwMDAwKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgd2FpdEZvckNvbmRpdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoIShhd2FpdCB0aGlzLnNoZWxsKFsnZ2V0cHJvcCcsICdpbml0LnN2Yy5ib290YW5pbSddKSkuaW5jbHVkZXMoJ3N0b3BwZWQnKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBTb21ldGltZXMgdGhlIHBhY2thZ2UgbWFuYWdlciBzZXJ2aWNlIG1pZ2h0IHN0aWxsIGJlaW5nIGluaXRpYWxpemVkXG4gICAgICAgIC8vIG9uIHNsb3cgc3lzdGVtcyBldmVuIGFmdGVyIGVtdWxhdG9yIGJvb3RpbmcgaXMgY29tcGxldGVkLlxuICAgICAgICAvLyBUaGUgdXN1YWwgb3V0cHV0IG9mIGBwbSBnZXQtaW5zdGFsbC1sb2NhdGlvbmAgY29tbWFuZCBsb29rcyBsaWtlIGAwW2F1dG9dYFxuICAgICAgICByZXR1cm4gL1xcZCtcXFtcXHcrXFxdLy50ZXN0KGF3YWl0IHRoaXMuc2hlbGwoWydwbScsICdnZXQtaW5zdGFsbC1sb2NhdGlvbiddKSk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nLmRlYnVnKGBXYWl0aW5nIGZvciBlbXVsYXRvciBzdGFydHVwLiBJbnRlcm1lZGlhdGUgZXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICB3YWl0TXM6IHRpbWVvdXRNcyxcbiAgICAgIGludGVydmFsTXM6IDMwMDAsXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYEVtdWxhdG9yIGlzIG5vdCByZWFkeSB3aXRoaW4gJHt0aW1lb3V0TXN9bXNgKTtcbiAgfVxufTtcblxuLyoqXG4gKiBDaGVjayBpZiB0aGUgY3VycmVudCBkZXZpY2UgaXMgcmVhZHkgdG8gYWNjZXB0IGZ1cnRoZXIgY29tbWFuZHMgKGJvb3RpbmcgY29tcGxldGVkKS5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gYXBwRGV2aWNlUmVhZHlUaW1lb3V0IFszMF0gLSBUaGUgbWF4aW11bSBudW1iZXIgb2Ygc2Vjb25kcyB0byB3YWl0LlxuICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBkZXZpY2UgaXMgbm90IHJlYWR5IHdpdGhpbiB0aGUgZ2l2ZW4gdGltZW91dC5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMud2FpdEZvckRldmljZSA9IGFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JEZXZpY2UgKGFwcERldmljZVJlYWR5VGltZW91dCA9IDMwKSB7XG4gIHRoaXMuYXBwRGV2aWNlUmVhZHlUaW1lb3V0ID0gYXBwRGV2aWNlUmVhZHlUaW1lb3V0O1xuICBjb25zdCByZXRyaWVzID0gMztcbiAgY29uc3QgdGltZW91dCA9IHBhcnNlSW50KHRoaXMuYXBwRGV2aWNlUmVhZHlUaW1lb3V0LCAxMCkgLyByZXRyaWVzICogMTAwMDtcbiAgYXdhaXQgcmV0cnkocmV0cmllcywgYXN5bmMgKCkgPT4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmFkYkV4ZWMoJ3dhaXQtZm9yLWRldmljZScsIHt0aW1lb3V0fSk7XG4gICAgICBhd2FpdCB0aGlzLnBpbmcoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlc3RhcnRBZGIoKTtcbiAgICAgIGF3YWl0IHRoaXMuZ2V0Q29ubmVjdGVkRGV2aWNlcygpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcnJvciB3YWl0aW5nIGZvciB0aGUgZGV2aWNlIHRvIGJlIGF2YWlsYWJsZS4gT3JpZ2luYWwgZXJyb3I6ICcke2UubWVzc2FnZX0nYCk7XG4gICAgfVxuICB9KTtcbn07XG5cbi8qKlxuICogUmVib290IHRoZSBjdXJyZW50IGRldmljZSBhbmQgd2FpdCB1bnRpbCBpdCBpcyBjb21wbGV0ZWQuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHJldHJpZXMgW0RFRkFVTFRfQURCX1JFQk9PVF9SRVRSSUVTXSAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiByZWJvb3QgcmV0cmllcy5cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgZGV2aWNlIGZhaWxlZCB0byByZWJvb3QgYW5kIG51bWJlciBvZiByZXRyaWVzIGlzIGV4Y2VlZGVkLlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5yZWJvb3QgPSBhc3luYyBmdW5jdGlvbiByZWJvb3QgKHJldHJpZXMgPSBERUZBVUxUX0FEQl9SRUJPT1RfUkVUUklFUykge1xuICAvLyBHZXQgcm9vdCBhY2Nlc3Mgc28gd2UgY2FuIHJ1biB0aGUgbmV4dCBzaGVsbCBjb21tYW5kcyB3aGljaCByZXF1aXJlIHJvb3QgYWNjZXNzXG4gIGNvbnN0IHsgd2FzQWxyZWFkeVJvb3RlZCB9ID0gYXdhaXQgdGhpcy5yb290KCk7XG4gIHRyeSB7XG4gICAgLy8gU3RvcCBhbmQgcmUtc3RhcnQgdGhlIGRldmljZVxuICAgIGF3YWl0IHRoaXMuc2hlbGwoWydzdG9wJ10pO1xuICAgIGF3YWl0IEIuZGVsYXkoMjAwMCk7IC8vIGxldCB0aGUgZW11IGZpbmlzaCBzdG9wcGluZztcbiAgICBhd2FpdCB0aGlzLnNldERldmljZVByb3BlcnR5KCdzeXMuYm9vdF9jb21wbGV0ZWQnLCAwLCB7XG4gICAgICBwcml2aWxlZ2VkOiBmYWxzZSAvLyBubyBuZWVkIHRvIHNldCBwcml2aWxlZ2VkIHRydWUgYmVjYXVzZSBkZXZpY2UgYWxyZWFkeSByb290ZWRcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLnNoZWxsKFsnc3RhcnQnXSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zdCB7bWVzc2FnZX0gPSBlO1xuXG4gICAgLy8gcHJvdmlkZSBhIGhlbHBmdWwgZXJyb3IgbWVzc2FnZSBpZiB0aGUgcmVhc29uIHJlYm9vdCBmYWlsZWQgd2FzIGJlY2F1c2UgQURCIGNvdWxkbid0IGdhaW4gcm9vdCBhY2Nlc3NcbiAgICBpZiAobWVzc2FnZS5pbmNsdWRlcygnbXVzdCBiZSByb290JykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ291bGQgbm90IHJlYm9vdCBkZXZpY2UuIFJlYm9vdGluZyByZXF1aXJlcyByb290IGFjY2VzcyBhbmQgYCArXG4gICAgICAgIGBhdHRlbXB0IHRvIGdldCByb290IGFjY2VzcyBvbiBkZXZpY2UgZmFpbGVkIHdpdGggZXJyb3I6ICcke21lc3NhZ2V9J2ApO1xuICAgIH1cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIC8vIFJldHVybiByb290IHN0YXRlIHRvIHdoYXQgaXQgd2FzIGJlZm9yZVxuICAgIGlmICghd2FzQWxyZWFkeVJvb3RlZCkge1xuICAgICAgYXdhaXQgdGhpcy51bnJvb3QoKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgdGltZXIgPSBuZXcgdGltaW5nLlRpbWVyKCkuc3RhcnQoKTtcbiAgYXdhaXQgcmV0cnlJbnRlcnZhbChyZXRyaWVzLCAxMDAwLCBhc3luYyAoKSA9PiB7XG4gICAgaWYgKChhd2FpdCB0aGlzLmdldERldmljZVByb3BlcnR5KCdzeXMuYm9vdF9jb21wbGV0ZWQnKSkgPT09ICcxJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyB3ZSBkb24ndCB3YW50IHRoZSBzdGFjayB0cmFjZSwgc28gbm8gbG9nLmVycm9yQW5kVGhyb3dcbiAgICBjb25zdCBtc2cgPSBgUmVib290IGlzIG5vdCBjb21wbGV0ZWQgYWZ0ZXIgJHt0aW1lci5nZXREdXJhdGlvbigpLmFzTWlsbGlTZWNvbmRzLnRvRml4ZWQoMCl9bXNgO1xuICAgIGxvZy5kZWJ1Zyhtc2cpO1xuICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICB9KTtcbn07XG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gcm9vdFJlc3VsdFxuICogQHByb3BlcnR5IHtib29sZWFufSBpc1N1Y2Nlc3NmdWwgVHJ1ZSBpZiB0aGUgY2FsbCB0byByb290L3Vucm9vdCB3YXMgc3VjY2Vzc2Z1bFxuICogQHByb3BlcnR5IHtib29sZWFufSB3YXNBbHJlYWR5Um9vdGVkIFRydWUgaWYgdGhlIGRldmljZSB3YXMgYWxyZWFkeSByb290ZWRcbiAqL1xuXG4vKipcbiAqIFN3aXRjaCBhZGIgc2VydmVyIHJvb3QgcHJpdmlsZWdlcy5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNFbGV2YXRlZCAtIFNob3VsZCB3ZSBlbGV2YXRlIHRvIHRvIHJvb3Qgb3IgdW5yb290PyAoZGVmYXVsdCB0cnVlKVxuICogQHJldHVybiB7cm9vdFJlc3VsdH1cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuY2hhbmdlVXNlclByaXZpbGVnZXMgPSBhc3luYyBmdW5jdGlvbiBjaGFuZ2VVc2VyUHJpdmlsZWdlcyAoaXNFbGV2YXRlZCkge1xuICBjb25zdCBjbWQgPSBpc0VsZXZhdGVkID8gJ3Jvb3QnIDogJ3Vucm9vdCc7XG5cbiAgLy8gSWYgaXQncyBhbHJlYWR5IHJvb3RlZCwgb3VyIGpvYiBpcyBkb25lLiBObyBuZWVkIHRvIHJvb3QgaXQgYWdhaW4uXG4gIGNvbnN0IGlzUm9vdCA9IGF3YWl0IHRoaXMuaXNSb290KCk7XG4gIGlmICgoaXNSb290ICYmIGlzRWxldmF0ZWQpIHx8ICghaXNSb290ICYmICFpc0VsZXZhdGVkKSkge1xuICAgIHJldHVybiB7aXNTdWNjZXNzZnVsOiB0cnVlLCB3YXNBbHJlYWR5Um9vdGVkOiBpc1Jvb3R9O1xuICB9XG5cbiAgbGV0IHdhc0FscmVhZHlSb290ZWQgPSBpc1Jvb3Q7XG4gIHRyeSB7XG4gICAgbGV0IHtzdGRvdXR9ID0gYXdhaXQgdGhpcy5hZGJFeGVjKFtjbWRdKTtcblxuICAgIC8vIG9uIHJlYWwgZGV2aWNlcyBpbiBzb21lIHNpdHVhdGlvbnMgd2UgZ2V0IGFuIGVycm9yIGluIHRoZSBzdGRvdXRcbiAgICBpZiAoc3Rkb3V0KSB7XG4gICAgICBpZiAoc3Rkb3V0LmluY2x1ZGVzKCdhZGJkIGNhbm5vdCBydW4gYXMgcm9vdCcpKSB7XG4gICAgICAgIHJldHVybiB7aXNTdWNjZXNzZnVsOiBmYWxzZSwgd2FzQWxyZWFkeVJvb3RlZH07XG4gICAgICB9XG4gICAgICAvLyBpZiB0aGUgZGV2aWNlIHdhcyBhbHJlYWR5IHJvb3RlZCwgcmV0dXJuIHRoYXQgaW4gdGhlIHJlc3VsdFxuICAgICAgaWYgKHN0ZG91dC5pbmNsdWRlcygnYWxyZWFkeSBydW5uaW5nIGFzIHJvb3QnKSkge1xuICAgICAgICB3YXNBbHJlYWR5Um9vdGVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtpc1N1Y2Nlc3NmdWw6IHRydWUsIHdhc0FscmVhZHlSb290ZWR9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zdCB7c3RkZXJyID0gJycsIG1lc3NhZ2V9ID0gZXJyO1xuICAgIGxvZy53YXJuKGBVbmFibGUgdG8gJHtjbWR9IGFkYiBkYWVtb24uIE9yaWdpbmFsIGVycm9yOiAnJHttZXNzYWdlfScuIFN0ZGVycjogJyR7c3RkZXJyfScuIENvbnRpbnVpbmcuYCk7XG5cbiAgICAvLyBDaGVjayB0aGUgb3V0cHV0IG9mIHRoZSBzdGRFcnIgdG8gc2VlIGlmIHRoZXJlJ3MgYW55IGNsdWVzIHRoYXQgc2hvdyB0aGF0IHRoZSBkZXZpY2Ugd2VudCBvZmZsaW5lXG4gICAgLy8gYW5kIGlmIGl0IGRpZCBnbyBvZmZsaW5lLCByZXN0YXJ0IEFEQlxuICAgIGlmIChbJ2Nsb3NlZCcsICdkZXZpY2Ugb2ZmbGluZScsICd0aW1lb3V0IGV4cGlyZWQnXS5zb21lKCh4KSA9PiBzdGRlcnIudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh4KSkpIHtcbiAgICAgIGxvZy53YXJuKGBBdHRlbXB0IHRvICdhZGIgJHtjbWR9JyBjYXVzZWQgZGV2aWNlIHRvIGdvIG9mZmxpbmUuIFJlc3RhcnRpbmcgYWRiLmApO1xuICAgICAgYXdhaXQgdGhpcy5yZXN0YXJ0QWRiKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtpc1N1Y2Nlc3NmdWw6IGZhbHNlLCB3YXNBbHJlYWR5Um9vdGVkfTtcbiAgfVxufTtcblxuLyoqXG4gKiBTd2l0Y2ggYWRiIHNlcnZlciB0byByb290IG1vZGVcbiAqIEByZXR1cm4ge3Jvb3RSZXN1bHR9XG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLnJvb3QgPSBhc3luYyBmdW5jdGlvbiByb290ICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuY2hhbmdlVXNlclByaXZpbGVnZXModHJ1ZSk7XG59O1xuXG4vKipcbiAqIFN3aXRjaCBhZGIgc2VydmVyIHRvIG5vbi1yb290IG1vZGUuXG4gKlxuICogQHJldHVybiB7cm9vdFJlc3VsdH1cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMudW5yb290ID0gYXN5bmMgZnVuY3Rpb24gdW5yb290ICgpIHtcbiAgcmV0dXJuIGF3YWl0IHRoaXMuY2hhbmdlVXNlclByaXZpbGVnZXMoZmFsc2UpO1xufTtcblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciB0aGUgY3VycmVudCB1c2VyIGlzIHJvb3RcbiAqXG4gKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIHRoZSB1c2VyIGlzIHJvb3RcbiAqIEB0aHJvd3Mge0Vycm9yfSBpZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgaWRlbnRpZnlpbmdcbiAqIHRoZSB1c2VyLlxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5pc1Jvb3QgPSBhc3luYyBmdW5jdGlvbiBpc1Jvb3QgKCkge1xuICByZXR1cm4gKGF3YWl0IHRoaXMuc2hlbGwoWyd3aG9hbWknXSkpLnRyaW0oKSA9PT0gJ3Jvb3QnO1xufTtcblxuLyoqXG4gKiBWZXJpZnkgd2hldGhlciBhIHJlbW90ZSBwYXRoIGV4aXN0cyBvbiB0aGUgZGV2aWNlIHVuZGVyIHRlc3QuXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IHJlbW90ZVBhdGggLSBUaGUgcmVtb3RlIHBhdGggdG8gdmVyaWZ5LlxuICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgZ2l2ZW4gcGF0aCBleGlzdHMgb24gdGhlIGRldmljZS5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuZmlsZUV4aXN0cyA9IGFzeW5jIGZ1bmN0aW9uIGZpbGVFeGlzdHMgKHJlbW90ZVBhdGgpIHtcbiAgY29uc3QgcGFzc0ZsYWcgPSAnX19QQVNTX18nO1xuICBjb25zdCBjaGVja0NtZCA9IGBbIC1lICcke3JlbW90ZVBhdGgucmVwbGFjZSgvJy9nLCBgXFxcXCdgKX0nIF0gJiYgZWNobyAke3Bhc3NGbGFnfWA7XG4gIHRyeSB7XG4gICAgcmV0dXJuIF8uaW5jbHVkZXMoYXdhaXQgdGhpcy5zaGVsbChbY2hlY2tDbWRdKSwgcGFzc0ZsYWcpO1xuICB9IGNhdGNoIChpZ24pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbi8qKlxuICogR2V0IHRoZSBvdXRwdXQgb2YgX2xzXyBjb21tYW5kIG9uIHRoZSBkZXZpY2UgdW5kZXIgdGVzdC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVtb3RlUGF0aCAtIFRoZSByZW1vdGUgcGF0aCAodGhlIGZpcnN0IGFyZ3VtZW50IHRvIHRoZSBfbHNfIGNvbW1hbmQpLlxuICogQHBhcmFtIHtBcnJheS48U3RyaW5nPn0gb3B0cyBbW11dIC0gQWRkaXRpb25hbCBfbHNfIG9wdGlvbnMuXG4gKiBAcmV0dXJuIHtBcnJheS48U3RyaW5nPn0gVGhlIF9sc18gb3V0cHV0IGFzIGFuIGFycmF5IG9mIHNwbGl0IGxpbmVzLlxuICogICAgICAgICAgICAgICAgICAgICAgICAgIEFuIGVtcHR5IGFycmF5IGlzIHJldHVybmVkIG9mIHRoZSBnaXZlbiBfcmVtb3RlUGF0aF9cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBkb2VzIG5vdCBleGlzdC5cbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMubHMgPSBhc3luYyBmdW5jdGlvbiBscyAocmVtb3RlUGF0aCwgb3B0cyA9IFtdKSB7XG4gIHRyeSB7XG4gICAgbGV0IGFyZ3MgPSBbJ2xzJywgLi4ub3B0cywgcmVtb3RlUGF0aF07XG4gICAgbGV0IHN0ZG91dCA9IGF3YWl0IHRoaXMuc2hlbGwoYXJncyk7XG4gICAgbGV0IGxpbmVzID0gc3Rkb3V0LnNwbGl0KCdcXG4nKTtcbiAgICByZXR1cm4gbGluZXMubWFwKChsKSA9PiBsLnRyaW0oKSlcbiAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgIC5maWx0ZXIoKGwpID0+IGwuaW5kZXhPZignTm8gc3VjaCBmaWxlJykgPT09IC0xKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyci5tZXNzYWdlLmluZGV4T2YoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSA9PT0gLTEpIHtcbiAgICAgIHRocm93IGVycjtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG59O1xuXG4vKipcbiAqIEdldCB0aGUgc2l6ZSBvZiB0aGUgcGFydGljdWxhciBmaWxlIGxvY2F0ZWQgb24gdGhlIGRldmljZSB1bmRlciB0ZXN0LlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSByZW1vdGVQYXRoIC0gVGhlIHJlbW90ZSBwYXRoIHRvIHRoZSBmaWxlLlxuICogQHJldHVybiB7bnVtYmVyfSBGaWxlIHNpemUgaW4gYnl0ZXMuXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIGdldHRpbmcgdGhlIHNpemUgb2YgdGhlIGdpdmVuIGZpbGUuXG4gKi9cbnN5c3RlbUNhbGxNZXRob2RzLmZpbGVTaXplID0gYXN5bmMgZnVuY3Rpb24gZmlsZVNpemUgKHJlbW90ZVBhdGgpIHtcbiAgdHJ5IHtcbiAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHRoaXMubHMocmVtb3RlUGF0aCwgWyctbGEnXSk7XG4gICAgaWYgKGZpbGVzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZW1vdGUgcGF0aCBpcyBub3QgYSBmaWxlYCk7XG4gICAgfVxuICAgIC8vIGh0dHBzOi8vcmVnZXgxMDEuY29tL3IvZk9zNFA0LzhcbiAgICBjb25zdCBtYXRjaCA9IC9bcnd4c1N0VFxcLStdezEwfVtcXHNcXGRdKlxcc1teXFxzXStcXHMrW15cXHNdK1xccysoXFxkKykvLmV4ZWMoZmlsZXNbMF0pO1xuICAgIGlmICghbWF0Y2ggfHwgXy5pc05hTihwYXJzZUludChtYXRjaFsxXSwgMTApKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gcGFyc2Ugc2l6ZSBmcm9tIGxpc3Qgb3V0cHV0OiAnJHtmaWxlc1swXX0nYCk7XG4gICAgfVxuICAgIHJldHVybiBwYXJzZUludChtYXRjaFsxXSwgMTApO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBnZXQgZmlsZSBzaXplIGZvciAnJHtyZW1vdGVQYXRofSc6ICR7ZXJyLm1lc3NhZ2V9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogSW5zdGFsbHMgdGhlIGdpdmVuIGNlcnRpZmljYXRlIG9uIGEgcm9vdGVkIHJlYWwgZGV2aWNlIG9yXG4gKiBhbiBlbXVsYXRvci4gVGhlIGVtdWxhdG9yIG11c3QgYmUgZXhlY3V0ZWQgd2l0aCBgLXdyaXRhYmxlLXN5c3RlbWBcbiAqIGNvbW1hbmQgbGluZSBvcHRpb24gYW5kIGFkYiBkYWVtb24gc2hvdWxkIGJlIHJ1bm5pbmcgaW4gcm9vdFxuICogbW9kZSBmb3IgdGhpcyBtZXRob2QgdG8gd29yayBwcm9wZXJseS4gVGhlIG1ldGhvZCBhbHNvIHJlcXVpcmVzXG4gKiBvcGVuc3NsIHRvb2wgdG8gYmUgYXZhaWxhYmxlIG9uIHRoZSBkZXN0aW5hdGlvbiBzeXN0ZW0uXG4gKiBSZWFkIGh0dHBzOi8vZ2l0aHViLmNvbS9hcHBpdW0vYXBwaXVtL2lzc3Vlcy8xMDk2NFxuICogZm9yIG1vcmUgZGV0YWlscyBvbiB0aGlzIHRvcGljXG4gKlxuICogQHBhcmFtIHtCdWZmZXJ8c3RyaW5nfSBjZXJ0IC0gYmFzZTY0LWRlY29kZWQgY29udGVudCBvZiB0aGUgYWN0dWFsIGNlcnRpZmljYXRlXG4gKiByZXByZXNlbnRlZCBhcyBhIHN0cmluZyBvciBhIGJ1ZmZlclxuICogQHRocm93cyB7RXJyb3J9IElmIG9wZW5zc2wgdG9vbCBpcyBub3QgYXZhaWxhYmxlIG9uIHRoZSBkZXN0aW5hdGlvbiBzeXN0ZW1cbiAqIG9yIGlmIHRoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSBpbnN0YWxsaW5nIHRoZSBjZXJ0aWZpY2F0ZVxuICovXG5zeXN0ZW1DYWxsTWV0aG9kcy5pbnN0YWxsTWl0bUNlcnRpZmljYXRlID0gYXN5bmMgZnVuY3Rpb24gaW5zdGFsbE1pdG1DZXJ0aWZpY2F0ZSAoY2VydCkge1xuICBjb25zdCBvcGVuU3NsID0gYXdhaXQgZ2V0T3BlblNzbEZvck9zKCk7XG5cbiAgaWYgKCFfLmlzQnVmZmVyKGNlcnQpKSB7XG4gICAgY2VydCA9IEJ1ZmZlci5mcm9tKGNlcnQsICdiYXNlNjQnKTtcbiAgfVxuXG4gIGNvbnN0IHRtcFJvb3QgPSBhd2FpdCB0ZW1wRGlyLm9wZW5EaXIoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBzcmNDZXJ0ID0gcGF0aC5yZXNvbHZlKHRtcFJvb3QsICdzb3VyY2UuY2VyJyk7XG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHNyY0NlcnQsIGNlcnQpO1xuICAgIGxldCB7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMob3BlblNzbCwgWyd4NTA5JywgJy1ub291dCcsICctaGFzaCcsICctaW4nLCBzcmNDZXJ0XSk7XG4gICAgY29uc3QgY2VydEhhc2ggPSBzdGRvdXQudHJpbSgpO1xuICAgIGxvZy5kZWJ1ZyhgR290IGNlcnRpZmljYXRlIGhhc2g6ICR7Y2VydEhhc2h9YCk7XG4gICAgbG9nLmRlYnVnKCdQcmVwYXJpbmcgY2VydGlmaWNhdGUgY29udGVudCcpO1xuICAgICh7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMob3BlblNzbCwgWyd4NTA5JywgJy1pbicsIHNyY0NlcnRdLCB7aXNCdWZmZXI6IHRydWV9KSk7XG4gICAgbGV0IGRzdENlcnRDb250ZW50ID0gc3Rkb3V0O1xuICAgICh7c3Rkb3V0fSA9IGF3YWl0IGV4ZWMob3BlblNzbCwgWyd4NTA5JyxcbiAgICAgICctaW4nLCBzcmNDZXJ0LFxuICAgICAgJy10ZXh0JyxcbiAgICAgICctZmluZ2VycHJpbnQnLFxuICAgICAgJy1ub291dCddLCB7aXNCdWZmZXI6IHRydWV9KSk7XG4gICAgZHN0Q2VydENvbnRlbnQgPSBCdWZmZXIuY29uY2F0KFtkc3RDZXJ0Q29udGVudCwgc3Rkb3V0XSk7XG4gICAgY29uc3QgZHN0Q2VydCA9IHBhdGgucmVzb2x2ZSh0bXBSb290LCBgJHtjZXJ0SGFzaH0uMGApO1xuICAgIGF3YWl0IGZzLndyaXRlRmlsZShkc3RDZXJ0LCBkc3RDZXJ0Q29udGVudCk7XG4gICAgbG9nLmRlYnVnKCdSZW1vdW50aW5nIC9zeXN0ZW0gaW4gcncgbW9kZScpO1xuICAgIC8vIFNvbWV0aW1lcyBlbXVsYXRvciByZWJvb3QgaXMgc3RpbGwgbm90IGZ1bGx5IGZpbmlzaGVkIG9uIHRoaXMgc3RhZ2UsIHNvIHJldHJ5XG4gICAgYXdhaXQgcmV0cnlJbnRlcnZhbCg1LCAyMDAwLCBhc3luYyAoKSA9PiBhd2FpdCB0aGlzLmFkYkV4ZWMoWydyZW1vdW50J10pKTtcbiAgICBsb2cuZGVidWcoYFVwbG9hZGluZyB0aGUgZ2VuZXJhdGVkIGNlcnRpZmljYXRlIGZyb20gJyR7ZHN0Q2VydH0nIHRvICcke0NFUlRTX1JPT1R9J2ApO1xuICAgIGF3YWl0IHRoaXMucHVzaChkc3RDZXJ0LCBDRVJUU19ST09UKTtcbiAgICBsb2cuZGVidWcoJ1JlbW91bnRpbmcgL3N5c3RlbSB0byBjb25maXJtIGNoYW5nZXMnKTtcbiAgICBhd2FpdCB0aGlzLmFkYkV4ZWMoWydyZW1vdW50J10pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBpbmplY3QgdGhlIGN1c3RvbSBjZXJ0aWZpY2F0ZS4gYCArXG4gICAgICAgICAgICAgICAgICAgIGBJcyB0aGUgY2VydGlmaWNhdGUgcHJvcGVybHkgZW5jb2RlZCBpbnRvIGJhc2U2NC1zdHJpbmc/IGAgK1xuICAgICAgICAgICAgICAgICAgICBgRG8geW91IGhhdmUgcm9vdCBwZXJtaXNzaW9ucyBvbiB0aGUgZGV2aWNlPyBgICtcbiAgICAgICAgICAgICAgICAgICAgYE9yaWdpbmFsIGVycm9yOiAke2Vyci5tZXNzYWdlfWApO1xuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGZzLnJpbXJhZih0bXBSb290KTtcbiAgfVxufTtcblxuLyoqXG4gKiBWZXJpZmllcyBpZiB0aGUgZ2l2ZW4gcm9vdCBjZXJ0aWZpY2F0ZSBpcyBhbHJlYWR5IGluc3RhbGxlZCBvbiB0aGUgZGV2aWNlLlxuICpcbiAqIEBwYXJhbSB7QnVmZmVyfHN0cmluZ30gY2VydCAtIGJhc2U2NC1kZWNvZGVkIGNvbnRlbnQgb2YgdGhlIGFjdHVhbCBjZXJ0aWZpY2F0ZVxuICogcmVwcmVzZW50ZWQgYXMgYSBzdHJpbmcgb3IgYSBidWZmZXJcbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBvcGVuc3NsIHRvb2wgaXMgbm90IGF2YWlsYWJsZSBvbiB0aGUgZGVzdGluYXRpb24gc3lzdGVtXG4gKiBvciBpZiB0aGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgY2hlY2tpbmcgdGhlIGNlcnRpZmljYXRlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgZ2l2ZW4gY2VydGlmaWNhdGUgaXMgYWxyZWFkeSBpbnN0YWxsZWRcbiAqL1xuc3lzdGVtQ2FsbE1ldGhvZHMuaXNNaXRtQ2VydGlmaWNhdGVJbnN0YWxsZWQgPSBhc3luYyBmdW5jdGlvbiBpc01pdG1DZXJ0aWZpY2F0ZUluc3RhbGxlZCAoY2VydCkge1xuICBjb25zdCBvcGVuU3NsID0gYXdhaXQgZ2V0T3BlblNzbEZvck9zKCk7XG5cbiAgaWYgKCFfLmlzQnVmZmVyKGNlcnQpKSB7XG4gICAgY2VydCA9IEJ1ZmZlci5mcm9tKGNlcnQsICdiYXNlNjQnKTtcbiAgfVxuXG4gIGNvbnN0IHRtcFJvb3QgPSBhd2FpdCB0ZW1wRGlyLm9wZW5EaXIoKTtcbiAgbGV0IGNlcnRIYXNoO1xuICB0cnkge1xuICAgIGNvbnN0IHRtcENlcnQgPSBwYXRoLnJlc29sdmUodG1wUm9vdCwgJ3NvdXJjZS5jZXInKTtcbiAgICBhd2FpdCBmcy53cml0ZUZpbGUodG1wQ2VydCwgY2VydCk7XG4gICAgY29uc3Qge3N0ZG91dH0gPSBhd2FpdCBleGVjKG9wZW5Tc2wsIFsneDUwOScsICctbm9vdXQnLCAnLWhhc2gnLCAnLWluJywgdG1wQ2VydF0pO1xuICAgIGNlcnRIYXNoID0gc3Rkb3V0LnRyaW0oKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgcmV0cmlldmUgdGhlIGNlcnRpZmljYXRlIGhhc2guIGAgK1xuICAgICAgICAgICAgICAgICAgICBgSXMgdGhlIGNlcnRpZmljYXRlIHByb3Blcmx5IGVuY29kZWQgaW50byBiYXNlNjQtc3RyaW5nPyBgICtcbiAgICAgICAgICAgICAgICAgICAgYE9yaWdpbmFsIGVycm9yOiAke2Vyci5tZXNzYWdlfWApO1xuICB9IGZpbmFsbHkge1xuICAgIGF3YWl0IGZzLnJpbXJhZih0bXBSb290KTtcbiAgfVxuICBjb25zdCBkc3RQYXRoID0gcGF0aC5wb3NpeC5yZXNvbHZlKENFUlRTX1JPT1QsIGAke2NlcnRIYXNofS4wYCk7XG4gIGxvZy5kZWJ1ZyhgQ2hlY2tpbmcgaWYgdGhlIGNlcnRpZmljYXRlIGlzIGFscmVhZHkgaW5zdGFsbGVkIGF0ICcke2RzdFBhdGh9J2ApO1xuICByZXR1cm4gYXdhaXQgdGhpcy5maWxlRXhpc3RzKGRzdFBhdGgpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgc3lzdGVtQ2FsbE1ldGhvZHM7XG5leHBvcnQgeyBERUZBVUxUX0FEQl9FWEVDX1RJTUVPVVQgfTtcbiJdLCJmaWxlIjoibGliL3Rvb2xzL3N5c3RlbS1jYWxscy5qcyIsInNvdXJjZVJvb3QiOiIuLi8uLi8uLiJ9