-
Notifications
You must be signed in to change notification settings - Fork 5
/
stream.pl
2109 lines (2015 loc) · 129 KB
/
stream.pl
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
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
use Mojolicious::Lite;
use Digest::MD5 qw(md5_hex);
use Scalar::Util 'weaken';
use File::Basename qw(dirname);
use File::Spec::Functions qw(catdir catfile);
use Asset::File;
use Mojolicious::Plugin::Config;
use File::Copy;
use Mojo::JSON qw(encode_json);
use IO::File;
use Encode qw(encode_utf8);
use Cwd;
use utf8;
our $VERSION = '1.0';
$ENV{MOJO_MAX_MESSAGE_SIZE} = 2147483648;
my $config = plugin Config => {
file => '/etc/StreamUpload.conf'
};
my $UploadServer = $config->{UploadServer} || 'http://125.89.72.212:3009';
my $FileRepository = $config->{FileRepository} || '/tmp/';
my $CrossOrigins = $config->{CrossOrigins} || '*';
my $TokenKey = $config->{TokenKey} || 'stream';
app->log->path($config->{log});
app->log->level('debug') if $config->{debug} == 1;
hook after_build_tx => sub {
my $tx = shift;
my $app = shift;
weaken $tx;
$tx->req->content->on(body => sub {
my $single = shift;
return unless $tx->req->url->path->contains('/upload');
my $args = $tx->req->params->to_hash;
my $file;
if ( $args->{token} and $args->{name} and $args->{size}
and $args->{token} eq generateToken({ name => $args->{name}, size => $args->{size}}) ) {
# 签名成功, 修改一些基本的信息
my $filePath = getDstPath($args->{name});
$tx->req->param(name => $filePath); # 最终路径名
$tx->req->param(path => $filePath . '.temp'); # 中间临时路径名
createDir($filePath);
$file = Asset::File->new(path => $tx->req->param('path'), cleanup => 0); # 整个句柄
}
if (!$file) {
app->log->debug("远程地址: ". $tx->remote_address . " 认证失败:". $args->{token});
$tx->res->code(200);
$tx->res->headers->content_type("application/json");
$tx->res->body(encode_json({
success => 0,
message => 'Error: 签名认证失败',
}));
return $tx->resume;
}
return unless $tx->req->method eq 'POST' or $tx->req->method eq 'OPTIONS';
$tx->req->max_message_size(0); # 让它可以上传无限大小
my ($from, $to, $range_size);
if ( $tx->req->headers->content_range
and $tx->req->headers->content_range =~ m/bytes (\w+)-(\d+)\/(\d+)/) {
($from, $to, $range_size) = ($1, $2, $3);
$from = 0 if $from eq 'null';
my $size = $file->size || 0;
if (!$range_size or $size != $from) {
$tx->res->code(416);
$tx->res->headers->content_type("application/json");
$tx->res->body(encode_json({
success => 0,
message => 'Error: 请求范围错误',
}));
return $tx->resume;
}
}
$single->unsubscribe('read')->on(read => sub {
my ($single, $bytes) = @_;
$file->add_chunk($bytes);
if ($range_size and $file->size and $file->size == $range_size) {
my $name = $tx->req->param('name');
$file->move_to($name);
$tx->req->param(path => $name); # 因为要进入后面的 ROUTE 所以, 需要让后面的程序在文件名移位置后能检查到大小
app->log->debug("远程地址: ". $tx->remote_address ." 上传文件: $name 完成");
}
});
});
};
get '/' => "index";
get '/bootstrap';
get '/tk' => sub {
my $self = shift;
my $name = $self->param('name');
my $size = $self->param('size');
my $token = generateToken({ name => $name, size => $size});
my $success = 1;
my $message = '';
return $self->render(json => {
token => $token,
server => $UploadServer,
success => $success,
message => $message,
});
};
# html5 文件上传和查询接口
# URI: /upload
# 参数:name(文件名,必填,如1040199_50.jpg)
# token(Token,必填,如A1409681943_1557)
# client(上传类型,必填,html5)
# size(文件字节大小,必填,空文件为0,如1557)
# 头信息:Content-Range(必须传入的头信息,格式:bytes 开始字节-结束字节/总字节,如:Content-Range:bytes 0-1557/1557)
any [qw(POST OPTIONS GET)] => '/upload' => sub {
my $self = shift;
$self->res->headers->header('Access-Control-Allow-Headers' => 'Content-Range,Content-Type');
$self->res->headers->header('Access-Control-Allow-Origin' => $CrossOrigins);
$self->res->headers->header('Access-Control-Allow-Methods' => 'POST, GET, OPTIONS');
my $file = Asset::File->new(path => $self->param('path')); # 整个句柄
return $self->render(json => {
start => $file->size || 0,
success => 1,
message => '',
});
};
# flash 上传接口
# URI: /fd
# 参数: token(Token,必填,如A1409681943_1557)
# client(上传类型,必填,form)
# 方式:POST
post '/fd' => sub {
my $self = shift;
my $upload = $self->req->upload('FileData');
my $name = $upload->filename;
my $size = $upload->size;
my $token = $self->param("token");
my $args = $self->req->params->to_hash;
my $filePath;
if ( $args->{token} and $args->{name} and $args->{size}
and $args->{token} eq generateToken({ name => $args->{name}, size => $args->{size}}) ) {
$filePath = getDstPath($name);
createDir($filePath);
}
my $success = 0;
if ($filePath) {
$success = 1;
$upload->move_to($filePath);
app->log->debug("远程地址: ". $self->tx->remote_address ." 上传文件: $filePath 完成");
}
return $self->render(json => {
start => $upload->size || 0,
success => $success,
message => '',
});
};
sub getDstPath {
my ($pathName, $size) = shift;
if ($size) {
return catfile( $FileRepository, "${size}_$pathName" );
}
else {
return catfile( $FileRepository, $pathName);
}
}
sub check_signature {
my ($signature, $prikey, $path) = @_;
my $tmpSign = lc md5_hex( "$path$prikey");
if ( substr($tmpSign, 16) eq $signature ) {
return 1
}
}
sub generateToken {
my $args = shift;
$args->{size} ||= "0000";
return if !$args->{name};
my $key_file = md5_hex(encode_utf8($args->{name})) . $args->{size};
my $tmpSign = lc md5_hex( $key_file. $TokenKey );
return substr($tmpSign, 16) . "_" . $key_file
}
sub createDir {
my $dest = shift;
return if !$dest or -d $dest;
my $dir = File::Basename::dirname( $dest );
if (! -e $dir ) {
if (! File::Path::make_path( $dir ) || ! -d $dir ) {
my $e = $!;
debugf("Failed to createdir %s: %s", $dir, $e);
}
}
}
app->start();
__DATA__
@@ crossdomain.xml
<?xml version="1.0" encoding="UTF-8"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
@@ index.html.ep
<!DOCTYPE html>
<html>
<head>
<title>New Style SWF/HTML5 Stream Uploading DEMO</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="stream-v1.css" rel="stylesheet" type="text/css">
</head>
<body>
<div id="i_select_files">
</div>
<div id="i_stream_files_queue">
</div>
<button onclick="javascript:_t.upload();">开始上传</button>|<button onclick="javascript:_t.stop();">停止上传</button>|<button onclick="javascript:_t.cancel();">取消</button>
|<button onclick="javascript:_t.disable();">禁用文件选择</button>|<button onclick="javascript:_t.enable();">启用文件选择</button>
<br>
Messages:
<div id="i_stream_message_container" class="stream-main-upload-box" style="overflow: auto;height:200px;">
</div>
<br>
<script type="text/javascript" src="stream-v1.js"></script>
<script type="text/javascript">
/**
* 配置文件(如果没有默认字样,说明默认值就是注释下的值)
* 但是,on*(onSelect, onMaxSizeExceed...)等函数的默认行为
* 是在ID为i_stream_message_container的页面元素中写日志
*/
var config = {
browseFileId : "i_select_files", /** 选择文件的ID, 默认: i_select_files */
browseFileBtn : "<div>请选择文件</div>", /** 显示选择文件的样式, 默认: `<div>请选择文件</div>` */
dragAndDropArea: "i_select_files", /** 拖拽上传区域,Id(字符类型"i_select_files")或者DOM对象, 默认: `i_select_files` */
dragAndDropTips: "<span>把文件(文件夹)拖拽到这里</span>", /** 拖拽提示, 默认: `<span>把文件(文件夹)拖拽到这里</span>` */
filesQueueId : "i_stream_files_queue", /** 文件上传容器的ID, 默认: i_stream_files_queue */
filesQueueHeight : 200, /** 文件上传容器的高度(px), 默认: 450 */
messagerId : "i_stream_message_container", /** 消息显示容器的ID, 默认: i_stream_message_container */
multipleFiles: true /** 多个文件一起上传, 默认: false */
};
var _t = new Stream(config);
</script>
</body>
@@ stream-v1.css
@charset "utf-8";
body {
color: #000;
line-height: 166.6%;
float: left;
font-family: verdana;
font-size: 12px;
}
ul,ol {
list-style: none;
}
ul,ol,li,img {
border: 0 none;
margin: 0;
padding: 0;
}
.stream-browse-files {
overflow: hidden;
position: relative;
}
.stream-browse-drag-files-area {
border: 2px dashed #555;
padding: 10px 0;
border-radius: 7px;
text-align: center;
margin: 10px 0;
cursor: pointer;
}
.stream-disable-browser {
color: #909090;
}
.stream-files-scroll {
height: 450px;
overflow: auto;
}
.stream-cell-file {
cursor: default;
position: relative;
zoom: 1;
padding: 10px 20px 10px 35px;
border-bottom-width: 1px;
border-bottom-style: dotted;
border-color: #ccc;
}
.stream-cell-file .stream-cell-infos:before,.stream-cell-file .stream-cell-infos:after {
clear: both;
content: ".";
font-size: 0;
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
.stream-cell-file .stream-file-name {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
.stream-cell-file .stream-process {
zoom: 1;
overflow: hidden;
}
.stream-cell-file .stream-cancel {
margin-right: 5px;
float: right;
}
a {
color: #158144;
}
.stream-cell-file .stream-process-bar {
width: 300px;
}
.stream-cell-file .stream-process-bar,.stream-cell-file .stream-percent {
float: left;
margin-right: 10px;
}
.stream-cell-file .stream-process-bar {
margin-top: 5px;
width: 430px;
}
.stream-process-bar {
position: relative;
border: 1px solid #ccc;
background: #fff;
width: 55px;
height: 10px;
overflow: hidden;
}
.stream-process-bar span {
position: absolute;
left: 0;
top: 0;
height: 8px;
border: 1px solid #fff;
font-size: 0;
background-position: 0 -149px;
background-image: url(./bgx.png);
background-repeat: repeat-x;
background-color: #A5DD3D;
}
.stream-process-bar,.stream-process-bar span {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-khtml-box-sizing: border-box;
box-sizing: border-box;
}
.stream-cell-file .stream-cell-infos {
zoom: 1;
color: #7D7D7D;
}
.stream-cell-file .stream-cell-infos .stream-cell-info {
width: 170px;
}
.stream-cell-file .stream-cell-infos span {
float: left;
margin-right: 8px;
}
.stream-total-tips .stream-process-bar {
width: 200px;
margin-top: -1px;
}
.stream-process-bar, .stream-uploading-ico {
-moz-box-align: center;
display: inline-block;
vertical-align: middle;
zoom: 1;
}
.stream-total-tips {
border: 1px solid #ccc;
border-width: 1px 0 0;
padding: 3px 5px 3px 25px;
position: relative;
zoom: 1;
background-color: #FFFFE1;
color: #565656;
}
.stream-main-upload-box {
width: 610px;
background-color: #FFFFFF;
border-style: solid;
border-width: 1px;
border-color: #50A05B;
clear: both;
overflow: hidden;
}
.stream-uploading-ico {
left: 11px;
position: absolute;
top: 11px;
background: url("./upload.gif") no-repeat scroll 0 1px transparent !important;
height: 18px;
width: 18px;
}
.stream-disabled {
cursor: not-allowed;
pointer-events: none;
opacity: .65;
filter: alpha(opacity=65);
-webkit-box-shadow: none;
box-shadow: none;
}
@@ stream-v1.js (base64)
LyoqDQogKiBAbmFtZSBVcGxvYWRlci5qcw0KICogQGF1dGhvciBKaWFuZw0KICogQGNyZWF0ZQky
MDEyLTEyLTIwDQogKiBAdmVyc2lvbiAwLjENCiAqIEBkZXNjcmlwdGlvbglUaGUgQW5ub3VzZSBm
dW50aW9uIGZvciBIVE1MNS9GTEFTSC9GT1JNIHVwbG9hZCBtZXRob2QuIFRoZQ0KICogCWZ1bmN0
aW9uIHdpbGwgYXV0b2x5IHRvIGNob29zZSB0aGUgcHJvcGVydHkgbWV0aG9kIHRvIGFqdXN0IHRv
IGNsaWVudA0KICogIEJyb3dzd2VyLiBUaGlzIGpzIGZ1bmN0aW9uIG1haW5seSBib3Jyb3cgZnJv
bSB5b3VrdS5jb20ncyB1cGxvYWRlci5taW4uanMNCiAqICBhbmQgdHJ5IHRvIHJlLWNyZWF0ZSBp
dCBmb3IgZnVsbGZpdGluZyBteSByZXF1aXJlbWVudC4gDQogKiBAZXhhbXBsZQ0KICogCQkxLiBu
ZXcgU3RyZWFtKCk7DQogKiAJCTIuIHZhciBjZmcgPSB7DQogKiAJCQkJZXh0RmlsdGVycyA6IFsi
LnR4dCIsICIuZ3oiXSwNCiAqIAkJCQlmaWxlRmllbGROYW1lIDogIkZpbGVEYXRhIg0KICogCQkJ
fTsNCiAqIAkJICAgbmV3IFN0cmVhbShjZmcpOw0KICovIA0KKGZ1bmN0aW9uKCl7DQoJdmFyIFBy
b3ZpZGVyLCBhRmlsdGVycyA9IFtdLCBuSWRDb3VudCA9IDAsIGFPdGhlckJyb3dzZXJzID0gWyJN
YXh0aG9uIiwgIlNFIDIuWCIsICJRUUJyb3dzZXIiXSwNCgkJblplcm8gPSAwLCBzT25lU3BhY2Ug
PSAiICIsIHNMQnJhY2UgPSAieyIsIHNSQnJhY2UgPSAifSIsDQoJCWdhID0gLyh+LShcZCspLX4p
L2csIHJMQnJhY2UgPSAvXHtMQlJBQ0VcfS9nLCByUkJyYWNlID0gL1x7UkJSQUNFXH0vZywNCgkJ
ZWEgPSB7DQoJCQkiJiIgOiAiJmFtcDsiLA0KCQkJIjwiIDogIiZsdDsiLA0KCQkJIj4iIDogIiZn
dDsiLA0KCQkJJyInIDogIiZxdW90OyIsDQoJCQkiJyIgOiAiJiN4Mjc7IiwNCgkJCSIvIiA6ICIm
I3gyRjsiLA0KCQkJImAiIDogIiYjeDYwOyINCgkJfSwgcGEgPSBBcnJheS5pc0FycmF5ICYmIC9c
e1xzKlxbKD86bmF0aXZlIGNvZGV8ZnVuY3Rpb24pXF1ccypcfS9pLnRlc3QoQXJyYXkuaXNBcnJh
eSkNCgkJCT8gQXJyYXkuaXNBcnJheQ0KCQkJOiBmdW5jdGlvbihhKSB7cmV0dXJuICJhcnJheSIg
PT09IGZUb1N0cmluZyhhKX0sDQoJCXNTdHJlYW1NZXNzYWdlcklkID0gImlfc3RyZWFtX21lc3Nh
Z2VfY29udGFpbmVyIiwNCgkJc0NlbGxGaWxlVGVtcGxhdGUgPSAnPGIgY2xhc3M9InN0cmVhbS11
cGxvYWRpbmctaWNvIj48L2I+JyArDQoJCQkJCSc8ZGl2IGNsYXNzPSJzdHJlYW0tZmlsZS1uYW1l
Ij48c3Ryb25nPjwvc3Ryb25nPjwvZGl2PicgKw0KCQkJCQknPGRpdiBjbGFzcz0ic3RyZWFtLXBy
b2Nlc3MiPicgKw0KCQkJCQknCTxhIGNsYXNzPSJzdHJlYW0tY2FuY2VsIiBocmVmPSJqYXZhc2Ny
aXB0OnZvaWQoMCkiPlx1NTIyMFx1OTY2NDwvYT4nICsNCgkJCQkJJwk8c3BhbiBjbGFzcz0ic3Ry
ZWFtLXByb2Nlc3MtYmFyIj48c3BhbiBzdHlsZT0id2lkdGg6IDAlOyI+PC9zcGFuPjwvc3Bhbj4n
ICsNCgkJCQkJJwk8c3BhbiBjbGFzcz0ic3RyZWFtLXBlcmNlbnQiPjAlPC9zcGFuPicgKw0KCQkJ
CQknPC9kaXY+JyArDQoJCQkJCSc8ZGl2IGNsYXNzPSJzdHJlYW0tY2VsbC1pbmZvcyI+JyArDQoJ
CQkJCScJPHNwYW4gY2xhc3M9InN0cmVhbS1jZWxsLWluZm8iPlx1OTAxZlx1NWVhNlx1ZmYxYTxl
bSBjbGFzcz0ic3RyZWFtLXNwZWVkIj48L2VtPjwvc3Bhbj4nICsNCgkJCQkJJwk8c3BhbiBjbGFz
cz0ic3RyZWFtLWNlbGwtaW5mbyI+XHU1ZGYyXHU0ZTBhXHU0ZjIwXHVmZjFhPGVtIGNsYXNzPSJz
dHJlYW0tdXBsb2FkZWQiPjwvZW0+PC9zcGFuPicgKw0KCQkJCQknCTxzcGFuIGNsYXNzPSJzdHJl
YW0tY2VsbC1pbmZvIj5cdTUyNjlcdTRmNTlcdTY1ZjZcdTk1ZjRcdWZmMWE8ZW0gY2xhc3M9InN0
cmVhbS1yZW1haW4tdGltZSI+PC9lbT48L3NwYW4+JyArDQoJCQkJCSc8L2Rpdj4nLA0KCQlzVG90
YWxDb250YWluZXIgPSAnPGRpdiBpZD0iI3RvdGFsQ29udGFpbmVySWQjIiBjbGFzcz0ic3RyZWFt
LXRvdGFsLXRpcHMiPicgKw0KCQkJJwlcdTRlMGFcdTRmMjBcdTYwM2JcdThmZGJcdTVlYTZcdWZm
MWE8c3BhbiBjbGFzcz0ic3RyZWFtLXByb2Nlc3MtYmFyIj48c3BhbiBzdHlsZT0id2lkdGg6IDAl
OyI+PC9zcGFuPjwvc3Bhbj4nICsNCgkJCScJPHNwYW4gY2xhc3M9InN0cmVhbS1wZXJjZW50Ij4w
JTwvc3Bhbj5cdWZmMGNcdTVkZjJcdTRlMGFcdTRmMjA8c3Ryb25nIGNsYXNzPSJfc3RyZWFtLXRv
dGFsLXVwbG9hZGVkIj4mbmJzcDs8L3N0cm9uZz4nICsNCgkJCScJXHVmZjBjXHU2MDNiXHU2NTg3
XHU0ZWY2XHU1OTI3XHU1YzBmPHN0cm9uZyBjbGFzcz0iX3N0cmVhbS10b3RhbC1zaXplIj4mbmJz
cDs8L3N0cm9uZz4nICsNCgkJCSc8L2Rpdj4nLA0KCQlzRmlsZXNDb250YWluZXIJPSAnPGRpdiBj
bGFzcz0ic3RyZWFtLWZpbGVzLXNjcm9sbCIgc3R5bGU9ImhlaWdodDogI2ZpbGVzUXVldWVIZWln
aHQjcHg7Ij48dWwgaWQ9IiNmaWxlc0NvbnRhaW5lcklkIyI+PC91bD48L2Rpdj4nOw0KCQ0KCWZ1
bmN0aW9uIGZHZW5lcmF0ZUlkKHByZWZpeCkgew0KCQl2YXIgYiA9IChuZXcgRGF0ZSkuZ2V0VGlt
ZSgpICsgIl8wMXZfIiArICsrbklkQ291bnQ7DQoJCXJldHVybiBwcmVmaXggPyBwcmVmaXggKyAi
XyIgKyBiIDogYjsNCgl9DQoJZnVuY3Rpb24gZkdldFJhbmRvbSgpIHsNCgkJcmV0dXJuIChuZXcg
RGF0ZSkuZ2V0VGltZSgpLnRvU3RyaW5nKCkuc3Vic3RyaW5nKDgpOw0KCX0NCglmdW5jdGlvbiBm
RXh0ZW5kKGEsIGIpew0KCQl2YXIgYyA9IDIgPCBhcmd1bWVudHMubGVuZ3RoID8gW2FyZ3VtZW50
c1syXV0gOiBudWxsOw0KCQlyZXR1cm4gZnVuY3Rpb24oKXsNCgkJCXZhciBkID0gInN0cmluZyIg
PT09IHR5cGVvZiBhID8gYlthXSA6IGEsZT1jID8gW2FyZ3VtZW50c1swXV0uY29uY2F0KGMpIDog
YXJndW1lbnRzOw0KCQkJcmV0dXJuIGQuYXBwbHkoYnx8ZCwgZSk7DQoJCX07DQoJfQ0KCQ0KCWZ1
bmN0aW9uIGZBZGRFdmVudExpc3RlbmVyKGEsIGIsIGMpIHsNCgkJYS5hZGRFdmVudExpc3RlbmVy
ID8gYS5hZGRFdmVudExpc3RlbmVyKGIsIGMsICExKSA6IGEuYXR0YWNoRXZlbnQgPyBhDQoJCQkJ
LmF0dGFjaEV2ZW50KCJvbiIgKyBiLCBjKSA6IGFbIm9uIiArIGJdID0gYzsNCgl9DQoJDQoJZnVu
Y3Rpb24gZlJlbW92ZUV2ZW50TGlzdGVuZXIoYSwgYiwgYykgew0KCQlhLnJlbW92ZUV2ZW50TGlz
dGVuZXIgPyBhLnJlbW92ZUV2ZW50TGlzdGVuZXIoYiwgYywgITEpIDogYS5kZXRhY2hFdmVudA0K
CQkJCT8gYS5kZXRhY2hFdmVudCgib24iICsgYiwgYykNCgkJCQk6IGFbIm9uIiArIGJdID0gbnVs
bDsNCgl9DQoJDQoJZnVuY3Rpb24gZlRvU3RyaW5nKGEpIHsNCgkJdmFyIGIgPSB7DQoJCQkidW5k
ZWZpbmVkIiA6ICJ1bmRlZmluZWQiLA0KCQkJbnVtYmVyIDogIm51bWJlciIsDQoJCQkiYm9vbGVh
biIgOiAiYm9vbGVhbiIsDQoJCQlzdHJpbmcgOiAic3RyaW5nIiwNCgkJCSJbb2JqZWN0IEZ1bmN0
aW9uXSIgOiAiZnVuY3Rpb24iLA0KCQkJIltvYmplY3QgUmVnRXhwXSIgOiAicmVnZXhwIiwNCgkJ
CSJbb2JqZWN0IEFycmF5XSIgOiAiYXJyYXkiLA0KCQkJIltvYmplY3QgRGF0ZV0iIDogImRhdGUi
LA0KCQkJIltvYmplY3QgRXJyb3JdIiA6ICJlcnJvciINCgkJfTsNCgkJcmV0dXJuIGJbdHlwZW9m
IGFdIHx8IGJbT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGEpXSB8fCAoYSA/ICJvYmpl
Y3QiIDogIm51bGwiKTsNCgl9DQoJDQoJZnVuY3Rpb24gZkFkZFZhcnMoanNvbiwgdXJsLCBjKSB7
DQoJCXZhciBfYXJyYXkgPSBbXSwgX3NlcCA9ICImIiwgZiA9IGZ1bmN0aW9uKGpzb24sIGMpIHsN
CgkJCXZhciBlID0gdXJsID8gL1xbXF0kLy50ZXN0KHVybCkgPyB1cmwgOiB1cmwgKyAiWyIgKyBj
ICsgIl0iIDogYzsNCgkJCSJ1bmRlZmluZWQiICE9IGUgJiYgInVuZGVmaW5lZCIgIT0gYw0KCQkJ
CSYmIF9hcnJheS5wdXNoKCJvYmplY3QiID09PSB0eXBlb2YganNvbg0KCQkJCQkJCT8gZkFkZFZh
cnMoanNvbiwgZSwgITApDQoJCQkJCQkJOiAiW29iamVjdCBGdW5jdGlvbl0iID09PSBPYmplY3Qu
cHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoanNvbikNCgkJCQkJCQkJPyBlbmNvZGVVUklDb21wb25l
bnQoZSkgKyAiPSIgKyBlbmNvZGVVUklDb21wb25lbnQoanNvbigpKQ0KCQkJCQkJCQk6IGVuY29k
ZVVSSUNvbXBvbmVudChlKSArICI9IiArIGVuY29kZVVSSUNvbXBvbmVudChqc29uKSkNCgkJfTsN
CgkJaWYgKCFjICYmIHVybCkNCgkJCV9zZXAgPSAvXD8vLnRlc3QodXJsKSA/IC9cPyQvLnRlc3Qo
dXJsKSA/ICIiIDogIiYiIDogIj8iLA0KCQkJX2FycmF5LnB1c2godXJsKSwNCgkJCV9hcnJheS5w
dXNoKGZBZGRWYXJzKGpzb24pKTsNCgkJZWxzZSBpZiAoIltvYmplY3QgQXJyYXldIiA9PT0gT2Jq
ZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGpzb24pDQoJCQkJJiYgInVuZGVmaW5lZCIgIT0g
dHlwZW9mIGpzb24pDQoJCQlmb3IgKHZhciBnID0gMCwgYyA9IGpzb24ubGVuZ3RoOyBnIDwgYzsg
KytnKQ0KCQkJCWYoanNvbltnXSwgZyk7DQoJCWVsc2UgaWYgKCJ1bmRlZmluZWQiICE9IHR5cGVv
ZiBqc29uICYmIG51bGwgIT09IGpzb24gJiYgIm9iamVjdCIgPT09IHR5cGVvZiBqc29uKQ0KCQkJ
Zm9yIChnIGluIGpzb24pDQoJCQkJZihqc29uW2ddLCBnKTsNCgkJZWxzZQ0KCQkJX2FycmF5LnB1
c2goZW5jb2RlVVJJQ29tcG9uZW50KHVybCkgKyAiPSIgKyBlbmNvZGVVUklDb21wb25lbnQoanNv
bikpOw0KCQlyZXR1cm4gX2FycmF5LmpvaW4oX3NlcCkucmVwbGFjZSgvXiYvLCAiIikucmVwbGFj
ZSgvJTIwL2csICIrIikNCgl9DQoJDQoJZnVuY3Rpb24gZk1lcmdlSnNvbihiYXNlLCBleHRlbmQp
IHsNCgkJdmFyIHJlc3VsdCA9IHt9Ow0KCQlmb3IgKHZhciBhdHRyIGluIGJhc2UpDQoJCQlyZXN1
bHRbYXR0cl0gPSBiYXNlW2F0dHJdOw0KCQlmb3IgKHZhciBhdHRyIGluIGV4dGVuZCkNCgkJCXJl
c3VsdFthdHRyXSA9IGV4dGVuZFthdHRyXTsNCgkJcmV0dXJuIHJlc3VsdDsNCgl9DQoJDQoJZnVu
Y3Rpb24gZkFkZENsYXNzKGVsZW1lbnQsIGtsYXNzKSB7DQoJCWZIYXNDbGFzcyhlbGVtZW50LCBr
bGFzcykgfHwgKGVsZW1lbnQuY2xhc3NOYW1lICs9ICIgIiArIGtsYXNzKTsNCgl9DQoJDQoJZnVu
Y3Rpb24gZkhhc0NsYXNzKGVsZW1lbnQsIGtsYXNzKSB7DQoJCXJldHVybiBSZWdFeHAoIihefCAp
IiArIGtsYXNzICsgIiggfCQpIikudGVzdChlbGVtZW50LmNsYXNzTmFtZSk7DQoJfQ0KCQ0KCWZ1
bmN0aW9uIGZSZW1vdmVDbGFzcyhlbGVtZW50LCBrbGFzcykgew0KCQllbGVtZW50LmNsYXNzTmFt
ZSA9IGVsZW1lbnQuY2xhc3NOYW1lLnJlcGxhY2UoUmVnRXhwKCIoXnwgKSIgKyBrbGFzcyArICIo
IHwkKSIpLCAiICIpDQoJCQkJLnJlcGxhY2UoL15ccyt8XHMrJC9nLCAiIik7DQoJfQ0KCQ0KCWZ1
bmN0aW9uIGZDb250YWlucyhjb250YWluZXIsIGtsYXNzKSB7DQoJCWlmICghY29udGFpbmVyKQ0K
CQkJcmV0dXJuIFtdOw0KCQlpZiAoY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwpDQoJCQlyZXR1
cm4gY29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoIi4iICsga2xhc3MpOw0KCQlmb3IgKHZhciBj
ID0gW10sIGVsZXMgPSBjb250YWluZXIuZ2V0RWxlbWVudHNCeVRhZ05hbWUoIioiKSwgZSA9IGVs
ZXMubGVuZ3RoLCBmID0gMDsgZiA8IGU7IGYrKykNCgkJCWZIYXNDbGFzcyhlbGVzW2ZdLCBrbGFz
cykgJiYgYy5wdXNoKGVsZXNbZl0pOw0KCQlyZXR1cm4gYzsNCgl9DQoJDQoJZnVuY3Rpb24gZkNy
ZWF0ZUNvbnRlbnRFbGUoY29udGVudCkgew0KCQl2YXIgYiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1l
bnQoImRpdiIpOw0KCQliLmlubmVySFRNTCA9IGNvbnRlbnQ7DQoJCWNvbnRlbnQgPSBiLmNoaWxk
Tm9kZXM7DQoJCXJldHVybiBjb250ZW50WzBdLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY29udGVu
dFswXSk7DQoJfQ0KCQ0KCWZ1bmN0aW9uIGZTaG93TWVzc2FnZShtc2csIHdhcm5pbmcpIHsNCgkJ
dmFyIG8gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChzU3RyZWFtTWVzc2FnZXJJZCk7DQoJCW8g
JiYgKG8uaW5uZXJIVE1MICs9ICI8YnI+IiArICghIXdhcm5pbmcgPyAoIjxzcGFuIHN0eWxlPSdj
b2xvcjpyZWQ7Jz4iICsgbXNnICsgIjwvc3Bhbj4iKTogbXNnKSk7DQoJfQ0KCQ0KCWZ1bmN0aW9u
IGZNZXNzYWdlKG1zZywgVmFyVmFscywgYywgZCkgew0KCQlmb3IgKHZhciBuTEluZGV4LCBuUklu
ZGV4LCBzZXBJbmRleCwgYXJnTmFtZSwgc2Vjb25kVmFyLCBzID0gW10sIF9hcmdOYW1lLCBsZW5n
dGggPSBtc2cubGVuZ3RoOzspIHsNCgkJCW5MSW5kZXggPSBtc2cubGFzdEluZGV4T2Yoc0xCcmFj
ZSwgbGVuZ3RoKTsNCgkJCWlmICgwID4gbkxJbmRleCkNCgkJCQlicmVhazsNCgkJCW5SSW5kZXgg
PSBtc2cuaW5kZXhPZihzUkJyYWNlLCBuTEluZGV4KTsNCgkJCWlmIChuTEluZGV4ICsgMSA+PSBu
UkluZGV4KQ0KCQkJCWJyZWFrOw0KCQkJYXJnTmFtZSA9IF9hcmdOYW1lID0gbXNnLnN1YnN0cmlu
ZyhuTEluZGV4ICsgMSwgblJJbmRleCk7DQoJCQlzZWNvbmRWYXIgPSBudWxsOw0KCQkJc2VwSW5k
ZXggPSBhcmdOYW1lLmluZGV4T2Yoc09uZVNwYWNlKTsNCgkJCS0xIDwgc2VwSW5kZXggJiYgKHNl
Y29uZFZhciA9IGFyZ05hbWUuc3Vic3RyaW5nKHNlcEluZGV4ICsgMSksIGFyZ05hbWUgPSBhcmdO
YW1lLnN1YnN0cmluZygwLCBzZXBJbmRleCkpOw0KCQkJc2VwSW5kZXggPSBWYXJWYWxzW2FyZ05h
bWVdOw0KCQkJYyAmJiAoc2VwSW5kZXggPSBjKGFyZ05hbWUsIHNlcEluZGV4LCBzZWNvbmRWYXIp
KTsNCgkJCSJ1bmRlZmluZWQiID09PSB0eXBlb2Ygc2VwSW5kZXggJiYgKHNlcEluZGV4ID0gIn4t
IiArIHMubGVuZ3RoICsgIi1+Iiwgcy5wdXNoKF9hcmdOYW1lKSk7DQoJCQltc2cgPSBtc2cuc3Vi
c3RyaW5nKDAsIG5MSW5kZXgpICsgc2VwSW5kZXggKyBtc2cuc3Vic3RyaW5nKG5SSW5kZXggKyAx
KTsNCgkJCWQgfHwgKGxlbmd0aCA9IG5MSW5kZXggLSAxKTsNCgkJfQ0KCQlyZXR1cm4gbXNnLnJl
cGxhY2UoZ2EsIGZ1bmN0aW9uKG1zZywgVmFyVmFscywgYykgew0KCQkJCQlyZXR1cm4gc0xCcmFj
ZSArIHNbcGFyc2VJbnQoYywgMTApXSArIHNSQnJhY2UNCgkJCQl9KS5yZXBsYWNlKHJMQnJhY2Us
IHNMQnJhY2UpLnJlcGxhY2UoclJCcmFjZSwgc1JCcmFjZSk7DQoJfQ0KCQ0KCWZ1bmN0aW9uIGZJ
c09iak9yRnVuKGEsIGIpIHsNCgkJdmFyIGMgPSB0eXBlb2YgYTsNCgkJcmV0dXJuIGEgJiYgKCJv
YmplY3QiID09PSBjIHx8ICFiICYmICgiZnVuY3Rpb24iID09PSBjIHx8ICJmdW5jdGlvbiIgPT09
IGZUb1N0cmluZyhhKSkpIHx8ICExOw0KCX0NCglmdW5jdGlvbiBmSXNOdW1iZXIodmFsKSB7DQoJ
CXJldHVybiAibnVtYmVyIiA9PT0gdHlwZW9mIHZhbCAmJiBpc0Zpbml0ZSh2YWwpOw0KCX0NCglm
dW5jdGlvbiBmSXNBcnJheSh2YWwpIHsNCgkJcmV0dXJuICJhcnJheSIgPT09IGZUb1N0cmluZyh2
YWwpOw0KCX0NCgkNCgkvKioNCgkgKiBUaGlzIGZ1bmN0aW9uIGlzIGZvciByZWdpc3RlcmluZyB0
aGUgZnVuY3Rpb24ocykgb24gaXRzIHByb3RvdHlwZS4NCgkgKiBAaG9zdFByb3RvdHlwZQl3aGlj
aCBpcyBpdHMgaG9zdCBwcm90b3R5cGUuDQoJICogQGZ1bnMJZnVuY3Rpb25zLCBzdWNoIGFze2Fh
OmZ1bmN0aW9uKCl7fSwgYmI6ZnVuY3Rpb24oKXt9fQ0KCSAqIEBmb3JzZVJlZwlib29sZWFuOiB3
aGVuIHRoZSBAaG9zdFByb3RvdHlwZSBkb24ndCBoYXZlIHRoZSBmdW5jdGlvbiwgdGhlbiByZWdp
c3RlciBpdC4NCgkgKiAJCXRydWU6IGRvIGl0LCBpZ25vcmUgdGhlIEBob3N0UHJvdG90eXBlIHdo
ZXRoZXIgaGFzIGl0Lg0KCSAqIAkJZmFsc2U6IHdoZW4gbm90IGhhdmUgaXQgc28gdGhhdCByZWdp
c3RlciBpdC4NCgkgKi8NCglmdW5jdGlvbiBmUmVnRnVucyhob3N0UHJvdG90eXBlLCBmdW5zLCBm
b3JzZVJlZywgZCkgew0KCQl2YXIgZSwgZiwgZzsNCgkJaWYgKCFob3N0UHJvdG90eXBlIHx8ICFm
dW5zKQ0KCQkJcmV0dXJuIGhvc3RQcm90b3R5cGUgfHwge307DQoJCWlmIChkKQ0KCQkJZm9yIChl
ID0gMCwgZyA9IGQubGVuZ3RoOyBlIDwgZzsgKytlKQ0KCQkJCWYgPSBkW2VdLCBPYmplY3QucHJv
dG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZnVucywgZikJJiYgKGZvcnNlUmVnIHx8ICEoZiBp
biBob3N0UHJvdG90eXBlKSkgJiYgKGhvc3RQcm90b3R5cGVbZl0gPSBmdW5zW2ZdKTsNCgkJZWxz
ZSB7DQoJCQlmb3IgKGYgaW4gZnVucykNCgkJCQlPYmplY3QucHJvdG90eXBlLmhhc093blByb3Bl
cnR5LmNhbGwoZnVucywgZikgJiYgKGZvcnNlUmVnIHx8ICEoZiBpbiBob3N0UHJvdG90eXBlKSkg
JiYgKGhvc3RQcm90b3R5cGVbZl0gPSBmdW5zW2ZdKTsNCgkJCSh7dmFsdWVPZiA6IDB9KS5wcm9w
ZXJ0eUlzRW51bWVyYWJsZSgidmFsdWVPZiIpCXx8IGZSZWdGdW5zKGhvc3RQcm90b3R5cGUsIGZ1
bnMsIGZvcnNlUmVnLCAiaGFzT3duUHJvcGVydHksaXNQcm90b3R5cGVPZixwcm9wZXJ0eUlzRW51
bWVyYWJsZSx0b1N0cmluZyx0b0xvY2FsZVN0cmluZyx2YWx1ZU9mIi5zcGxpdCgiLCIpKTsNCgkJ
fQ0KCQlyZXR1cm4gaG9zdFByb3RvdHlwZTsNCgl9DQoJDQoJZnVuY3Rpb24gZlJlZ0V2ZW50cygp
IHsNCgkJZlJlZ0Z1bnModGhpcy5jb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHsNCgkJCQkJcHVibGlz
aCA6IGZ1bmN0aW9uKGEpIHsNCgkJCQkJCXRoaXMuX2V2dHNbYV0gfHwgKHRoaXMuX2V2dHNbYV0g
PSBudWxsKTsNCgkJCQkJfSwNCgkJCQkJb24gOiBmdW5jdGlvbihhLCBiLCBjKSB7DQoJCQkJCQl2
YXIgZCA9IHRoaXMuX2V2dHM7DQoJCQkJCQlkW2FdID0ge307DQoJCQkJCQlkW2FdLnR5cGUgPSBh
Ow0KCQkJCQkJdGhpcy5uYW1lICYmIChkW2FdLnR5cGUgPSB0aGlzLm5hbWUgKyAiOiIgKyBhKTsN
CgkJCQkJCWRbYV0uZm4gPSBmdW5jdGlvbigpIHsNCgkJCQkJCQliLmFwcGx5KGMsIGFyZ3VtZW50
cyk7DQoJCQkJCQl9Ow0KCQkJCQl9LA0KCQkJCQlhZnRlciA6IGZ1bmN0aW9uKGEsIGIsIGMpIHsN
CgkJCQkJCXRoaXMub24oYSwgYiwgYyk7DQoJCQkJCX0sDQoJCQkJCWZpcmUgOiBmdW5jdGlvbihh
KSB7DQoJCQkJCQl2YXIgYiA9IHRoaXMuX2V2dHNbYV07DQoJCQkJCQlpZiAoYikgew0KCQkJCQkJ
CXZhciBjID0ge3RhcmdldCA6IHRoaXMsCXR5cGUgOiBiLnR5cGV9LA0KCQkJCQkJCQlkID0gQXJy
YXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTsNCgkJCQkJCQlpZiAoZklzT2Jq
T3JGdW4oZFswXSkpDQoJCQkJCQkJCWZvciAodmFyIGUgaW4gYykNCgkJCQkJCQkJCWRbMF1bZV0J
PyBkWzBdWyJfIiArIGVdID0gY1tlXSA6IGRbMF1bZV0gPSBjW2VdOw0KCQkJCQkJCWVsc2UNCgkJ
CQkJCQkJZFswXSA9IGM7DQoJCQkJCQkJImZ1bmN0aW9uIiA9PT0gZlRvU3RyaW5nKGIuZm4pICYm
IGIuZm4uYXBwbHkodGhpcywgZCk7DQoJCQkJCQl9DQoJCQkJCX0sDQoJCQkJCWRldGFjaCA6IGZ1
bmN0aW9uKGEpIHsNCgkJCQkJCWRlbGV0ZSB0aGlzLl9ldnRzW2FdOw0KCQkJCQl9DQoJCQkJfSwg
ITEpOw0KCQl0aGlzLl9ldnRzID0ge307DQoJfQ0KCQ0KCQ0KCWZ1bmN0aW9uIFBhcmVudChhcmdz
KSB7DQoJCWZSZWdFdmVudHMuY2FsbCh0aGlzKTsNCgkJdGhpcy5faXNBcHBseVN1cGVyQ2xhc3Mg
fHwgZlJlZ0Z1bnModGhpcy5jb25zdHJ1Y3Rvci5wcm90b3R5cGUsIFBhcmVudC5wcm90b3R5cGUs
ICExKTsNCgkJaWYgKGFyZ3MpIHsNCgkJCWZvciAodmFyIGZpZWxkIGluIGFyZ3MpDQoJCQkJdGhp
cy5zZXQoZmllbGQsIGFyZ3NbZmllbGRdKTsNCgkJfQ0KCQkiZnVuY3Rpb24iID09PSB0eXBlb2Yg
dGhpcy5pbml0aWFsaXplciAmJiB0aGlzLmluaXRpYWxpemVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50
cyk7DQoJfQ0KCVBhcmVudC5wcm90b3R5cGUgPSB7DQoJCV9pc0FwcGx5U3VwZXJDbGFzcyA6ICEw
LA0KCQlpbml0aWFsaXplciA6IGZ1bmN0aW9uKCkgew0KCQl9LA0KCQlnZXQgOiBmdW5jdGlvbihr
ZXkpIHsNCgkJCXJldHVybiB0aGlzLmNvbmZpZ1trZXldOw0KCQl9LA0KCQlzZXQgOiBmdW5jdGlv
bihrZXksIHZhbCkgew0KCQkJdmFyIGM7DQoJCQlrZXkgJiYgInVuZGVmaW5lZCIgIT09IHR5cGVv
ZiB2YWwgJiYga2V5IGluIHRoaXMuY29uZmlnCSYmICh0aGlzLmNvbmZpZ1trZXldID0gdmFsLCBj
ID0ga2V5ICsgIkNoYW5nZSIsIHRoaXMuX2V2dCAmJiBjIGluIHRoaXMuX2V2dC5ldmVudHMgJiYg
dGhpcy5maXJlKGMpKTsNCgkJfQ0KCX07DQoJDQoJZnVuY3Rpb24gU1dGUmVmZXJlbmNlKGEsIGIs
IGMpIHsNCgkJZlJlZ0V2ZW50cy5jYWxsKHRoaXMpOw0KCQl2YXIgZCA9IHRoaXMuX2lkID0gZkdl
bmVyYXRlSWQoInVwbG9hZGVyLXN3ZiIpLCBjID0gYyB8fCB7fSwgZSA9ICgoYy52ZXJzaW9uIHx8
IHNGbGFzaFZlcnNpb24pICsgIiIpLnNwbGl0KCIuIiksDQoJCQllID0gU1dGUmVmZXJlbmNlLmlz
Rmxhc2hWZXJzaW9uQXRMZWFzdChwYXJzZUludChlWzBdLCAxMCksIHBhcnNlSW50KGVbMV0sIDEw
KSwgcGFyc2VJbnQoZVsyXSwgMTApKSwNCgkJCWYgPSBTV0ZSZWZlcmVuY2UuaXNGbGFzaFZlcnNp
b25BdExlYXN0KDgsIDAsIDApICYmICFlICYmIGMudXNlRXhwcmVzc0luc3RhbGwsDQoJCQlnID0g
ZiA/IHNGbGFzaERvd25sb2FkIDogYiwgDQoJCQliID0gIjxvYmplY3QgIiwgaCA9ICImU1dGSWQ9
IiArIGQgKyAiJmNhbGxiYWNrPSIgKyBzRmxhc2hFdmVudEhhbmRsZXIgKyAiJmFsbG93ZWREb21h
aW49IiArIGRvY3VtZW50LmxvY2F0aW9uLmhvc3RuYW1lOw0KCQlTV0ZSZWZlcmVuY2UuX2luc3Rh
bmNlc1tkXSA9IHRoaXM7DQoJCWlmIChhICYmIChlIHx8IGYpICYmIGcpIHsNCgkJCWIgKz0gJ2lk
PSInICsgZCArICciICc7DQoJCQliID0gQnJvd3Nlci5pZSA/IGIgKyAoJ2NsYXNzaWQ9IicgKyBz
SUVGbGFzaENsYXNzSWQgKyAnIiAnKSA6IGINCgkJCQkJKyAoJ3R5cGU9IicgKyBzU2hvY2t3YXZl
Rmxhc2ggKyAnIiBkYXRhPSInICsgZyArICciICcpOw0KCQkJYiArPSAnd2lkdGg9IjEwMCUiIGhl
aWdodD0iMTAwJSI+JzsNCgkJCUJyb3dzZXIuaWUgJiYgKGIgKz0gJzxwYXJhbSBuYW1lPSJtb3Zp
ZSIgdmFsdWU9IicgKyBnICsgJyIvPicpOw0KCQkJZm9yICh2YXIgaiBpbiBjLmZpeGVkQXR0cmli
dXRlcykNCgkJCQlvYS5oYXNPd25Qcm9wZXJ0eShqKQ0KCQkJCQkJJiYgKGIgKz0gJzxwYXJhbSBu
YW1lPSInICsgaiArICciIHZhbHVlPSInICsgYy5maXhlZEF0dHJpYnV0ZXNbal0gKyAnIi8+Jyk7
DQoJCQlmb3IgKHZhciBzIGluIGMuZmxhc2hWYXJzKQ0KCQkJCWogPSBjLmZsYXNoVmFyc1tzXSwg
InN0cmluZyIgPT09IHR5cGVvZiBqDQoJCQkJCQkmJiAoaCArPSAiJiIgKyBzICsgIj0iICsgZW5j
b2RlVVJJQ29tcG9uZW50KGopKTsNCgkJCWggJiYgKGIgKz0gJzxwYXJhbSBuYW1lPSJmbGFzaFZh
cnMiIHZhbHVlPSInICsgaCArICciLz4nKTsNCgkJCWEuaW5uZXJIVE1MID0gYiArICI8L29iamVj
dD4iOw0KCQkJdGhpcy5zd2YgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChkKTsNCgkJfSBlbHNl
DQoJCQl0aGlzLnB1Ymxpc2goIndyb25nZmxhc2h2ZXJzaW9uIiwge2ZpcmVPbmNlIDogITB9KSwg
dGhpcy5maXJlKCJ3cm9uZ2ZsYXNodmVyc2lvbiIsIHt0eXBlIDogIndyb25nZmxhc2h2ZXJzaW9u
In0pOw0KCX0NCgkNCglTV0ZSZWZlcmVuY2UuZ2V0Rmxhc2hWZXJzaW9uID0gZnVuY3Rpb24oKSB7
DQoJCXJldHVybiAiIiArIEJyb3dzZXIuZmxhc2hNYWpvciArICIuIiArICgiIiArIEJyb3dzZXIu
Zmxhc2hNaW5vcikgKyAiLiIgKyAoIiIgKyBCcm93c2VyLmZsYXNoUmV2KTsNCgl9Ow0KCVNXRlJl
ZmVyZW5jZS5pc0ZsYXNoVmVyc2lvbkF0TGVhc3QgPSBmdW5jdGlvbihhLCBiLCBjKSB7cmV0dXJu
IHRydWU7DQoJCS8qdmFyIGQgPSBwYXJzZUludChCcm93c2VyLmZsYXNoTWFqb3IsIDEwKSwgZSA9
IHBhcnNlSW50KEJyb3dzZXIuZmxhc2hNaW5vciwgMTApLCBmID0gcGFyc2VJbnQoDQoJCQkJQnJv
d3Nlci5mbGFzaFJldiwgMTApLCBhID0gcGFyc2VJbnQoYSB8fCAwLCAxMCksIGIgPSBwYXJzZUlu
dChiIHx8IDAsDQoJCQkJMTApLCBjID0gcGFyc2VJbnQoYyB8fCAwLCAxMCk7DQoJCXJldHVybiBh
ID09PSBkID8gYiA9PT0gZSA/IGMgPD0gZiA6IGIgPCBlIDogYSA8IGQ7Ki8NCgl9Ow0KCVNXRlJl
ZmVyZW5jZS5faW5zdGFuY2VzID0gU1dGUmVmZXJlbmNlLl9pbnN0YW5jZXMgfHwge307DQoJU1dG
UmVmZXJlbmNlLmV2ZW50SGFuZGxlciA9IGZ1bmN0aW9uKGEsIGIpIHtTV0ZSZWZlcmVuY2UuX2lu
c3RhbmNlc1thXS5fZXZlbnRIYW5kbGVyKGIpO307DQoJU1dGUmVmZXJlbmNlLnByb3RvdHlwZSA9
IHsNCgkJaW5pdGlhbGl6ZXIgOiBmdW5jdGlvbigpIHt9LA0KCQlfZXZlbnRIYW5kbGVyIDogZnVu
Y3Rpb24oYSkgew0KCQkJInN3ZlJlYWR5IiA9PT0gYS50eXBlID8gKHRoaXMucHVibGlzaCgic3dm
UmVhZHkiLCB7ZmlyZU9uY2UgOiAhMH0pLCB0aGlzLmZpcmUoInN3ZlJlYWR5IiwgYSkpDQoJCQkJ
CQkJCTogImxvZyIgIT09IGEudHlwZSAmJiB0aGlzLmZpcmUoYS50eXBlLCBhKTsNCgkJfSwNCgkJ
Y2FsbFNXRiA6IGZ1bmN0aW9uKGEsIGIpIHsNCgkJCWIgfHwgKGIgPSBbXSk7DQoJCQlyZXR1cm4g
dGhpcy5zd2ZbYV0gPyB0aGlzLnN3ZlthXS5hcHBseSh0aGlzLnN3ZiwgYikgOiBudWxsOw0KCQl9
LA0KCQl0b1N0cmluZyA6IGZ1bmN0aW9uKCkge3JldHVybiAiU1dGICIgKyB0aGlzLl9pZDt9DQoJ
fTsNCglTV0ZSZWZlcmVuY2UucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU1dGUmVmZXJlbmNlOw0K
CQ0KCWZ1bmN0aW9uIFNXRlByb3ZpZGVyKGEpIHsNCgkJdGhpcy5zd2ZDb250YWluZXJJZCA9IGZH
ZW5lcmF0ZUlkKCJ1cGxvYWRlciIpOw0KCQl0aGlzLnF1ZXVlID0gdGhpcy5zd2ZSZWZlcmVuY2Ug
PSBudWxsOw0KCQl0aGlzLmJ1dHRvblN0YXRlID0gInVwIjsNCgkJdGhpcy5jb25maWcgPSB7DQoJ
CQllbmFibGVkIDogITAsDQoJCQltdWx0aXBsZUZpbGVzIDogITAsDQoJCQlidXR0b25DbGFzc05h
bWVzIDogew0KCQkJCWhvdmVyIDogInVwbG9hZGVyLWJ1dHRvbi1ob3ZlciIsDQoJCQkJYWN0aXZl
IDogInVwbG9hZGVyLWJ1dHRvbi1hY3RpdmUiLA0KCQkJCWRpc2FibGVkIDogInVwbG9hZGVyLWJ1
dHRvbi1kaXNhYmxlZCIsDQoJCQkJZm9jdXMgOiAidXBsb2FkZXItYnV0dG9uLXNlbGVjdGVkIg0K
CQkJfSwNCgkJCWNvbnRhaW5lckNsYXNzTmFtZXMgOiB7aG92ZXIgOiAidXBob3RCZyJ9LA0KCQkJ
ZmlsZUZpbHRlcnMgOiBhRmlsdGVycywNCgkJCWZpbGVGaWVsZE5hbWUgOiAiRmlsZURhdGEiLA0K
CQkJc2ltTGltaXQgOiAxLA0KCQkJcmV0cnlDb3VudCA6IDMsDQoJCQlwb3N0VmFyc1BlckZpbGUg
OiB7fSwNCgkJCXN3ZlVSTCA6ICIvRmxhc2hVcGxvYWRlci5zd2YiLA0KCQkJdXBsb2FkVVJMIDog
Ii9mZCINCgkJfTsNCgkJUGFyZW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7DQoJfQ0KCVNXRlBy
b3ZpZGVyLnByb3RvdHlwZSA9IHsNCgkJY29uc3RydWN0b3IgOiBTV0ZQcm92aWRlciwNCgkJbmFt
ZSA6ICJ1cGxvYWRlciIsDQoJCWJ1dHRvblN0YXRlIDogInVwIiwNCgkJc3dmQ29udGFpbmVySWQg
OiBudWxsLA0KCQlzd2ZSZWZlcmVuY2UgOiBudWxsLA0KCQlxdWV1ZSA6IG51bGwsDQoJCWluaXRp
YWxpemVyIDogZnVuY3Rpb24oKSB7DQoJCQl0aGlzLnB1Ymxpc2goImZpbGVzZWxlY3QiKTsNCgkJ
CXRoaXMucHVibGlzaCgidXBsb2Fkc3RhcnQiKTsNCgkJCXRoaXMucHVibGlzaCgiZmlsZXVwbG9h
ZHN0YXJ0Iik7DQoJCQl0aGlzLnB1Ymxpc2goInVwbG9hZHByb2dyZXNzIik7DQoJCQl0aGlzLnB1
Ymxpc2goInRvdGFsdXBsb2FkcHJvZ3Jlc3MiKTsNCgkJCXRoaXMucHVibGlzaCgidXBsb2FkY29t
cGxldGUiKTsNCgkJCXRoaXMucHVibGlzaCgiYWxsdXBsb2Fkc2NvbXBsZXRlIik7DQoJCQl0aGlz
LnB1Ymxpc2goInVwbG9hZGVycm9yIik7DQoJCQl0aGlzLnB1Ymxpc2goIm1vdXNlZW50ZXIiKTsN
CgkJCXRoaXMucHVibGlzaCgibW91c2VsZWF2ZSIpOw0KCQkJdGhpcy5wdWJsaXNoKCJtb3VzZWRv
d24iKTsNCgkJCXRoaXMucHVibGlzaCgibW91c2V1cCIpOw0KCQkJdGhpcy5wdWJsaXNoKCJjbGlj
ayIpOw0KCQl9LA0KCQlyZW5kZXIgOiBmdW5jdGlvbihhKSB7DQoJCQlhICYmICh0aGlzLnJlbmRl
clVJKGEpLCB0aGlzLmJpbmRVSSgpKTsNCgkJfSwNCgkJcmVuZGVyVUkgOiBmdW5jdGlvbihhKSB7
DQoJCQl0aGlzLmNvbnRlbnRCb3ggPSBhOw0KCQkJdGhpcy5jb250ZW50Qm94LnN0eWxlLnBvc2l0
aW9uID0gInJlbGF0aXZlIjsNCgkJCXZhciBiID0gZkNyZWF0ZUNvbnRlbnRFbGUoIjxkaXYgaWQ9
JyIgKyB0aGlzLnN3ZkNvbnRhaW5lcklkICsgIicgc3R5bGU9J3Bvc2l0aW9uOmFic29sdXRlO3Rv
cDowcHg7IGxlZnQ6IDBweDsgbWFyZ2luOiAwOyBwYWRkaW5nOiAwOyBib3JkZXI6IDA7IHdpZHRo
OjEwMCU7IGhlaWdodDoxMDAlJz48L2Rpdj4iKTsNCgkJCWIuc3R5bGUud2lkdGggPSBhLm9mZnNl
dFdpZHRoICsgInB4IjsNCgkJCWIuc3R5bGUuaGVpZ2h0ID0gYS5vZmZzZXRIZWlnaHQgKyAicHgi
Ow0KCQkJdGhpcy5jb250ZW50Qm94LmFwcGVuZENoaWxkKGIpOw0KCQkJdGhpcy5zd2ZSZWZlcmVu
Y2UgPSBuZXcgU1dGUmVmZXJlbmNlKGIsIHRoaXMuZ2V0KCJzd2ZVUkwiKSwgew0KCQkJCQkJdmVy
c2lvbiA6ICIxMC4wLjQ1IiwNCgkJCQkJCWZpeGVkQXR0cmlidXRlcyA6IHsNCgkJCQkJCQl3bW9k
ZSA6ICJ0cmFuc3BhcmVudCIsDQoJCQkJCQkJYWxsb3dTY3JpcHRBY2Nlc3MgOiAiYWx3YXlzIiwN
CgkJCQkJCQlhbGxvd05ldHdvcmtpbmcgOiAiYWxsIiwNCgkJCQkJCQlzY2FsZSA6ICJub3NjYWxl
Ig0KCQkJCQkJfQ0KCQkJCQl9KTsNCgkJfSwNCgkJYmluZFVJIDogZnVuY3Rpb24oKSB7DQoJCQl0
aGlzLnN3ZlJlZmVyZW5jZS5vbigic3dmUmVhZHkiLCBmdW5jdGlvbigpIHsNCgkJCQl0aGlzLnNl
dE11bHRpcGxlRmlsZXMoKTsNCgkJCQl0aGlzLnNldEZpbGVGaWx0ZXJzKCk7DQoJCQkJdGhpcy50
cmlnZ2VyRW5hYmxlZCgpOw0KCQkJCXRoaXMuYWZ0ZXIoIm11bHRpcGxlRmlsZXNDaGFuZ2UiLCB0
aGlzLnNldE11bHRpcGxlRmlsZXMsIHRoaXMpOw0KCQkJCXRoaXMuYWZ0ZXIoImZpbGVGaWx0ZXJz
Q2hhbmdlIiwgdGhpcy5zZXRGaWxlRmlsdGVycywgdGhpcyk7DQoJCQkJdGhpcy5hZnRlcigiZW5h
YmxlZENoYW5nZSIsIHRoaXMudHJpZ2dlckVuYWJsZWQsIHRoaXMpOw0KCQkJfSwgdGhpcyk7DQoJ
CQl0aGlzLnN3ZlJlZmVyZW5jZS5vbigiZmlsZXNlbGVjdCIsIHRoaXMudXBkYXRlRmlsZUxpc3Qs
IHRoaXMpOw0KCQkJdGhpcy5zd2ZSZWZlcmVuY2Uub24oIm1vdXNlZW50ZXIiLCBmdW5jdGlvbigp
IHt0aGlzLnNldENvbnRhaW5lckNsYXNzKCJob3ZlciIsICEwKTt9LCB0aGlzKTsNCgkJCXRoaXMu
c3dmUmVmZXJlbmNlLm9uKCJtb3VzZWxlYXZlIiwgZnVuY3Rpb24oKSB7dGhpcy5zZXRDb250YWlu
ZXJDbGFzcygiaG92ZXIiLCAhMSk7fSwgdGhpcyk7DQoJCX0sDQoJCXNldENvbnRhaW5lckNsYXNz
IDogZnVuY3Rpb24oYSwgYikgew0KCQkJYiA/IGZBZGRDbGFzcyh0aGlzLmNvbnRlbnRCb3gsIHRo
aXMuZ2V0KCJjb250YWluZXJDbGFzc05hbWVzIilbYV0pIDogZlJlbW92ZUNsYXNzKA0KCQkJCQl0
aGlzLmNvbnRlbnRCb3gsIHRoaXMuZ2V0KCJjb250YWluZXJDbGFzc05hbWVzIilbYV0pOw0KCQl9
LA0KCQlzZXRGaWxlRmlsdGVycyA6IGZ1bmN0aW9uKCkgew0KCQkJdGhpcy5zd2ZSZWZlcmVuY2Ug
JiYgMCA8IHRoaXMuZ2V0KCJmaWxlRmlsdGVycyIpLmxlbmd0aA0KCQkJCQkmJiB0aGlzLnN3ZlJl
ZmVyZW5jZS5jYWxsU1dGKCJzZXRGaWxlRmlsdGVycyIsIFt0aGlzLmdldCgiZmlsZUZpbHRlcnMi
KV0pOw0KCQl9LA0KCQlzZXRNdWx0aXBsZUZpbGVzIDogZnVuY3Rpb24oKSB7DQoJCQl0aGlzLnN3
ZlJlZmVyZW5jZSAmJiB0aGlzLnN3ZlJlZmVyZW5jZS5jYWxsU1dGKCJzZXRBbGxvd011bHRpcGxl
RmlsZXMiLCBbdGhpcy5nZXQoIm11bHRpcGxlRmlsZXMiKV0pOw0KCQl9LA0KCQl0cmlnZ2VyRW5h
YmxlZCA6IGZ1bmN0aW9uKCkgew0KCQkJdGhpcy5nZXQoImVuYWJsZWQiKQ0KCQkJCQk/ICh0aGlz
LnN3ZlJlZmVyZW5jZS5jYWxsU1dGKCJlbmFibGUiKSwgdGhpcy5zd2ZSZWZlcmVuY2Uuc3dmLnNl
dEF0dHJpYnV0ZSgiYXJpYS1kaXNhYmxlZCIsICJmYWxzZSIpKQ0KCQkJCQk6ICh0aGlzLnN3ZlJl
ZmVyZW5jZS5jYWxsU1dGKCJkaXNhYmxlIiksIHRoaXMuc3dmUmVmZXJlbmNlLnN3Zi5zZXRBdHRy
aWJ1dGUoImFyaWEtZGlzYWJsZWQiLCAidHJ1ZSIpKQ0KCQl9LA0KCQl1cGRhdGVGaWxlTGlzdCA6
IGZ1bmN0aW9uKGEpIHsNCgkJCXRoaXMuc3dmUmVmZXJlbmNlLnN3Zi5mb2N1cygpOw0KCQkJZm9y
ICh2YXIgYSA9IGEuZmlsZUxpc3QsIGIgPSBbXSwgYyA9IHRoaXMuc3dmUmVmZXJlbmNlLCBkID0g
MDsgZCA8IGEubGVuZ3RoOyBkKyspIHsNCgkJCQl2YXIgZSA9IHt9Ow0KCQkJCWUuaWQgPSBhW2Rd
LmZpbGVJZDsNCgkJCQllLm5hbWUgPSBhW2RdLmZpbGVSZWZlcmVuY2UubmFtZTsNCgkJCQllLnNp
emUgPSBhW2RdLmZpbGVSZWZlcmVuY2Uuc2l6ZTsNCgkJCQllLnR5cGUgPSBhW2RdLmZpbGVSZWZl
cmVuY2UudHlwZTsNCgkJCQllLmRhdGVDcmVhdGVkID0gYVtkXS5maWxlUmVmZXJlbmNlLmNyZWF0
aW9uRGF0ZTsNCgkJCQllLmRhdGVNb2RpZmllZCA9IGFbZF0uZmlsZVJlZmVyZW5jZS5tb2RpZmlj
YXRpb25EYXRlOw0KCQkJCWUudXBsb2FkZXIgPSBjOw0KCQkJCWIucHVzaChuZXcgU1dGVXBsb2Fk
ZXIoZSkpOw0KCQkJfQ0KCQkJMCA8IGIubGVuZ3RoICYmIHRoaXMuZmlyZSgiZmlsZXNlbGVjdCIs
IHtmaWxlTGlzdCA6IGJ9KTsNCgkJfSwNCgkJdXBsb2FkRXZlbnRIYW5kbGVyIDogZnVuY3Rpb24o
YSkgew0KCQkJc3dpdGNoIChhLnR5cGUpIHsNCgkJCQljYXNlICJleGVjdXRvcjp1cGxvYWRzdGFy
dCIgOg0KCQkJCQl0aGlzLmZpcmUoImZpbGV1cGxvYWRzdGFydCIsIGEpOw0KCQkJCQlicmVhazsN
CgkJCQljYXNlICJleGVjdXRvcjp1cGxvYWRwcm9ncmVzcyIgOg0KCQkJCQl0aGlzLmZpcmUoInVw
bG9hZHByb2dyZXNzIiwgYSk7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgInVwbG9hZGVycXVldWU6
dG90YWx1cGxvYWRwcm9ncmVzcyIgOg0KCQkJCQl0aGlzLmZpcmUoInRvdGFsdXBsb2FkcHJvZ3Jl
c3MiLCBhKTsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAiZXhlY3V0b3I6dXBsb2FkY29tcGxldGUi
IDoNCgkJCQkJdGhpcy5maXJlKCJ1cGxvYWRjb21wbGV0ZSIsIGEpOw0KCQkJCQlicmVhazsNCgkJ
CQljYXNlICJ1cGxvYWRlcnF1ZXVlOmFsbHVwbG9hZHNjb21wbGV0ZSIgOg0KCQkJCQl0aGlzLnF1
ZXVlID0gbnVsbDsNCgkJCQkJdGhpcy5maXJlKCJhbGx1cGxvYWRzY29tcGxldGUiLCBhKTsNCgkJ
CQkJYnJlYWs7DQoJCQkJY2FzZSAiZXhlY3V0b3I6dXBsb2FkZXJyb3IiIDoNCgkJCQljYXNlICJ1
cGxvYWRlcnF1ZXVlOnVwbG9hZGVycm9yIiA6DQoJCQkJCXRoaXMuZmlyZSgidXBsb2FkZXJyb3Ii
LCBhKTsNCgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAiZXhlY3V0b3I6dXBsb2FkY2FuY2VsIiA6DQoJ
CQkJY2FzZSAidXBsb2FkZXJxdWV1ZTp1cGxvYWRjYW5jZWwiIDoNCgkJCQkJdGhpcy5maXJlKCJ1
cGxvYWRjYW5jZWwiLCBhKTsNCgkJCX0NCgkJfSwNCgkJdXBsb2FkIDogZnVuY3Rpb24odXBsb2Fk
ZXIsIHVybCwgcG9zdFZhcnMpIHsNCgkJCXZhciB1cmwgPSB1cmwgfHwgdGhpcy5nZXQoInVwbG9h
ZFVSTCIpLCBwb3N0VmFycyA9IGZNZXJnZUpzb24ocG9zdFZhcnMsIHRoaXMuZ2V0KCJwb3N0VmFy
c1BlckZpbGUiKSksIGlkID0gdXBsb2FkZXIuaWQsDQoJCQkJcG9zdFZhcnMgPSBwb3N0VmFycy5o
YXNPd25Qcm9wZXJ0eShpZCkgPyBwb3N0VmFyc1tpZF0gOiBwb3N0VmFyczsNCgkJCXVwbG9hZGVy
IGluc3RhbmNlb2YgU1dGVXBsb2FkZXINCgkJCQkJJiYgKHVwbG9hZGVyLm9uKCJ1cGxvYWRzdGFy
dCIsIHRoaXMudXBsb2FkRXZlbnRIYW5kbGVyLCB0aGlzKSwNCgkJCQkJCXVwbG9hZGVyLm9uKCJ1
cGxvYWRwcm9ncmVzcyIsIHRoaXMudXBsb2FkRXZlbnRIYW5kbGVyLCB0aGlzKSwNCgkJCQkJCXVw
bG9hZGVyLm9uKCJ1cGxvYWRjb21wbGV0ZSIsIHRoaXMudXBsb2FkRXZlbnRIYW5kbGVyLCB0aGlz
KSwNCgkJCQkJCXVwbG9hZGVyLm9uKCJ1cGxvYWRlcnJvciIsIHRoaXMudXBsb2FkRXZlbnRIYW5k
bGVyLCB0aGlzKSwNCgkJCQkJCXVwbG9hZGVyLm9uKCJ1cGxvYWRjYW5jZWwiLCB0aGlzLnVwbG9h
ZEV2ZW50SGFuZGxlciwgdGhpcyksDQoJCQkJCQl1cGxvYWRlci5zdGFydFVwbG9hZCh1cmwsIHBv
c3RWYXJzLCB0aGlzLmdldCgiZmlsZUZpZWxkTmFtZSIpKSk7DQoJCX0NCgl9Ow0KCQ0KCWZ1bmN0
aW9uIFNXRlVwbG9hZGVyKGEpIHsNCgkJdGhpcy5ieXRlc1NwZWVkID0gdGhpcy5ieXRlc1ByZXZM
b2FkZWQgPSAwOw0KCQl0aGlzLmJ5dGVzU3BlZWRzID0gW107DQoJCXRoaXMucHJlVGltZSA9IHRo
aXMucmVtYWluVGltZSA9IDA7DQoJCXRoaXMuY29uZmlnID0gew0KCQkJaWQgOiAiIiwNCgkJCW5h
bWUgOiAiIiwNCgkJCXNpemUgOiAiIiwNCgkJCXR5cGUgOiAiIiwNCgkJCWRhdGVDcmVhdGVkIDog
IiIsDQoJCQlkYXRlTW9kaWZpZWQgOiAiIiwNCgkJCXVwbG9hZGVyIDogIiINCgkJfTsNCgkJUGFy
ZW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7DQoJfQkNCglTV0ZVcGxvYWRlci5wcm90b3R5cGUg
PSB7DQoJCWNvbnN0cnVjdG9yIDogU1dGVXBsb2FkZXIsDQoJCW5hbWUgOiAiZXhlY3V0b3IiLA0K
CQlpbml0aWFsaXplciA6IGZ1bmN0aW9uKCkgew0KCQkJdGhpcy5pZCA9IGZHZW5lcmF0ZUlkKCJm
aWxlIik7DQoJCX0sDQoJCXN3ZkV2ZW50SGFuZGxlciA6IGZ1bmN0aW9uKGEpIHsNCgkJCWlmIChh
LmlkID09PSB0aGlzLmdldCgiaWQiKSkNCgkJCQlzd2l0Y2ggKGEudHlwZSkgew0KCQkJCQljYXNl
ICJ1cGxvYWRzdGFydCIgOg0KCQkJCQkJdGhpcy5maXJlKCJ1cGxvYWRzdGFydCIsIHt1cGxvYWRl
ciA6IHRoaXMuZ2V0KCJ1cGxvYWRlciIpfSk7DQoJCQkJCQlicmVhazsNCgkJCQkJY2FzZSAidXBs
b2FkcHJvZ3Jlc3MiIDoNCgkJCQkJCXZhciBiID0gKG5ldyBEYXRlKS5nZXRUaW1lKCksIGMgPSAo
YiAtIHRoaXMucHJlVGltZSkgLyAxRTMsIGQgPSAwOw0KCQkJCQkJaWYgKDEgPD0gYyB8fCAwID09
IHRoaXMuYnl0ZXNQcmV2TG9hZGVkKSB7DQoJCQkJCQkJdGhpcy5ieXRlc1NwZWVkID0gTWF0aC5y
b3VuZCgoYS5ieXRlc0xvYWRlZCAtIHRoaXMuYnl0ZXNQcmV2TG9hZGVkKSAvIGMpOw0KCQkJCQkJ
CXRoaXMuYnl0ZXNQcmV2TG9hZGVkID0gYS5ieXRlc0xvYWRlZDsNCgkJCQkJCQl0aGlzLnByZVRp
bWUgPSBiOw0KCQkJCQkJCTUgPCB0aGlzLmJ5dGVzU3BlZWRzLmxlbmd0aCAmJiB0aGlzLmJ5dGVz
U3BlZWRzLnNoaWZ0KCk7DQoJCQkJCQkJdGhpcy5ieXRlc1NwZWVkcy5wdXNoKHRoaXMuYnl0ZXNT
cGVlZCk7DQoJCQkJCQkJZm9yIChiID0gMDsgYiA8IHRoaXMuYnl0ZXNTcGVlZHMubGVuZ3RoOyBi
KyspDQoJCQkJCQkJCWQgKz0gdGhpcy5ieXRlc1NwZWVkc1tiXTsNCgkJCQkJCQl0aGlzLmJ5dGVz
U3BlZWQgPSBNYXRoLnJvdW5kKGQgLyB0aGlzLmJ5dGVzU3BlZWRzLmxlbmd0aCk7DQoJCQkJCQkJ
dGhpcy5yZW1haW5UaW1lID0gTWF0aC5jZWlsKChhLmJ5dGVzVG90YWwgLSBhLmJ5dGVzTG9hZGVk
KSAvIHRoaXMuYnl0ZXNTcGVlZCk7DQoJCQkJCQl9DQoJCQkJCQl0aGlzLmZpcmUoInVwbG9hZHBy
b2dyZXNzIiwgew0KCQkJCQkJCQkJb3JpZ2luRXZlbnQgOiBhLA0KCQkJCQkJCQkJYnl0ZXNMb2Fk
ZWQgOiBhLmJ5dGVzTG9hZGVkLA0KCQkJCQkJCQkJYnl0ZXNTcGVlZCA6IHRoaXMuYnl0ZXNTcGVl
ZCwNCgkJCQkJCQkJCWJ5dGVzVG90YWwgOiBhLmJ5dGVzVG90YWwsDQoJCQkJCQkJCQlyZW1haW5U
aW1lIDogdGhpcy5yZW1haW5UaW1lLA0KCQkJCQkJCQkJcGVyY2VudExvYWRlZCA6IE1hdGgubWlu
KDEwMCwgTWF0aC5yb3VuZCgxRTQgKiBhLmJ5dGVzTG9hZGVkIC8gYS5ieXRlc1RvdGFsKSAvIDEw
MCkNCgkJCQkJCQkJfSk7DQoJCQkJCQlicmVhazsNCgkJCQkJY2FzZSAidXBsb2FkY29tcGxldGUi
IDoNCgkJCQkJCXRoaXMuZmlyZSgidXBsb2FkZmluaXNoZWQiLCB7b3JpZ2luRXZlbnQgOiBhfSk7
DQoJCQkJCQlicmVhazsNCgkJCQkJY2FzZSAidXBsb2FkY29tcGxldGVkYXRhIiA6DQoJCQkJCQl0
aGlzLmZpcmUoInVwbG9hZGNvbXBsZXRlIiwgew0KCQkJCQkJCQkJb3JpZ2luRXZlbnQgOiBhLA0K
CQkJCQkJCQkJZGF0YSA6IGEuZGF0YQ0KCQkJCQkJCQl9KTsNCgkJCQkJCWJyZWFrOw0KCQkJCQlj
YXNlICJ1cGxvYWRjYW5jZWwiIDoNCgkJCQkJCXRoaXMuZmlyZSgidXBsb2FkY2FuY2VsIiwge29y
aWdpbkV2ZW50IDogYX0pOw0KCQkJCQkJYnJlYWs7DQoJCQkJCWNhc2UgInVwbG9hZGVycm9yIiA6
DQoJCQkJCQl0aGlzLmZpcmUoInVwbG9hZGVycm9yIiwgew0KCQkJCQkJCQkJb3JpZ2luRXZlbnQg
OiBhLA0KCQkJCQkJCQkJc3RhdHVzIDogYS5zdGF0dXMsDQoJCQkJCQkJCQlzdGF0dXNUZXh0IDog
YS5tZXNzYWdlLA0KCQkJCQkJCQkJc291cmNlIDogYS5zb3VyY2UNCgkJCQkJCQkJfSk7DQoJCQkJ
fQ0KCQl9LA0KCQlzdGFydFVwbG9hZCA6IGZ1bmN0aW9uKHVybCwgcG9zdFZhcnMsIGZpbGVGaWVs
ZE5hbWUpIHsNCgkJCWlmICh0aGlzLmdldCgidXBsb2FkZXIiKSkgew0KCQkJCXZhciB1cGxvYWRl
ciA9IHRoaXMuZ2V0KCJ1cGxvYWRlciIpLCBmaWxlRmllbGROYW1lID0gZmlsZUZpZWxkTmFtZSB8
fCAiRmlsZURhdGEiLCBpZCA9IHRoaXMuZ2V0KCJpZCIpLCBwb3N0VmFycyA9IHBvc3RWYXJzIHx8
IG51bGw7DQoJCQkJdXBsb2FkZXIub24oInVwbG9hZHN0YXJ0IiwgdGhpcy5zd2ZFdmVudEhhbmRs
ZXIsIHRoaXMpOw0KCQkJCXVwbG9hZGVyLm9uKCJ1cGxvYWRwcm9ncmVzcyIsIHRoaXMuc3dmRXZl
bnRIYW5kbGVyLCB0aGlzKTsNCgkJCQl1cGxvYWRlci5vbigidXBsb2FkY29tcGxldGUiLCB0aGlz
LnN3ZkV2ZW50SGFuZGxlciwgdGhpcyk7DQoJCQkJdXBsb2FkZXIub24oInVwbG9hZGNvbXBsZXRl
ZGF0YSIsIHRoaXMuc3dmRXZlbnRIYW5kbGVyLCB0aGlzKTsNCgkJCQl1cGxvYWRlci5vbigidXBs
b2FkZXJyb3IiLCB0aGlzLnN3ZkV2ZW50SGFuZGxlciwgdGhpcyk7DQoJCQkJdGhpcy5yZW1haW5U
aW1lID0gdGhpcy5ieXRlc1NwZWVkID0gdGhpcy5ieXRlc1ByZXZMb2FkZWQgPSAwOw0KCQkJCXRo
aXMuYnl0ZXNTcGVlZHMgPSBbXTsNCgkJCQlpZiAoIXRoaXMucHJlVGltZSkNCgkJCQkJdGhpcy5w
cmVUaW1lID0gKG5ldyBEYXRlKS5nZXRUaW1lKCk7DQoJCQkJdXBsb2FkZXIuY2FsbFNXRigidXBs
b2FkIiwgW2lkLCB1cmwsIHBvc3RWYXJzLCBmaWxlRmllbGROYW1lXSk7DQoJCQl9DQoJCX0sDQoJ
CWNhbmNlbFVwbG9hZCA6IGZ1bmN0aW9uKCkgew0KCQkJdGhpcy5nZXQoInVwbG9hZGVyIikgDQoJ
CQkJJiYgKHRoaXMuZ2V0KCJ1cGxvYWRlciIpLmNhbGxTV0YoImNhbmNlbCIsIFt0aGlzLmdldCgi
aWQiKV0pLCB0aGlzLmZpcmUoInVwbG9hZGNhbmNlbCIpKTsNCgkJfQ0KCX07DQoJDQoJZnVuY3Rp
b24gU3RyZWFtUHJvdmlkZXIoYSkgew0KCQl0aGlzLmJ1dHRvbkJpbmRpbmcgPSB0aGlzLnF1ZXVl
ID0gdGhpcy5maWxlSW5wdXRGaWVsZCA9IG51bGw7DQoJCXRoaXMuY29uZmlnID0gew0KCQkJZW5h
YmxlZCA6ICEwLA0KCQkJbXVsdGlwbGVGaWxlcyA6ICEwLA0KCQkJZHJhZ0FuZERyb3BBcmVhIDog
IiIsDQoJCQlkcmFnQW5kRHJvcFRpcHMgOiAiIiwNCgkJCWZpbGVGaWx0ZXJzIDogYUZpbHRlcnMs
DQoJCQlmaWxlRmllbGROYW1lIDogIkZpbGVEYXRhIiwNCgkJCXNpbUxpbWl0IDogMSwNCgkJCXJl
dHJ5Q291bnQgOiAzLA0KCQkJcG9zdFZhcnNQZXJGaWxlIDoge30sDQoJCQl1cGxvYWRVUkwgOiAi
L3VwbG9hZCINCgkJfTsNCgkJUGFyZW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7DQoJfQ0KCVN0
cmVhbVByb3ZpZGVyLnByb3RvdHlwZSA9IHsNCgkJY29uc3RydWN0b3IgOiBTdHJlYW1Qcm92aWRl
ciwNCgkJbmFtZSA6ICJzdHJlYW1fcHJvdmlkZXIiLA0KCQlpbml0aWFsaXplcjogZnVuY3Rpb24o
KXsNCgkJCXRoaXMucHVibGlzaCgiZmlsZXNlbGVjdCIpOw0KCQkJdGhpcy5wdWJsaXNoKCJ1cGxv
YWRzdGFydCIpOw0KCQkJdGhpcy5wdWJsaXNoKCJmaWxldXBsb2Fkc3RhcnQiKTsNCgkJCXRoaXMu
cHVibGlzaCgidXBsb2FkcHJvZ3Jlc3MiKTsNCgkJCXRoaXMucHVibGlzaCgidG90YWx1cGxvYWRw
cm9ncmVzcyIpOw0KCQkJdGhpcy5wdWJsaXNoKCJ1cGxvYWRjb21wbGV0ZSIpOw0KCQkJdGhpcy5w
dWJsaXNoKCJhbGx1cGxvYWRzY29tcGxldGUiKTsNCgkJCXRoaXMucHVibGlzaCgidXBsb2FkZXJy
b3IiKTsNCgkJCXRoaXMucHVibGlzaCgiZHJhZ2VudGVyIik7DQoJCQl0aGlzLnB1Ymxpc2goImRy
YWdvdmVyIik7DQoJCQl0aGlzLnB1Ymxpc2goImRyYWdsZWF2ZSIpOw0KCQkJdGhpcy5wdWJsaXNo
KCJkcm9wIik7DQoJCX0sDQoJCXJlbmRlciA6IGZ1bmN0aW9uKGEpIHsNCgkJCWEgJiYgKHRoaXMu
cmVuZGVyVUkoYSksIHRoaXMuYmluZFVJKCkpOw0KCQl9LA0KCQlyZW5kZXJVSSA6IGZ1bmN0aW9u
KGEpIHsNCgkJCXRoaXMuY29udGVudEJveCA9IGE7DQoJCQl0aGlzLmZpbGVJbnB1dEZpZWxkID0g
ZkNyZWF0ZUNvbnRlbnRFbGUoIjxpbnB1dCB0eXBlPSdmaWxlJyBzdHlsZT0ndmlzaWJpbGl0eTpo
aWRkZW47d2lkdGg6MHB4O2hlaWdodDowcHg7Jz4iKTsNCgkJCXRoaXMuY29udGVudEJveC5hcHBl
bmRDaGlsZCh0aGlzLmZpbGVJbnB1dEZpZWxkKTsNCgkJCXRoaXMuZ2V0KCJkcmFnQW5kRHJvcEFy
ZWEiKSAmJiAhdGhpcy5nZXQoImRyYWdBbmREcm9wQXJlYSIpLm5vZGVUeXBlICYmIHRoaXMuc2V0
KCJkcmFnQW5kRHJvcEFyZWEiLCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldCgiZHJh
Z0FuZERyb3BBcmVhIikpKTsgDQoJCQliRHJhZ2dhYmxlICYmIHRoaXMuZ2V0KCJkcmFnQW5kRHJv
cEFyZWEiKSAmJiAoZkFkZENsYXNzKHRoaXMuZ2V0KCJkcmFnQW5kRHJvcEFyZWEiKSwgJ3N0cmVh
bS1icm93c2UtZHJhZy1maWxlcy1hcmVhJyksIHRoaXMuZ2V0KCJkcmFnQW5kRHJvcEFyZWEiKS5h
cHBlbmRDaGlsZChmQ3JlYXRlQ29udGVudEVsZSh0aGlzLmdldCgiZHJhZ0FuZERyb3BUaXBzIikp
KSk7DQoJCX0sDQoJCWJpbmRVSSA6IGZ1bmN0aW9uKCkgew0KCQkJdGhpcy5iaW5kU2VsZWN0QnV0
dG9uKCk7DQoJCQl0aGlzLnNldE11bHRpcGxlRmlsZXMoKTsNCgkJCXRoaXMuc2V0RmlsZUZpbHRl
cnMoKTsNCgkJCXRoaXMuYmluZERyb3BBcmVhKCk7DQoJCQl0aGlzLnRyaWdnZXJFbmFibGVkKCk7
DQoJCQl0aGlzLmFmdGVyKCJtdWx0aXBsZUZpbGVzQ2hhbmdlIiwgdGhpcy5zZXRNdWx0aXBsZUZp
bGVzLCB0aGlzKTsNCgkJCXRoaXMuYWZ0ZXIoImZpbGVGaWx0ZXJzQ2hhbmdlIiwgdGhpcy5zZXRG
aWxlRmlsdGVycywgdGhpcyk7DQoJCQl0aGlzLmFmdGVyKCJlbmFibGVkQ2hhbmdlIiwgdGhpcy50
cmlnZ2VyRW5hYmxlZCwgdGhpcyk7DQoJCQl0aGlzLmFmdGVyKCJkcmFnQW5kRHJvcEFyZWFDaGFu
Z2UiLCB0aGlzLmJpbmREcm9wQXJlYSwgdGhpcyk7DQoJCQlmQWRkRXZlbnRMaXN0ZW5lcih0aGlz
LmZpbGVJbnB1dEZpZWxkLCAiY2hhbmdlIiwgZkV4dGVuZCh0aGlzLnVwZGF0ZUZpbGVMaXN0LCB0
aGlzKSk7DQoJCX0sDQoJCWJpbmREcm9wQXJlYSA6IGZ1bmN0aW9uKCkgew0KCQkJdmFyIGEgPSB0
aGlzLmdldCgiZHJhZ0FuZERyb3BBcmVhIik7DQoJCQl0aGlzLmRyb3BCaW5kaW5nID0gZkV4dGVu
ZCh0aGlzLmRyYWdFdmVudEhhbmRsZXIsIHRoaXMpOw0KCQkJbnVsbCAhPT0gYQkmJiAoZkFkZEV2
ZW50TGlzdGVuZXIoYSwgImRyb3AiLCB0aGlzLmRyb3BCaW5kaW5nKSwNCgkJCQkJCQlmQWRkRXZl
bnRMaXN0ZW5lcihhLCAiZHJhZ2VudGVyIiwgdGhpcy5kcm9wQmluZGluZyksDQoJCQkJCQkJZkFk
ZEV2ZW50TGlzdGVuZXIoYSwgImRyYWdvdmVyIiwgdGhpcy5kcm9wQmluZGluZyksDQoJCQkJCQkJ
ZkFkZEV2ZW50TGlzdGVuZXIoYSwgImRyYWdsZWF2ZSIsIHRoaXMuZHJvcEJpbmRpbmcpKTsNCgkJ
fSwNCgkJZHJhZ0V2ZW50SGFuZGxlciA6IGZ1bmN0aW9uKGV2dCkgew0KCQkJZXZ0ID0gZXZ0IHx8
IHdpbmRvdy5ldmVudDsNCgkJCWV2dC5wcmV2ZW50RGVmYXVsdCA/IGV2dC5wcmV2ZW50RGVmYXVs
dCgpIDogZXZ0LnJldHVyblZhbHVlID0gITE7DQoJCQlldnQuc3RvcFByb3BhZ2F0aW9uID8gZXZ0
LnN0b3BQcm9wYWdhdGlvbigpIDogZXZ0LmNhbmNlbEJ1YmJsZSA9ICEwOw0KCQkJc3dpdGNoIChl
dnQudHlwZSkgew0KCQkJCWNhc2UgImRyYWdlbnRlciIgOg0KCQkJCQl0aGlzLmZpcmUoImRyYWdl
bnRlciIpOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICJkcmFnb3ZlciIgOg0KCQkJCQl0aGlzLmZp
cmUoImRyYWdvdmVyIik7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgImRyYWdsZWF2ZSIgOg0KCQkJ
CQl0aGlzLmZpcmUoImRyYWdsZWF2ZSIpOw0KCQkJCQlicmVhazsNCgkJCQljYXNlICJkcm9wIiA6
DQoJCQkJCXZhciBjYWxsYmFjayA9IGZ1bmN0aW9uKGZpbGVzLCBzZWxmKSB7DQoJCQkJCQlmb3Ig
KHZhciBsaXN0ID0gW10sIGMgPSAwOyBjIDwgZmlsZXMubGVuZ3RoOyBjKyspDQoJCQkJCQkJbGlz
dC5wdXNoKG5ldyBTdHJlYW1VcGxvYWRlcihmaWxlc1tjXSkpOw0KCQkJCQkJMCA8IGxpc3QubGVu
Z3RoICYmIHNlbGYuZmlyZSgiZmlsZXNlbGVjdCIsIHtmaWxlTGlzdCA6IGxpc3R9KTsNCgkJCQkJ
fTsNCgkJCQkJaWYgKGJGb2xkZXIpIHsNCgkJCQkJCXZhciBpdGVtcyA9IGV2dC5kYXRhVHJhbnNm
ZXIuaXRlbXM7DQoJCQkJCQlpZiAoaXRlbXMubGVuZ3RoICYmIGl0ZW1zW2l0ZW1zLmxlbmd0aCAt
IDFdKSB7DQoJCQkJCQkJdmFyIGVudHJ5ID0gaXRlbXNbaXRlbXMubGVuZ3RoIC0gMV0ud2Via2l0
R2V0QXNFbnRyeSgpIHx8IGl0ZW1zW2l0ZW1zLmxlbmd0aCAtIDFdLmdldEFzRW50cnkoKTsNCgkJ
CQkJCQllbnRyeSAmJiB0aGlzLnRyYXZlcnNlRmlsZVRyZWUoZW50cnkuZmlsZXN5c3RlbS5yb290
LCBjYWxsYmFjayk7DQoJCQkJCQl9DQoJCQkJCX0gZWxzZSB7DQoJCQkJCQl2YXIgZmlsZXMgPSBl
dnQuZGF0YVRyYW5zZmVyLmZpbGVzOw0KCQkJCQkJaWYgKGV2dC5NT1pfU09VUkNFX01PVVNFKSB7
DQoJCQkJCQkJZm9yICh2YXIgbGlzdCA9IFtdLCBjID0gMDsgYyA8IGZpbGVzLmxlbmd0aDsgYysr
KQ0KCQkJCQkJCQlmaWxlc1tjXS5zaXplID4gMCAmJiBsaXN0LnB1c2goZmlsZXNbY10pOw0KCQkJ
CQkJCWZpbGVzID0gbGlzdDsNCgkJCQkJCX0NCgkJCQkJCWNhbGxiYWNrKGZpbGVzLCB0aGlzKTsN
CgkJCQkJfQ0KCQkJCQl0aGlzLmZpcmUoImRyb3AiKTsNCgkJCX0NCgkJfSwNCgkJdHJhdmVyc2VG
aWxlVHJlZSA6IGZ1bmN0aW9uIChkaXJlY3RvcnksIGNhbGxiYWNrKSB7DQoJCQljYWxsYmFjay5w
ZW5kaW5nIHx8IChjYWxsYmFjay5wZW5kaW5nID0gMCk7DQoJCQljYWxsYmFjay5maWxlcyB8fCAo
Y2FsbGJhY2suZmlsZXMgPSBbXSk7DQoJCQljYWxsYmFjay5wZW5kaW5nKys7DQoJCQl2YXIgc2Vs
ZiA9IHRoaXMsIHJlbGF0aXZlUGF0aCA9IGRpcmVjdG9yeS5mdWxsUGF0aC5yZXBsYWNlKC9eXC8v
LCAiIikucmVwbGFjZSgvKC4rPylcLz8kLywgIiQxLyIpLCByZWFkZXIgPSBkaXJlY3RvcnkuY3Jl
YXRlUmVhZGVyKCk7DQoJCQlyZWFkZXIucmVhZEVudHJpZXMoZnVuY3Rpb24oZW50cmllcykgew0K
CQkJCWNhbGxiYWNrLnBlbmRpbmctLTsNCgkJCQlpZiAoIWVudHJpZXMubGVuZ3RoKSB7DQoJCQkJ
CWZTaG93TWVzc2FnZSgiXHU1RkZEXHU3NTY1XHU3QTdBXHU2NTg3XHU0RUY2XHU1OTM5XHVGRjFB
YCIgKyByZWxhdGl2ZVBhdGggKyBkaXJlY3RvcnkubmFtZSArICJgIiwgdHJ1ZSk7DQoJCQkJfSBl
bHNlIHsNCgkJCQkJZm9yICh2YXIgaSA9IDA7IGkgPCBlbnRyaWVzLmxlbmd0aDsgaSsrKSB7DQoJ
CQkJCQl2YXIgZW50cnkgPSBlbnRyaWVzW2ldOw0KCQkJCQkJaWYgKGVudHJ5LmlzRmlsZSkgew0K
CQkJCQkJCWNhbGxiYWNrLnBlbmRpbmcrKzsNCgkJCQkJCQllbnRyeS5maWxlKGZ1bmN0aW9uKGYp
IHsNCgkJCQkJCQkJZi5SZWxhdGl2ZVBhdGggPSByZWxhdGl2ZVBhdGggKyBmLm5hbWU7IC8qKiBz
ZWxmIGRlZmluZSBhcmd1bWVudCAqLw0KCQkJCQkJCQljYWxsYmFjay5maWxlcy5wdXNoKGYpOw0K
CQkJCQkJCQkoLS1jYWxsYmFjay5wZW5kaW5nID09PSAwKSAmJiBjYWxsYmFjayhjYWxsYmFjay5m
aWxlcywgc2VsZik7DQoJCQkJCQkJfSk7DQoJCQkJCQkJY29udGludWU7DQoJCQkJCQl9DQoJCQkJ
CQlzZWxmLnRyYXZlcnNlRmlsZVRyZWUoZW50cnksIGNhbGxiYWNrKTsNCgkJCQkJfQ0KCQkJCX0N
CgkJCQkoY2FsbGJhY2sucGVuZGluZyA9PT0gMCkgJiYgY2FsbGJhY2soY2FsbGJhY2suZmlsZXMs
IHNlbGYpOw0KCQkJfSk7DQoJCX0sDQoJCXJlYmluZEZpbGVGaWVsZCA6IGZ1bmN0aW9uKCkgew0K
CQkJdGhpcy5maWxlSW5wdXRGaWVsZC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuZmlsZUlu
cHV0RmllbGQpOw0KCQkJdGhpcy5maWxlSW5wdXRGaWVsZCA9IGZDcmVhdGVDb250ZW50RWxlKCI8
aW5wdXQgdHlwZT0nZmlsZScgc3R5bGU9J3Zpc2liaWxpdHk6aGlkZGVuO3dpZHRoOjBweDtoZWln
aHQ6MHB4Oyc+Iik7DQoJCQl0aGlzLmNvbnRlbnRCb3guYXBwZW5kQ2hpbGQodGhpcy5maWxlSW5w
dXRGaWVsZCk7DQoJCQl0aGlzLmdldCgiZHJhZ0FuZERyb3BBcmVhIikgJiYgIXRoaXMuZ2V0KCJk
cmFnQW5kRHJvcEFyZWEiKS5ub2RlVHlwZSAmJiB0aGlzLnNldCgiZHJhZ0FuZERyb3BBcmVhIiwg
ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXQoImRyYWdBbmREcm9wQXJlYSIpKSk7IA0K
CQkJYkRyYWdnYWJsZSAmJiAoZkFkZENsYXNzKHRoaXMuZ2V0KCJkcmFnQW5kRHJvcEFyZWEiKSwg
J3N0cmVhbS1icm93c2UtZHJhZy1maWxlcy1hcmVhJykpOw0KCQkJdGhpcy5zZXRNdWx0aXBsZUZp
bGVzKCk7DQoJCQl0aGlzLnNldEZpbGVGaWx0ZXJzKCk7DQoJCQlmQWRkRXZlbnRMaXN0ZW5lcih0
aGlzLmZpbGVJbnB1dEZpZWxkLCAiY2hhbmdlIiwgZkV4dGVuZCh0aGlzLnVwZGF0ZUZpbGVMaXN0
LCB0aGlzKSk7DQoJCX0sDQoJCWJpbmRTZWxlY3RCdXR0b24gOiBmdW5jdGlvbigpIHsNCgkJCXRo
aXMuYnV0dG9uQmluZGluZyA9IGZFeHRlbmQodGhpcy5vcGVuRmlsZVNlbGVjdERpYWxvZywgdGhp
cyk7DQoJCQlmQWRkRXZlbnRMaXN0ZW5lcih0aGlzLmNvbnRlbnRCb3gsICJjbGljayIsIHRoaXMu
YnV0dG9uQmluZGluZyk7DQoJCX0sDQoJCXNldE11bHRpcGxlRmlsZXMgOiBmdW5jdGlvbigpIHsN
CgkJCSEwID09PSB0aGlzLmdldCgibXVsdGlwbGVGaWxlcyIpDQoJCQkJCSYmIHRoaXMuZmlsZUlu
cHV0RmllbGQuc2V0QXR0cmlidXRlKCJtdWx0aXBsZSIsICJtdWx0aXBsZSIpDQoJCX0sDQoJCXNl
dEZpbGVGaWx0ZXJzIDogZnVuY3Rpb24oKSB7DQoJCQl2YXIgYSA9IHRoaXMuZ2V0KCJmaWxlRmls
dGVycyIpOw0KCQkJMCA8IGEubGVuZ3RoID8gdGhpcy5maWxlSW5wdXRGaWVsZC5zZXRBdHRyaWJ1
dGUoImFjY2VwdCIsIGENCgkJCQkJCQkuam9pbigiLCIpKSA6IHRoaXMuZmlsZUlucHV0RmllbGQu
c2V0QXR0cmlidXRlKA0KCQkJCQkiYWNjZXB0IiwgIiIpDQoJCX0sDQoJCXRyaWdnZXJFbmFibGVk
IDogZnVuY3Rpb24oKSB7DQoJCQl2YXIgYSA9IHRoaXMuZ2V0KCJkcmFnQW5kRHJvcEFyZWEiKTsN
CgkJCWlmICh0aGlzLmdldCgiZW5hYmxlZCIpICYmIG51bGwgPT09IHRoaXMuYnV0dG9uQmluZGlu
ZykNCgkJCQl0aGlzLmJpbmRTZWxlY3RCdXR0b24oKSwgdGhpcy5iaW5kRHJvcEFyZWEoKSwgZlJl
bW92ZUNsYXNzKGEsICdzdHJlYW0tZGlzYWJsZWQnKTsNCgkJCWVsc2UgaWYgKCF0aGlzLmdldCgi
ZW5hYmxlZCIpICYmIHRoaXMuYnV0dG9uQmluZGluZykgew0KCQkJCWZSZW1vdmVFdmVudExpc3Rl
bmVyKHRoaXMuY29udGVudEJveCwgImNsaWNrIiwgdGhpcy5idXR0b25CaW5kaW5nKSwNCgkJCQl0
aGlzLmJ1dHRvbkJpbmRpbmcgPSBudWxsOw0KCQkJCQ0KCQkJCW51bGwgIT09IGEgJiYgdGhpcy5k
cm9wQmluZGluZyAhPSBudWxsICYmIChmUmVtb3ZlRXZlbnRMaXN0ZW5lcihhLCAiZHJvcCIsIHRo
aXMuZHJvcEJpbmRpbmcpLA0KCQkJCQkJCWZSZW1vdmVFdmVudExpc3RlbmVyKGEsICJkcmFnZW50
ZXIiLCB0aGlzLmRyb3BCaW5kaW5nKSwNCgkJCQkJCQlmUmVtb3ZlRXZlbnRMaXN0ZW5lcihhLCAi
ZHJhZ292ZXIiLCB0aGlzLmRyb3BCaW5kaW5nKSwNCgkJCQkJCQlmUmVtb3ZlRXZlbnRMaXN0ZW5l
cihhLCAiZHJhZ2xlYXZlIiwgdGhpcy5kcm9wQmluZGluZyksDQoJCQkJCQkJZkFkZENsYXNzKGEs
ICdzdHJlYW0tZGlzYWJsZWQnKSk7DQoJCQl9CQkJCQ0KCQl9LA0KCQl1cGRhdGVGaWxlTGlzdCA6
IGZ1bmN0aW9uKGEpIHsNCgkJCWZvciAodmFyIGEgPSBhLnRhcmdldC5maWxlcywgYiA9IFtdLCBj
ID0gMDsgYyA8IGEubGVuZ3RoOyBjKyspIHsNCgkJCQlpZiAoYVtjXS5uYW1lID09ICIuIikgY29u
dGludWU7DQoJCQkJYi5wdXNoKG5ldyBTdHJlYW1VcGxvYWRlcihhW2NdKSk7DQoJCQl9DQoJCQkw
IDwgYi5sZW5ndGggJiYgdGhpcy5maXJlKCJmaWxlc2VsZWN0Iiwge2ZpbGVMaXN0IDogYn0pOw0K
CQkJdGhpcy5yZWJpbmRGaWxlRmllbGQoKTsNCgkJfSwNCgkJb3BlbkZpbGVTZWxlY3REaWFsb2cg
OiBmdW5jdGlvbihhKSB7DQoJCQl0aGlzLmZpbGVJbnB1dEZpZWxkLmNsaWNrICYmIGEudGFyZ2V0
ICE9IHRoaXMuZmlsZUlucHV0RmllbGQgJiYgdGhpcy5maWxlSW5wdXRGaWVsZC5jbGljaygpOw0K
CQl9LA0KCQl1cGxvYWRFdmVudEhhbmRsZXIgOiBmdW5jdGlvbihhKSB7DQoJCQlzd2l0Y2ggKGEu
dHlwZSkgew0KCQkJCWNhc2UgImV4ZWN1dG9yOnVwbG9hZHN0YXJ0IiA6DQoJCQkJCXRoaXMuZmly
ZSgiZmlsZXVwbG9hZHN0YXJ0IiwgYSk7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgImV4ZWN1dG9y
OnVwbG9hZHByb2dyZXNzIiA6DQoJCQkJCXRoaXMuZmlyZSgidXBsb2FkcHJvZ3Jlc3MiLCBhKTsN
CgkJCQkJYnJlYWs7DQoJCQkJY2FzZSAidXBsb2FkZXJxdWV1ZTp0b3RhbHVwbG9hZHByb2dyZXNz
IiA6DQoJCQkJCXRoaXMuZmlyZSgidG90YWx1cGxvYWRwcm9ncmVzcyIsIGEpOw0KCQkJCQlicmVh
azsNCgkJCQljYXNlICJleGVjdXRvcjp1cGxvYWRjb21wbGV0ZSIgOg0KCQkJCQl0aGlzLmZpcmUo
InVwbG9hZGNvbXBsZXRlIiwgYSk7DQoJCQkJCWJyZWFrOw0KCQkJCWNhc2UgInVwbG9hZGVycXVl
dWU6YWxsdXBsb2Fkc2NvbXBsZXRlIiA6DQoJCQkJCXRoaXMucXVldWUgPSBudWxsOw0KCQkJCQl0
aGlzLmZpcmUoImFsbHVwbG9hZHNjb21wbGV0ZSIsIGEpOw0KCQkJCQlicmVhazsNCgkJCQljYXNl
ICJleGVjdXRvcjp1cGxvYWRlcnJvciIgOg0KCQkJCWNhc2UgInVwbG9hZGVycXVldWU6dXBsb2Fk
ZXJyb3IiIDoNCgkJCQkJdGhpcy5maXJlKCJ1cGxvYWRlcnJvciIsIGEpOw0KCQkJCQlicmVhazsN
CgkJCQljYXNlICJleGVjdXRvcjp1cGxvYWRjYW5jZWwiIDoNCgkJCQljYXNlICJ1cGxvYWRlcnF1
ZXVlOnVwbG9hZGNhbmNlbCIgOg0KCQkJCQl0aGlzLmZpcmUoInVwbG9hZGNhbmNlbCIsIGEpOw0K
CQkJfQ0KCQl9LA0KCQl1cGxvYWQgOiBmdW5jdGlvbih1cGxvYWRlciwgdXJsLCBwb3N0VmFycykg
ew0KCQkJdmFyIHVybCA9IHVybCB8fCB0aGlzLmdldCgidXBsb2FkVVJMIiksIHBvc3RWYXJzID0g
Zk1lcmdlSnNvbihwb3N0VmFycywgdGhpcy5nZXQoInBvc3RWYXJzUGVyRmlsZSIpKSwNCgkJCQlk
ID0gdXBsb2FkZXIuaWQsIHBvc3RWYXJzID0gcG9zdFZhcnMuaGFzT3duUHJvcGVydHkoZCkgPyBw
b3N0VmFyc1tkXSA6IHBvc3RWYXJzOw0KCQkJdXBsb2FkZXIgaW5zdGFuY2VvZiBTdHJlYW1VcGxv
YWRlcg0KCQkJCQkmJiAodXBsb2FkZXIub24oInVwbG9hZHN0YXJ0IiwgdGhpcy51cGxvYWRFdmVu
dEhhbmRsZXIsIHRoaXMpLA0KCQkJCQkJdXBsb2FkZXIub24oInVwbG9hZHByb2dyZXNzIiwgdGhp
cy51cGxvYWRFdmVudEhhbmRsZXIsIHRoaXMpLA0KCQkJCQkJdXBsb2FkZXIub24oInVwbG9hZGNv
bXBsZXRlIiwgdGhpcy51cGxvYWRFdmVudEhhbmRsZXIsIHRoaXMpLA0KCQkJCQkJdXBsb2FkZXIu
b24oInVwbG9hZGVycm9yIiwgdGhpcy51cGxvYWRFdmVudEhhbmRsZXIsIHRoaXMpLA0KCQkJCQkJ
dXBsb2FkZXIub24oInVwbG9hZGNhbmNlbCIsIHRoaXMudXBsb2FkRXZlbnRIYW5kbGVyLCB0aGlz
KSwNCgkJCQkJCXVwbG9hZGVyLnN0YXJ0VXBsb2FkKHVybCwgcG9zdFZhcnMsIHRoaXMuZ2V0KCJm
aWxlRmllbGROYW1lIikpKTsNCgkJfQ0KCX07DQoJDQoJdmFyIFN0cmVhbVVwbG9hZGVyID0gZnVu
Y3Rpb24oKXsNCgkJdGhpcy5yZW1haW5UaW1lID0gdGhpcy5ieXRlc1NwZWVkID0gdGhpcy5ieXRl
c1N0YXJ0ID0gdGhpcy5ieXRlc1ByZXZMb2FkZWQgPSAwOw0KCQl0aGlzLmJ5dGVzU3BlZWRzID0g
W107DQoJCXRoaXMucmV0cnlUaW1lcyA9IHRoaXMucHJlVGltZSA9IDA7DQoJCXRoaXMuY29uZmln
ID0gew0KCQkJaWQgOiAiIiwNCgkJCW5hbWUgOiAiIiwNCgkJCXNpemUgOiAiIiwNCgkJCXR5cGUg
OiAiIiwNCgkJCWRhdGVDcmVhdGVkIDogIiIsDQoJCQlkYXRlTW9kaWZpZWQgOiAiIiwNCgkJCXVw
bG9hZGVyIDogIiIsDQoJCQl1cGxvYWRVUkwgOiAiIiwNCgkJCXNlcnZlckFkZHJlc3MgOiAiIiwN