fork-openpgpjs/test/test-bundle.js
seancolyer b7d0322b8e Test cleanup, and fall out from that. test/crypto/openpgp.crypto.js is
still broken because DSA still has issues. I'm guessing elgamal will too
once the DSA ones are fixed.
2013-08-18 17:37:37 -04:00

12625 lines
1.1 MiB
Raw Blame History

require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
JXG = {exists: (function(undefined){return function(v){return !(v===undefined || v===null);}})()};
JXG.decompress = function(str) {return unescape((new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(str))).unzip()[0][0]);};
/*
Copyright 2008-2012
Matthias Ehmann,
Michael Gerhaeuser,
Carsten Miller,
Bianca Valentin,
Alfred Wassermann,
Peter Wilfahrt
This file is part of JSXGraph.
Dual licensed under the Apache License Version 2.0, or LGPL Version 3 licenses.
You should have received a copy of the GNU Lesser General Public License
along with JSXCompressor. If not, see <http://www.gnu.org/licenses/>.
You should have received a copy of the Apache License along with JSXCompressor.
If not, see <http://www.apache.org/licenses/>.
*/
/**
* @class Util class
* @classdesc Utilities for uncompressing and base64 decoding
* Class for gunzipping, unzipping and base64 decoding of files.
* It is used for reading GEONExT, Geogebra and Intergeo files.
*
* Only Huffman codes are decoded in gunzip.
* The code is based on the source code for gunzip.c by Pasi Ojala
* {@link http://www.cs.tut.fi/~albert/Dev/gunzip/gunzip.c}
* {@link http://www.cs.tut.fi/~albert}
*/
JXG.Util = {};
/**
* Unzip zip files
*/
JXG.Util.Unzip = function (barray){
var outputArr = [],
output = "",
debug = false,
gpflags,
files = 0,
unzipped = [],
crc,
buf32k = new Array(32768),
bIdx = 0,
modeZIP=false,
CRC, SIZE,
bitReverse = [
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
],
cplens = [
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
],
cplext = [
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99
], /* 99==invalid */
cpdist = [
0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0007, 0x0009, 0x000d,
0x0011, 0x0019, 0x0021, 0x0031, 0x0041, 0x0061, 0x0081, 0x00c1,
0x0101, 0x0181, 0x0201, 0x0301, 0x0401, 0x0601, 0x0801, 0x0c01,
0x1001, 0x1801, 0x2001, 0x3001, 0x4001, 0x6001
],
cpdext = [
0, 0, 0, 0, 1, 1, 2, 2,
3, 3, 4, 4, 5, 5, 6, 6,
7, 7, 8, 8, 9, 9, 10, 10,
11, 11, 12, 12, 13, 13
],
border = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
bA = barray,
bytepos=0,
bitpos=0,
bb = 1,
bits=0,
NAMEMAX = 256,
nameBuf = [],
fileout;
function readByte(){
bits+=8;
if (bytepos<bA.length){
//if (debug)
// document.write(bytepos+": "+bA[bytepos]+"<br>");
return bA[bytepos++];
} else
return -1;
};
function byteAlign(){
bb = 1;
};
function readBit(){
var carry;
bits++;
carry = (bb & 1);
bb >>= 1;
if (bb==0){
bb = readByte();
carry = (bb & 1);
bb = (bb>>1) | 0x80;
}
return carry;
};
function readBits(a) {
var res = 0,
i = a;
while(i--) {
res = (res<<1) | readBit();
}
if(a) {
res = bitReverse[res]>>(8-a);
}
return res;
};
function flushBuffer(){
//document.write('FLUSHBUFFER:'+buf32k);
bIdx = 0;
};
function addBuffer(a){
SIZE++;
//CRC=updcrc(a,crc);
buf32k[bIdx++] = a;
outputArr.push(String.fromCharCode(a));
//output+=String.fromCharCode(a);
if(bIdx==0x8000){
//document.write('ADDBUFFER:'+buf32k);
bIdx=0;
}
};
function HufNode() {
this.b0=0;
this.b1=0;
this.jump = null;
this.jumppos = -1;
};
var LITERALS = 288;
var literalTree = new Array(LITERALS);
var distanceTree = new Array(32);
var treepos=0;
var Places = null;
var Places2 = null;
var impDistanceTree = new Array(64);
var impLengthTree = new Array(64);
var len = 0;
var fpos = new Array(17);
fpos[0]=0;
var flens;
var fmax;
function IsPat() {
while (1) {
if (fpos[len] >= fmax)
return -1;
if (flens[fpos[len]] == len)
return fpos[len]++;
fpos[len]++;
}
};
function Rec() {
var curplace = Places[treepos];
var tmp;
if (debug)
document.write("<br>len:"+len+" treepos:"+treepos);
if(len==17) { //war 17
return -1;
}
treepos++;
len++;
tmp = IsPat();
if (debug)
document.write("<br>IsPat "+tmp);
if(tmp >= 0) {
curplace.b0 = tmp; /* leaf cell for 0-bit */
if (debug)
document.write("<br>b0 "+curplace.b0);
} else {
/* Not a Leaf cell */
curplace.b0 = 0x8000;
if (debug)
document.write("<br>b0 "+curplace.b0);
if(Rec())
return -1;
}
tmp = IsPat();
if(tmp >= 0) {
curplace.b1 = tmp; /* leaf cell for 1-bit */
if (debug)
document.write("<br>b1 "+curplace.b1);
curplace.jump = null; /* Just for the display routine */
} else {
/* Not a Leaf cell */
curplace.b1 = 0x8000;
if (debug)
document.write("<br>b1 "+curplace.b1);
curplace.jump = Places[treepos];
curplace.jumppos = treepos;
if(Rec())
return -1;
}
len--;
return 0;
};
function CreateTree(currentTree, numval, lengths, show) {
var i;
/* Create the Huffman decode tree/table */
//document.write("<br>createtree<br>");
if (debug)
document.write("currentTree "+currentTree+" numval "+numval+" lengths "+lengths+" show "+show);
Places = currentTree;
treepos=0;
flens = lengths;
fmax = numval;
for (i=0;i<17;i++)
fpos[i] = 0;
len = 0;
if(Rec()) {
//fprintf(stderr, "invalid huffman tree\n");
if (debug)
alert("invalid huffman tree\n");
return -1;
}
if (debug){
document.write('<br>Tree: '+Places.length);
for (var a=0;a<32;a++){
document.write("Places["+a+"].b0="+Places[a].b0+"<br>");
document.write("Places["+a+"].b1="+Places[a].b1+"<br>");
}
}
/*if(show) {
var tmp;
for(tmp=currentTree;tmp<Places;tmp++) {
fprintf(stdout, "0x%03x 0x%03x (0x%04x)",tmp-currentTree, tmp->jump?tmp->jump-currentTree:0,(tmp->jump?tmp->jump-currentTree:0)*6+0xcf0);
if(!(tmp.b0 & 0x8000)) {
//fprintf(stdout, " 0x%03x (%c)", tmp->b0,(tmp->b0<256 && isprint(tmp->b0))?tmp->b0:'<27>');
}
if(!(tmp.b1 & 0x8000)) {
if((tmp.b0 & 0x8000))
fprintf(stdout, " ");
fprintf(stdout, " 0x%03x (%c)", tmp->b1,(tmp->b1<256 && isprint(tmp->b1))?tmp->b1:'<27>');
}
fprintf(stdout, "\n");
}
}*/
return 0;
};
function DecodeValue(currentTree) {
var len, i,
xtreepos=0,
X = currentTree[xtreepos],
b;
/* decode one symbol of the data */
while(1) {
b=readBit();
if (debug)
document.write("b="+b);
if(b) {
if(!(X.b1 & 0x8000)){
if (debug)
document.write("ret1");
return X.b1; /* If leaf node, return data */
}
X = X.jump;
len = currentTree.length;
for (i=0;i<len;i++){
if (currentTree[i]===X){
xtreepos=i;
break;
}
}
//xtreepos++;
} else {
if(!(X.b0 & 0x8000)){
if (debug)
document.write("ret2");
return X.b0; /* If leaf node, return data */
}
//X++; //??????????????????
xtreepos++;
X = currentTree[xtreepos];
}
}
if (debug)
document.write("ret3");
return -1;
};
function DeflateLoop() {
var last, c, type, i, len;
do {
/*if((last = readBit())){
fprintf(errfp, "Last Block: ");
} else {
fprintf(errfp, "Not Last Block: ");
}*/
last = readBit();
type = readBits(2);
switch(type) {
case 0:
if (debug)
alert("Stored\n");
break;
case 1:
if (debug)
alert("Fixed Huffman codes\n");
break;
case 2:
if (debug)
alert("Dynamic Huffman codes\n");
break;
case 3:
if (debug)
alert("Reserved block type!!\n");
break;
default:
if (debug)
alert("Unexpected value %d!\n", type);
break;
}
if(type==0) {
var blockLen, cSum;
// Stored
byteAlign();
blockLen = readByte();
blockLen |= (readByte()<<8);
cSum = readByte();
cSum |= (readByte()<<8);
if(((blockLen ^ ~cSum) & 0xffff)) {
document.write("BlockLen checksum mismatch\n");
}
while(blockLen--) {
c = readByte();
addBuffer(c);
}
} else if(type==1) {
var j;
/* Fixed Huffman tables -- fixed decode routine */
while(1) {
/*
256 0000000 0
: : :
279 0010111 23
0 00110000 48
: : :
143 10111111 191
280 11000000 192
: : :
287 11000111 199
144 110010000 400
: : :
255 111111111 511
Note the bit order!
*/
j = (bitReverse[readBits(7)]>>1);
if(j > 23) {
j = (j<<1) | readBit(); /* 48..255 */
if(j > 199) { /* 200..255 */
j -= 128; /* 72..127 */
j = (j<<1) | readBit(); /* 144..255 << */
} else { /* 48..199 */
j -= 48; /* 0..151 */
if(j > 143) {
j = j+136; /* 280..287 << */
/* 0..143 << */
}
}
} else { /* 0..23 */
j += 256; /* 256..279 << */
}
if(j < 256) {
addBuffer(j);
//document.write("out:"+String.fromCharCode(j));
/*fprintf(errfp, "@%d %02x\n", SIZE, j);*/
} else if(j == 256) {
/* EOF */
break;
} else {
var len, dist;
j -= 256 + 1; /* bytes + EOF */
len = readBits(cplext[j]) + cplens[j];
j = bitReverse[readBits(5)]>>3;
if(cpdext[j] > 8) {
dist = readBits(8);
dist |= (readBits(cpdext[j]-8)<<8);
} else {
dist = readBits(cpdext[j]);
}
dist += cpdist[j];
/*fprintf(errfp, "@%d (l%02x,d%04x)\n", SIZE, len, dist);*/
for(j=0;j<len;j++) {
var c = buf32k[(bIdx - dist) & 0x7fff];
addBuffer(c);
}
}
} // while
} else if(type==2) {
var j, n, literalCodes, distCodes, lenCodes;
var ll = new Array(288+32); // "static" just to preserve stack
// Dynamic Huffman tables
literalCodes = 257 + readBits(5);
distCodes = 1 + readBits(5);
lenCodes = 4 + readBits(4);
//document.write("<br>param: "+literalCodes+" "+distCodes+" "+lenCodes+"<br>");
for(j=0; j<19; j++) {
ll[j] = 0;
}
// Get the decode tree code lengths
//document.write("<br>");
for(j=0; j<lenCodes; j++) {
ll[border[j]] = readBits(3);
//document.write(ll[border[j]]+" ");
}
//fprintf(errfp, "\n");
//document.write('<br>ll:'+ll);
len = distanceTree.length;
for (i=0; i<len; i++)
distanceTree[i]=new HufNode();
if(CreateTree(distanceTree, 19, ll, 0)) {
flushBuffer();
return 1;
}
if (debug){
document.write("<br>distanceTree");
for(var a=0;a<distanceTree.length;a++){
document.write("<br>"+distanceTree[a].b0+" "+distanceTree[a].b1+" "+distanceTree[a].jump+" "+distanceTree[a].jumppos);
/*if (distanceTree[a].jumppos!=-1)
document.write(" "+distanceTree[a].jump.b0+" "+distanceTree[a].jump.b1);
*/
}
}
//document.write('<BR>tree created');
//read in literal and distance code lengths
n = literalCodes + distCodes;
i = 0;
var z=-1;
if (debug)
document.write("<br>n="+n+" bits: "+bits+"<br>");
while(i < n) {
z++;
j = DecodeValue(distanceTree);
if (debug)
document.write("<br>"+z+" i:"+i+" decode: "+j+" bits "+bits+"<br>");
if(j<16) { // length of code in bits (0..15)
ll[i++] = j;
} else if(j==16) { // repeat last length 3 to 6 times
var l;
j = 3 + readBits(2);
if(i+j > n) {
flushBuffer();
return 1;
}
l = i ? ll[i-1] : 0;
while(j--) {
ll[i++] = l;
}
} else {
if(j==17) { // 3 to 10 zero length codes
j = 3 + readBits(3);
} else { // j == 18: 11 to 138 zero length codes
j = 11 + readBits(7);
}
if(i+j > n) {
flushBuffer();
return 1;
}
while(j--) {
ll[i++] = 0;
}
}
}
/*for(j=0; j<literalCodes+distCodes; j++) {
//fprintf(errfp, "%d ", ll[j]);
if ((j&7)==7)
fprintf(errfp, "\n");
}
fprintf(errfp, "\n");*/
// Can overwrite tree decode tree as it is not used anymore
len = literalTree.length;
for (i=0; i<len; i++)
literalTree[i]=new HufNode();
if(CreateTree(literalTree, literalCodes, ll, 0)) {
flushBuffer();
return 1;
}
len = literalTree.length;
for (i=0; i<len; i++)
distanceTree[i]=new HufNode();
var ll2 = new Array();
for (i=literalCodes; i <ll.length; i++){
ll2[i-literalCodes]=ll[i];
}
if(CreateTree(distanceTree, distCodes, ll2, 0)) {
flushBuffer();
return 1;
}
if (debug)
document.write("<br>literalTree");
outer:
while(1) {
j = DecodeValue(literalTree);
if(j >= 256) { // In C64: if carry set
var len, dist;
j -= 256;
if(j == 0) {
// EOF
break;
}
j--;
len = readBits(cplext[j]) + cplens[j];
j = DecodeValue(distanceTree);
if(cpdext[j] > 8) {
dist = readBits(8);
dist |= (readBits(cpdext[j]-8)<<8);
} else {
dist = readBits(cpdext[j]);
}
dist += cpdist[j];
while(len--) {
if(bIdx - dist < 0) {
break outer;
}
var c = buf32k[(bIdx - dist) & 0x7fff];
addBuffer(c);
}
} else {
addBuffer(j);
}
}
}
} while(!last);
flushBuffer();
byteAlign();
return 0;
};
JXG.Util.Unzip.prototype.unzipFile = function(name) {
var i;
this.unzip();
//alert(unzipped[0][1]);
for (i=0;i<unzipped.length;i++){
if(unzipped[i][1]==name) {
return unzipped[i][0];
}
}
};
JXG.Util.Unzip.prototype.deflate = function() {
outputArr = [];
var tmp = [];
modeZIP = false;
DeflateLoop();
if (debug)
alert(outputArr.join(''));
unzipped[files] = new Array(2);
unzipped[files][0] = outputArr.join('');
unzipped[files][1] = "DEFLATE";
files++;
return unzipped;
}
JXG.Util.Unzip.prototype.unzip = function() {
//convertToByteArray(input);
if (debug)
alert(bA);
/*for (i=0;i<bA.length*8;i++){
document.write(readBit());
if ((i+1)%8==0)
document.write(" ");
}*/
/*for (i=0;i<bA.length;i++){
document.write(readByte()+" ");
if ((i+1)%8==0)
document.write(" ");
}
for (i=0;i<bA.length;i++){
document.write(bA[i]+" ");
if ((i+1)%16==0)
document.write("<br>");
}
*/
//alert(bA);
nextFile();
return unzipped;
};
function nextFile(){
if (debug)
alert("NEXTFILE");
outputArr = [];
var tmp = [];
modeZIP = false;
tmp[0] = readByte();
tmp[1] = readByte();
if (debug)
alert("type: "+tmp[0]+" "+tmp[1]);
if (tmp[0] == parseInt("78",16) && tmp[1] == parseInt("da",16)){ //GZIP
if (debug)
alert("GEONExT-GZIP");
DeflateLoop();
if (debug)
alert(outputArr.join(''));
unzipped[files] = new Array(2);
unzipped[files][0] = outputArr.join('');
unzipped[files][1] = "geonext.gxt";
files++;
}
if (tmp[0] == parseInt("78",16) && tmp[1] == parseInt("9c",16)){ //ZLIB
if (debug)
alert("ZLIB");
DeflateLoop();
if (debug)
alert(outputArr.join(''));
unzipped[files] = new Array(2);
unzipped[files][0] = outputArr.join('');
unzipped[files][1] = "ZLIB";
files++;
}
if (tmp[0] == parseInt("1f",16) && tmp[1] == parseInt("8b",16)){ //GZIP
if (debug)
alert("GZIP");
//DeflateLoop();
skipdir();
if (debug)
alert(outputArr.join(''));
unzipped[files] = new Array(2);
unzipped[files][0] = outputArr.join('');
unzipped[files][1] = "file";
files++;
}
if (tmp[0] == parseInt("50",16) && tmp[1] == parseInt("4b",16)){ //ZIP
modeZIP = true;
tmp[2] = readByte();
tmp[3] = readByte();
if (tmp[2] == parseInt("3",16) && tmp[3] == parseInt("4",16)){
//MODE_ZIP
tmp[0] = readByte();
tmp[1] = readByte();
if (debug)
alert("ZIP-Version: "+tmp[1]+" "+tmp[0]/10+"."+tmp[0]%10);
gpflags = readByte();
gpflags |= (readByte()<<8);
if (debug)
alert("gpflags: "+gpflags);
var method = readByte();
method |= (readByte()<<8);
if (debug)
alert("method: "+method);
readByte();
readByte();
readByte();
readByte();
var crc = readByte();
crc |= (readByte()<<8);
crc |= (readByte()<<16);
crc |= (readByte()<<24);
var compSize = readByte();
compSize |= (readByte()<<8);
compSize |= (readByte()<<16);
compSize |= (readByte()<<24);
var size = readByte();
size |= (readByte()<<8);
size |= (readByte()<<16);
size |= (readByte()<<24);
if (debug)
alert("local CRC: "+crc+"\nlocal Size: "+size+"\nlocal CompSize: "+compSize);
var filelen = readByte();
filelen |= (readByte()<<8);
var extralen = readByte();
extralen |= (readByte()<<8);
if (debug)
alert("filelen "+filelen);
i = 0;
nameBuf = [];
while (filelen--){
var c = readByte();
if (c == "/" | c ==":"){
i = 0;
} else if (i < NAMEMAX-1)
nameBuf[i++] = String.fromCharCode(c);
}
if (debug)
alert("nameBuf: "+nameBuf);
//nameBuf[i] = "\0";
if (!fileout)
fileout = nameBuf;
var i = 0;
while (i < extralen){
c = readByte();
i++;
}
CRC = 0xffffffff;
SIZE = 0;
if (size = 0 && fileOut.charAt(fileout.length-1)=="/"){
//skipdir
if (debug)
alert("skipdir");
}
if (method == 8){
DeflateLoop();
if (debug)
alert(outputArr.join(''));
unzipped[files] = new Array(2);
unzipped[files][0] = outputArr.join('');
unzipped[files][1] = nameBuf.join('');
files++;
//return outputArr.join('');
}
skipdir();
}
}
};
function skipdir(){
var crc,
tmp = [],
compSize, size, os, i, c;
if ((gpflags & 8)) {
tmp[0] = readByte();
tmp[1] = readByte();
tmp[2] = readByte();
tmp[3] = readByte();
if (tmp[0] == parseInt("50",16) &&
tmp[1] == parseInt("4b",16) &&
tmp[2] == parseInt("07",16) &&
tmp[3] == parseInt("08",16))
{
crc = readByte();
crc |= (readByte()<<8);
crc |= (readByte()<<16);
crc |= (readByte()<<24);
} else {
crc = tmp[0] | (tmp[1]<<8) | (tmp[2]<<16) | (tmp[3]<<24);
}
compSize = readByte();
compSize |= (readByte()<<8);
compSize |= (readByte()<<16);
compSize |= (readByte()<<24);
size = readByte();
size |= (readByte()<<8);
size |= (readByte()<<16);
size |= (readByte()<<24);
if (debug)
alert("CRC:");
}
if (modeZIP)
nextFile();
tmp[0] = readByte();
if (tmp[0] != 8) {
if (debug)
alert("Unknown compression method!");
return 0;
}
gpflags = readByte();
if (debug){
if ((gpflags & ~(parseInt("1f",16))))
alert("Unknown flags set!");
}
readByte();
readByte();
readByte();
readByte();
readByte();
os = readByte();
if ((gpflags & 4)){
tmp[0] = readByte();
tmp[2] = readByte();
len = tmp[0] + 256*tmp[1];
if (debug)
alert("Extra field size: "+len);
for (i=0;i<len;i++)
readByte();
}
if ((gpflags & 8)){
i=0;
nameBuf=[];
while (c=readByte()){
if(c == "7" || c == ":")
i=0;
if (i<NAMEMAX-1)
nameBuf[i++] = c;
}
//nameBuf[i] = "\0";
if (debug)
alert("original file name: "+nameBuf);
}
if ((gpflags & 16)){
while (c=readByte()){
//FILE COMMENT
}
}
if ((gpflags & 2)){
readByte();
readByte();
}
DeflateLoop();
crc = readByte();
crc |= (readByte()<<8);
crc |= (readByte()<<16);
crc |= (readByte()<<24);
size = readByte();
size |= (readByte()<<8);
size |= (readByte()<<16);
size |= (readByte()<<24);
if (modeZIP)
nextFile();
};
};
/**
* Base64 encoding / decoding
* {@link http://www.webtoolkit.info/}
*/
JXG.Util.Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = [],
chr1, chr2, chr3, enc1, enc2, enc3, enc4,
i = 0;
input = JXG.Util.Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output.push([this._keyStr.charAt(enc1),
this._keyStr.charAt(enc2),
this._keyStr.charAt(enc3),
this._keyStr.charAt(enc4)].join(''));
}
return output.join('');
},
// public method for decoding
decode : function (input, utf8) {
var output = [],
chr1, chr2, chr3,
enc1, enc2, enc3, enc4,
i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output.push(String.fromCharCode(chr1));
if (enc3 != 64) {
output.push(String.fromCharCode(chr2));
}
if (enc4 != 64) {
output.push(String.fromCharCode(chr3));
}
}
output = output.join('');
if (utf8) {
output = JXG.Util.Base64._utf8_decode(output);
}
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = [],
i = 0,
c = 0, c2 = 0, c3 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string.push(String.fromCharCode(c));
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63)));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)));
i += 3;
}
}
return string.join('');
},
_destrip: function (stripped, wrap){
var lines = [], lineno, i,
destripped = [];
if (wrap==null)
wrap = 76;
stripped.replace(/ /g, "");
lineno = stripped.length / wrap;
for (i = 0; i < lineno; i++)
lines[i]=stripped.substr(i * wrap, wrap);
if (lineno != stripped.length / wrap)
lines[lines.length]=stripped.substr(lineno * wrap, stripped.length-(lineno * wrap));
for (i = 0; i < lines.length; i++)
destripped.push(lines[i]);
return destripped.join('\n');
},
decodeAsArray: function (input){
var dec = this.decode(input),
ar = [], i;
for (i=0;i<dec.length;i++){
ar[i]=dec.charCodeAt(i);
}
return ar;
},
decodeGEONExT : function (input) {
return decodeAsArray(destrip(input),false);
}
};
/**
* @private
*/
JXG.Util.asciiCharCodeAt = function(str,i){
var c = str.charCodeAt(i);
if (c>255){
switch (c) {
case 8364: c=128;
break;
case 8218: c=130;
break;
case 402: c=131;
break;
case 8222: c=132;
break;
case 8230: c=133;
break;
case 8224: c=134;
break;
case 8225: c=135;
break;
case 710: c=136;
break;
case 8240: c=137;
break;
case 352: c=138;
break;
case 8249: c=139;
break;
case 338: c=140;
break;
case 381: c=142;
break;
case 8216: c=145;
break;
case 8217: c=146;
break;
case 8220: c=147;
break;
case 8221: c=148;
break;
case 8226: c=149;
break;
case 8211: c=150;
break;
case 8212: c=151;
break;
case 732: c=152;
break;
case 8482: c=153;
break;
case 353: c=154;
break;
case 8250: c=155;
break;
case 339: c=156;
break;
case 382: c=158;
break;
case 376: c=159;
break;
default:
break;
}
}
return c;
};
/**
* Decoding string into utf-8
* @param {String} string to decode
* @return {String} utf8 decoded string
*/
JXG.Util.utf8Decode = function(utftext) {
var string = [];
var i = 0;
var c = 0, c1 = 0, c2 = 0, c3;
if (!JXG.exists(utftext)) return '';
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string.push(String.fromCharCode(c));
i++;
} else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string.push(String.fromCharCode(((c & 31) << 6) | (c2 & 63)));
i += 2;
} else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string.push(String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)));
i += 3;
}
};
return string.join('');
};
/**
* Generate a random uuid.
* http://www.broofa.com
* mailto:robert@broofa.com
*
* Copyright (c) 2010 Robert Kieffer
* Dual licensed under the MIT and GPL licenses.
*
* EXAMPLES:
* >>> Math.uuid()
* "92329D39-6F5C-4520-ABFC-AAB64544E172"
*/
JXG.Util.genUUID = function() {
// Private array of chars to use
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''),
uuid = new Array(36), rnd=0, r;
for (var i = 0; i < 36; i++) {
if (i==8 || i==13 || i==18 || i==23) {
uuid[i] = '-';
} else if (i==14) {
uuid[i] = '4';
} else {
if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
r = rnd & 0xf;
rnd = rnd >> 4;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
return uuid.join('');
};
module.exports = JXG;
},{}],2:[function(require,module,exports){
// Modified by Recurity Labs GmbH
// modified version of http://www.hanewin.net/encrypt/PGdecode.js:
/* OpenPGP encryption using RSA/AES
* Copyright 2005-2006 Herbert Hanewinkel, www.haneWIN.de
* version 2.0, check www.haneWIN.de for the latest version
* This software is provided as-is, without express or implied warranty.
* Permission to use, copy, modify, distribute or sell this software, with or
* without fee, for any purpose and by any individual or organization, is hereby
* granted, provided that the above copyright notice and this paragraph appear
* in all copies. Distribution as a part of an application or binary must
* include the above copyright notice in the documentation and/or other
* materials provided with the application or distribution.
*/
var util = require('../util'),
cipher = require('./cipher');
module.exports = {
/**
* An array of bytes, that is integers with values from 0 to 255
* @typedef {(Array|Uint8Array)} openpgp_byte_array
*/
/**
* Block cipher function
* @callback openpgp_cipher_block_fn
* @param {openpgp_byte_array} block A block to perform operations on
* @param {openpgp_byte_array} key to use in encryption/decryption
* @return {openpgp_byte_array} Encrypted/decrypted block
*/
// --------------------------------------
/**
* This function encrypts a given with the specified prefixrandom
* using the specified blockcipher to encrypt a message
* @param {String} prefixrandom random bytes of block_size length provided
* as a string to be used in prefixing the data
* @param {openpgp_cipher_block_fn} blockcipherfn the algorithm encrypt function to encrypt
* data in one block_size encryption.
* @param {Integer} block_size the block size in bytes of the algorithm used
* @param {String} plaintext data to be encrypted provided as a string
* @param {openpgp_byte_array} key key to be used to encrypt the data. This will be passed to the
* blockcipherfn
* @param {Boolean} resync a boolean value specifying if a resync of the
* IV should be used or not. The encrypteddatapacket uses the
* "old" style with a resync. Encryption within an
* encryptedintegrityprotecteddata packet is not resyncing the IV.
* @return {String} a string with the encrypted data
*/
encrypt: function (prefixrandom, cipherfn, plaintext, key, resync) {
cipherfn = new cipher[cipherfn](key);
var block_size = cipherfn.blockSize;
var FR = new Array(block_size);
var FRE = new Array(block_size);
prefixrandom = prefixrandom + prefixrandom.charAt(block_size-2) +prefixrandom.charAt(block_size-1);
util.print_debug("prefixrandom:"+util.hexstrdump(prefixrandom));
var ciphertext = "";
// 1. The feedback register (FR) is set to the IV, which is all zeros.
for (var i = 0; i < block_size; i++) FR[i] = 0;
// 2. FR is encrypted to produce FRE (FR Encrypted). This is the
// encryption of an all-zero value.
FRE = cipherfn.encrypt(FR);
// 3. FRE is xored with the first BS octets of random data prefixed to
// the plaintext to produce C[1] through C[BS], the first BS octets
// of ciphertext.
for (var i = 0; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ prefixrandom.charCodeAt(i));
// 4. FR is loaded with C[1] through C[BS].
for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i);
// 5. FR is encrypted to produce FRE, the encryption of the first BS
// octets of ciphertext.
FRE = cipherfn.encrypt(FR);
// 6. The left two octets of FRE get xored with the next two octets of
// data that were prefixed to the plaintext. This produces C[BS+1]
// and C[BS+2], the next two octets of ciphertext.
ciphertext += String.fromCharCode(FRE[0] ^ prefixrandom.charCodeAt(block_size));
ciphertext += String.fromCharCode(FRE[1] ^ prefixrandom.charCodeAt(block_size+1));
if (resync) {
// 7. (The resync step) FR is loaded with C3-C10.
for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i+2);
} else {
for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(i);
}
// 8. FR is encrypted to produce FRE.
FRE = cipherfn.encrypt(FR, key);
if (resync) {
// 9. FRE is xored with the first 8 octets of the given plaintext, now
// that we have finished encrypting the 10 octets of prefixed data.
// This produces C11-C18, the next 8 octets of ciphertext.
for (var i = 0; i < block_size; i++)
ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(i));
for(n=block_size+2; n < plaintext.length; n+=block_size) {
// 10. FR is loaded with C11-C18
for (var i = 0; i < block_size; i++) FR[i] = ciphertext.charCodeAt(n+i);
// 11. FR is encrypted to produce FRE.
FRE = cipherfn.encrypt(FR);
// 12. FRE is xored with the next 8 octets of plaintext, to produce the
// next 8 octets of ciphertext. These are loaded into FR and the
// process is repeated until the plaintext is used up.
for (var i = 0; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt((n-2)+i));
}
}
else {
plaintext = " "+plaintext;
// 9. FRE is xored with the first 8 octets of the given plaintext, now
// that we have finished encrypting the 10 octets of prefixed data.
// This produces C11-C18, the next 8 octets of ciphertext.
for (var i = 2; i < block_size; i++) ciphertext += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(i));
var tempCiphertext = ciphertext.substring(0,2*block_size).split('');
var tempCiphertextString = ciphertext.substring(block_size);
for(n=block_size; n<plaintext.length; n+=block_size) {
// 10. FR is loaded with C11-C18
for (var i = 0; i < block_size; i++) FR[i] = tempCiphertextString.charCodeAt(i);
tempCiphertextString='';
// 11. FR is encrypted to produce FRE.
FRE = cipherfn.encrypt(FR);
// 12. FRE is xored with the next 8 octets of plaintext, to produce the
// next 8 octets of ciphertext. These are loaded into FR and the
// process is repeated until the plaintext is used up.
for (var i = 0; i < block_size; i++){ tempCiphertext.push(String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(n+i)));
tempCiphertextString += String.fromCharCode(FRE[i] ^ plaintext.charCodeAt(n+i));
}
}
ciphertext = tempCiphertext.join('');
}
ciphertext = ciphertext.substring(0, plaintext.length + 2 + block_size);
return ciphertext;
},
/**
* Decrypts the prefixed data for the Modification Detection Code (MDC) computation
* @param {openpgp_block_cipher_fn} cipherfn.encrypt Cipher function to use
* @param {Integer} block_size Blocksize of the algorithm
* @param {openpgp_byte_array} key The key for encryption
* @param {String} ciphertext The encrypted data
* @return {String} plaintext Data of D(ciphertext) with blocksize length +2
*/
mdc: function (cipherfn, key, ciphertext) {
cipherfn = new cipher[cipherfn](key);
var block_size = cipherfn.blockSize;
var iblock = new Array(block_size);
var ablock = new Array(block_size);
var i;
// initialisation vector
for(i=0; i < block_size; i++) iblock[i] = 0;
iblock = cipherfn.encrypt(iblock);
for(i = 0; i < block_size; i++)
{
ablock[i] = ciphertext.charCodeAt(i);
iblock[i] ^= ablock[i];
}
ablock = cipherfn.encrypt(ablock);
return util.bin2str(iblock)+
String.fromCharCode(ablock[0]^ciphertext.charCodeAt(block_size))+
String.fromCharCode(ablock[1]^ciphertext.charCodeAt(block_size+1));
},
/**
* This function decrypts a given plaintext using the specified
* blockcipher to decrypt a message
* @param {openpgp_cipher_block_fn} blockcipherfn The algorithm _encrypt_ function to encrypt
* data in one block_size encryption.
* @param {Integer} block_size the block size in bytes of the algorithm used
* @param {String} plaintext ciphertext to be decrypted provided as a string
* @param {openpgp_byte_array} key key to be used to decrypt the ciphertext. This will be passed to the
* blockcipherfn
* @param {Boolean} resync a boolean value specifying if a resync of the
* IV should be used or not. The encrypteddatapacket uses the
* "old" style with a resync. Decryption within an
* encryptedintegrityprotecteddata packet is not resyncing the IV.
* @return {String} a string with the plaintext data
*/
decrypt: function (cipherfn, key, ciphertext, resync) {
cipherfn = new cipher[cipherfn](key);
var block_size = cipherfn.blockSize;
var iblock = new Array(block_size);
var ablock = new Array(block_size);
var i, n = '';
var text = [];
// initialisation vector
for(i=0; i < block_size; i++) iblock[i] = 0;
iblock = cipherfn.encrypt(iblock, key);
for(i = 0; i < block_size; i++)
{
ablock[i] = ciphertext.charCodeAt(i);
iblock[i] ^= ablock[i];
}
ablock = cipherfn.encrypt(ablock, key);
// test check octets
if(iblock[block_size-2]!=(ablock[0]^ciphertext.charCodeAt(block_size))
|| iblock[block_size-1]!=(ablock[1]^ciphertext.charCodeAt(block_size+1)))
{
throw new Error('Invalid data.');
}
/* RFC4880: Tag 18 and Resync:
* [...] Unlike the Symmetrically Encrypted Data Packet, no
* special CFB resynchronization is done after encrypting this prefix
* data. See "OpenPGP CFB Mode" below for more details.
*/
if (resync) {
for(i=0; i<block_size; i++) iblock[i] = ciphertext.charCodeAt(i+2);
for(n=block_size+2; n<ciphertext.length; n+=block_size)
{
ablock = cipherfn.encrypt(iblock);
for(i = 0; i<block_size && i+n < ciphertext.length; i++)
{
iblock[i] = ciphertext.charCodeAt(n+i);
text.push(String.fromCharCode(ablock[i]^iblock[i]));
}
}
} else {
for(i=0; i<block_size; i++) iblock[i] = ciphertext.charCodeAt(i);
for(n=block_size; n<ciphertext.length; n+=block_size)
{
ablock = cipherfn.encrypt(iblock);
for(i = 0; i<block_size && i+n < ciphertext.length; i++)
{
iblock[i] = ciphertext.charCodeAt(n+i);
text.push(String.fromCharCode(ablock[i]^iblock[i]));
}
}
}
var n = resync ? 0 : 2;
text = text.join('');
text = text.substring(n, ciphertext.length - block_size - 2 + n);
return text;
},
normalEncrypt: function(cipherfn, key, plaintext, iv) {
cipherfn = new cipher[cipherfn](key);
var block_size = cipherfn.blockSize;
var blocki ="";
var blockc = "";
var pos = 0;
var cyphertext = [];
var tempBlock = [];
blockc = iv.substring(0,block_size);
while (plaintext.length > block_size*pos) {
var encblock = cipherfn.encrypt(util.str2bin(blockc));
blocki = plaintext.substring((pos*block_size),(pos*block_size)+block_size);
for (var i=0; i < blocki.length; i++)
tempBlock.push(String.fromCharCode(blocki.charCodeAt(i) ^ encblock[i]));
blockc = tempBlock.join('');
tempBlock = [];
cyphertext.push(blockc);
pos++;
}
return cyphertext.join('');
},
normalDecrypt: function(cipherfn, key, ciphertext, iv) {
cipherfn = new cipher[cipherfn](key);
var block_size = cipherfn.blockSize;
var blockp ="";
var pos = 0;
var plaintext = [];
var offset = 0;
if (iv == null)
for (var i = 0; i < block_size; i++) blockp += String.fromCharCode(0);
else
blockp = iv.substring(0,block_size);
while (ciphertext.length > (block_size*pos)) {
var decblock = cipherfn.encrypt(util.str2bin(blockp));
blockp = ciphertext.substring((pos*(block_size))+offset,(pos*(block_size))+(block_size)+offset);
for (var i=0; i < blockp.length; i++) {
plaintext.push(String.fromCharCode(blockp.charCodeAt(i) ^ decblock[i]));
}
pos++;
}
return plaintext.join('');
}
}
},{"../util":52,"./cipher":7}],3:[function(require,module,exports){
/* Rijndael (AES) Encryption
* Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
* version 1.1, check www.haneWIN.de for the latest version
* This software is provided as-is, without express or implied warranty.
* Permission to use, copy, modify, distribute or sell this software, with or
* without fee, for any purpose and by any individual or organization, is hereby
* granted, provided that the above copyright notice and this paragraph appear
* in all copies. Distribution as a part of an application or binary must
* include the above copyright notice in the documentation and/or other
* materials provided with the application or distribution.
*/
var util = require('../../util');
// The round constants used in subkey expansion
var Rcon = [
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ];
// Precomputed lookup table for the SBox
var S = [
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171,
118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113,
216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214,
179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69,
249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68,
23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73,
6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37,
46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225,
248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187,
22 ];
var T1 = [
0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6,
0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,
0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec,
0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,
0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b,
0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9,
0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d,
0x28181830, 0xa1969637, 0x0f05050a, 0xb59a9a2f,
0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea,
0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,
0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d,
0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,
0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972,
0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511,
0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b,
0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05,
0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142,
0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,
0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e,
0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,
0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b,
0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14,
0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4,
0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2,
0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949,
0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,
0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c,
0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,
0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc,
0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27,
0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433,
0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9,
0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a,
0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,
0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c ];
var T2 = [
0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d,
0xf2f2ff0d, 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154,
0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a,
0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea,
0x9c9c23bf, 0xa4a453f7, 0x7272e496, 0xc0c09b5b,
0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908,
0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e,
0x18183028, 0x969637a1, 0x05050a0f, 0x9a9a2fb5,
0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f,
0x0909121b, 0x83831d9e, 0x2c2c5874, 0x1a1a342e,
0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce,
0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed,
0x6a6ad4be, 0xcbcb8d46, 0xbebe67d9, 0x3939724b,
0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194,
0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3,
0x5151a2f3, 0xa3a35dfe, 0x404080c0, 0x8f8f058a,
0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263,
0x10102030, 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d,
0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39,
0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f,
0x22224466, 0x2a2a547e, 0x90903bab, 0x88880b83,
0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e,
0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6,
0x919139a8, 0x959531a4, 0xe4e4d337, 0x7979f28b,
0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0,
0x6c6cd8b4, 0x5656acfa, 0xf4f4f307, 0xeaeacf25,
0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72,
0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85,
0x7070e090, 0x3e3e7c42, 0xb5b571c4, 0x6666ccaa,
0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9,
0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7,
0x9b9b2db6, 0x1e1e3c22, 0x87871592, 0xe9e9c920,
0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17,
0xbfbf65da, 0xe6e6d731, 0x424284c6, 0x6868d0b8,
0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a ];
var T3 = [
0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b,
0xf2ff0df2, 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5,
0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76,
0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf,
0x9c23bf9c, 0xa453f7a4, 0x72e49672, 0xc09b5bc0,
0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1,
0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3,
0x18302818, 0x9637a196, 0x050a0f05, 0x9a2fb59a,
0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75,
0x09121b09, 0x831d9e83, 0x2c58742c, 0x1a342e1a,
0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3,
0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b,
0x6ad4be6a, 0xcb8d46cb, 0xbe67d9be, 0x39724b39,
0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485,
0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8,
0x51a2f351, 0xa35dfea3, 0x4080c040, 0x8f058a8f,
0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321,
0x10203010, 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2,
0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917,
0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc,
0x22446622, 0x2a547e2a, 0x903bab90, 0x880b8388,
0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a,
0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662,
0x9139a891, 0x9531a495, 0xe4d337e4, 0x79f28b79,
0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9,
0x6cd8b46c, 0x56acfa56, 0xf4f307f4, 0xeacf25ea,
0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e,
0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a,
0x70e09070, 0x3e7c423e, 0xb571c4b5, 0x66ccaa66,
0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e,
0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794,
0x9b2db69b, 0x1e3c221e, 0x87159287, 0xe9c920e9,
0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d,
0xbf65dabf, 0xe6d731e6, 0x4284c642, 0x68d0b868,
0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16 ];
var T4 = [
0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b,
0xff0df2f2, 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5,
0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676,
0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf,
0x23bf9c9c, 0x53f7a4a4, 0xe4967272, 0x9b5bc0c0,
0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1,
0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3,
0x30281818, 0x37a19696, 0x0a0f0505, 0x2fb59a9a,
0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575,
0x121b0909, 0x1d9e8383, 0x58742c2c, 0x342e1a1a,
0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3,
0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b,
0xd4be6a6a, 0x8d46cbcb, 0x67d9bebe, 0x724b3939,
0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585,
0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8,
0xa2f35151, 0x5dfea3a3, 0x80c04040, 0x058a8f8f,
0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121,
0x20301010, 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2,
0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717,
0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc,
0x44662222, 0x547e2a2a, 0x3bab9090, 0x0b838888,
0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a,
0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262,
0x39a89191, 0x31a49595, 0xd337e4e4, 0xf28b7979,
0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9,
0xd8b46c6c, 0xacfa5656, 0xf307f4f4, 0xcf25eaea,
0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e,
0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a,
0xe0907070, 0x7c423e3e, 0x71c4b5b5, 0xccaa6666,
0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e,
0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494,
0x2db69b9b, 0x3c221e1e, 0x15928787, 0xc920e9e9,
0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d,
0x65dabfbf, 0xd731e6e6, 0x84c64242, 0xd0b86868,
0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616 ];
function B0(x) { return (x&255); }
function B1(x) { return ((x>>8)&255); }
function B2(x) { return ((x>>16)&255); }
function B3(x) { return ((x>>24)&255); }
function F1(x0, x1, x2, x3)
{
return B1(T1[x0&255]) | (B1(T1[(x1>>8)&255])<<8)
| (B1(T1[(x2>>16)&255])<<16) | (B1(T1[x3>>>24])<<24);
}
function packBytes(octets)
{
var i, j;
var len=octets.length;
var b=new Array(len/4);
if (!octets || len % 4) return;
for (i=0, j=0; j<len; j+= 4)
b[i++] = octets[j] | (octets[j+1]<<8) | (octets[j+2]<<16) | (octets[j+3]<<24);
return b;
}
function unpackBytes(packed)
{
var j;
var i=0, l = packed.length;
var r = new Array(l*4);
for (j=0; j<l; j++)
{
r[i++] = B0(packed[j]);
r[i++] = B1(packed[j]);
r[i++] = B2(packed[j]);
r[i++] = B3(packed[j]);
}
return r;
}
// ------------------------------------------------
var maxkc=8;
var maxrk=14;
function keyExpansion(key)
{
var kc, i, j, r, t;
var rounds;
var keySched=new Array(maxrk+1);
var keylen=key.length;
var k=new Array(maxkc);
var tk=new Array(maxkc);
var rconpointer=0;
if(keylen==16)
{
rounds=10;
kc=4;
}
else if(keylen==24)
{
rounds=12;
kc=6;
}
else if(keylen==32)
{
rounds=14;
kc=8;
}
else
{
util.print_error('aes.js: Invalid key-length for AES key:'+keylen);
return;
}
for(i=0; i<maxrk+1; i++) keySched[i]=new Array(4);
for(i=0,j=0; j<keylen; j++,i+=4)
k[j] = key.charCodeAt(i) | (key.charCodeAt(i+1)<<8)
| (key.charCodeAt(i+2)<<16) | (key.charCodeAt(i+3)<<24);
for(j=kc-1; j>=0; j--) tk[j] = k[j];
r=0;
t=0;
for(j=0; (j<kc)&&(r<rounds+1); )
{
for(; (j<kc)&&(t<4); j++,t++)
{
keySched[r][t]=tk[j];
}
if(t==4)
{
r++;
t=0;
}
}
while(r<rounds+1)
{
var temp = tk[kc-1];
tk[0] ^= S[B1(temp)] | (S[B2(temp)]<<8) | (S[B3(temp)]<<16) | (S[B0(temp)]<<24);
tk[0] ^= Rcon[rconpointer++];
if(kc != 8)
{
for(j=1; j<kc; j++) tk[j] ^= tk[j-1];
}
else
{
for(j=1; j<kc/2; j++) tk[j] ^= tk[j-1];
temp = tk[kc/2-1];
tk[kc/2] ^= S[B0(temp)] | (S[B1(temp)]<<8) | (S[B2(temp)]<<16) | (S[B3(temp)]<<24);
for(j=kc/2+1; j<kc; j++) tk[j] ^= tk[j-1];
}
for(j=0; (j<kc)&&(r<rounds+1); )
{
for(; (j<kc)&&(t<4); j++,t++)
{
keySched[r][t]=tk[j];
}
if(t==4)
{
r++;
t=0;
}
}
}
this.rounds = rounds;
this.rk = keySched;
return this;
}
function AESencrypt(block, ctx)
{
var r;
var t0,t1,t2,t3;
var b = packBytes(block);
var rounds = ctx.rounds;
var b0 = b[0];
var b1 = b[1];
var b2 = b[2];
var b3 = b[3];
for(r=0; r<rounds-1; r++)
{
t0 = b0 ^ ctx.rk[r][0];
t1 = b1 ^ ctx.rk[r][1];
t2 = b2 ^ ctx.rk[r][2];
t3 = b3 ^ ctx.rk[r][3];
b0 = T1[t0&255] ^ T2[(t1>>8)&255] ^ T3[(t2>>16)&255] ^ T4[t3>>>24];
b1 = T1[t1&255] ^ T2[(t2>>8)&255] ^ T3[(t3>>16)&255] ^ T4[t0>>>24];
b2 = T1[t2&255] ^ T2[(t3>>8)&255] ^ T3[(t0>>16)&255] ^ T4[t1>>>24];
b3 = T1[t3&255] ^ T2[(t0>>8)&255] ^ T3[(t1>>16)&255] ^ T4[t2>>>24];
}
// last round is special
r = rounds-1;
t0 = b0 ^ ctx.rk[r][0];
t1 = b1 ^ ctx.rk[r][1];
t2 = b2 ^ ctx.rk[r][2];
t3 = b3 ^ ctx.rk[r][3];
b[0] = F1(t0, t1, t2, t3) ^ ctx.rk[rounds][0];
b[1] = F1(t1, t2, t3, t0) ^ ctx.rk[rounds][1];
b[2] = F1(t2, t3, t0, t1) ^ ctx.rk[rounds][2];
b[3] = F1(t3, t0, t1, t2) ^ ctx.rk[rounds][3];
return unpackBytes(b);
}
function makeClass(length) {
var c = function(key) {
this.key = keyExpansion(key);
this.encrypt = function(block) {
return AESencrypt(block, this.key);
}
}
c.blockSize = c.prototype.blockSize = 16;
c.keySize = c.prototype.keySize = length / 8;
return c;
}
module.exports = {}
var types = [128, 192, 256];
for(var i in types ) {
module.exports[types[i]] = makeClass(types[i]);
}
},{"../../util":52}],4:[function(require,module,exports){
/* Modified by Recurity Labs GmbH
*
* Originally written by nklein software (nklein.com)
*/
/*
* Javascript implementation based on Bruce Schneier's reference implementation.
*
*
* The constructor doesn't do much of anything. It's just here
* so we can start defining properties and methods and such.
*/
function Blowfish() {
};
/*
* Declare the block size so that protocols know what size
* Initialization Vector (IV) they will need.
*/
Blowfish.prototype.BLOCKSIZE = 8;
/*
* These are the default SBOXES.
*/
Blowfish.prototype.SBOXES = [
[
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
], [
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
], [
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
], [
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
]
];
//*
//* This is the default PARRAY
//*
Blowfish.prototype.PARRAY = [
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
];
//*
//* This is the number of rounds the cipher will go
//*
Blowfish.prototype.NN = 16;
//*
//* This function is needed to get rid of problems
//* with the high-bit getting set. If we don't do
//* this, then sometimes ( aa & 0x00FFFFFFFF ) is not
//* equal to ( bb & 0x00FFFFFFFF ) even when they
//* agree bit-for-bit for the first 32 bits.
//*
Blowfish.prototype._clean = function( xx ) {
if ( xx < 0 ) {
var yy = xx & 0x7FFFFFFF;
xx = yy + 0x80000000;
}
return xx;
};
//*
//* This is the mixing function that uses the sboxes
//*
Blowfish.prototype._F = function ( xx ) {
var aa;
var bb;
var cc;
var dd;
var yy;
dd = xx & 0x00FF;
xx >>>= 8;
cc = xx & 0x00FF;
xx >>>= 8;
bb = xx & 0x00FF;
xx >>>= 8;
aa = xx & 0x00FF;
yy = this.sboxes[ 0 ][ aa ] + this.sboxes[ 1 ][ bb ];
yy = yy ^ this.sboxes[ 2 ][ cc ];
yy = yy + this.sboxes[ 3 ][ dd ];
return yy;
};
//*
//* This method takes an array with two values, left and right
//* and does NN rounds of Blowfish on them.
//*
Blowfish.prototype._encrypt_block = function ( vals ) {
var dataL = vals[ 0 ];
var dataR = vals[ 1 ];
var ii;
for ( ii=0; ii < this.NN; ++ii ) {
dataL = dataL ^ this.parray[ ii ];
dataR = this._F( dataL ) ^ dataR;
var tmp = dataL;
dataL = dataR;
dataR = tmp;
}
dataL = dataL ^ this.parray[ this.NN + 0 ];
dataR = dataR ^ this.parray[ this.NN + 1 ];
vals[ 0 ] = this._clean( dataR );
vals[ 1 ] = this._clean( dataL );
};
//*
//* This method takes a vector of numbers and turns them
//* into long words so that they can be processed by the
//* real algorithm.
//*
//* Maybe I should make the real algorithm above take a vector
//* instead. That will involve more looping, but it won't require
//* the F() method to deconstruct the vector.
//*
Blowfish.prototype.encrypt_block = function ( vector ) {
var ii;
var vals = [ 0, 0 ];
var off = this.BLOCKSIZE/2;
for ( ii = 0; ii < this.BLOCKSIZE/2; ++ii ) {
vals[0] = ( vals[0] << 8 ) | ( vector[ ii + 0 ] & 0x00FF );
vals[1] = ( vals[1] << 8 ) | ( vector[ ii + off ] & 0x00FF );
}
this._encrypt_block( vals );
var ret = [ ];
for ( ii = 0; ii < this.BLOCKSIZE/2; ++ii ) {
ret[ ii + 0 ] = ( vals[ 0 ] >>> (24 - 8*(ii)) & 0x00FF );
ret[ ii + off ] = ( vals[ 1 ] >>> (24 - 8*(ii)) & 0x00FF );
// vals[ 0 ] = ( vals[ 0 ] >>> 8 );
// vals[ 1 ] = ( vals[ 1 ] >>> 8 );
}
return ret;
};
//*
//* This method takes an array with two values, left and right
//* and undoes NN rounds of Blowfish on them.
//*
Blowfish.prototype._decrypt_block = function ( vals ) {
var dataL = vals[ 0 ];
var dataR = vals[ 1 ];
var ii;
for ( ii=this.NN+1; ii > 1; --ii ) {
dataL = dataL ^ this.parray[ ii ];
dataR = this._F( dataL ) ^ dataR;
var tmp = dataL;
dataL = dataR;
dataR = tmp;
}
dataL = dataL ^ this.parray[ 1 ];
dataR = dataR ^ this.parray[ 0 ];
vals[ 0 ] = this._clean( dataR );
vals[ 1 ] = this._clean( dataL );
};
//*
//* This method takes a key array and initializes the
//* sboxes and parray for this encryption.
//*
Blowfish.prototype.init = function ( key ) {
var ii;
var jj = 0;
this.parray = [];
for ( ii=0; ii < this.NN + 2; ++ii ) {
var data = 0x00000000;
var kk;
for ( kk=0; kk < 4; ++kk ) {
data = ( data << 8 ) | ( key[ jj ] & 0x00FF );
if ( ++jj >= key.length ) {
jj = 0;
}
}
this.parray[ ii ] = this.PARRAY[ ii ] ^ data;
}
this.sboxes = [];
for ( ii=0; ii < 4; ++ii ) {
this.sboxes[ ii ] = [];
for ( jj=0; jj < 256; ++jj ) {
this.sboxes[ ii ][ jj ] = this.SBOXES[ ii ][ jj ];
}
}
var vals = [ 0x00000000, 0x00000000 ];
for ( ii=0; ii < this.NN+2; ii += 2 ) {
this._encrypt_block( vals );
this.parray[ ii + 0 ] = vals[ 0 ];
this.parray[ ii + 1 ] = vals[ 1 ];
}
for ( ii=0; ii < 4; ++ii ) {
for ( jj=0; jj < 256; jj += 2 ) {
this._encrypt_block( vals );
this.sboxes[ ii ][ jj + 0 ] = vals[ 0 ];
this.sboxes[ ii ][ jj + 1 ] = vals[ 1 ];
}
}
};
var util = require('../../util');
// added by Recurity Labs
function BFencrypt(block,key) {
var bf = new Blowfish();
bf.init(util.str2bin(key));
return bf.encrypt_block(block);
}
function BF(key) {
this.bf = new Blowfish();
this.bf.init(util.str2bin(key));
this.encrypt = function(block) {
return this.bf.encrypt_block(block);
}
}
module.exports = BF;
module.exports.keySize = BF.prototype.keySize = 16;
module.exports.blockSize = BF.prototype.blockSize = 16;
},{"../../util":52}],5:[function(require,module,exports){
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Copyright 2010 pjacobs@xeekr.com . All rights reserved.
// Modified by Recurity Labs GmbH
// fixed/modified by Herbert Hanewinkel, www.haneWIN.de
// check www.haneWIN.de for the latest version
// cast5.js is a Javascript implementation of CAST-128, as defined in RFC 2144.
// CAST-128 is a common OpenPGP cipher.
// CAST5 constructor
function openpgp_symenc_cast5() {
this.BlockSize= 8;
this.KeySize = 16;
this.setKey = function (key) {
this.masking = new Array(16);
this.rotate = new Array(16);
this.reset();
if (key.length == this.KeySize)
{
this.keySchedule(key);
}
else
{
util.print_error('cast5.js: CAST-128: keys must be 16 bytes');
return false;
}
return true;
};
this.reset = function() {
for (var i = 0; i < 16; i++)
{
this.masking[i] = 0;
this.rotate[i] = 0;
}
};
this.getBlockSize = function() {
return BlockSize;
};
this.encrypt = function(src) {
var dst = new Array(src.length);
for(var i = 0; i < src.length; i+=8)
{
var l = src[i]<<24 | src[i+1]<<16 | src[i+2]<<8 | src[i+3];
var r = src[i+4]<<24 | src[i+5]<<16 | src[i+6]<<8 | src[i+7];
var t;
t = r; r = l^f1(r, this.masking[0], this.rotate[0]); l = t;
t = r; r = l^f2(r, this.masking[1], this.rotate[1]); l = t;
t = r; r = l^f3(r, this.masking[2], this.rotate[2]); l = t;
t = r; r = l^f1(r, this.masking[3], this.rotate[3]); l = t;
t = r; r = l^f2(r, this.masking[4], this.rotate[4]); l = t;
t = r; r = l^f3(r, this.masking[5], this.rotate[5]); l = t;
t = r; r = l^f1(r, this.masking[6], this.rotate[6]); l = t;
t = r; r = l^f2(r, this.masking[7], this.rotate[7]); l = t;
t = r; r = l^f3(r, this.masking[8], this.rotate[8]); l = t;
t = r; r = l^f1(r, this.masking[9], this.rotate[9]); l = t;
t = r; r = l^f2(r, this.masking[10], this.rotate[10]); l = t;
t = r; r = l^f3(r, this.masking[11], this.rotate[11]); l = t;
t = r; r = l^f1(r, this.masking[12], this.rotate[12]); l = t;
t = r; r = l^f2(r, this.masking[13], this.rotate[13]); l = t;
t = r; r = l^f3(r, this.masking[14], this.rotate[14]); l = t;
t = r; r = l^f1(r, this.masking[15], this.rotate[15]); l = t;
dst[i] = (r >>> 24)&255;
dst[i+1] = (r >>> 16)&255;
dst[i+2] = (r >>> 8)&255;
dst[i+3] = r&255;
dst[i+4] = (l >>> 24)&255;
dst[i+5] = (l >>> 16)&255;
dst[i+6] = (l >>> 8)&255;
dst[i+7] = l&255;
}
return dst;
};
this.decrypt = function(src) {
var dst = new Array(src.length);
for(var i = 0; i < src.length; i+=8)
{
var l = src[i]<<24 | src[i+1]<<16 | src[i+2]<<8 | src[i+3];
var r = src[i+4]<<24 | src[i+5]<<16 | src[i+6]<<8 | src[i+7];
var t;
t = r; r = l^f1(r, this.masking[15], this.rotate[15]); l = t;
t = r; r = l^f3(r, this.masking[14], this.rotate[14]); l = t;
t = r; r = l^f2(r, this.masking[13], this.rotate[13]); l = t;
t = r; r = l^f1(r, this.masking[12], this.rotate[12]); l = t;
t = r; r = l^f3(r, this.masking[11], this.rotate[11]); l = t;
t = r; r = l^f2(r, this.masking[10], this.rotate[10]); l = t;
t = r; r = l^f1(r, this.masking[9], this.rotate[9]); l = t;
t = r; r = l^f3(r, this.masking[8], this.rotate[8]); l = t;
t = r; r = l^f2(r, this.masking[7], this.rotate[7]); l = t;
t = r; r = l^f1(r, this.masking[6], this.rotate[6]); l = t;
t = r; r = l^f3(r, this.masking[5], this.rotate[5]); l = t;
t = r; r = l^f2(r, this.masking[4], this.rotate[4]); l = t;
t = r; r = l^f1(r, this.masking[3], this.rotate[3]); l = t;
t = r; r = l^f3(r, this.masking[2], this.rotate[2]); l = t;
t = r; r = l^f2(r, this.masking[1], this.rotate[1]); l = t;
t = r; r = l^f1(r, this.masking[0], this.rotate[0]); l = t;
dst[i] = (r >>> 24)&255;
dst[i+1] = (r >>> 16)&255;
dst[i+2] = (r >>> 8)&255;
dst[i+3] = r&255;
dst[i+4] = (l >>> 24)&255;
dst[i+5] = (l >> 16)&255;
dst[i+6] = (l >> 8)&255;
dst[i+7] = l&255;
}
return dst;
};
var scheduleA = new Array(4);
scheduleA[0] = new Array(4);
scheduleA[0][0] = new Array(4, 0, 0xd, 0xf, 0xc, 0xe, 0x8);
scheduleA[0][1] = new Array(5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa);
scheduleA[0][2] = new Array(6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9);
scheduleA[0][3] = new Array(7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb);
scheduleA[1] = new Array(4);
scheduleA[1][0] = new Array(0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0);
scheduleA[1][1] = new Array(1, 4, 0, 2, 1, 3, 16 + 2);
scheduleA[1][2] = new Array(2, 5, 7, 6, 5, 4, 16 + 1);
scheduleA[1][3] = new Array(3, 7, 0xa, 9, 0xb, 8, 16 + 3);
scheduleA[2] = new Array(4);
scheduleA[2][0] = new Array(4, 0, 0xd, 0xf, 0xc, 0xe, 8);
scheduleA[2][1] = new Array(5, 2, 16 + 0, 16 + 2, 16 + 1, 16 + 3, 0xa);
scheduleA[2][2] = new Array(6, 3, 16 + 7, 16 + 6, 16 + 5, 16 + 4, 9);
scheduleA[2][3] = new Array(7, 1, 16 + 0xa, 16 + 9, 16 + 0xb, 16 + 8, 0xb);
scheduleA[3] = new Array(4);
scheduleA[3][0] = new Array(0, 6, 16 + 5, 16 + 7, 16 + 4, 16 + 6, 16 + 0);
scheduleA[3][1] = new Array(1, 4, 0, 2, 1, 3, 16 + 2);
scheduleA[3][2] = new Array(2, 5, 7, 6, 5, 4, 16 + 1);
scheduleA[3][3] = new Array(3, 7, 0xa, 9, 0xb, 8, 16 + 3);
var scheduleB = new Array(4);
scheduleB[0] = new Array(4);
scheduleB[0][0] = new Array(16 + 8, 16 + 9, 16 + 7, 16 + 6, 16 + 2);
scheduleB[0][1] = new Array(16 + 0xa, 16 + 0xb, 16 + 5, 16 + 4, 16 + 6);
scheduleB[0][2] = new Array(16 + 0xc, 16 + 0xd, 16 + 3, 16 + 2, 16 + 9);
scheduleB[0][3] = new Array(16 + 0xe, 16 + 0xf, 16 + 1, 16 + 0, 16 + 0xc);
scheduleB[1] = new Array(4);
scheduleB[1][0] = new Array(3, 2, 0xc, 0xd, 8);
scheduleB[1][1] = new Array(1, 0, 0xe, 0xf, 0xd);
scheduleB[1][2] = new Array(7, 6, 8, 9, 3);
scheduleB[1][3] = new Array(5, 4, 0xa, 0xb, 7);
scheduleB[2] = new Array(4);
scheduleB[2][0] = new Array(16 + 3, 16 + 2, 16 + 0xc, 16 + 0xd, 16 + 9);
scheduleB[2][1] = new Array(16 + 1, 16 + 0, 16 + 0xe, 16 + 0xf, 16 + 0xc);
scheduleB[2][2] = new Array(16 + 7, 16 + 6, 16 + 8, 16 + 9, 16 + 2);
scheduleB[2][3] = new Array(16 + 5, 16 + 4, 16 + 0xa, 16 + 0xb, 16 + 6);
scheduleB[3] = new Array(4);
scheduleB[3][0] = new Array(8, 9, 7, 6, 3);
scheduleB[3][1] = new Array(0xa, 0xb, 5, 4, 7);
scheduleB[3][2] = new Array(0xc, 0xd, 3, 2, 8);
scheduleB[3][3] = new Array(0xe, 0xf, 1, 0, 0xd);
// changed 'in' to 'inn' (in javascript 'in' is a reserved word)
this.keySchedule = function(inn)
{
var t = new Array(8);
var k = new Array(32);
for (var i = 0; i < 4; i++)
{
var j = i * 4;
t[i] = inn[j]<<24 | inn[j+1]<<16 | inn[j+2]<<8 | inn[j+3];
}
var x = [6, 7, 4, 5];
var ki = 0;
for (var half = 0; half < 2; half++)
{
for (var round = 0; round < 4; round++)
{
for (var j = 0; j < 4; j++)
{
var a = scheduleA[round][j];
var w = t[a[1]];
w ^= sBox[4][(t[a[2]>>>2]>>>(24-8*(a[2]&3)))&0xff];
w ^= sBox[5][(t[a[3]>>>2]>>>(24-8*(a[3]&3)))&0xff];
w ^= sBox[6][(t[a[4]>>>2]>>>(24-8*(a[4]&3)))&0xff];
w ^= sBox[7][(t[a[5]>>>2]>>>(24-8*(a[5]&3)))&0xff];
w ^= sBox[x[j]][(t[a[6]>>>2]>>>(24-8*(a[6]&3)))&0xff];
t[a[0]] = w;
}
for (var j = 0; j < 4; j++)
{
var b = scheduleB[round][j];
var w = sBox[4][(t[b[0]>>>2]>>>(24-8*(b[0]&3)))&0xff];
w ^= sBox[5][(t[b[1]>>>2]>>>(24-8*(b[1]&3)))&0xff];
w ^= sBox[6][(t[b[2]>>>2]>>>(24-8*(b[2]&3)))&0xff];
w ^= sBox[7][(t[b[3]>>>2]>>>(24-8*(b[3]&3)))&0xff];
w ^= sBox[4+j][(t[b[4]>>>2]>>>(24-8*(b[4]&3)))&0xff];
k[ki] = w;
ki++;
}
}
}
for (var i = 0; i < 16; i++)
{
this.masking[i] = k[i];
this.rotate[i] = k[16+i] & 0x1f;
}
};
// These are the three 'f' functions. See RFC 2144, section 2.2.
function f1(d, m, r)
{
var t = m + d;
var I = (t << r) | (t >>> (32 - r));
return ((sBox[0][I>>>24] ^ sBox[1][(I>>>16)&255]) - sBox[2][(I>>>8)&255]) + sBox[3][I&255];
}
function f2(d, m, r)
{
var t = m ^ d;
var I = (t << r) | (t >>> (32 - r));
return ((sBox[0][I>>>24] - sBox[1][(I>>>16)&255]) + sBox[2][(I>>>8)&255]) ^ sBox[3][I&255];
}
function f3(d, m, r)
{
var t = m - d;
var I = (t << r) | (t >>> (32 - r));
return ((sBox[0][I>>>24] + sBox[1][(I>>>16)&255]) ^ sBox[2][(I>>>8)&255]) - sBox[3][I&255];
}
var sBox = new Array(8);
sBox[0] = new Array(
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf);
sBox[1] = new Array(
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1);
sBox[2] = new Array(
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783);
sBox[3] = new Array(
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2);
sBox[4] = new Array(
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4);
sBox[5] = new Array(
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f);
sBox[6] = new Array(
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3);
sBox[7] = new Array(
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e);
};
var util = require('../../util');
function cast5(key) {
this.cast5 = new openpgp_symenc_cast5();
this.cast5.setKey(util.str2bin(key));
this.encrypt = function(block) {
return this.cast5.encrypt(block);
}
}
module.exports = cast5;
module.exports.blockSize = cast5.prototype.blockSize = 8;
module.exports.keySize = cast5.prototype.keySize = 16;
},{"../../util":52}],6:[function(require,module,exports){
//Paul Tero, July 2001
//http://www.tero.co.uk/des/
//
//Optimised for performance with large blocks by Michael Hayworth, November 2001
//http://www.netdealing.com
//
// Modified by Recurity Labs GmbH
//THIS SOFTWARE IS PROVIDED "AS IS" AND
//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
//FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//SUCH DAMAGE.
//des
//this takes the key, the message, and whether to encrypt or decrypt
function des (keys, message, encrypt, mode, iv, padding) {
//declaring this locally speeds things up a bit
var spfunction1 = new Array (0x1010400,0,0x10000,0x1010404,0x1010004,0x10404,0x4,0x10000,0x400,0x1010400,0x1010404,0x400,0x1000404,0x1010004,0x1000000,0x4,0x404,0x1000400,0x1000400,0x10400,0x10400,0x1010000,0x1010000,0x1000404,0x10004,0x1000004,0x1000004,0x10004,0,0x404,0x10404,0x1000000,0x10000,0x1010404,0x4,0x1010000,0x1010400,0x1000000,0x1000000,0x400,0x1010004,0x10000,0x10400,0x1000004,0x400,0x4,0x1000404,0x10404,0x1010404,0x10004,0x1010000,0x1000404,0x1000004,0x404,0x10404,0x1010400,0x404,0x1000400,0x1000400,0,0x10004,0x10400,0,0x1010004);
var spfunction2 = new Array (-0x7fef7fe0,-0x7fff8000,0x8000,0x108020,0x100000,0x20,-0x7fefffe0,-0x7fff7fe0,-0x7fffffe0,-0x7fef7fe0,-0x7fef8000,-0x80000000,-0x7fff8000,0x100000,0x20,-0x7fefffe0,0x108000,0x100020,-0x7fff7fe0,0,-0x80000000,0x8000,0x108020,-0x7ff00000,0x100020,-0x7fffffe0,0,0x108000,0x8020,-0x7fef8000,-0x7ff00000,0x8020,0,0x108020,-0x7fefffe0,0x100000,-0x7fff7fe0,-0x7ff00000,-0x7fef8000,0x8000,-0x7ff00000,-0x7fff8000,0x20,-0x7fef7fe0,0x108020,0x20,0x8000,-0x80000000,0x8020,-0x7fef8000,0x100000,-0x7fffffe0,0x100020,-0x7fff7fe0,-0x7fffffe0,0x100020,0x108000,0,-0x7fff8000,0x8020,-0x80000000,-0x7fefffe0,-0x7fef7fe0,0x108000);
var spfunction3 = new Array (0x208,0x8020200,0,0x8020008,0x8000200,0,0x20208,0x8000200,0x20008,0x8000008,0x8000008,0x20000,0x8020208,0x20008,0x8020000,0x208,0x8000000,0x8,0x8020200,0x200,0x20200,0x8020000,0x8020008,0x20208,0x8000208,0x20200,0x20000,0x8000208,0x8,0x8020208,0x200,0x8000000,0x8020200,0x8000000,0x20008,0x208,0x20000,0x8020200,0x8000200,0,0x200,0x20008,0x8020208,0x8000200,0x8000008,0x200,0,0x8020008,0x8000208,0x20000,0x8000000,0x8020208,0x8,0x20208,0x20200,0x8000008,0x8020000,0x8000208,0x208,0x8020000,0x20208,0x8,0x8020008,0x20200);
var spfunction4 = new Array (0x802001,0x2081,0x2081,0x80,0x802080,0x800081,0x800001,0x2001,0,0x802000,0x802000,0x802081,0x81,0,0x800080,0x800001,0x1,0x2000,0x800000,0x802001,0x80,0x800000,0x2001,0x2080,0x800081,0x1,0x2080,0x800080,0x2000,0x802080,0x802081,0x81,0x800080,0x800001,0x802000,0x802081,0x81,0,0,0x802000,0x2080,0x800080,0x800081,0x1,0x802001,0x2081,0x2081,0x80,0x802081,0x81,0x1,0x2000,0x800001,0x2001,0x802080,0x800081,0x2001,0x2080,0x800000,0x802001,0x80,0x800000,0x2000,0x802080);
var spfunction5 = new Array (0x100,0x2080100,0x2080000,0x42000100,0x80000,0x100,0x40000000,0x2080000,0x40080100,0x80000,0x2000100,0x40080100,0x42000100,0x42080000,0x80100,0x40000000,0x2000000,0x40080000,0x40080000,0,0x40000100,0x42080100,0x42080100,0x2000100,0x42080000,0x40000100,0,0x42000000,0x2080100,0x2000000,0x42000000,0x80100,0x80000,0x42000100,0x100,0x2000000,0x40000000,0x2080000,0x42000100,0x40080100,0x2000100,0x40000000,0x42080000,0x2080100,0x40080100,0x100,0x2000000,0x42080000,0x42080100,0x80100,0x42000000,0x42080100,0x2080000,0,0x40080000,0x42000000,0x80100,0x2000100,0x40000100,0x80000,0,0x40080000,0x2080100,0x40000100);
var spfunction6 = new Array (0x20000010,0x20400000,0x4000,0x20404010,0x20400000,0x10,0x20404010,0x400000,0x20004000,0x404010,0x400000,0x20000010,0x400010,0x20004000,0x20000000,0x4010,0,0x400010,0x20004010,0x4000,0x404000,0x20004010,0x10,0x20400010,0x20400010,0,0x404010,0x20404000,0x4010,0x404000,0x20404000,0x20000000,0x20004000,0x10,0x20400010,0x404000,0x20404010,0x400000,0x4010,0x20000010,0x400000,0x20004000,0x20000000,0x4010,0x20000010,0x20404010,0x404000,0x20400000,0x404010,0x20404000,0,0x20400010,0x10,0x4000,0x20400000,0x404010,0x4000,0x400010,0x20004010,0,0x20404000,0x20000000,0x400010,0x20004010);
var spfunction7 = new Array (0x200000,0x4200002,0x4000802,0,0x800,0x4000802,0x200802,0x4200800,0x4200802,0x200000,0,0x4000002,0x2,0x4000000,0x4200002,0x802,0x4000800,0x200802,0x200002,0x4000800,0x4000002,0x4200000,0x4200800,0x200002,0x4200000,0x800,0x802,0x4200802,0x200800,0x2,0x4000000,0x200800,0x4000000,0x200800,0x200000,0x4000802,0x4000802,0x4200002,0x4200002,0x2,0x200002,0x4000000,0x4000800,0x200000,0x4200800,0x802,0x200802,0x4200800,0x802,0x4000002,0x4200802,0x4200000,0x200800,0,0x2,0x4200802,0,0x200802,0x4200000,0x800,0x4000002,0x4000800,0x800,0x200002);
var spfunction8 = new Array (0x10001040,0x1000,0x40000,0x10041040,0x10000000,0x10001040,0x40,0x10000000,0x40040,0x10040000,0x10041040,0x41000,0x10041000,0x41040,0x1000,0x40,0x10040000,0x10000040,0x10001000,0x1040,0x41000,0x40040,0x10040040,0x10041000,0x1040,0,0,0x10040040,0x10000040,0x10001000,0x41040,0x40000,0x41040,0x40000,0x10041000,0x1000,0x40,0x10040040,0x1000,0x41040,0x10001000,0x40,0x10000040,0x10040000,0x10040040,0x10000000,0x40000,0x10001040,0,0x10041040,0x40040,0x10000040,0x10040000,0x10001000,0x10001040,0,0x10041040,0x41000,0x41000,0x1040,0x1040,0x40040,0x10000000,0x10041000);
//create the 16 or 48 subkeys we will need
var m=0, i, j, temp, temp2, right1, right2, left, right, looping;
var cbcleft, cbcleft2, cbcright, cbcright2
var endloop, loopinc;
var len = message.length;
var chunk = 0;
//set up the loops for single and triple des
var iterations = keys.length == 32 ? 3 : 9; //single or triple des
if (iterations == 3) {looping = encrypt ? new Array (0, 32, 2) : new Array (30, -2, -2);}
else {looping = encrypt ? new Array (0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array (94, 62, -2, 32, 64, 2, 30, -2, -2);}
//pad the message depending on the padding parameter
if (padding == 2) message += " "; //pad the message with spaces
else if (padding == 1) {temp = 8-(len%8); message += String.fromCharCode (temp,temp,temp,temp,temp,temp,temp,temp); if (temp==8) len+=8;} //PKCS7 padding
else if (!padding) message += "\0\0\0\0\0\0\0\0"; //pad the message out with null bytes
//store the result here
result = "";
tempresult = "";
if (mode == 1) { //CBC mode
cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
m=0;
}
//loop through each 64 bit chunk of the message
while (m < len) {
left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
//for Cipher Block Chaining mode, xor the message with the previous result
if (mode == 1) {if (encrypt) {left ^= cbcleft; right ^= cbcright;} else {cbcleft2 = cbcleft; cbcright2 = cbcright; cbcleft = left; cbcright = right;}}
//first each 64 but chunk of the message must be permuted according to IP
temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
left = ((left << 1) | (left >>> 31));
right = ((right << 1) | (right >>> 31));
//do this either 1 or 3 times for each chunk of the message
for (j=0; j<iterations; j+=3) {
endloop = looping[j+1];
loopinc = looping[j+2];
//now go through and perform the encryption or decryption
for (i=looping[j]; i!=endloop; i+=loopinc) { //for efficiency
right1 = right ^ keys[i];
right2 = ((right >>> 4) | (right << 28)) ^ keys[i+1];
//the result is attained by passing these bytes through the S selection functions
temp = left;
left = right;
right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f]
| spfunction6[(right1 >>> 8) & 0x3f] | spfunction8[right1 & 0x3f]
| spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f]
| spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]);
}
temp = left; left = right; right = temp; //unreverse left and right
} //for either 1 or 3 iterations
//move then each one bit to the right
left = ((left >>> 1) | (left << 31));
right = ((right >>> 1) | (right << 31));
//now perform IP-1, which is IP in the opposite direction
temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
temp = ((right >>> 2) ^ left) & 0x33333333; left ^= temp; right ^= (temp << 2);
temp = ((left >>> 16) ^ right) & 0x0000ffff; right ^= temp; left ^= (temp << 16);
temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
//for Cipher Block Chaining mode, xor the message with the previous result
if (mode == 1) {if (encrypt) {cbcleft = left; cbcright = right;} else {left ^= cbcleft2; right ^= cbcright2;}}
tempresult += String.fromCharCode ((left>>>24), ((left>>>16) & 0xff), ((left>>>8) & 0xff), (left & 0xff), (right>>>24), ((right>>>16) & 0xff), ((right>>>8) & 0xff), (right & 0xff));
chunk += 8;
if (chunk == 512) {result += tempresult; tempresult = ""; chunk = 0;}
} //for every 8 characters, or 64 bits in the message
//return the result as an array
result += tempresult;
result = result.replace(/\0*$/g, "");
return result;
} //end of des
//des_createKeys
//this takes as input a 64 bit key (even though only 56 bits are used)
//as an array of 2 integers, and returns 16 48 bit keys
function des_createKeys (key) {
//declaring this locally speeds things up a bit
pc2bytes0 = new Array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204);
pc2bytes1 = new Array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101);
pc2bytes2 = new Array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808);
pc2bytes3 = new Array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000);
pc2bytes4 = new Array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010);
pc2bytes5 = new Array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420);
pc2bytes6 = new Array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002);
pc2bytes7 = new Array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800);
pc2bytes8 = new Array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002);
pc2bytes9 = new Array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408);
pc2bytes10 = new Array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020);
pc2bytes11 = new Array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200);
pc2bytes12 = new Array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010);
pc2bytes13 = new Array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105);
//how many iterations (1 for des, 3 for triple des)
var iterations = key.length > 8 ? 3 : 1; //changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
//stores the return keys
var keys = new Array (32 * iterations);
//now define the left shifts which need to be done
var shifts = new Array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
//other variables
var lefttemp, righttemp, m=0, n=0, temp;
for (var j=0; j<iterations; j++) { //either 1 or 3 iterations
left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
temp = ((left >>> 4) ^ right) & 0x0f0f0f0f; right ^= temp; left ^= (temp << 4);
temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
temp = ((left >>> 2) ^ right) & 0x33333333; right ^= temp; left ^= (temp << 2);
temp = ((right >>> -16) ^ left) & 0x0000ffff; left ^= temp; right ^= (temp << -16);
temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
temp = ((right >>> 8) ^ left) & 0x00ff00ff; left ^= temp; right ^= (temp << 8);
temp = ((left >>> 1) ^ right) & 0x55555555; right ^= temp; left ^= (temp << 1);
//the right side needs to be shifted and to get the last four bits of the left side
temp = (left << 8) | ((right >>> 20) & 0x000000f0);
//left needs to be put upside down
left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
right = temp;
//now go through and perform these shifts on the left and right keys
for (i=0; i < shifts.length; i++) {
//shift the keys either one or two bits to the left
if (shifts[i]) {left = (left << 2) | (left >>> 26); right = (right << 2) | (right >>> 26);}
else {left = (left << 1) | (left >>> 27); right = (right << 1) | (right >>> 27);}
left &= -0xf; right &= -0xf;
//now apply PC-2, in such a way that E is easier when encrypting or decrypting
//this conversion will look like PC-2 except only the last 6 bits of each byte are used
//rather than 48 consecutive bits and the order of lines will be according to
//how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf]
| pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf]
| pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf]
| pc2bytes6[(left >>> 4) & 0xf];
righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf]
| pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf]
| pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf]
| pc2bytes13[(right >>> 4) & 0xf];
temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff;
keys[n++] = lefttemp ^ temp; keys[n++] = righttemp ^ (temp << 16);
}
} //for each iterations
//return the keys we've created
return keys;
} //end of des_createKeys
var util = require('../../util');
// added by Recurity Labs
function Des(key) {
this.key = [];
for(var i = 0; i < 3; i++) {
this.key.push(key.substr(i * 8, 8));
}
this.encrypt = function(block) {
return util.str2bin(des(des_createKeys(this.key[2]),
des(des_createKeys(this.key[1]),
des(des_createKeys(this.key[0]),
util.bin2str(block), true, 0,null,null),
false, 0,null,null), true, 0,null,null));
}
}
module.exports = Des;
module.exports.keySize = Des.prototype.keySize = 24;
module.exports.blockSize = Des.prototype.blockSize = 8;
},{"../../util":52}],7:[function(require,module,exports){
module.exports = {
des: require('./des.js'),
cast5: require('./cast5.js'),
twofish: require('./twofish.js'),
blowfish: require('./blowfish.js')
}
var aes = require('./aes.js');
for(var i in aes) {
module.exports['aes' + i] = aes[i];
}
},{"./aes.js":3,"./blowfish.js":4,"./cast5.js":5,"./des.js":6,"./twofish.js":8}],8:[function(require,module,exports){
/* Modified by Recurity Labs GmbH
*
* Cipher.js
* A block-cipher algorithm implementation on JavaScript
* See Cipher.readme.txt for further information.
*
* Copyright(c) 2009 Atsushi Oka [ http://oka.nu/ ]
* This script file is distributed under the LGPL
*
* ACKNOWLEDGMENT
*
* The main subroutines are written by Michiel van Everdingen.
*
* Michiel van Everdingen
* http://home.versatel.nl/MAvanEverdingen/index.html
*
* All rights for these routines are reserved to Michiel van Everdingen.
*
*/
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Math
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var MAXINT = 0xFFFFFFFF;
function rotb(b,n){ return ( b<<n | b>>>( 8-n) ) & 0xFF; }
function rotw(w,n){ return ( w<<n | w>>>(32-n) ) & MAXINT; }
function getW(a,i){ return a[i]|a[i+1]<<8|a[i+2]<<16|a[i+3]<<24; }
function setW(a,i,w){ a.splice(i,4,w&0xFF,(w>>>8)&0xFF,(w>>>16)&0xFF,(w>>>24)&0xFF); }
function setWInv(a,i,w){ a.splice(i,4,(w>>>24)&0xFF,(w>>>16)&0xFF,(w>>>8)&0xFF,w&0xFF); }
function getB(x,n){ return (x>>>(n*8))&0xFF; }
function getNrBits(i){ var n=0; while (i>0){ n++; i>>>=1; } return n; }
function getMask(n){ return (1<<n)-1; }
//added 2008/11/13 XXX MUST USE ONE-WAY HASH FUNCTION FOR SECURITY REASON
function randByte() {
return Math.floor( Math.random() * 256 );
}
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Twofish
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
function createTwofish() {
//
var keyBytes = null;
var dataBytes = null;
var dataOffset = -1;
// var dataLength = -1;
var algorithmName = null;
// var idx2 = -1;
//
algorithmName = "twofish";
var tfsKey = [];
var tfsM = [ [], [], [], [] ];
function tfsInit(key) {
keyBytes = key;
var i, a, b, c, d, meKey = [], moKey = [], inKey = [];
var kLen;
var sKey = [];
var f01, f5b, fef;
var q0 = [ [ 8, 1, 7, 13, 6, 15, 3, 2, 0, 11, 5, 9, 14, 12, 10, 4 ],
[ 2, 8, 11, 13, 15, 7, 6, 14, 3, 1, 9, 4, 0, 10, 12, 5 ] ];
var q1 = [ [ 14, 12, 11, 8, 1, 2, 3, 5, 15, 4, 10, 6, 7, 0, 9, 13 ],
[ 1, 14, 2, 11, 4, 12, 3, 7, 6, 13, 10, 5, 15, 9, 0, 8 ] ];
var q2 = [ [ 11, 10, 5, 14, 6, 13, 9, 0, 12, 8, 15, 3, 2, 4, 7, 1 ],
[ 4, 12, 7, 5, 1, 6, 9, 10, 0, 14, 13, 8, 2, 11, 3, 15 ] ];
var q3 = [ [ 13, 7, 15, 4, 1, 2, 6, 14, 9, 11, 3, 0, 8, 5, 12, 10 ],
[ 11, 9, 5, 1, 12, 3, 13, 14, 6, 4, 7, 15, 2, 0, 8, 10 ] ];
var ror4 = [ 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 ];
var ashx = [ 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 5, 14, 7 ];
var q = [ [], [] ];
var m = [ [], [], [], [] ];
function ffm5b(x) {
return x ^ (x >> 2) ^ [ 0, 90, 180, 238 ][x & 3];
}
function ffmEf(x) {
return x ^ (x >> 1) ^ (x >> 2) ^ [ 0, 238, 180, 90 ][x & 3];
}
function mdsRem(p, q) {
var i, t, u;
for (i = 0; i < 8; i++) {
t = q >>> 24;
q = ((q << 8) & MAXINT) | p >>> 24;
p = (p << 8) & MAXINT;
u = t << 1;
if (t & 128) {
u ^= 333;
}
q ^= t ^ (u << 16);
u ^= t >>> 1;
if (t & 1) {
u ^= 166;
}
q ^= u << 24 | u << 8;
}
return q;
}
function qp(n, x) {
var a, b, c, d;
a = x >> 4;
b = x & 15;
c = q0[n][a ^ b];
d = q1[n][ror4[b] ^ ashx[a]];
return q3[n][ror4[d] ^ ashx[c]] << 4 | q2[n][c ^ d];
}
function hFun(x, key) {
var a = getB(x, 0), b = getB(x, 1), c = getB(x, 2), d = getB(x, 3);
switch (kLen) {
case 4:
a = q[1][a] ^ getB(key[3], 0);
b = q[0][b] ^ getB(key[3], 1);
c = q[0][c] ^ getB(key[3], 2);
d = q[1][d] ^ getB(key[3], 3);
case 3:
a = q[1][a] ^ getB(key[2], 0);
b = q[1][b] ^ getB(key[2], 1);
c = q[0][c] ^ getB(key[2], 2);
d = q[0][d] ^ getB(key[2], 3);
case 2:
a = q[0][q[0][a] ^ getB(key[1], 0)] ^ getB(key[0], 0);
b = q[0][q[1][b] ^ getB(key[1], 1)] ^ getB(key[0], 1);
c = q[1][q[0][c] ^ getB(key[1], 2)] ^ getB(key[0], 2);
d = q[1][q[1][d] ^ getB(key[1], 3)] ^ getB(key[0], 3);
}
return m[0][a] ^ m[1][b] ^ m[2][c] ^ m[3][d];
}
keyBytes = keyBytes.slice(0, 32);
i = keyBytes.length;
while (i != 16 && i != 24 && i != 32)
keyBytes[i++] = 0;
for (i = 0; i < keyBytes.length; i += 4) {
inKey[i >> 2] = getW(keyBytes, i);
}
for (i = 0; i < 256; i++) {
q[0][i] = qp(0, i);
q[1][i] = qp(1, i);
}
for (i = 0; i < 256; i++) {
f01 = q[1][i];
f5b = ffm5b(f01);
fef = ffmEf(f01);
m[0][i] = f01 + (f5b << 8) + (fef << 16) + (fef << 24);
m[2][i] = f5b + (fef << 8) + (f01 << 16) + (fef << 24);
f01 = q[0][i];
f5b = ffm5b(f01);
fef = ffmEf(f01);
m[1][i] = fef + (fef << 8) + (f5b << 16) + (f01 << 24);
m[3][i] = f5b + (f01 << 8) + (fef << 16) + (f5b << 24);
}
kLen = inKey.length / 2;
for (i = 0; i < kLen; i++) {
a = inKey[i + i];
meKey[i] = a;
b = inKey[i + i + 1];
moKey[i] = b;
sKey[kLen - i - 1] = mdsRem(a, b);
}
for (i = 0; i < 40; i += 2) {
a = 0x1010101 * i;
b = a + 0x1010101;
a = hFun(a, meKey);
b = rotw(hFun(b, moKey), 8);
tfsKey[i] = (a + b) & MAXINT;
tfsKey[i + 1] = rotw(a + 2 * b, 9);
}
for (i = 0; i < 256; i++) {
a = b = c = d = i;
switch (kLen) {
case 4:
a = q[1][a] ^ getB(sKey[3], 0);
b = q[0][b] ^ getB(sKey[3], 1);
c = q[0][c] ^ getB(sKey[3], 2);
d = q[1][d] ^ getB(sKey[3], 3);
case 3:
a = q[1][a] ^ getB(sKey[2], 0);
b = q[1][b] ^ getB(sKey[2], 1);
c = q[0][c] ^ getB(sKey[2], 2);
d = q[0][d] ^ getB(sKey[2], 3);
case 2:
tfsM[0][i] = m[0][q[0][q[0][a] ^ getB(sKey[1], 0)]
^ getB(sKey[0], 0)];
tfsM[1][i] = m[1][q[0][q[1][b] ^ getB(sKey[1], 1)]
^ getB(sKey[0], 1)];
tfsM[2][i] = m[2][q[1][q[0][c] ^ getB(sKey[1], 2)]
^ getB(sKey[0], 2)];
tfsM[3][i] = m[3][q[1][q[1][d] ^ getB(sKey[1], 3)]
^ getB(sKey[0], 3)];
}
}
}
function tfsG0(x) {
return tfsM[0][getB(x, 0)] ^ tfsM[1][getB(x, 1)] ^ tfsM[2][getB(x, 2)]
^ tfsM[3][getB(x, 3)];
}
function tfsG1(x) {
return tfsM[0][getB(x, 3)] ^ tfsM[1][getB(x, 0)] ^ tfsM[2][getB(x, 1)]
^ tfsM[3][getB(x, 2)];
}
function tfsFrnd(r, blk) {
var a = tfsG0(blk[0]);
var b = tfsG1(blk[1]);
blk[2] = rotw(blk[2] ^ (a + b + tfsKey[4 * r + 8]) & MAXINT, 31);
blk[3] = rotw(blk[3], 1) ^ (a + 2 * b + tfsKey[4 * r + 9]) & MAXINT;
a = tfsG0(blk[2]);
b = tfsG1(blk[3]);
blk[0] = rotw(blk[0] ^ (a + b + tfsKey[4 * r + 10]) & MAXINT, 31);
blk[1] = rotw(blk[1], 1) ^ (a + 2 * b + tfsKey[4 * r + 11]) & MAXINT;
}
function tfsIrnd(i, blk) {
var a = tfsG0(blk[0]);
var b = tfsG1(blk[1]);
blk[2] = rotw(blk[2], 1) ^ (a + b + tfsKey[4 * i + 10]) & MAXINT;
blk[3] = rotw(blk[3] ^ (a + 2 * b + tfsKey[4 * i + 11]) & MAXINT, 31);
a = tfsG0(blk[2]);
b = tfsG1(blk[3]);
blk[0] = rotw(blk[0], 1) ^ (a + b + tfsKey[4 * i + 8]) & MAXINT;
blk[1] = rotw(blk[1] ^ (a + 2 * b + tfsKey[4 * i + 9]) & MAXINT, 31);
}
function tfsClose() {
tfsKey = [];
tfsM = [ [], [], [], [] ];
}
function tfsEncrypt(data, offset) {
dataBytes = data;
dataOffset = offset;
var blk = [ getW(dataBytes, dataOffset) ^ tfsKey[0],
getW(dataBytes, dataOffset + 4) ^ tfsKey[1],
getW(dataBytes, dataOffset + 8) ^ tfsKey[2],
getW(dataBytes, dataOffset + 12) ^ tfsKey[3] ];
for ( var j = 0; j < 8; j++) {
tfsFrnd(j, blk);
}
setW(dataBytes, dataOffset, blk[2] ^ tfsKey[4]);
setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[5]);
setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[6]);
setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[7]);
dataOffset += 16;
return dataBytes;
}
function tfsDecrypt(data, offset) {
dataBytes = data;
dataOffset = offset;
var blk = [ getW(dataBytes, dataOffset) ^ tfsKey[4],
getW(dataBytes, dataOffset + 4) ^ tfsKey[5],
getW(dataBytes, dataOffset + 8) ^ tfsKey[6],
getW(dataBytes, dataOffset + 12) ^ tfsKey[7] ];
for ( var j = 7; j >= 0; j--) {
tfsIrnd(j, blk);
}
setW(dataBytes, dataOffset, blk[2] ^ tfsKey[0]);
setW(dataBytes, dataOffset + 4, blk[3] ^ tfsKey[1]);
setW(dataBytes, dataOffset + 8, blk[0] ^ tfsKey[2]);
setW(dataBytes, dataOffset + 12, blk[1] ^ tfsKey[3]);
dataOffset += 16;
}
// added by Recurity Labs
function tfsFinal() {
return dataBytes;
}
return {
name : "twofish",
blocksize : 128 / 8,
open : tfsInit,
close : tfsClose,
encrypt : tfsEncrypt,
decrypt : tfsDecrypt,
// added by Recurity Labs
finalize: tfsFinal
};
}
var util = require('../../util');
// added by Recurity Labs
function TFencrypt(block, key) {
var block_copy = [].concat(block);
var tf = createTwofish();
tf.open(util.str2bin(key),0);
var result = tf.encrypt(block_copy, 0);
tf.close();
return result;
}
function TF(key) {
this.tf = createTwofish();
this.tf.open(util.str2bin(key),0);
this.encrypt = function(block) {
return this.tf.encrypt([].concat(block), 0);
}
}
module.exports = TF;
module.exports.keySize = TF.prototype.keySize = 32;
module.exports.blockSize = TF.prototype.blockSize = 16;
},{"../../util":52}],9:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// The GPG4Browsers crypto interface
var random = require('./random.js'),
cipher = require('./cipher'),
cfb = require('./cfb.js'),
publicKey= require('./public_key'),
type_mpi = require('../type/mpi.js');
module.exports = {
/**
* Encrypts data using the specified public key multiprecision integers
* and the specified algorithm.
* @param {Integer} algo Algorithm to be used (See RFC4880 9.1)
* @param {openpgp_type_mpi[]} publicMPIs Algorithm dependent multiprecision integers
* @param {openpgp_type_mpi} data Data to be encrypted as MPI
* @return {openpgp_type_mpi[]} if RSA an openpgp_type_mpi;
* if elgamal encryption an array of two openpgp_type_mpi is returned; otherwise null
*/
publicKeyEncrypt: function(algo, publicMPIs, data) {
var result = (function() {
switch(algo) {
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
var rsa = new publicKey.rsa();
var n = publicMPIs[0].toBigInteger();
var e = publicMPIs[1].toBigInteger();
var m = data.toBigInteger();
return [rsa.encrypt(m,e,n)];
case 'elgamal':
var elgamal = new publicKey.elgamal();
var p = publicMPIs[0].toBigInteger();
var g = publicMPIs[1].toBigInteger();
var y = publicMPIs[2].toBigInteger();
var m = data.toBigInteger();
return elgamal.encrypt(m,g,p,y);
default:
return [];
}
})();
return result.map(function(bn) {
var mpi = new type_mpi();
mpi.fromBigInteger(bn);
return mpi;
});
},
/**
* Decrypts data using the specified public key multiprecision integers of the private key,
* the specified secretMPIs of the private key and the specified algorithm.
* @param {Integer} algo Algorithm to be used (See RFC4880 9.1)
* @param {openpgp_type_mpi[]} publicMPIs Algorithm dependent multiprecision integers
* of the public key part of the private key
* @param {openpgp_type_mpi[]} secretMPIs Algorithm dependent multiprecision integers
* of the private key used
* @param {openpgp_type_mpi} data Data to be encrypted as MPI
* @return {openpgp_type_mpi} returns a big integer containing the decrypted data; otherwise null
*/
publicKeyDecrypt: function (algo, keyIntegers, dataIntegers) {
var bn = (function() {
switch(algo) {
case 'rsa_encrypt_sign':
case 'rsa_encrypt':
var rsa = new publicKey.rsa();
// 0 and 1 are the public key.
var d = keyIntegers[2].toBigInteger();
var p = keyIntegers[3].toBigInteger();
var q = keyIntegers[4].toBigInteger();
var u = keyIntegers[5].toBigInteger();
var m = dataIntegers[0].toBigInteger();
return rsa.decrypt(m, d, p, q, u);
case 'elgamal':
var elgamal = new publicKey.elgamal();
var x = keyIntegers[3].toBigInteger();
var c1 = dataIntegers[0].toBigInteger();
var c2 = dataIntegers[1].toBigInteger();
var p = keyIntegers[0].toBigInteger();
return elgamal.decrypt(c1,c2,p,x);
default:
return null;
}
})();
var result = new type_mpi();
result.fromBigInteger(bn);
return result;
},
/** Returns the number of integers comprising the private key of an algorithm
* @param {openpgp.publickey} algo The public key algorithm
* @return {Integer} The number of integers.
*/
getPrivateMpiCount: function(algo) {
switch(algo) {
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
case 'rsa_sign':
// Algorithm-Specific Fields for RSA secret keys:
// - multiprecision integer (MPI) of RSA secret exponent d.
// - MPI of RSA secret prime value p.
// - MPI of RSA secret prime value q (p < q).
// - MPI of u, the multiplicative inverse of p, mod q.
return 4;
case 'elgamal':
// Algorithm-Specific Fields for Elgamal secret keys:
// - MPI of Elgamal secret exponent x.
return 1;
case 'dsa':
// Algorithm-Specific Fields for DSA secret keys:
// - MPI of DSA secret exponent x.
return 1;
default:
throw new Error('Unknown algorithm');
}
},
getPublicMpiCount: function(algo) {
// - A series of multiprecision integers comprising the key material:
// Algorithm-Specific Fields for RSA public keys:
// - a multiprecision integer (MPI) of RSA public modulus n;
// - an MPI of RSA public encryption exponent e.
switch(algo) {
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
case 'rsa_sign':
return 2;
// Algorithm-Specific Fields for Elgamal public keys:
// - MPI of Elgamal prime p;
// - MPI of Elgamal group generator g;
// - MPI of Elgamal public key value y (= g**x mod p where x is secret).
case 'elgamal':
return 3;
// Algorithm-Specific Fields for DSA public keys:
// - MPI of DSA prime p;
// - MPI of DSA group order q (q is a prime divisor of p-1);
// - MPI of DSA group generator g;
// - MPI of DSA public-key value y (= g**x mod p where x is secret).
case 'dsa':
return 4;
default:
throw new Error('Unknown algorithm.');
}
},
/**
* generate random byte prefix as string for the specified algorithm
* @param {Integer} algo Algorithm to use (see RFC4880 9.2)
* @return {String} Random bytes with length equal to the block
* size of the cipher
*/
getPrefixRandom: function(algo) {
return random.getRandomBytes(cipher[algo].blockSize);
},
/**
* Generating a session key for the specified symmetric algorithm
* @param {Integer} algo Algorithm to use (see RFC4880 9.2)
* @return {String} Random bytes as a string to be used as a key
*/
generateSessionKey: function(algo) {
return random.getRandomBytes(this.getKeyLength(algo));
},
/**
* Create a secure random big integer of bits length
* @param {Integer} bits Bit length of the MPI to create
* @return {BigInteger} Resulting big integer
*/
getRandomBigInteger: function(bits) {
if (bits < 0) {
return null;
}
var numBytes = Math.floor((bits+7)/8);
var randomBits = random.getRandomBytes(numBytes);
if (bits % 8 > 0) {
randomBits = String.fromCharCode(
(Math.pow(2,bits % 8)-1) &
randomBits.charCodeAt(0)) +
randomBits.substring(1);
}
var mpi = new type_mpi();
mpi.fromBytes(randomBits);
return mpi.toBigInteger();
},
getRandomBigIntegerInRange: function(min, max) {
if (max.compareTo(min) <= 0) {
return;
}
var range = max.subtract(min);
var r = this.getRandomBigInteger(range.bitLength());
while (r > range) {
r = this.getRandomBigInteger(range.bitLength());
}
return min.add(r);
},
}
},{"../type/mpi.js":50,"./cfb.js":2,"./cipher":7,"./public_key":20,"./random.js":23}],10:[function(require,module,exports){
var sha = require('./sha.js');
module.exports = {
md5: require('./md5.js'),
sha1: sha.sha1,
sha256: sha.sha256,
sha224: sha.sha224,
sha384: sha.sha384,
sha512: sha.sha512,
ripemd: require('./ripe-md.js'),
/**
* Create a hash on the specified data using the specified algorithm
* @param {Integer} algo Hash algorithm type (see RFC4880 9.4)
* @param {String} data Data to be hashed
* @return {String} hash value
*/
digest: function(algo, data) {
switch(algo) {
case 1: // - MD5 [HAC]
return this.md5(data);
case 2: // - SHA-1 [FIPS180]
return this.sha1(data);
case 3: // - RIPE-MD/160 [HAC]
return this.ripemd(data);
case 8: // - SHA256 [FIPS180]
return this.sha256(data);
case 9: // - SHA384 [FIPS180]
return this.sha384(data);
case 10:// - SHA512 [FIPS180]
return this.sha512(data);
case 11:// - SHA224 [FIPS180]
return this.sha224(data);
default:
throw new Error('Invalid hash function.');
}
},
/**
* Returns the hash size in bytes of the specified hash algorithm type
* @param {Integer} algo Hash algorithm type (See RFC4880 9.4)
* @return {Integer} Size in bytes of the resulting hash
*/
getHashByteLength: function(algo) {
switch(algo) {
case 1: // - MD5 [HAC]
return 16;
case 2: // - SHA-1 [FIPS180]
case 3: // - RIPE-MD/160 [HAC]
return 20;
case 8: // - SHA256 [FIPS180]
return 32;
case 9: // - SHA384 [FIPS180]
return 48
case 10:// - SHA512 [FIPS180]
return 64;
case 11:// - SHA224 [FIPS180]
return 28;
default:
throw new Error('Invalid hash algorithm.');
}
}
}
},{"./md5.js":11,"./ripe-md.js":12,"./sha.js":13}],11:[function(require,module,exports){
/**
* A fast MD5 JavaScript implementation
* Copyright (c) 2012 Joseph Myers
* http://www.myersdaily.org/joseph/javascript/md5-text.html
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for any purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies.
*
* Of course, this soft is provided "as is" without express or implied
* warranty of any kind.
*/
var util = require('../../util/util.js');
function MD5(entree) {
var hex = md5(entree);
var bin = util.hex2bin(hex);
return bin;
}
function md5cycle(x, k) {
var a = x[0], b = x[1], c = x[2], d = x[3];
a = ff(a, b, c, d, k[0], 7, -680876936);
d = ff(d, a, b, c, k[1], 12, -389564586);
c = ff(c, d, a, b, k[2], 17, 606105819);
b = ff(b, c, d, a, k[3], 22, -1044525330);
a = ff(a, b, c, d, k[4], 7, -176418897);
d = ff(d, a, b, c, k[5], 12, 1200080426);
c = ff(c, d, a, b, k[6], 17, -1473231341);
b = ff(b, c, d, a, k[7], 22, -45705983);
a = ff(a, b, c, d, k[8], 7, 1770035416);
d = ff(d, a, b, c, k[9], 12, -1958414417);
c = ff(c, d, a, b, k[10], 17, -42063);
b = ff(b, c, d, a, k[11], 22, -1990404162);
a = ff(a, b, c, d, k[12], 7, 1804603682);
d = ff(d, a, b, c, k[13], 12, -40341101);
c = ff(c, d, a, b, k[14], 17, -1502002290);
b = ff(b, c, d, a, k[15], 22, 1236535329);
a = gg(a, b, c, d, k[1], 5, -165796510);
d = gg(d, a, b, c, k[6], 9, -1069501632);
c = gg(c, d, a, b, k[11], 14, 643717713);
b = gg(b, c, d, a, k[0], 20, -373897302);
a = gg(a, b, c, d, k[5], 5, -701558691);
d = gg(d, a, b, c, k[10], 9, 38016083);
c = gg(c, d, a, b, k[15], 14, -660478335);
b = gg(b, c, d, a, k[4], 20, -405537848);
a = gg(a, b, c, d, k[9], 5, 568446438);
d = gg(d, a, b, c, k[14], 9, -1019803690);
c = gg(c, d, a, b, k[3], 14, -187363961);
b = gg(b, c, d, a, k[8], 20, 1163531501);
a = gg(a, b, c, d, k[13], 5, -1444681467);
d = gg(d, a, b, c, k[2], 9, -51403784);
c = gg(c, d, a, b, k[7], 14, 1735328473);
b = gg(b, c, d, a, k[12], 20, -1926607734);
a = hh(a, b, c, d, k[5], 4, -378558);
d = hh(d, a, b, c, k[8], 11, -2022574463);
c = hh(c, d, a, b, k[11], 16, 1839030562);
b = hh(b, c, d, a, k[14], 23, -35309556);
a = hh(a, b, c, d, k[1], 4, -1530992060);
d = hh(d, a, b, c, k[4], 11, 1272893353);
c = hh(c, d, a, b, k[7], 16, -155497632);
b = hh(b, c, d, a, k[10], 23, -1094730640);
a = hh(a, b, c, d, k[13], 4, 681279174);
d = hh(d, a, b, c, k[0], 11, -358537222);
c = hh(c, d, a, b, k[3], 16, -722521979);
b = hh(b, c, d, a, k[6], 23, 76029189);
a = hh(a, b, c, d, k[9], 4, -640364487);
d = hh(d, a, b, c, k[12], 11, -421815835);
c = hh(c, d, a, b, k[15], 16, 530742520);
b = hh(b, c, d, a, k[2], 23, -995338651);
a = ii(a, b, c, d, k[0], 6, -198630844);
d = ii(d, a, b, c, k[7], 10, 1126891415);
c = ii(c, d, a, b, k[14], 15, -1416354905);
b = ii(b, c, d, a, k[5], 21, -57434055);
a = ii(a, b, c, d, k[12], 6, 1700485571);
d = ii(d, a, b, c, k[3], 10, -1894986606);
c = ii(c, d, a, b, k[10], 15, -1051523);
b = ii(b, c, d, a, k[1], 21, -2054922799);
a = ii(a, b, c, d, k[8], 6, 1873313359);
d = ii(d, a, b, c, k[15], 10, -30611744);
c = ii(c, d, a, b, k[6], 15, -1560198380);
b = ii(b, c, d, a, k[13], 21, 1309151649);
a = ii(a, b, c, d, k[4], 6, -145523070);
d = ii(d, a, b, c, k[11], 10, -1120210379);
c = ii(c, d, a, b, k[2], 15, 718787259);
b = ii(b, c, d, a, k[9], 21, -343485551);
x[0] = add32(a, x[0]);
x[1] = add32(b, x[1]);
x[2] = add32(c, x[2]);
x[3] = add32(d, x[3]);
}
function cmn(q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t));
return add32((a << s) | (a >>> (32 - s)), b);
}
function ff(a, b, c, d, x, s, t) {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function gg(a, b, c, d, x, s, t) {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function hh(a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t);
}
function ii(a, b, c, d, x, s, t) {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
}
function md51(s) {
txt = '';
var n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878], i;
for (i=64; i<=s.length; i+=64) {
md5cycle(state, md5blk(s.substring(i-64, i)));
}
s = s.substring(i-64);
var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0];
for (i=0; i<s.length; i++)
tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3);
tail[i>>2] |= 0x80 << ((i%4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i=0; i<16; i++) tail[i] = 0;
}
tail[14] = n*8;
md5cycle(state, tail);
return state;
}
/* there needs to be support for Unicode here,
* unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps
* by adding every four 16-bit characters and
* shortening the sum to 32 bits). Otherwise
* I suggest performing MD-5 as if every character
* was two bytes--e.g., 0040 0025 = @%--but then
* how will an ordinary MD-5 sum be matched?
* There is no way to standardize text to something
* like UTF-8 before transformation; speed cost is
* utterly prohibitive. The JavaScript standard
* itself needs to look at this: it should start
* providing access to strings as preformed UTF-8
* 8-bit unsigned value arrays.
*/
function md5blk(s) { /* I figured global was faster. */
var md5blks = [], i; /* Andy King said do it this way. */
for (i=0; i<64; i+=4) {
md5blks[i>>2] = s.charCodeAt(i)
+ (s.charCodeAt(i+1) << 8)
+ (s.charCodeAt(i+2) << 16)
+ (s.charCodeAt(i+3) << 24);
}
return md5blks;
}
var hex_chr = '0123456789abcdef'.split('');
function rhex(n)
{
var s='', j=0;
for(; j<4; j++)
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
+ hex_chr[(n >> (j * 8)) & 0x0F];
return s;
}
function hex(x) {
for (var i=0; i<x.length; i++)
x[i] = rhex(x[i]);
return x.join('');
}
function md5(s) {
return hex(md51(s));
}
/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause. */
function add32(a, b) {
return (a + b) & 0xFFFFFFFF;
}
if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
function add32(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
}
module.exports = MD5
},{"../../util/util.js":52}],12:[function(require,module,exports){
/*
* CryptoMX Tools
* Copyright (C) 2004 - 2006 Derek Buitenhuis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* Modified by Recurity Labs GmbH
*/
var RMDsize = 160;
var X = new Array();
function ROL(x, n)
{
return new Number ((x << n) | ( x >>> (32 - n)));
}
function F(x, y, z)
{
return new Number(x ^ y ^ z);
}
function G(x, y, z)
{
return new Number((x & y) | (~x & z));
}
function H(x, y, z)
{
return new Number((x | ~y) ^ z);
}
function I(x, y, z)
{
return new Number((x & z) | (y & ~z));
}
function J(x, y, z)
{
return new Number(x ^ (y | ~z));
}
function mixOneRound(a, b, c, d, e, x, s, roundNumber)
{
switch (roundNumber)
{
case 0 : a += F(b, c, d) + x + 0x00000000; break;
case 1 : a += G(b, c, d) + x + 0x5a827999; break;
case 2 : a += H(b, c, d) + x + 0x6ed9eba1; break;
case 3 : a += I(b, c, d) + x + 0x8f1bbcdc; break;
case 4 : a += J(b, c, d) + x + 0xa953fd4e; break;
case 5 : a += J(b, c, d) + x + 0x50a28be6; break;
case 6 : a += I(b, c, d) + x + 0x5c4dd124; break;
case 7 : a += H(b, c, d) + x + 0x6d703ef3; break;
case 8 : a += G(b, c, d) + x + 0x7a6d76e9; break;
case 9 : a += F(b, c, d) + x + 0x00000000; break;
default : document.write("Bogus round number"); break;
}
a = ROL(a, s) + e;
c = ROL(c, 10);
a &= 0xffffffff;
b &= 0xffffffff;
c &= 0xffffffff;
d &= 0xffffffff;
e &= 0xffffffff;
var retBlock = new Array();
retBlock[0] = a;
retBlock[1] = b;
retBlock[2] = c;
retBlock[3] = d;
retBlock[4] = e;
retBlock[5] = x;
retBlock[6] = s;
return retBlock;
}
function MDinit (MDbuf)
{
MDbuf[0] = 0x67452301;
MDbuf[1] = 0xefcdab89;
MDbuf[2] = 0x98badcfe;
MDbuf[3] = 0x10325476;
MDbuf[4] = 0xc3d2e1f0;
}
var ROLs = [
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
[ 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12],
[11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5],
[11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12],
[ 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6],
[ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6],
[ 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11],
[ 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5],
[15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8],
[ 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]
];
var indexes = [
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
[ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8],
[ 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12],
[ 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2],
[ 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13],
[ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12],
[ 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2],
[15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13],
[ 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14],
[12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]
];
function compress (MDbuf, X)
{
blockA = new Array();
blockB = new Array();
var retBlock;
for (var i=0; i < 5; i++)
{
blockA[i] = new Number(MDbuf[i]);
blockB[i] = new Number(MDbuf[i]);
}
var step = 0;
for (var j = 0; j < 5; j++)
{
for (var i = 0; i < 16; i++)
{
retBlock = mixOneRound(
blockA[(step+0) % 5],
blockA[(step+1) % 5],
blockA[(step+2) % 5],
blockA[(step+3) % 5],
blockA[(step+4) % 5],
X[indexes[j][i]],
ROLs[j][i],
j
);
blockA[(step+0) % 5] = retBlock[0];
blockA[(step+1) % 5] = retBlock[1];
blockA[(step+2) % 5] = retBlock[2];
blockA[(step+3) % 5] = retBlock[3];
blockA[(step+4) % 5] = retBlock[4];
step += 4;
}
}
step = 0;
for (var j = 5; j < 10; j++)
{
for (var i = 0; i < 16; i++)
{
retBlock = mixOneRound(
blockB[(step+0) % 5],
blockB[(step+1) % 5],
blockB[(step+2) % 5],
blockB[(step+3) % 5],
blockB[(step+4) % 5],
X[indexes[j][i]],
ROLs[j][i],
j
);
blockB[(step+0) % 5] = retBlock[0];
blockB[(step+1) % 5] = retBlock[1];
blockB[(step+2) % 5] = retBlock[2];
blockB[(step+3) % 5] = retBlock[3];
blockB[(step+4) % 5] = retBlock[4];
step += 4;
}
}
blockB[3] += blockA[2] + MDbuf[1];
MDbuf[1] = MDbuf[2] + blockA[3] + blockB[4];
MDbuf[2] = MDbuf[3] + blockA[4] + blockB[0];
MDbuf[3] = MDbuf[4] + blockA[0] + blockB[1];
MDbuf[4] = MDbuf[0] + blockA[1] + blockB[2];
MDbuf[0] = blockB[3];
}
function zeroX(X)
{
for (var i = 0; i < 16; i++) { X[i] = 0; }
}
function MDfinish (MDbuf, strptr, lswlen, mswlen)
{
var X = new Array(16);
zeroX(X);
var j = 0;
for (var i=0; i < (lswlen & 63); i++)
{
X[i >>> 2] ^= (strptr.charCodeAt(j++) & 255) << (8 * (i & 3));
}
X[(lswlen >>> 2) & 15] ^= 1 << (8 * (lswlen & 3) + 7);
if ((lswlen & 63) > 55)
{
compress(MDbuf, X);
var X = new Array(16);
zeroX(X);
}
X[14] = lswlen << 3;
X[15] = (lswlen >>> 29) | (mswlen << 3);
compress(MDbuf, X);
}
function BYTES_TO_DWORD(fourChars)
{
var tmp = (fourChars.charCodeAt(3) & 255) << 24;
tmp |= (fourChars.charCodeAt(2) & 255) << 16;
tmp |= (fourChars.charCodeAt(1) & 255) << 8;
tmp |= (fourChars.charCodeAt(0) & 255);
return tmp;
}
function RMD(message)
{
var MDbuf = new Array(RMDsize / 32);
var hashcode = new Array(RMDsize / 8);
var length;
var nbytes;
MDinit(MDbuf);
length = message.length;
var X = new Array(16);
zeroX(X);
var j=0;
for (var nbytes=length; nbytes > 63; nbytes -= 64)
{
for (var i=0; i < 16; i++)
{
X[i] = BYTES_TO_DWORD(message.substr(j, 4));
j += 4;
}
compress(MDbuf, X);
}
MDfinish(MDbuf, message.substr(j), length, 0);
for (var i=0; i < RMDsize / 8; i += 4)
{
hashcode[i] = MDbuf[i >>> 2] & 255;
hashcode[i+1] = (MDbuf[i >>> 2] >>> 8) & 255;
hashcode[i+2] = (MDbuf[i >>> 2] >>> 16) & 255;
hashcode[i+3] = (MDbuf[i >>> 2] >>> 24) & 255;
}
return hashcode;
}
function RMDstring(message)
{
var hashcode = RMD(message);
var retString = "";
for (var i=0; i < RMDsize/8; i++)
{
retString += String.fromCharCode(hashcode[i]);
}
return retString;
}
module.exports = RMDstring;
},{}],13:[function(require,module,exports){
/* A JavaScript implementation of the SHA family of hashes, as defined in FIPS
* PUB 180-2 as well as the corresponding HMAC implementation as defined in
* FIPS PUB 198a
*
* Version 1.3 Copyright Brian Turek 2008-2010
* Distributed under the BSD License
* See http://jssha.sourceforge.net/ for more information
*
* Several functions taken from Paul Johnson
*/
/* Modified by Recurity Labs GmbH
*
* This code has been slightly modified direct string output:
* - bin2bstr has been added
* - following wrappers of this library have been added:
* - str_sha1
* - str_sha256
* - str_sha224
* - str_sha384
* - str_sha512
*/
var jsSHA = (function () {
/*
* Configurable variables. Defaults typically work
*/
/* Number of Bits Per character (8 for ASCII, 16 for Unicode) */
var charSize = 8,
/* base-64 pad character. "=" for strict RFC compliance */
b64pad = "",
/* hex output format. 0 - lowercase; 1 - uppercase */
hexCase = 0,
/*
* Int_64 is a object for 2 32-bit numbers emulating a 64-bit number
*
* @constructor
* @param {Number} msint_32 The most significant 32-bits of a 64-bit number
* @param {Number} lsint_32 The least significant 32-bits of a 64-bit number
*/
Int_64 = function (msint_32, lsint_32)
{
this.highOrder = msint_32;
this.lowOrder = lsint_32;
},
/*
* Convert a string to an array of big-endian words
* If charSize is ASCII, characters >255 have their hi-byte silently
* ignored.
*
* @param {String} str String to be converted to binary representation
* @return Integer array representation of the parameter
*/
str2binb = function (str)
{
var bin = [], mask = (1 << charSize) - 1,
length = str.length * charSize, i;
for (i = 0; i < length; i += charSize)
{
bin[i >> 5] |= (str.charCodeAt(i / charSize) & mask) <<
(32 - charSize - (i % 32));
}
return bin;
},
/*
* Convert a hex string to an array of big-endian words
*
* @param {String} str String to be converted to binary representation
* @return Integer array representation of the parameter
*/
hex2binb = function (str)
{
var bin = [], length = str.length, i, num;
for (i = 0; i < length; i += 2)
{
num = parseInt(str.substr(i, 2), 16);
if (!isNaN(num))
{
bin[i >> 3] |= num << (24 - (4 * (i % 8)));
}
else
{
return "INVALID HEX STRING";
}
}
return bin;
},
/*
* Convert an array of big-endian words to a hex string.
*
* @private
* @param {Array} binarray Array of integers to be converted to hexidecimal
* representation
* @return Hexidecimal representation of the parameter in String form
*/
binb2hex = function (binarray)
{
var hex_tab = (hexCase) ? "0123456789ABCDEF" : "0123456789abcdef",
str = "", length = binarray.length * 4, i, srcByte;
for (i = 0; i < length; i += 1)
{
srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
str += hex_tab.charAt((srcByte >> 4) & 0xF) +
hex_tab.charAt(srcByte & 0xF);
}
return str;
},
/*
* Convert an array of big-endian words to a base-64 string
*
* @private
* @param {Array} binarray Array of integers to be converted to base-64
* representation
* @return Base-64 encoded representation of the parameter in String form
*/
binb2b64 = function (binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +
"0123456789+/", str = "", length = binarray.length * 4, i, j,
triplet;
for (i = 0; i < length; i += 3)
{
triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) |
(((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) |
((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF);
for (j = 0; j < 4; j += 1)
{
if (i * 8 + j * 6 <= binarray.length * 32)
{
str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
}
else
{
str += b64pad;
}
}
}
return str;
},
/*
* Convert an array of big-endian words to a string
*/
binb2str = function (bin)
{
var str = "";
var mask = (1 << 8) - 1;
for(var i = 0; i < bin.length * 32; i += 8)
str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);
return str;
},
/*
* The 32-bit implementation of circular rotate left
*
* @private
* @param {Number} x The 32-bit integer argument
* @param {Number} n The number of bits to shift
* @return The x shifted circularly by n bits
*/
rotl_32 = function (x, n)
{
return (x << n) | (x >>> (32 - n));
},
/*
* The 32-bit implementation of circular rotate right
*
* @private
* @param {Number} x The 32-bit integer argument
* @param {Number} n The number of bits to shift
* @return The x shifted circularly by n bits
*/
rotr_32 = function (x, n)
{
return (x >>> n) | (x << (32 - n));
},
/*
* The 64-bit implementation of circular rotate right
*
* @private
* @param {Int_64} x The 64-bit integer argument
* @param {Number} n The number of bits to shift
* @return The x shifted circularly by n bits
*/
rotr_64 = function (x, n)
{
if (n <= 32)
{
return new Int_64(
(x.highOrder >>> n) | (x.lowOrder << (32 - n)),
(x.lowOrder >>> n) | (x.highOrder << (32 - n))
);
}
else
{
return new Int_64(
(x.lowOrder >>> n) | (x.highOrder << (32 - n)),
(x.highOrder >>> n) | (x.lowOrder << (32 - n))
);
}
},
/*
* The 32-bit implementation of shift right
*
* @private
* @param {Number} x The 32-bit integer argument
* @param {Number} n The number of bits to shift
* @return The x shifted by n bits
*/
shr_32 = function (x, n)
{
return x >>> n;
},
/*
* The 64-bit implementation of shift right
*
* @private
* @param {Int_64} x The 64-bit integer argument
* @param {Number} n The number of bits to shift
* @return The x shifted by n bits
*/
shr_64 = function (x, n)
{
if (n <= 32)
{
return new Int_64(
x.highOrder >>> n,
x.lowOrder >>> n | (x.highOrder << (32 - n))
);
}
else
{
return new Int_64(
0,
x.highOrder << (32 - n)
);
}
},
/*
* The 32-bit implementation of the NIST specified Parity function
*
* @private
* @param {Number} x The first 32-bit integer argument
* @param {Number} y The second 32-bit integer argument
* @param {Number} z The third 32-bit integer argument
* @return The NIST specified output of the function
*/
parity_32 = function (x, y, z)
{
return x ^ y ^ z;
},
/*
* The 32-bit implementation of the NIST specified Ch function
*
* @private
* @param {Number} x The first 32-bit integer argument
* @param {Number} y The second 32-bit integer argument
* @param {Number} z The third 32-bit integer argument
* @return The NIST specified output of the function
*/
ch_32 = function (x, y, z)
{
return (x & y) ^ (~x & z);
},
/*
* The 64-bit implementation of the NIST specified Ch function
*
* @private
* @param {Int_64} x The first 64-bit integer argument
* @param {Int_64} y The second 64-bit integer argument
* @param {Int_64} z The third 64-bit integer argument
* @return The NIST specified output of the function
*/
ch_64 = function (x, y, z)
{
return new Int_64(
(x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
(x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
);
},
/*
* The 32-bit implementation of the NIST specified Maj function
*
* @private
* @param {Number} x The first 32-bit integer argument
* @param {Number} y The second 32-bit integer argument
* @param {Number} z The third 32-bit integer argument
* @return The NIST specified output of the function
*/
maj_32 = function (x, y, z)
{
return (x & y) ^ (x & z) ^ (y & z);
},
/*
* The 64-bit implementation of the NIST specified Maj function
*
* @private
* @param {Int_64} x The first 64-bit integer argument
* @param {Int_64} y The second 64-bit integer argument
* @param {Int_64} z The third 64-bit integer argument
* @return The NIST specified output of the function
*/
maj_64 = function (x, y, z)
{
return new Int_64(
(x.highOrder & y.highOrder) ^
(x.highOrder & z.highOrder) ^
(y.highOrder & z.highOrder),
(x.lowOrder & y.lowOrder) ^
(x.lowOrder & z.lowOrder) ^
(y.lowOrder & z.lowOrder)
);
},
/*
* The 32-bit implementation of the NIST specified Sigma0 function
*
* @private
* @param {Number} x The 32-bit integer argument
* @return The NIST specified output of the function
*/
sigma0_32 = function (x)
{
return rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22);
},
/*
* The 64-bit implementation of the NIST specified Sigma0 function
*
* @private
* @param {Int_64} x The 64-bit integer argument
* @return The NIST specified output of the function
*/
sigma0_64 = function (x)
{
var rotr28 = rotr_64(x, 28), rotr34 = rotr_64(x, 34),
rotr39 = rotr_64(x, 39);
return new Int_64(
rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder);
},
/*
* The 32-bit implementation of the NIST specified Sigma1 function
*
* @private
* @param {Number} x The 32-bit integer argument
* @return The NIST specified output of the function
*/
sigma1_32 = function (x)
{
return rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25);
},
/*
* The 64-bit implementation of the NIST specified Sigma1 function
*
* @private
* @param {Int_64} x The 64-bit integer argument
* @return The NIST specified output of the function
*/
sigma1_64 = function (x)
{
var rotr14 = rotr_64(x, 14), rotr18 = rotr_64(x, 18),
rotr41 = rotr_64(x, 41);
return new Int_64(
rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder);
},
/*
* The 32-bit implementation of the NIST specified Gamma0 function
*
* @private
* @param {Number} x The 32-bit integer argument
* @return The NIST specified output of the function
*/
gamma0_32 = function (x)
{
return rotr_32(x, 7) ^ rotr_32(x, 18) ^ shr_32(x, 3);
},
/*
* The 64-bit implementation of the NIST specified Gamma0 function
*
* @private
* @param {Int_64} x The 64-bit integer argument
* @return The NIST specified output of the function
*/
gamma0_64 = function (x)
{
var rotr1 = rotr_64(x, 1), rotr8 = rotr_64(x, 8), shr7 = shr_64(x, 7);
return new Int_64(
rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
);
},
/*
* The 32-bit implementation of the NIST specified Gamma1 function
*
* @private
* @param {Number} x The 32-bit integer argument
* @return The NIST specified output of the function
*/
gamma1_32 = function (x)
{
return rotr_32(x, 17) ^ rotr_32(x, 19) ^ shr_32(x, 10);
},
/*
* The 64-bit implementation of the NIST specified Gamma1 function
*
* @private
* @param {Int_64} x The 64-bit integer argument
* @return The NIST specified output of the function
*/
gamma1_64 = function (x)
{
var rotr19 = rotr_64(x, 19), rotr61 = rotr_64(x, 61),
shr6 = shr_64(x, 6);
return new Int_64(
rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
);
},
/*
* Add two 32-bit integers, wrapping at 2^32. This uses 16-bit operations
* internally to work around bugs in some JS interpreters.
*
* @private
* @param {Number} x The first 32-bit integer argument to be added
* @param {Number} y The second 32-bit integer argument to be added
* @return The sum of x + y
*/
safeAdd_32_2 = function (x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16);
return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
},
/*
* Add four 32-bit integers, wrapping at 2^32. This uses 16-bit operations
* internally to work around bugs in some JS interpreters.
*
* @private
* @param {Number} a The first 32-bit integer argument to be added
* @param {Number} b The second 32-bit integer argument to be added
* @param {Number} c The third 32-bit integer argument to be added
* @param {Number} d The fourth 32-bit integer argument to be added
* @return The sum of a + b + c + d
*/
safeAdd_32_4 = function (a, b, c, d)
{
var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF),
msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) +
(lsw >>> 16);
return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
},
/*
* Add five 32-bit integers, wrapping at 2^32. This uses 16-bit operations
* internally to work around bugs in some JS interpreters.
*
* @private
* @param {Number} a The first 32-bit integer argument to be added
* @param {Number} b The second 32-bit integer argument to be added
* @param {Number} c The third 32-bit integer argument to be added
* @param {Number} d The fourth 32-bit integer argument to be added
* @param {Number} e The fifth 32-bit integer argument to be added
* @return The sum of a + b + c + d + e
*/
safeAdd_32_5 = function (a, b, c, d, e)
{
var lsw = (a & 0xFFFF) + (b & 0xFFFF) + (c & 0xFFFF) + (d & 0xFFFF) +
(e & 0xFFFF),
msw = (a >>> 16) + (b >>> 16) + (c >>> 16) + (d >>> 16) +
(e >>> 16) + (lsw >>> 16);
return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
},
/*
* Add two 64-bit integers, wrapping at 2^64. This uses 16-bit operations
* internally to work around bugs in some JS interpreters.
*
* @private
* @param {Int_64} x The first 64-bit integer argument to be added
* @param {Int_64} y The second 64-bit integer argument to be added
* @return The sum of x + y
*/
safeAdd_64_2 = function (x, y)
{
var lsw, msw, lowOrder, highOrder;
lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
return new Int_64(highOrder, lowOrder);
},
/*
* Add four 64-bit integers, wrapping at 2^64. This uses 16-bit operations
* internally to work around bugs in some JS interpreters.
*
* @private
* @param {Int_64} a The first 64-bit integer argument to be added
* @param {Int_64} b The second 64-bit integer argument to be added
* @param {Int_64} c The third 64-bit integer argument to be added
* @param {Int_64} d The fouth 64-bit integer argument to be added
* @return The sum of a + b + c + d
*/
safeAdd_64_4 = function (a, b, c, d)
{
var lsw, msw, lowOrder, highOrder;
lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) +
(c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) +
(c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) +
(c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) +
(c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
return new Int_64(highOrder, lowOrder);
},
/*
* Add five 64-bit integers, wrapping at 2^64. This uses 16-bit operations
* internally to work around bugs in some JS interpreters.
*
* @private
* @param {Int_64} a The first 64-bit integer argument to be added
* @param {Int_64} b The second 64-bit integer argument to be added
* @param {Int_64} c The third 64-bit integer argument to be added
* @param {Int_64} d The fouth 64-bit integer argument to be added
* @param {Int_64} e The fouth 64-bit integer argument to be added
* @return The sum of a + b + c + d + e
*/
safeAdd_64_5 = function (a, b, c, d, e)
{
var lsw, msw, lowOrder, highOrder;
lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) +
(c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) +
(e.lowOrder & 0xFFFF);
msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) +
(c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) +
(lsw >>> 16);
lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) +
(c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) +
(e.highOrder & 0xFFFF) + (msw >>> 16);
msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) +
(c.highOrder >>> 16) + (d.highOrder >>> 16) +
(e.highOrder >>> 16) + (lsw >>> 16);
highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
return new Int_64(highOrder, lowOrder);
},
/*
* Calculates the SHA-1 hash of the string set at instantiation
*
* @private
* @param {Array} message The binary array representation of the string to
* hash
* @param {Number} messageLen The number of bits in the message
* @return The array of integers representing the SHA-1 hash of message
*/
coreSHA1 = function (message, messageLen)
{
var W = [], a, b, c, d, e, T, ch = ch_32, parity = parity_32,
maj = maj_32, rotl = rotl_32, safeAdd_2 = safeAdd_32_2, i, t,
safeAdd_5 = safeAdd_32_5, appendedMessageLength,
H = [
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0
],
K = [
0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
0x5a827999, 0x5a827999, 0x5a827999, 0x5a827999,
0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1, 0x6ed9eba1,
0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc, 0x8f1bbcdc,
0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6,
0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6
];
/* Append '1' at the end of the binary string */
message[messageLen >> 5] |= 0x80 << (24 - (messageLen % 32));
/* Append length of binary string in the position such that the new
length is a multiple of 512. Logic does not work for even multiples
of 512 but there can never be even multiples of 512 */
message[(((messageLen + 65) >> 9) << 4) + 15] = messageLen;
appendedMessageLength = message.length;
for (i = 0; i < appendedMessageLength; i += 16)
{
a = H[0];
b = H[1];
c = H[2];
d = H[3];
e = H[4];
for (t = 0; t < 80; t += 1)
{
if (t < 16)
{
W[t] = message[t + i];
}
else
{
W[t] = rotl(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
}
if (t < 20)
{
T = safeAdd_5(rotl(a, 5), ch(b, c, d), e, K[t], W[t]);
}
else if (t < 40)
{
T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]);
}
else if (t < 60)
{
T = safeAdd_5(rotl(a, 5), maj(b, c, d), e, K[t], W[t]);
} else {
T = safeAdd_5(rotl(a, 5), parity(b, c, d), e, K[t], W[t]);
}
e = d;
d = c;
c = rotl(b, 30);
b = a;
a = T;
}
H[0] = safeAdd_2(a, H[0]);
H[1] = safeAdd_2(b, H[1]);
H[2] = safeAdd_2(c, H[2]);
H[3] = safeAdd_2(d, H[3]);
H[4] = safeAdd_2(e, H[4]);
}
return H;
},
/*
* Calculates the desired SHA-2 hash of the string set at instantiation
*
* @private
* @param {Array} The binary array representation of the string to hash
* @param {Number} The number of bits in message
* @param {String} variant The desired SHA-2 variant
* @return The array of integers representing the SHA-2 hash of message
*/
coreSHA2 = function (message, messageLen, variant)
{
var a, b, c, d, e, f, g, h, T1, T2, H, numRounds, lengthPosition, i, t,
binaryStringInc, binaryStringMult, safeAdd_2, safeAdd_4, safeAdd_5,
gamma0, gamma1, sigma0, sigma1, ch, maj, Int, K, W = [],
appendedMessageLength;
/* Set up the various function handles and variable for the specific
* variant */
if (variant === "SHA-224" || variant === "SHA-256")
{
/* 32-bit variant */
numRounds = 64;
lengthPosition = (((messageLen + 65) >> 9) << 4) + 15;
binaryStringInc = 16;
binaryStringMult = 1;
Int = Number;
safeAdd_2 = safeAdd_32_2;
safeAdd_4 = safeAdd_32_4;
safeAdd_5 = safeAdd_32_5;
gamma0 = gamma0_32;
gamma1 = gamma1_32;
sigma0 = sigma0_32;
sigma1 = sigma1_32;
maj = maj_32;
ch = ch_32;
K = [
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
];
if (variant === "SHA-224")
{
H = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
}
else
{
H = [
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
];
}
}
else if (variant === "SHA-384" || variant === "SHA-512")
{
/* 64-bit variant */
numRounds = 80;
lengthPosition = (((messageLen + 128) >> 10) << 5) + 31;
binaryStringInc = 32;
binaryStringMult = 2;
Int = Int_64;
safeAdd_2 = safeAdd_64_2;
safeAdd_4 = safeAdd_64_4;
safeAdd_5 = safeAdd_64_5;
gamma0 = gamma0_64;
gamma1 = gamma1_64;
sigma0 = sigma0_64;
sigma1 = sigma1_64;
maj = maj_64;
ch = ch_64;
K = [
new Int(0x428a2f98, 0xd728ae22), new Int(0x71374491, 0x23ef65cd),
new Int(0xb5c0fbcf, 0xec4d3b2f), new Int(0xe9b5dba5, 0x8189dbbc),
new Int(0x3956c25b, 0xf348b538), new Int(0x59f111f1, 0xb605d019),
new Int(0x923f82a4, 0xaf194f9b), new Int(0xab1c5ed5, 0xda6d8118),
new Int(0xd807aa98, 0xa3030242), new Int(0x12835b01, 0x45706fbe),
new Int(0x243185be, 0x4ee4b28c), new Int(0x550c7dc3, 0xd5ffb4e2),
new Int(0x72be5d74, 0xf27b896f), new Int(0x80deb1fe, 0x3b1696b1),
new Int(0x9bdc06a7, 0x25c71235), new Int(0xc19bf174, 0xcf692694),
new Int(0xe49b69c1, 0x9ef14ad2), new Int(0xefbe4786, 0x384f25e3),
new Int(0x0fc19dc6, 0x8b8cd5b5), new Int(0x240ca1cc, 0x77ac9c65),
new Int(0x2de92c6f, 0x592b0275), new Int(0x4a7484aa, 0x6ea6e483),
new Int(0x5cb0a9dc, 0xbd41fbd4), new Int(0x76f988da, 0x831153b5),
new Int(0x983e5152, 0xee66dfab), new Int(0xa831c66d, 0x2db43210),
new Int(0xb00327c8, 0x98fb213f), new Int(0xbf597fc7, 0xbeef0ee4),
new Int(0xc6e00bf3, 0x3da88fc2), new Int(0xd5a79147, 0x930aa725),
new Int(0x06ca6351, 0xe003826f), new Int(0x14292967, 0x0a0e6e70),
new Int(0x27b70a85, 0x46d22ffc), new Int(0x2e1b2138, 0x5c26c926),
new Int(0x4d2c6dfc, 0x5ac42aed), new Int(0x53380d13, 0x9d95b3df),
new Int(0x650a7354, 0x8baf63de), new Int(0x766a0abb, 0x3c77b2a8),
new Int(0x81c2c92e, 0x47edaee6), new Int(0x92722c85, 0x1482353b),
new Int(0xa2bfe8a1, 0x4cf10364), new Int(0xa81a664b, 0xbc423001),
new Int(0xc24b8b70, 0xd0f89791), new Int(0xc76c51a3, 0x0654be30),
new Int(0xd192e819, 0xd6ef5218), new Int(0xd6990624, 0x5565a910),
new Int(0xf40e3585, 0x5771202a), new Int(0x106aa070, 0x32bbd1b8),
new Int(0x19a4c116, 0xb8d2d0c8), new Int(0x1e376c08, 0x5141ab53),
new Int(0x2748774c, 0xdf8eeb99), new Int(0x34b0bcb5, 0xe19b48a8),
new Int(0x391c0cb3, 0xc5c95a63), new Int(0x4ed8aa4a, 0xe3418acb),
new Int(0x5b9cca4f, 0x7763e373), new Int(0x682e6ff3, 0xd6b2b8a3),
new Int(0x748f82ee, 0x5defb2fc), new Int(0x78a5636f, 0x43172f60),
new Int(0x84c87814, 0xa1f0ab72), new Int(0x8cc70208, 0x1a6439ec),
new Int(0x90befffa, 0x23631e28), new Int(0xa4506ceb, 0xde82bde9),
new Int(0xbef9a3f7, 0xb2c67915), new Int(0xc67178f2, 0xe372532b),
new Int(0xca273ece, 0xea26619c), new Int(0xd186b8c7, 0x21c0c207),
new Int(0xeada7dd6, 0xcde0eb1e), new Int(0xf57d4f7f, 0xee6ed178),
new Int(0x06f067aa, 0x72176fba), new Int(0x0a637dc5, 0xa2c898a6),
new Int(0x113f9804, 0xbef90dae), new Int(0x1b710b35, 0x131c471b),
new Int(0x28db77f5, 0x23047d84), new Int(0x32caab7b, 0x40c72493),
new Int(0x3c9ebe0a, 0x15c9bebc), new Int(0x431d67c4, 0x9c100d4c),
new Int(0x4cc5d4be, 0xcb3e42b6), new Int(0x597f299c, 0xfc657e2a),
new Int(0x5fcb6fab, 0x3ad6faec), new Int(0x6c44198c, 0x4a475817)
];
if (variant === "SHA-384")
{
H = [
new Int(0xcbbb9d5d, 0xc1059ed8), new Int(0x0629a292a, 0x367cd507),
new Int(0x9159015a, 0x3070dd17), new Int(0x0152fecd8, 0xf70e5939),
new Int(0x67332667, 0xffc00b31), new Int(0x98eb44a87, 0x68581511),
new Int(0xdb0c2e0d, 0x64f98fa7), new Int(0x047b5481d, 0xbefa4fa4)
];
}
else
{
H = [
new Int(0x6a09e667, 0xf3bcc908), new Int(0xbb67ae85, 0x84caa73b),
new Int(0x3c6ef372, 0xfe94f82b), new Int(0xa54ff53a, 0x5f1d36f1),
new Int(0x510e527f, 0xade682d1), new Int(0x9b05688c, 0x2b3e6c1f),
new Int(0x1f83d9ab, 0xfb41bd6b), new Int(0x5be0cd19, 0x137e2179)
];
}
}
/* Append '1' at the end of the binary string */
message[messageLen >> 5] |= 0x80 << (24 - messageLen % 32);
/* Append length of binary string in the position such that the new
* length is correct */
message[lengthPosition] = messageLen;
appendedMessageLength = message.length;
for (i = 0; i < appendedMessageLength; i += binaryStringInc)
{
a = H[0];
b = H[1];
c = H[2];
d = H[3];
e = H[4];
f = H[5];
g = H[6];
h = H[7];
for (t = 0; t < numRounds; t += 1)
{
if (t < 16)
{
/* Bit of a hack - for 32-bit, the second term is ignored */
W[t] = new Int(message[t * binaryStringMult + i],
message[t * binaryStringMult + i + 1]);
}
else
{
W[t] = safeAdd_4(
gamma1(W[t - 2]), W[t - 7],
gamma0(W[t - 15]), W[t - 16]
);
}
T1 = safeAdd_5(h, sigma1(e), ch(e, f, g), K[t], W[t]);
T2 = safeAdd_2(sigma0(a), maj(a, b, c));
h = g;
g = f;
f = e;
e = safeAdd_2(d, T1);
d = c;
c = b;
b = a;
a = safeAdd_2(T1, T2);
}
H[0] = safeAdd_2(a, H[0]);
H[1] = safeAdd_2(b, H[1]);
H[2] = safeAdd_2(c, H[2]);
H[3] = safeAdd_2(d, H[3]);
H[4] = safeAdd_2(e, H[4]);
H[5] = safeAdd_2(f, H[5]);
H[6] = safeAdd_2(g, H[6]);
H[7] = safeAdd_2(h, H[7]);
}
switch (variant)
{
case "SHA-224":
return [
H[0], H[1], H[2], H[3],
H[4], H[5], H[6]
];
case "SHA-256":
return H;
case "SHA-384":
return [
H[0].highOrder, H[0].lowOrder,
H[1].highOrder, H[1].lowOrder,
H[2].highOrder, H[2].lowOrder,
H[3].highOrder, H[3].lowOrder,
H[4].highOrder, H[4].lowOrder,
H[5].highOrder, H[5].lowOrder
];
case "SHA-512":
return [
H[0].highOrder, H[0].lowOrder,
H[1].highOrder, H[1].lowOrder,
H[2].highOrder, H[2].lowOrder,
H[3].highOrder, H[3].lowOrder,
H[4].highOrder, H[4].lowOrder,
H[5].highOrder, H[5].lowOrder,
H[6].highOrder, H[6].lowOrder,
H[7].highOrder, H[7].lowOrder
];
default:
/* This should never be reached */
return [];
}
},
/*
* jsSHA is the workhorse of the library. Instantiate it with the string to
* be hashed as the parameter
*
* @constructor
* @param {String} srcString The string to be hashed
* @param {String} inputFormat The format of srcString, ASCII or HEX
*/
jsSHA = function (srcString, inputFormat)
{
this.sha1 = null;
this.sha224 = null;
this.sha256 = null;
this.sha384 = null;
this.sha512 = null;
this.strBinLen = null;
this.strToHash = null;
/* Convert the input string into the correct type */
if ("HEX" === inputFormat)
{
if (0 !== (srcString.length % 2))
{
return "TEXT MUST BE IN BYTE INCREMENTS";
}
this.strBinLen = srcString.length * 4;
this.strToHash = hex2binb(srcString);
}
else if (("ASCII" === inputFormat) ||
('undefined' === typeof(inputFormat)))
{
this.strBinLen = srcString.length * charSize;
this.strToHash = str2binb(srcString);
}
else
{
return "UNKNOWN TEXT INPUT TYPE";
}
};
jsSHA.prototype = {
/*
* Returns the desired SHA hash of the string specified at instantiation
* using the specified parameters
*
* @param {String} variant The desired SHA variant (SHA-1, SHA-224,
* SHA-256, SHA-384, or SHA-512)
* @param {String} format The desired output formatting (B64 or HEX)
* @return The string representation of the hash in the format specified
*/
getHash : function (variant, format)
{
var formatFunc = null, message = this.strToHash.slice();
switch (format)
{
case "HEX":
formatFunc = binb2hex;
break;
case "B64":
formatFunc = binb2b64;
break;
case "ASCII":
formatFunc = binb2str;
break;
default:
return "FORMAT NOT RECOGNIZED";
}
switch (variant)
{
case "SHA-1":
if (null === this.sha1)
{
this.sha1 = coreSHA1(message, this.strBinLen);
}
return formatFunc(this.sha1);
case "SHA-224":
if (null === this.sha224)
{
this.sha224 = coreSHA2(message, this.strBinLen, variant);
}
return formatFunc(this.sha224);
case "SHA-256":
if (null === this.sha256)
{
this.sha256 = coreSHA2(message, this.strBinLen, variant);
}
return formatFunc(this.sha256);
case "SHA-384":
if (null === this.sha384)
{
this.sha384 = coreSHA2(message, this.strBinLen, variant);
}
return formatFunc(this.sha384);
case "SHA-512":
if (null === this.sha512)
{
this.sha512 = coreSHA2(message, this.strBinLen, variant);
}
return formatFunc(this.sha512);
default:
return "HASH NOT RECOGNIZED";
}
},
/*
* Returns the desired HMAC of the string specified at instantiation
* using the key and variant param.
*
* @param {String} key The key used to calculate the HMAC
* @param {String} inputFormat The format of key, ASCII or HEX
* @param {String} variant The desired SHA variant (SHA-1, SHA-224,
* SHA-256, SHA-384, or SHA-512)
* @param {String} outputFormat The desired output formatting
* (B64 or HEX)
* @return The string representation of the hash in the format specified
*/
getHMAC : function (key, inputFormat, variant, outputFormat)
{
var formatFunc, keyToUse, blockByteSize, blockBitSize, i,
retVal, lastArrayIndex, keyBinLen, hashBitSize,
keyWithIPad = [], keyWithOPad = [];
/* Validate the output format selection */
switch (outputFormat)
{
case "HEX":
formatFunc = binb2hex;
break;
case "B64":
formatFunc = binb2b64;
break;
case "ASCII":
formatFunc = binb2str;
break;
default:
return "FORMAT NOT RECOGNIZED";
}
/* Validate the hash variant selection and set needed variables */
switch (variant)
{
case "SHA-1":
blockByteSize = 64;
hashBitSize = 160;
break;
case "SHA-224":
blockByteSize = 64;
hashBitSize = 224;
break;
case "SHA-256":
blockByteSize = 64;
hashBitSize = 256;
break;
case "SHA-384":
blockByteSize = 128;
hashBitSize = 384;
break;
case "SHA-512":
blockByteSize = 128;
hashBitSize = 512;
break;
default:
return "HASH NOT RECOGNIZED";
}
/* Validate input format selection */
if ("HEX" === inputFormat)
{
/* Nibbles must come in pairs */
if (0 !== (key.length % 2))
{
return "KEY MUST BE IN BYTE INCREMENTS";
}
keyToUse = hex2binb(key);
keyBinLen = key.length * 4;
}
else if ("ASCII" === inputFormat)
{
keyToUse = str2binb(key);
keyBinLen = key.length * charSize;
}
else
{
return "UNKNOWN KEY INPUT TYPE";
}
/* These are used multiple times, calculate and store them */
blockBitSize = blockByteSize * 8;
lastArrayIndex = (blockByteSize / 4) - 1;
/* Figure out what to do with the key based on its size relative to
* the hash's block size */
if (blockByteSize < (keyBinLen / 8))
{
if ("SHA-1" === variant)
{
keyToUse = coreSHA1(keyToUse, keyBinLen);
}
else
{
keyToUse = coreSHA2(keyToUse, keyBinLen, variant);
}
/* For all variants, the block size is bigger than the output
* size so there will never be a useful byte at the end of the
* string */
keyToUse[lastArrayIndex] &= 0xFFFFFF00;
}
else if (blockByteSize > (keyBinLen / 8))
{
/* If the blockByteSize is greater than the key length, there
* will always be at LEAST one "useless" byte at the end of the
* string */
keyToUse[lastArrayIndex] &= 0xFFFFFF00;
}
/* Create ipad and opad */
for (i = 0; i <= lastArrayIndex; i += 1)
{
keyWithIPad[i] = keyToUse[i] ^ 0x36363636;
keyWithOPad[i] = keyToUse[i] ^ 0x5C5C5C5C;
}
/* Calculate the HMAC */
if ("SHA-1" === variant)
{
retVal = coreSHA1(
keyWithIPad.concat(this.strToHash),
blockBitSize + this.strBinLen);
retVal = coreSHA1(
keyWithOPad.concat(retVal),
blockBitSize + hashBitSize);
}
else
{
retVal = coreSHA2(
keyWithIPad.concat(this.strToHash),
blockBitSize + this.strBinLen, variant);
retVal = coreSHA2(
keyWithOPad.concat(retVal),
blockBitSize + hashBitSize, variant);
}
return (formatFunc(retVal));
}
};
return jsSHA;
}());
module.exports = {
sha1: function(str) {
var shaObj = new jsSHA(str, "ASCII");
return shaObj.getHash("SHA-1", "ASCII");
},
sha224: function(str) {
var shaObj = new jsSHA(str, "ASCII");
return shaObj.getHash("SHA-224", "ASCII");
},
sha256: function(str) {
var shaObj = new jsSHA(str, "ASCII");
return shaObj.getHash("SHA-256", "ASCII");
},
sha384: function(str) {
var shaObj = new jsSHA(str, "ASCII");
return shaObj.getHash("SHA-384", "ASCII");
},
sha512: function(str) {
var shaObj = new jsSHA(str, "ASCII");
return shaObj.getHash("SHA-512", "ASCII");
}
}
},{}],14:[function(require,module,exports){
module.exports = {
cipher: require('./cipher'),
hash: require('./hash'),
cfb: require('./cfb.js'),
publicKey: require('./public_key'),
signature: require('./signature.js'),
random: require('./random.js'),
pkcs1: require('./pkcs1.js')
}
var crypto = require('./crypto.js');
for(var i in crypto)
module.exports[i] = crypto[i];
},{"./cfb.js":2,"./cipher":7,"./crypto.js":9,"./hash":10,"./pkcs1.js":15,"./public_key":20,"./random.js":23,"./signature.js":24}],15:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* ASN1 object identifiers for hashes (See RFC4880 5.2.2)
*/
hash_headers = new Array();
hash_headers[1] = [0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10];
hash_headers[3] = [0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14];
hash_headers[2] = [0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14];
hash_headers[8] = [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20];
hash_headers[9] = [0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30];
hash_headers[10] = [0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40];
hash_headers[11] = [0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,0x04,0x1C];
var crypto = require('./crypto.js'),
random = require('./random.js'),
util = require('../util'),
BigInteger = require('./public_key/jsbn.js'),
hash = require('./hash');
module.exports = {
eme: {
/**
* create a EME-PKCS1-v1_5 padding (See RFC4880 13.1.1)
* @param {String} message message to be padded
* @param {Integer} length Length to the resulting message
* @return {String} EME-PKCS1 padded message
*/
encode: function(message, length) {
if (message.length > length-11)
return -1;
var result = "";
result += String.fromCharCode(0);
result += String.fromCharCode(2);
for (var i = 0; i < length - message.length - 3; i++) {
result += String.fromCharCode(random.getPseudoRandom(1,255));
}
result += String.fromCharCode(0);
result += message;
return result;
},
/**
* decodes a EME-PKCS1-v1_5 padding (See RFC4880 13.1.2)
* @param {String} message EME-PKCS1 padded message
* @return {String} decoded message
*/
decode: function(message, len) {
if (message.length < len)
message = String.fromCharCode(0)+message;
if (message.length < 12 || message.charCodeAt(0) != 0 || message.charCodeAt(1) != 2)
return -1;
var i = 2;
while (message.charCodeAt(i) != 0 && message.length > i)
i++;
return message.substring(i+1, message.length);
},
},
emsa: {
/**
* create a EMSA-PKCS1-v1_5 padding (See RFC4880 13.1.3)
* @param {Integer} algo Hash algorithm type used
* @param {String} data Data to be hashed
* @param {Integer} keylength Key size of the public mpi in bytes
* @returns {String} Hashcode with pkcs1padding as string
*/
encode: function(algo, data, keylength) {
var data2 = "";
data2 += String.fromCharCode(0x00);
data2 += String.fromCharCode(0x01);
for (var i = 0; i < (keylength - hash_headers[algo].length - 3 -
hash.getHashByteLength(algo)); i++)
data2 += String.fromCharCode(0xff);
data2 += String.fromCharCode(0x00);
for (var i = 0; i < hash_headers[algo].length; i++)
data2 += String.fromCharCode(hash_headers[algo][i]);
data2 += hash.digest(algo, data);
return new BigInteger(util.hexstrdump(data2),16);
},
/**
* extract the hash out of an EMSA-PKCS1-v1.5 padding (See RFC4880 13.1.3)
* @param {String} data Hash in pkcs1 encoding
* @returns {String} The hash as string
*/
decode: function(algo, data) {
var i = 0;
if (data.charCodeAt(0) == 0) i++;
else if (data.charCodeAt(0) != 1) return -1;
else i++;
while (data.charCodeAt(i) == 0xFF) i++;
if (data.charCodeAt(i++) != 0) return -1;
var j = 0;
for (j = 0; j < hash_headers[algo].length && j+i < data.length; j++) {
if (data.charCodeAt(j+i) != hash_headers[algo][j]) return -1;
}
i+= j;
if (data.substring(i).length < hash.getHashByteLength(algo)) return -1;
return data.substring(i);
}
}
}
},{"../util":52,"./crypto.js":9,"./hash":10,"./public_key/jsbn.js":21,"./random.js":23}],16:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// A Digital signature algorithm implementation
var BigInteger = require('./jsbn.js'),
crypto = require('../crypto.js'),
hashModule = require('../hash'),
util = require('../../util');
function DSA() {
// s1 = ((g**s) mod p) mod q
// s1 = ((s**-1)*(sha-1(m)+(s1*x) mod q)
function sign(hashalgo, m, g, p, q, x) {
// If the output size of the chosen hash is larger than the number of
// bits of q, the hash result is truncated to fit by taking the number
// of leftmost bits equal to the number of bits of q. This (possibly
// truncated) hash function result is treated as a number and used
// directly in the DSA signature algorithm.
var hashed_data = util.getLeftNBits(hashModule.digest(hashalgo,m),q.bitLength());
var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
var k = crypto.getRandomBigIntegerInRange(BigInteger.ONE.add(BigInteger.ONE), q.subtract(BigInteger.ONE));
var s1 = (g.modPow(k,p)).mod(q);
var s2 = (k.modInverse(q).multiply(hash.add(x.multiply(s1)))).mod(q);
var result = new Array();
result[0] = s1.toMPI();
result[1] = s2.toMPI();
return result;
}
function select_hash_algorithm(q) {
var usersetting = openpgp.config.config.prefer_hash_algorithm;
/*
* 1024-bit key, 160-bit q, SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512 hash
* 2048-bit key, 224-bit q, SHA-224, SHA-256, SHA-384, or SHA-512 hash
* 2048-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
* 3072-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
*/
switch (Math.round(q.bitLength() / 8)) {
case 20: // 1024 bit
if (usersetting != 2 &&
usersetting > 11 &&
usersetting != 10 &&
usersetting < 8)
return 2; // prefer sha1
return usersetting;
case 28: // 2048 bit
if (usersetting > 11 &&
usersetting < 8)
return 11;
return usersetting;
case 32: // 4096 bit // prefer sha224
if (usersetting > 10 &&
usersetting < 8)
return 8; // prefer sha256
return usersetting;
default:
util.print_debug("DSA select hash algorithm: returning null for an unknown length of q");
return null;
}
}
this.select_hash_algorithm = select_hash_algorithm;
function verify(hashalgo, s1,s2,m,p,q,g,y) {
var hashed_data = util.getLeftNBits(hashModule.digest(hashalgo,m),q.bitLength());
var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
if (BigInteger.ZERO.compareTo(s1) > 0 ||
s1.compareTo(q) > 0 ||
BigInteger.ZERO.compareTo(s2) > 0 ||
s2.compareTo(q) > 0) {
util.print_error("invalid DSA Signature");
return null;
}
var w = s2.modInverse(q);
var u1 = hash.multiply(w).mod(q);
var u2 = s1.multiply(w).mod(q);
return g.modPow(u1,p).multiply(y.modPow(u2,p)).mod(p).mod(q);
}
/*
* unused code. This can be used as a start to write a key generator
* function.
function generateKey(bitcount) {
var qi = new BigInteger(bitcount, primeCenterie);
var pi = generateP(q, 512);
var gi = generateG(p, q, bitcount);
var xi;
do {
xi = new BigInteger(q.bitCount(), rand);
} while (x.compareTo(BigInteger.ZERO) != 1 && x.compareTo(q) != -1);
var yi = g.modPow(x, p);
return {x: xi, q: qi, p: pi, g: gi, y: yi};
}
function generateP(q, bitlength, randomfn) {
if (bitlength % 64 != 0) {
return false;
}
var pTemp;
var pTemp2;
do {
pTemp = randomfn(bitcount, true);
pTemp2 = pTemp.subtract(BigInteger.ONE);
pTemp = pTemp.subtract(pTemp2.remainder(q));
} while (!pTemp.isProbablePrime(primeCenterie) || pTemp.bitLength() != l);
return pTemp;
}
function generateG(p, q, bitlength, randomfn) {
var aux = p.subtract(BigInteger.ONE);
var pow = aux.divide(q);
var gTemp;
do {
gTemp = randomfn(bitlength);
} while (gTemp.compareTo(aux) != -1 && gTemp.compareTo(BigInteger.ONE) != 1);
return gTemp.modPow(pow, p);
}
function generateK(q, bitlength, randomfn) {
var tempK;
do {
tempK = randomfn(bitlength, false);
} while (tempK.compareTo(q) != -1 && tempK.compareTo(BigInteger.ZERO) != 1);
return tempK;
}
function generateR(q,p) {
k = generateK(q);
var r = g.modPow(k, p).mod(q);
return r;
}
function generateS(hashfn,k,r,m,q,x) {
var hash = hashfn(m);
s = (k.modInverse(q).multiply(hash.add(x.multiply(r)))).mod(q);
return s;
} */
this.sign = sign;
this.verify = verify;
// this.generate = generateKey;
}
module.exports = DSA;
},{"../../util":52,"../crypto.js":9,"../hash":10,"./jsbn.js":21}],17:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* @class
* @classdesc Implementation of the One-Pass Signature Packets (Tag 4)
*
* RFC4880 5.4:
* The One-Pass Signature packet precedes the signed data and contains
* enough information to allow the receiver to begin calculating any
* hashes needed to verify the signature. It allows the Signature
* packet to be placed at the end of the message, so that the signer
* can compute the entire signed message in one pass.
*/
var enums = require('../enums.js'),
type_keyid = require('../type/keyid.js');
module.exports = function packet_one_pass_signature() {
this.version = null; // A one-octet version number. The current version is 3.
this.type = null; // A one-octet signature type. Signature types are described in RFC4880 Section 5.2.1.
this.hashAlgorithm = null; // A one-octet number describing the hash algorithm used. (See RFC4880 9.4)
this.publicKeyAlgorithm = null; // A one-octet number describing the public-key algorithm used. (See RFC4880 9.1)
this.signingKeyId = null; // An eight-octet number holding the Key ID of the signing key.
this.flags = null; // A one-octet number holding a flag showing whether the signature is nested. A zero value indicates that the next packet is another One-Pass Signature packet that describes another signature to be applied to the same message data.
/**
* parsing function for a one-pass signature packet (tag 4).
* @param {String} bytes payload of a tag 4 packet
* @param {Integer} position position to start reading from the bytes string
* @param {Integer} len length of the packet or the remaining length of bytes at position
* @return {openpgp_packet_encrypteddata} object representation
*/
this.read = function(bytes) {
var mypos = 0;
// A one-octet version number. The current version is 3.
this.version = bytes.charCodeAt(mypos++);
// A one-octet signature type. Signature types are described in
// Section 5.2.1.
this.type = enums.read(enums.signature, bytes.charCodeAt(mypos++));
// A one-octet number describing the hash algorithm used.
this.hashAlgorithm = enums.read(enums.hash, bytes.charCodeAt(mypos++));
// A one-octet number describing the public-key algorithm used.
this.publicKeyAlgorithm = enums.read(enums.publicKey, bytes.charCodeAt(mypos++));
// An eight-octet number holding the Key ID of the signing key.
this.signingKeyId = new type_keyid();
this.signingKeyId.read(bytes.substr(mypos));
mypos += 8;
// A one-octet number holding a flag showing whether the signature
// is nested. A zero value indicates that the next packet is
// another One-Pass Signature packet that describes another
// signature to be applied to the same message data.
this.flags = bytes.charCodeAt(mypos++);
return this;
}
/**
* creates a string representation of a one-pass signature packet
* @param {Integer} type Signature types as described in RFC4880 Section 5.2.1.
* @param {Integer} hashalgorithm the hash algorithm used within the signature
* @param {openpgp_msg_privatekey} privatekey the private key used to generate the signature
* @param {Integer} length length of data to be signed
* @param {boolean} nested boolean showing whether the signature is nested.
* "true" indicates that the next packet is another One-Pass Signature packet
* that describes another signature to be applied to the same message data.
* @return {String} a string representation of a one-pass signature packet
*/
this.write = function(type, hashalgorithm, privatekey, length, nested) {
var result ="";
result += String.fromCharCode(3);
result += String.fromCharCode(enums.write(enums.signature, type));
result += String.fromCharCode(enums.write(enums.hash, this.hashAlgorithm));
result += String.fromCharCode(enums.write(enums.publicKey, privatekey.algorithm));
result += privatekey.getKeyId();
if (nested)
result += String.fromCharCode(0);
else
result += String.fromCharCode(1);
return result;
}
};
},{"../enums.js":27,"../type/keyid.js":49}],"test-bundle.js":[function(require,module,exports){
module.exports=require('2ZZCcm');
},{}],19:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// ElGamal implementation
var BigInteger = require('./jsbn.js'),
util = require('../../util');
function Elgamal() {
function encrypt(m,g,p,y) {
// choose k in {2,...,p-2}
var two = BigInteger.ONE.add(BigInteger.ONE);
var pMinus2 = p.subtract(two);
var k = openpgp_crypto_getRandomBigIntegerInRange(two, pMinus2);
var k = k.mod(pMinus2).add(BigInteger.ONE);
var c = new Array();
c[0] = g.modPow(k, p);
c[1] = y.modPow(k, p).multiply(m).mod(p).toMPI();
c[0] = c[0].toMPI();
return c;
}
function decrypt(c1,c2,p,x) {
util.print_debug("Elgamal Decrypt:\nc1:"+util.hexstrdump(c1.toMPI())+"\n"+
"c2:"+util.hexstrdump(c2.toMPI())+"\n"+
"p:"+util.hexstrdump(p.toMPI())+"\n"+
"x:"+util.hexstrdump(x.toMPI()));
return (c1.modPow(x, p).modInverse(p)).multiply(c2).mod(p);
//var c = c1.pow(x).modInverse(p); // c0^-a mod p
//return c.multiply(c2).mod(p);
}
// signing and signature verification using Elgamal is not required by OpenPGP.
this.encrypt = encrypt;
this.decrypt = decrypt;
}
module.exports = Elgamal;
},{"../../util":52,"./jsbn.js":21}],20:[function(require,module,exports){
module.exports = {
rsa: require('./rsa.js'),
elgamal: require('./elgamal.js'),
dsa: require('./dsa.js')
}
},{"./dsa.js":16,"./elgamal.js":19,"./rsa.js":22}],21:[function(require,module,exports){
/*
* Copyright (c) 2003-2005 Tom Wu (tjw@cs.Stanford.EDU)
* All Rights Reserved.
*
* Modified by Recurity Labs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following condition applies:
*
* All redistributions must retain an intact copy of this copyright notice
* and disclaimer.
*/
var util = require('../../util');
// Basic JavaScript BN library - subset useful for RSA encryption.
// Bits per digit
var dbits;
// JavaScript engine analysis
var canary = 0xdeadbeefcafe;
var j_lm = ((canary&0xffffff)==0xefcafe);
// (public) Constructor
function BigInteger(a,b,c) {
if(a != null)
if("number" == typeof a) this.fromNumber(a,b,c);
else if(b == null && "string" != typeof a) this.fromString(a,256);
else this.fromString(a,b);
}
// return new, unset BigInteger
function nbi() { return new BigInteger(null); }
// am: Compute w_j += (x*this_i), propagate carries,
// c is initial carry, returns final carry.
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
// We need to select the fastest one that works in this environment.
// am1: use a single mult and divide to get the high bits,
// max digit bits should be 26 because
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
function am1(i,x,w,j,c,n) {
while(--n >= 0) {
var v = x*this[i++]+w[j]+c;
c = Math.floor(v/0x4000000);
w[j++] = v&0x3ffffff;
}
return c;
}
// am2 avoids a big mult-and-extract completely.
// Max digit bits should be <= 30 because we do bitwise ops
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
function am2(i,x,w,j,c,n) {
var xl = x&0x7fff, xh = x>>15;
while(--n >= 0) {
var l = this[i]&0x7fff;
var h = this[i++]>>15;
var m = xh*l+h*xl;
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
w[j++] = l&0x3fffffff;
}
return c;
}
// Alternately, set max digit bits to 28 since some
// browsers slow down when dealing with 32-bit numbers.
function am3(i,x,w,j,c,n) {
var xl = x&0x3fff, xh = x>>14;
while(--n >= 0) {
var l = this[i]&0x3fff;
var h = this[i++]>>14;
var m = xh*l+h*xl;
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
c = (l>>28)+(m>>14)+xh*h;
w[j++] = l&0xfffffff;
}
return c;
}
/*if(j_lm && (navigator != undefined &&
navigator.appName == "Microsoft Internet Explorer")) {
BigInteger.prototype.am = am2;
dbits = 30;
}
else if(j_lm && (navigator != undefined && navigator.appName != "Netscape")) {*/
BigInteger.prototype.am = am1;
dbits = 26;
/*}
else { // Mozilla/Netscape seems to prefer am3
BigInteger.prototype.am = am3;
dbits = 28;
}*/
BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1<<dbits)-1);
BigInteger.prototype.DV = (1<<dbits);
var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2,BI_FP);
BigInteger.prototype.F1 = BI_FP-dbits;
BigInteger.prototype.F2 = 2*dbits-BI_FP;
// Digit conversions
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr,vv;
rr = "0".charCodeAt(0);
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
rr = "a".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
rr = "A".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
function int2char(n) { return BI_RM.charAt(n); }
function intAt(s,i) {
var c = BI_RC[s.charCodeAt(i)];
return (c==null)?-1:c;
}
// (protected) copy this to r
function bnpCopyTo(r) {
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
r.t = this.t;
r.s = this.s;
}
// (protected) set from integer value x, -DV <= x < DV
function bnpFromInt(x) {
this.t = 1;
this.s = (x<0)?-1:0;
if(x > 0) this[0] = x;
else if(x < -1) this[0] = x+DV;
else this.t = 0;
}
// return bigint initialized to value
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
// (protected) set from string and radix
function bnpFromString(s,b) {
var k;
if(b == 16) k = 4;
else if(b == 8) k = 3;
else if(b == 256) k = 8; // byte array
else if(b == 2) k = 1;
else if(b == 32) k = 5;
else if(b == 4) k = 2;
else { this.fromRadix(s,b); return; }
this.t = 0;
this.s = 0;
var i = s.length, mi = false, sh = 0;
while(--i >= 0) {
var x = (k==8)?s[i]&0xff:intAt(s,i);
if(x < 0) {
if(s.charAt(i) == "-") mi = true;
continue;
}
mi = false;
if(sh == 0)
this[this.t++] = x;
else if(sh+k > this.DB) {
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
this[this.t++] = (x>>(this.DB-sh));
}
else
this[this.t-1] |= x<<sh;
sh += k;
if(sh >= this.DB) sh -= this.DB;
}
if(k == 8 && (s[0]&0x80) != 0) {
this.s = -1;
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
}
this.clamp();
if(mi) BigInteger.ZERO.subTo(this,this);
}
// (protected) clamp off excess high words
function bnpClamp() {
var c = this.s&this.DM;
while(this.t > 0 && this[this.t-1] == c) --this.t;
}
// (public) return string representation in given radix
function bnToString(b) {
if(this.s < 0) return "-"+this.negate().toString(b);
var k;
if(b == 16) k = 4;
else if(b == 8) k = 3;
else if(b == 2) k = 1;
else if(b == 32) k = 5;
else if(b == 4) k = 2;
else return this.toRadix(b);
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
var p = this.DB-(i*this.DB)%k;
if(i-- > 0) {
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
while(i >= 0) {
if(p < k) {
d = (this[i]&((1<<p)-1))<<(k-p);
d |= this[--i]>>(p+=this.DB-k);
}
else {
d = (this[i]>>(p-=k))&km;
if(p <= 0) { p += this.DB; --i; }
}
if(d > 0) m = true;
if(m) r += int2char(d);
}
}
return m?r:"0";
}
// (public) -this
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
// (public) |this|
function bnAbs() { return (this.s<0)?this.negate():this; }
// (public) return + if this > a, - if this < a, 0 if equal
function bnCompareTo(a) {
var r = this.s-a.s;
if(r != 0) return r;
var i = this.t;
r = i-a.t;
if(r != 0) return r;
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
return 0;
}
// returns bit length of the integer x
function nbits(x) {
var r = 1, t;
if((t=x>>>16) != 0) { x = t; r += 16; }
if((t=x>>8) != 0) { x = t; r += 8; }
if((t=x>>4) != 0) { x = t; r += 4; }
if((t=x>>2) != 0) { x = t; r += 2; }
if((t=x>>1) != 0) { x = t; r += 1; }
return r;
}
// (public) return the number of bits in "this"
function bnBitLength() {
if(this.t <= 0) return 0;
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
}
// (protected) r = this << n*DB
function bnpDLShiftTo(n,r) {
var i;
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
for(i = n-1; i >= 0; --i) r[i] = 0;
r.t = this.t+n;
r.s = this.s;
}
// (protected) r = this >> n*DB
function bnpDRShiftTo(n,r) {
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
r.t = Math.max(this.t-n,0);
r.s = this.s;
}
// (protected) r = this << n
function bnpLShiftTo(n,r) {
var bs = n%this.DB;
var cbs = this.DB-bs;
var bm = (1<<cbs)-1;
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
for(i = this.t-1; i >= 0; --i) {
r[i+ds+1] = (this[i]>>cbs)|c;
c = (this[i]&bm)<<bs;
}
for(i = ds-1; i >= 0; --i) r[i] = 0;
r[ds] = c;
r.t = this.t+ds+1;
r.s = this.s;
r.clamp();
}
// (protected) r = this >> n
function bnpRShiftTo(n,r) {
r.s = this.s;
var ds = Math.floor(n/this.DB);
if(ds >= this.t) { r.t = 0; return; }
var bs = n%this.DB;
var cbs = this.DB-bs;
var bm = (1<<bs)-1;
r[0] = this[ds]>>bs;
for(var i = ds+1; i < this.t; ++i) {
r[i-ds-1] |= (this[i]&bm)<<cbs;
r[i-ds] = this[i]>>bs;
}
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
r.t = this.t-ds;
r.clamp();
}
// (protected) r = this - a
function bnpSubTo(a,r) {
var i = 0, c = 0, m = Math.min(a.t,this.t);
while(i < m) {
c += this[i]-a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
if(a.t < this.t) {
c -= a.s;
while(i < this.t) {
c += this[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += this.s;
}
else {
c += this.s;
while(i < a.t) {
c -= a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c -= a.s;
}
r.s = (c<0)?-1:0;
if(c < -1) r[i++] = this.DV+c;
else if(c > 0) r[i++] = c;
r.t = i;
r.clamp();
}
// (protected) r = this * a, r != this,a (HAC 14.12)
// "this" should be the larger one if appropriate.
function bnpMultiplyTo(a,r) {
var x = this.abs(), y = a.abs();
var i = x.t;
r.t = i+y.t;
while(--i >= 0) r[i] = 0;
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
r.s = 0;
r.clamp();
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
}
// (protected) r = this^2, r != this (HAC 14.16)
function bnpSquareTo(r) {
var x = this.abs();
var i = r.t = 2*x.t;
while(--i >= 0) r[i] = 0;
for(i = 0; i < x.t-1; ++i) {
var c = x.am(i,x[i],r,2*i,0,1);
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
r[i+x.t] -= x.DV;
r[i+x.t+1] = 1;
}
}
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
r.s = 0;
r.clamp();
}
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
// r != q, this != m. q or r may be null.
function bnpDivRemTo(m,q,r) {
var pm = m.abs();
if(pm.t <= 0) return;
var pt = this.abs();
if(pt.t < pm.t) {
if(q != null) q.fromInt(0);
if(r != null) this.copyTo(r);
return;
}
if(r == null) r = nbi();
var y = nbi(), ts = this.s, ms = m.s;
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
else { pm.copyTo(y); pt.copyTo(r); }
var ys = y.t;
var y0 = y[ys-1];
if(y0 == 0) return;
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
y.dlShiftTo(j,t);
if(r.compareTo(t) >= 0) {
r[r.t++] = 1;
r.subTo(t,r);
}
BigInteger.ONE.dlShiftTo(ys,t);
t.subTo(y,y); // "negative" y so we can replace sub with am later
while(y.t < ys) y[y.t++] = 0;
while(--j >= 0) {
// Estimate quotient digit
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
y.dlShiftTo(j,t);
r.subTo(t,r);
while(r[i] < --qd) r.subTo(t,r);
}
}
if(q != null) {
r.drShiftTo(ys,q);
if(ts != ms) BigInteger.ZERO.subTo(q,q);
}
r.t = ys;
r.clamp();
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
if(ts < 0) BigInteger.ZERO.subTo(r,r);
}
// (public) this mod a
function bnMod(a) {
var r = nbi();
this.abs().divRemTo(a,null,r);
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
return r;
}
// Modular reduction using "classic" algorithm
function Classic(m) { this.m = m; }
function cConvert(x) {
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
else return x;
}
function cRevert(x) { return x; }
function cReduce(x) { x.divRemTo(this.m,null,x); }
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
// justification:
// xy == 1 (mod m)
// xy = 1+km
// xy(2-xy) = (1+km)(1-km)
// x[y(2-xy)] = 1-k^2m^2
// x[y(2-xy)] == 1 (mod m^2)
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
// JS multiply "overflows" differently from C/C++, so care is needed here.
function bnpInvDigit() {
if(this.t < 1) return 0;
var x = this[0];
if((x&1) == 0) return 0;
var y = x&3; // y == 1/x mod 2^2
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
// last step - calculate inverse mod DV directly;
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
// we really want the negative inverse, and -DV < y < DV
return (y>0)?this.DV-y:-y;
}
// Montgomery reduction
function Montgomery(m) {
this.m = m;
this.mp = m.invDigit();
this.mpl = this.mp&0x7fff;
this.mph = this.mp>>15;
this.um = (1<<(m.DB-15))-1;
this.mt2 = 2*m.t;
}
// xR mod m
function montConvert(x) {
var r = nbi();
x.abs().dlShiftTo(this.m.t,r);
r.divRemTo(this.m,null,r);
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
return r;
}
// x/R mod m
function montRevert(x) {
var r = nbi();
x.copyTo(r);
this.reduce(r);
return r;
}
// x = x/R mod m (HAC 14.32)
function montReduce(x) {
while(x.t <= this.mt2) // pad x so am has enough room later
x[x.t++] = 0;
for(var i = 0; i < this.m.t; ++i) {
// faster way of calculating u0 = x[i]*mp mod DV
var j = x[i]&0x7fff;
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
// use am to combine the multiply-shift-add into one call
j = i+this.m.t;
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
// propagate carry
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
}
x.clamp();
x.drShiftTo(this.m.t,x);
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}
// r = "x^2/R mod m"; x != r
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
// r = "xy/R mod m"; x,y != r
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;
// (protected) true iff this is even
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
function bnpExp(e,z) {
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
g.copyTo(r);
while(--i >= 0) {
z.sqrTo(r,r2);
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
else { var t = r; r = r2; r2 = t; }
}
return z.revert(r);
}
// (public) this^e % m, 0 <= e < 2^32
function bnModPowInt(e,m) {
var z;
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
return this.exp(e,z);
}
// protected
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;
// public
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;
// "constants"
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);
module.exports = BigInteger;
/*
* Copyright (c) 2003-2005 Tom Wu (tjw@cs.Stanford.EDU)
* All Rights Reserved.
*
* Modified by Recurity Labs GmbH
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* In addition, the following condition applies:
*
* All redistributions must retain an intact copy of this copyright notice
* and disclaimer.
*/
// Extended JavaScript BN functions, required for RSA private ops.
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
// Version 1.2: square() API, isProbablePrime fix
// (public)
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
// (public) return value as integer
function bnIntValue() {
if(this.s < 0) {
if(this.t == 1) return this[0]-this.DV;
else if(this.t == 0) return -1;
}
else if(this.t == 1) return this[0];
else if(this.t == 0) return 0;
// assumes 16 < DB < 32
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
}
// (public) return value as byte
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
// (public) return value as short (assumes DB>=16)
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
// (protected) return x s.t. r^x < DV
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
// (public) 0 if this == 0, 1 if this > 0
function bnSigNum() {
if(this.s < 0) return -1;
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
else return 1;
}
// (protected) convert to radix string
function bnpToRadix(b) {
if(b == null) b = 10;
if(this.signum() == 0 || b < 2 || b > 36) return "0";
var cs = this.chunkSize(b);
var a = Math.pow(b,cs);
var d = nbv(a), y = nbi(), z = nbi(), r = "";
this.divRemTo(d,y,z);
while(y.signum() > 0) {
r = (a+z.intValue()).toString(b).substr(1) + r;
y.divRemTo(d,y,z);
}
return z.intValue().toString(b) + r;
}
// (protected) convert from radix string
function bnpFromRadix(s,b) {
this.fromInt(0);
if(b == null) b = 10;
var cs = this.chunkSize(b);
var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
for(var i = 0; i < s.length; ++i) {
var x = intAt(s,i);
if(x < 0) {
if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
continue;
}
w = b*w+x;
if(++j >= cs) {
this.dMultiply(d);
this.dAddOffset(w,0);
j = 0;
w = 0;
}
}
if(j > 0) {
this.dMultiply(Math.pow(b,j));
this.dAddOffset(w,0);
}
if(mi) BigInteger.ZERO.subTo(this,this);
}
// (protected) alternate constructor
function bnpFromNumber(a,b,c) {
if("number" == typeof b) {
// new BigInteger(int,int,RNG)
if(a < 2) this.fromInt(1);
else {
this.fromNumber(a,c);
if(!this.testBit(a-1)) // force MSB set
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
if(this.isEven()) this.dAddOffset(1,0); // force odd
while(!this.isProbablePrime(b)) {
this.dAddOffset(2,0);
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
}
}
}
else {
// new BigInteger(int,RNG)
var x = new Array(), t = a&7;
x.length = (a>>3)+1;
b.nextBytes(x);
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
this.fromString(x,256);
}
}
// (public) convert to bigendian byte array
function bnToByteArray() {
var i = this.t, r = new Array();
r[0] = this.s;
var p = this.DB-(i*this.DB)%8, d, k = 0;
if(i-- > 0) {
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
r[k++] = d|(this.s<<(this.DB-p));
while(i >= 0) {
if(p < 8) {
d = (this[i]&((1<<p)-1))<<(8-p);
d |= this[--i]>>(p+=this.DB-8);
}
else {
d = (this[i]>>(p-=8))&0xff;
if(p <= 0) { p += this.DB; --i; }
}
//if((d&0x80) != 0) d |= -256;
//if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
if(k > 0 || d != this.s) r[k++] = d;
}
}
return r;
}
function bnEquals(a) { return(this.compareTo(a)==0); }
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
// (protected) r = this op a (bitwise)
function bnpBitwiseTo(a,op,r) {
var i, f, m = Math.min(a.t,this.t);
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
if(a.t < this.t) {
f = a.s&this.DM;
for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
r.t = this.t;
}
else {
f = this.s&this.DM;
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
r.t = a.t;
}
r.s = op(this.s,a.s);
r.clamp();
}
// (public) this & a
function op_and(x,y) { return x&y; }
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
// (public) this | a
function op_or(x,y) { return x|y; }
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
// (public) this ^ a
function op_xor(x,y) { return x^y; }
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
// (public) this & ~a
function op_andnot(x,y) { return x&~y; }
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
// (public) ~this
function bnNot() {
var r = nbi();
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
r.t = this.t;
r.s = ~this.s;
return r;
}
// (public) this << n
function bnShiftLeft(n) {
var r = nbi();
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
return r;
}
// (public) this >> n
function bnShiftRight(n) {
var r = nbi();
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
return r;
}
// return index of lowest 1-bit in x, x < 2^31
function lbit(x) {
if(x == 0) return -1;
var r = 0;
if((x&0xffff) == 0) { x >>= 16; r += 16; }
if((x&0xff) == 0) { x >>= 8; r += 8; }
if((x&0xf) == 0) { x >>= 4; r += 4; }
if((x&3) == 0) { x >>= 2; r += 2; }
if((x&1) == 0) ++r;
return r;
}
// (public) returns index of lowest 1-bit (or -1 if none)
function bnGetLowestSetBit() {
for(var i = 0; i < this.t; ++i)
if(this[i] != 0) return i*this.DB+lbit(this[i]);
if(this.s < 0) return this.t*this.DB;
return -1;
}
// return number of 1 bits in x
function cbit(x) {
var r = 0;
while(x != 0) { x &= x-1; ++r; }
return r;
}
// (public) return number of set bits
function bnBitCount() {
var r = 0, x = this.s&this.DM;
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
return r;
}
// (public) true iff nth bit is set
function bnTestBit(n) {
var j = Math.floor(n/this.DB);
if(j >= this.t) return(this.s!=0);
return((this[j]&(1<<(n%this.DB)))!=0);
}
// (protected) this op (1<<n)
function bnpChangeBit(n,op) {
var r = BigInteger.ONE.shiftLeft(n);
this.bitwiseTo(r,op,r);
return r;
}
// (public) this | (1<<n)
function bnSetBit(n) { return this.changeBit(n,op_or); }
// (public) this & ~(1<<n)
function bnClearBit(n) { return this.changeBit(n,op_andnot); }
// (public) this ^ (1<<n)
function bnFlipBit(n) { return this.changeBit(n,op_xor); }
// (protected) r = this + a
function bnpAddTo(a,r) {
var i = 0, c = 0, m = Math.min(a.t,this.t);
while(i < m) {
c += this[i]+a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
if(a.t < this.t) {
c += a.s;
while(i < this.t) {
c += this[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += this.s;
}
else {
c += this.s;
while(i < a.t) {
c += a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += a.s;
}
r.s = (c<0)?-1:0;
if(c > 0) r[i++] = c;
else if(c < -1) r[i++] = this.DV+c;
r.t = i;
r.clamp();
}
// (public) this + a
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
// (public) this - a
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
// (public) this * a
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
// (public) this^2
function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
// (public) this / a
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
// (public) this % a
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
// (public) [this/a,this%a]
function bnDivideAndRemainder(a) {
var q = nbi(), r = nbi();
this.divRemTo(a,q,r);
return new Array(q,r);
}
// (protected) this *= n, this >= 0, 1 < n < DV
function bnpDMultiply(n) {
this[this.t] = this.am(0,n-1,this,0,0,this.t);
++this.t;
this.clamp();
}
// (protected) this += n << w words, this >= 0
function bnpDAddOffset(n,w) {
if(n == 0) return;
while(this.t <= w) this[this.t++] = 0;
this[w] += n;
while(this[w] >= this.DV) {
this[w] -= this.DV;
if(++w >= this.t) this[this.t++] = 0;
++this[w];
}
}
// A "null" reducer
function NullExp() {}
function nNop(x) { return x; }
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
function nSqrTo(x,r) { x.squareTo(r); }
NullExp.prototype.convert = nNop;
NullExp.prototype.revert = nNop;
NullExp.prototype.mulTo = nMulTo;
NullExp.prototype.sqrTo = nSqrTo;
// (public) this^e
function bnPow(e) { return this.exp(e,new NullExp()); }
// (protected) r = lower n words of "this * a", a.t <= n
// "this" should be the larger one if appropriate.
function bnpMultiplyLowerTo(a,n,r) {
var i = Math.min(this.t+a.t,n);
r.s = 0; // assumes a,this >= 0
r.t = i;
while(i > 0) r[--i] = 0;
var j;
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
r.clamp();
}
// (protected) r = "this * a" without lower n words, n > 0
// "this" should be the larger one if appropriate.
function bnpMultiplyUpperTo(a,n,r) {
--n;
var i = r.t = this.t+a.t-n;
r.s = 0; // assumes a,this >= 0
while(--i >= 0) r[i] = 0;
for(i = Math.max(n-this.t,0); i < a.t; ++i)
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
r.clamp();
r.drShiftTo(1,r);
}
// Barrett modular reduction
function Barrett(m) {
// setup Barrett
this.r2 = nbi();
this.q3 = nbi();
BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
this.mu = this.r2.divide(m);
this.m = m;
}
function barrettConvert(x) {
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
else if(x.compareTo(this.m) < 0) return x;
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
}
function barrettRevert(x) { return x; }
// x = x mod m (HAC 14.42)
function barrettReduce(x) {
x.drShiftTo(this.m.t-1,this.r2);
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
x.subTo(this.r2,x);
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}
// r = x^2 mod m; x != r
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
// r = x*y mod m; x,y != r
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Barrett.prototype.convert = barrettConvert;
Barrett.prototype.revert = barrettRevert;
Barrett.prototype.reduce = barrettReduce;
Barrett.prototype.mulTo = barrettMulTo;
Barrett.prototype.sqrTo = barrettSqrTo;
// (public) this^e % m (HAC 14.85)
function bnModPow(e,m) {
var i = e.bitLength(), k, r = nbv(1), z;
if(i <= 0) return r;
else if(i < 18) k = 1;
else if(i < 48) k = 3;
else if(i < 144) k = 4;
else if(i < 768) k = 5;
else k = 6;
if(i < 8)
z = new Classic(m);
else if(m.isEven())
z = new Barrett(m);
else
z = new Montgomery(m);
// precomputation
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
g[1] = z.convert(this);
if(k > 1) {
var g2 = nbi();
z.sqrTo(g[1],g2);
while(n <= km) {
g[n] = nbi();
z.mulTo(g2,g[n-2],g[n]);
n += 2;
}
}
var j = e.t-1, w, is1 = true, r2 = nbi(), t;
i = nbits(e[j])-1;
while(j >= 0) {
if(i >= k1) w = (e[j]>>(i-k1))&km;
else {
w = (e[j]&((1<<(i+1))-1))<<(k1-i);
if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
}
n = k;
while((w&1) == 0) { w >>= 1; --n; }
if((i -= n) < 0) { i += this.DB; --j; }
if(is1) { // ret == 1, don't bother squaring or multiplying it
g[w].copyTo(r);
is1 = false;
}
else {
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
z.mulTo(r2,g[w],r);
}
while(j >= 0 && (e[j]&(1<<i)) == 0) {
z.sqrTo(r,r2); t = r; r = r2; r2 = t;
if(--i < 0) { i = this.DB-1; --j; }
}
}
return z.revert(r);
}
// (public) gcd(this,a) (HAC 14.54)
function bnGCD(a) {
var x = (this.s<0)?this.negate():this.clone();
var y = (a.s<0)?a.negate():a.clone();
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
if(g < 0) return x;
if(i < g) g = i;
if(g > 0) {
x.rShiftTo(g,x);
y.rShiftTo(g,y);
}
while(x.signum() > 0) {
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
if(x.compareTo(y) >= 0) {
x.subTo(y,x);
x.rShiftTo(1,x);
}
else {
y.subTo(x,y);
y.rShiftTo(1,y);
}
}
if(g > 0) y.lShiftTo(g,y);
return y;
}
// (protected) this % n, n < 2^26
function bnpModInt(n) {
if(n <= 0) return 0;
var d = this.DV%n, r = (this.s<0)?n-1:0;
if(this.t > 0)
if(d == 0) r = this[0]%n;
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
return r;
}
// (public) 1/this % m (HAC 14.61)
function bnModInverse(m) {
var ac = m.isEven();
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
var u = m.clone(), v = this.clone();
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
while(u.signum() != 0) {
while(u.isEven()) {
u.rShiftTo(1,u);
if(ac) {
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
a.rShiftTo(1,a);
}
else if(!b.isEven()) b.subTo(m,b);
b.rShiftTo(1,b);
}
while(v.isEven()) {
v.rShiftTo(1,v);
if(ac) {
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
c.rShiftTo(1,c);
}
else if(!d.isEven()) d.subTo(m,d);
d.rShiftTo(1,d);
}
if(u.compareTo(v) >= 0) {
u.subTo(v,u);
if(ac) a.subTo(c,a);
b.subTo(d,b);
}
else {
v.subTo(u,v);
if(ac) c.subTo(a,c);
d.subTo(b,d);
}
}
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
if(d.compareTo(m) >= 0) return d.subtract(m);
if(d.signum() < 0) d.addTo(m,d); else return d;
if(d.signum() < 0) return d.add(m); else return d;
}
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
var lplim = (1<<26)/lowprimes[lowprimes.length-1];
// (public) test primality with certainty >= 1-.5^t
function bnIsProbablePrime(t) {
var i, x = this.abs();
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
for(i = 0; i < lowprimes.length; ++i)
if(x[0] == lowprimes[i]) return true;
return false;
}
if(x.isEven()) return false;
i = 1;
while(i < lowprimes.length) {
var m = lowprimes[i], j = i+1;
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
m = x.modInt(m);
while(i < j) if(m%lowprimes[i++] == 0) return false;
}
return x.millerRabin(t);
}
/* added by Recurity Labs */
function nbits(x) {
var n = 1, t;
if ((t = x >>> 16) != 0) {
x = t;
n += 16;
}
if ((t = x >> 8) != 0) {
x = t;
n += 8;
}
if ((t = x >> 4) != 0) {
x = t;
n += 4;
}
if ((t = x >> 2) != 0) {
x = t;
n += 2;
}
if ((t = x >> 1) != 0) {
x = t;
n += 1;
}
return n;
}
function bnToMPI () {
var ba = this.toByteArray();
var size = (ba.length-1)*8+nbits(ba[0]);
var result = "";
result += String.fromCharCode((size & 0xFF00) >> 8);
result += String.fromCharCode(size & 0xFF);
result += util.bin2str(ba);
return result;
}
/* END of addition */
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
function bnpMillerRabin(t) {
var n1 = this.subtract(BigInteger.ONE);
var k = n1.getLowestSetBit();
if(k <= 0) return false;
var r = n1.shiftRight(k);
t = (t+1)>>1;
if(t > lowprimes.length) t = lowprimes.length;
var a = nbi();
for(var i = 0; i < t; ++i) {
//Pick bases at random, instead of starting at 2
a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
var y = a.modPow(r,this);
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
var j = 1;
while(j++ < k && y.compareTo(n1) != 0) {
y = y.modPowInt(2,this);
if(y.compareTo(BigInteger.ONE) == 0) return false;
}
if(y.compareTo(n1) != 0) return false;
}
}
return true;
}
var BigInteger = require('./jsbn.js');
// protected
BigInteger.prototype.chunkSize = bnpChunkSize;
BigInteger.prototype.toRadix = bnpToRadix;
BigInteger.prototype.fromRadix = bnpFromRadix;
BigInteger.prototype.fromNumber = bnpFromNumber;
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
BigInteger.prototype.changeBit = bnpChangeBit;
BigInteger.prototype.addTo = bnpAddTo;
BigInteger.prototype.dMultiply = bnpDMultiply;
BigInteger.prototype.dAddOffset = bnpDAddOffset;
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
BigInteger.prototype.modInt = bnpModInt;
BigInteger.prototype.millerRabin = bnpMillerRabin;
// public
BigInteger.prototype.clone = bnClone;
BigInteger.prototype.intValue = bnIntValue;
BigInteger.prototype.byteValue = bnByteValue;
BigInteger.prototype.shortValue = bnShortValue;
BigInteger.prototype.signum = bnSigNum;
BigInteger.prototype.toByteArray = bnToByteArray;
BigInteger.prototype.equals = bnEquals;
BigInteger.prototype.min = bnMin;
BigInteger.prototype.max = bnMax;
BigInteger.prototype.and = bnAnd;
BigInteger.prototype.or = bnOr;
BigInteger.prototype.xor = bnXor;
BigInteger.prototype.andNot = bnAndNot;
BigInteger.prototype.not = bnNot;
BigInteger.prototype.shiftLeft = bnShiftLeft;
BigInteger.prototype.shiftRight = bnShiftRight;
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
BigInteger.prototype.bitCount = bnBitCount;
BigInteger.prototype.testBit = bnTestBit;
BigInteger.prototype.setBit = bnSetBit;
BigInteger.prototype.clearBit = bnClearBit;
BigInteger.prototype.flipBit = bnFlipBit;
BigInteger.prototype.add = bnAdd;
BigInteger.prototype.subtract = bnSubtract;
BigInteger.prototype.multiply = bnMultiply;
BigInteger.prototype.divide = bnDivide;
BigInteger.prototype.remainder = bnRemainder;
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
BigInteger.prototype.modPow = bnModPow;
BigInteger.prototype.modInverse = bnModInverse;
BigInteger.prototype.pow = bnPow;
BigInteger.prototype.gcd = bnGCD;
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
BigInteger.prototype.toMPI = bnToMPI;
// JSBN-specific extension
BigInteger.prototype.square = bnSquare;
},{"../../util":52,"./jsbn.js":21}],22:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
// RSA implementation
var BigInteger = require('./jsbn.js'),
util = require('../../util'),
random = require('../random.js');
function SecureRandom(){
function nextBytes(byteArray){
for(var n = 0; n < byteArray.length;n++){
byteArray[n] = random.getSecureRandomOctet();
}
}
this.nextBytes = nextBytes;
}
function RSA() {
/**
* This function uses jsbn Big Num library to decrypt RSA
* @param m
* message
* @param d
* RSA d as BigInteger
* @param p
* RSA p as BigInteger
* @param q
* RSA q as BigInteger
* @param u
* RSA u as BigInteger
* @return {BigInteger} The decrypted value of the message
*/
function decrypt(m, d, p, q, u) {
var xp = m.mod(p).modPow(d.mod(p.subtract(BigInteger.ONE)), p);
var xq = m.mod(q).modPow(d.mod(q.subtract(BigInteger.ONE)), q);
util.print_debug("rsa.js decrypt\nxpn:"+util.hexstrdump(xp.toMPI())+"\nxqn:"+util.hexstrdump(xq.toMPI()));
var t = xq.subtract(xp);
if (t[0] == 0) {
t = xp.subtract(xq);
t = t.multiply(u).mod(q);
t = q.subtract(t);
} else {
t = t.multiply(u).mod(q);
}
return t.multiply(p).add(xp);
}
/**
* encrypt message
* @param m message as BigInteger
* @param e public MPI part as BigInteger
* @param n public MPI part as BigInteger
* @return BigInteger
*/
function encrypt(m,e,n) {
return m.modPowInt(e, n);
}
/* Sign and Verify */
function sign(m,d,n) {
return m.modPow(d, n);
}
function verify(x,e,n) {
return x.modPowInt(e, n);
}
// "empty" RSA key constructor
function keyObject() {
this.n = null;
this.e = 0;
this.ee = null;
this.d = null;
this.p = null;
this.q = null;
this.dmp1 = null;
this.dmq1 = null;
this.u = null;
}
// Generate a new random private key B bits long, using public expt E
function generate(B,E) {
var key = new keyObject();
var rng = new SecureRandom();
var qs = B>>1;
key.e = parseInt(E,16);
key.ee = new BigInteger(E,16);
for(;;) {
for(;;) {
key.p = new BigInteger(B-qs,1,rng);
if(key.p.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.p.isProbablePrime(10)) break;
}
for(;;) {
key.q = new BigInteger(qs,1,rng);
if(key.q.subtract(BigInteger.ONE).gcd(key.ee).compareTo(BigInteger.ONE) == 0 && key.q.isProbablePrime(10)) break;
}
if(key.p.compareTo(key.q) <= 0) {
var t = key.p;
key.p = key.q;
key.q = t;
}
var p1 = key.p.subtract(BigInteger.ONE);
var q1 = key.q.subtract(BigInteger.ONE);
var phi = p1.multiply(q1);
if(phi.gcd(key.ee).compareTo(BigInteger.ONE) == 0) {
key.n = key.p.multiply(key.q);
key.d = key.ee.modInverse(phi);
key.dmp1 = key.d.mod(p1);
key.dmq1 = key.d.mod(q1);
key.u = key.p.modInverse(key.q);
break;
}
}
return key;
}
this.encrypt = encrypt;
this.decrypt = decrypt;
this.verify = verify;
this.sign = sign;
this.generate = generate;
this.keyObject = keyObject;
}
module.exports = RSA;
},{"../../util":52,"../random.js":23,"./jsbn.js":21}],23:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// The GPG4Browsers crypto interface
module.exports = {
/**
* Retrieve secure random byte string of the specified length
* @param {Integer} length Length in bytes to generate
* @return {String} Random byte string
*/
getRandomBytes: function(length) {
var result = '';
for (var i = 0; i < length; i++) {
result += String.fromCharCode(this.getSecureRandomOctet());
}
return result;
},
/**
* Return a pseudo-random number in the specified range
* @param {Integer} from Min of the random number
* @param {Integer} to Max of the random number (max 32bit)
* @return {Integer} A pseudo random number
*/
getPseudoRandom: function(from, to) {
return Math.round(Math.random()*(to-from))+from;
},
/**
* Return a secure random number in the specified range
* @param {Integer} from Min of the random number
* @param {Integer} to Max of the random number (max 32bit)
* @return {Integer} A secure random number
*/
getSecureRandom: function(from, to) {
var buf = new Uint32Array(1);
window.crypto.getRandomValues(buf);
var bits = ((to-from)).toString(2).length;
while ((buf[0] & (Math.pow(2, bits) -1)) > (to-from))
window.crypto.getRandomValues(buf);
return from+(Math.abs(buf[0] & (Math.pow(2, bits) -1)));
},
getSecureRandomOctet: function() {
var buf = new Uint32Array(1);
window.crypto.getRandomValues(buf);
return buf[0] & 0xFF;
}
}
},{}],24:[function(require,module,exports){
var publicKey = require('./public_key'),
pkcs1 = require('./pkcs1.js'),
hashModule = require('./hash');
module.exports = {
/**
*
* @param {Integer} algo public Key algorithm
* @param {Integer} hash_algo Hash algorithm
* @param {openpgp_type_mpi[]} msg_MPIs Signature multiprecision integers
* @param {openpgp_type_mpi[]} publickey_MPIs Public key multiprecision integers
* @param {String} data Data on where the signature was computed on.
* @return {Boolean} true if signature (sig_data was equal to data over hash)
*/
verify: function(algo, hash_algo, msg_MPIs, publickey_MPIs, data) {
var calc_hash = hashModule.digest(hash_algo, data);
switch(algo) {
case 1: // RSA (Encrypt or Sign) [HAC]
case 2: // RSA Encrypt-Only [HAC]
case 3: // RSA Sign-Only [HAC]
var rsa = new publicKey.rsa();
var n = publickey_MPIs[0].toBigInteger();
var e = publickey_MPIs[1].toBigInteger();
var x = msg_MPIs[0].toBigInteger();
var dopublic = rsa.verify(x,e,n);
var hash = pkcs1.emsa.decode(hash_algo,dopublic.toMPI().substring(2));
if (hash == -1) {
throw new Error('PKCS1 padding in message or key incorrect. Aborting...');
}
return hash == calc_hash;
case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
throw new Error("signing with Elgamal is not defined in the OpenPGP standard.");
case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
var dsa = new publicKey.dsa();
var s1 = msg_MPIs[0].toBigInteger();
var s2 = msg_MPIs[1].toBigInteger();
var p = publickey_MPIs[0].toBigInteger();
var q = publickey_MPIs[1].toBigInteger();
var g = publickey_MPIs[2].toBigInteger();
var y = publickey_MPIs[3].toBigInteger();
var m = data;
var dopublic = dsa.verify(hash_algo,s1,s2,m,p,q,g,y);
return dopublic.compareTo(s1) == 0;
default:
throw new Error('Invalid signature algorithm.');
}
},
/**
* Create a signature on data using the specified algorithm
* @param {Integer} hash_algo hash Algorithm to use (See RFC4880 9.4)
* @param {Integer} algo Asymmetric cipher algorithm to use (See RFC4880 9.1)
* @param {openpgp_type_mpi[]} publicMPIs Public key multiprecision integers
* of the private key
* @param {openpgp_type_mpi[]} secretMPIs Private key multiprecision
* integers which is used to sign the data
* @param {String} data Data to be signed
* @return {openpgp_type_mpi[]}
*/
sign: function(hash_algo, algo, keyIntegers, data) {
switch(algo) {
case 1: // RSA (Encrypt or Sign) [HAC]
case 2: // RSA Encrypt-Only [HAC]
case 3: // RSA Sign-Only [HAC]
var rsa = new publicKey.rsa();
var d = keyIntegers[2].toBigInteger();
var n = keyIntegers[0].toBigInteger();
var m = pkcs1.emsa.encode(hash_algo,
data, keyIntegers[0].byteLength());
return rsa.sign(m, d, n).toMPI();
case 17: // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
var dsa = new publicKey.dsa();
var p = keyIntegers[0].toBigInteger();
var q = keyIntegers[1].toBigInteger();
var g = keyIntegers[2].toBigInteger();
var y = keyIntegers[3].toBigInteger();
var x = keyIntegers[4].toBigInteger();
var m = data;
var result = dsa.sign(hash_algo,m, g, p, q, x);
return result[0].toString() + result[1].toString();
case 16: // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.');
default:
throw new Error('Invalid signature algorithm.');
}
}
}
},{"./hash":10,"./pkcs1.js":15,"./public_key":20}],25:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var base64 = require('./base64.js');
/**
* Finds out which Ascii Armoring type is used. This is an internal function
* @param {String} text [String] ascii armored text
* @returns {Integer} 0 = MESSAGE PART n of m
* 1 = MESSAGE PART n
* 2 = SIGNED MESSAGE
* 3 = PGP MESSAGE
* 4 = PUBLIC KEY BLOCK
* 5 = PRIVATE KEY BLOCK
* null = unknown
*/
function get_type(text) {
var splittedtext = text.split('-----');
// BEGIN PGP MESSAGE, PART X/Y
// Used for multi-part messages, where the armor is split amongst Y
// parts, and this is the Xth part out of Y.
if (splittedtext[1].match(/BEGIN PGP MESSAGE, PART \d+\/\d+/)) {
return 0;
} else
// BEGIN PGP MESSAGE, PART X
// Used for multi-part messages, where this is the Xth part of an
// unspecified number of parts. Requires the MESSAGE-ID Armor
// Header to be used.
if (splittedtext[1].match(/BEGIN PGP MESSAGE, PART \d+/)) {
return 1;
} else
// BEGIN PGP SIGNATURE
// Used for detached signatures, OpenPGP/MIME signatures, and
// cleartext signatures. Note that PGP 2.x uses BEGIN PGP MESSAGE
// for detached signatures.
if (splittedtext[1].match(/BEGIN PGP SIGNED MESSAGE/)) {
return 2;
} else
// BEGIN PGP MESSAGE
// Used for signed, encrypted, or compressed files.
if (splittedtext[1].match(/BEGIN PGP MESSAGE/)) {
return 3;
} else
// BEGIN PGP PUBLIC KEY BLOCK
// Used for armoring public keys.
if (splittedtext[1].match(/BEGIN PGP PUBLIC KEY BLOCK/)) {
return 4;
} else
// BEGIN PGP PRIVATE KEY BLOCK
// Used for armoring private keys.
if (splittedtext[1].match(/BEGIN PGP PRIVATE KEY BLOCK/)) {
return 5;
}
}
/**
* Add additional information to the armor version of an OpenPGP binary
* packet block.
* @author Alex
* @version 2011-12-16
* @returns {String} The header information
*/
function armor_addheader() {
var result = "";
if (openpgp.config.config.show_version) {
result += "Version: "+openpgp.config.versionstring+'\r\n';
}
if (openpgp.config.config.show_comment) {
result += "Comment: "+openpgp.config.commentstring+'\r\n';
}
result += '\r\n';
return result;
}
/**
* Calculates a checksum over the given data and returns it base64 encoded
* @param {String} data Data to create a CRC-24 checksum for
* @return {String} Base64 encoded checksum
*/
function getCheckSum(data) {
var c = createcrc24(data);
var str = "" + String.fromCharCode(c >> 16)+
String.fromCharCode((c >> 8) & 0xFF)+
String.fromCharCode(c & 0xFF);
return base64.encode(str);
}
/**
* Calculates the checksum over the given data and compares it with the
* given base64 encoded checksum
* @param {String} data Data to create a CRC-24 checksum for
* @param {String} checksum Base64 encoded checksum
* @return {Boolean} True if the given checksum is correct; otherwise false
*/
function verifyCheckSum(data, checksum) {
var c = getCheckSum(data);
var d = checksum;
return c[0] == d[0] && c[1] == d[1] && c[2] == d[2];
}
/**
* Internal function to calculate a CRC-24 checksum over a given string (data)
* @param {String} data Data to create a CRC-24 checksum for
* @return {Integer} The CRC-24 checksum as number
*/
var crc_table = [
0x00000000, 0x00864cfb, 0x018ad50d, 0x010c99f6, 0x0393e6e1, 0x0315aa1a, 0x021933ec, 0x029f7f17, 0x07a18139, 0x0727cdc2, 0x062b5434, 0x06ad18cf, 0x043267d8, 0x04b42b23, 0x05b8b2d5, 0x053efe2e, 0x0fc54e89, 0x0f430272, 0x0e4f9b84, 0x0ec9d77f, 0x0c56a868, 0x0cd0e493, 0x0ddc7d65, 0x0d5a319e, 0x0864cfb0, 0x08e2834b, 0x09ee1abd, 0x09685646, 0x0bf72951, 0x0b7165aa, 0x0a7dfc5c, 0x0afbb0a7, 0x1f0cd1e9, 0x1f8a9d12, 0x1e8604e4, 0x1e00481f, 0x1c9f3708, 0x1c197bf3, 0x1d15e205, 0x1d93aefe, 0x18ad50d0, 0x182b1c2b, 0x192785dd, 0x19a1c926, 0x1b3eb631, 0x1bb8faca, 0x1ab4633c, 0x1a322fc7, 0x10c99f60, 0x104fd39b, 0x11434a6d, 0x11c50696, 0x135a7981, 0x13dc357a, 0x12d0ac8c, 0x1256e077, 0x17681e59, 0x17ee52a2, 0x16e2cb54, 0x166487af, 0x14fbf8b8, 0x147db443, 0x15712db5, 0x15f7614e, 0x3e19a3d2, 0x3e9fef29, 0x3f9376df, 0x3f153a24, 0x3d8a4533, 0x3d0c09c8, 0x3c00903e, 0x3c86dcc5, 0x39b822eb, 0x393e6e10, 0x3832f7e6, 0x38b4bb1d, 0x3a2bc40a, 0x3aad88f1, 0x3ba11107, 0x3b275dfc, 0x31dced5b, 0x315aa1a0,
0x30563856, 0x30d074ad, 0x324f0bba, 0x32c94741, 0x33c5deb7, 0x3343924c, 0x367d6c62, 0x36fb2099, 0x37f7b96f, 0x3771f594, 0x35ee8a83, 0x3568c678, 0x34645f8e, 0x34e21375, 0x2115723b, 0x21933ec0, 0x209fa736, 0x2019ebcd, 0x228694da, 0x2200d821, 0x230c41d7, 0x238a0d2c, 0x26b4f302, 0x2632bff9, 0x273e260f, 0x27b86af4, 0x252715e3, 0x25a15918, 0x24adc0ee, 0x242b8c15, 0x2ed03cb2, 0x2e567049, 0x2f5ae9bf, 0x2fdca544, 0x2d43da53, 0x2dc596a8, 0x2cc90f5e, 0x2c4f43a5, 0x2971bd8b, 0x29f7f170, 0x28fb6886, 0x287d247d, 0x2ae25b6a, 0x2a641791, 0x2b688e67, 0x2beec29c, 0x7c3347a4, 0x7cb50b5f, 0x7db992a9, 0x7d3fde52, 0x7fa0a145, 0x7f26edbe, 0x7e2a7448, 0x7eac38b3, 0x7b92c69d, 0x7b148a66, 0x7a181390, 0x7a9e5f6b, 0x7801207c, 0x78876c87, 0x798bf571, 0x790db98a, 0x73f6092d, 0x737045d6, 0x727cdc20, 0x72fa90db, 0x7065efcc, 0x70e3a337, 0x71ef3ac1, 0x7169763a, 0x74578814, 0x74d1c4ef, 0x75dd5d19, 0x755b11e2, 0x77c46ef5, 0x7742220e, 0x764ebbf8, 0x76c8f703, 0x633f964d, 0x63b9dab6, 0x62b54340, 0x62330fbb,
0x60ac70ac, 0x602a3c57, 0x6126a5a1, 0x61a0e95a, 0x649e1774, 0x64185b8f, 0x6514c279, 0x65928e82, 0x670df195, 0x678bbd6e, 0x66872498, 0x66016863, 0x6cfad8c4, 0x6c7c943f, 0x6d700dc9, 0x6df64132, 0x6f693e25, 0x6fef72de, 0x6ee3eb28, 0x6e65a7d3, 0x6b5b59fd, 0x6bdd1506, 0x6ad18cf0, 0x6a57c00b, 0x68c8bf1c, 0x684ef3e7, 0x69426a11, 0x69c426ea, 0x422ae476, 0x42aca88d, 0x43a0317b, 0x43267d80, 0x41b90297, 0x413f4e6c, 0x4033d79a, 0x40b59b61, 0x458b654f, 0x450d29b4, 0x4401b042, 0x4487fcb9, 0x461883ae, 0x469ecf55, 0x479256a3, 0x47141a58, 0x4defaaff, 0x4d69e604, 0x4c657ff2, 0x4ce33309, 0x4e7c4c1e, 0x4efa00e5, 0x4ff69913, 0x4f70d5e8, 0x4a4e2bc6, 0x4ac8673d, 0x4bc4fecb, 0x4b42b230, 0x49ddcd27, 0x495b81dc, 0x4857182a, 0x48d154d1, 0x5d26359f, 0x5da07964, 0x5cace092, 0x5c2aac69, 0x5eb5d37e, 0x5e339f85, 0x5f3f0673, 0x5fb94a88, 0x5a87b4a6, 0x5a01f85d, 0x5b0d61ab, 0x5b8b2d50, 0x59145247, 0x59921ebc, 0x589e874a, 0x5818cbb1, 0x52e37b16, 0x526537ed, 0x5369ae1b, 0x53efe2e0, 0x51709df7, 0x51f6d10c,
0x50fa48fa, 0x507c0401, 0x5542fa2f, 0x55c4b6d4, 0x54c82f22, 0x544e63d9, 0x56d11cce, 0x56575035, 0x575bc9c3, 0x57dd8538];
function createcrc24(input) {
var crc = 0xB704CE;
var index = 0;
while((input.length - index) > 16) {
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+1)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+2)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+3)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+4)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+5)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+6)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+7)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+8)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+9)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+10)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+11)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+12)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+13)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+14)) & 0xff];
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index+15)) & 0xff];
index += 16;
}
for(var j = index; j < input.length; j++) {
crc = (crc << 8) ^ crc_table[((crc >> 16) ^ input.charCodeAt(index++)) & 0xff]
}
return crc & 0xffffff;
}
/**
* DeArmor an OpenPGP armored message; verify the checksum and return
* the encoded bytes
* @param {String} text OpenPGP armored message
* @returns {(Boolean|Object)} Either false in case of an error
* or an object with attribute "text" containing the message text
* and an attribute "openpgp" containing the bytes.
*/
function dearmor(text) {
text = text.replace(/\r/g, '')
var type = get_type(text);
if (type != 2) {
var splittedtext = text.split('-----');
var data = {
openpgp: base64.decode(
splittedtext[2]
.split('\n\n')[1]
.split("\n=")[0]
.replace(/\n- /g,"\n")),
type: type
};
if (verifyCheckSum(data.openpgp,
splittedtext[2]
.split('\n\n')[1]
.split("\n=")[1]
.split('\n')[0]))
return data;
else {
util.print_error("Ascii armor integrity check on message failed: '"
+ splittedtext[2]
.split('\n\n')[1]
.split("\n=")[1]
.split('\n')[0]
+ "' should be '"
+ getCheckSum(data)) + "'";
return false;
}
} else {
var splittedtext = text.split('-----');
var result = {
text: splittedtext[2]
.replace(/\n- /g,"\n")
.split("\n\n")[1],
openpgp: base64_decode(splittedtext[4]
.split("\n\n")[1]
.split("\n=")[0]),
type: type
};
if (verifyCheckSum(result.openpgp, splittedtext[4]
.split("\n\n")[1]
.split("\n=")[1]))
return result;
else {
util.print_error("Ascii armor integrity check on message failed");
return false;
}
}
}
/**
* Armor an OpenPGP binary packet block
* @param {Integer} messagetype type of the message
* @param data
* @param {Integer} partindex
* @param {Integer} parttotal
* @returns {String} Armored text
*/
function armor(messagetype, data, partindex, parttotal) {
var result = "";
switch(messagetype) {
case 0:
result += "-----BEGIN PGP MESSAGE, PART "+partindex+"/"+parttotal+"-----\r\n";
result += armor_addheader();
result += base64.encode(data);
result += "\r\n="+getCheckSum(data)+"\r\n";
result += "-----END PGP MESSAGE, PART "+partindex+"/"+parttotal+"-----\r\n";
break;
case 1:
result += "-----BEGIN PGP MESSAGE, PART "+partindex+"-----\r\n";
result += armor_addheader();
result += base64.encode(data);
result += "\r\n="+getCheckSum(data)+"\r\n";
result += "-----END PGP MESSAGE, PART "+partindex+"-----\r\n";
break;
case 2:
result += "\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\nHash: "+data.hash+"\r\n\r\n";
result += data.text.replace(/\n-/g,"\n- -");
result += "\r\n-----BEGIN PGP SIGNATURE-----\r\n";
result += armor_addheader();
result += base64.encode(data.openpgp);
result += "\r\n="+getCheckSum(data.openpgp)+"\r\n";
result += "-----END PGP SIGNATURE-----\r\n";
break;
case 3:
result += "-----BEGIN PGP MESSAGE-----\r\n";
result += armor_addheader();
result += base64.encode(data);
result += "\r\n="+getCheckSum(data)+"\r\n";
result += "-----END PGP MESSAGE-----\r\n";
break;
case 4:
result += "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n";
result += armor_addheader();
result += base64.encode(data);
result += "\r\n="+getCheckSum(data)+"\r\n";
result += "-----END PGP PUBLIC KEY BLOCK-----\r\n\r\n";
break;
case 5:
result += "-----BEGIN PGP PRIVATE KEY BLOCK-----\r\n";
result += armor_addheader();
result += base64.encode(data);
result += "\r\n="+getCheckSum(data)+"\r\n";
result += "-----END PGP PRIVATE KEY BLOCK-----\r\n";
break;
}
return result;
}
module.exports = {
encode: armor,
decode: dearmor
}
},{"./base64.js":26}],26:[function(require,module,exports){
/* OpenPGP radix-64/base64 string encoding/decoding
* Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
* version 1.0, check www.haneWIN.de for the latest version
*
* This software is provided as-is, without express or implied warranty.
* Permission to use, copy, modify, distribute or sell this software, with or
* without fee, for any purpose and by any individual or organization, is hereby
* granted, provided that the above copyright notice and this paragraph appear
* in all copies. Distribution as a part of an application or binary must
* include the above copyright notice in the documentation and/or other materials
* provided with the application or distribution.
*/
var b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function s2r(t) {
var a, c, n;
var r = '', l = 0, s = 0;
var tl = t.length;
for (n = 0; n < tl; n++) {
c = t.charCodeAt(n);
if (s == 0) {
r += b64s.charAt((c >> 2) & 63);
a = (c & 3) << 4;
} else if (s == 1) {
r += b64s.charAt((a | (c >> 4) & 15));
a = (c & 15) << 2;
} else if (s == 2) {
r += b64s.charAt(a | ((c >> 6) & 3));
l += 1;
if ((l % 60) == 0)
r += "\n";
r += b64s.charAt(c & 63);
}
l += 1;
if ((l % 60) == 0)
r += "\n";
s += 1;
if (s == 3)
s = 0;
}
if (s > 0) {
r += b64s.charAt(a);
l += 1;
if ((l % 60) == 0)
r += "\n";
r += '=';
l += 1;
}
if (s == 1) {
if ((l % 60) == 0)
r += "\n";
r += '=';
}
return r;
}
function r2s(t) {
var c, n;
var r = '', s = 0, a = 0;
var tl = t.length;
for (n = 0; n < tl; n++) {
c = b64s.indexOf(t.charAt(n));
if (c >= 0) {
if (s)
r += String.fromCharCode(a | (c >> (6 - s)) & 255);
s = (s + 2) & 7;
a = (c << s) & 255;
}
}
return r;
}
module.exports = {
encode: s2r,
decode: r2s
}
},{}],27:[function(require,module,exports){
module.exports = {
/** A string to key specifier type
* @enum {Integer}
*/
s2k: {
simple: 0,
salted: 1,
iterated: 3,
gnu: 101
},
/** RFC4880, section 9.1
* @enum {String}
*/
publicKey: {
rsa_encrypt_sign: 1,
rsa_encrypt: 2,
rsa_sign: 3,
elgamal: 16,
dsa: 17
},
/** RFC4880, section 9.2
* @enum {String}
*/
symmetric: {
plaintext: 0,
/** Not implemented! */
idea: 1,
tripledes: 2,
cast5: 3,
blowfish: 4,
aes128: 7,
aes192: 8,
aes256: 9,
twofish: 10
},
/** RFC4880, section 9.3
* @enum {String}
*/
compression: {
uncompressed: 0,
/** RFC1951 */
zip: 1,
/** RFC1950 */
zlib: 2,
bzip2: 3
},
/** RFC4880, section 9.4
* @enum {String}
*/
hash: {
md5: 1,
sha1: 2,
ripemd: 3,
sha256: 8,
sha384: 9,
sha512: 10,
sha224: 11
},
/**
* @enum {String}
* A list of packet types and numeric tags associated with them.
*/
packet: {
public_key_encrypted_session_key: 1,
signature: 2,
sym_encrypted_session_key: 3,
one_pass_signature: 4,
secret_key: 5,
public_key: 6,
secret_subkey: 7,
compressed: 8,
symmetrically_encrypted: 9,
marker: 10,
literal: 11,
trust: 12,
userid: 13,
public_subkey: 14,
user_attribute: 17,
sym_encrypted_integrity_protected: 18,
modification_detection_code: 19
},
/**
* Data types in the literal packet
* @readonly
* @enum {String}
*/
literal: {
/** Binary data */
binary: 'b'.charCodeAt(),
/** Text data */
text: 't'.charCodeAt(),
/** Utf8 data */
utf8: 'u'.charCodeAt()
},
/** One pass signature packet type
* @enum {String} */
signature: {
/** 0x00: Signature of a binary document. */
binary: 0,
/** 0x01: Signature of a canonical text document.
* Canonicalyzing the document by converting line endings. */
text: 1,
/** 0x02: Standalone signature.
* This signature is a signature of only its own subpacket contents.
* It is calculated identically to a signature over a zero-lengh
* binary document. Note that it doesn't make sense to have a V3
* standalone signature. */
standalone: 2,
/** 0x10: Generic certification of a User ID and Public-Key packet.
* The issuer of this certification does not make any particular
* assertion as to how well the certifier has checked that the owner
* of the key is in fact the person described by the User ID. */
cert_generic: 16,
/** 0x11: Persona certification of a User ID and Public-Key packet.
* The issuer of this certification has not done any verification of
* the claim that the owner of this key is the User ID specified. */
cert_persona: 17,
/** 0x12: Casual certification of a User ID and Public-Key packet.
* The issuer of this certification has done some casual
* verification of the claim of identity. */
cert_casual: 18,
/** 0x13: Positive certification of a User ID and Public-Key packet.
* The issuer of this certification has done substantial
* verification of the claim of identity.
*
* Most OpenPGP implementations make their "key signatures" as 0x10
* certifications. Some implementations can issue 0x11-0x13
* certifications, but few differentiate between the types. */
cert_positive: 19,
/** 0x30: Certification revocation signature
* This signature revokes an earlier User ID certification signature
* (signature class 0x10 through 0x13) or direct-key signature
* (0x1F). It should be issued by the same key that issued the
* revoked signature or an authorized revocation key. The signature
* is computed over the same data as the certificate that it
* revokes, and should have a later creation date than that
* certificate. */
cert_revocation: 48,
/** 0x18: Subkey Binding Signature
* This signature is a statement by the top-level signing key that
* indicates that it owns the subkey. This signature is calculated
* directly on the primary key and subkey, and not on any User ID or
* other packets. A signature that binds a signing subkey MUST have
* an Embedded Signature subpacket in this binding signature that
* contains a 0x19 signature made by the signing subkey on the
* primary key and subkey. */
subkey_binding: 24,
/** 0x19: Primary Key Binding Signature
* This signature is a statement by a signing subkey, indicating
* that it is owned by the primary key and subkey. This signature
* is calculated the same way as a 0x18 signature: directly on the
* primary key and subkey, and not on any User ID or other packets.
* When a signature is made over a key, the hash data starts with the
* octet 0x99, followed by a two-octet length of the key, and then body
* of the key packet. (Note that this is an old-style packet header for
* a key packet with two-octet length.) A subkey binding signature
* (type 0x18) or primary key binding signature (type 0x19) then hashes
* the subkey using the same format as the main key (also using 0x99 as
* the first octet). */
key_binding: 25,
/** 0x1F: Signature directly on a key
* This signature is calculated directly on a key. It binds the
* information in the Signature subpackets to the key, and is
* appropriate to be used for subpackets that provide information
* about the key, such as the Revocation Key subpacket. It is also
* appropriate for statements that non-self certifiers want to make
* about the key itself, rather than the binding between a key and a
* name. */
key: 31,
/** 0x20: Key revocation signature
* The signature is calculated directly on the key being revoked. A
* revoked key is not to be used. Only revocation signatures by the
* key being revoked, or by an authorized revocation key, should be
* considered valid revocation signatures.a */
key_revocation: 32,
/** 0x28: Subkey revocation signature
* The signature is calculated directly on the subkey being revoked.
* A revoked subkey is not to be used. Only revocation signatures
* by the top-level signature key that is bound to this subkey, or
* by an authorized revocation key, should be considered valid
* revocation signatures.
* Key revocation signatures (types 0x20 and 0x28)
* hash only the key being revoked. */
subkey_revocation: 40,
/** 0x40: Timestamp signature.
* This signature is only meaningful for the timestamp contained in
* it. */
timestamp: 64,
/** 0x50: Third-Party Confirmation signature.
* This signature is a signature over some other OpenPGP Signature
* packet(s). It is analogous to a notary seal on the signed data.
* A third-party signature SHOULD include Signature Target
* subpacket(s) to give easy identification. Note that we really do
* mean SHOULD. There are plausible uses for this (such as a blind
* party that only sees the signature, not the key or source
* document) that cannot include a target subpacket. */
third_party: 80
},
// Asserts validity and converts from string/integer to integer.
write: function(type, e) {
if(typeof e == 'number') {
e = this.read(type, e);
}
if(type[e] != undefined) {
return type[e];
} else throw new Error('Invalid enum value.');
},
// Converts from an integer to string.
read: function(type, e) {
for(var i in type)
if(type[i] == e) return i;
throw new Error('Invalid enum value.');
}
}
},{}],28:[function(require,module,exports){
var crypto = require('./crypto');
module.exports = require('./openpgp.js');
module.exports.util = require('./util');
module.exports.packet = require('./packet');
module.exports.mpi = require('./type/mpi.js');
module.exports.s2k = require('./type/s2k.js');
module.exports.keyid = require('./type/keyid.js');
module.exports.armor = require('./encoding/armor.js');
for(var i in crypto)
module.exports[i] = crypto[i];
},{"./crypto":14,"./encoding/armor.js":25,"./openpgp.js":29,"./packet":32,"./type/keyid.js":49,"./type/mpi.js":50,"./type/s2k.js":51,"./util":52}],29:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* @fileoverview The openpgp base class should provide all of the functionality
* to consume the openpgp.js library. All additional classes are documented
* for extending and developing on top of the base library.
*/
/**
* GPG4Browsers Core interface. A single instance is hold
* from the beginning. To use this library call "openpgp.init()"
* @alias openpgp
* @class
* @classdesc Main Openpgp.js class. Use this to initiate and make all calls to this library.
*/
function _openpgp () {
this.tostring = "";
/**
* initializes the library:
* - reading the keyring from local storage
* - reading the config from local storage
*/
function init() {
this.config = new openpgp_config();
this.config.read();
this.keyring = new openpgp_keyring();
this.keyring.init();
}
/**
* reads several publicKey objects from a ascii armored
* representation an returns openpgp_msg_publickey packets
* @param {String} armoredText OpenPGP armored text containing
* the public key(s)
* @return {openpgp_msg_publickey[]} on error the function
* returns null
*/
function read_publicKey(armoredText) {
var mypos = 0;
var publicKeys = new Array();
var publicKeyCount = 0;
var input = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')).openpgp;
var l = input.length;
while (mypos != input.length) {
var first_packet = openpgp_packet.read_packet(input, mypos, l);
// public key parser
if (input[mypos].charCodeAt() == 0x99 || first_packet.tagType == 6) {
publicKeys[publicKeyCount] = new openpgp_msg_publickey();
publicKeys[publicKeyCount].header = input.substring(mypos,mypos+3);
if (input[mypos].charCodeAt() == 0x99) {
// parse the length and read a tag6 packet
mypos++;
var l = (input[mypos++].charCodeAt() << 8)
| input[mypos++].charCodeAt();
publicKeys[publicKeyCount].publicKeyPacket = new openpgp_packet_keymaterial();
publicKeys[publicKeyCount].publicKeyPacket.header = publicKeys[publicKeyCount].header;
publicKeys[publicKeyCount].publicKeyPacket.read_tag6(input, mypos, l);
mypos += publicKeys[publicKeyCount].publicKeyPacket.packetLength;
mypos += publicKeys[publicKeyCount].read_nodes(publicKeys[publicKeyCount].publicKeyPacket, input, mypos, (input.length - mypos));
} else {
publicKeys[publicKeyCount] = new openpgp_msg_publickey();
publicKeys[publicKeyCount].publicKeyPacket = first_packet;
mypos += first_packet.headerLength+first_packet.packetLength;
mypos += publicKeys[publicKeyCount].read_nodes(first_packet, input, mypos, input.length -mypos);
}
} else {
util.print_error("no public key found!");
return null;
}
publicKeys[publicKeyCount].data = input.substring(0,mypos);
publicKeyCount++;
}
return publicKeys;
}
/**
* reads several privateKey objects from a ascii armored
* representation an returns openpgp_msg_privatekey objects
* @param {String} armoredText OpenPGP armored text containing
* the private key(s)
* @return {openpgp_msg_privatekey[]} on error the function
* returns null
*/
function read_privateKey(armoredText) {
var privateKeys = new Array();
var privateKeyCount = 0;
var mypos = 0;
var input = openpgp_encoding_deArmor(armoredText.replace(/\r/g,'')).openpgp;
var l = input.length;
while (mypos != input.length) {
var first_packet = openpgp_packet.read_packet(input, mypos, l);
if (first_packet.tagType == 5) {
privateKeys[privateKeys.length] = new openpgp_msg_privatekey();
mypos += first_packet.headerLength+first_packet.packetLength;
mypos += privateKeys[privateKeyCount].read_nodes(first_packet, input, mypos, l);
// other blocks
} else {
util.print_error('no block packet found!');
return null;
}
privateKeys[privateKeyCount].data = input.substring(0,mypos);
privateKeyCount++;
}
return privateKeys;
}
/**
* reads message packets out of an OpenPGP armored text and
* returns an array of message objects
* @param {String} armoredText text to be parsed
* @return {openpgp_msg_message[]} on error the function
* returns null
*/
function read_message(armoredText) {
var dearmored;
try{
dearmored = openpgp_encoding_deArmor(armoredText.replace(/\r/g,''));
}
catch(e){
util.print_error('no message found!');
return null;
}
return read_messages_dearmored(dearmored);
}
/**
* reads message packets out of an OpenPGP armored text and
* returns an array of message objects. Can be called externally or internally.
* External call will parse a de-armored messaged and return messages found.
* Internal will be called to read packets wrapped in other packets (i.e. compressed)
* @param {String} input dearmored text of OpenPGP packets, to be parsed
* @return {openpgp_msg_message[]} on error the function
* returns null
*/
function read_messages_dearmored(input){
var messageString = input.openpgp;
var signatureText = input.text; //text to verify signatures against. Modified by Tag11.
var messages = new Array();
var messageCount = 0;
var mypos = 0;
var l = messageString.length;
while (mypos < messageString.length) {
var first_packet = openpgp_packet.read_packet(messageString, mypos, l);
if (!first_packet) {
break;
}
// public key parser (definition from the standard:)
// OpenPGP Message :- Encrypted Message | Signed Message |
// Compressed Message | Literal Message.
// Compressed Message :- Compressed Data Packet.
//
// Literal Message :- Literal Data Packet.
//
// ESK :- Public-Key Encrypted Session Key Packet |
// Symmetric-Key Encrypted Session Key Packet.
//
// ESK Sequence :- ESK | ESK Sequence, ESK.
//
// Encrypted Data :- Symmetrically Encrypted Data Packet |
// Symmetrically Encrypted Integrity Protected Data Packet
//
// Encrypted Message :- Encrypted Data | ESK Sequence, Encrypted Data.
//
// One-Pass Signed Message :- One-Pass Signature Packet,
// OpenPGP Message, Corresponding Signature Packet.
// Signed Message :- Signature Packet, OpenPGP Message |
// One-Pass Signed Message.
if (first_packet.tagType == 1 ||
(first_packet.tagType == 2 && first_packet.signatureType < 16) ||
first_packet.tagType == 3 ||
first_packet.tagType == 4 ||
first_packet.tagType == 8 ||
first_packet.tagType == 9 ||
first_packet.tagType == 10 ||
first_packet.tagType == 11 ||
first_packet.tagType == 18 ||
first_packet.tagType == 19) {
messages[messages.length] = new openpgp_msg_message();
messages[messageCount].messagePacket = first_packet;
messages[messageCount].type = input.type;
// Encrypted Message
if (first_packet.tagType == 9 ||
first_packet.tagType == 1 ||
first_packet.tagType == 3 ||
first_packet.tagType == 18) {
if (first_packet.tagType == 9) {
util.print_error("unexpected openpgp packet");
break;
} else if (first_packet.tagType == 1) {
util.print_debug("session key found:\n "+first_packet.toString());
var issessionkey = true;
messages[messageCount].sessionKeys = new Array();
var sessionKeyCount = 0;
while (issessionkey) {
messages[messageCount].sessionKeys[sessionKeyCount] = first_packet;
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
first_packet = openpgp_packet.read_packet(messageString, mypos, l);
if (first_packet.tagType != 1 && first_packet.tagType != 3)
issessionkey = false;
sessionKeyCount++;
}
if (first_packet.tagType == 18 || first_packet.tagType == 9) {
util.print_debug("encrypted data found:\n "+first_packet.toString());
messages[messageCount].encryptedData = first_packet;
mypos += first_packet.packetLength+first_packet.headerLength;
l -= (first_packet.packetLength+first_packet.headerLength);
messageCount++;
} else {
util.print_debug("something is wrong: "+first_packet.tagType);
}
} else if (first_packet.tagType == 18) {
util.print_debug("symmetric encrypted data");
break;
}
} else
if (first_packet.tagType == 2 && first_packet.signatureType < 3) {
// Signed Message
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
messages[messageCount].text = signatureText;
messages[messageCount].signature = first_packet;
messageCount++;
} else
// Signed Message
if (first_packet.tagType == 4) {
//TODO: Implement check
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
} else
if (first_packet.tagType == 8) {
// Compressed Message
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
var decompressedText = first_packet.decompress();
messages = messages.concat(openpgp.read_messages_dearmored({text: decompressedText, openpgp: decompressedText}));
} else
// Marker Packet (Obsolete Literal Packet) (Tag 10)
// "Such a packet MUST be ignored when received." see http://tools.ietf.org/html/rfc4880#section-5.8
if (first_packet.tagType == 10) {
// reset messages
messages.length = 0;
// continue with next packet
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
} else
if (first_packet.tagType == 11) {
// Literal Message -- work is already done in read_packet
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
signatureText = first_packet.data;
messages[messageCount].data = first_packet.data;
messageCount++;
} else
if (first_packet.tagType == 19) {
// Modification Detect Code
mypos += first_packet.packetLength + first_packet.headerLength;
l -= (first_packet.packetLength + first_packet.headerLength);
}
} else {
util.print_error('no message found!');
return null;
}
}
return messages;
}
/**
* creates a binary string representation of an encrypted and signed message.
* The message will be encrypted with the public keys specified and signed
* with the specified private key.
* @param {Object} privatekey {obj: [openpgp_msg_privatekey]} Private key
* to be used to sign the message
* @param {Object[]} publickeys An arraf of {obj: [openpgp_msg_publickey]}
* - public keys to be used to encrypt the message
* @param {String} messagetext message text to encrypt and sign
* @return {String} a binary string representation of the message which
* can be OpenPGP armored
*/
function write_signed_and_encrypted_message(privatekey, publickeys, messagetext) {
var result = "";
var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));
util.print_debug_hexstr_dump("literal_packet: |"+literal+"|\n",literal);
for (var i = 0; i < publickeys.length; i++) {
var onepasssignature = new openpgp_packet_onepasssignature();
var onepasssigstr = "";
if (i == 0)
onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm, privatekey, false);
else
onepasssigstr = onepasssignature.write_packet(1, openpgp.config.config.prefer_hash_algorithm, privatekey, false);
util.print_debug_hexstr_dump("onepasssigstr: |"+onepasssigstr+"|\n",onepasssigstr);
var datasignature = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"), privatekey);
util.print_debug_hexstr_dump("datasignature: |"+datasignature.openpgp+"|\n",datasignature.openpgp);
if (i == 0) {
result = onepasssigstr+literal+datasignature.openpgp;
} else {
result = onepasssigstr+result+datasignature.openpgp;
}
}
util.print_debug_hexstr_dump("signed packet: |"+result+"|\n",result);
// signatures done.. now encryption
var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher);
var result2 = "";
// creating session keys for each recipient
for (var i = 0; i < publickeys.length; i++) {
var pkey = publickeys[i].getEncryptionKey();
if (pkey == null) {
util.print_error("no encryption key found! Key is for signing only.");
return null;
}
result2 += new openpgp_packet_encryptedsessionkey().
write_pub_key_packet(
pkey.getKeyId(),
pkey.MPIs,
pkey.publicKeyAlgorithm,
openpgp.config.config.encryption_cipher,
sessionkey);
}
if (openpgp.config.config.integrity_protect) {
result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
} else {
result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
}
return openpgp_encoding_armor(3,result2,null,null);
}
/**
* creates a binary string representation of an encrypted message.
* The message will be encrypted with the public keys specified
* @param {Object[]} publickeys An array of {obj: [openpgp_msg_publickey]}
* -public keys to be used to encrypt the message
* @param {String} messagetext message text to encrypt
* @return {String} a binary string representation of the message
* which can be OpenPGP armored
*/
function write_encrypted_message(publickeys, messagetext) {
var result = "";
var literal = new openpgp_packet_literaldata().write_packet(messagetext.replace(/\r\n/g,"\n").replace(/\n/g,"\r\n"));
util.print_debug_hexstr_dump("literal_packet: |"+literal+"|\n",literal);
result = literal;
// signatures done.. now encryption
var sessionkey = openpgp_crypto_generateSessionKey(openpgp.config.config.encryption_cipher);
var result2 = "";
// creating session keys for each recipient
for (var i = 0; i < publickeys.length; i++) {
var pkey = publickeys[i].getEncryptionKey();
if (pkey == null) {
util.print_error("no encryption key found! Key is for signing only.");
return null;
}
result2 += new openpgp_packet_encryptedsessionkey().
write_pub_key_packet(
pkey.getKeyId(),
pkey.MPIs,
pkey.publicKeyAlgorithm,
openpgp.config.config.encryption_cipher,
sessionkey);
}
if (openpgp.config.config.integrity_protect) {
result2 += new openpgp_packet_encryptedintegrityprotecteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
} else {
result2 += new openpgp_packet_encrypteddata().write_packet(openpgp.config.config.encryption_cipher, sessionkey, result);
}
return openpgp_encoding_armor(3,result2,null,null);
}
/**
* creates a binary string representation a signed message.
* The message will be signed with the specified private key.
* @param {Object} privatekey {obj: [openpgp_msg_privatekey]}
* - the private key to be used to sign the message
* @param {String} messagetext message text to sign
* @return {Object} {Object: text [String]}, openpgp: {String} a binary
* string representation of the message which can be OpenPGP
* armored(openpgp) and a text representation of the message (text).
* This can be directly used to OpenPGP armor the message
*/
function write_signed_message(privatekey, messagetext) {
var sig = new openpgp_packet_signature().write_message_signature(1, messagetext.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"), privatekey);
var result = {text: messagetext.replace(/\r\n/g,"\n").replace(/\n/,"\r\n"), openpgp: sig.openpgp, hash: sig.hash};
return openpgp_encoding_armor(2,result, null, null)
}
/**
* generates a new key pair for openpgp. Beta stage. Currently only
* supports RSA keys, and no subkeys.
* @param {Integer} keyType to indicate what type of key to make.
* RSA is 1. Follows algorithms outlined in OpenPGP.
* @param {Integer} numBits number of bits for the key creation. (should
* be 1024+, generally)
* @param {String} userId assumes already in form of "User Name
* <username@email.com>"
* @param {String} passphrase The passphrase used to encrypt the resulting private key
* @return {Object} {privateKey: [openpgp_msg_privatekey],
* privateKeyArmored: [string], publicKeyArmored: [string]}
*/
function generate_key_pair(keyType, numBits, userId, passphrase){
var userIdPacket = new openpgp_packet_userid();
var userIdString = userIdPacket.write_packet(userId);
var keyPair = openpgp_crypto_generateKeyPair(keyType,numBits, passphrase, openpgp.config.config.prefer_hash_algorithm, 3);
var privKeyString = keyPair.privateKey;
var privKeyPacket = new openpgp_packet_keymaterial().read_priv_key(privKeyString.string,3,privKeyString.string.length);
if(!privKeyPacket.decryptSecretMPIs(passphrase))
util.print_error('Issue creating key. Unable to read resulting private key');
var privKey = new openpgp_msg_privatekey();
privKey.privateKeyPacket = privKeyPacket;
privKey.getPreferredSignatureHashAlgorithm = function(){return openpgp.config.config.prefer_hash_algorithm};//need to override this to solve catch 22 to generate signature. 8 is value for SHA256
var publicKeyString = privKey.privateKeyPacket.publicKey.data;
var hashData = String.fromCharCode(0x99)+ String.fromCharCode(((publicKeyString.length) >> 8) & 0xFF)
+ String.fromCharCode((publicKeyString.length) & 0xFF) +publicKeyString+String.fromCharCode(0xB4) +
String.fromCharCode((userId.length) >> 24) +String.fromCharCode(((userId.length) >> 16) & 0xFF)
+ String.fromCharCode(((userId.length) >> 8) & 0xFF) + String.fromCharCode((userId.length) & 0xFF) + userId
var signature = new openpgp_packet_signature();
signature = signature.write_message_signature(16,hashData, privKey);
var publicArmored = openpgp_encoding_armor(4, keyPair.publicKey.string + userIdString + signature.openpgp );
var privArmored = openpgp_encoding_armor(5,privKeyString.string+userIdString+signature.openpgp);
return {privateKey : privKey, privateKeyArmored: privArmored, publicKeyArmored: publicArmored}
}
this.generate_key_pair = generate_key_pair;
this.write_signed_message = write_signed_message;
this.write_signed_and_encrypted_message = write_signed_and_encrypted_message;
this.write_encrypted_message = write_encrypted_message;
this.read_message = read_message;
this.read_messages_dearmored = read_messages_dearmored;
this.read_publicKey = read_publicKey;
this.read_privateKey = read_privateKey;
this.init = init;
}
module.exports = new _openpgp();
},{}],30:[function(require,module,exports){
var enums = require('../enums.js');
// This is pretty ugly, but browserify needs to have the requires explicitly written.
module.exports = {
compressed: require('./compressed.js'),
sym_encrypted_integrity_protected: require('./sym_encrypted_integrity_protected.js'),
public_key_encrypted_session_key: require('./public_key_encrypted_session_key.js'),
sym_encrypted_session_key: require('./sym_encrypted_session_key.js'),
literal: require('./literal.js'),
public_key: require('./public_key.js'),
symmetrically_encrypted: require('./symmetrically_encrypted.js'),
marker: require('./marker.js'),
public_subkey: require('./public_subkey.js'),
user_attribute: require('./user_attribute.js'),
one_pass_signature: require('./one_pass_signature.js'),
secret_key: require('./secret_key.js'),
userid: require('./userid.js'),
secret_subkey: require('./secret_subkey.js'),
signature: require('./signature.js'),
trust: require('./trust.js')
}
for(var i in enums.packet) {
var packetClass = module.exports[i];
if(packetClass != undefined)
packetClass.prototype.tag = enums.packet[i];
}
},{"../enums.js":27,"./compressed.js":31,"./literal.js":33,"./marker.js":34,"./one_pass_signature.js":17,"./public_key.js":37,"./public_key_encrypted_session_key.js":38,"./public_subkey.js":39,"./secret_key.js":40,"./secret_subkey.js":41,"./signature.js":42,"./sym_encrypted_integrity_protected.js":43,"./sym_encrypted_session_key.js":44,"./symmetrically_encrypted.js":45,"./trust.js":46,"./user_attribute.js":47,"./userid.js":48}],31:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var enums = require('../enums.js'),
JXG = require('../compression/jxg.js'),
base64 = require('../encoding/base64.js');
/**
* @class
* @classdesc Implementation of the Compressed Data Packet (Tag 8)
*
* RFC4880 5.6:
* The Compressed Data packet contains compressed data. Typically, this
* packet is found as the contents of an encrypted packet, or following
* a Signature or One-Pass Signature packet, and contains a literal data
* packet.
*/
module.exports = function packet_compressed() {
/** @type {packetlist} */
this.packets;
/** @type {compression} */
this.algorithm = 'uncompressed';
this.compressed = null;
/**
* Parsing function for the packet.
* @param {String} input Payload of a tag 8 packet
* @param {Integer} position Position to start reading from the input string
* @parAM {iNTEGER} LEN lENGTH OF the packet or the remaining length of
* input at position
* @return {openpgp_packet_compressed} Object representation
*/
this.read = function(bytes) {
// One octet that gives the algorithm used to compress the packet.
this.algorithm = enums.read(enums.compression, bytes.charCodeAt(0));
// Compressed data, which makes up the remainder of the packet.
this.compressed = bytes.substr(1);
this.decompress();
}
this.write = function() {
if(this.compressed == null)
this.compress();
return String.fromCharCode(enums.write(enums.compression, this.algorithm))
+ this.compressed;
}
/**
* Decompression method for decompressing the compressed data
* read by read_packet
* @return {String} The decompressed data
*/
this.decompress = function() {
var decompressed;
switch (this.algorithm) {
case 'uncompressed':
decompressed = this.compressed;
break;
case 'zip':
var compData = this.compressed;
var radix = base64.encode(compData).replace(/\n/g,"");
// no header in this case, directly call deflate
var jxg_obj = new JXG.Util.Unzip(JXG.Util.Base64.decodeAsArray(radix));
decompressed = unescape(jxg_obj.deflate()[0][0]);
break;
case 'zlib':
//RFC 1950. Bits 0-3 Compression Method
var compressionMethod = this.compressed.charCodeAt(0) % 0x10;
//Bits 4-7 RFC 1950 are LZ77 Window. Generally this value is 7 == 32k window size.
// 2nd Byte in RFC 1950 is for "FLAGs" Allows for a Dictionary
// (how is this defined). Basic checksum, and compression level.
if (compressionMethod == 8) { //CM 8 is for DEFLATE, RFC 1951
// remove 4 bytes ADLER32 checksum from the end
var compData = this.compressed.substring(0, this.compressed.length - 4);
var radix = base64.encode(compData).replace(/\n/g,"");
//TODO check ADLER32 checksum
decompressed = JXG.decompress(radix);
break;
} else {
util.print_error("Compression algorithm ZLIB only supports " +
"DEFLATE compression method.");
}
break;
case 'bzip2':
// TODO: need to implement this
throw new Error('Compression algorithm BZip2 [BZ2] is not implemented.');
break;
default:
throw new Error("Compression algorithm unknown :" + this.alogrithm);
break;
}
this.packets.read(decompressed);
}
/**
* Compress the packet data (member decompressedData)
* @param {Integer} type Algorithm to be used // See RFC 4880 9.3
* @param {String} data Data to be compressed
* @return {String} The compressed data stored in attribute compressedData
*/
this.compress = function() {
switch (this.algorithm) {
case 'uncompressed': // - Uncompressed
this.compressed = this.packets.write();
break;
case 'zip': // - ZIP [RFC1951]
util.print_error("Compression algorithm ZIP [RFC1951] is not implemented.");
break;
case 'zlib': // - ZLIB [RFC1950]
// TODO: need to implement this
util.print_error("Compression algorithm ZLIB [RFC1950] is not implemented.");
break;
case 'bzip2': // - BZip2 [BZ2]
// TODO: need to implement this
util.print_error("Compression algorithm BZip2 [BZ2] is not implemented.");
break;
default:
util.print_error("Compression algorithm unknown :"+this.type);
break;
}
}
};
},{"../compression/jxg.js":1,"../encoding/base64.js":26,"../enums.js":27}],32:[function(require,module,exports){
var enums = require('../enums.js');
module.exports = {
list: require('./packetlist.js'),
}
var packets = require('./all_packets.js');
for(var i in packets)
module.exports[i] = packets[i];
},{"../enums.js":27,"./all_packets.js":30,"./packetlist.js":36}],33:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var util = require('../util'),
enums = require('../enums.js');
/**
* @class
* @classdesc Implementation of the Literal Data Packet (Tag 11)
*
* RFC4880 5.9: A Literal Data packet contains the body of a message; data that
* is not to be further interpreted.
*/
module.exports = function packet_literal() {
this.format = 'utf8';
this.data = '';
this.date = new Date();
/**
* Set the packet data to a javascript native string or a squence of
* bytes. Conversion to a proper utf8 encoding takes place when the
* packet is written.
* @param {String} str Any native javascript string
* @param {openpgp_packet_literaldata.format} format
*/
this.set = function(str, format) {
this.format = format;
this.data = str;
}
/**
* Set the packet data to value represented by the provided string
* of bytes together with the appropriate conversion format.
* @param {String} bytes The string of bytes
* @param {openpgp_packet_literaldata.format} format
*/
this.setBytes = function(bytes, format) {
this.format = format;
if(format == 'utf8')
bytes = util.decode_utf8(bytes);
this.data = bytes;
}
/**
* Get the byte sequence representing the literal packet data
* @returns {String} A sequence of bytes
*/
this.getBytes = function() {
if(this.format == 'utf8')
return util.encode_utf8(this.data);
else
return this.data;
}
/**
* Parsing function for a literal data packet (tag 11).
*
* @param {String} input Payload of a tag 11 packet
* @param {Integer} position
* Position to start reading from the input string
* @param {Integer} len
* Length of the packet or the remaining length of
* input at position
* @return {openpgp_packet_encrypteddata} object representation
*/
this.read = function(bytes) {
// - A one-octet field that describes how the data is formatted.
var format = enums.read(enums.literal, bytes[0].charCodeAt());
var filename_len = bytes.charCodeAt(1);
this.filename = util.decode_utf8(bytes.substr(2, filename_len));
this.date = util.readDate(bytes.substr(2
+ filename_len, 4));
var data = bytes.substring(6 + filename_len);
this.setBytes(data, format);
}
/**
* Creates a string representation of the packet
*
* @param {String} data The data to be inserted as body
* @return {String} string-representation of the packet
*/
this.write = function() {
var filename = util.encode_utf8("msg.txt");
var data = this.getBytes();
var result = '';
result += String.fromCharCode(enums.write(enums.literal, this.format));
result += String.fromCharCode(filename.length);
result += filename;
result += util.writeDate(this.date);
result += data;
return result;
}
}
},{"../enums.js":27,"../util":52}],34:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* @class
* @classdesc Implementation of the strange "Marker packet" (Tag 10)
*
* RFC4880 5.8: An experimental version of PGP used this packet as the Literal
* packet, but no released version of PGP generated Literal packets with this
* tag. With PGP 5.x, this packet has been reassigned and is reserved for use as
* the Marker packet.
*
* Such a packet MUST be ignored when received.
*/
function packet_marker() {
/**
* Parsing function for a literal data packet (tag 10).
*
* @param {String} input Payload of a tag 10 packet
* @param {Integer} position
* Position to start reading from the input string
* @param {Integer} len
* Length of the packet or the remaining length of
* input at position
* @return {openpgp_packet_encrypteddata} Object representation
*/
this.read = function(bytes) {
if (bytes[0].charCodeAt() == 0x50 && // P
bytes[1].charCodeAt() == 0x47 && // G
bytes[2].charCodeAt() == 0x50) // P
return true;
// marker packet does not contain "PGP"
return false;
}
}
module.exports = packet_marker;
},{}],35:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var enums = require('../enums.js'),
util = require('../util');
module.exports = {
readSimpleLength: function(bytes) {
var len = 0,
offset,
type = bytes[0].charCodeAt();
if (type < 192) {
len = bytes[0].charCodeAt();
offset = 1;
} else if (type < 255) {
len = ((bytes[0].charCodeAt() - 192) << 8) + (bytes[1].charCodeAt()) + 192;
offset = 2;
} else if (type == 255) {
len = util.readNumber(bytes.substr(1, 4));
offset = 5;
}
return { len: len, offset: offset };
},
/**
* Encodes a given integer of length to the openpgp length specifier to a
* string
*
* @param {Integer} length The length to encode
* @return {String} String with openpgp length representation
*/
writeSimpleLength: function(length) {
var result = "";
if (length < 192) {
result += String.fromCharCode(length);
} else if (length > 191 && length < 8384) {
/*
* let a = (total data packet length) - 192 let bc = two octet
* representation of a let d = b + 192
*/
result += String.fromCharCode(((length - 192) >> 8) + 192);
result += String.fromCharCode((length - 192) & 0xFF);
} else {
result += String.fromCharCode(255);
result += util.writeNumber(length, 4);
}
return result;
},
/**
* Writes a packet header version 4 with the given tag_type and length to a
* string
*
* @param {Integer} tag_type Tag type
* @param {Integer} length Length of the payload
* @return {String} String of the header
*/
writeHeader: function(tag_type, length) {
/* we're only generating v4 packet headers here */
var result = "";
result += String.fromCharCode(0xC0 | tag_type);
result += this.writeSimpleLength(length);
return result;
},
/**
* Writes a packet header Version 3 with the given tag_type and length to a
* string
*
* @param {Integer} tag_type Tag type
* @param {Integer} length Length of the payload
* @return {String} String of the header
*/
writeOldHeader: function(tag_type, length) {
var result = "";
if (length < 256) {
result += String.fromCharCode(0x80 | (tag_type << 2));
result += String.fromCharCode(length);
} else if (length < 65536) {
result += String.fromCharCode(0x80 | (tag_type << 2) | 1);
result += util.writeNumber(length, 2);
} else {
result += String.fromCharCode(0x80 | (tag_type << 2) | 2);
result += util.writeNumber(length, 4);
}
return result;
},
/**
* Generic static Packet Parser function
*
* @param {String} input Input stream as string
* @param {integer} position Position to start parsing
* @param {integer} len Length of the input from position on
* @return {Object} Returns a parsed openpgp_packet
*/
read: function(input, position, len) {
// some sanity checks
if (input == null || input.length <= position
|| input.substring(position).length < 2
|| (input[position].charCodeAt() & 0x80) == 0) {
util
.print_error("Error during parsing. This message / key is probably not containing a valid OpenPGP format.");
return null;
}
var mypos = position;
var tag = -1;
var format = -1;
var packet_length;
format = 0; // 0 = old format; 1 = new format
if ((input[mypos].charCodeAt() & 0x40) != 0) {
format = 1;
}
var packet_length_type;
if (format) {
// new format header
tag = input[mypos].charCodeAt() & 0x3F; // bit 5-0
} else {
// old format header
tag = (input[mypos].charCodeAt() & 0x3F) >> 2; // bit 5-2
packet_length_type = input[mypos].charCodeAt() & 0x03; // bit 1-0
}
// header octet parsing done
mypos++;
// parsed length from length field
var bodydata = null;
// used for partial body lengths
var real_packet_length = -1;
if (!format) {
// 4.2.1. Old Format Packet Lengths
switch (packet_length_type) {
case 0: // The packet has a one-octet length. The header is 2 octets
// long.
packet_length = input[mypos++].charCodeAt();
break;
case 1: // The packet has a two-octet length. The header is 3 octets
// long.
packet_length = (input[mypos++].charCodeAt() << 8)
| input[mypos++].charCodeAt();
break;
case 2: // The packet has a four-octet length. The header is 5
// octets long.
packet_length = (input[mypos++].charCodeAt() << 24)
| (input[mypos++].charCodeAt() << 16)
| (input[mypos++].charCodeAt() << 8)
| input[mypos++].charCodeAt();
break;
default:
// 3 - The packet is of indeterminate length. The header is 1
// octet long, and the implementation must determine how long
// the packet is. If the packet is in a file, this means that
// the packet extends until the end of the file. In general,
// an implementation SHOULD NOT use indeterminate-length
// packets except where the end of the data will be clear
// from the context, and even then it is better to use a
// definite length, or a new format header. The new format
// headers described below have a mechanism for precisely
// encoding data of indeterminate length.
packet_length = len;
break;
}
} else // 4.2.2. New Format Packet Lengths
{
// 4.2.2.1. One-Octet Lengths
if (input[mypos].charCodeAt() < 192) {
packet_length = input[mypos++].charCodeAt();
util.print_debug("1 byte length:" + packet_length);
// 4.2.2.2. Two-Octet Lengths
} else if (input[mypos].charCodeAt() >= 192
&& input[mypos].charCodeAt() < 224) {
packet_length = ((input[mypos++].charCodeAt() - 192) << 8)
+ (input[mypos++].charCodeAt()) + 192;
util.print_debug("2 byte length:" + packet_length);
// 4.2.2.4. Partial Body Lengths
} else if (input[mypos].charCodeAt() > 223
&& input[mypos].charCodeAt() < 255) {
packet_length = 1 << (input[mypos++].charCodeAt() & 0x1F);
util.print_debug("4 byte length:" + packet_length);
// EEEK, we're reading the full data here...
var mypos2 = mypos + packet_length;
bodydata = input.substring(mypos, mypos + packet_length);
while (true) {
if (input[mypos2].charCodeAt() < 192) {
var tmplen = input[mypos2++].charCodeAt();
packet_length += tmplen;
bodydata += input.substring(mypos2, mypos2 + tmplen);
mypos2 += tmplen;
break;
} else if (input[mypos2].charCodeAt() >= 192
&& input[mypos2].charCodeAt() < 224) {
var tmplen = ((input[mypos2++].charCodeAt() - 192) << 8)
+ (input[mypos2++].charCodeAt()) + 192;
packet_length += tmplen;
bodydata += input.substring(mypos2, mypos2 + tmplen);
mypos2 += tmplen;
break;
} else if (input[mypos2].charCodeAt() > 223
&& input[mypos2].charCodeAt() < 255) {
var tmplen = 1 << (input[mypos2++].charCodeAt() & 0x1F);
packet_length += tmplen;
bodydata += input.substring(mypos2, mypos2 + tmplen);
mypos2 += tmplen;
} else {
mypos2++;
var tmplen = (input[mypos2++].charCodeAt() << 24)
| (input[mypos2++].charCodeAt() << 16)
| (input[mypos2++].charCodeAt() << 8)
| input[mypos2++].charCodeAt();
bodydata += input.substring(mypos2, mypos2 + tmplen);
packet_length += tmplen;
mypos2 += tmplen;
break;
}
}
real_packet_length = mypos2;
// 4.2.2.3. Five-Octet Lengths
} else {
mypos++;
packet_length = (input[mypos++].charCodeAt() << 24)
| (input[mypos++].charCodeAt() << 16)
| (input[mypos++].charCodeAt() << 8)
| input[mypos++].charCodeAt();
}
}
// if there was'nt a partial body length: use the specified
// packet_length
if (real_packet_length == -1) {
real_packet_length = packet_length;
}
if (bodydata == null) {
bodydata = input.substring(mypos, mypos + real_packet_length);
}
return {
tag: tag,
packet: bodydata,
offset: mypos + real_packet_length
};
}
}
},{"../enums.js":27,"../util":52}],36:[function(require,module,exports){
var packetParser = require('./packet.js'),
packets = require('./all_packets.js'),
enums = require('../enums.js');
/**
* @class
* @classdesc This class represents a list of openpgp packets.
* Take care when iterating over it - the packets themselves
* are stored as numerical indices.
*/
module.exports = function packetlist() {
/** The number of packets contained within the list.
* @readonly
* @type {Integer} */
this.length = 0;
/**
* Reads a stream of binary data and interprents it as a list of packets.
* @param {openpgp_bytearray} An array of bytes.
*/
this.read = function(bytes) {
var i = 0;
while(i < bytes.length) {
var parsed = packetParser.read(bytes, i, bytes.length - i);
i = parsed.offset;
var tag = enums.read(enums.packet, parsed.tag);
var packet = new packets[tag]();
this.push(packet);
packet.read(parsed.packet);
}
}
/**
* Creates a binary representation of openpgp objects contained within the
* class instance.
* @returns {openpgp_bytearray} An array of bytes containing valid openpgp packets.
*/
this.write = function() {
var bytes = '';
for(var i = 0; i < this.length; i++) {
var packetbytes = this[i].write();
bytes += packetParser.writeHeader(this[i].tag, packetbytes.length);
bytes += packetbytes;
}
return bytes;
}
/**
* Adds a packet to the list. This is the only supported method of doing so;
* writing to packetlist[i] directly will result in an error.
*/
this.push = function(packet) {
packet.packets = new packetlist();
this[this.length] = packet;
this.length++;
}
}
},{"../enums.js":27,"./all_packets.js":30,"./packet.js":35}],37:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var util = require('../util'),
type_mpi = require('../type/mpi.js'),
enums = require('../enums.js'),
crypto = require('../crypto');
/**
* @class
* @classdesc Implementation of the Key Material Packet (Tag 5,6,7,14)
*
* RFC4480 5.5:
* A key material packet contains all the information about a public or
* private key. There are four variants of this packet type, and two
* major versions. Consequently, this section is complex.
*/
module.exports = function packet_public_key() {
/** Key creation date.
* @type {Date} */
this.created = new Date();
/** A list of multiprecision integers
* @type {openpgp_type_mpi} */
this.mpi = [];
/** Public key algorithm
* @type {openpgp.publickey} */
this.algorithm = 'rsa_sign';
/**
* Internal Parser for public keys as specified in RFC 4880 section
* 5.5.2 Public-Key Packet Formats
* called by read_tag&lt;num&gt;
* @param {String} input Input string to read the packet from
* @param {Integer} position Start position for the parser
* @param {Integer} len Length of the packet or remaining length of input
* @return {Object} This object with attributes set by the parser
*/
this.readPublicKey = this.read = function(bytes) {
// A one-octet version number (3 or 4).
var version = bytes[0].charCodeAt();
if (version == 4) {
// - A four-octet number denoting the time that the key was created.
this.created = util.readDate(bytes.substr(1, 4));
// - A one-octet number denoting the public-key algorithm of this key.
this.algorithm = enums.read(enums.publicKey, bytes[5].charCodeAt());
var mpicount = crypto.getPublicMpiCount(this.algorithm);
this.mpi = [];
var bmpi = bytes.substr(6);
var p = 0;
for (var i = 0;
i < mpicount && p < bmpi.length;
i++) {
this.mpi[i] = new type_mpi();
p += this.mpi[i].read(bmpi.substr(p))
if(p > bmpi.length)
util.print_error("openpgp.packet.keymaterial.js\n"
+'error reading MPI @:'+p);
}
return p + 6;
} else {
throw new Error('Version ' + version + ' of the key packet is unsupported.');
}
}
/*
* Same as write_private_key, but has less information because of
* public key.
* @param {Integer} keyType Follows the OpenPGP algorithm standard,
* IE 1 corresponds to RSA.
* @param {RSA.keyObject} key
* @param timePacket
* @return {Object} {body: [string]OpenPGP packet body contents,
* header: [string] OpenPGP packet header, string: [string] header+body}
*/
this.writePublicKey = this.write = function() {
// Version
var result = String.fromCharCode(4);
result += util.writeDate(this.created);
result += String.fromCharCode(enums.write(enums.publicKey, this.algorithm));
var mpicount = crypto.getPublicMpiCount(this.algorithm);
for(var i = 0; i < mpicount; i++) {
result += this.mpi[i].write();
}
return result;
}
// Write an old version packet - it's used by some of the internal routines.
this.writeOld = function() {
var bytes = this.writePublicKey();
return String.fromCharCode(0x99) +
util.writeNumber(bytes.length, 2) +
bytes;
}
/**
* Calculates the key id of the key
* @return {String} A 8 byte key id
*/
this.getKeyId = function() {
return this.getFingerprint().substr(12, 8);
}
/**
* Calculates the fingerprint of the key
* @return {String} A string containing the fingerprint
*/
this.getFingerprint = function() {
var toHash = this.writeOld();
return crypto.hash.sha1(toHash, toHash.length);
}
}
},{"../crypto":14,"../enums.js":27,"../type/mpi.js":50,"../util":52}],38:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var type_keyid = require('../type/keyid.js'),
util = require('../util'),
type_mpi = require('../type/mpi.js'),
enums = require('../enums.js'),
crypto = require('../crypto');
/**
* @class
* @classdesc Public-Key Encrypted Session Key Packets (Tag 1)
*
* RFC4880 5.1: A Public-Key Encrypted Session Key packet holds the session key
* used to encrypt a message. Zero or more Public-Key Encrypted Session Key
* packets and/or Symmetric-Key Encrypted Session Key packets may precede a
* Symmetrically Encrypted Data Packet, which holds an encrypted message. The
* message is encrypted with the session key, and the session key is itself
* encrypted and stored in the Encrypted Session Key packet(s). The
* Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted
* Session Key packet for each OpenPGP key to which the message is encrypted.
* The recipient of the message finds a session key that is encrypted to their
* public key, decrypts the session key, and then uses the session key to
* decrypt the message.
*/
module.exports = function packet_public_key_encrypted_session_key() {
this.version = 3;
this.publicKeyId = new type_keyid();
this.publicKeyAlgorithm = 'rsa_encrypt';
this.sessionKey = null;
this.sessionKeyAlgorithm = 'aes256';
/** @type {openpgp_type_mpi[]} */
this.encrypted = [];
/**
* Parsing function for a publickey encrypted session key packet (tag 1).
*
* @param {String} input Payload of a tag 1 packet
* @param {Integer} position Position to start reading from the input string
* @param {Integer} len Length of the packet or the remaining length of
* input at position
* @return {openpgp_packet_encrypteddata} Object representation
*/
this.read = function(bytes) {
this.version = bytes[0].charCodeAt();
this.publicKeyId.read(bytes.substr(1));
this.publicKeyAlgorithm = enums.read(enums.publicKey, bytes[9].charCodeAt());
var i = 10;
var integerCount = (function(algo) {
switch (algo) {
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
return 1;
case 'elgamal':
return 2;
default:
throw new Error("Invalid algorithm.");
}
})(this.publicKeyAlgorithm);
this.encrypted = [];
for(var j = 0; j < integerCount; j++) {
var mpi = new type_mpi();
i += mpi.read(bytes.substr(i));
this.encrypted.push(mpi);
}
}
/**
* Create a string representation of a tag 1 packet
*
* @param {String} publicKeyId
* The public key id corresponding to publicMPIs key as string
* @param {openpgp_type_mpi[]} publicMPIs
* Multiprecision integer objects describing the public key
* @param {Integer} pubalgo
* The corresponding public key algorithm // See RFC4880 9.1
* @param {Integer} symmalgo
* The symmetric cipher algorithm used to encrypt the data
* within an encrypteddatapacket or encryptedintegrity-
* protecteddatapacket
* following this packet //See RFC4880 9.2
* @param {String} sessionkey
* A string of randombytes representing the session key
* @return {String} The string representation
*/
this.write = function() {
var result = String.fromCharCode(this.version);
result += this.publicKeyId.write();
result += String.fromCharCode(
enums.write(enums.publicKey, this.publicKeyAlgorithm));
for ( var i = 0; i < this.encrypted.length; i++) {
result += this.encrypted[i].write()
}
return result;
}
this.encrypt = function(key) {
var data = String.fromCharCode(
enums.write(enums.symmetric, this.sessionKeyAlgorithm));
data += this.sessionKey;
var checksum = util.calc_checksum(this.sessionKey);
data += util.writeNumber(checksum, 2);
var mpi = new type_mpi();
mpi.fromBytes(crypto.pkcs1.eme.encode(
data,
key.mpi[0].byteLength()));
this.encrypted = crypto.publicKeyEncrypt(
this.publicKeyAlgorithm,
key.mpi,
mpi);
}
/**
* Decrypts the session key (only for public key encrypted session key
* packets (tag 1)
*
* @param {openpgp_msg_message} msg
* The message object (with member encryptedData
* @param {openpgp_msg_privatekey} key
* Private key with secMPIs unlocked
* @return {String} The unencrypted session key
*/
this.decrypt = function(key) {
var result = crypto.publicKeyDecrypt(
this.publicKeyAlgorithm,
key.mpi,
this.encrypted).toBytes();
var checksum = util.readNumber(result.substr(result.length - 2));
var decoded = crypto.pkcs1.eme.decode(
result,
key.mpi[0].byteLength());
var key = decoded.substring(1, decoded.length - 2);
if(checksum != util.calc_checksum(key)) {
throw new Error('Checksum mismatch');
}
else {
this.sessionKey = key;
this.sessionKeyAlgorithm =
enums.read(enums.symmetric, decoded.charCodeAt(0));
}
}
};
},{"../crypto":14,"../enums.js":27,"../type/keyid.js":49,"../type/mpi.js":50,"../util":52}],39:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var public_key = require('./public_key.js');
module.exports = function public_subkey() {
public_key.call(this);
}
},{"./public_key.js":37}],40:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var publicKey = require('./public_key.js'),
enums = require('../enums.js'),
util = require('../util'),
crypto = require('../crypto'),
type_mpi = require('../type/mpi.js'),
type_s2k = require('../type/s2k.js');
/**
* @class
* @classdesc Implementation of the Key Material Packet (Tag 5,6,7,14)
*
* RFC4480 5.5:
* A key material packet contains all the information about a public or
* private key. There are four variants of this packet type, and two
* major versions. Consequently, this section is complex.
*/
function packet_secret_key() {
publicKey.call(this);
this.encrypted = null;
function get_hash_len(hash) {
if(hash == 'sha1')
return 20;
else
return 2;
}
function get_hash_fn(hash) {
if(hash == 'sha1')
return crypto.hash.sha1;
else
return function(c) {
return util.writeNumber(util.calc_checksum(c), 2);
}
}
// Helper function
function parse_cleartext_mpi(hash_algorithm, cleartext, algorithm) {
var hashlen = get_hash_len(hash_algorithm),
hashfn = get_hash_fn(hash_algorithm);
var hashtext = cleartext.substr(cleartext.length - hashlen);
cleartext = cleartext.substr(0, cleartext.length - hashlen);
var hash = hashfn(cleartext);
if(hash != hashtext)
throw new Error("Hash mismatch.");
var mpis = crypto.getPrivateMpiCount(algorithm);
var j = 0;
var mpi = [];
for(var i = 0; i < mpis && j < cleartext.length; i++) {
mpi[i] = new type_mpi();
j += mpi[i].read(cleartext.substr(j));
}
return mpi;
}
function write_cleartext_mpi(hash_algorithm, algorithm, mpi) {
var bytes= '';
var discard = crypto.getPublicMpiCount(algorithm);
for(var i = discard; i < mpi.length; i++) {
bytes += mpi[i].write();
}
bytes += get_hash_fn(hash_algorithm)(bytes);
return bytes;
}
// 5.5.3. Secret-Key Packet Formats
/**
* Internal parser for private keys as specified in RFC 4880 section 5.5.3
* @param {String} bytes Input string to read the packet from
* @param {Integer} position Start position for the parser
* @param {Integer} len Length of the packet or remaining length of bytes
* @return {Object} This object with attributes set by the parser
*/
this.read = function(bytes) {
// - A Public-Key or Public-Subkey packet, as described above.
var len = this.readPublicKey(bytes);
bytes = bytes.substr(len);
// - One octet indicating string-to-key usage conventions. Zero
// indicates that the secret-key data is not encrypted. 255 or 254
// indicates that a string-to-key specifier is being given. Any
// other value is a symmetric-key encryption algorithm identifier.
var isEncrypted = bytes[0].charCodeAt();
if(isEncrypted) {
this.encrypted = bytes;
} else {
// - Plain or encrypted multiprecision integers comprising the secret
// key data. These algorithm-specific fields are as described
// below.
this.mpi = this.mpi.concat(parse_cleartext_mpi('mod', bytes.substr(1),
this.algorithm));
}
}
/*
* Creates an OpenPGP key packet for the given key. much
* TODO in regards to s2k, subkeys.
* @param {Integer} keyType Follows the OpenPGP algorithm standard,
* IE 1 corresponds to RSA.
* @param {RSA.keyObject} key
* @param passphrase
* @param s2kHash
* @param symmetricEncryptionAlgorithm
* @param timePacket
* @return {Object} {body: [string]OpenPGP packet body contents,
header: [string] OpenPGP packet header, string: [string] header+body}
*/
this.write = function() {
var bytes = this.writePublicKey();
if(!this.encrypted) {
bytes += String.fromCharCode(0);
bytes += write_cleartext_mpi('mod', this.algorithm, this.mpi);
} else {
bytes += this.encrypted;
}
return bytes;
}
/** Encrypt the payload. By default, we use aes256 and iterated, salted string
* to key specifier
* @param {String} passphrase
*/
this.encrypt = function(passphrase) {
var s2k = new type_s2k(),
symmetric = 'aes256',
cleartext = write_cleartext_mpi('sha1', this.algorithm, this.mpi),
key = produceEncryptionKey(s2k, passphrase, symmetric),
blockLen = crypto.cipher[symmetric].blockSize,
iv = crypto.random.getRandomBytes(blockLen);
this.encrypted = '';
this.encrypted += String.fromCharCode(254);
this.encrypted += String.fromCharCode(enums.write(enums.symmetric, symmetric));
this.encrypted += s2k.write();
this.encrypted += iv;
this.encrypted += crypto.cfb.normalEncrypt(symmetric, key, cleartext, iv);
}
function produceEncryptionKey(s2k, passphrase, algorithm) {
return s2k.produce_key(passphrase,
crypto.cipher[algorithm].keySize);
}
/**
* Decrypts the private key MPIs which are needed to use the key.
* openpgp_packet_keymaterial.hasUnencryptedSecretKeyData should be
* false otherwise
* a call to this function is not needed
*
* @param {String} str_passphrase The passphrase for this private key
* as string
* @return {Boolean} True if the passphrase was correct; false if not
*/
this.decrypt = function(passphrase) {
if (!this.encrypted)
return;
var i = 0,
symmetric,
key;
var s2k_usage = this.encrypted[i++].charCodeAt();
// - [Optional] If string-to-key usage octet was 255 or 254, a one-
// octet symmetric encryption algorithm.
if (s2k_usage == 255 || s2k_usage == 254) {
symmetric = this.encrypted[i++].charCodeAt();
symmetric = enums.read(enums.symmetric, symmetric);
// - [Optional] If string-to-key usage octet was 255 or 254, a
// string-to-key specifier. The length of the string-to-key
// specifier is implied by its type, as described above.
var s2k = new type_s2k();
i += s2k.read(this.encrypted.substr(i));
key = produceEncryptionKey(s2k, passphrase, symmetric);
} else {
symmetric = s2k_usage;
symmetric = enums.read(enums.symmetric, symmetric);
key = crypto.hash.md5(passphrase);
}
// - [Optional] If secret data is encrypted (string-to-key usage octet
// not zero), an Initial Vector (IV) of the same length as the
// cipher's block size.
var iv = this.encrypted.substr(i,
crypto.cipher[symmetric].blockSize);
i += iv.length;
var cleartext,
ciphertext = this.encrypted.substr(i);
cleartext = crypto.cfb.normalDecrypt(symmetric, key, ciphertext, iv);
var hash = s2k_usage == 254 ?
'sha1' :
'mod';
this.mpi = this.mpi.concat(parse_cleartext_mpi(hash, cleartext,
this.algorithm));
}
this.generate = function(bits) {
}
}
packet_secret_key.prototype = new publicKey;
module.exports = packet_secret_key;
},{"../crypto":14,"../enums.js":27,"../type/mpi.js":50,"../type/s2k.js":51,"../util":52,"./public_key.js":37}],41:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var secret_key = require('./secret_key.js');
module.exports = function secret_subkey() {
secret_key.call(this);
}
},{"./secret_key.js":40}],42:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var util = require('../util'),
packet = require('./packet.js'),
enums = require('../enums.js'),
crypto = require('../crypto'),
type_mpi = require('../type/mpi.js');
/**
* @class
* @classdesc Implementation of the Signature Packet (Tag 2)
*
* RFC4480 5.2:
* A Signature packet describes a binding between some public key and
* some data. The most common signatures are a signature of a file or a
* block of text, and a signature that is a certification of a User ID.
*/
module.exports = function packet_signature() {
this.signatureType = null;
this.hashAlgorithm = null;
this.publicKeyAlgorithm = null;
this.signatureData = null;
this.signedHashValue = null;
this.mpi = null;
this.created = null;
this.signatureExpirationTime = null;
this.signatureNeverExpires = null;
this.exportable = null;
this.trustLevel = null;
this.trustAmount = null;
this.regularExpression = null;
this.revocable = null;
this.keyExpirationTime = null;
this.keyNeverExpires = null;
this.preferredSymmetricAlgorithms = null;
this.revocationKeyClass = null;
this.revocationKeyAlgorithm = null;
this.revocationKeyFingerprint = null;
this.issuerKeyId = null;
this.notation = {};
this.preferredHashAlgorithms = null;
this.preferredCompressionAlgorithms = null;
this.keyServerPreferences = null;
this.preferredKeyServer = null;
this.isPrimaryUserID = null;
this.policyURI = null;
this.keyFlags = null;
this.signersUserId = null;
this.reasonForRevocationFlag = null;
this.reasonForRevocationString = null;
this.signatureTargetPublicKeyAlgorithm = null;
this.signatureTargetHashAlgorithm = null;
this.signatureTargetHash = null;
this.embeddedSignature = null;
this.verified = false;
/**
* parsing function for a signature packet (tag 2).
* @param {String} bytes payload of a tag 2 packet
* @param {Integer} position position to start reading from the bytes string
* @param {Integer} len length of the packet or the remaining length of bytes at position
* @return {openpgp_packet_encrypteddata} object representation
*/
this.read = function(bytes) {
var i = 0;
var version = bytes[i++].charCodeAt();
// switch on version (3 and 4)
switch (version) {
case 3:
// One-octet length of following hashed material. MUST be 5.
if (bytes[i++].charCodeAt() != 5)
util.print_debug("openpgp.packet.signature.js\n"+
'invalid One-octet length of following hashed material.' +
'MUST be 5. @:'+(i-1));
var sigpos = i;
// One-octet signature type.
this.signatureType = bytes[i++].charCodeAt();
// Four-octet creation time.
this.created = util.readDate(bytes.substr(i, 4));
i += 4;
// storing data appended to data which gets verified
this.signatureData = bytes.substring(position, i);
// Eight-octet Key ID of signer.
this.issuerKeyId = bytes.substring(i, i +8);
i += 8;
// One-octet public-key algorithm.
this.publicKeyAlgorithm = bytes[i++].charCodeAt();
// One-octet hash algorithm.
this.hashAlgorithm = bytes[i++].charCodeAt();
break;
case 4:
this.signatureType = bytes[i++].charCodeAt();
this.publicKeyAlgorithm = bytes[i++].charCodeAt();
this.hashAlgorithm = bytes[i++].charCodeAt();
function subpackets(bytes, signed) {
// Two-octet scalar octet count for following hashed subpacket
// data.
var subpacket_length = util.readNumber(
bytes.substr(0, 2));
var i = 2;
// Hashed subpacket data set (zero or more subpackets)
var subpacked_read = 0;
while (i < 2 + subpacket_length) {
var len = packet.readSimpleLength(bytes.substr(i));
i += len.offset;
// Since it is trivial to add data to the unhashed portion of
// the packet we simply ignore all unauthenticated data.
if(signed)
this.read_sub_packet(bytes.substr(i, len.len));
i += len.len;
}
return i;
}
i += subpackets.call(this, bytes.substr(i), true);
// A V4 signature hashes the packet body
// starting from its first field, the version number, through the end
// of the hashed subpacket data. Thus, the fields hashed are the
// signature version, the signature type, the public-key algorithm, the
// hash algorithm, the hashed subpacket length, and the hashed
// subpacket body.
this.signatureData = bytes.substr(0, i);
i += subpackets.call(this, bytes.substr(i), false);
break;
default:
throw new Error('Version ' + version + ' of the signature is unsupported.');
break;
}
// Two-octet field holding left 16 bits of signed hash value.
this.signedHashValue = bytes.substr(i, 2);
i += 2;
this.signature = bytes.substr(i);
}
this.write = function() {
return this.signatureData +
util.writeNumber(0, 2) + // Number of unsigned subpackets.
this.signedHashValue +
this.signature;
}
/**
* Signs provided data. This needs to be done prior to serialization.
* @param {Object} data Contains packets to be signed.
* @param {openpgp_msg_privatekey} privatekey private key used to sign the message.
*/
this.sign = function(key, data) {
var signatureType = enums.write(enums.signature, this.signatureType),
publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm),
hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
var result = String.fromCharCode(4);
result += String.fromCharCode(signatureType);
result += String.fromCharCode(publicKeyAlgorithm);
result += String.fromCharCode(hashAlgorithm);
// Add subpackets here
result += util.writeNumber(0, 2);
this.signatureData = result;
var trailer = this.calculateTrailer();
var toHash = this.toSign(signatureType, data) +
this.signatureData + trailer;
var hash = crypto.hash.digest(hashAlgorithm, toHash);
this.signedHashValue = hash.substr(0, 2);
this.signature = crypto.signature.sign(hashAlgorithm,
publicKeyAlgorithm, key.mpi, toHash);
}
/**
* creates a string representation of a sub signature packet (See RFC 4880 5.2.3.1)
* @param {Integer} type subpacket signature type. Signature types as described
* in RFC4880 Section 5.2.3.2
* @param {String} data data to be included
* @return {String} a string-representation of a sub signature packet (See RFC 4880 5.2.3.1)
*/
function write_sub_packet(type, data) {
var result = "";
result += packet.writeSimpleLength(data.length+1);
result += String.fromCharCode(type);
result += data;
return result;
}
// V4 signature sub packets
this.read_sub_packet = function(bytes) {
var mypos = 0;
function read_array(prop, bytes) {
this[prop] = [];
for (var i = 0; i < bytes.length; i++) {
this[prop].push(bytes[i].charCodeAt());
}
}
// The leftwost bit denotes a "critical" packet, but we ignore it.
var type = bytes[mypos++].charCodeAt() & 0x7F;
// subpacket type
switch (type) {
case 2: // Signature Creation Time
this.created = util.readDate(bytes.substr(mypos));
break;
case 3: // Signature Expiration Time
var time = util.readDate(bytes.substr(mypos));
this.signatureNeverExpires = time.getTime() == 0;
this.signatureExpirationTime = time;
break;
case 4: // Exportable Certification
this.exportable = bytes[mypos++].charCodeAt() == 1;
break;
case 5: // Trust Signature
this.trustLevel = bytes[mypos++].charCodeAt();
this.trustAmount = bytes[mypos++].charCodeAt();
break;
case 6: // Regular Expression
this.regularExpression = bytes.substr(mypos);
break;
case 7: // Revocable
this.revocable = bytes[mypos++].charCodeAt() == 1;
break;
case 9: // Key Expiration Time
var time = util.readDate(bytes.substr(mypos));
this.keyExpirationTime = time;
this.keyNeverExpires = time.getTime() == 0;
break;
case 11: // Preferred Symmetric Algorithms
this.preferredSymmetricAlgorithms = [];
while(mypos != bytes.length) {
this.preferredSymmetricAlgorithms.push(bytes[mypos++].charCodeAt());
}
break;
case 12: // Revocation Key
// (1 octet of class, 1 octet of public-key algorithm ID, 20
// octets of
// fingerprint)
this.revocationKeyClass = bytes[mypos++].charCodeAt();
this.revocationKeyAlgorithm = bytes[mypos++].charCodeAt();
this.revocationKeyFingerprint = bytes.substr(mypos, 20);
break;
case 16: // Issuer
this.issuerKeyId = bytes.substr(mypos, 8);
break;
case 20: // Notation Data
// We don't know how to handle anything but a text flagged data.
if(bytes[mypos].charCodeAt() == 0x80) {
// We extract key/value tuple from the byte stream.
mypos += 4;
var m = util.writeNumber(bytes.substr(mypos, 2));
mypos += 2
var n = util.writeNumber(bytes.substr(mypos, 2));
mypos += 2
var name = bytes.substr(mypos, m),
value = bytes.substr(mypos + m, n);
this.notation[name] = value;
}
else throw new Error("Unsupported notation flag.");
break;
case 21: // Preferred Hash Algorithms
read_array.call(this, 'preferredHashAlgorithms', bytes.substr(mypos));
break;
case 22: // Preferred Compression Algorithms
read_array.call(this, 'preferredCompressionAlgorithms ', bytes.substr(mypos));
break;
case 23: // Key Server Preferences
read_array.call(this, 'keyServerPreferencess', bytes.substr(mypos));
break;
case 24: // Preferred Key Server
this.preferredKeyServer = bytes.substr(mypos);
break;
case 25: // Primary User ID
this.isPrimaryUserID = bytes[mypos++] != 0;
break;
case 26: // Policy URI
this.policyURI = bytes.substr(mypos);
break;
case 27: // Key Flags
read_array.call(this, 'keyFlags', bytes.substr(mypos));
break;
case 28: // Signer's User ID
this.signersUserId += bytes.substr(mypos);
break;
case 29: // Reason for Revocation
this.reasonForRevocationFlag = bytes[mypos++].charCodeAt();
this.reasonForRevocationString = bytes.substr(mypos);
break;
case 30: // Features
read_array.call(this, 'features', bytes.substr(mypos));
break;
case 31: // Signature Target
// (1 octet public-key algorithm, 1 octet hash algorithm, N octets hash)
this.signatureTargetPublicKeyAlgorithm = bytes[mypos++].charCodeAt();
this.signatureTargetHashAlgorithm = bytes[mypos++].charCodeAt();
var len = crypto.getHashByteLength(this.signatureTargetHashAlgorithm);
this.signatureTargetHash = bytes.substr(mypos, len);
break;
case 32: // Embedded Signature
this.embeddedSignature = new packet_signature();
this.embeddedSignature.read(bytes.substr(mypos));
break;
default:
util.print_error("openpgp.packet.signature.js\n"+
'unknown signature subpacket type '+type+" @:"+mypos+
" subplen:"+subplen+" len:"+len);
break;
}
};
// Produces data to produce signature on
this.toSign = function(type, data) {
var t = enums.signature
switch(type) {
case t.binary:
return data.literal.getBytes();
case t.text:
return this.toSign(t.binary, data)
.replace(/\r\n/g, '\n')
.replace(/\n/g, '\r\n');
case t.standalone:
return ''
case t.cert_generic:
case t.cert_persona:
case t.cert_casual:
case t.cert_positive:
case t.cert_revocation:
{
var packet, tag;
if(data.userid != undefined) {
tag = 0xB4;
packet = data.userid;
}
else if(data.userattribute != undefined) {
tag = 0xD1
packet = data.userattribute;
}
else throw new Error('Either a userid or userattribute packet needs to be ' +
'supplied for certification.');
var bytes = packet.write();
return this.toSign(t.key, data) +
String.fromCharCode(tag) +
util.writeNumber(bytes.length, 4) +
bytes;
}
case t.subkey_binding:
case t.key_binding:
{
return this.toSign(t.key, data) + this.toSign(t.key, { key: data.bind });
}
case t.key:
{
if(data.key == undefined)
throw new Error('Key packet is required for this sigtature.');
return data.key.writeOld();
}
case t.key_revocation:
case t.subkey_revocation:
return this.toSign(t.key, data);
case t.timestamp:
return '';
case t.thrid_party:
throw new Error('Not implemented');
break;
default:
throw new Error('Unknown signature type.')
}
}
this.calculateTrailer = function() {
// calculating the trailer
var trailer = '';
trailer += String.fromCharCode(4); // Version
trailer += String.fromCharCode(0xFF);
trailer += util.writeNumber(this.signatureData.length, 4);
return trailer
}
/**
* verifys the signature packet. Note: not signature types are implemented
* @param {String} data data which on the signature applies
* @param {openpgp_msg_privatekey} key the public key to verify the signature
* @return {boolean} True if message is verified, else false.
*/
this.verify = function(key, data) {
var signatureType = enums.write(enums.signature, this.signatureType),
publicKeyAlgorithm = enums.write(enums.publicKey, this.publicKeyAlgorithm),
hashAlgorithm = enums.write(enums.hash, this.hashAlgorithm);
var bytes = this.toSign(signatureType, data),
trailer = this.calculateTrailer();
var mpicount = 0;
// Algorithm-Specific Fields for RSA signatures:
// - multiprecision number (MPI) of RSA signature value m**d mod n.
if (publicKeyAlgorithm > 0 && publicKeyAlgorithm < 4)
mpicount = 1;
// Algorithm-Specific Fields for DSA signatures:
// - MPI of DSA value r.
// - MPI of DSA value s.
else if (publicKeyAlgorithm == 17)
mpicount = 2;
var mpi = [], i = 0;
for (var j = 0; j < mpicount; j++) {
mpi[j] = new type_mpi();
i += mpi[j].read(this.signature.substr(i));
}
this.verified = crypto.signature.verify(publicKeyAlgorithm,
hashAlgorithm, mpi, key.mpi,
bytes + this.signatureData + trailer);
return this.verified;
}
}
},{"../crypto":14,"../enums.js":27,"../type/mpi.js":50,"../util":52,"./packet.js":35}],43:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var util = require('../util'),
crypto = require('../crypto');
/**
* @class
* @classdesc Implementation of the Sym. Encrypted Integrity Protected Data
* Packet (Tag 18)
*
* RFC4880 5.13: The Symmetrically Encrypted Integrity Protected Data packet is
* a variant of the Symmetrically Encrypted Data packet. It is a new feature
* created for OpenPGP that addresses the problem of detecting a modification to
* encrypted data. It is used in combination with a Modification Detection Code
* packet.
*/
module.exports = function packet_sym_encrypted_integrity_protected() {
/** The encrypted payload. */
this.encrypted = null; // string
/** @type {Boolean}
* If after decrypting the packet this is set to true,
* a modification has been detected and thus the contents
* should be discarded.
*/
this.modification = false;
this.packets;
this.read = function(bytes) {
// - A one-octet version number. The only currently defined value is
// 1.
var version = bytes[0].charCodeAt();
if (version != 1) {
throw new Error('Invalid packet version.');
}
// - Encrypted data, the output of the selected symmetric-key cipher
// operating in Cipher Feedback mode with shift amount equal to the
// block size of the cipher (CFB-n where n is the block size).
this.encrypted = bytes.substr(1);
}
this.write = function() {
return String.fromCharCode(1) // Version
+ this.encrypted;
}
this.encrypt = function(sessionKeyAlgorithm, key) {
var bytes = this.packets.write()
var prefixrandom = crypto.getPrefixRandom(sessionKeyAlgorithm);
var prefix = prefixrandom
+ prefixrandom.charAt(prefixrandom.length - 2)
+ prefixrandom.charAt(prefixrandom.length - 1)
var tohash = bytes;
// Modification detection code packet.
tohash += String.fromCharCode(0xD3);
tohash += String.fromCharCode(0x14);
tohash += crypto.hash.sha1(prefix + tohash);
this.encrypted = crypto.cfb.encrypt(prefixrandom,
sessionKeyAlgorithm, tohash, key, false).substring(0,
prefix.length + tohash.length);
}
/**
* Decrypts the encrypted data contained in this object read_packet must
* have been called before
*
* @param {Integer} sessionKeyAlgorithm
* The selected symmetric encryption algorithm to be used
* @param {String} key The key of cipher blocksize length to be used
* @return {String} The decrypted data of this packet
*/
this.decrypt = function(sessionKeyAlgorithm, key) {
var decrypted = crypto.cfb.decrypt(
sessionKeyAlgorithm, key, this.encrypted, false);
// there must be a modification detection code packet as the
// last packet and everything gets hashed except the hash itself
this.hash = crypto.hash.sha1(
crypto.cfb.mdc(sessionKeyAlgorithm, key, this.encrypted)
+ decrypted.substring(0, decrypted.length - 20));
var mdc = decrypted.substr(decrypted.length - 20, 20);
if(this.hash != mdc) {
throw new Error('Modification detected.');
}
else
this.packets.read(decrypted.substr(0, decrypted.length - 22));
}
};
},{"../crypto":14,"../util":52}],44:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var type_s2k = require('../type/s2k.js'),
enums = require('../enums.js'),
crypto = require('../crypto');
/**
* @class
* @classdesc Public-Key Encrypted Session Key Packets (Tag 1)
*
* RFC4880 5.1: A Public-Key Encrypted Session Key packet holds the session key
* used to encrypt a message. Zero or more Public-Key Encrypted Session Key
* packets and/or Symmetric-Key Encrypted Session Key packets may precede a
* Symmetrically Encrypted Data Packet, which holds an encrypted message. The
* message is encrypted with the session key, and the session key is itself
* encrypted and stored in the Encrypted Session Key packet(s). The
* Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted
* Session Key packet for each OpenPGP key to which the message is encrypted.
* The recipient of the message finds a session key that is encrypted to their
* public key, decrypts the session key, and then uses the session key to
* decrypt the message.
*/
module.exports = function packet_sym_encrypted_session_key() {
this.tag = 3;
this.sessionKeyEncryptionAlgorithm = null;
this.sessionKeyAlgorithm = 'aes256';
this.encrypted = null;
this.s2k = new type_s2k();
/**
* Parsing function for a symmetric encrypted session key packet (tag 3).
*
* @param {String} input Payload of a tag 1 packet
* @param {Integer} position Position to start reading from the input string
* @param {Integer} len
* Length of the packet or the remaining length of
* input at position
* @return {openpgp_packet_encrypteddata} Object representation
*/
this.read = function(bytes) {
// A one-octet version number. The only currently defined version is 4.
this.version = bytes[0].charCodeAt();
// A one-octet number describing the symmetric algorithm used.
var algo = enums.read(enums.symmetric, bytes[1].charCodeAt());
// A string-to-key (S2K) specifier, length as defined above.
var s2klength = this.s2k.read(bytes.substr(2));
// Optionally, the encrypted session key itself, which is decrypted
// with the string-to-key object.
var done = s2klength + 2;
if(done < bytes.length) {
this.encrypted = bytes.substr(done);
this.sessionKeyEncryptionAlgorithm = algo
}
else
this.sessionKeyAlgorithm = algo;
}
this.write = function() {
var algo = this.encrypted == null ?
this.sessionKeyAlgorithm :
this.sessionKeyEncryptionAlgorithm;
var bytes = String.fromCharCode(this.version) +
String.fromCharCode(enums.write(enums.symmetric, algo)) +
this.s2k.write();
if(this.encrypted != null)
bytes += this.encrypted;
return bytes;
}
/**
* Decrypts the session key (only for public key encrypted session key
* packets (tag 1)
*
* @param {openpgp_msg_message} msg
* The message object (with member encryptedData
* @param {openpgp_msg_privatekey} key
* Private key with secMPIs unlocked
* @return {String} The unencrypted session key
*/
this.decrypt = function(passphrase) {
var algo = this.sessionKeyEncryptionAlgorithm != null ?
this.sessionKeyEncryptionAlgorithm :
this.sessionKeyAlgorithm;
var length = crypto.cipher[algo].keySize;
var key = this.s2k.produce_key(passphrase, length);
if(this.encrypted == null) {
this.sessionKey = key;
} else {
var decrypted = crypto.cfb.decrypt(
this.sessionKeyEncryptionAlgorithm, key, this.encrypted, true);
this.sessionKeyAlgorithm = enums.read(enums.symmetric,
decrypted[0].keyCodeAt());
this.sessionKey = decrypted.substr(1);
}
}
this.encrypt = function(passphrase) {
var length = crypto.getKeyLength(this.sessionKeyEncryptionAlgorithm);
var key = this.s2k.produce_key(passphrase, length);
var private_key = String.fromCharCode(
enums.write(enums.symmetric, this.sessionKeyAlgorithm)) +
crypto.getRandomBytes(
crypto.getKeyLength(this.sessionKeyAlgorithm));
this.encrypted = crypto.cfb.encrypt(
crypto.getPrefixRandom(this.sessionKeyEncryptionAlgorithm),
this.sessionKeyEncryptionAlgorithm, key, private_key, true);
}
};
},{"../crypto":14,"../enums.js":27,"../type/s2k.js":51}],45:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var crypto = require('../crypto');
/**
* @class
* @classdesc Implementation of the Symmetrically Encrypted Data Packet (Tag 9)
*
* RFC4880 5.7: The Symmetrically Encrypted Data packet contains data encrypted
* with a symmetric-key algorithm. When it has been decrypted, it contains other
* packets (usually a literal data packet or compressed data packet, but in
* theory other Symmetrically Encrypted Data packets or sequences of packets
* that form whole OpenPGP messages).
*/
module.exports = function packet_symmetrically_encrypted() {
this.encrypted = null;
/** Decrypted packets contained within.
* @type {openpgp_packetlist} */
this.packets;
this.read = function(bytes) {
this.encrypted = bytes;
}
this.write = function() {
return this.encrypted;
}
/**
* Symmetrically decrypt the packet data
*
* @param {Integer} sessionKeyAlgorithm
* Symmetric key algorithm to use // See RFC4880 9.2
* @param {String} key
* Key as string with the corresponding length to the
* algorithm
* @return The decrypted data;
*/
this.decrypt = function(sessionKeyAlgorithm, key) {
var decrypted = crypto.cfb.decrypt(
sessionKeyAlgorithm, key, this.encrypted, true);
this.packets.read(decrypted);
}
this.encrypt = function(algo, key) {
var data = this.packets.write();
this.encrypted = crypto.cfb.encrypt(
crypto.getPrefixRandom(algo), algo, data, key, true);
}
};
},{"../crypto":14}],46:[function(require,module,exports){
module.exports = function packet_trust() {
};
},{}],47:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* @class
* @classdesc Implementation of the User Attribute Packet (Tag 17)
* The User Attribute packet is a variation of the User ID packet. It
* is capable of storing more types of data than the User ID packet,
* which is limited to text. Like the User ID packet, a User Attribute
* packet may be certified by the key owner ("self-signed") or any other
* key owner who cares to certify it. Except as noted, a User Attribute
* packet may be used anywhere that a User ID packet may be used.
*
* While User Attribute packets are not a required part of the OpenPGP
* standard, implementations SHOULD provide at least enough
* compatibility to properly handle a certification signature on the
* User Attribute packet. A simple way to do this is by treating the
* User Attribute packet as a User ID packet with opaque contents, but
* an implementation may use any method desired.
*/
module.exports = function packet_user_attribute() {
this.tag = 17;
this.attributes = [];
/**
* parsing function for a user attribute packet (tag 17).
* @param {String} input payload of a tag 17 packet
* @param {Integer} position position to start reading from the input string
* @param {Integer} len length of the packet or the remaining length of input at position
* @return {openpgp_packet_encrypteddata} object representation
*/
this.read = function(bytes) {
var i = 0;
while(i < bytes.length) {
var len = openpgp_packet.read_simple_length(bytes);
i += len.offset;
this.attributes.push(bytes.substr(i, len.len));
i += len.len;
}
}
};
},{}],48:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var util = require('../util');
/**
* @class
* @classdesc Implementation of the User ID Packet (Tag 13)
* A User ID packet consists of UTF-8 text that is intended to represent
* the name and email address of the key holder. By convention, it
* includes an RFC 2822 [RFC2822] mail name-addr, but there are no
* restrictions on its content. The packet length in the header
* specifies the length of the User ID.
*/
module.exports = function packet_userid() {
/** @type {String} A string containing the user id. Usually in the form
* John Doe <john@example.com>
*/
this.userid = '';
/**
* Parsing function for a user id packet (tag 13).
* @param {String} input payload of a tag 13 packet
* @param {Integer} position position to start reading from the input string
* @param {Integer} len length of the packet or the remaining length of input
* at position
* @return {openpgp_packet_encrypteddata} object representation
*/
this.read = function(bytes) {
this.userid = util.decode_utf8(bytes);
}
/**
* Creates a string representation of the user id packet
* @param {String} user_id the user id as string ("John Doe <john.doe@mail.us")
* @return {String} string representation
*/
this.write = function() {
return util.encode_utf8(this.userid);
}
}
},{"../util":52}],49:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/**
* @class
* @classdesc Implementation of type key id (RFC4880 3.3)
* A Key ID is an eight-octet scalar that identifies a key.
Implementations SHOULD NOT assume that Key IDs are unique. The
section "Enhanced Key Formats" below describes how Key IDs are
formed.
*/
module.exports = function keyid() {
var bytes = '';
for(var i = 0; i < 8; i++)
bytes += String.fromCharCode(0);
/**
* Parsing method for a key id
* @param {String} input Input to read the key id from
* @param {integer} position Position where to start reading the key
* id from input
* @return {openpgp_type_keyid} This object
*/
this.read = function(bytes) {
this.bytes = bytes.substr(0, 8);
}
this.write = function() {
return this.bytes;
}
};
},{}],50:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
// Hint: We hold our MPIs as an array of octets in big endian format preceeding a two
// octet scalar: MPI: [a,b,c,d,e,f]
// - MPI size: (a << 8) | b
// - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8)
var BigInteger = require('../crypto/public_key/jsbn.js'),
util = require('../util');
/**
* @class
* @classdescImplementation of type MPI (RFC4880 3.2)
* Multiprecision integers (also called MPIs) are unsigned integers used
* to hold large integers such as the ones used in cryptographic
* calculations.
* An MPI consists of two pieces: a two-octet scalar that is the length
* of the MPI in bits followed by a string of octets that contain the
* actual integer.
*/
module.exports = function mpi() {
/** An implementation dependent integer */
this.data = null;
/**
* Parsing function for a mpi (RFC 4880 3.2).
* @param {String} input Payload of mpi data
* @param {Integer} position Position to start reading from the input
* string
* @param {Integer} len Length of the packet or the remaining length of
* input at position
* @return {openpgp_type_mpi} Object representation
*/
this.read = function(bytes) {
var bits = (bytes[0].charCodeAt() << 8) | bytes[1].charCodeAt();
// Additional rules:
//
// The size of an MPI is ((MPI.length + 7) / 8) + 2 octets.
//
// The length field of an MPI describes the length starting from its
// most significant non-zero bit. Thus, the MPI [00 02 01] is not
// formed correctly. It should be [00 01 01].
// TODO: Verification of this size method! This size calculation as
// specified above is not applicable in JavaScript
var bytelen = Math.ceil(bits / 8);
var raw = bytes.substr(2, bytelen);
this.fromBytes(raw);
return 2 + bytelen;
}
this.fromBytes = function(bytes) {
this.data = new BigInteger(util.hexstrdump(bytes), 16);
}
this.toBytes = function() {
return this.write().substr(2);
}
this.byteLength = function() {
return this.toBytes().length;
}
/**
* Converts the mpi object to a string as specified in RFC4880 3.2
* @return {String} mpi Byte representation
*/
this.write = function() {
return this.data.toMPI();
}
this.toBigInteger = function() {
return this.data.clone();
}
this.fromBigInteger = function(bn) {
this.data = bn.clone();
}
}
},{"../crypto/public_key/jsbn.js":21,"../util":52}],51:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var enums = require('../enums.js'),
util = require('../util'),
crypto = require('../crypto');
/**
* @class
* @classdesc Implementation of the String-to-key specifier (RFC4880 3.7)
* String-to-key (S2K) specifiers are used to convert passphrase strings
into symmetric-key encryption/decryption keys. They are used in two
places, currently: to encrypt the secret part of private keys in the
private keyring, and to convert passphrases to encryption keys for
symmetrically encrypted messages.
*/
module.exports = function s2k() {
/** @type {openpgp.hash} */
this.algorithm = 'sha256';
/** @type {openpgp_type_s2k.type} */
this.type = 'iterated';
this.c = 96;
/** @type {openpgp_bytearray}
* Eight bytes of salt. */
this.salt = crypto.random.getRandomBytes(8);
// Exponen bias, defined in RFC4880
var expbias = 6;
this.get_count = function() {
return (16 + (this.c & 15)) << ((this.c >> 4) + expbias);
}
/**
* Parsing function for a string-to-key specifier (RFC 4880 3.7).
* @param {String} input Payload of string-to-key specifier
* @return {Integer} Actual length of the object
*/
this.read = function(bytes) {
var i = 0;
this.type = enums.read(enums.s2k, bytes[i++].charCodeAt());
this.algorithm = enums.read(enums.hash, bytes[i++].charCodeAt());
switch (this.type) {
case 'simple':
break;
case 'salted':
this.salt = bytes.substr(i, 8);
i += 8;
break;
case 'iterated':
this.salt = bytes.substr(i, 8);
i += 8;
// Octet 10: count, a one-octet, coded value
this.c = bytes[i++].charCodeAt();
break;
case 'gnu':
if(bytes.substr(i, 3) == "GNU") {
i += 3; // GNU
var gnuExtType = 1000 + bytes[i++].charCodeAt();
if(gnuExtType == 1001) {
this.type = gnuExtType;
// GnuPG extension mode 1001 -- don't write secret key at all
} else {
throw new Error("Unknown s2k gnu protection mode.");
}
} else {
throw new Error("Unknown s2k type.");
}
break;
default:
throw new Error("Unknown s2k type.");
break;
}
return i;
}
/**
* writes an s2k hash based on the inputs.
* @return {String} Produced key of hashAlgorithm hash length
*/
this.write = function() {
var bytes = String.fromCharCode(enums.write(enums.s2k, this.type));
bytes += String.fromCharCode(enums.write(enums.hash, this.algorithm));
switch(this.type) {
case 'simple':
break;
case 'salted':
bytes += this.salt;
break;
case 'iterated':
bytes += this.salt;
bytes += String.fromCharCode(this.c);
break;
};
return bytes;
}
/**
* Produces a key using the specified passphrase and the defined
* hashAlgorithm
* @param {String} passphrase Passphrase containing user input
* @return {String} Produced key with a length corresponding to
* hashAlgorithm hash length
*/
this.produce_key = function(passphrase, numBytes) {
passphrase = util.encode_utf8(passphrase);
function round(prefix, s2k) {
var algorithm = enums.write(enums.hash, s2k.algorithm);
switch(s2k.type) {
case 'simple':
return crypto.hash.digest(algorithm, prefix + passphrase);
case 'salted':
return crypto.hash.digest(algorithm,
prefix + s2k.salt + passphrase);
case 'iterated':
var isp = [],
count = s2k.get_count();
data = s2k.salt + passphrase;
while (isp.length * data.length < count)
isp.push(data);
isp = isp.join('');
if (isp.length > count)
isp = isp.substr(0, count);
return crypto.hash.digest(algorithm, prefix + isp);
};
}
var result = '',
prefix = '';
while(result.length <= numBytes) {
result += round(prefix, this);
prefix += String.fromCharCode(0);
}
return result.substr(0, numBytes);
}
}
},{"../crypto":14,"../enums.js":27,"../util":52}],52:[function(require,module,exports){
// GPG4Browsers - An OpenPGP implementation in javascript
// Copyright (C) 2011 Recurity Labs GmbH
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
var Util = function() {
this.readNumber = function (bytes) {
var n = 0;
for(var i = 0; i < bytes.length; i++) {
n <<= 8;
n += bytes[i].charCodeAt()
}
return n;
}
this.writeNumber = function(n, bytes) {
var b = '';
for(var i = 0; i < bytes; i++) {
b += String.fromCharCode((n >> (8 * (bytes- i - 1))) & 0xFF);
}
return b;
}
this.readDate = function(bytes) {
var n = this.readNumber(bytes);
var d = new Date();
d.setTime(n * 1000);
return d;
}
this.writeDate = function(time) {
var numeric = Math.round(time.getTime() / 1000);
return this.writeNumber(numeric, 4);
}
this.emailRegEx = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/;
this.debug = false;
this.hexdump = function(str) {
var r=[];
var e=str.length;
var c=0;
var h;
var i = 0;
while(c<e){
h=str.charCodeAt(c++).toString(16);
while(h.length<2) h="0"+h;
r.push(" "+h);
i++;
if (i % 32 == 0)
r.push("\n ");
}
return r.join('');
};
/**
* Create hexstring from a binary
* @param {String} str String to convert
* @return {String} String containing the hexadecimal values
*/
this.hexstrdump = function(str) {
if (str == null)
return "";
var r=[];
var e=str.length;
var c=0;
var h;
while(c<e){
h=str[c++].charCodeAt().toString(16);
while(h.length<2) h="0"+h;
r.push(""+h);
}
return r.join('');
};
/**
* Create binary string from a hex encoded string
* @param {String} str Hex string to convert
* @return {String} String containing the binary values
*/
this.hex2bin = function(hex) {
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
};
/**
* Creating a hex string from an binary array of integers (0..255)
* @param {String} str Array of bytes to convert
* @return {String} Hexadecimal representation of the array
*/
this.hexidump = function(str) {
var r=[];
var e=str.length;
var c=0;
var h;
while(c<e){
h=str[c++].toString(16);
while(h.length<2) h="0"+h;
r.push(""+h);
}
return r.join('');
};
/**
* Convert a native javascript string to a string of utf8 bytes
* @param {String} str The string to convert
* @return {String} A valid squence of utf8 bytes
*/
this.encode_utf8 = function(str) {
return unescape(encodeURIComponent(str));
};
/**
* Convert a string of utf8 bytes to a native javascript string
* @param {String} utf8 A valid squence of utf8 bytes
* @return {String} A native javascript string
*/
this.decode_utf8 = function(utf8) {
return decodeURIComponent(escape(utf8));
};
var str2bin = function(str, result) {
for (var i = 0; i < str.length; i++) {
result[i] = str.charCodeAt(i);
}
return result;
};
var bin2str = function(bin) {
var result = [];
for (var i = 0; i < bin.length; i++) {
result.push(String.fromCharCode(bin[i]));
}
return result.join('');
};
/**
* Convert a string to an array of integers(0.255)
* @param {String} str String to convert
* @return {Integer[]} An array of (binary) integers
*/
this.str2bin = function(str) {
return str2bin(str, new Array(str.length));
};
/**
* Convert an array of integers(0.255) to a string
* @param {Integer[]} bin An array of (binary) integers to convert
* @return {String} The string representation of the array
*/
this.bin2str = bin2str;
/**
* Convert a string to a Uint8Array
* @param {String} str String to convert
* @return {Uint8Array} The array of (binary) integers
*/
this.str2Uint8Array = function(str) {
return str2bin(str, new Uint8Array(new ArrayBuffer(str.length)));
};
/**
* Convert a Uint8Array to a string. This currently functions
* the same as bin2str.
* @param {Uint8Array} bin An array of (binary) integers to convert
* @return {String} String representation of the array
*/
this.Uint8Array2str = bin2str;
/**
* Calculates a 16bit sum of a string by adding each character
* codes modulus 65535
* @param {String} text String to create a sum of
* @return {Integer} An integer containing the sum of all character
* codes % 65535
*/
this.calc_checksum = function(text) {
var checksum = { s: 0, add: function (sadd) { this.s = (this.s + sadd) % 65536; }};
for (var i = 0; i < text.length; i++) {
checksum.add(text.charCodeAt(i));
}
return checksum.s;
};
/**
* Helper function to print a debug message. Debug
* messages are only printed if
* openpgp.config.debug is set to true. The calling
* Javascript context MUST define
* a "showMessages(text)" function. Line feeds ('\n')
* are automatically converted to HTML line feeds '<br/>'
* @param {String} str String of the debug message
* @return {String} An HTML tt entity containing a paragraph with a
* style attribute where the debug message is HTMLencoded in.
*/
this.print_debug = function(str) {
if (this.debug) {
console.log(str);
}
};
/**
* Helper function to print a debug message. Debug
* messages are only printed if
* openpgp.config.debug is set to true. The calling
* Javascript context MUST define
* a "showMessages(text)" function. Line feeds ('\n')
* are automatically converted to HTML line feeds '<br/>'
* Different than print_debug because will call hexstrdump iff necessary.
* @param {String} str String of the debug message
* @return {String} An HTML tt entity containing a paragraph with a
* style attribute where the debug message is HTMLencoded in.
*/
this.print_debug_hexstr_dump = function(str,strToHex) {
if (this.debug) {
str = str + this.hexstrdump(strToHex);
console.log(str);
}
};
/**
* Helper function to print an error message.
* The calling Javascript context MUST define
* a "showMessages(text)" function. Line feeds ('\n')
* are automatically converted to HTML line feeds '<br/>'
* @param {String} str String of the error message
* @return {String} A HTML paragraph entity with a style attribute
* containing the HTML encoded error message
*/
this.print_error = function(str) {
if(this.debug)
throw str;
console.log(str);
};
/**
* Helper function to print an info message.
* The calling Javascript context MUST define
* a "showMessages(text)" function. Line feeds ('\n')
* are automatically converted to HTML line feeds '<br/>'.
* @param {String} str String of the info message
* @return {String} A HTML paragraph entity with a style attribute
* containing the HTML encoded info message
*/
this.print_info = function(str) {
if(this.debug)
console.log(str);
};
this.print_warning = function(str) {
console.log(str);
};
this.getLeftNBits = function (string, bitcount) {
var rest = bitcount % 8;
if (rest == 0)
return string.substring(0, bitcount / 8);
var bytes = (bitcount - rest) / 8 +1;
var result = string.substring(0, bytes);
return this.shiftRight(result, 8-rest); // +String.fromCharCode(string.charCodeAt(bytes -1) << (8-rest) & 0xFF);
};
/**
* Shifting a string to n bits right
* @param {String} value The string to shift
* @param {Integer} bitcount Amount of bits to shift (MUST be smaller
* than 9)
* @return {String} Resulting string.
*/
this.shiftRight = function(value, bitcount) {
var temp = util.str2bin(value);
if (bitcount % 8 != 0) {
for (var i = temp.length-1; i >= 0; i--) {
temp[i] >>= bitcount % 8;
if (i > 0)
temp[i] |= (temp[i - 1] << (8 - (bitcount % 8))) & 0xFF;
}
} else {
return value;
}
return util.bin2str(temp);
};
/**
* Return the algorithm type as string
* @return {String} String representing the message type
*/
this.get_hashAlgorithmString = function(algo) {
switch(algo) {
case 1:
return "MD5";
case 2:
return "SHA1";
case 3:
return "RIPEMD160";
case 8:
return "SHA256";
case 9:
return "SHA384";
case 10:
return "SHA512";
case 11:
return "SHA224";
}
return "unknown";
};
};
/**
* an instance that should be used.
*/
module.exports = new Util();
},{}],53:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("AES Rijndael cipher test with test vectors from ecb_tbl.txt", function() {
var openpgp = require('../../../');
var util = openpgp.util;
var result = new Array();
function test_aes(input, key, output) {
var aes = new openpgp.cipher.aes128(util.bin2str(key));
var result = util.bin2str(aes.encrypt(input));
return util.hexstrdump(result) == util.hexstrdump(util.bin2str(output));
};
var testvectors128 = [[[0x00,0x01,0x02,0x03,0x05,0x06,0x07,0x08,0x0A,0x0B,0x0C,0x0D,0x0F,0x10,0x11,0x12],[0x50,0x68,0x12,0xA4,0x5F,0x08,0xC8,0x89,0xB9,0x7F,0x59,0x80,0x03,0x8B,0x83,0x59],[0xD8,0xF5,0x32,0x53,0x82,0x89,0xEF,0x7D,0x06,0xB5,0x06,0xA4,0xFD,0x5B,0xE9,0xC9]],
[[0x14,0x15,0x16,0x17,0x19,0x1A,0x1B,0x1C,0x1E,0x1F,0x20,0x21,0x23,0x24,0x25,0x26],[0x5C,0x6D,0x71,0xCA,0x30,0xDE,0x8B,0x8B,0x00,0x54,0x99,0x84,0xD2,0xEC,0x7D,0x4B],[0x59,0xAB,0x30,0xF4,0xD4,0xEE,0x6E,0x4F,0xF9,0x90,0x7E,0xF6,0x5B,0x1F,0xB6,0x8C]],
[[0x28,0x29,0x2A,0x2B,0x2D,0x2E,0x2F,0x30,0x32,0x33,0x34,0x35,0x37,0x38,0x39,0x3A],[0x53,0xF3,0xF4,0xC6,0x4F,0x86,0x16,0xE4,0xE7,0xC5,0x61,0x99,0xF4,0x8F,0x21,0xF6],[0xBF,0x1E,0xD2,0xFC,0xB2,0xAF,0x3F,0xD4,0x14,0x43,0xB5,0x6D,0x85,0x02,0x5C,0xB1]],
[[0x3C,0x3D,0x3E,0x3F,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0x49,0x4B,0x4C,0x4D,0x4E],[0xA1,0xEB,0x65,0xA3,0x48,0x71,0x65,0xFB,0x0F,0x1C,0x27,0xFF,0x99,0x59,0xF7,0x03],[0x73,0x16,0x63,0x2D,0x5C,0x32,0x23,0x3E,0xDC,0xB0,0x78,0x05,0x60,0xEA,0xE8,0xB2]],
[[0x50,0x51,0x52,0x53,0x55,0x56,0x57,0x58,0x5A,0x5B,0x5C,0x5D,0x5F,0x60,0x61,0x62],[0x35,0x53,0xEC,0xF0,0xB1,0x73,0x95,0x58,0xB0,0x8E,0x35,0x0A,0x98,0xA3,0x9B,0xFA],[0x40,0x8C,0x07,0x3E,0x3E,0x25,0x38,0x07,0x2B,0x72,0x62,0x5E,0x68,0xB8,0x36,0x4B]],
[[0x64,0x65,0x66,0x67,0x69,0x6A,0x6B,0x6C,0x6E,0x6F,0x70,0x71,0x73,0x74,0x75,0x76],[0x67,0x42,0x99,0x69,0x49,0x0B,0x97,0x11,0xAE,0x2B,0x01,0xDC,0x49,0x7A,0xFD,0xE8],[0xE1,0xF9,0x4D,0xFA,0x77,0x65,0x97,0xBE,0xAC,0xA2,0x62,0xF2,0xF6,0x36,0x6F,0xEA]],
[[0x78,0x79,0x7A,0x7B,0x7D,0x7E,0x7F,0x80,0x82,0x83,0x84,0x85,0x87,0x88,0x89,0x8A],[0x93,0x38,0x5C,0x1F,0x2A,0xEC,0x8B,0xED,0x19,0x2F,0x5A,0x8E,0x16,0x1D,0xD5,0x08],[0xF2,0x9E,0x98,0x6C,0x6A,0x1C,0x27,0xD7,0xB2,0x9F,0xFD,0x7E,0xE9,0x2B,0x75,0xF1]],
[[0x8C,0x8D,0x8E,0x8F,0x91,0x92,0x93,0x94,0x96,0x97,0x98,0x99,0x9B,0x9C,0x9D,0x9E],[0xB5,0xBF,0x94,0x6B,0xE1,0x9B,0xEB,0x8D,0xB3,0x98,0x3B,0x5F,0x4C,0x6E,0x8D,0xDB],[0x13,0x1C,0x88,0x6A,0x57,0xF8,0xC2,0xE7,0x13,0xAB,0xA6,0x95,0x5E,0x2B,0x55,0xB5]],
[[0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA8,0xAA,0xAB,0xAC,0xAD,0xAF,0xB0,0xB1,0xB2],[0x41,0x32,0x1E,0xE1,0x0E,0x21,0xBD,0x90,0x72,0x27,0xC4,0x45,0x0F,0xF4,0x23,0x24],[0xD2,0xAB,0x76,0x62,0xDF,0x9B,0x8C,0x74,0x02,0x10,0xE5,0xEE,0xB6,0x1C,0x19,0x9D]],
[[0xB4,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,0xC5,0xC6],[0x00,0xA8,0x2F,0x59,0xC9,0x1C,0x84,0x86,0xD1,0x2C,0x0A,0x80,0x12,0x4F,0x60,0x89],[0x14,0xC1,0x05,0x54,0xB2,0x85,0x9C,0x48,0x4C,0xAB,0x58,0x69,0xBB,0xE7,0xC4,0x70]],
[[0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,0xCF,0xD0,0xD2,0xD3,0xD4,0xD5,0xD7,0xD8,0xD9,0xDA],[0x7C,0xE0,0xFD,0x07,0x67,0x54,0x69,0x1B,0x4B,0xBD,0x9F,0xAF,0x8A,0x13,0x72,0xFE],[0xDB,0x4D,0x49,0x8F,0x0A,0x49,0xCF,0x55,0x44,0x5D,0x50,0x2C,0x1F,0x9A,0xB3,0xB5]],
[[0xDC,0xDD,0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEB,0xEC,0xED,0xEE],[0x23,0x60,0x5A,0x82,0x43,0xD0,0x77,0x64,0x54,0x1B,0xC5,0xAD,0x35,0x5B,0x31,0x29],[0x6D,0x96,0xFE,0xF7,0xD6,0x65,0x90,0xA7,0x7A,0x77,0xBB,0x20,0x56,0x66,0x7F,0x7F]],
[[0xF0,0xF1,0xF2,0xF3,0xF5,0xF6,0xF7,0xF8,0xFA,0xFB,0xFC,0xFD,0xFE,0x01,0x00,0x02],[0x12,0xA8,0xCF,0xA2,0x3E,0xA7,0x64,0xFD,0x87,0x62,0x32,0xB4,0xE8,0x42,0xBC,0x44],[0x31,0x6F,0xB6,0x8E,0xDB,0xA7,0x36,0xC5,0x3E,0x78,0x47,0x7B,0xF9,0x13,0x72,0x5C]],
[[0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16],[0xBC,0xAF,0x32,0x41,0x5E,0x83,0x08,0xB3,0x72,0x3E,0x5F,0xDD,0x85,0x3C,0xCC,0x80],[0x69,0x36,0xF2,0xB9,0x3A,0xF8,0x39,0x7F,0xD3,0xA7,0x71,0xFC,0x01,0x1C,0x8C,0x37]],
[[0x2C,0x2D,0x2E,0x2F,0x31,0x32,0x33,0x34,0x36,0x37,0x38,0x39,0x3B,0x3C,0x3D,0x3E],[0x89,0xAF,0xAE,0x68,0x5D,0x80,0x1A,0xD7,0x47,0xAC,0xE9,0x1F,0xC4,0x9A,0xDD,0xE0],[0xF3,0xF9,0x2F,0x7A,0x9C,0x59,0x17,0x9C,0x1F,0xCC,0x2C,0x2B,0xA0,0xB0,0x82,0xCD]]];
var testvectors192 = [[[0x00,0x01,0x02,0x03,0x05,0x06,0x07,0x08,0x0A,0x0B,0x0C,0x0D,0x0F,0x10,0x11,0x12,0x14,0x15,0x16,0x17,0x19,0x1A,0x1B,0x1C],[0x2D,0x33,0xEE,0xF2,0xC0,0x43,0x0A,0x8A,0x9E,0xBF,0x45,0xE8,0x09,0xC4,0x0B,0xB6],[0xDF,0xF4,0x94,0x5E,0x03,0x36,0xDF,0x4C,0x1C,0x56,0xBC,0x70,0x0E,0xFF,0x83,0x7F]],
[[0x1E,0x1F,0x20,0x21,0x23,0x24,0x25,0x26,0x28,0x29,0x2A,0x2B,0x2D,0x2E,0x2F,0x30,0x32,0x33,0x34,0x35,0x37,0x38,0x39,0x3A],[0x6A,0xA3,0x75,0xD1,0xFA,0x15,0x5A,0x61,0xFB,0x72,0x35,0x3E,0x0A,0x5A,0x87,0x56],[0xB6,0xFD,0xDE,0xF4,0x75,0x27,0x65,0xE3,0x47,0xD5,0xD2,0xDC,0x19,0x6D,0x12,0x52]],
[[0x3C,0x3D,0x3E,0x3F,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0x49,0x4B,0x4C,0x4D,0x4E,0x50,0x51,0x52,0x53,0x55,0x56,0x57,0x58],[0xBC,0x37,0x36,0x51,0x8B,0x94,0x90,0xDC,0xB8,0xED,0x60,0xEB,0x26,0x75,0x8E,0xD4],[0xD2,0x36,0x84,0xE3,0xD9,0x63,0xB3,0xAF,0xCF,0x1A,0x11,0x4A,0xCA,0x90,0xCB,0xD6]],
[[0x5A,0x5B,0x5C,0x5D,0x5F,0x60,0x61,0x62,0x64,0x65,0x66,0x67,0x69,0x6A,0x6B,0x6C,0x6E,0x6F,0x70,0x71,0x73,0x74,0x75,0x76],[0xAA,0x21,0x44,0x02,0xB4,0x6C,0xFF,0xB9,0xF7,0x61,0xEC,0x11,0x26,0x3A,0x31,0x1E],[0x3A,0x7A,0xC0,0x27,0x75,0x3E,0x2A,0x18,0xC2,0xCE,0xAB,0x9E,0x17,0xC1,0x1F,0xD0]],
[[0x78,0x79,0x7A,0x7B,0x7D,0x7E,0x7F,0x80,0x82,0x83,0x84,0x85,0x87,0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x8F,0x91,0x92,0x93,0x94],[0x02,0xAE,0xA8,0x6E,0x57,0x2E,0xEA,0xB6,0x6B,0x2C,0x3A,0xF5,0xE9,0xA4,0x6F,0xD6],[0x8F,0x67,0x86,0xBD,0x00,0x75,0x28,0xBA,0x26,0x60,0x3C,0x16,0x01,0xCD,0xD0,0xD8]],
[[0x96,0x97,0x98,0x99,0x9B,0x9C,0x9D,0x9E,0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA8,0xAA,0xAB,0xAC,0xAD,0xAF,0xB0,0xB1,0xB2],[0xE2,0xAE,0xF6,0xAC,0xC3,0x3B,0x96,0x5C,0x4F,0xA1,0xF9,0x1C,0x75,0xFF,0x6F,0x36],[0xD1,0x7D,0x07,0x3B,0x01,0xE7,0x15,0x02,0xE2,0x8B,0x47,0xAB,0x55,0x11,0x68,0xB3]],
[[0xB4,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,0xC5,0xC6,0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,0xCF,0xD0],[0x06,0x59,0xDF,0x46,0x42,0x71,0x62,0xB9,0x43,0x48,0x65,0xDD,0x94,0x99,0xF9,0x1D],[0xA4,0x69,0xDA,0x51,0x71,0x19,0xFA,0xB9,0x58,0x76,0xF4,0x1D,0x06,0xD4,0x0F,0xFA]],
[[0xD2,0xD3,0xD4,0xD5,0xD7,0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEB,0xEC,0xED,0xEE],[0x49,0xA4,0x42,0x39,0xC7,0x48,0xFE,0xB4,0x56,0xF5,0x9C,0x27,0x6A,0x56,0x58,0xDF],[0x60,0x91,0xAA,0x3B,0x69,0x5C,0x11,0xF5,0xC0,0xB6,0xAD,0x26,0xD3,0xD8,0x62,0xFF]],
[[0xF0,0xF1,0xF2,0xF3,0xF5,0xF6,0xF7,0xF8,0xFA,0xFB,0xFC,0xFD,0xFE,0x01,0x00,0x02,0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C],[0x66,0x20,0x8F,0x6E,0x9D,0x04,0x52,0x5B,0xDE,0xDB,0x27,0x33,0xB6,0xA6,0xBE,0x37],[0x70,0xF9,0xE6,0x7F,0x9F,0x8D,0xF1,0x29,0x41,0x31,0x66,0x2D,0xC6,0xE6,0x93,0x64]],
[[0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16,0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20,0x22,0x23,0x24,0x25,0x27,0x28,0x29,0x2A],[0x33,0x93,0xF8,0xDF,0xC7,0x29,0xC9,0x7F,0x54,0x80,0xB9,0x50,0xBC,0x96,0x66,0xB0],[0xD1,0x54,0xDC,0xAF,0xAD,0x8B,0x20,0x7F,0xA5,0xCB,0xC9,0x5E,0x99,0x96,0xB5,0x59]],
[[0x2C,0x2D,0x2E,0x2F,0x31,0x32,0x33,0x34,0x36,0x37,0x38,0x39,0x3B,0x3C,0x3D,0x3E,0x40,0x41,0x42,0x43,0x45,0x46,0x47,0x48],[0x60,0x68,0x34,0xC8,0xCE,0x06,0x3F,0x32,0x34,0xCF,0x11,0x45,0x32,0x5D,0xBD,0x71],[0x49,0x34,0xD5,0x41,0xE8,0xB4,0x6F,0xA3,0x39,0xC8,0x05,0xA7,0xAE,0xB9,0xE5,0xDA]],
[[0x4A,0x4B,0x4C,0x4D,0x4F,0x50,0x51,0x52,0x54,0x55,0x56,0x57,0x59,0x5A,0x5B,0x5C,0x5E,0x5F,0x60,0x61,0x63,0x64,0x65,0x66],[0xFE,0xC1,0xC0,0x4F,0x52,0x9B,0xBD,0x17,0xD8,0xCE,0xCF,0xCC,0x47,0x18,0xB1,0x7F],[0x62,0x56,0x4C,0x73,0x8F,0x3E,0xFE,0x18,0x6E,0x1A,0x12,0x7A,0x0C,0x4D,0x3C,0x61]],
[[0x68,0x69,0x6A,0x6B,0x6D,0x6E,0x6F,0x70,0x72,0x73,0x74,0x75,0x77,0x78,0x79,0x7A,0x7C,0x7D,0x7E,0x7F,0x81,0x82,0x83,0x84],[0x32,0xDF,0x99,0xB4,0x31,0xED,0x5D,0xC5,0xAC,0xF8,0xCA,0xF6,0xDC,0x6C,0xE4,0x75],[0x07,0x80,0x5A,0xA0,0x43,0x98,0x6E,0xB2,0x36,0x93,0xE2,0x3B,0xEF,0x8F,0x34,0x38]],
[[0x86,0x87,0x88,0x89,0x8B,0x8C,0x8D,0x8E,0x90,0x91,0x92,0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C,0x9D,0x9F,0xA0,0xA1,0xA2],[0x7F,0xDC,0x2B,0x74,0x6F,0x3F,0x66,0x52,0x96,0x94,0x3B,0x83,0x71,0x0D,0x1F,0x82],[0xDF,0x0B,0x49,0x31,0x03,0x8B,0xAD,0xE8,0x48,0xDE,0xE3,0xB4,0xB8,0x5A,0xA4,0x4B]],
[[0xA4,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,0xB1,0xB3,0xB4,0xB5,0xB6,0xB8,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0],[0x8F,0xBA,0x15,0x10,0xA3,0xC5,0xB8,0x7E,0x2E,0xAA,0x3F,0x7A,0x91,0x45,0x5C,0xA2],[0x59,0x2D,0x5F,0xDE,0xD7,0x65,0x82,0xE4,0x14,0x3C,0x65,0x09,0x93,0x09,0x47,0x7C]]];
var testvectors256 = [[[0x00,0x01,0x02,0x03,0x05,0x06,0x07,0x08,0x0A,0x0B,0x0C,0x0D,0x0F,0x10,0x11,0x12,0x14,0x15,0x16,0x17,0x19,0x1A,0x1B,0x1C,0x1E,0x1F,0x20,0x21,0x23,0x24,0x25,0x26],[0x83,0x4E,0xAD,0xFC,0xCA,0xC7,0xE1,0xB3,0x06,0x64,0xB1,0xAB,0xA4,0x48,0x15,0xAB],[0x19,0x46,0xDA,0xBF,0x6A,0x03,0xA2,0xA2,0xC3,0xD0,0xB0,0x50,0x80,0xAE,0xD6,0xFC]],
[[0x28,0x29,0x2A,0x2B,0x2D,0x2E,0x2F,0x30,0x32,0x33,0x34,0x35,0x37,0x38,0x39,0x3A,0x3C,0x3D,0x3E,0x3F,0x41,0x42,0x43,0x44,0x46,0x47,0x48,0x49,0x4B,0x4C,0x4D,0x4E],[0xD9,0xDC,0x4D,0xBA,0x30,0x21,0xB0,0x5D,0x67,0xC0,0x51,0x8F,0x72,0xB6,0x2B,0xF1],[0x5E,0xD3,0x01,0xD7,0x47,0xD3,0xCC,0x71,0x54,0x45,0xEB,0xDE,0xC6,0x2F,0x2F,0xB4]],
[[0x50,0x51,0x52,0x53,0x55,0x56,0x57,0x58,0x5A,0x5B,0x5C,0x5D,0x5F,0x60,0x61,0x62,0x64,0x65,0x66,0x67,0x69,0x6A,0x6B,0x6C,0x6E,0x6F,0x70,0x71,0x73,0x74,0x75,0x76],[0xA2,0x91,0xD8,0x63,0x01,0xA4,0xA7,0x39,0xF7,0x39,0x21,0x73,0xAA,0x3C,0x60,0x4C],[0x65,0x85,0xC8,0xF4,0x3D,0x13,0xA6,0xBE,0xAB,0x64,0x19,0xFC,0x59,0x35,0xB9,0xD0]],
[[0x78,0x79,0x7A,0x7B,0x7D,0x7E,0x7F,0x80,0x82,0x83,0x84,0x85,0x87,0x88,0x89,0x8A,0x8C,0x8D,0x8E,0x8F,0x91,0x92,0x93,0x94,0x96,0x97,0x98,0x99,0x9B,0x9C,0x9D,0x9E],[0x42,0x64,0xB2,0x69,0x64,0x98,0xDE,0x4D,0xF7,0x97,0x88,0xA9,0xF8,0x3E,0x93,0x90],[0x2A,0x5B,0x56,0xA5,0x96,0x68,0x0F,0xCC,0x0E,0x05,0xF5,0xE0,0xF1,0x51,0xEC,0xAE]],
[[0xA0,0xA1,0xA2,0xA3,0xA5,0xA6,0xA7,0xA8,0xAA,0xAB,0xAC,0xAD,0xAF,0xB0,0xB1,0xB2,0xB4,0xB5,0xB6,0xB7,0xB9,0xBA,0xBB,0xBC,0xBE,0xBF,0xC0,0xC1,0xC3,0xC4,0xC5,0xC6],[0xEE,0x99,0x32,0xB3,0x72,0x18,0x04,0xD5,0xA8,0x3E,0xF5,0x94,0x92,0x45,0xB6,0xF6],[0xF5,0xD6,0xFF,0x41,0x4F,0xD2,0xC6,0x18,0x14,0x94,0xD2,0x0C,0x37,0xF2,0xB8,0xC4]],
[[0xC8,0xC9,0xCA,0xCB,0xCD,0xCE,0xCF,0xD0,0xD2,0xD3,0xD4,0xD5,0xD7,0xD8,0xD9,0xDA,0xDC,0xDD,0xDE,0xDF,0xE1,0xE2,0xE3,0xE4,0xE6,0xE7,0xE8,0xE9,0xEB,0xEC,0xED,0xEE],[0xE6,0x24,0x8F,0x55,0xC5,0xFD,0xCB,0xCA,0x9C,0xBB,0xB0,0x1C,0x88,0xA2,0xEA,0x77],[0x85,0x39,0x9C,0x01,0xF5,0x9F,0xFF,0xB5,0x20,0x4F,0x19,0xF8,0x48,0x2F,0x00,0xB8]],
[[0xF0,0xF1,0xF2,0xF3,0xF5,0xF6,0xF7,0xF8,0xFA,0xFB,0xFC,0xFD,0xFE,0x01,0x00,0x02,0x04,0x05,0x06,0x07,0x09,0x0A,0x0B,0x0C,0x0E,0x0F,0x10,0x11,0x13,0x14,0x15,0x16],[0xB8,0x35,0x8E,0x41,0xB9,0xDF,0xF6,0x5F,0xD4,0x61,0xD5,0x5A,0x99,0x26,0x62,0x47],[0x92,0x09,0x7B,0x4C,0x88,0xA0,0x41,0xDD,0xF9,0x81,0x44,0xBC,0x8D,0x22,0xE8,0xE7]],
[[0x18,0x19,0x1A,0x1B,0x1D,0x1E,0x1F,0x20,0x22,0x23,0x24,0x25,0x27,0x28,0x29,0x2A,0x2C,0x2D,0x2E,0x2F,0x31,0x32,0x33,0x34,0x36,0x37,0x38,0x39,0x3B,0x3C,0x3D,0x3E],[0xF0,0xE2,0xD7,0x22,0x60,0xAF,0x58,0xE2,0x1E,0x01,0x5A,0xB3,0xA4,0xC0,0xD9,0x06],[0x89,0xBD,0x5B,0x73,0xB3,0x56,0xAB,0x41,0x2A,0xEF,0x9F,0x76,0xCE,0xA2,0xD6,0x5C]],
[[0x40,0x41,0x42,0x43,0x45,0x46,0x47,0x48,0x4A,0x4B,0x4C,0x4D,0x4F,0x50,0x51,0x52,0x54,0x55,0x56,0x57,0x59,0x5A,0x5B,0x5C,0x5E,0x5F,0x60,0x61,0x63,0x64,0x65,0x66],[0x47,0x5B,0x8B,0x82,0x3C,0xE8,0x89,0x3D,0xB3,0xC4,0x4A,0x9F,0x2A,0x37,0x9F,0xF7],[0x25,0x36,0x96,0x90,0x93,0xC5,0x5F,0xF9,0x45,0x46,0x92,0xF2,0xFA,0xC2,0xF5,0x30]],
[[0x68,0x69,0x6A,0x6B,0x6D,0x6E,0x6F,0x70,0x72,0x73,0x74,0x75,0x77,0x78,0x79,0x7A,0x7C,0x7D,0x7E,0x7F,0x81,0x82,0x83,0x84,0x86,0x87,0x88,0x89,0x8B,0x8C,0x8D,0x8E],[0x68,0x8F,0x52,0x81,0x94,0x58,0x12,0x86,0x2F,0x5F,0x30,0x76,0xCF,0x80,0x41,0x2F],[0x07,0xFC,0x76,0xA8,0x72,0x84,0x3F,0x3F,0x6E,0x00,0x81,0xEE,0x93,0x96,0xD6,0x37]],
[[0x90,0x91,0x92,0x93,0x95,0x96,0x97,0x98,0x9A,0x9B,0x9C,0x9D,0x9F,0xA0,0xA1,0xA2,0xA4,0xA5,0xA6,0xA7,0xA9,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,0xB1,0xB3,0xB4,0xB5,0xB6],[0x08,0xD1,0xD2,0xBC,0x75,0x0A,0xF5,0x53,0x36,0x5D,0x35,0xE7,0x5A,0xFA,0xCE,0xAA],[0xE3,0x8B,0xA8,0xEC,0x2A,0xA7,0x41,0x35,0x8D,0xCC,0x93,0xE8,0xF1,0x41,0xC4,0x91]],
[[0xB8,0xB9,0xBA,0xBB,0xBD,0xBE,0xBF,0xC0,0xC2,0xC3,0xC4,0xC5,0xC7,0xC8,0xC9,0xCA,0xCC,0xCD,0xCE,0xCF,0xD1,0xD2,0xD3,0xD4,0xD6,0xD7,0xD8,0xD9,0xDB,0xDC,0xDD,0xDE],[0x87,0x07,0x12,0x1F,0x47,0xCC,0x3E,0xFC,0xEC,0xA5,0xF9,0xA8,0x47,0x49,0x50,0xA1],[0xD0,0x28,0xEE,0x23,0xE4,0xA8,0x90,0x75,0xD0,0xB0,0x3E,0x86,0x8D,0x7D,0x3A,0x42]],
[[0xE0,0xE1,0xE2,0xE3,0xE5,0xE6,0xE7,0xE8,0xEA,0xEB,0xEC,0xED,0xEF,0xF0,0xF1,0xF2,0xF4,0xF5,0xF6,0xF7,0xF9,0xFA,0xFB,0xFC,0xFE,0xFE,0x01,0x01,0x03,0x04,0x05,0x06],[0xE5,0x1A,0xA0,0xB1,0x35,0xDB,0xA5,0x66,0x93,0x9C,0x3B,0x63,0x59,0xA9,0x80,0xC5],[0x8C,0xD9,0x42,0x3D,0xFC,0x45,0x9E,0x54,0x71,0x55,0xC5,0xD1,0xD5,0x22,0xE5,0x40]],
[[0x08,0x09,0x0A,0x0B,0x0D,0x0E,0x0F,0x10,0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1A,0x1C,0x1D,0x1E,0x1F,0x21,0x22,0x23,0x24,0x26,0x27,0x28,0x29,0x2B,0x2C,0x2D,0x2E],[0x06,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x21],[0x08,0x0E,0x95,0x17,0xEB,0x16,0x77,0x71,0x9A,0xCF,0x72,0x80,0x86,0x04,0x0A,0xE3]],
[[0x30,0x31,0x32,0x33,0x35,0x36,0x37,0x38,0x3A,0x3B,0x3C,0x3D,0x3F,0x40,0x41,0x42,0x44,0x45,0x46,0x47,0x49,0x4A,0x4B,0x4C,0x4E,0x4F,0x50,0x51,0x53,0x54,0x55,0x56],[0x72,0x61,0x65,0xC1,0x72,0x3F,0xBC,0xF6,0xC0,0x26,0xD7,0xD0,0x0B,0x09,0x10,0x27],[0x7C,0x17,0x00,0x21,0x1A,0x39,0x91,0xFC,0x0E,0xCD,0xED,0x0A,0xB3,0xE5,0x76,0xB0]]];
var res = true;
var j = 0;
for (var i = 0; i < testvectors128.length; i++) {
var res2 = test_aes(testvectors128[i][1],testvectors128[i][0],testvectors128[i][2]);
res &= res2;
if (!res2) {
result[j] = new unit.result("Testing 128 bit key vector with block "+
util.hexidump(testvectors128[i][1])+
" and key "+util.hexidump(testvectors128[i][0])+
" should be "+util.hexidump(testvectors128[i][2]),
false);
j++;
}
}
if (res) {
result[j] = new unit.result("128 bit key test vectors completed.",true)
j++;
}
res = true;
for (var i = 0; i < testvectors192.length; i++) {
var res2 = test_aes(testvectors192[i][1],testvectors192[i][0],testvectors192[i][2]);
res &= res2;
if (!res2) {
result[j] = new unit.result("Testing 192 bit key vector with block "+
util.hexidump(testvectors192[i][1])+
" and key "+util.hexidump(testvectors192[i][0])+
" should be "+util.hexidump(testvectors192[i][2]),
false);
j++;
}
}
if (res) {
result[j] = new unit.result("192 bit key test vectors completed.",true)
j++;
}
res = true;
for (var i = 0; i < testvectors256.length; i++) {
var res2 = test_aes(testvectors256[i][1],testvectors256[i][0],testvectors256[i][2]);
res &= res2;
if (!res2) {
result[j] = new unit.result("Testing 256 bit key vector with block "+
util.hexidump(testvectors256[i][1])+
" and key "+util.hexidump(testvectors256[i][0])+
" should be "+util.hexidump(testvectors256[i][2]),
false);
j++;
}
}
if (res) {
result[j] = new unit.result("256 bit key test vectors completed.", true)
j++;
}
return result;
});
},{"../../../":28,"../../unit.js":63}],54:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("Blowfish cipher test with test vectors from http://www.schneier.com/code/vectors.txt", function() {
var openpgp = require('../../../'),
util = openpgp.util,
BFencrypt = openpgp.cipher.blowfish;
var result = [];
function test_bf(input, key, output) {
var blowfish = new openpgp.cipher.blowfish(util.bin2str(key));
var result = util.bin2str(blowfish.encrypt(input));
return (util.hexstrdump(result) == util.hexstrdump(util.bin2str(output)));
}
var testvectors = [[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x4E,0xF9,0x97,0x45,0x61,0x98,0xDD,0x78]],
[[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF],[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF],[0x51,0x86,0x6F,0xD5,0xB8,0x5E,0xCB,0x8A]],
[[0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01],[0x7D,0x85,0x6F,0x9A,0x61,0x30,0x63,0xF2]],
[[0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11],[0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11],[0x24,0x66,0xDD,0x87,0x8B,0x96,0x3C,0x9D]],
[[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11],[0x61,0xF9,0xC3,0x80,0x22,0x81,0xB0,0x96]],
[[0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11],[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0x7D,0x0C,0xC6,0x30,0xAF,0xDA,0x1E,0xC7]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x4E,0xF9,0x97,0x45,0x61,0x98,0xDD,0x78]],
[[0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10],[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0x0A,0xCE,0xAB,0x0F,0xC6,0xA0,0xA2,0x8D]],
[[0x7C,0xA1,0x10,0x45,0x4A,0x1A,0x6E,0x57],[0x01,0xA1,0xD6,0xD0,0x39,0x77,0x67,0x42],[0x59,0xC6,0x82,0x45,0xEB,0x05,0x28,0x2B]],
[[0x01,0x31,0xD9,0x61,0x9D,0xC1,0x37,0x6E],[0x5C,0xD5,0x4C,0xA8,0x3D,0xEF,0x57,0xDA],[0xB1,0xB8,0xCC,0x0B,0x25,0x0F,0x09,0xA0]],
[[0x07,0xA1,0x13,0x3E,0x4A,0x0B,0x26,0x86],[0x02,0x48,0xD4,0x38,0x06,0xF6,0x71,0x72],[0x17,0x30,0xE5,0x77,0x8B,0xEA,0x1D,0xA4]],
[[0x38,0x49,0x67,0x4C,0x26,0x02,0x31,0x9E],[0x51,0x45,0x4B,0x58,0x2D,0xDF,0x44,0x0A],[0xA2,0x5E,0x78,0x56,0xCF,0x26,0x51,0xEB]],
[[0x04,0xB9,0x15,0xBA,0x43,0xFE,0xB5,0xB6],[0x42,0xFD,0x44,0x30,0x59,0x57,0x7F,0xA2],[0x35,0x38,0x82,0xB1,0x09,0xCE,0x8F,0x1A]],
[[0x01,0x13,0xB9,0x70,0xFD,0x34,0xF2,0xCE],[0x05,0x9B,0x5E,0x08,0x51,0xCF,0x14,0x3A],[0x48,0xF4,0xD0,0x88,0x4C,0x37,0x99,0x18]],
[[0x01,0x70,0xF1,0x75,0x46,0x8F,0xB5,0xE6],[0x07,0x56,0xD8,0xE0,0x77,0x47,0x61,0xD2],[0x43,0x21,0x93,0xB7,0x89,0x51,0xFC,0x98]],
[[0x43,0x29,0x7F,0xAD,0x38,0xE3,0x73,0xFE],[0x76,0x25,0x14,0xB8,0x29,0xBF,0x48,0x6A],[0x13,0xF0,0x41,0x54,0xD6,0x9D,0x1A,0xE5]],
[[0x07,0xA7,0x13,0x70,0x45,0xDA,0x2A,0x16],[0x3B,0xDD,0x11,0x90,0x49,0x37,0x28,0x02],[0x2E,0xED,0xDA,0x93,0xFF,0xD3,0x9C,0x79]],
[[0x04,0x68,0x91,0x04,0xC2,0xFD,0x3B,0x2F],[0x26,0x95,0x5F,0x68,0x35,0xAF,0x60,0x9A],[0xD8,0x87,0xE0,0x39,0x3C,0x2D,0xA6,0xE3]],
[[0x37,0xD0,0x6B,0xB5,0x16,0xCB,0x75,0x46],[0x16,0x4D,0x5E,0x40,0x4F,0x27,0x52,0x32],[0x5F,0x99,0xD0,0x4F,0x5B,0x16,0x39,0x69]],
[[0x1F,0x08,0x26,0x0D,0x1A,0xC2,0x46,0x5E],[0x6B,0x05,0x6E,0x18,0x75,0x9F,0x5C,0xCA],[0x4A,0x05,0x7A,0x3B,0x24,0xD3,0x97,0x7B]],
[[0x58,0x40,0x23,0x64,0x1A,0xBA,0x61,0x76],[0x00,0x4B,0xD6,0xEF,0x09,0x17,0x60,0x62],[0x45,0x20,0x31,0xC1,0xE4,0xFA,0xDA,0x8E]],
[[0x02,0x58,0x16,0x16,0x46,0x29,0xB0,0x07],[0x48,0x0D,0x39,0x00,0x6E,0xE7,0x62,0xF2],[0x75,0x55,0xAE,0x39,0xF5,0x9B,0x87,0xBD]],
[[0x49,0x79,0x3E,0xBC,0x79,0xB3,0x25,0x8F],[0x43,0x75,0x40,0xC8,0x69,0x8F,0x3C,0xFA],[0x53,0xC5,0x5F,0x9C,0xB4,0x9F,0xC0,0x19]],
[[0x4F,0xB0,0x5E,0x15,0x15,0xAB,0x73,0xA7],[0x07,0x2D,0x43,0xA0,0x77,0x07,0x52,0x92],[0x7A,0x8E,0x7B,0xFA,0x93,0x7E,0x89,0xA3]],
[[0x49,0xE9,0x5D,0x6D,0x4C,0xA2,0x29,0xBF],[0x02,0xFE,0x55,0x77,0x81,0x17,0xF1,0x2A],[0xCF,0x9C,0x5D,0x7A,0x49,0x86,0xAD,0xB5]],
[[0x01,0x83,0x10,0xDC,0x40,0x9B,0x26,0xD6],[0x1D,0x9D,0x5C,0x50,0x18,0xF7,0x28,0xC2],[0xD1,0xAB,0xB2,0x90,0x65,0x8B,0xC7,0x78]],
[[0x1C,0x58,0x7F,0x1C,0x13,0x92,0x4F,0xEF],[0x30,0x55,0x32,0x28,0x6D,0x6F,0x29,0x5A],[0x55,0xCB,0x37,0x74,0xD1,0x3E,0xF2,0x01]],
[[0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01],[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0xFA,0x34,0xEC,0x48,0x47,0xB2,0x68,0xB2]],
[[0x1F,0x1F,0x1F,0x1F,0x0E,0x0E,0x0E,0x0E],[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0xA7,0x90,0x79,0x51,0x08,0xEA,0x3C,0xAE]],
[[0xE0,0xFE,0xE0,0xFE,0xF1,0xFE,0xF1,0xFE],[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0xC3,0x9E,0x07,0x2D,0x9F,0xAC,0x63,0x1D]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF],[0x01,0x49,0x33,0xE0,0xCD,0xAF,0xF6,0xE4]],
[[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF],[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0xF2,0x1E,0x9A,0x77,0xB7,0x1C,0x49,0xBC]],
[[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x24,0x59,0x46,0x88,0x57,0x54,0x36,0x9A]],
[[0xFE,0xDC,0xBA,0x98,0x76,0x54,0x32,0x10],[0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF],[0x6B,0x5C,0x5A,0x9C,0x5D,0x9E,0x0A,0x5A]]];
var res = true;
var j = 0;
for (var i = 0; i < testvectors.length; i++) {
var res2 = test_bf(testvectors[i][1],testvectors[i][0],testvectors[i][2]);
res &= res2;
if (!res2) {
result[j] = new unit.result("Testing vector "+i+" with block "+
util.hexidump(testvectors[i][0])+
" and key "+util.hexidump(testvectors[i][1])+
" should be "+util.hexidump(testvectors[i][2]), false);
j++;
}
}
if (res) {
result[j] = new unit.result("34 test vectors completed ", true);
}
return result;
});
},{"../../../":28,"../../unit.js":63}],55:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("CAST-128 cipher test with test vectors from RFC2144", function() {
var openpgp = require('../../../'),
util = openpgp.util;
var result = [];
function test_cast(input, key, output) {
var cast5 = new openpgp.cipher.cast5(util.bin2str(key));
var result = util.bin2str(cast5.encrypt(input));
return util.hexstrdump(result) == util.hexstrdump(util.bin2str(output));
}
var testvectors = [[[0x01,0x23,0x45,0x67,0x12,0x34,0x56,0x78,0x23,0x45,0x67,0x89,0x34,0x56,0x78,0x9A],[0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF],[0x23,0x8B,0x4F,0xE5,0x84,0x7E,0x44,0xB2]]];
for (var i = 0; i < testvectors.length; i++) {
result[i] = new unit.result("Testing vector with block "+
util.hexidump(testvectors[i][0])+
" and key "+util.hexidump(testvectors[i][1])+
" should be "+util.hexidump(testvectors[i][2]),
test_cast(testvectors[i][1],testvectors[i][0],testvectors[i][2]));
}
return result;
});
},{"../../../":28,"../../unit.js":63}],56:[function(require,module,exports){
var unit = require('../../unit.js');
//TODO SC 8/2013 -- This test is failing the first test because of truncating the last 0x00, all other tests are passing. Should investigate.
unit.register("TripleDES (EDE) cipher test with test vectors from http://csrc.nist.gov/publications/nistpubs/800-20/800-20.pdf", function() {
var openpgp = require('../../../'),
util = openpgp.util;
var result = [];
var key = util.bin2str([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]);
var testvectors = [[[0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00]],
[[0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0xDD,0x7F,0x12,0x1C,0xA5,0x01,0x56,0x19]],
[[0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x2E,0x86,0x53,0x10,0x4F,0x38,0x34,0xEA]],
[[0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x4B,0xD3,0x88,0xFF,0x6C,0xD8,0x1D,0x4F]],
[[0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x20,0xB9,0xE7,0x67,0xB2,0xFB,0x14,0x56]],
[[0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x55,0x57,0x93,0x80,0xD7,0x71,0x38,0xEF]],
[[0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x6C,0xC5,0xDE,0xFA,0xAF,0x04,0x51,0x2F]],
[[0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00],[0x0D,0x9F,0x27,0x9B,0xA5,0xD8,0x72,0x60]],
[[0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00],[0xD9,0x03,0x1B,0x02,0x71,0xBD,0x5A,0x0A]],
[[0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00],[0x42,0x42,0x50,0xB3,0x7C,0x3D,0xD9,0x51]],
[[0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00],[0xB8,0x06,0x1B,0x7E,0xCD,0x9A,0x21,0xE5]],
[[0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00],[0xF1,0x5D,0x0F,0x28,0x6B,0x65,0xBD,0x28]],
[[0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00],[0xAD,0xD0,0xCC,0x8D,0x6E,0x5D,0xEB,0xA1]],
[[0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00],[0xE6,0xD5,0xF8,0x27,0x52,0xAD,0x63,0xD1]],
[[0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00],[0xEC,0xBF,0xE3,0xBD,0x3F,0x59,0x1A,0x5E]],
[[0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00],[0xF3,0x56,0x83,0x43,0x79,0xD1,0x65,0xCD]],
[[0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00],[0x2B,0x9F,0x98,0x2F,0x20,0x03,0x7F,0xA9]],
[[0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00],[0x88,0x9D,0xE0,0x68,0xA1,0x6F,0x0B,0xE6]],
[[0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00],[0xE1,0x9E,0x27,0x5D,0x84,0x6A,0x12,0x98]],
[[0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00],[0x32,0x9A,0x8E,0xD5,0x23,0xD7,0x1A,0xEC]],
[[0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00],[0xE7,0xFC,0xE2,0x25,0x57,0xD2,0x3C,0x97]],
[[0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00],[0x12,0xA9,0xF5,0x81,0x7F,0xF2,0xD6,0x5D]]];
var res = true;
var j = 0;
for (var i = 0; i < testvectors.length; i++) {
var des = new openpgp.cipher.des(key);
var encr = util.bin2str(des.encrypt(testvectors[i][0], key));
var res2 = encr == util.bin2str(testvectors[i][1]);
res &= res2;
if (!res2) {
result[j] = new unit.result("Testing vector with block " +
util.hexidump(testvectors[i][0]) +
" and key " + util.hexstrdump(key) +
" should be " + util.hexidump(testvectors[i][1]) + " != " +
util.hexidump(encr),
false);
j++;
}
}
if (res) {
result[j] = new unit.result("All 3DES EDE test vectors completed", true);
}
return result;
});
},{"../../../":28,"../../unit.js":63}],57:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("Twofish test with test vectors from http://www.schneier.com/code/ecb_ival.txt", function() {
var openpgp = require('../../../'),
util = openpgp.util;
function TFencrypt(block, key) {
var tf = new openpgp.cipher.twofish(key);
return tf.encrypt(block);
}
var result = [];
var start = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var start_short = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var testvectors = [[0x57,0xFF,0x73,0x9D,0x4D,0xC9,0x2C,0x1B,0xD7,0xFC,0x01,0x70,0x0C,0xC8,0x21,0x6F],
[0xD4,0x3B,0xB7,0x55,0x6E,0xA3,0x2E,0x46,0xF2,0xA2,0x82,0xB7,0xD4,0x5B,0x4E,0x0D],
[0x90,0xAF,0xE9,0x1B,0xB2,0x88,0x54,0x4F,0x2C,0x32,0xDC,0x23,0x9B,0x26,0x35,0xE6],
[0x6C,0xB4,0x56,0x1C,0x40,0xBF,0x0A,0x97,0x05,0x93,0x1C,0xB6,0xD4,0x08,0xE7,0xFA],
[0x30,0x59,0xD6,0xD6,0x17,0x53,0xB9,0x58,0xD9,0x2F,0x47,0x81,0xC8,0x64,0x0E,0x58],
[0xE6,0x94,0x65,0x77,0x05,0x05,0xD7,0xF8,0x0E,0xF6,0x8C,0xA3,0x8A,0xB3,0xA3,0xD6],
[0x5A,0xB6,0x7A,0x5F,0x85,0x39,0xA4,0xA5,0xFD,0x9F,0x03,0x73,0xBA,0x46,0x34,0x66],
[0xDC,0x09,0x6B,0xCD,0x99,0xFC,0x72,0xF7,0x99,0x36,0xD4,0xC7,0x48,0xE7,0x5A,0xF7],
[0xC5,0xA3,0xE7,0xCE,0xE0,0xF1,0xB7,0x26,0x05,0x28,0xA6,0x8F,0xB4,0xEA,0x05,0xF2],
[0x43,0xD5,0xCE,0xC3,0x27,0xB2,0x4A,0xB9,0x0A,0xD3,0x4A,0x79,0xD0,0x46,0x91,0x51]];
testvectors[47] = [0x43,0x10,0x58,0xF4,0xDB,0xC7,0xF7,0x34,0xDA,0x4F,0x02,0xF0,0x4C,0xC4,0xF4,0x59];
testvectors[48] = [0x37,0xFE,0x26,0xFF,0x1C,0xF6,0x61,0x75,0xF5,0xDD,0xF4,0xC3,0x3B,0x97,0xA2,0x05];
var res = true;
var j = 0;
for (var i = 0; i < 49; i++) {
var res2 = false;
var blk, key, ct;
if (i === 0) {
blk = start_short;
key = util.bin2str(start);
ct = testvectors[0];
res2 = (util.bin2str(TFencrypt(blk,key)) == util.bin2str(ct));
} else if (i === 1) {
blk = testvectors[0];
key = util.bin2str(start);
ct = testvectors[1];
res2 = (util.bin2str(TFencrypt(blk,key)) == util.bin2str(ct));
} else if (i === 2) {
blk = testvectors[i-1];
key = util.bin2str(testvectors[i-2].concat(start_short));
ct = testvectors[i];
res2 = (util.bin2str(TFencrypt(blk,key)) == util.bin2str(ct));
} else if (i < 10 || i > 46) {
blk = testvectors[i-1];
key = util.bin2str(testvectors[i-2].concat(testvectors[i-3]));
ct = testvectors[i];
res2 = (util.bin2str(TFencrypt(blk,key)) == util.bin2str(ct));
} else {
testvectors[i] = TFencrypt(testvectors[i-1],util.bin2str(testvectors[i-2].concat(testvectors[i-3])));
res2 = true;
}
res &= res2;
if (!res2) {
result[j] = new unit.result("Testing vector with block "+util.hexidump(blk)+" with key "+ util.hexstrdump(key) +" should be "+util.hexidump(ct)+" but is "+util.hexidump(TFencrypt(blk,key)), false);
j++;
}
}
if (res) {
result[j] = new unit.result("49 test vectors completed", true);
}
return result;
});
},{"../../../":28,"../../unit.js":63}],58:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("MD5 test with test vectors from RFC 1321", function() {
var openpgp = require('../../../'),
util = openpgp.util,
MD5 = openpgp.hash.md5;
var result = new Array();
result[0] = new unit.result("MD5 (\"\") = d41d8cd98f00b204e9800998ecf8427e",
util.hexstrdump(MD5("")) == "d41d8cd98f00b204e9800998ecf8427e");
result[1] = new unit.result("MD5 (\"a\") = 0cc175b9c0f1b6a831c399e269772661",
util.hexstrdump(MD5 ("abc")) == "900150983cd24fb0d6963f7d28e17f72");
result[2] = new unit.result("MD5 (\"message digest\") = f96b697d7cb7938d525a2f31aaf161d0",
util.hexstrdump(MD5 ("message digest")) == "f96b697d7cb7938d525a2f31aaf161d0");
result[3] = new unit.result("MD5 (\"abcdefghijklmnopqrstuvwxyz\") = c3fcd3d76192e4007dfb496cca67e13b",
util.hexstrdump(MD5 ("abcdefghijklmnopqrstuvwxyz")) == "c3fcd3d76192e4007dfb496cca67e13b");
result[4] = new unit.result("MD5 (\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\") = d174ab98d277d9f5a5611c2c9f419d9f",
util.hexstrdump(MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")) == "d174ab98d277d9f5a5611c2c9f419d9f");
result[5] = new unit.result("MD5 (\"12345678901234567890123456789012345678901234567890123456789012345678901234567890\") = 57edf4a22be3c955ac49da2e2107b67a",
util.hexstrdump(MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890")) == "57edf4a22be3c955ac49da2e2107b67a");
return result;
});
},{"../../../":28,"../../unit.js":63}],59:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("RIPE-MD 160 bits test with test vectors from http://homes.esat.kuleuven.be/~bosselae/ripemd160.html", function() {
var openpgp = require('../../../'),
util = openpgp.util,
RMDstring = openpgp.hash.ripemd;
var result = new Array();
result[0] = new unit.result("RMDstring (\"\") = 9c1185a5c5e9fc54612808977ee8f548b2258d31",
util.hexstrdump(RMDstring("")) == "9c1185a5c5e9fc54612808977ee8f548b2258d31");
result[1] = new unit.result("RMDstring (\"a\") = 0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
util.hexstrdump(RMDstring("a")) == "0bdc9d2d256b3ee9daae347be6f4dc835a467ffe");
result[2] = new unit.result("RMDstring (\"abc\") = 8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
util.hexstrdump(RMDstring("abc")) == "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc");
result[3] = new unit.result("RMDstring (\"message digest\") = 5d0689ef49d2fae572b881b123a85ffa21595f36",
util.hexstrdump(RMDstring("message digest")) == "5d0689ef49d2fae572b881b123a85ffa21595f36");
return result;
});
},{"../../../":28,"../../unit.js":63}],60:[function(require,module,exports){
var unit = require('../../unit.js');
unit.register("SHA* test with test vectors from NIST FIPS 180-2", function() {
var openpgp = require('../../../'),
util = openpgp.util,
hash = openpgp.hash;
var result = new Array();
result[0] = new unit.result("SHA1 - a9993e364706816aba3e25717850c26c9cd0d89d = hash.sha1(\"abc\") ",
"a9993e364706816aba3e25717850c26c9cd0d89d" == util.hexstrdump(hash.sha1("abc")));
result[1] = new unit.result("SHA1 - 84983e441c3bd26ebaae4aa1f95129e5e54670f1 = hash.sha1(\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\") ",
"84983e441c3bd26ebaae4aa1f95129e5e54670f1" == util.hexstrdump(hash.sha1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
result[2] = new unit.result("SHA224 - 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7 = hash.sha224(\"abc\") ",
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" == util.hexstrdump(hash.sha224("abc")));
result[3] = new unit.result("SHA224 - 75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525 = hash.sha224(\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\") ",
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525" == util.hexstrdump(hash.sha224("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
result[4] = new unit.result("SHA256 - ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad = hash.sha256(\"abc\") ",
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" == util.hexstrdump(hash.sha256("abc")));
result[5] = new unit.result("SHA256 - 248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1 = hash.sha256(\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\") ",
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1" == util.hexstrdump(hash.sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
result[6] = new unit.result("SHA384 - cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 = hash.sha384(\"abc\") ",
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7" == util.hexstrdump(hash.sha384("abc")));
result[7] = new unit.result("SHA384 - 3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b = str384(\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\") ",
"3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b" == util.hexstrdump(hash.sha384("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
result[8] = new unit.result("SHA512 - ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f = hash.sha512(\"abc\") ",
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" == util.hexstrdump(hash.sha512("abc")));
result[9] = new unit.result("SHA512 - 204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445 = hash.sha512(\"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq\") ",
"204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" == util.hexstrdump(hash.sha512("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
return result;
});
},{"../../../":28,"../../unit.js":63}],61:[function(require,module,exports){
var unit = require('../unit.js');
unit.register("Functional testing of openpgp_crypto_* methods", function() {
var openpgp = require('../../');
var util = openpgp.util;
var result = [];
var RSApubMPIstrs = [
util.bin2str([0x08,0x00,0xac,0x15,0xb3,0xd6,0xd2,0x0f,0xf0,0x7a,0xdd,0x21,0xb7,
0xbf,0x61,0xfa,0xca,0x93,0x86,0xc8,0x55,0x5a,0x4b,0xa6,0xa4,0x1a,
0x60,0xa2,0x3a,0x37,0x06,0x08,0xd8,0x15,0x8e,0x85,0x45,0xaa,0xb7,
0x1d,0x7b,0x0b,0x73,0x94,0x55,0x0c,0x5c,0xec,0xc0,0x22,0x4b,0xa1,
0x64,0x20,0x7d,0x4d,0xa8,0x96,0x1a,0x64,0x38,0x93,0xcd,0xec,0x73,
0x5d,0xf9,0x89,0x88,0x24,0x3d,0x48,0xff,0x3b,0x87,0x62,0xd0,0x84,
0xea,0xff,0x39,0xb5,0x27,0x70,0xea,0x4a,0xb2,0x2e,0x9d,0xf1,0x7c,
0x23,0xec,0xf4,0x5e,0xea,0x61,0x3d,0xe5,0xd8,0x0d,0xf9,0x59,0x6d,
0x28,0x00,0xeb,0xcb,0xc9,0x55,0x00,0x72,0x30,0x1f,0x65,0x9d,0xd6,
0x17,0x58,0x5f,0xa6,0x4a,0xa0,0xdd,0xe1,0x76,0xf2,0xef,0x21,0x9f,
0x84,0xfc,0xaa,0x5b,0x52,0x6e,0xc1,0xa2,0xb9,0xbd,0xb9,0xf4,0x9e,
0x49,0x92,0xf2,0xaf,0x57,0x86,0xf2,0xef,0x70,0xbf,0x51,0x40,0xfd,
0xbf,0x56,0x51,0xe8,0x2c,0xa2,0x4f,0xf8,0xa4,0xd7,0x36,0x18,0x85,
0xce,0x09,0x0d,0xbc,0x8d,0x65,0x5e,0x8a,0x1d,0x98,0xb0,0x4d,0x9d,
0xc1,0xcf,0x82,0xe1,0xb7,0x43,0x5d,0x5a,0x72,0xcd,0x55,0xd2,0xff,
0xb1,0xb4,0x78,0xbf,0xa1,0x7d,0xac,0xd9,0x1b,0xc4,0xfa,0x39,0x34,
0x92,0x09,0xf9,0x08,0x2a,0x6b,0x9d,0x14,0x56,0x12,0x4c,0xe9,0xa6,
0x29,0xc1,0xf3,0xa9,0x0b,0xfc,0x31,0x75,0x58,0x74,0x2a,0x88,0xaf,
0xee,0xc9,0xa4,0xcd,0x15,0xdc,0x1b,0x8d,0x64,0xc1,0x36,0x17,0xc4,
0x8d,0x5e,0x99,0x7a,0x5b,0x9f,0x39,0xd0,0x00,0x6e,0xf9]),
util.bin2str([0x00,0x11,0x01,0x00,0x01])];
var RSAsecMPIstrs = [
util.bin2str([0x07,0xfe,0x23,0xff,0xce,0x45,0x6c,0x60,0x65,0x40,0x6e,0xae,0x35,
0x10,0x56,0x60,0xee,0xab,0xfa,0x10,0x42,0xba,0xc7,0x04,0xaf,0x63,
0xcd,0x3f,0x62,0xca,0x4b,0xfa,0xe1,0xa9,0x70,0xcd,0x34,0x8b,0xc8,
0x0e,0xe4,0xc4,0xba,0x83,0x17,0x5f,0xa4,0xb8,0xea,0x60,0xc2,0x4d,
0x9a,0xf2,0xa9,0x03,0xeb,0xf6,0xaa,0xc2,0xb8,0x8b,0x43,0x12,0xe9,
0xf7,0x88,0xd2,0x5a,0xa6,0xaa,0x23,0x71,0x31,0x74,0xdb,0x19,0x20,
0x15,0x41,0x1b,0x43,0x68,0x62,0xd8,0xc0,0x93,0x91,0xe8,0xfc,0xb1,
0xa9,0x9a,0x52,0x6c,0xe0,0xbf,0x43,0x01,0xa8,0x37,0x14,0x28,0xbf,
0x0b,0x15,0x56,0x3e,0xa5,0x79,0xa0,0xc4,0x42,0x88,0xee,0xeb,0x1b,
0xf4,0x7a,0x4a,0x58,0x31,0x58,0x81,0xd2,0x3e,0xde,0x07,0x64,0x92,
0xf0,0x60,0xd3,0x9a,0x29,0xca,0xc6,0x67,0x75,0x07,0xca,0x92,0x39,
0x56,0xf6,0x11,0x84,0xba,0x6d,0x4b,0xe6,0x6f,0x66,0xc2,0x17,0xeb,
0x46,0x69,0x1c,0xbb,0xdf,0xc0,0x38,0x00,0xd6,0x01,0xe6,0x70,0x9d,
0x4b,0x9b,0x70,0xed,0x5c,0xb8,0xcf,0xe8,0x68,0x71,0xbe,0x24,0x6d,
0xb1,0xa3,0x13,0xcc,0xf1,0xbc,0x67,0xdc,0xe0,0x69,0x09,0x82,0x3c,
0x3b,0x0f,0x14,0x98,0x48,0x30,0xb2,0x70,0xc6,0x9e,0xfa,0x46,0x8f,
0xf1,0xc0,0x65,0x8e,0xc6,0xae,0xdc,0x47,0x91,0x13,0x1e,0xd6,0x4a,
0xf2,0xad,0xda,0xc2,0xc7,0x39,0x78,0x99,0xde,0x57,0x14,0x45,0x7f,
0x32,0x38,0xa3,0x44,0x0f,0xe7,0x39,0x4c,0x6f,0x0f,0x32,0x7e,0xf1,
0x5c,0x84,0x97,0xdd,0xa0,0x0c,0x87,0x66,0x7d,0x75,0x79]),
util.bin2str([0x04,0x00,0xc2,0xbc,0x71,0xf7,0x41,0x4a,0x09,0x66,0x70,0x02,0x68,
0x8b,0xeb,0xe2,0x34,0xd1,0x12,0x83,0x93,0x75,0xe9,0x71,0x32,0xe2,
0xed,0x18,0x6f,0x8e,0x3a,0xff,0x22,0x70,0x28,0x01,0xbf,0x4a,0x39,
0x41,0xbb,0x3c,0x4a,0xbc,0xb8,0x13,0xfc,0x14,0xf6,0x71,0xa1,0x44,
0x1c,0x02,0xa1,0x73,0x81,0xcc,0xa0,0x35,0x02,0x3e,0x97,0xb5,0xc4,
0x94,0x33,0xf1,0xd1,0xdf,0x14,0x3f,0xfb,0x8f,0xb9,0x75,0x70,0xdc,
0x74,0x3f,0x07,0x35,0x8f,0x53,0xaa,0xb2,0xd6,0x88,0x51,0x71,0x4e,
0x01,0x24,0xec,0x7d,0xca,0xf6,0xa2,0xb3,0xbb,0xad,0x2e,0x60,0xfb,
0x1c,0xee,0x49,0xd0,0x4e,0x5c,0xe3,0x1f,0x88,0x48,0xe4,0x68,0x14,
0x3d,0x71,0xba,0xd7,0x4d,0x35,0x10,0x86,0x37,0x62,0xe0,0xa5,0x0b]),
util.bin2str([0x04,0x00,0xe2,0x38,0xf9,0xc8,0x3c,0xd1,0xcf,0x62,0x93,0xc3,0x77,
0x76,0x97,0x44,0xe8,0xc8,0xca,0x93,0x9a,0xef,0xf0,0x63,0x76,0x25,
0x3b,0x1c,0x46,0xff,0x90,0x13,0x91,0x15,0x97,0x7e,0x88,0x95,0xd4,
0x7f,0x2f,0x52,0x6e,0x0d,0x55,0x55,0x2e,0xf1,0x58,0x5c,0x7e,0x56,
0xd4,0x48,0xaa,0xdb,0x8c,0x44,0x4d,0x84,0x69,0x33,0x87,0x07,0xb2,
0x7e,0xf5,0xa0,0x60,0xfb,0x73,0x59,0x46,0x29,0xcb,0x1e,0x3f,0x7c,
0x2f,0xa6,0x53,0xe3,0x8c,0xef,0xd5,0xeb,0xbb,0xc8,0x9a,0x8e,0x66,
0x4a,0x47,0x2f,0xe1,0xba,0x5e,0x32,0xd4,0x52,0x04,0x88,0x9d,0x63,
0x3e,0xba,0x71,0x2d,0xf7,0x61,0xd5,0xfc,0x26,0xbf,0xd8,0x60,0x92,
0x7b,0x94,0xf8,0x6f,0x3d,0x97,0x0b,0x0c,0x52,0x8c,0xb3,0xb6,0x8b]),
util.bin2str([0x04,0x00,0xb7,0xc5,0x4d,0x6e,0x2f,0xdd,0xef,0xec,0x07,0x70,0xa2,
0x7c,0x1c,0x9d,0x8e,0x66,0x60,0x7c,0x61,0x1e,0x45,0xe9,0xdc,0x82,
0x2f,0xc5,0x7e,0x1a,0xc6,0xd0,0x92,0xc5,0x22,0x9b,0x9a,0xfb,0x73,
0x95,0x99,0xf2,0x7c,0xdb,0x2a,0x93,0x7b,0x5a,0x29,0x73,0x24,0x16,
0x41,0x49,0xb5,0xf2,0x5f,0xbe,0xe7,0x64,0x4d,0xda,0x52,0x9e,0xc1,
0x41,0x40,0x5e,0x03,0x92,0x8d,0x39,0x95,0x1f,0x68,0x9f,0x00,0x2e,
0x0c,0x6f,0xcf,0xd9,0x6d,0x68,0xf7,0x00,0x4f,0x0e,0xc8,0x0b,0xfa,
0x51,0xe0,0x22,0xf0,0xff,0xa7,0x42,0xd4,0xde,0x0b,0x47,0x8f,0x2b,
0xf5,0x4d,0x04,0x32,0x91,0x89,0x4b,0x0e,0x05,0x8d,0x70,0xf9,0xbb,
0xe7,0xd6,0x76,0xea,0x0e,0x1a,0x90,0x30,0xf5,0x98,0x01,0xc5,0x73])];
var DSApubMPIstrs = [
util.bin2str([0x08,0x00,0xa8,0x85,0x5c,0x28,0x05,0x94,0x03,0xbe,0x07,0x6c,0x13,0x3e,0x65,
0xfb,0xb5,0xe1,0x99,0x7c,0xfa,0x84,0xe3,0xac,0x47,0xa5,0xc4,0x46,0xd8,0x5f,
0x44,0xe9,0xc1,0x6b,0x69,0xf7,0x10,0x76,0x49,0xa7,0x25,0x85,0xf4,0x1b,0xed,
0xc6,0x60,0xc4,0x5b,0xaa,0xd4,0x87,0xd6,0x8f,0x92,0x56,0x7d,0x55,0x3f,0x45,
0xae,0x12,0x73,0xda,0x29,0x8c,0xba,0x32,0xcc,0xd7,0xa4,0xd0,0x24,0xb0,0x7c,
0xd8,0x0c,0x3a,0x91,0x6f,0x98,0x40,0x9c,0x9a,0xa8,0xcc,0x28,0x27,0x95,0x0b,
0xe1,0x5b,0xb9,0x3b,0x1c,0x1c,0xd2,0xec,0xab,0x07,0x25,0x8d,0x7a,0x2a,0x2b,
0x16,0x14,0xe8,0xda,0x71,0xd2,0xab,0xba,0x85,0x14,0x0d,0xc5,0xe0,0x88,0xeb,
0xa5,0xe2,0xd5,0x48,0x3d,0x74,0x0c,0x41,0xeb,0xfd,0xb6,0x4e,0xf9,0x2c,0x82,
0x17,0xdd,0x64,0x1e,0x19,0x39,0xa3,0x7f,0xf9,0x00,0xcd,0x9b,0xda,0x2e,0xbd,
0x71,0x12,0xdf,0x0d,0x7c,0x0a,0x6b,0x2d,0x21,0x3b,0x9c,0x66,0x93,0x4a,0x1e,
0x90,0x79,0xd3,0x5a,0x5b,0xe5,0xb9,0x94,0x1b,0xe6,0x47,0x99,0x06,0x98,0xd8,
0x2a,0xe5,0xe2,0xa6,0x95,0x6a,0x07,0xc8,0xac,0x7c,0xe9,0xfc,0xa2,0x6a,0x16,
0x2c,0x94,0x98,0xbd,0x91,0x0a,0x7c,0x7c,0x2c,0xb9,0x7e,0xa2,0x51,0x8b,0x45,
0x1d,0x46,0x34,0xa8,0x52,0x2b,0xdd,0xd9,0xa8,0xbc,0x46,0x78,0x66,0xe1,0x72,
0x11,0xf1,0xcb,0x1a,0xb6,0x4e,0x05,0x54,0xf7,0xe9,0xbe,0x4c,0x25,0x59,0x08,
0x9f,0xf8,0xea,0x25,0x97,0x33,0xd6,0xc9,0x0f,0x59,0x0e,0xfd,0x9f,0xdc,0xe2,
0xc0,0xcf,0x2f]),
util.bin2str([0x01,0x00,0xe1,0x72,0x2c,0xd0,0xbb,0x1a,0x4f,0xb6,0xb6,0x95,0x77,0x71,0x2e,
0x01,0x48,0x3e,0x35,0x54,0x64,0x2b,0xed,0x40,0x5f,0x65,0x0c,0x57,0x28,0x5f,
0xfd,0xfd,0xff,0xd7]),
util.bin2str([0x07,0xff,0x5d,0x9f,0xc4,0xb5,0x63,0x25,0x9d,0x72,0x88,0xe5,0x53,0x46,0x98,
0xe3,0xe9,0x62,0xcb,0x0c,0xa1,0xb7,0x75,0x9f,0x18,0x41,0x94,0x32,0x28,0x29,
0x6d,0x69,0xe0,0x3f,0x7d,0x7b,0x2b,0x06,0x5a,0x33,0x5c,0xd4,0x36,0x31,0x09,
0x54,0x85,0x9d,0xb8,0x20,0xfe,0xda,0xfc,0xcd,0x1f,0xb1,0x2c,0x15,0x08,0x9d,
0x32,0x53,0x2f,0xc1,0x42,0x22,0x69,0xff,0x67,0x2e,0x39,0x97,0x50,0x66,0x39,
0xda,0xcf,0xfd,0x64,0x6f,0x91,0x05,0x64,0x37,0xc5,0x07,0x24,0xaa,0x40,0xa0,
0x75,0x82,0x1d,0x97,0x96,0x12,0xf1,0xbd,0x9e,0x09,0x26,0x3c,0x97,0x5d,0x57,
0xb8,0x5c,0x7d,0x89,0x03,0x82,0xcd,0x40,0xe5,0x03,0xe6,0x4a,0xfb,0xbc,0xd2,
0xef,0x7a,0x89,0x02,0x08,0xc8,0x52,0xfa,0x97,0x74,0x66,0x32,0xae,0xa6,0x52,
0x4b,0xef,0x5f,0xce,0x91,0x23,0x3f,0xab,0x9d,0x62,0x21,0xef,0x48,0x6d,0x07,
0x5a,0xba,0xdf,0x00,0x91,0x54,0xea,0x5c,0xfa,0x4b,0x16,0x28,0x1a,0xce,0x48,
0xb7,0x5c,0x50,0xa5,0x59,0xa4,0xb4,0xaf,0x1f,0xeb,0x8d,0x58,0x3f,0x0a,0xa5,
0x97,0x2b,0x51,0x56,0xe8,0x88,0xf6,0x07,0xbc,0xdf,0xfa,0x2b,0x7b,0x88,0xe0,
0x46,0xc8,0x7a,0x3e,0xd8,0x80,0xdb,0x4d,0x87,0x61,0x4f,0x64,0xcd,0xeb,0xe8,
0x0d,0x86,0x16,0xcc,0xdd,0x6c,0x76,0x66,0xc1,0x73,0xb7,0x08,0x98,0x89,0x2f,
0x67,0x69,0xd1,0xfc,0x97,0x4d,0xa2,0xce,0xad,0xbb,0x6f,0xab,0xa5,0xd6,0x18,
0xb3,0x1a,0x96,0x02,0xbc,0x31,0x42,0xa2,0xad,0x77,0xe8,0xe2,0x4c,0x99,0xf9,
0xdd,0xbe,0xcd]),
util.bin2str([0x07,0xff,0x5d,0xfe,0x9c,0x98,0xef,0x3a,0xa6,0x49,0xf0,0x10,0x67,0x79,0x2a,
0x9d,0x79,0x43,0x06,0xa4,0xa8,0x6b,0x1a,0x6d,0x1f,0x77,0x6e,0x00,0x31,0xb9,
0xed,0xc9,0x66,0xff,0xf1,0x21,0x32,0xfa,0x62,0x43,0xcd,0x97,0xd3,0x3d,0xaf,
0xb4,0x29,0x29,0x26,0x4e,0x1c,0xa0,0xad,0x1c,0x07,0x28,0x3f,0xe5,0x43,0x10,
0xba,0xb4,0x08,0xe0,0xdc,0xa2,0xc3,0x5b,0x1f,0xbd,0x94,0xc7,0x43,0xe5,0xf2,
0x17,0x30,0x54,0x7f,0x14,0xbe,0xf4,0xbd,0x91,0x3b,0xe4,0x36,0xa4,0x50,0x5b,
0x37,0x89,0x5e,0xcc,0xc7,0x74,0x54,0x32,0x20,0x09,0x63,0x98,0xb7,0xd9,0xaf,
0x7f,0xb0,0x6c,0x27,0x43,0xfe,0x52,0xe6,0x1a,0x88,0x59,0x25,0xfc,0xeb,0x43,
0x50,0xc7,0x65,0x43,0xc1,0x86,0x73,0x58,0x53,0x3a,0xcf,0x7a,0xa3,0x1d,0x56,
0xc8,0x4a,0x80,0x70,0xb7,0xbf,0xf2,0xa3,0xec,0xe8,0x77,0x05,0x33,0x09,0x9d,
0xaa,0xca,0xa0,0xe1,0x64,0x64,0x6f,0x76,0x99,0x41,0x75,0x78,0x90,0xf6,0xe7,
0x23,0xe6,0xec,0x50,0xe5,0x99,0xa8,0x3e,0x1a,0x4b,0xc9,0x88,0x58,0x66,0xae,
0x1a,0x53,0x5e,0xe4,0xb7,0x86,0xcf,0xa6,0xe5,0xad,0xb4,0x80,0xa0,0xf1,0x0d,
0x96,0xb8,0x41,0xd0,0x07,0x9a,0x21,0x8d,0x50,0x7f,0x4f,0x73,0x13,0xa2,0xe2,
0x02,0x07,0xc3,0xa3,0x0f,0x09,0x18,0x7f,0xf7,0x6b,0x90,0x70,0xc0,0xf9,0x0c,
0x67,0x8d,0x9d,0x14,0xb6,0x9d,0x32,0x82,0xd0,0xb5,0xc6,0x57,0xf0,0x91,0xd9,
0xc3,0x26,0xae,0x9f,0xa9,0x67,0x49,0x96,0x5c,0x07,0x3e,0x47,0x5c,0xed,0x60,
0x07,0xac,0x6a])];
var DSAsecMPIstrs = [util.bin2str([0x01,0x00,0x9b,0x58,0xa8,0xf4,0x04,0xb1,0xd5,0x14,0x09,0xe1,
0xe1,0xa1,0x8a,0x0b,0xa3,0xc3,0xa3,0x66,0xaa,0x27,0x99,0x50,
0x1c,0x4d,0xba,0x24,0xee,0xdf,0xdf,0xb8,0x8e,0x8e])];
var ElgamalpubMPIstrs =
[util.bin2str([0x08,0x00,0xea,0xcc,0xbe,0xe2,0xe4,0x5a,0x51,0x18,0x93,0xa1,0x12,0x2f,
0x00,0x99,0x42,0xd8,0x5c,0x1c,0x2f,0xb6,0x3c,0xd9,0x94,0x61,0xb4,0x55,
0x8d,0x4e,0x73,0xe6,0x69,0xbc,0x1d,0x33,0xe3,0x2d,0x91,0x23,0x69,0x95,
0x98,0xd7,0x18,0x5a,0xaf,0xa7,0x93,0xc6,0x05,0x93,0x3a,0xc7,0xea,0xd0,
0xb1,0xa9,0xc7,0xab,0x41,0x89,0xc8,0x38,0x99,0xdc,0x1a,0x57,0x35,0x1a,
0x27,0x62,0x40,0x71,0x9f,0x36,0x1c,0x6d,0x18,0x1c,0x93,0xf7,0xba,0x35,
0x06,0xed,0x30,0xb8,0xd9,0x8a,0x7c,0x03,0xaf,0xba,0x40,0x1f,0x62,0xf1,
0x6d,0x87,0x2c,0xa6,0x2e,0x46,0xb0,0xaa,0xbc,0xbc,0x93,0xfa,0x9b,0x47,
0x3f,0x70,0x1f,0x2a,0xc2,0x66,0x9c,0x7c,0x69,0xe0,0x2b,0x05,0xee,0xb7,
0xa7,0x7f,0xf3,0x21,0x48,0x85,0xc2,0x95,0x5f,0x6f,0x1e,0xb3,0x9b,0x97,
0xf8,0x14,0xc3,0xff,0x4d,0x97,0x25,0x29,0x94,0x41,0x4b,0x90,0xd8,0xba,
0x71,0x45,0x4b,0x1e,0x2f,0xca,0x82,0x5f,0x56,0x77,0xe9,0xd3,0x88,0x5d,
0x8b,0xec,0x92,0x8b,0x8a,0x23,0x88,0x05,0xf8,0x2c,0xa8,0xf1,0x70,0x76,
0xe7,0xbf,0x75,0xa8,0x31,0x14,0x8e,0x76,0xc8,0x01,0xa6,0x25,0x27,0x49,
0xaf,0xdc,0xf4,0xf6,0xf4,0xce,0x90,0x84,0x15,0x2b,0x4d,0xb3,0xcc,0x77,
0xdb,0x65,0x71,0x75,0xd3,0x00,0x1d,0x22,0xc5,0x42,0x2f,0x51,0xfa,0x7b,
0xeb,0x6e,0x03,0xd9,0x41,0xdd,0x2d,0x1a,0xdd,0x07,0x74,0x8b,0xb7,0xa2,
0xfa,0xb2,0x59,0x0e,0x0e,0x94,0x7c,0x00,0xad,0x95,0x23,0x42,0x91,0x18,
0x4c,0x97,0xf1,0x27,0x62,0x77]),
util.bin2str([0x00,0x03,0x05]),
util.bin2str([0x07,0xff,0x57,0x19,0x76,0xfc,0x09,0x6a,0x7a,0xf7,0xba,0xb2,0x42,0xbf,
0xcd,0x2b,0xc1,0x1a,0x79,0x25,0x8c,0xad,0xf4,0x3a,0x0a,0x7a,0x9b,0x4c,
0x46,0x3c,0xe0,0x4f,0xcc,0x6e,0xe5,0x7a,0x33,0x3a,0x4e,0x80,0xcb,0xd3,
0x62,0xd7,0x8f,0xe2,0xc8,0xb0,0xd0,0xcb,0x49,0xc9,0x9e,0x2d,0x97,0x16,
0x3a,0x7d,0xb1,0xe1,0xd3,0xd9,0xd7,0x3f,0x20,0x60,0xe3,0x3e,0x77,0xea,
0x0c,0xe4,0x7b,0xf0,0x39,0x1a,0x0d,0xd9,0x8f,0x73,0xd2,0x51,0xb8,0x0c,
0x0e,0x15,0x1e,0xad,0x7c,0xd8,0x9d,0x74,0x6e,0xa2,0x17,0x6b,0x58,0x14,
0x2b,0xb7,0xad,0x8a,0xd7,0x66,0xc0,0xdf,0xea,0x2d,0xfc,0xc4,0x6e,0x68,
0xb6,0x4c,0x9a,0x16,0xa4,0x3d,0xc2,0x26,0x0c,0xb7,0xd4,0x13,0x7b,0x22,
0xfd,0x84,0xd7,0x0f,0xdc,0x42,0x75,0x05,0x85,0x29,0x00,0x31,0x1d,0xec,
0x4e,0x22,0x8b,0xf6,0x37,0x83,0x45,0xe5,0xb3,0x31,0x61,0x2c,0x02,0xa1,
0xc6,0x9d,0xea,0xba,0x3d,0x8a,0xab,0x0f,0x61,0x5e,0x14,0x64,0x69,0x1e,
0xa0,0x15,0x48,0x86,0xe5,0x11,0x06,0xe8,0xde,0x34,0xc7,0xa7,0x3d,0x35,
0xd1,0x76,0xc2,0xbe,0x01,0x82,0x61,0x8d,0xe7,0x7e,0x28,0x1d,0x4e,0x8c,
0xb9,0xe8,0x7e,0xa4,0x5f,0xa6,0x3a,0x9e,0x5d,0xac,0xf3,0x60,0x22,0x14,
0xd5,0xd5,0xbe,0x1f,0xf0,0x19,0xe6,0x81,0xfd,0x5d,0xe1,0xf8,0x76,0x5f,
0xe3,0xda,0xba,0x19,0xf3,0xcb,0x10,0xa0,0x6b,0xd0,0x2d,0xbe,0x40,0x42,
0x7b,0x9b,0x15,0xa4,0x2d,0xec,0xcf,0x09,0xd6,0xe3,0x92,0xc3,0x8d,0x65,
0x6b,0x60,0x97,0xda,0x6b,0xca])];
var ElgamalsecMPIstrs = [
util.bin2str([0x01,0x52,0x02,0x80,0x87,0xf6,0xe4,0x49,0xd7,0x2e,0x3e,0xfe,0x60,0xb9,
0xa3,0x2a,0xf0,0x67,0x58,0xe9,0xf6,0x47,0x83,0xde,0x7e,0xfb,0xbb,0xbd,
0xdf,0x48,0x12,0x1b,0x06,0x7d,0x13,0xbc,0x3b,0x49,0xf9,0x86,0xd4,0x53,
0xed,0x2d,0x68])];
var RSApubMPIs = [];
var i;
for (i = 0; i < 2; i++) {
RSApubMPIs[i] = new openpgp.mpi();
RSApubMPIs[i].read(RSApubMPIstrs[i],0,RSApubMPIstrs[i].length);
}
var RSAsecMPIs = [];
for (i = 0; i < 4; i++) {
RSAsecMPIs[i] = new openpgp.mpi();
RSAsecMPIs[i].read(RSAsecMPIstrs[i],0,RSAsecMPIstrs[i].length);
}
var DSAsecMPIs = [];
for (i = 0; i < 1; i++) {
DSAsecMPIs[i] = new openpgp.mpi();
DSAsecMPIs[i].read(DSAsecMPIstrs[i],0,DSAsecMPIstrs[i].length);
}
var DSApubMPIs = [];
for (i = 0; i < 4; i++) {
DSApubMPIs[i] = new openpgp.mpi();
DSApubMPIs[i].read(DSApubMPIstrs[i],0,DSApubMPIstrs[i].length);
}
var ElgamalsecMPIs = [];
for (i = 0; i < 1; i++) {
ElgamalsecMPIs[i] = new openpgp.mpi();
ElgamalsecMPIs[i].read(ElgamalsecMPIstrs[i],0,ElgamalsecMPIstrs[i].length);
}
var ElgamalpubMPIs = [];
for (i = 0; i < 3; i++) {
ElgamalpubMPIs[i] = new openpgp.mpi();
ElgamalpubMPIs[i].read(ElgamalpubMPIstrs[i],0,ElgamalpubMPIstrs[i].length);
}
//Originally we passed public and secret MPI separately, now they are joined. Is this what we want to do long term?
debugger;
// RSA
var RSAsignedData = openpgp.signature.sign(2, 1, RSApubMPIs.concat(RSAsecMPIs), "foobar");
var RSAsignedDataMPI = new openpgp.mpi();
RSAsignedDataMPI.read(RSAsignedData, 0, RSAsignedData.length);
result[0] = new unit.result("Testing RSA Sign and Verify",
openpgp.signature.verify(1, 2, [RSAsignedDataMPI], RSApubMPIs, "foobar"));
// DSA
var DSAsignedData = openpgp.signature.sign(2, 17, DSApubMPIs.concat(DSAsecMPIs), "foobar");
var DSAmsgMPIs = [];
DSAmsgMPIs[0] = new openpgp.mpi();
DSAmsgMPIs[1] = new openpgp.mpi();
DSAmsgMPIs[0].read(DSAsignedData, 0, DSAsignedData.length);
DSAmsgMPIs[1].read(DSAsignedData, DSAmsgMPIs[0].packetLength, DSAsignedData.length);
result[1] = new unit.result("Testing DSA Sign and Verify",
openpgp.signature.verify(17, 2, DSAmsgMPIs, DSApubMPIs, "foobar"));
var symmAlgo = 9; // AES256
var symmKey = openpgp.generateSessionKey(symmAlgo);
var symmencDataOCFB = openpgp.cfb.encrypt(openpgp.getPrefixRandom(symmAlgo),symmAlgo, symmKey, "foobar",true);
var symmencDataCFB = openpgp.cfb.encrypt(openpgp.getPrefixRandom(symmAlgo),symmAlgo, symmKey, "foobar",false);
result[2] = new unit.result("Testing symmetric encrypt and decrypt with OpenPGP CFB resync",
openpgp.cfb.decrypt(symmAlgo,symmKey,symmencDataOCFB,true) == "foobar");
result[3] = new unit.result("Testing symmetric encrypt and decrypt without OpenPGP CFB resync (used in modification detection code \"MDC\" packets)",
openpgp.cfb.decrypt(symmAlgo,symmKey,symmencDataCFB,false) == "foobar");
var RSAEncryptedData = openpgp.cfb.encrypt(1, RSApubMPIs, new openpgp.mpi().create(openpgp_encoding_eme_pkcs1_encode(symmKey, RSApubMPIs[0].mpiByteLength)));
var RSAEncryptedDataMPI = new openpgp.mpi();
RSAEncryptedDataMPI.read(RSAEncryptedData, 0,RSAEncryptedData.length);
result[4] = new unit.result("Testing asymmetric encrypt and decrypt using RSA with eme_pkcs1 padding",
openpgp_encoding_eme_pkcs1_decode(openpgp.cfb.decrypt(1, RSApubMPIs.concat(RSAsecMPIs), [RSAEncryptedDataMPI]).toMPI().substring(2), RSApubMPIs[0].mpiByteLength) == symmKey);
var ElgamalEncryptedData = openpgp.cfb.encrypt(16, ElgamalpubMPIs, new openpgp.mpi().create(openpgp_encoding_eme_pkcs1_encode(symmKey, ElgamalpubMPIs[0].mpiByteLength)));
var ElgamalEncryptedDataMPIs = [];
ElgamalEncryptedDataMPIs[0] = new openpgp.mpi();
ElgamalEncryptedDataMPIs[0].read(ElgamalEncryptedData[0], 0, ElgamalEncryptedData[0].length);
ElgamalEncryptedDataMPIs[1] = new openpgp.mpi();
ElgamalEncryptedDataMPIs[1].read(ElgamalEncryptedData[1], 0, ElgamalEncryptedData[1].length);
result[5] = new unit.result("Testing asymmetric encrypt and decrypt using Elgamal with eme_pkcs1 padding",
openpgp_encoding_eme_pkcs1_decode(openpgp.cfb.decrypt(16, ElgamalpubMPIs.concat(ElgamalsecMPIs), ElgamalEncryptedDataMPIs).toMPI().substring(2), ElgamalpubMPIs[0].mpiByteLength) == symmKey);
return result;
});
},{"../../":28,"../unit.js":63}],"2ZZCcm":[function(require,module,exports){
module.exports = require('./unit.js');
require('./crypto/hash/sha.js');
require('./crypto/hash/md5.js');
require('./crypto/hash/ripemd.js');
require('./crypto/cipher/aes.js');
require('./crypto/cipher/blowfish.js');
require('./crypto/cipher/cast5.js');
require('./crypto/cipher/des.js');
require('./crypto/cipher/twofish.js');
require('./crypto/openpgp.crypto.js');
},{"./crypto/cipher/aes.js":53,"./crypto/cipher/blowfish.js":54,"./crypto/cipher/cast5.js":55,"./crypto/cipher/des.js":56,"./crypto/cipher/twofish.js":57,"./crypto/hash/md5.js":58,"./crypto/hash/ripemd.js":59,"./crypto/hash/sha.js":60,"./crypto/openpgp.crypto.js":61,"./unit.js":63}],63:[function(require,module,exports){
var process=require("__browserify_process");
module.exports = {
tests: [],
register: function(str_title, func_runtest) {
this.tests.push({ title: str_title, run: func_runtest });
},
run: function() {
var test = this.tests.shift();
var result = {
title: test.title
};
result.tests = test.run();
return result;
},
run_all: function() {
var passed = true;
while(this.tests.length > 0) {
var result = this.run();
console.log('Test: ' + result.title);
for(var i in result.tests) {
var res = result.tests[i].result ?
'SUCCESS' : 'FAILED';
console.log(result.tests[i].description + ' ' + res);
passed = passed && result.tests[i].result;
}
}
if(!passed) process.exit(1);
},
result: function(str_description, boolean_result) {
this.description = str_description;
this.result = boolean_result;
}
}
},{"__browserify_process":64}],64:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
if (ev.source === window && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}]},{},[])
//@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jb21wcmVzc2lvbi9qeGcuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vY2ZiLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvY3J5cHRvL2NpcGhlci9hZXMuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vY2lwaGVyL2Jsb3dmaXNoLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvY3J5cHRvL2NpcGhlci9jYXN0NS5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9jaXBoZXIvZGVzLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvY3J5cHRvL2NpcGhlci9pbmRleC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9jaXBoZXIvdHdvZmlzaC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9jcnlwdG8uanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vaGFzaC9pbmRleC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9oYXNoL21kNS5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9oYXNoL3JpcGUtbWQuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vaGFzaC9zaGEuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vaW5kZXguanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vcGtjczEuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vcHVibGljX2tleS9kc2EuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9wYWNrZXQvb25lX3Bhc3Nfc2lnbmF0dXJlLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvY3J5cHRvL3B1YmxpY19rZXkvZWxnYW1hbC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9wdWJsaWNfa2V5L2luZGV4LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvY3J5cHRvL3B1YmxpY19rZXkvanNibi5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9wdWJsaWNfa2V5L3JzYS5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2NyeXB0by9yYW5kb20uanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9jcnlwdG8vc2lnbmF0dXJlLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvZW5jb2RpbmcvYXJtb3IuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9lbmNvZGluZy9iYXNlNjQuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9lbnVtcy5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL2luZGV4LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvb3BlbnBncC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3BhY2tldC9hbGxfcGFja2V0cy5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3BhY2tldC9jb21wcmVzc2VkLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L2luZGV4LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L2xpdGVyYWwuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9wYWNrZXQvbWFya2VyLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3BhY2tldC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3BhY2tldC9wYWNrZXRsaXN0LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3B1YmxpY19rZXkuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9wYWNrZXQvcHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9wYWNrZXQvcHVibGljX3N1YmtleS5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3BhY2tldC9zZWNyZXRfa2V5LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3NlY3JldF9zdWJrZXkuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy9wYWNrZXQvc2lnbmF0dXJlLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3N5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3BhY2tldC9zeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3N5bW1ldHJpY2FsbHlfZW5jcnlwdGVkLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3RydXN0LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3VzZXJfYXR0cmlidXRlLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvcGFja2V0L3VzZXJpZC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3R5cGUva2V5aWQuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3NyYy90eXBlL21waS5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvc3JjL3R5cGUvczJrLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC9zcmMvdXRpbC91dGlsLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC90ZXN0L2NyeXB0by9jaXBoZXIvYWVzLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC90ZXN0L2NyeXB0by9jaXBoZXIvYmxvd2Zpc2guanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3Rlc3QvY3J5cHRvL2NpcGhlci9jYXN0NS5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvdGVzdC9jcnlwdG8vY2lwaGVyL2Rlcy5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvdGVzdC9jcnlwdG8vY2lwaGVyL3R3b2Zpc2guanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3Rlc3QvY3J5cHRvL2hhc2gvbWQ1LmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC90ZXN0L2NyeXB0by9oYXNoL3JpcGVtZC5qcyIsIi9Vc2Vycy96ZXVzL0RvY3VtZW50cy9HZW5lcmFsL1Byb2plY3RzL29wZW5wZ3Bqcy9naXQvdGVzdC9jcnlwdG8vaGFzaC9zaGEuanMiLCIvVXNlcnMvemV1cy9Eb2N1bWVudHMvR2VuZXJhbC9Qcm9qZWN0cy9vcGVucGdwanMvZ2l0L3Rlc3QvY3J5cHRvL29wZW5wZ3AuY3J5cHRvLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC90ZXN0L3Rlc3QtYWxsLmpzIiwiL1VzZXJzL3pldXMvRG9jdW1lbnRzL0dlbmVyYWwvUHJvamVjdHMvb3BlbnBncGpzL2dpdC90ZXN0L3VuaXQuanMiLCIvdXNyL2xvY2FsL3NoYXJlL25wbS9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2luc2VydC1tb2R1bGUtZ2xvYmFscy9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2U0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbHNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN0R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcnpDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1UUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM2VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0tBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyJKWEcgPSB7ZXhpc3RzOiAoZnVuY3Rpb24odW5kZWZpbmVkKXtyZXR1cm4gZnVuY3Rpb24odil7cmV0dXJuICEodj09PXVuZGVmaW5lZCB8fCB2PT09bnVsbCk7fX0pKCl9O1xuSlhHLmRlY29tcHJlc3MgPSBmdW5jdGlvbihzdHIpIHtyZXR1cm4gdW5lc2NhcGUoKG5ldyBKWEcuVXRpbC5VbnppcChKWEcuVXRpbC5CYXNlNjQuZGVjb2RlQXNBcnJheShzdHIpKSkudW56aXAoKVswXVswXSk7fTtcbi8qXG4gICAgQ29weXJpZ2h0IDIwMDgtMjAxMlxuICAgICAgICBNYXR0aGlhcyBFaG1hbm4sXG4gICAgICAgIE1pY2hhZWwgR2VyaGFldXNlcixcbiAgICAgICAgQ2Fyc3RlbiBNaWxsZXIsXG4gICAgICAgIEJpYW5jYSBWYWxlbnRpbixcbiAgICAgICAgQWxmcmVkIFdhc3Nlcm1hbm4sXG4gICAgICAgIFBldGVyIFdpbGZhaHJ0XG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBKU1hHcmFwaC5cbiAgICBcbiAgICBEdWFsIGxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSBWZXJzaW9uIDIuMCwgb3IgTEdQTCBWZXJzaW9uIDMgbGljZW5zZXMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIEpTWENvbXByZXNzb3IuICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gICAgXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgQXBhY2hlIExpY2Vuc2UgYWxvbmcgd2l0aCBKU1hDb21wcmVzc29yLiAgXG4gICAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy8+LlxuXG4qL1xuXG4vKipcbiAgKiBAY2xhc3MgVXRpbCBjbGFzc1xuICAqIEBjbGFzc2Rlc2MgVXRpbGl0aWVzIGZvciB1bmNvbXByZXNzaW5nIGFuZCBiYXNlNjQgZGVjb2RpbmdcbiAgKiBDbGFzcyBmb3IgZ3VuemlwcGluZywgdW56aXBwaW5nIGFuZCBiYXNlNjQgZGVjb2Rpbmcgb2YgZmlsZXMuXG4gICogSXQgaXMgdXNlZCBmb3IgcmVhZGluZyBHRU9ORXhULCBHZW9nZWJyYSBhbmQgSW50ZXJnZW8gZmlsZXMuXG4gICpcbiAgKiBPbmx5IEh1ZmZtYW4gY29kZXMgYXJlIGRlY29kZWQgaW4gZ3VuemlwLlxuICAqIFRoZSBjb2RlIGlzIGJhc2VkIG9uIHRoZSBzb3VyY2UgY29kZSBmb3IgZ3VuemlwLmMgYnkgUGFzaSBPamFsYSBcbiAgKiB7QGxpbmsgaHR0cDovL3d3dy5jcy50dXQuZmkvfmFsYmVydC9EZXYvZ3VuemlwL2d1bnppcC5jfVxuICAqIHtAbGluayBodHRwOi8vd3d3LmNzLnR1dC5maS9+YWxiZXJ0fVxuICAqL1xuSlhHLlV0aWwgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuLyoqXG4gKiBVbnppcCB6aXAgZmlsZXNcbiAqL1xuSlhHLlV0aWwuVW56aXAgPSBmdW5jdGlvbiAoYmFycmF5KXtcbiAgICB2YXIgb3V0cHV0QXJyID0gW10sXG4gICAgICAgIG91dHB1dCA9IFwiXCIsXG4gICAgICAgIGRlYnVnID0gZmFsc2UsXG4gICAgICAgIGdwZmxhZ3MsXG4gICAgICAgIGZpbGVzID0gMCxcbiAgICAgICAgdW56aXBwZWQgPSBbXSxcbiAgICAgICAgY3JjLFxuICAgICAgICBidWYzMmsgPSBuZXcgQXJyYXkoMzI3NjgpLFxuICAgICAgICBiSWR4ID0gMCxcbiAgICAgICAgbW9kZVpJUD1mYWxzZSxcblxuICAgICAgICBDUkMsIFNJWkUsXG4gICAgXG4gICAgICAgIGJpdFJldmVyc2UgPSBbXG4gICAgICAgIDB4MDAsIDB4ODAsIDB4NDAsIDB4YzAsIDB4MjAsIDB4YTAsIDB4NjAsIDB4ZTAsXG4gICAgICAgIDB4MTAsIDB4OTAsIDB4NTAsIDB4ZDAsIDB4MzAsIDB4YjAsIDB4NzAsIDB4ZjAsXG4gICAgICAgIDB4MDgsIDB4ODgsIDB4NDgsIDB4YzgsIDB4MjgsIDB4YTgsIDB4NjgsIDB4ZTgsXG4gICAgICAgIDB4MTgsIDB4OTgsIDB4NTgsIDB4ZDgsIDB4MzgsIDB4YjgsIDB4NzgsIDB4ZjgsXG4gICAgICAgIDB4MDQsIDB4ODQsIDB4NDQsIDB4YzQsIDB4MjQsIDB4YTQsIDB4NjQsIDB4ZTQsXG4gICAgICAgIDB4MTQsIDB4OTQsIDB4NTQsIDB4ZDQsIDB4MzQsIDB4YjQsIDB4NzQsIDB4ZjQsXG4gICAgICAgIDB4MGMsIDB4OGMsIDB4NGMsIDB4Y2MsIDB4MmMsIDB4YWMsIDB4NmMsIDB4ZWMsXG4gICAgICAgIDB4MWMsIDB4OWMsIDB4NWMsIDB4ZGMsIDB4M2MsIDB4YmMsIDB4N2MsIDB4ZmMsXG4gICAgICAgIDB4MDIsIDB4ODIsIDB4NDIsIDB4YzIsIDB4MjIsIDB4YTIsIDB4NjIsIDB4ZTIsXG4gICAgICAgIDB4MTIsIDB4OTIsIDB4NTIsIDB4ZDIsIDB4MzIsIDB4YjIsIDB4NzIsIDB4ZjIsXG4gICAgICAgIDB4MGEsIDB4OGEsIDB4NGEsIDB4Y2EsIDB4MmEsIDB4YWEsIDB4NmEsIDB4ZWEsXG4gICAgICAgIDB4MWEsIDB4OWEsIDB4NWEsIDB4ZGEsIDB4M2EsIDB4YmEsIDB4N2EsIDB4ZmEsXG4gICAgICAgIDB4MDYsIDB4ODYsIDB4NDYsIDB4YzYsIDB4MjYsIDB4YTYsIDB4NjYsIDB4ZTYsXG4gICAgICAgIDB4MTYsIDB4OTYsIDB4NTYsIDB4ZDYsIDB4MzYsIDB4YjYsIDB4NzYsIDB4ZjYsXG4gICAgICAgIDB4MGUsIDB4OGUsIDB4NGUsIDB4Y2UsIDB4MmUsIDB4YWUsIDB4NmUsIDB4ZWUsXG4gICAgICAgIDB4MWUsIDB4OWUsIDB4NWUsIDB4ZGUsIDB4M2UsIDB4YmUsIDB4N2UsIDB4ZmUsXG4gICAgICAgIDB4MDEsIDB4ODEsIDB4NDEsIDB4YzEsIDB4MjEsIDB4YTEsIDB4NjEsIDB4ZTEsXG4gICAgICAgIDB4MTEsIDB4OTEsIDB4NTEsIDB4ZDEsIDB4MzEsIDB4YjEsIDB4NzEsIDB4ZjEsXG4gICAgICAgIDB4MDksIDB4ODksIDB4NDksIDB4YzksIDB4MjksIDB4YTksIDB4NjksIDB4ZTksXG4gICAgICAgIDB4MTksIDB4OTksIDB4NTksIDB4ZDksIDB4MzksIDB4YjksIDB4NzksIDB4ZjksXG4gICAgICAgIDB4MDUsIDB4ODUsIDB4NDUsIDB4YzUsIDB4MjUsIDB4YTUsIDB4NjUsIDB4ZTUsXG4gICAgICAgIDB4MTUsIDB4OTUsIDB4NTUsIDB4ZDUsIDB4MzUsIDB4YjUsIDB4NzUsIDB4ZjUsXG4gICAgICAgIDB4MGQsIDB4OGQsIDB4NGQsIDB4Y2QsIDB4MmQsIDB4YWQsIDB4NmQsIDB4ZWQsXG4gICAgICAgIDB4MWQsIDB4OWQsIDB4NWQsIDB4ZGQsIDB4M2QsIDB4YmQsIDB4N2QsIDB4ZmQsXG4gICAgICAgIDB4MDMsIDB4ODMsIDB4NDMsIDB4YzMsIDB4MjMsIDB4YTMsIDB4NjMsIDB4ZTMsXG4gICAgICAgIDB4MTMsIDB4OTMsIDB4NTMsIDB4ZDMsIDB4MzMsIDB4YjMsIDB4NzMsIDB4ZjMsXG4gICAgICAgIDB4MGIsIDB4OGIsIDB4NGIsIDB4Y2IsIDB4MmIsIDB4YWIsIDB4NmIsIDB4ZWIsXG4gICAgICAgIDB4MWIsIDB4OWIsIDB4NWIsIDB4ZGIsIDB4M2IsIDB4YmIsIDB4N2IsIDB4ZmIsXG4gICAgICAgIDB4MDcsIDB4ODcsIDB4NDcsIDB4YzcsIDB4MjcsIDB4YTcsIDB4NjcsIDB4ZTcsXG4gICAgICAgIDB4MTcsIDB4OTcsIDB4NTcsIDB4ZDcsIDB4MzcsIDB4YjcsIDB4NzcsIDB4ZjcsXG4gICAgICAgIDB4MGYsIDB4OGYsIDB4NGYsIDB4Y2YsIDB4MmYsIDB4YWYsIDB4NmYsIDB4ZWYsXG4gICAgICAgIDB4MWYsIDB4OWYsIDB4NWYsIDB4ZGYsIDB4M2YsIDB4YmYsIDB4N2YsIDB4ZmZcbiAgICBdLFxuICAgIFxuICAgIGNwbGVucyA9IFtcbiAgICAgICAgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMywgMTUsIDE3LCAxOSwgMjMsIDI3LCAzMSxcbiAgICAgICAgMzUsIDQzLCA1MSwgNTksIDY3LCA4MywgOTksIDExNSwgMTMxLCAxNjMsIDE5NSwgMjI3LCAyNTgsIDAsIDBcbiAgICBdLFxuXG4gICAgY3BsZXh0ID0gW1xuICAgICAgICAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAxLCAxLCAxLCAxLCAyLCAyLCAyLCAyLFxuICAgICAgICAzLCAzLCAzLCAzLCA0LCA0LCA0LCA0LCA1LCA1LCA1LCA1LCAwLCA5OSwgOTlcbiAgICBdLCAvKiA5OT09aW52YWxpZCAqL1xuXG4gICAgY3BkaXN0ID0gW1xuICAgICAgICAweDAwMDEsIDB4MDAwMiwgMHgwMDAzLCAweDAwMDQsIDB4MDAwNSwgMHgwMDA3LCAweDAwMDksIDB4MDAwZCxcbiAgICAgICAgMHgwMDExLCAweDAwMTksIDB4MDAyMSwgMHgwMDMxLCAweDAwNDEsIDB4MDA2MSwgMHgwMDgxLCAweDAwYzEsXG4gICAgICAgIDB4MDEwMSwgMHgwMTgxLCAweDAyMDEsIDB4MDMwMSwgMHgwNDAxLCAweDA2MDEsIDB4MDgwMSwgMHgwYzAxLFxuICAgICAgICAweDEwMDEsIDB4MTgwMSwgMHgyMDAxLCAweDMwMDEsIDB4NDAwMSwgMHg2MDAxXG4gICAgXSxcblxuICAgIGNwZGV4dCA9IFtcbiAgICAgICAgMCwgIDAsICAwLCAgMCwgIDEsICAxLCAgMiwgIDIsXG4gICAgICAgIDMsICAzLCAgNCwgIDQsICA1LCAgNSwgIDYsICA2LFxuICAgICAgICA3LCAgNywgIDgsICA4LCAgOSwgIDksIDEwLCAxMCxcbiAgICAgICAgMTEsIDExLCAxMiwgMTIsIDEzLCAxM1xuICAgIF0sXG4gICAgXG4gICAgYm9yZGVyID0gWzE2LCAxNywgMTgsIDAsIDgsIDcsIDksIDYsIDEwLCA1LCAxMSwgNCwgMTIsIDMsIDEzLCAyLCAxNCwgMSwgMTVdLFxuICAgIFxuICAgIGJBID0gYmFycmF5LFxuXG4gICAgYnl0ZXBvcz0wLFxuICAgIGJpdHBvcz0wLFxuICAgIGJiID0gMSxcbiAgICBiaXRzPTAsXG4gICAgXG4gICAgTkFNRU1BWCA9IDI1NixcbiAgICBcbiAgICBuYW1lQnVmID0gW10sXG4gICAgXG4gICAgZmlsZW91dDtcbiAgICBcbiAgICBmdW5jdGlvbiByZWFkQnl0ZSgpe1xuICAgICAgICBiaXRzKz04O1xuICAgICAgICBpZiAoYnl0ZXBvczxiQS5sZW5ndGgpe1xuICAgICAgICAgICAgLy9pZiAoZGVidWcpXG4gICAgICAgICAgICAvLyAgICBkb2N1bWVudC53cml0ZShieXRlcG9zK1wiOiBcIitiQVtieXRlcG9zXStcIjxicj5cIik7XG4gICAgICAgICAgICByZXR1cm4gYkFbYnl0ZXBvcysrXTtcbiAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGJ5dGVBbGlnbigpe1xuICAgICAgICBiYiA9IDE7XG4gICAgfTtcbiAgICBcbiAgICBmdW5jdGlvbiByZWFkQml0KCl7XG4gICAgICAgIHZhciBjYXJyeTtcbiAgICAgICAgYml0cysrO1xuICAgICAgICBjYXJyeSA9IChiYiAmIDEpO1xuICAgICAgICBiYiA+Pj0gMTtcbiAgICAgICAgaWYgKGJiPT0wKXtcbiAgICAgICAgICAgIGJiID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgICAgIGNhcnJ5ID0gKGJiICYgMSk7XG4gICAgICAgICAgICBiYiA9IChiYj4+MSkgfCAweDgwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjYXJyeTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVhZEJpdHMoYSkge1xuICAgICAgICB2YXIgcmVzID0gMCxcbiAgICAgICAgICAgIGkgPSBhO1xuICAgIFxuICAgICAgICB3aGlsZShpLS0pIHtcbiAgICAgICAgICAgIHJlcyA9IChyZXM8PDEpIHwgcmVhZEJpdCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmKGEpIHtcbiAgICAgICAgICAgIHJlcyA9IGJpdFJldmVyc2VbcmVzXT4+KDgtYSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xuICAgICAgICBcbiAgICBmdW5jdGlvbiBmbHVzaEJ1ZmZlcigpe1xuICAgICAgICAvL2RvY3VtZW50LndyaXRlKCdGTFVTSEJVRkZFUjonK2J1ZjMyayk7XG4gICAgICAgIGJJZHggPSAwO1xuICAgIH07XG4gICAgZnVuY3Rpb24gYWRkQnVmZmVyKGEpe1xuICAgICAgICBTSVpFKys7XG4gICAgICAgIC8vQ1JDPXVwZGNyYyhhLGNyYyk7XG4gICAgICAgIGJ1ZjMya1tiSWR4KytdID0gYTtcbiAgICAgICAgb3V0cHV0QXJyLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhKSk7XG4gICAgICAgIC8vb3V0cHV0Kz1TdHJpbmcuZnJvbUNoYXJDb2RlKGEpO1xuICAgICAgICBpZihiSWR4PT0weDgwMDApe1xuICAgICAgICAgICAgLy9kb2N1bWVudC53cml0ZSgnQUREQlVGRkVSOicrYnVmMzJrKTtcbiAgICAgICAgICAgIGJJZHg9MDtcbiAgICAgICAgfVxuICAgIH07XG4gICAgXG4gICAgZnVuY3Rpb24gSHVmTm9kZSgpIHtcbiAgICAgICAgdGhpcy5iMD0wO1xuICAgICAgICB0aGlzLmIxPTA7XG4gICAgICAgIHRoaXMuanVtcCA9IG51bGw7XG4gICAgICAgIHRoaXMuanVtcHBvcyA9IC0xO1xuICAgIH07XG5cbiAgICB2YXIgTElURVJBTFMgPSAyODg7XG4gICAgXG4gICAgdmFyIGxpdGVyYWxUcmVlID0gbmV3IEFycmF5KExJVEVSQUxTKTtcbiAgICB2YXIgZGlzdGFuY2VUcmVlID0gbmV3IEFycmF5KDMyKTtcbiAgICB2YXIgdHJlZXBvcz0wO1xuICAgIHZhciBQbGFjZXMgPSBudWxsO1xuICAgIHZhciBQbGFjZXMyID0gbnVsbDtcbiAgICBcbiAgICB2YXIgaW1wRGlzdGFuY2VUcmVlID0gbmV3IEFycmF5KDY0KTtcbiAgICB2YXIgaW1wTGVuZ3RoVHJlZSA9IG5ldyBBcnJheSg2NCk7XG4gICAgXG4gICAgdmFyIGxlbiA9IDA7XG4gICAgdmFyIGZwb3MgPSBuZXcgQXJyYXkoMTcpO1xuICAgIGZwb3NbMF09MDtcbiAgICB2YXIgZmxlbnM7XG4gICAgdmFyIGZtYXg7XG4gICAgXG4gICAgZnVuY3Rpb24gSXNQYXQoKSB7XG4gICAgICAgIHdoaWxlICgxKSB7XG4gICAgICAgICAgICBpZiAoZnBvc1tsZW5dID49IGZtYXgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgaWYgKGZsZW5zW2Zwb3NbbGVuXV0gPT0gbGVuKVxuICAgICAgICAgICAgICAgIHJldHVybiBmcG9zW2xlbl0rKztcbiAgICAgICAgICAgIGZwb3NbbGVuXSsrO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIFJlYygpIHtcbiAgICAgICAgdmFyIGN1cnBsYWNlID0gUGxhY2VzW3RyZWVwb3NdO1xuICAgICAgICB2YXIgdG1wO1xuICAgICAgICBpZiAoZGVidWcpXG4gICAgXHRcdGRvY3VtZW50LndyaXRlKFwiPGJyPmxlbjpcIitsZW4rXCIgdHJlZXBvczpcIit0cmVlcG9zKTtcbiAgICAgICAgaWYobGVuPT0xNykgeyAvL3dhciAxN1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIHRyZWVwb3MrKztcbiAgICAgICAgbGVuKys7XG4gICAgXHRcbiAgICAgICAgdG1wID0gSXNQYXQoKTtcbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwiPGJyPklzUGF0IFwiK3RtcCk7XG4gICAgICAgIGlmKHRtcCA+PSAwKSB7XG4gICAgICAgICAgICBjdXJwbGFjZS5iMCA9IHRtcDsgICAgLyogbGVhZiBjZWxsIGZvciAwLWJpdCAqL1xuICAgICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcIjxicj5iMCBcIitjdXJwbGFjZS5iMCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8qIE5vdCBhIExlYWYgY2VsbCAqL1xuICAgICAgICBjdXJwbGFjZS5iMCA9IDB4ODAwMDtcbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwiPGJyPmIwIFwiK2N1cnBsYWNlLmIwKTtcbiAgICAgICAgaWYoUmVjKCkpXG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgdG1wID0gSXNQYXQoKTtcbiAgICAgICAgaWYodG1wID49IDApIHtcbiAgICAgICAgICAgIGN1cnBsYWNlLmIxID0gdG1wOyAgICAvKiBsZWFmIGNlbGwgZm9yIDEtYml0ICovXG4gICAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwiPGJyPmIxIFwiK2N1cnBsYWNlLmIxKTtcbiAgICAgICAgICAgIGN1cnBsYWNlLmp1bXAgPSBudWxsOyAgICAvKiBKdXN0IGZvciB0aGUgZGlzcGxheSByb3V0aW5lICovXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvKiBOb3QgYSBMZWFmIGNlbGwgKi9cbiAgICAgICAgICAgIGN1cnBsYWNlLmIxID0gMHg4MDAwO1xuICAgICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcIjxicj5iMSBcIitjdXJwbGFjZS5iMSk7XG4gICAgICAgICAgICBjdXJwbGFjZS5qdW1wID0gUGxhY2VzW3RyZWVwb3NdO1xuICAgICAgICAgICAgY3VycGxhY2UuanVtcHBvcyA9IHRyZWVwb3M7XG4gICAgICAgICAgICBpZihSZWMoKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgICAgbGVuLS07XG4gICAgICAgIHJldHVybiAwO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBDcmVhdGVUcmVlKGN1cnJlbnRUcmVlLCBudW12YWwsIGxlbmd0aHMsIHNob3cpIHtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIC8qIENyZWF0ZSB0aGUgSHVmZm1hbiBkZWNvZGUgdHJlZS90YWJsZSAqL1xuICAgICAgICAvL2RvY3VtZW50LndyaXRlKFwiPGJyPmNyZWF0ZXRyZWU8YnI+XCIpO1xuICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgIFx0ZG9jdW1lbnQud3JpdGUoXCJjdXJyZW50VHJlZSBcIitjdXJyZW50VHJlZStcIiBudW12YWwgXCIrbnVtdmFsK1wiIGxlbmd0aHMgXCIrbGVuZ3RocytcIiBzaG93IFwiK3Nob3cpO1xuICAgICAgICBQbGFjZXMgPSBjdXJyZW50VHJlZTtcbiAgICAgICAgdHJlZXBvcz0wO1xuICAgICAgICBmbGVucyA9IGxlbmd0aHM7XG4gICAgICAgIGZtYXggID0gbnVtdmFsO1xuICAgICAgICBmb3IgKGk9MDtpPDE3O2krKylcbiAgICAgICAgICAgIGZwb3NbaV0gPSAwO1xuICAgICAgICBsZW4gPSAwO1xuICAgICAgICBpZihSZWMoKSkge1xuICAgICAgICAgICAgLy9mcHJpbnRmKHN0ZGVyciwgXCJpbnZhbGlkIGh1ZmZtYW4gdHJlZVxcblwiKTtcbiAgICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIFx0YWxlcnQoXCJpbnZhbGlkIGh1ZmZtYW4gdHJlZVxcblwiKTtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGVidWcpe1xuICAgICAgICBcdGRvY3VtZW50LndyaXRlKCc8YnI+VHJlZTogJytQbGFjZXMubGVuZ3RoKTtcbiAgICAgICAgXHRmb3IgKHZhciBhPTA7YTwzMjthKyspe1xuICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcIlBsYWNlc1tcIithK1wiXS5iMD1cIitQbGFjZXNbYV0uYjArXCI8YnI+XCIpO1xuICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcIlBsYWNlc1tcIithK1wiXS5iMT1cIitQbGFjZXNbYV0uYjErXCI8YnI+XCIpO1xuICAgICAgICBcdH1cbiAgICAgICAgfVxuICAgIFxuICAgICAgICAvKmlmKHNob3cpIHtcbiAgICAgICAgICAgIHZhciB0bXA7XG4gICAgICAgICAgICBmb3IodG1wPWN1cnJlbnRUcmVlO3RtcDxQbGFjZXM7dG1wKyspIHtcbiAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91dCwgXCIweCUwM3ggIDB4JTAzeCAoMHglMDR4KVwiLHRtcC1jdXJyZW50VHJlZSwgdG1wLT5qdW1wP3RtcC0+anVtcC1jdXJyZW50VHJlZTowLCh0bXAtPmp1bXA/dG1wLT5qdW1wLWN1cnJlbnRUcmVlOjApKjYrMHhjZjApO1xuICAgICAgICAgICAgICAgIGlmKCEodG1wLmIwICYgMHg4MDAwKSkge1xuICAgICAgICAgICAgICAgICAgICAvL2ZwcmludGYoc3Rkb3V0LCBcIiAgMHglMDN4ICglYylcIiwgdG1wLT5iMCwodG1wLT5iMDwyNTYgJiYgaXNwcmludCh0bXAtPmIwKSk/dG1wLT5iMDon77+9Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKCEodG1wLmIxICYgMHg4MDAwKSkge1xuICAgICAgICAgICAgICAgICAgICBpZigodG1wLmIwICYgMHg4MDAwKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGZwcmludGYoc3Rkb3V0LCBcIiAgICAgICAgICAgXCIpO1xuICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91dCwgXCIgIDB4JTAzeCAoJWMpXCIsIHRtcC0+YjEsKHRtcC0+YjE8MjU2ICYmIGlzcHJpbnQodG1wLT5iMSkpP3RtcC0+YjE6J++/vScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91dCwgXCJcXG5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0qL1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9O1xuICAgIFxuICAgIGZ1bmN0aW9uIERlY29kZVZhbHVlKGN1cnJlbnRUcmVlKSB7XG4gICAgICAgIHZhciBsZW4sIGksXG4gICAgICAgICAgICB4dHJlZXBvcz0wLFxuICAgICAgICAgICAgWCA9IGN1cnJlbnRUcmVlW3h0cmVlcG9zXSxcbiAgICAgICAgICAgIGI7XG5cbiAgICAgICAgLyogZGVjb2RlIG9uZSBzeW1ib2wgb2YgdGhlIGRhdGEgKi9cbiAgICAgICAgd2hpbGUoMSkge1xuICAgICAgICAgICAgYj1yZWFkQml0KCk7XG4gICAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwiYj1cIitiKTtcbiAgICAgICAgICAgIGlmKGIpIHtcbiAgICAgICAgICAgICAgICBpZighKFguYjEgJiAweDgwMDApKXtcbiAgICAgICAgICAgICAgICBcdGlmIChkZWJ1ZylcbiAgICAgICAgICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcInJldDFcIik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBYLmIxOyAgICAvKiBJZiBsZWFmIG5vZGUsIHJldHVybiBkYXRhICovXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIFggPSBYLmp1bXA7XG4gICAgICAgICAgICAgICAgbGVuID0gY3VycmVudFRyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAoaT0wO2k8bGVuO2krKyl7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50VHJlZVtpXT09PVgpe1xuICAgICAgICAgICAgICAgICAgICAgICAgeHRyZWVwb3M9aTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8veHRyZWVwb3MrKztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYoIShYLmIwICYgMHg4MDAwKSl7XG4gICAgICAgICAgICAgICAgXHRpZiAoZGVidWcpXG4gICAgICAgICAgICAgICAgICAgIFx0ZG9jdW1lbnQud3JpdGUoXCJyZXQyXCIpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gWC5iMDsgICAgLyogSWYgbGVhZiBub2RlLCByZXR1cm4gZGF0YSAqL1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL1grKzsgLy8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz9cbiAgICAgICAgICAgICAgICB4dHJlZXBvcysrO1xuICAgICAgICAgICAgICAgIFggPSBjdXJyZW50VHJlZVt4dHJlZXBvc107XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwicmV0M1wiKTtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH07XG4gICAgXG4gICAgZnVuY3Rpb24gRGVmbGF0ZUxvb3AoKSB7XG4gICAgdmFyIGxhc3QsIGMsIHR5cGUsIGksIGxlbjtcblxuICAgIGRvIHtcbiAgICAgICAgLyppZigobGFzdCA9IHJlYWRCaXQoKSkpe1xuICAgICAgICAgICAgZnByaW50ZihlcnJmcCwgXCJMYXN0IEJsb2NrOiBcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcHJpbnRmKGVycmZwLCBcIk5vdCBMYXN0IEJsb2NrOiBcIik7XG4gICAgICAgIH0qL1xuICAgICAgICBsYXN0ID0gcmVhZEJpdCgpO1xuICAgICAgICB0eXBlID0gcmVhZEJpdHMoMik7XG4gICAgICAgIHN3aXRjaCh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICBcdGlmIChkZWJ1ZylcbiAgICAgICAgICAgICAgICBcdGFsZXJ0KFwiU3RvcmVkXFxuXCIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgXHRpZiAoZGVidWcpXG4gICAgICAgICAgICAgICAgXHRhbGVydChcIkZpeGVkIEh1ZmZtYW4gY29kZXNcXG5cIik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICBcdGlmIChkZWJ1ZylcbiAgICAgICAgICAgICAgICBcdGFsZXJ0KFwiRHluYW1pYyBIdWZmbWFuIGNvZGVzXFxuXCIpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgXHRpZiAoZGVidWcpXG4gICAgICAgICAgICAgICAgXHRhbGVydChcIlJlc2VydmVkIGJsb2NrIHR5cGUhIVxcblwiKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBcdGlmIChkZWJ1ZylcbiAgICAgICAgICAgICAgICBcdGFsZXJ0KFwiVW5leHBlY3RlZCB2YWx1ZSAlZCFcXG5cIiwgdHlwZSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBpZih0eXBlPT0wKSB7XG4gICAgICAgICAgICB2YXIgYmxvY2tMZW4sIGNTdW07XG5cbiAgICAgICAgICAgIC8vIFN0b3JlZCBcbiAgICAgICAgICAgIGJ5dGVBbGlnbigpO1xuICAgICAgICAgICAgYmxvY2tMZW4gPSByZWFkQnl0ZSgpO1xuICAgICAgICAgICAgYmxvY2tMZW4gfD0gKHJlYWRCeXRlKCk8PDgpO1xuXG4gICAgICAgICAgICBjU3VtID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgICAgIGNTdW0gfD0gKHJlYWRCeXRlKCk8PDgpO1xuXG4gICAgICAgICAgICBpZigoKGJsb2NrTGVuIF4gfmNTdW0pICYgMHhmZmZmKSkge1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwiQmxvY2tMZW4gY2hlY2tzdW0gbWlzbWF0Y2hcXG5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZShibG9ja0xlbi0tKSB7XG4gICAgICAgICAgICAgICAgYyA9IHJlYWRCeXRlKCk7XG4gICAgICAgICAgICAgICAgYWRkQnVmZmVyKGMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYodHlwZT09MSkge1xuICAgICAgICAgICAgdmFyIGo7XG5cbiAgICAgICAgICAgIC8qIEZpeGVkIEh1ZmZtYW4gdGFibGVzIC0tIGZpeGVkIGRlY29kZSByb3V0aW5lICovXG4gICAgICAgICAgICB3aGlsZSgxKSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgIDI1NiAgICAwMDAwMDAwICAgICAgICAwXG4gICAgICAgICAgICAgICAgOiAgIDogICAgIDpcbiAgICAgICAgICAgICAgICAyNzkgICAgMDAxMDExMSAgICAgICAgMjNcbiAgICAgICAgICAgICAgICAwICAgMDAxMTAwMDAgICAgNDhcbiAgICAgICAgICAgICAgICA6ICAgIDogICAgICA6XG4gICAgICAgICAgICAgICAgMTQzICAgIDEwMTExMTExICAgIDE5MVxuICAgICAgICAgICAgICAgIDI4MCAxMTAwMDAwMCAgICAxOTJcbiAgICAgICAgICAgICAgICA6ICAgIDogICAgICA6XG4gICAgICAgICAgICAgICAgMjg3IDExMDAwMTExICAgIDE5OVxuICAgICAgICAgICAgICAgIDE0NCAgICAxMTAwMTAwMDAgICAgNDAwXG4gICAgICAgICAgICAgICAgOiAgICA6ICAgICAgIDpcbiAgICAgICAgICAgICAgICAyNTUgICAgMTExMTExMTExICAgIDUxMVxuICAgIFxuICAgICAgICAgICAgICAgIE5vdGUgdGhlIGJpdCBvcmRlciFcbiAgICAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICBqID0gKGJpdFJldmVyc2VbcmVhZEJpdHMoNyldPj4xKTtcbiAgICAgICAgICAgIGlmKGogPiAyMykge1xuICAgICAgICAgICAgICAgIGogPSAoajw8MSkgfCByZWFkQml0KCk7ICAgIC8qIDQ4Li4yNTUgKi9cblxuICAgICAgICAgICAgICAgIGlmKGogPiAxOTkpIHsgICAgLyogMjAwLi4yNTUgKi9cbiAgICAgICAgICAgICAgICAgICAgaiAtPSAxMjg7ICAgIC8qICA3Mi4uMTI3ICovXG4gICAgICAgICAgICAgICAgICAgIGogPSAoajw8MSkgfCByZWFkQml0KCk7ICAgICAgICAvKiAxNDQuLjI1NSA8PCAqL1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAvKiAgNDguLjE5OSAqL1xuICAgICAgICAgICAgICAgICAgICBqIC09IDQ4OyAgICAvKiAgIDAuLjE1MSAqL1xuICAgICAgICAgICAgICAgICAgICBpZihqID4gMTQzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBqID0gaisxMzY7ICAgIC8qIDI4MC4uMjg3IDw8ICovXG4gICAgICAgICAgICAgICAgICAgICAgICAvKiAgIDAuLjE0MyA8PCAqL1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHsgICAgLyogICAwLi4yMyAqL1xuICAgICAgICAgICAgICAgIGogKz0gMjU2OyAgICAvKiAyNTYuLjI3OSA8PCAqL1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoaiA8IDI1Nikge1xuICAgICAgICAgICAgICAgIGFkZEJ1ZmZlcihqKTtcbiAgICAgICAgICAgICAgICAvL2RvY3VtZW50LndyaXRlKFwib3V0OlwiK1N0cmluZy5mcm9tQ2hhckNvZGUoaikpO1xuICAgICAgICAgICAgICAgIC8qZnByaW50ZihlcnJmcCwgXCJAJWQgJTAyeFxcblwiLCBTSVpFLCBqKTsqL1xuICAgICAgICAgICAgfSBlbHNlIGlmKGogPT0gMjU2KSB7XG4gICAgICAgICAgICAgICAgLyogRU9GICovXG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBsZW4sIGRpc3Q7XG5cbiAgICAgICAgICAgICAgICBqIC09IDI1NiArIDE7ICAgIC8qIGJ5dGVzICsgRU9GICovXG4gICAgICAgICAgICAgICAgbGVuID0gcmVhZEJpdHMoY3BsZXh0W2pdKSArIGNwbGVuc1tqXTtcblxuICAgICAgICAgICAgICAgIGogPSBiaXRSZXZlcnNlW3JlYWRCaXRzKDUpXT4+MztcbiAgICAgICAgICAgICAgICBpZihjcGRleHRbal0gPiA4KSB7XG4gICAgICAgICAgICAgICAgICAgIGRpc3QgPSByZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgICAgICAgZGlzdCB8PSAocmVhZEJpdHMoY3BkZXh0W2pdLTgpPDw4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkaXN0ID0gcmVhZEJpdHMoY3BkZXh0W2pdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGlzdCArPSBjcGRpc3Rbal07XG5cbiAgICAgICAgICAgICAgICAvKmZwcmludGYoZXJyZnAsIFwiQCVkIChsJTAyeCxkJTA0eClcXG5cIiwgU0laRSwgbGVuLCBkaXN0KTsqL1xuICAgICAgICAgICAgICAgIGZvcihqPTA7ajxsZW47aisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjID0gYnVmMzJrWyhiSWR4IC0gZGlzdCkgJiAweDdmZmZdO1xuICAgICAgICAgICAgICAgICAgICBhZGRCdWZmZXIoYyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSAvLyB3aGlsZVxuICAgICAgICB9IGVsc2UgaWYodHlwZT09Mikge1xuICAgICAgICAgICAgdmFyIGosIG4sIGxpdGVyYWxDb2RlcywgZGlzdENvZGVzLCBsZW5Db2RlcztcbiAgICAgICAgICAgIHZhciBsbCA9IG5ldyBBcnJheSgyODgrMzIpOyAgICAvLyBcInN0YXRpY1wiIGp1c3QgdG8gcHJlc2VydmUgc3RhY2tcbiAgICBcbiAgICAgICAgICAgIC8vIER5bmFtaWMgSHVmZm1hbiB0YWJsZXMgXG4gICAgXG4gICAgICAgICAgICBsaXRlcmFsQ29kZXMgPSAyNTcgKyByZWFkQml0cyg1KTtcbiAgICAgICAgICAgIGRpc3RDb2RlcyA9IDEgKyByZWFkQml0cyg1KTtcbiAgICAgICAgICAgIGxlbkNvZGVzID0gNCArIHJlYWRCaXRzKDQpO1xuICAgICAgICAgICAgLy9kb2N1bWVudC53cml0ZShcIjxicj5wYXJhbTogXCIrbGl0ZXJhbENvZGVzK1wiIFwiK2Rpc3RDb2RlcytcIiBcIitsZW5Db2RlcytcIjxicj5cIik7XG4gICAgICAgICAgICBmb3Ioaj0wOyBqPDE5OyBqKyspIHtcbiAgICAgICAgICAgICAgICBsbFtqXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgXG4gICAgICAgICAgICAvLyBHZXQgdGhlIGRlY29kZSB0cmVlIGNvZGUgbGVuZ3Roc1xuICAgIFxuICAgICAgICAgICAgLy9kb2N1bWVudC53cml0ZShcIjxicj5cIik7XG4gICAgICAgICAgICBmb3Ioaj0wOyBqPGxlbkNvZGVzOyBqKyspIHtcbiAgICAgICAgICAgICAgICBsbFtib3JkZXJbal1dID0gcmVhZEJpdHMoMyk7XG4gICAgICAgICAgICAgICAgLy9kb2N1bWVudC53cml0ZShsbFtib3JkZXJbal1dK1wiIFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vZnByaW50ZihlcnJmcCwgXCJcXG5cIik7XG4gICAgICAgICAgICAvL2RvY3VtZW50LndyaXRlKCc8YnI+bGw6JytsbCk7XG4gICAgICAgICAgICBsZW4gPSBkaXN0YW5jZVRyZWUubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChpPTA7IGk8bGVuOyBpKyspXG4gICAgICAgICAgICAgICAgZGlzdGFuY2VUcmVlW2ldPW5ldyBIdWZOb2RlKCk7XG4gICAgICAgICAgICBpZihDcmVhdGVUcmVlKGRpc3RhbmNlVHJlZSwgMTksIGxsLCAwKSkge1xuICAgICAgICAgICAgICAgIGZsdXNoQnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVidWcpe1xuICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcIjxicj5kaXN0YW5jZVRyZWVcIik7XG4gICAgICAgICAgICBcdGZvcih2YXIgYT0wO2E8ZGlzdGFuY2VUcmVlLmxlbmd0aDthKyspe1xuICAgICAgICAgICAgICAgIFx0ZG9jdW1lbnQud3JpdGUoXCI8YnI+XCIrZGlzdGFuY2VUcmVlW2FdLmIwK1wiIFwiK2Rpc3RhbmNlVHJlZVthXS5iMStcIiBcIitkaXN0YW5jZVRyZWVbYV0uanVtcCtcIiBcIitkaXN0YW5jZVRyZWVbYV0uanVtcHBvcyk7XG4gICAgICAgICAgICAgICAgXHQvKmlmIChkaXN0YW5jZVRyZWVbYV0uanVtcHBvcyE9LTEpXG4gICAgICAgICAgICAgICAgICAgIFx0ZG9jdW1lbnQud3JpdGUoXCIgXCIrZGlzdGFuY2VUcmVlW2FdLmp1bXAuYjArXCIgXCIrZGlzdGFuY2VUcmVlW2FdLmp1bXAuYjEpO1xuICAgICAgICAgICAgICAgIFx0Ki9cbiAgICAgICAgICAgIFx0fVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy9kb2N1bWVudC53cml0ZSgnPEJSPnRyZWUgY3JlYXRlZCcpO1xuICAgIFxuICAgICAgICAgICAgLy9yZWFkIGluIGxpdGVyYWwgYW5kIGRpc3RhbmNlIGNvZGUgbGVuZ3Roc1xuICAgICAgICAgICAgbiA9IGxpdGVyYWxDb2RlcyArIGRpc3RDb2RlcztcbiAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgICAgdmFyIHo9LTE7XG4gICAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwiPGJyPm49XCIrbitcIiBiaXRzOiBcIitiaXRzK1wiPGJyPlwiKTtcbiAgICAgICAgICAgIHdoaWxlKGkgPCBuKSB7XG4gICAgICAgICAgICAgICAgeisrO1xuICAgICAgICAgICAgICAgIGogPSBEZWNvZGVWYWx1ZShkaXN0YW5jZVRyZWUpO1xuICAgICAgICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgICAgICBcdGRvY3VtZW50LndyaXRlKFwiPGJyPlwiK3orXCIgaTpcIitpK1wiIGRlY29kZTogXCIraitcIiAgICBiaXRzIFwiK2JpdHMrXCI8YnI+XCIpO1xuICAgICAgICAgICAgICAgIGlmKGo8MTYpIHsgICAgLy8gbGVuZ3RoIG9mIGNvZGUgaW4gYml0cyAoMC4uMTUpXG4gICAgICAgICAgICAgICAgICAgICAgIGxsW2krK10gPSBqO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZihqPT0xNikgeyAgICAvLyByZXBlYXQgbGFzdCBsZW5ndGggMyB0byA2IHRpbWVzIFxuICAgICAgICAgICAgICAgICAgICAgICB2YXIgbDtcbiAgICAgICAgICAgICAgICAgICAgaiA9IDMgKyByZWFkQml0cygyKTtcbiAgICAgICAgICAgICAgICAgICAgaWYoaStqID4gbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmx1c2hCdWZmZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGwgPSBpID8gbGxbaS0xXSA6IDA7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlKGotLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGxbaSsrXSA9IGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZihqPT0xNykgeyAgICAgICAgLy8gMyB0byAxMCB6ZXJvIGxlbmd0aCBjb2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgaiA9IDMgKyByZWFkQml0cygzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgIC8vIGogPT0gMTg6IDExIHRvIDEzOCB6ZXJvIGxlbmd0aCBjb2RlcyBcbiAgICAgICAgICAgICAgICAgICAgICAgIGogPSAxMSArIHJlYWRCaXRzKDcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmKGkraiA+IG4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsdXNoQnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB3aGlsZShqLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxsW2krK10gPSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLypmb3Ioaj0wOyBqPGxpdGVyYWxDb2RlcytkaXN0Q29kZXM7IGorKykge1xuICAgICAgICAgICAgICAgIC8vZnByaW50ZihlcnJmcCwgXCIlZCBcIiwgbGxbal0pO1xuICAgICAgICAgICAgICAgIGlmICgoaiY3KT09NylcbiAgICAgICAgICAgICAgICAgICAgZnByaW50ZihlcnJmcCwgXCJcXG5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmcHJpbnRmKGVycmZwLCBcIlxcblwiKTsqL1xuICAgICAgICAgICAgLy8gQ2FuIG92ZXJ3cml0ZSB0cmVlIGRlY29kZSB0cmVlIGFzIGl0IGlzIG5vdCB1c2VkIGFueW1vcmVcbiAgICAgICAgICAgIGxlbiA9IGxpdGVyYWxUcmVlLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAoaT0wOyBpPGxlbjsgaSsrKVxuICAgICAgICAgICAgICAgIGxpdGVyYWxUcmVlW2ldPW5ldyBIdWZOb2RlKCk7XG4gICAgICAgICAgICBpZihDcmVhdGVUcmVlKGxpdGVyYWxUcmVlLCBsaXRlcmFsQ29kZXMsIGxsLCAwKSkge1xuICAgICAgICAgICAgICAgIGZsdXNoQnVmZmVyKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZW4gPSBsaXRlcmFsVHJlZS5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGk9MDsgaTxsZW47IGkrKylcbiAgICAgICAgICAgICAgICBkaXN0YW5jZVRyZWVbaV09bmV3IEh1Zk5vZGUoKTtcbiAgICAgICAgICAgIHZhciBsbDIgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgICAgIGZvciAoaT1saXRlcmFsQ29kZXM7IGkgPGxsLmxlbmd0aDsgaSsrKXtcbiAgICAgICAgICAgICAgICBsbDJbaS1saXRlcmFsQ29kZXNdPWxsW2ldO1xuICAgICAgICAgICAgfSAgICBcbiAgICAgICAgICAgIGlmKENyZWF0ZVRyZWUoZGlzdGFuY2VUcmVlLCBkaXN0Q29kZXMsIGxsMiwgMCkpIHtcbiAgICAgICAgICAgICAgICBmbHVzaEJ1ZmZlcigpO1xuICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICBcdFx0ZG9jdW1lbnQud3JpdGUoXCI8YnI+bGl0ZXJhbFRyZWVcIik7XG4gICAgICAgICAgICBvdXRlcjpcbiAgICAgICAgICAgIHdoaWxlKDEpIHtcbiAgICAgICAgICAgICAgICBqID0gRGVjb2RlVmFsdWUobGl0ZXJhbFRyZWUpO1xuICAgICAgICAgICAgICAgIGlmKGogPj0gMjU2KSB7ICAgICAgICAvLyBJbiBDNjQ6IGlmIGNhcnJ5IHNldFxuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuLCBkaXN0O1xuICAgICAgICAgICAgICAgICAgICBqIC09IDI1NjtcbiAgICAgICAgICAgICAgICAgICAgaWYoaiA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBFT0ZcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgICAgICAgICAgbGVuID0gcmVhZEJpdHMoY3BsZXh0W2pdKSArIGNwbGVuc1tqXTtcbiAgICBcbiAgICAgICAgICAgICAgICAgICAgaiA9IERlY29kZVZhbHVlKGRpc3RhbmNlVHJlZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmKGNwZGV4dFtqXSA+IDgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3QgPSByZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpc3QgfD0gKHJlYWRCaXRzKGNwZGV4dFtqXS04KTw8OCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaXN0ID0gcmVhZEJpdHMoY3BkZXh0W2pdKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkaXN0ICs9IGNwZGlzdFtqXTtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUobGVuLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKGJJZHggLSBkaXN0IDwgMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrIG91dGVyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGMgPSBidWYzMmtbKGJJZHggLSBkaXN0KSAmIDB4N2ZmZl07XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRCdWZmZXIoYyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhZGRCdWZmZXIoaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSB3aGlsZSghbGFzdCk7XG4gICAgZmx1c2hCdWZmZXIoKTtcblxuICAgIGJ5dGVBbGlnbigpO1xuICAgIHJldHVybiAwO1xufTtcblxuSlhHLlV0aWwuVW56aXAucHJvdG90eXBlLnVuemlwRmlsZSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgaTtcblx0dGhpcy51bnppcCgpO1xuXHQvL2FsZXJ0KHVuemlwcGVkWzBdWzFdKTtcblx0Zm9yIChpPTA7aTx1bnppcHBlZC5sZW5ndGg7aSsrKXtcblx0XHRpZih1bnppcHBlZFtpXVsxXT09bmFtZSkge1xuXHRcdFx0cmV0dXJuIHVuemlwcGVkW2ldWzBdO1xuXHRcdH1cblx0fVxuXHRcbiAgfTtcblxuSlhHLlV0aWwuVW56aXAucHJvdG90eXBlLmRlZmxhdGUgPSBmdW5jdGlvbigpIHtcbiAgICBvdXRwdXRBcnIgPSBbXTtcbiAgICB2YXIgdG1wID0gW107XG4gICAgbW9kZVpJUCA9IGZhbHNlO1xuICAgIERlZmxhdGVMb29wKCk7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuICAgIHVuemlwcGVkW2ZpbGVzXSA9IG5ldyBBcnJheSgyKTtcbiAgICB1bnppcHBlZFtmaWxlc11bMF0gPSBvdXRwdXRBcnIuam9pbignJyk7XG4gICAgdW56aXBwZWRbZmlsZXNdWzFdID0gXCJERUZMQVRFXCI7XG4gICAgZmlsZXMrKztcbiAgICByZXR1cm4gdW56aXBwZWQ7XG59ICAgIFxuICAgIFxuSlhHLlV0aWwuVW56aXAucHJvdG90eXBlLnVuemlwID0gZnVuY3Rpb24oKSB7XG5cdC8vY29udmVydFRvQnl0ZUFycmF5KGlucHV0KTtcblx0aWYgKGRlYnVnKVxuXHRcdGFsZXJ0KGJBKTtcblx0Lypmb3IgKGk9MDtpPGJBLmxlbmd0aCo4O2krKyl7XG5cdFx0ZG9jdW1lbnQud3JpdGUocmVhZEJpdCgpKTtcblx0XHRpZiAoKGkrMSklOD09MClcblx0XHRcdGRvY3VtZW50LndyaXRlKFwiIFwiKTtcblx0fSovXG5cdC8qZm9yIChpPTA7aTxiQS5sZW5ndGg7aSsrKXtcblx0XHRkb2N1bWVudC53cml0ZShyZWFkQnl0ZSgpK1wiIFwiKTtcblx0XHRpZiAoKGkrMSklOD09MClcblx0XHRcdGRvY3VtZW50LndyaXRlKFwiIFwiKTtcblx0fVxuXHRmb3IgKGk9MDtpPGJBLmxlbmd0aDtpKyspe1xuXHRcdGRvY3VtZW50LndyaXRlKGJBW2ldK1wiIFwiKTtcblx0XHRpZiAoKGkrMSklMTY9PTApXG5cdFx0XHRkb2N1bWVudC53cml0ZShcIjxicj5cIik7XG5cdH1cdFxuXHQqL1xuXHQvL2FsZXJ0KGJBKTtcblx0bmV4dEZpbGUoKTtcblx0cmV0dXJuIHVuemlwcGVkO1xuICB9O1xuICAgIFxuIGZ1bmN0aW9uIG5leHRGaWxlKCl7XG4gXHRpZiAoZGVidWcpXG4gXHRcdGFsZXJ0KFwiTkVYVEZJTEVcIik7XG4gXHRvdXRwdXRBcnIgPSBbXTtcbiBcdHZhciB0bXAgPSBbXTtcbiBcdG1vZGVaSVAgPSBmYWxzZTtcblx0dG1wWzBdID0gcmVhZEJ5dGUoKTtcblx0dG1wWzFdID0gcmVhZEJ5dGUoKTtcblx0aWYgKGRlYnVnKVxuXHRcdGFsZXJ0KFwidHlwZTogXCIrdG1wWzBdK1wiIFwiK3RtcFsxXSk7XG5cdGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI3OFwiLDE2KSAmJiB0bXBbMV0gPT0gcGFyc2VJbnQoXCJkYVwiLDE2KSl7IC8vR1pJUFxuXHRcdGlmIChkZWJ1Zylcblx0XHRcdGFsZXJ0KFwiR0VPTkV4VC1HWklQXCIpO1xuXHRcdERlZmxhdGVMb29wKCk7XG5cdFx0aWYgKGRlYnVnKVxuXHRcdFx0YWxlcnQob3V0cHV0QXJyLmpvaW4oJycpKTtcblx0XHR1bnppcHBlZFtmaWxlc10gPSBuZXcgQXJyYXkoMik7XG4gICAgXHR1bnppcHBlZFtmaWxlc11bMF0gPSBvdXRwdXRBcnIuam9pbignJyk7XG4gICAgXHR1bnppcHBlZFtmaWxlc11bMV0gPSBcImdlb25leHQuZ3h0XCI7XG4gICAgXHRmaWxlcysrO1xuXHR9XG5cdGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI3OFwiLDE2KSAmJiB0bXBbMV0gPT0gcGFyc2VJbnQoXCI5Y1wiLDE2KSl7IC8vWkxJQlxuXHRcdGlmIChkZWJ1Zylcblx0XHRcdGFsZXJ0KFwiWkxJQlwiKTtcblx0XHREZWZsYXRlTG9vcCgpO1xuXHRcdGlmIChkZWJ1Zylcblx0XHRcdGFsZXJ0KG91dHB1dEFyci5qb2luKCcnKSk7XG5cdFx0dW56aXBwZWRbZmlsZXNdID0gbmV3IEFycmF5KDIpO1xuICAgIFx0dW56aXBwZWRbZmlsZXNdWzBdID0gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgIFx0dW56aXBwZWRbZmlsZXNdWzFdID0gXCJaTElCXCI7XG4gICAgXHRmaWxlcysrO1xuXHR9XG5cdGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCIxZlwiLDE2KSAmJiB0bXBbMV0gPT0gcGFyc2VJbnQoXCI4YlwiLDE2KSl7IC8vR1pJUFxuXHRcdGlmIChkZWJ1Zylcblx0XHRcdGFsZXJ0KFwiR1pJUFwiKTtcblx0XHQvL0RlZmxhdGVMb29wKCk7XG5cdFx0c2tpcGRpcigpO1xuXHRcdGlmIChkZWJ1Zylcblx0XHRcdGFsZXJ0KG91dHB1dEFyci5qb2luKCcnKSk7XG5cdFx0dW56aXBwZWRbZmlsZXNdID0gbmV3IEFycmF5KDIpO1xuICAgIFx0dW56aXBwZWRbZmlsZXNdWzBdID0gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgIFx0dW56aXBwZWRbZmlsZXNdWzFdID0gXCJmaWxlXCI7XG4gICAgXHRmaWxlcysrO1xuXHR9XG5cdGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI1MFwiLDE2KSAmJiB0bXBbMV0gPT0gcGFyc2VJbnQoXCI0YlwiLDE2KSl7IC8vWklQXG5cdFx0bW9kZVpJUCA9IHRydWU7XG5cdFx0dG1wWzJdID0gcmVhZEJ5dGUoKTtcblx0XHR0bXBbM10gPSByZWFkQnl0ZSgpO1xuXHRcdGlmICh0bXBbMl0gPT0gcGFyc2VJbnQoXCIzXCIsMTYpICYmIHRtcFszXSA9PSBwYXJzZUludChcIjRcIiwxNikpe1xuXHRcdFx0Ly9NT0RFX1pJUFxuXHRcdFx0dG1wWzBdID0gcmVhZEJ5dGUoKTtcblx0XHRcdHRtcFsxXSA9IHJlYWRCeXRlKCk7XG5cdFx0XHRpZiAoZGVidWcpXG5cdFx0XHRcdGFsZXJ0KFwiWklQLVZlcnNpb246IFwiK3RtcFsxXStcIiBcIit0bXBbMF0vMTArXCIuXCIrdG1wWzBdJTEwKTtcblx0XHRcdFxuXHRcdFx0Z3BmbGFncyA9IHJlYWRCeXRlKCk7XG5cdFx0XHRncGZsYWdzIHw9IChyZWFkQnl0ZSgpPDw4KTtcblx0XHRcdGlmIChkZWJ1Zylcblx0XHRcdFx0YWxlcnQoXCJncGZsYWdzOiBcIitncGZsYWdzKTtcblx0XHRcdFxuXHRcdFx0dmFyIG1ldGhvZCA9IHJlYWRCeXRlKCk7XG5cdFx0XHRtZXRob2QgfD0gKHJlYWRCeXRlKCk8PDgpO1xuXHRcdFx0aWYgKGRlYnVnKVxuXHRcdFx0XHRhbGVydChcIm1ldGhvZDogXCIrbWV0aG9kKTtcblx0XHRcdFxuXHRcdFx0cmVhZEJ5dGUoKTtcblx0XHRcdHJlYWRCeXRlKCk7XG5cdFx0XHRyZWFkQnl0ZSgpO1xuXHRcdFx0cmVhZEJ5dGUoKTtcblx0XHRcdFxuXHRcdFx0dmFyIGNyYyA9IHJlYWRCeXRlKCk7XG5cdFx0XHRjcmMgfD0gKHJlYWRCeXRlKCk8PDgpO1xuXHRcdFx0Y3JjIHw9IChyZWFkQnl0ZSgpPDwxNik7XG5cdFx0XHRjcmMgfD0gKHJlYWRCeXRlKCk8PDI0KTtcblx0XHRcdFxuXHRcdFx0dmFyIGNvbXBTaXplID0gcmVhZEJ5dGUoKTtcblx0XHRcdGNvbXBTaXplIHw9IChyZWFkQnl0ZSgpPDw4KTtcblx0XHRcdGNvbXBTaXplIHw9IChyZWFkQnl0ZSgpPDwxNik7XG5cdFx0XHRjb21wU2l6ZSB8PSAocmVhZEJ5dGUoKTw8MjQpO1xuXHRcdFx0XG5cdFx0XHR2YXIgc2l6ZSA9IHJlYWRCeXRlKCk7XG5cdFx0XHRzaXplIHw9IChyZWFkQnl0ZSgpPDw4KTtcblx0XHRcdHNpemUgfD0gKHJlYWRCeXRlKCk8PDE2KTtcblx0XHRcdHNpemUgfD0gKHJlYWRCeXRlKCk8PDI0KTtcblx0XHRcdFxuXHRcdFx0aWYgKGRlYnVnKVxuXHRcdFx0XHRhbGVydChcImxvY2FsIENSQzogXCIrY3JjK1wiXFxubG9jYWwgU2l6ZTogXCIrc2l6ZStcIlxcbmxvY2FsIENvbXBTaXplOiBcIitjb21wU2l6ZSk7XG5cdFx0XHRcblx0XHRcdHZhciBmaWxlbGVuID0gcmVhZEJ5dGUoKTtcblx0XHRcdGZpbGVsZW4gfD0gKHJlYWRCeXRlKCk8PDgpO1xuXHRcdFx0XG5cdFx0XHR2YXIgZXh0cmFsZW4gPSByZWFkQnl0ZSgpO1xuXHRcdFx0ZXh0cmFsZW4gfD0gKHJlYWRCeXRlKCk8PDgpO1xuXHRcdFx0XG5cdFx0XHRpZiAoZGVidWcpXG5cdFx0XHRcdGFsZXJ0KFwiZmlsZWxlbiBcIitmaWxlbGVuKTtcblx0XHRcdGkgPSAwO1xuXHRcdFx0bmFtZUJ1ZiA9IFtdO1xuXHRcdFx0d2hpbGUgKGZpbGVsZW4tLSl7IFxuXHRcdFx0XHR2YXIgYyA9IHJlYWRCeXRlKCk7XG5cdFx0XHRcdGlmIChjID09IFwiL1wiIHwgYyA9PVwiOlwiKXtcblx0XHRcdFx0XHRpID0gMDtcblx0XHRcdFx0fSBlbHNlIGlmIChpIDwgTkFNRU1BWC0xKVxuXHRcdFx0XHRcdG5hbWVCdWZbaSsrXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYyk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoZGVidWcpXG5cdFx0XHRcdGFsZXJ0KFwibmFtZUJ1ZjogXCIrbmFtZUJ1Zik7XG5cdFx0XHRcblx0XHRcdC8vbmFtZUJ1ZltpXSA9IFwiXFwwXCI7XG5cdFx0XHRpZiAoIWZpbGVvdXQpXG5cdFx0XHRcdGZpbGVvdXQgPSBuYW1lQnVmO1xuXHRcdFx0XG5cdFx0XHR2YXIgaSA9IDA7XG5cdFx0XHR3aGlsZSAoaSA8IGV4dHJhbGVuKXtcblx0XHRcdFx0YyA9IHJlYWRCeXRlKCk7XG5cdFx0XHRcdGkrKztcblx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRDUkMgPSAweGZmZmZmZmZmO1xuXHRcdFx0U0laRSA9IDA7XG5cdFx0XHRcblx0XHRcdGlmIChzaXplID0gMCAmJiBmaWxlT3V0LmNoYXJBdChmaWxlb3V0Lmxlbmd0aC0xKT09XCIvXCIpe1xuXHRcdFx0XHQvL3NraXBkaXJcblx0XHRcdFx0aWYgKGRlYnVnKVxuXHRcdFx0XHRcdGFsZXJ0KFwic2tpcGRpclwiKTtcblx0XHRcdH1cblx0XHRcdGlmIChtZXRob2QgPT0gOCl7XG5cdFx0XHRcdERlZmxhdGVMb29wKCk7XG5cdFx0XHRcdGlmIChkZWJ1Zylcblx0XHRcdFx0XHRhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuXHRcdFx0XHR1bnppcHBlZFtmaWxlc10gPSBuZXcgQXJyYXkoMik7XG5cdFx0XHRcdHVuemlwcGVkW2ZpbGVzXVswXSA9IG91dHB1dEFyci5qb2luKCcnKTtcbiAgICBcdFx0XHR1bnppcHBlZFtmaWxlc11bMV0gPSBuYW1lQnVmLmpvaW4oJycpO1xuICAgIFx0XHRcdGZpbGVzKys7XG5cdFx0XHRcdC8vcmV0dXJuIG91dHB1dEFyci5qb2luKCcnKTtcblx0XHRcdH1cblx0XHRcdHNraXBkaXIoKTtcblx0XHR9XG5cdH1cbiB9O1xuXHRcbmZ1bmN0aW9uIHNraXBkaXIoKXtcbiAgICB2YXIgY3JjLCBcbiAgICAgICAgdG1wID0gW10sXG4gICAgICAgIGNvbXBTaXplLCBzaXplLCBvcywgaSwgYztcbiAgICBcblx0aWYgKChncGZsYWdzICYgOCkpIHtcblx0XHR0bXBbMF0gPSByZWFkQnl0ZSgpO1xuXHRcdHRtcFsxXSA9IHJlYWRCeXRlKCk7XG5cdFx0dG1wWzJdID0gcmVhZEJ5dGUoKTtcblx0XHR0bXBbM10gPSByZWFkQnl0ZSgpO1xuXHRcdFxuXHRcdGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI1MFwiLDE2KSAmJiBcbiAgICAgICAgICAgIHRtcFsxXSA9PSBwYXJzZUludChcIjRiXCIsMTYpICYmIFxuICAgICAgICAgICAgdG1wWzJdID09IHBhcnNlSW50KFwiMDdcIiwxNikgJiYgXG4gICAgICAgICAgICB0bXBbM10gPT0gcGFyc2VJbnQoXCIwOFwiLDE2KSlcbiAgICAgICAge1xuICAgICAgICAgICAgY3JjID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKTw8OCk7XG4gICAgICAgICAgICBjcmMgfD0gKHJlYWRCeXRlKCk8PDE2KTtcbiAgICAgICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKTw8MjQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjcmMgPSB0bXBbMF0gfCAodG1wWzFdPDw4KSB8ICh0bXBbMl08PDE2KSB8ICh0bXBbM108PDI0KTtcblx0XHR9XG5cdFx0XG5cdFx0Y29tcFNpemUgPSByZWFkQnl0ZSgpO1xuXHRcdGNvbXBTaXplIHw9IChyZWFkQnl0ZSgpPDw4KTtcblx0XHRjb21wU2l6ZSB8PSAocmVhZEJ5dGUoKTw8MTYpO1xuXHRcdGNvbXBTaXplIHw9IChyZWFkQnl0ZSgpPDwyNCk7XG5cdFx0XG5cdFx0c2l6ZSA9IHJlYWRCeXRlKCk7XG5cdFx0c2l6ZSB8PSAocmVhZEJ5dGUoKTw8OCk7XG5cdFx0c2l6ZSB8PSAocmVhZEJ5dGUoKTw8MTYpO1xuXHRcdHNpemUgfD0gKHJlYWRCeXRlKCk8PDI0KTtcblx0XHRcblx0XHRpZiAoZGVidWcpXG5cdFx0XHRhbGVydChcIkNSQzpcIik7XG5cdH1cblxuXHRpZiAobW9kZVpJUClcblx0XHRuZXh0RmlsZSgpO1xuXHRcblx0dG1wWzBdID0gcmVhZEJ5dGUoKTtcblx0aWYgKHRtcFswXSAhPSA4KSB7XG5cdFx0aWYgKGRlYnVnKVxuXHRcdFx0YWxlcnQoXCJVbmtub3duIGNvbXByZXNzaW9uIG1ldGhvZCFcIik7XG4gICAgICAgIHJldHVybiAwO1x0XG5cdH1cblx0XG5cdGdwZmxhZ3MgPSByZWFkQnl0ZSgpO1xuXHRpZiAoZGVidWcpe1xuXHRcdGlmICgoZ3BmbGFncyAmIH4ocGFyc2VJbnQoXCIxZlwiLDE2KSkpKVxuXHRcdFx0YWxlcnQoXCJVbmtub3duIGZsYWdzIHNldCFcIik7XG5cdH1cblx0XG5cdHJlYWRCeXRlKCk7XG5cdHJlYWRCeXRlKCk7XG5cdHJlYWRCeXRlKCk7XG5cdHJlYWRCeXRlKCk7XG5cdFxuXHRyZWFkQnl0ZSgpO1xuXHRvcyA9IHJlYWRCeXRlKCk7XG5cdFxuXHRpZiAoKGdwZmxhZ3MgJiA0KSl7XG5cdFx0dG1wWzBdID0gcmVhZEJ5dGUoKTtcblx0XHR0bXBbMl0gPSByZWFkQnl0ZSgpO1xuXHRcdGxlbiA9IHRtcFswXSArIDI1Nip0bXBbMV07XG5cdFx0aWYgKGRlYnVnKVxuXHRcdFx0YWxlcnQoXCJFeHRyYSBmaWVsZCBzaXplOiBcIitsZW4pO1xuXHRcdGZvciAoaT0wO2k8bGVuO2krKylcblx0XHRcdHJlYWRCeXRlKCk7XG5cdH1cblx0XG5cdGlmICgoZ3BmbGFncyAmIDgpKXtcblx0XHRpPTA7XG5cdFx0bmFtZUJ1Zj1bXTtcblx0XHR3aGlsZSAoYz1yZWFkQnl0ZSgpKXtcblx0XHRcdGlmKGMgPT0gXCI3XCIgfHwgYyA9PSBcIjpcIilcblx0XHRcdFx0aT0wO1xuXHRcdFx0aWYgKGk8TkFNRU1BWC0xKVxuXHRcdFx0XHRuYW1lQnVmW2krK10gPSBjO1xuXHRcdH1cblx0XHQvL25hbWVCdWZbaV0gPSBcIlxcMFwiO1xuXHRcdGlmIChkZWJ1Zylcblx0XHRcdGFsZXJ0KFwib3JpZ2luYWwgZmlsZSBuYW1lOiBcIituYW1lQnVmKTtcblx0fVxuXHRcdFxuXHRpZiAoKGdwZmxhZ3MgJiAxNikpe1xuXHRcdHdoaWxlIChjPXJlYWRCeXRlKCkpe1xuXHRcdFx0Ly9GSUxFIENPTU1FTlRcblx0XHR9XG5cdH1cblx0XG5cdGlmICgoZ3BmbGFncyAmIDIpKXtcblx0XHRyZWFkQnl0ZSgpO1xuXHRcdHJlYWRCeXRlKCk7XG5cdH1cblx0XG5cdERlZmxhdGVMb29wKCk7XG5cdFxuXHRjcmMgPSByZWFkQnl0ZSgpO1xuXHRjcmMgfD0gKHJlYWRCeXRlKCk8PDgpO1xuXHRjcmMgfD0gKHJlYWRCeXRlKCk8PDE2KTtcblx0Y3JjIHw9IChyZWFkQnl0ZSgpPDwyNCk7XG5cdFxuXHRzaXplID0gcmVhZEJ5dGUoKTtcblx0c2l6ZSB8PSAocmVhZEJ5dGUoKTw8OCk7XG5cdHNpemUgfD0gKHJlYWRCeXRlKCk8PDE2KTtcblx0c2l6ZSB8PSAocmVhZEJ5dGUoKTw8MjQpO1xuXHRcblx0aWYgKG1vZGVaSVApXG5cdFx0bmV4dEZpbGUoKTtcblx0XG59O1xuXG59O1xuXG4vKipcbiogIEJhc2U2NCBlbmNvZGluZyAvIGRlY29kaW5nXG4qICB7QGxpbmsgaHR0cDovL3d3dy53ZWJ0b29sa2l0LmluZm8vfVxuKi9cbkpYRy5VdGlsLkJhc2U2NCA9IHtcblxuICAgIC8vIHByaXZhdGUgcHJvcGVydHlcbiAgICBfa2V5U3RyIDogXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvPVwiLFxuXG4gICAgLy8gcHVibGljIG1ldGhvZCBmb3IgZW5jb2RpbmdcbiAgICBlbmNvZGUgOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgY2hyMSwgY2hyMiwgY2hyMywgZW5jMSwgZW5jMiwgZW5jMywgZW5jNCxcbiAgICAgICAgICAgIGkgPSAwO1xuXG4gICAgICAgIGlucHV0ID0gSlhHLlV0aWwuQmFzZTY0Ll91dGY4X2VuY29kZShpbnB1dCk7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBpbnB1dC5sZW5ndGgpIHtcblxuICAgICAgICAgICAgY2hyMSA9IGlucHV0LmNoYXJDb2RlQXQoaSsrKTtcbiAgICAgICAgICAgIGNocjIgPSBpbnB1dC5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICAgICAgICBjaHIzID0gaW5wdXQuY2hhckNvZGVBdChpKyspO1xuXG4gICAgICAgICAgICBlbmMxID0gY2hyMSA+PiAyO1xuICAgICAgICAgICAgZW5jMiA9ICgoY2hyMSAmIDMpIDw8IDQpIHwgKGNocjIgPj4gNCk7XG4gICAgICAgICAgICBlbmMzID0gKChjaHIyICYgMTUpIDw8IDIpIHwgKGNocjMgPj4gNik7XG4gICAgICAgICAgICBlbmM0ID0gY2hyMyAmIDYzO1xuXG4gICAgICAgICAgICBpZiAoaXNOYU4oY2hyMikpIHtcbiAgICAgICAgICAgICAgICBlbmMzID0gZW5jNCA9IDY0O1xuICAgICAgICAgICAgfSBlbHNlIGlmIChpc05hTihjaHIzKSkge1xuICAgICAgICAgICAgICAgIGVuYzQgPSA2NDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgb3V0cHV0LnB1c2goW3RoaXMuX2tleVN0ci5jaGFyQXQoZW5jMSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fa2V5U3RyLmNoYXJBdChlbmMyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9rZXlTdHIuY2hhckF0KGVuYzMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2tleVN0ci5jaGFyQXQoZW5jNCldLmpvaW4oJycpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvdXRwdXQuam9pbignJyk7XG4gICAgfSxcblxuICAgIC8vIHB1YmxpYyBtZXRob2QgZm9yIGRlY29kaW5nXG4gICAgZGVjb2RlIDogZnVuY3Rpb24gKGlucHV0LCB1dGY4KSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgIGNocjEsIGNocjIsIGNocjMsXG4gICAgICAgICAgICBlbmMxLCBlbmMyLCBlbmMzLCBlbmM0LFxuICAgICAgICAgICAgaSA9IDA7XG5cbiAgICAgICAgaW5wdXQgPSBpbnB1dC5yZXBsYWNlKC9bXkEtWmEtejAtOVxcK1xcL1xcPV0vZywgXCJcIik7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBpbnB1dC5sZW5ndGgpIHtcblxuICAgICAgICAgICAgZW5jMSA9IHRoaXMuX2tleVN0ci5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcbiAgICAgICAgICAgIGVuYzIgPSB0aGlzLl9rZXlTdHIuaW5kZXhPZihpbnB1dC5jaGFyQXQoaSsrKSk7XG4gICAgICAgICAgICBlbmMzID0gdGhpcy5fa2V5U3RyLmluZGV4T2YoaW5wdXQuY2hhckF0KGkrKykpO1xuICAgICAgICAgICAgZW5jNCA9IHRoaXMuX2tleVN0ci5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcblxuICAgICAgICAgICAgY2hyMSA9IChlbmMxIDw8IDIpIHwgKGVuYzIgPj4gNCk7XG4gICAgICAgICAgICBjaHIyID0gKChlbmMyICYgMTUpIDw8IDQpIHwgKGVuYzMgPj4gMik7XG4gICAgICAgICAgICBjaHIzID0gKChlbmMzICYgMykgPDwgNikgfCBlbmM0O1xuXG4gICAgICAgICAgICBvdXRwdXQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNocjEpKTtcblxuICAgICAgICAgICAgaWYgKGVuYzMgIT0gNjQpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNocjIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChlbmM0ICE9IDY0KSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaHIzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIG91dHB1dCA9IG91dHB1dC5qb2luKCcnKTsgXG4gICAgICAgIFxuICAgICAgICBpZiAodXRmOCkge1xuICAgICAgICAgICAgb3V0cHV0ID0gSlhHLlV0aWwuQmFzZTY0Ll91dGY4X2RlY29kZShvdXRwdXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXRwdXQ7XG5cbiAgICB9LFxuXG4gICAgLy8gcHJpdmF0ZSBtZXRob2QgZm9yIFVURi04IGVuY29kaW5nXG4gICAgX3V0ZjhfZW5jb2RlIDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICBzdHJpbmcgPSBzdHJpbmcucmVwbGFjZSgvXFxyXFxuL2csXCJcXG5cIik7XG4gICAgICAgIHZhciB1dGZ0ZXh0ID0gXCJcIjtcblxuICAgICAgICBmb3IgKHZhciBuID0gMDsgbiA8IHN0cmluZy5sZW5ndGg7IG4rKykge1xuXG4gICAgICAgICAgICB2YXIgYyA9IHN0cmluZy5jaGFyQ29kZUF0KG4pO1xuXG4gICAgICAgICAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgICAgICAgICAgIHV0ZnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYoKGMgPiAxMjcpICYmIChjIDwgMjA0OCkpIHtcbiAgICAgICAgICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgPj4gNikgfCAxOTIpO1xuICAgICAgICAgICAgICAgIHV0ZnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoYyAmIDYzKSB8IDEyOCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgPj4gMTIpIHwgMjI0KTtcbiAgICAgICAgICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKChjID4+IDYpICYgNjMpIHwgMTI4KTtcbiAgICAgICAgICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgJiA2MykgfCAxMjgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdXRmdGV4dDtcbiAgICB9LFxuXG4gICAgLy8gcHJpdmF0ZSBtZXRob2QgZm9yIFVURi04IGRlY29kaW5nXG4gICAgX3V0ZjhfZGVjb2RlIDogZnVuY3Rpb24gKHV0ZnRleHQpIHtcbiAgICAgICAgdmFyIHN0cmluZyA9IFtdLFxuICAgICAgICAgICAgaSA9IDAsXG4gICAgICAgICAgICBjID0gMCwgYzIgPSAwLCBjMyA9IDA7XG5cbiAgICAgICAgd2hpbGUgKCBpIDwgdXRmdGV4dC5sZW5ndGggKSB7XG4gICAgICAgICAgICBjID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkpO1xuICAgICAgICAgICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgICAgICAgICAgICBzdHJpbmcucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGMpKTtcbiAgICAgICAgICAgICAgICBpKys7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmKChjID4gMTkxKSAmJiAoYyA8IDIyNCkpIHtcbiAgICAgICAgICAgICAgICBjMiA9IHV0ZnRleHQuY2hhckNvZGVBdChpKzEpO1xuICAgICAgICAgICAgICAgIHN0cmluZy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoKChjICYgMzEpIDw8IDYpIHwgKGMyICYgNjMpKSk7XG4gICAgICAgICAgICAgICAgaSArPSAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYzIgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSsxKTtcbiAgICAgICAgICAgICAgICBjMyA9IHV0ZnRleHQuY2hhckNvZGVBdChpKzIpO1xuICAgICAgICAgICAgICAgIHN0cmluZy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoKChjICYgMTUpIDw8IDEyKSB8ICgoYzIgJiA2MykgPDwgNikgfCAoYzMgJiA2MykpKTtcbiAgICAgICAgICAgICAgICBpICs9IDM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cmluZy5qb2luKCcnKTtcbiAgICB9LFxuICAgIFxuICAgIF9kZXN0cmlwOiBmdW5jdGlvbiAoc3RyaXBwZWQsIHdyYXApe1xuICAgICAgICB2YXIgbGluZXMgPSBbXSwgbGluZW5vLCBpLFxuICAgICAgICAgICAgZGVzdHJpcHBlZCA9IFtdO1xuICAgICAgICBcbiAgICAgICAgaWYgKHdyYXA9PW51bGwpIFxuICAgICAgICAgICAgd3JhcCA9IDc2O1xuICAgICAgICAgICAgXG4gICAgICAgIHN0cmlwcGVkLnJlcGxhY2UoLyAvZywgXCJcIik7XG4gICAgICAgIGxpbmVubyA9IHN0cmlwcGVkLmxlbmd0aCAvIHdyYXA7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaW5lbm87IGkrKylcbiAgICAgICAgICAgIGxpbmVzW2ldPXN0cmlwcGVkLnN1YnN0cihpICogd3JhcCwgd3JhcCk7XG4gICAgICAgIGlmIChsaW5lbm8gIT0gc3RyaXBwZWQubGVuZ3RoIC8gd3JhcClcbiAgICAgICAgICAgIGxpbmVzW2xpbmVzLmxlbmd0aF09c3RyaXBwZWQuc3Vic3RyKGxpbmVubyAqIHdyYXAsIHN0cmlwcGVkLmxlbmd0aC0obGluZW5vICogd3JhcCkpO1xuICAgICAgICAgICAgXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKylcbiAgICAgICAgICAgIGRlc3RyaXBwZWQucHVzaChsaW5lc1tpXSk7XG4gICAgICAgIHJldHVybiBkZXN0cmlwcGVkLmpvaW4oJ1xcbicpO1xuICAgIH0sXG4gICAgXG4gICAgZGVjb2RlQXNBcnJheTogZnVuY3Rpb24gKGlucHV0KXtcbiAgICAgICAgdmFyIGRlYyA9IHRoaXMuZGVjb2RlKGlucHV0KSxcbiAgICAgICAgICAgIGFyID0gW10sIGk7XG4gICAgICAgIGZvciAoaT0wO2k8ZGVjLmxlbmd0aDtpKyspe1xuICAgICAgICAgICAgYXJbaV09ZGVjLmNoYXJDb2RlQXQoaSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFyO1xuICAgIH0sXG4gICAgXG4gICAgZGVjb2RlR0VPTkV4VCA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gZGVjb2RlQXNBcnJheShkZXN0cmlwKGlucHV0KSxmYWxzZSk7XG4gICAgfVxufTtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5KWEcuVXRpbC5hc2NpaUNoYXJDb2RlQXQgPSBmdW5jdGlvbihzdHIsaSl7XG5cdHZhciBjID0gc3RyLmNoYXJDb2RlQXQoaSk7XG5cdGlmIChjPjI1NSl7XG4gICAgXHRzd2l0Y2ggKGMpIHtcblx0XHRcdGNhc2UgODM2NDogYz0xMjg7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDgyMTg6IGM9MTMwO1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSA0MDI6IGM9MTMxO1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSA4MjIyOiBjPTEzMjtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgODIzMDogYz0xMzM7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDgyMjQ6IGM9MTM0O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSA4MjI1OiBjPTEzNTtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgNzEwOiBjPTEzNjtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgODI0MDogYz0xMzc7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDM1MjogYz0xMzg7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDgyNDk6IGM9MTM5O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSAzMzg6IGM9MTQwO1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSAzODE6IGM9MTQyO1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSA4MjE2OiBjPTE0NTtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgODIxNzogYz0xNDY7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDgyMjA6IGM9MTQ3O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSA4MjIxOiBjPTE0ODtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgODIyNjogYz0xNDk7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDgyMTE6IGM9MTUwO1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSA4MjEyOiBjPTE1MTtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgNzMyOiBjPTE1Mjtcblx0ICAgIFx0YnJlYWs7XG5cdCAgICBcdGNhc2UgODQ4MjogYz0xNTM7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDM1MzogYz0xNTQ7XG5cdCAgICBcdGJyZWFrO1xuXHQgICAgXHRjYXNlIDgyNTA6IGM9MTU1O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSAzMzk6IGM9MTU2O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSAzODI6IGM9MTU4O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0Y2FzZSAzNzY6IGM9MTU5O1xuXHQgICAgXHRicmVhaztcblx0ICAgIFx0ZGVmYXVsdDpcblx0ICAgIFx0YnJlYWs7XG5cdCAgICB9XG5cdH1cblx0cmV0dXJuIGM7XG59O1xuXG4vKipcbiAqIERlY29kaW5nIHN0cmluZyBpbnRvIHV0Zi04XG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyaW5nIHRvIGRlY29kZVxuICogQHJldHVybiB7U3RyaW5nfSB1dGY4IGRlY29kZWQgc3RyaW5nXG4gKi9cbkpYRy5VdGlsLnV0ZjhEZWNvZGUgPSBmdW5jdGlvbih1dGZ0ZXh0KSB7XG4gIHZhciBzdHJpbmcgPSBbXTtcbiAgdmFyIGkgPSAwO1xuICB2YXIgYyA9IDAsIGMxID0gMCwgYzIgPSAwLCBjMztcbiAgaWYgKCFKWEcuZXhpc3RzKHV0ZnRleHQpKSByZXR1cm4gJyc7XG4gIFxuICB3aGlsZSAoIGkgPCB1dGZ0ZXh0Lmxlbmd0aCApIHtcbiAgICBjID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkpO1xuXG4gICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgIHN0cmluZy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYykpO1xuICAgICAgaSsrO1xuICAgIH0gZWxzZSBpZigoYyA+IDE5MSkgJiYgKGMgPCAyMjQpKSB7XG4gICAgICBjMiA9IHV0ZnRleHQuY2hhckNvZGVBdChpKzEpO1xuICAgICAgc3RyaW5nLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMgJiAzMSkgPDwgNikgfCAoYzIgJiA2MykpKTtcbiAgICAgIGkgKz0gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgYzIgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSsxKTtcbiAgICAgIGMzID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkrMik7XG4gICAgICBzdHJpbmcucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKCgoYyAmIDE1KSA8PCAxMikgfCAoKGMyICYgNjMpIDw8IDYpIHwgKGMzICYgNjMpKSk7XG4gICAgICBpICs9IDM7XG4gICAgfVxuICB9O1xuICByZXR1cm4gc3RyaW5nLmpvaW4oJycpO1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZSBhIHJhbmRvbSB1dWlkLlxuICogaHR0cDovL3d3dy5icm9vZmEuY29tXG4gKiBtYWlsdG86cm9iZXJ0QGJyb29mYS5jb21cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAgUm9iZXJ0IEtpZWZmZXJcbiAqIER1YWwgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBhbmQgR1BMIGxpY2Vuc2VzLlxuICpcbiAqIEVYQU1QTEVTOlxuICogICA+Pj4gTWF0aC51dWlkKClcbiAqICAgXCI5MjMyOUQzOS02RjVDLTQ1MjAtQUJGQy1BQUI2NDU0NEUxNzJcIlxuICovXG5KWEcuVXRpbC5nZW5VVUlEID0gZnVuY3Rpb24oKSB7XG4gICAgLy8gUHJpdmF0ZSBhcnJheSBvZiBjaGFycyB0byB1c2VcbiAgICB2YXIgY2hhcnMgPSAnMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonLnNwbGl0KCcnKSxcbiAgICAgICAgdXVpZCA9IG5ldyBBcnJheSgzNiksIHJuZD0wLCByO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAzNjsgaSsrKSB7XG4gICAgICBpZiAoaT09OCB8fCBpPT0xMyB8fCAgaT09MTggfHwgaT09MjMpIHtcbiAgICAgICAgdXVpZFtpXSA9ICctJztcbiAgICAgIH0gZWxzZSBpZiAoaT09MTQpIHtcbiAgICAgICAgdXVpZFtpXSA9ICc0JztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChybmQgPD0gMHgwMikgcm5kID0gMHgyMDAwMDAwICsgKE1hdGgucmFuZG9tKCkqMHgxMDAwMDAwKXwwO1xuICAgICAgICByID0gcm5kICYgMHhmO1xuICAgICAgICBybmQgPSBybmQgPj4gNDtcbiAgICAgICAgdXVpZFtpXSA9IGNoYXJzWyhpID09IDE5KSA/IChyICYgMHgzKSB8IDB4OCA6IHJdO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB1dWlkLmpvaW4oJycpO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpYRztcbiIsIi8vIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSCBcblxuLy8gbW9kaWZpZWQgdmVyc2lvbiBvZiBodHRwOi8vd3d3LmhhbmV3aW4ubmV0L2VuY3J5cHQvUEdkZWNvZGUuanM6XG5cbi8qIE9wZW5QR1AgZW5jcnlwdGlvbiB1c2luZyBSU0EvQUVTXG4gKiBDb3B5cmlnaHQgMjAwNS0yMDA2IEhlcmJlcnQgSGFuZXdpbmtlbCwgd3d3LmhhbmVXSU4uZGVcbiAqIHZlcnNpb24gMi4wLCBjaGVjayB3d3cuaGFuZVdJTi5kZSBmb3IgdGhlIGxhdGVzdCB2ZXJzaW9uXG5cbiAqIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgYXMtaXMsIHdpdGhvdXQgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LiAgXG4gKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlIG9yIHNlbGwgdGhpcyBzb2Z0d2FyZSwgd2l0aCBvclxuICogd2l0aG91dCBmZWUsIGZvciBhbnkgcHVycG9zZSBhbmQgYnkgYW55IGluZGl2aWR1YWwgb3Igb3JnYW5pemF0aW9uLCBpcyBoZXJlYnlcbiAqIGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGFyYWdyYXBoIGFwcGVhciBcbiAqIGluIGFsbCBjb3BpZXMuIERpc3RyaWJ1dGlvbiBhcyBhIHBhcnQgb2YgYW4gYXBwbGljYXRpb24gb3IgYmluYXJ5IG11c3RcbiAqIGluY2x1ZGUgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyXG4gKiBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgYXBwbGljYXRpb24gb3IgZGlzdHJpYnV0aW9uLlxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuXHRjaXBoZXIgPSByZXF1aXJlKCcuL2NpcGhlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuXHQvKipcblx0ICogQW4gYXJyYXkgb2YgYnl0ZXMsIHRoYXQgaXMgaW50ZWdlcnMgd2l0aCB2YWx1ZXMgZnJvbSAwIHRvIDI1NVxuXHQgKiBAdHlwZWRlZiB7KEFycmF5fFVpbnQ4QXJyYXkpfSBvcGVucGdwX2J5dGVfYXJyYXlcblx0ICovXG5cblx0LyoqXG5cdCAqIEJsb2NrIGNpcGhlciBmdW5jdGlvblxuXHQgKiBAY2FsbGJhY2sgb3BlbnBncF9jaXBoZXJfYmxvY2tfZm5cblx0ICogQHBhcmFtIHtvcGVucGdwX2J5dGVfYXJyYXl9IGJsb2NrIEEgYmxvY2sgdG8gcGVyZm9ybSBvcGVyYXRpb25zIG9uXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9ieXRlX2FycmF5fSBrZXkgdG8gdXNlIGluIGVuY3J5cHRpb24vZGVjcnlwdGlvblxuXHQgKiBAcmV0dXJuIHtvcGVucGdwX2J5dGVfYXJyYXl9IEVuY3J5cHRlZC9kZWNyeXB0ZWQgYmxvY2tcblx0ICovXG5cblxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvKipcblx0ICogVGhpcyBmdW5jdGlvbiBlbmNyeXB0cyBhIGdpdmVuIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXhyYW5kb20gXG5cdCAqIHVzaW5nIHRoZSBzcGVjaWZpZWQgYmxvY2tjaXBoZXIgdG8gZW5jcnlwdCBhIG1lc3NhZ2Vcblx0ICogQHBhcmFtIHtTdHJpbmd9IHByZWZpeHJhbmRvbSByYW5kb20gYnl0ZXMgb2YgYmxvY2tfc2l6ZSBsZW5ndGggcHJvdmlkZWQgXG5cdCAqICBhcyBhIHN0cmluZyB0byBiZSB1c2VkIGluIHByZWZpeGluZyB0aGUgZGF0YVxuXHQgKiBAcGFyYW0ge29wZW5wZ3BfY2lwaGVyX2Jsb2NrX2ZufSBibG9ja2NpcGhlcmZuIHRoZSBhbGdvcml0aG0gZW5jcnlwdCBmdW5jdGlvbiB0byBlbmNyeXB0XG5cdCAqICBkYXRhIGluIG9uZSBibG9ja19zaXplIGVuY3J5cHRpb24uIFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGJsb2NrX3NpemUgdGhlIGJsb2NrIHNpemUgaW4gYnl0ZXMgb2YgdGhlIGFsZ29yaXRobSB1c2VkXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBwbGFpbnRleHQgZGF0YSB0byBiZSBlbmNyeXB0ZWQgcHJvdmlkZWQgYXMgYSBzdHJpbmdcblx0ICogQHBhcmFtIHtvcGVucGdwX2J5dGVfYXJyYXl9IGtleSBrZXkgdG8gYmUgdXNlZCB0byBlbmNyeXB0IHRoZSBkYXRhLiBUaGlzIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSBcblx0ICogIGJsb2NrY2lwaGVyZm5cblx0ICogQHBhcmFtIHtCb29sZWFufSByZXN5bmMgYSBib29sZWFuIHZhbHVlIHNwZWNpZnlpbmcgaWYgYSByZXN5bmMgb2YgdGhlIFxuXHQgKiAgSVYgc2hvdWxkIGJlIHVzZWQgb3Igbm90LiBUaGUgZW5jcnlwdGVkZGF0YXBhY2tldCB1c2VzIHRoZSBcblx0ICogIFwib2xkXCIgc3R5bGUgd2l0aCBhIHJlc3luYy4gRW5jcnlwdGlvbiB3aXRoaW4gYW4gXG5cdCAqICBlbmNyeXB0ZWRpbnRlZ3JpdHlwcm90ZWN0ZWRkYXRhIHBhY2tldCBpcyBub3QgcmVzeW5jaW5nIHRoZSBJVi5cblx0ICogQHJldHVybiB7U3RyaW5nfSBhIHN0cmluZyB3aXRoIHRoZSBlbmNyeXB0ZWQgZGF0YVxuXHQgKi9cblx0ZW5jcnlwdDogZnVuY3Rpb24gKHByZWZpeHJhbmRvbSwgY2lwaGVyZm4sIHBsYWludGV4dCwga2V5LCByZXN5bmMpIHtcblx0XHRjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG5cdFx0dmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cblx0XHR2YXIgRlIgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG5cdFx0dmFyIEZSRSA9IG5ldyBBcnJheShibG9ja19zaXplKTtcblxuXHRcdHByZWZpeHJhbmRvbSA9IHByZWZpeHJhbmRvbSArIHByZWZpeHJhbmRvbS5jaGFyQXQoYmxvY2tfc2l6ZS0yKSArcHJlZml4cmFuZG9tLmNoYXJBdChibG9ja19zaXplLTEpO1xuXHRcdHV0aWwucHJpbnRfZGVidWcoXCJwcmVmaXhyYW5kb206XCIrdXRpbC5oZXhzdHJkdW1wKHByZWZpeHJhbmRvbSkpO1xuXHRcdHZhciBjaXBoZXJ0ZXh0ID0gXCJcIjtcblx0XHQvLyAxLiAgVGhlIGZlZWRiYWNrIHJlZ2lzdGVyIChGUikgaXMgc2V0IHRvIHRoZSBJViwgd2hpY2ggaXMgYWxsIHplcm9zLlxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBGUltpXSA9IDA7XG5cdFx0XG5cdFx0Ly8gMi4gIEZSIGlzIGVuY3J5cHRlZCB0byBwcm9kdWNlIEZSRSAoRlIgRW5jcnlwdGVkKS4gIFRoaXMgaXMgdGhlXG5cdFx0Ly8gICAgIGVuY3J5cHRpb24gb2YgYW4gYWxsLXplcm8gdmFsdWUuXG5cdFx0RlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG5cdFx0Ly8gMy4gIEZSRSBpcyB4b3JlZCB3aXRoIHRoZSBmaXJzdCBCUyBvY3RldHMgb2YgcmFuZG9tIGRhdGEgcHJlZml4ZWQgdG9cblx0XHQvLyAgICAgdGhlIHBsYWludGV4dCB0byBwcm9kdWNlIENbMV0gdGhyb3VnaCBDW0JTXSwgdGhlIGZpcnN0IEJTIG9jdGV0c1xuXHRcdC8vICAgICBvZiBjaXBoZXJ0ZXh0LlxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBjaXBoZXJ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFW2ldIF4gcHJlZml4cmFuZG9tLmNoYXJDb2RlQXQoaSkpO1xuXHRcdFxuXHRcdC8vIDQuICBGUiBpcyBsb2FkZWQgd2l0aCBDWzFdIHRocm91Z2ggQ1tCU10uXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkpO1xuXHRcdFxuXHRcdC8vIDUuICBGUiBpcyBlbmNyeXB0ZWQgdG8gcHJvZHVjZSBGUkUsIHRoZSBlbmNyeXB0aW9uIG9mIHRoZSBmaXJzdCBCU1xuXHRcdC8vIFx0ICAgb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG5cdFx0RlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG5cblx0XHQvLyA2LiAgVGhlIGxlZnQgdHdvIG9jdGV0cyBvZiBGUkUgZ2V0IHhvcmVkIHdpdGggdGhlIG5leHQgdHdvIG9jdGV0cyBvZlxuXHRcdC8vICAgICBkYXRhIHRoYXQgd2VyZSBwcmVmaXhlZCB0byB0aGUgcGxhaW50ZXh0LiAgVGhpcyBwcm9kdWNlcyBDW0JTKzFdXG5cdFx0Ly8gICAgIGFuZCBDW0JTKzJdLCB0aGUgbmV4dCB0d28gb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG5cdFx0Y2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVswXSBeIHByZWZpeHJhbmRvbS5jaGFyQ29kZUF0KGJsb2NrX3NpemUpKTtcblx0XHRjaXBoZXJ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFWzFdIF4gcHJlZml4cmFuZG9tLmNoYXJDb2RlQXQoYmxvY2tfc2l6ZSsxKSk7XG5cblx0XHRpZiAocmVzeW5jKSB7XG5cdFx0XHQvLyA3LiAgKFRoZSByZXN5bmMgc3RlcCkgRlIgaXMgbG9hZGVkIHdpdGggQzMtQzEwLlxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkrMik7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBGUltpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcblx0XHR9XG5cdFx0Ly8gOC4gIEZSIGlzIGVuY3J5cHRlZCB0byBwcm9kdWNlIEZSRS5cblx0XHRGUkUgPSBjaXBoZXJmbi5lbmNyeXB0KEZSLCBrZXkpO1xuXHRcdFxuXHRcdGlmIChyZXN5bmMpIHtcblx0XHRcdC8vIDkuICBGUkUgaXMgeG9yZWQgd2l0aCB0aGUgZmlyc3QgOCBvY3RldHMgb2YgdGhlIGdpdmVuIHBsYWludGV4dCwgbm93XG5cdFx0XHQvL1x0ICAgdGhhdCB3ZSBoYXZlIGZpbmlzaGVkIGVuY3J5cHRpbmcgdGhlIDEwIG9jdGV0cyBvZiBwcmVmaXhlZCBkYXRhLlxuXHRcdFx0Ly8gXHQgICBUaGlzIHByb2R1Y2VzIEMxMS1DMTgsIHRoZSBuZXh0IDggb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKylcblx0XHRcdFx0Y2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVtpXSBeIHBsYWludGV4dC5jaGFyQ29kZUF0KGkpKTtcblx0XHRcdGZvcihuPWJsb2NrX3NpemUrMjsgbiA8IHBsYWludGV4dC5sZW5ndGg7IG4rPWJsb2NrX3NpemUpIHtcblx0XHRcdFx0Ly8gMTAuIEZSIGlzIGxvYWRlZCB3aXRoIEMxMS1DMThcblx0XHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KG4raSk7XG5cdFx0XHRcblx0XHRcdFx0Ly8gMTEuIEZSIGlzIGVuY3J5cHRlZCB0byBwcm9kdWNlIEZSRS5cblx0XHRcdFx0RlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG5cdFx0XHRcblx0XHRcdFx0Ly8gMTIuIEZSRSBpcyB4b3JlZCB3aXRoIHRoZSBuZXh0IDggb2N0ZXRzIG9mIHBsYWludGV4dCwgdG8gcHJvZHVjZSB0aGVcblx0XHRcdFx0Ly8gbmV4dCA4IG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LiAgVGhlc2UgYXJlIGxvYWRlZCBpbnRvIEZSIGFuZCB0aGVcblx0XHRcdFx0Ly8gcHJvY2VzcyBpcyByZXBlYXRlZCB1bnRpbCB0aGUgcGxhaW50ZXh0IGlzIHVzZWQgdXAuXG5cdFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBjaXBoZXJ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFW2ldIF4gcGxhaW50ZXh0LmNoYXJDb2RlQXQoKG4tMikraSkpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHBsYWludGV4dCA9IFwiICBcIitwbGFpbnRleHQ7XG5cdFx0XHQvLyA5LiAgRlJFIGlzIHhvcmVkIHdpdGggdGhlIGZpcnN0IDggb2N0ZXRzIG9mIHRoZSBnaXZlbiBwbGFpbnRleHQsIG5vd1xuXHRcdFx0Ly9cdCAgIHRoYXQgd2UgaGF2ZSBmaW5pc2hlZCBlbmNyeXB0aW5nIHRoZSAxMCBvY3RldHMgb2YgcHJlZml4ZWQgZGF0YS5cblx0XHRcdC8vIFx0ICAgVGhpcyBwcm9kdWNlcyBDMTEtQzE4LCB0aGUgbmV4dCA4IG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LlxuXHRcdFx0Zm9yICh2YXIgaSA9IDI7IGkgPCBibG9ja19zaXplOyBpKyspIGNpcGhlcnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwbGFpbnRleHQuY2hhckNvZGVBdChpKSk7XG5cdFx0XHR2YXIgdGVtcENpcGhlcnRleHQgPSBjaXBoZXJ0ZXh0LnN1YnN0cmluZygwLDIqYmxvY2tfc2l6ZSkuc3BsaXQoJycpO1xuXHRcdFx0dmFyIHRlbXBDaXBoZXJ0ZXh0U3RyaW5nID0gY2lwaGVydGV4dC5zdWJzdHJpbmcoYmxvY2tfc2l6ZSk7XG5cdFx0XHRmb3Iobj1ibG9ja19zaXplOyBuPHBsYWludGV4dC5sZW5ndGg7IG4rPWJsb2NrX3NpemUpIHtcblx0XHRcdFx0Ly8gMTAuIEZSIGlzIGxvYWRlZCB3aXRoIEMxMS1DMThcblx0XHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gdGVtcENpcGhlcnRleHRTdHJpbmcuY2hhckNvZGVBdChpKTtcblx0XHRcdFx0dGVtcENpcGhlcnRleHRTdHJpbmc9Jyc7XG5cdFx0XHRcdFxuXHRcdFx0XHQvLyAxMS4gRlIgaXMgZW5jcnlwdGVkIHRvIHByb2R1Y2UgRlJFLlxuXHRcdFx0XHRGUkUgPSBjaXBoZXJmbi5lbmNyeXB0KEZSKTtcblx0XHRcdFx0XG5cdFx0XHRcdC8vIDEyLiBGUkUgaXMgeG9yZWQgd2l0aCB0aGUgbmV4dCA4IG9jdGV0cyBvZiBwbGFpbnRleHQsIHRvIHByb2R1Y2UgdGhlXG5cdFx0XHRcdC8vICAgICBuZXh0IDggb2N0ZXRzIG9mIGNpcGhlcnRleHQuICBUaGVzZSBhcmUgbG9hZGVkIGludG8gRlIgYW5kIHRoZVxuXHRcdFx0XHQvLyAgICAgcHJvY2VzcyBpcyByZXBlYXRlZCB1bnRpbCB0aGUgcGxhaW50ZXh0IGlzIHVzZWQgdXAuXG5cdFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKXsgdGVtcENpcGhlcnRleHQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVtpXSBeIHBsYWludGV4dC5jaGFyQ29kZUF0KG4raSkpKTtcblx0XHRcdFx0dGVtcENpcGhlcnRleHRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwbGFpbnRleHQuY2hhckNvZGVBdChuK2kpKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Y2lwaGVydGV4dCA9IHRlbXBDaXBoZXJ0ZXh0LmpvaW4oJycpO1xuXHRcdFx0XG5cdFx0fVxuXG5cdFx0Y2lwaGVydGV4dCA9IGNpcGhlcnRleHQuc3Vic3RyaW5nKDAsIHBsYWludGV4dC5sZW5ndGggKyAyICsgYmxvY2tfc2l6ZSk7XG5cblx0XHRyZXR1cm4gY2lwaGVydGV4dDtcblx0fSxcblxuXHQvKipcblx0ICogRGVjcnlwdHMgdGhlIHByZWZpeGVkIGRhdGEgZm9yIHRoZSBNb2RpZmljYXRpb24gRGV0ZWN0aW9uIENvZGUgKE1EQykgY29tcHV0YXRpb25cblx0ICogQHBhcmFtIHtvcGVucGdwX2Jsb2NrX2NpcGhlcl9mbn0gY2lwaGVyZm4uZW5jcnlwdCBDaXBoZXIgZnVuY3Rpb24gdG8gdXNlXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gYmxvY2tfc2l6ZSBCbG9ja3NpemUgb2YgdGhlIGFsZ29yaXRobVxuXHQgKiBAcGFyYW0ge29wZW5wZ3BfYnl0ZV9hcnJheX0ga2V5IFRoZSBrZXkgZm9yIGVuY3J5cHRpb25cblx0ICogQHBhcmFtIHtTdHJpbmd9IGNpcGhlcnRleHQgVGhlIGVuY3J5cHRlZCBkYXRhXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gcGxhaW50ZXh0IERhdGEgb2YgRChjaXBoZXJ0ZXh0KSB3aXRoIGJsb2Nrc2l6ZSBsZW5ndGggKzJcblx0ICovXG5cdG1kYzogZnVuY3Rpb24gKGNpcGhlcmZuLCBrZXksIGNpcGhlcnRleHQpIHtcblx0XHRjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG5cdFx0dmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cblx0XHR2YXIgaWJsb2NrID0gbmV3IEFycmF5KGJsb2NrX3NpemUpO1xuXHRcdHZhciBhYmxvY2sgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG5cdFx0dmFyIGk7XG5cblxuXHRcdC8vIGluaXRpYWxpc2F0aW9uIHZlY3RvclxuXHRcdGZvcihpPTA7IGkgPCBibG9ja19zaXplOyBpKyspIGlibG9ja1tpXSA9IDA7XG5cblx0XHRpYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGlibG9jayk7XG5cdFx0Zm9yKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKVxuXHRcdHtcblx0XHRcdGFibG9ja1tpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcblx0XHRcdGlibG9ja1tpXSBePSBhYmxvY2tbaV07XG5cdFx0fVxuXG5cdFx0YWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChhYmxvY2spO1xuXG5cdFx0cmV0dXJuIHV0aWwuYmluMnN0cihpYmxvY2spK1xuXHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZShhYmxvY2tbMF1eY2lwaGVydGV4dC5jaGFyQ29kZUF0KGJsb2NrX3NpemUpKStcblx0XHRcdFN0cmluZy5mcm9tQ2hhckNvZGUoYWJsb2NrWzFdXmNpcGhlcnRleHQuY2hhckNvZGVBdChibG9ja19zaXplKzEpKTtcblx0fSxcblx0LyoqXG5cdCAqIFRoaXMgZnVuY3Rpb24gZGVjcnlwdHMgYSBnaXZlbiBwbGFpbnRleHQgdXNpbmcgdGhlIHNwZWNpZmllZFxuXHQgKiBibG9ja2NpcGhlciB0byBkZWNyeXB0IGEgbWVzc2FnZVxuXHQgKiBAcGFyYW0ge29wZW5wZ3BfY2lwaGVyX2Jsb2NrX2ZufSBibG9ja2NpcGhlcmZuIFRoZSBhbGdvcml0aG0gX2VuY3J5cHRfIGZ1bmN0aW9uIHRvIGVuY3J5cHRcblx0ICogIGRhdGEgaW4gb25lIGJsb2NrX3NpemUgZW5jcnlwdGlvbi5cblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBibG9ja19zaXplIHRoZSBibG9jayBzaXplIGluIGJ5dGVzIG9mIHRoZSBhbGdvcml0aG0gdXNlZFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gcGxhaW50ZXh0IGNpcGhlcnRleHQgdG8gYmUgZGVjcnlwdGVkIHByb3ZpZGVkIGFzIGEgc3RyaW5nXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9ieXRlX2FycmF5fSBrZXkga2V5IHRvIGJlIHVzZWQgdG8gZGVjcnlwdCB0aGUgY2lwaGVydGV4dC4gVGhpcyB3aWxsIGJlIHBhc3NlZCB0byB0aGUgXG5cdCAqICBibG9ja2NpcGhlcmZuXG5cdCAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVzeW5jIGEgYm9vbGVhbiB2YWx1ZSBzcGVjaWZ5aW5nIGlmIGEgcmVzeW5jIG9mIHRoZSBcblx0ICogIElWIHNob3VsZCBiZSB1c2VkIG9yIG5vdC4gVGhlIGVuY3J5cHRlZGRhdGFwYWNrZXQgdXNlcyB0aGUgXG5cdCAqICBcIm9sZFwiIHN0eWxlIHdpdGggYSByZXN5bmMuIERlY3J5cHRpb24gd2l0aGluIGFuIFxuXHQgKiAgZW5jcnlwdGVkaW50ZWdyaXR5cHJvdGVjdGVkZGF0YSBwYWNrZXQgaXMgbm90IHJlc3luY2luZyB0aGUgSVYuXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gYSBzdHJpbmcgd2l0aCB0aGUgcGxhaW50ZXh0IGRhdGFcblx0ICovXG5cblx0ZGVjcnlwdDogZnVuY3Rpb24gKGNpcGhlcmZuLCBrZXksIGNpcGhlcnRleHQsIHJlc3luYykge1xuXHRcdGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcblx0XHR2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuXHRcdHZhciBpYmxvY2sgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG5cdFx0dmFyIGFibG9jayA9IG5ldyBBcnJheShibG9ja19zaXplKTtcblx0XHR2YXIgaSwgbiA9ICcnO1xuXHRcdHZhciB0ZXh0ID0gW107XG5cblx0XHQvLyBpbml0aWFsaXNhdGlvbiB2ZWN0b3Jcblx0XHRmb3IoaT0wOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSAwO1xuXG5cdFx0aWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChpYmxvY2ssIGtleSk7XG5cdFx0Zm9yKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKVxuXHRcdHtcblx0XHRcdGFibG9ja1tpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcblx0XHRcdGlibG9ja1tpXSBePSBhYmxvY2tbaV07XG5cdFx0fVxuXG5cdFx0YWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChhYmxvY2ssIGtleSk7XG5cblx0XHQvLyB0ZXN0IGNoZWNrIG9jdGV0c1xuXHRcdGlmKGlibG9ja1tibG9ja19zaXplLTJdIT0oYWJsb2NrWzBdXmNpcGhlcnRleHQuY2hhckNvZGVBdChibG9ja19zaXplKSlcblx0XHR8fCBpYmxvY2tbYmxvY2tfc2l6ZS0xXSE9KGFibG9ja1sxXV5jaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoYmxvY2tfc2l6ZSsxKSkpXG5cdFx0e1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEuJyk7XG5cdFx0fVxuXHRcdFxuXHRcdC8qICBSRkM0ODgwOiBUYWcgMTggYW5kIFJlc3luYzpcblx0XHQgKiAgWy4uLl0gVW5saWtlIHRoZSBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIFBhY2tldCwgbm9cblx0XHQgKiAgc3BlY2lhbCBDRkIgcmVzeW5jaHJvbml6YXRpb24gaXMgZG9uZSBhZnRlciBlbmNyeXB0aW5nIHRoaXMgcHJlZml4XG5cdFx0ICogIGRhdGEuICBTZWUgXCJPcGVuUEdQIENGQiBNb2RlXCIgYmVsb3cgZm9yIG1vcmUgZGV0YWlscy5cblxuXHRcdCAqL1xuXHRcdFxuXHRcdGlmIChyZXN5bmMpIHtcblx0XHRcdGZvcihpPTA7IGk8YmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSsyKTtcblx0XHRcdGZvcihuPWJsb2NrX3NpemUrMjsgbjxjaXBoZXJ0ZXh0Lmxlbmd0aDsgbis9YmxvY2tfc2l6ZSlcblx0XHRcdHtcblx0XHRcdFx0YWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChpYmxvY2spO1xuXG5cdFx0XHRcdGZvcihpID0gMDsgaTxibG9ja19zaXplICYmIGkrbiA8IGNpcGhlcnRleHQubGVuZ3RoOyBpKyspXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQobitpKTtcblx0XHRcdFx0XHR0ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhYmxvY2tbaV1eaWJsb2NrW2ldKSk7IFxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvcihpPTA7IGk8YmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSk7XG5cdFx0XHRmb3Iobj1ibG9ja19zaXplOyBuPGNpcGhlcnRleHQubGVuZ3RoOyBuKz1ibG9ja19zaXplKVxuXHRcdFx0e1xuXHRcdFx0XHRhYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGlibG9jayk7XG5cdFx0XHRcdGZvcihpID0gMDsgaTxibG9ja19zaXplICYmIGkrbiA8IGNpcGhlcnRleHQubGVuZ3RoOyBpKyspXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQobitpKTtcblx0XHRcdFx0XHR0ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhYmxvY2tbaV1eaWJsb2NrW2ldKSk7IFxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIG4gPSByZXN5bmMgPyAwIDogMjtcblxuXHRcdHRleHQgPSB0ZXh0LmpvaW4oJycpO1xuXG5cdFx0dGV4dCA9IHRleHQuc3Vic3RyaW5nKG4sIGNpcGhlcnRleHQubGVuZ3RoIC0gYmxvY2tfc2l6ZSAtIDIgKyBuKTtcblxuXHRcdFxuXHRcdHJldHVybiB0ZXh0O1xuXHR9LFxuXG5cblx0bm9ybWFsRW5jcnlwdDogZnVuY3Rpb24oY2lwaGVyZm4sIGtleSwgcGxhaW50ZXh0LCBpdikge1xuXHRcdGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcblx0XHR2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuXHRcdHZhciBibG9ja2kgPVwiXCI7XG5cdFx0dmFyIGJsb2NrYyA9IFwiXCI7XG5cdFx0dmFyIHBvcyA9IDA7XG5cdFx0dmFyIGN5cGhlcnRleHQgPSBbXTtcblx0XHR2YXIgdGVtcEJsb2NrID0gW107XG5cdFx0YmxvY2tjID0gaXYuc3Vic3RyaW5nKDAsYmxvY2tfc2l6ZSk7XG5cdFx0d2hpbGUgKHBsYWludGV4dC5sZW5ndGggPiBibG9ja19zaXplKnBvcykge1xuXHRcdFx0dmFyIGVuY2Jsb2NrID0gY2lwaGVyZm4uZW5jcnlwdCh1dGlsLnN0cjJiaW4oYmxvY2tjKSk7XG5cdFx0XHRibG9ja2kgPSBwbGFpbnRleHQuc3Vic3RyaW5nKChwb3MqYmxvY2tfc2l6ZSksKHBvcypibG9ja19zaXplKStibG9ja19zaXplKTtcblx0XHRcdGZvciAodmFyIGk9MDsgaSA8IGJsb2NraS5sZW5ndGg7IGkrKylcblx0XHRcdFx0dGVtcEJsb2NrLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShibG9ja2kuY2hhckNvZGVBdChpKSBeIGVuY2Jsb2NrW2ldKSk7XG5cdFx0XHRibG9ja2MgPSB0ZW1wQmxvY2suam9pbignJyk7XG5cdFx0XHR0ZW1wQmxvY2sgPSBbXTtcblx0XHRcdGN5cGhlcnRleHQucHVzaChibG9ja2MpO1xuXHRcdFx0cG9zKys7XG5cdFx0fVxuXHRcdHJldHVybiBjeXBoZXJ0ZXh0LmpvaW4oJycpO1xuXHR9LFxuXG5cdG5vcm1hbERlY3J5cHQ6IGZ1bmN0aW9uKGNpcGhlcmZuLCBrZXksIGNpcGhlcnRleHQsIGl2KSB7IFxuXHRcdGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcblx0XHR2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuXHRcdHZhciBibG9ja3AgPVwiXCI7XG5cdFx0dmFyIHBvcyA9IDA7XG5cdFx0dmFyIHBsYWludGV4dCA9IFtdO1xuXHRcdHZhciBvZmZzZXQgPSAwO1xuXHRcdGlmIChpdiA9PSBudWxsKVxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIGJsb2NrcCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuXHRcdGVsc2Vcblx0XHRcdGJsb2NrcCA9IGl2LnN1YnN0cmluZygwLGJsb2NrX3NpemUpO1xuXHRcdHdoaWxlIChjaXBoZXJ0ZXh0Lmxlbmd0aCA+IChibG9ja19zaXplKnBvcykpIHtcblx0XHRcdHZhciBkZWNibG9jayA9IGNpcGhlcmZuLmVuY3J5cHQodXRpbC5zdHIyYmluKGJsb2NrcCkpO1xuXHRcdFx0YmxvY2twID0gY2lwaGVydGV4dC5zdWJzdHJpbmcoKHBvcyooYmxvY2tfc2l6ZSkpK29mZnNldCwocG9zKihibG9ja19zaXplKSkrKGJsb2NrX3NpemUpK29mZnNldCk7XG5cdFx0XHRmb3IgKHZhciBpPTA7IGkgPCBibG9ja3AubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0cGxhaW50ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShibG9ja3AuY2hhckNvZGVBdChpKSBeIGRlY2Jsb2NrW2ldKSk7XG5cdFx0XHR9XG5cdFx0XHRwb3MrKztcblx0XHR9XG5cdFx0XG5cdFx0cmV0dXJuIHBsYWludGV4dC5qb2luKCcnKTtcblx0fVxufVxuIiwiXG4vKiBSaWpuZGFlbCAoQUVTKSBFbmNyeXB0aW9uXG4gKiBDb3B5cmlnaHQgMjAwNSBIZXJiZXJ0IEhhbmV3aW5rZWwsIHd3dy5oYW5lV0lOLmRlXG4gKiB2ZXJzaW9uIDEuMSwgY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxuXG4gKiBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkIGFzLWlzLCB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4gIFxuICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgZGlzdHJpYnV0ZSBvciBzZWxsIHRoaXMgc29mdHdhcmUsIHdpdGggb3JcbiAqIHdpdGhvdXQgZmVlLCBmb3IgYW55IHB1cnBvc2UgYW5kIGJ5IGFueSBpbmRpdmlkdWFsIG9yIG9yZ2FuaXphdGlvbiwgaXMgaGVyZWJ5XG4gKiBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBhcmFncmFwaCBhcHBlYXIgXG4gKiBpbiBhbGwgY29waWVzLiBEaXN0cmlidXRpb24gYXMgYSBwYXJ0IG9mIGFuIGFwcGxpY2F0aW9uIG9yIGJpbmFyeSBtdXN0XG4gKiBpbmNsdWRlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlclxuICogbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGFwcGxpY2F0aW9uIG9yIGRpc3RyaWJ1dGlvbi5cbiAqL1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gVGhlIHJvdW5kIGNvbnN0YW50cyB1c2VkIGluIHN1YmtleSBleHBhbnNpb25cbnZhciBSY29uID0gWyBcbjB4MDEsIDB4MDIsIDB4MDQsIDB4MDgsIDB4MTAsIDB4MjAsIDB4NDAsIDB4ODAsIDB4MWIsIDB4MzYsIDB4NmMsIDB4ZDgsIFxuMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCwgXG4weGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxIF07XG5cbi8vIFByZWNvbXB1dGVkIGxvb2t1cCB0YWJsZSBmb3IgdGhlIFNCb3hcbnZhciBTID0gW1xuIDk5LCAxMjQsIDExOSwgMTIzLCAyNDIsIDEwNywgMTExLCAxOTcsICA0OCwgICAxLCAxMDMsICA0MywgMjU0LCAyMTUsIDE3MSwgXG4xMTgsIDIwMiwgMTMwLCAyMDEsIDEyNSwgMjUwLCAgODksICA3MSwgMjQwLCAxNzMsIDIxMiwgMTYyLCAxNzUsIDE1NiwgMTY0LCBcbjExNCwgMTkyLCAxODMsIDI1MywgMTQ3LCAgMzgsICA1NCwgIDYzLCAyNDcsIDIwNCwgIDUyLCAxNjUsIDIyOSwgMjQxLCAxMTMsIFxuMjE2LCAgNDksICAyMSwgICA0LCAxOTksICAzNSwgMTk1LCAgMjQsIDE1MCwgICA1LCAxNTQsICAgNywgIDE4LCAxMjgsIDIyNiwgXG4yMzUsICAzOSwgMTc4LCAxMTcsICAgOSwgMTMxLCAgNDQsICAyNiwgIDI3LCAxMTAsICA5MCwgMTYwLCAgODIsICA1OSwgMjE0LCBcbjE3OSwgIDQxLCAyMjcsICA0NywgMTMyLCAgODMsIDIwOSwgICAwLCAyMzcsICAzMiwgMjUyLCAxNzcsICA5MSwgMTA2LCAyMDMsIFxuMTkwLCAgNTcsICA3NCwgIDc2LCAgODgsIDIwNywgMjA4LCAyMzksIDE3MCwgMjUxLCAgNjcsICA3NywgIDUxLCAxMzMsICA2OSwgXG4yNDksICAgMiwgMTI3LCAgODAsICA2MCwgMTU5LCAxNjgsICA4MSwgMTYzLCAgNjQsIDE0MywgMTQ2LCAxNTcsICA1NiwgMjQ1LCBcbjE4OCwgMTgyLCAyMTgsICAzMywgIDE2LCAyNTUsIDI0MywgMjEwLCAyMDUsICAxMiwgIDE5LCAyMzYsICA5NSwgMTUxLCAgNjgsICBcbjIzLCAgMTk2LCAxNjcsIDEyNiwgIDYxLCAxMDAsICA5MywgIDI1LCAxMTUsICA5NiwgMTI5LCAgNzksIDIyMCwgIDM0LCAgNDIsIFxuMTQ0LCAxMzYsICA3MCwgMjM4LCAxODQsICAyMCwgMjIyLCAgOTQsICAxMSwgMjE5LCAyMjQsICA1MCwgIDU4LCAgMTAsICA3MyxcbiAgNiwgIDM2LCAgOTIsIDE5NCwgMjExLCAxNzIsICA5OCwgMTQ1LCAxNDksIDIyOCwgMTIxLCAyMzEsIDIwMCwgIDU1LCAxMDksIFxuMTQxLCAyMTMsICA3OCwgMTY5LCAxMDgsICA4NiwgMjQ0LCAyMzQsIDEwMSwgMTIyLCAxNzQsICAgOCwgMTg2LCAxMjAsICAzNywgIFxuIDQ2LCAgMjgsIDE2NiwgMTgwLCAxOTgsIDIzMiwgMjIxLCAxMTYsICAzMSwgIDc1LCAxODksIDEzOSwgMTM4LCAxMTIsICA2MiwgXG4xODEsIDEwMiwgIDcyLCAgIDMsIDI0NiwgIDE0LCAgOTcsICA1MywgIDg3LCAxODUsIDEzNCwgMTkzLCAgMjksIDE1OCwgMjI1LFxuMjQ4LCAxNTIsICAxNywgMTA1LCAyMTcsIDE0MiwgMTQ4LCAxNTUsICAzMCwgMTM1LCAyMzMsIDIwNiwgIDg1LCAgNDAsIDIyMyxcbjE0MCwgMTYxLCAxMzcsICAxMywgMTkxLCAyMzAsICA2NiwgMTA0LCAgNjUsIDE1MywgIDQ1LCAgMTUsIDE3NiwgIDg0LCAxODcsICBcbiAyMiBdO1xuXG52YXIgVDEgPSBbXG4weGE1NjM2M2M2LCAweDg0N2M3Y2Y4LCAweDk5Nzc3N2VlLCAweDhkN2I3YmY2LFxuMHgwZGYyZjJmZiwgMHhiZDZiNmJkNiwgMHhiMTZmNmZkZSwgMHg1NGM1YzU5MSxcbjB4NTAzMDMwNjAsIDB4MDMwMTAxMDIsIDB4YTk2NzY3Y2UsIDB4N2QyYjJiNTYsXG4weDE5ZmVmZWU3LCAweDYyZDdkN2I1LCAweGU2YWJhYjRkLCAweDlhNzY3NmVjLFxuMHg0NWNhY2E4ZiwgMHg5ZDgyODIxZiwgMHg0MGM5Yzk4OSwgMHg4NzdkN2RmYSxcbjB4MTVmYWZhZWYsIDB4ZWI1OTU5YjIsIDB4Yzk0NzQ3OGUsIDB4MGJmMGYwZmIsXG4weGVjYWRhZDQxLCAweDY3ZDRkNGIzLCAweGZkYTJhMjVmLCAweGVhYWZhZjQ1LFxuMHhiZjljOWMyMywgMHhmN2E0YTQ1MywgMHg5NjcyNzJlNCwgMHg1YmMwYzA5YixcbjB4YzJiN2I3NzUsIDB4MWNmZGZkZTEsIDB4YWU5MzkzM2QsIDB4NmEyNjI2NGMsXG4weDVhMzYzNjZjLCAweDQxM2YzZjdlLCAweDAyZjdmN2Y1LCAweDRmY2NjYzgzLFxuMHg1YzM0MzQ2OCwgMHhmNGE1YTU1MSwgMHgzNGU1ZTVkMSwgMHgwOGYxZjFmOSxcbjB4OTM3MTcxZTIsIDB4NzNkOGQ4YWIsIDB4NTMzMTMxNjIsIDB4M2YxNTE1MmEsXG4weDBjMDQwNDA4LCAweDUyYzdjNzk1LCAweDY1MjMyMzQ2LCAweDVlYzNjMzlkLFxuMHgyODE4MTgzMCwgMHhhMTk2OTYzNywgMHgwZjA1MDUwYSwgMHhiNTlhOWEyZixcbjB4MDkwNzA3MGUsIDB4MzYxMjEyMjQsIDB4OWI4MDgwMWIsIDB4M2RlMmUyZGYsXG4weDI2ZWJlYmNkLCAweDY5MjcyNzRlLCAweGNkYjJiMjdmLCAweDlmNzU3NWVhLFxuMHgxYjA5MDkxMiwgMHg5ZTgzODMxZCwgMHg3NDJjMmM1OCwgMHgyZTFhMWEzNCxcbjB4MmQxYjFiMzYsIDB4YjI2ZTZlZGMsIDB4ZWU1YTVhYjQsIDB4ZmJhMGEwNWIsXG4weGY2NTI1MmE0LCAweDRkM2IzYjc2LCAweDYxZDZkNmI3LCAweGNlYjNiMzdkLFxuMHg3YjI5Mjk1MiwgMHgzZWUzZTNkZCwgMHg3MTJmMmY1ZSwgMHg5Nzg0ODQxMyxcbjB4ZjU1MzUzYTYsIDB4NjhkMWQxYjksIDB4MDAwMDAwMDAsIDB4MmNlZGVkYzEsXG4weDYwMjAyMDQwLCAweDFmZmNmY2UzLCAweGM4YjFiMTc5LCAweGVkNWI1YmI2LFxuMHhiZTZhNmFkNCwgMHg0NmNiY2I4ZCwgMHhkOWJlYmU2NywgMHg0YjM5Mzk3MixcbjB4ZGU0YTRhOTQsIDB4ZDQ0YzRjOTgsIDB4ZTg1ODU4YjAsIDB4NGFjZmNmODUsXG4weDZiZDBkMGJiLCAweDJhZWZlZmM1LCAweGU1YWFhYTRmLCAweDE2ZmJmYmVkLFxuMHhjNTQzNDM4NiwgMHhkNzRkNGQ5YSwgMHg1NTMzMzM2NiwgMHg5NDg1ODUxMSxcbjB4Y2Y0NTQ1OGEsIDB4MTBmOWY5ZTksIDB4MDYwMjAyMDQsIDB4ODE3ZjdmZmUsXG4weGYwNTA1MGEwLCAweDQ0M2MzYzc4LCAweGJhOWY5ZjI1LCAweGUzYThhODRiLFxuMHhmMzUxNTFhMiwgMHhmZWEzYTM1ZCwgMHhjMDQwNDA4MCwgMHg4YThmOGYwNSxcbjB4YWQ5MjkyM2YsIDB4YmM5ZDlkMjEsIDB4NDgzODM4NzAsIDB4MDRmNWY1ZjEsXG4weGRmYmNiYzYzLCAweGMxYjZiNjc3LCAweDc1ZGFkYWFmLCAweDYzMjEyMTQyLFxuMHgzMDEwMTAyMCwgMHgxYWZmZmZlNSwgMHgwZWYzZjNmZCwgMHg2ZGQyZDJiZixcbjB4NGNjZGNkODEsIDB4MTQwYzBjMTgsIDB4MzUxMzEzMjYsIDB4MmZlY2VjYzMsXG4weGUxNWY1ZmJlLCAweGEyOTc5NzM1LCAweGNjNDQ0NDg4LCAweDM5MTcxNzJlLFxuMHg1N2M0YzQ5MywgMHhmMmE3YTc1NSwgMHg4MjdlN2VmYywgMHg0NzNkM2Q3YSxcbjB4YWM2NDY0YzgsIDB4ZTc1ZDVkYmEsIDB4MmIxOTE5MzIsIDB4OTU3MzczZTYsXG4weGEwNjA2MGMwLCAweDk4ODE4MTE5LCAweGQxNGY0ZjllLCAweDdmZGNkY2EzLFxuMHg2NjIyMjI0NCwgMHg3ZTJhMmE1NCwgMHhhYjkwOTAzYiwgMHg4Mzg4ODgwYixcbjB4Y2E0NjQ2OGMsIDB4MjllZWVlYzcsIDB4ZDNiOGI4NmIsIDB4M2MxNDE0MjgsXG4weDc5ZGVkZWE3LCAweGUyNWU1ZWJjLCAweDFkMGIwYjE2LCAweDc2ZGJkYmFkLFxuMHgzYmUwZTBkYiwgMHg1NjMyMzI2NCwgMHg0ZTNhM2E3NCwgMHgxZTBhMGExNCxcbjB4ZGI0OTQ5OTIsIDB4MGEwNjA2MGMsIDB4NmMyNDI0NDgsIDB4ZTQ1YzVjYjgsXG4weDVkYzJjMjlmLCAweDZlZDNkM2JkLCAweGVmYWNhYzQzLCAweGE2NjI2MmM0LFxuMHhhODkxOTEzOSwgMHhhNDk1OTUzMSwgMHgzN2U0ZTRkMywgMHg4Yjc5NzlmMixcbjB4MzJlN2U3ZDUsIDB4NDNjOGM4OGIsIDB4NTkzNzM3NmUsIDB4Yjc2ZDZkZGEsXG4weDhjOGQ4ZDAxLCAweDY0ZDVkNWIxLCAweGQyNGU0ZTljLCAweGUwYTlhOTQ5LFxuMHhiNDZjNmNkOCwgMHhmYTU2NTZhYywgMHgwN2Y0ZjRmMywgMHgyNWVhZWFjZixcbjB4YWY2NTY1Y2EsIDB4OGU3YTdhZjQsIDB4ZTlhZWFlNDcsIDB4MTgwODA4MTAsXG4weGQ1YmFiYTZmLCAweDg4Nzg3OGYwLCAweDZmMjUyNTRhLCAweDcyMmUyZTVjLFxuMHgyNDFjMWMzOCwgMHhmMWE2YTY1NywgMHhjN2I0YjQ3MywgMHg1MWM2YzY5NyxcbjB4MjNlOGU4Y2IsIDB4N2NkZGRkYTEsIDB4OWM3NDc0ZTgsIDB4MjExZjFmM2UsXG4weGRkNGI0Yjk2LCAweGRjYmRiZDYxLCAweDg2OGI4YjBkLCAweDg1OGE4YTBmLFxuMHg5MDcwNzBlMCwgMHg0MjNlM2U3YywgMHhjNGI1YjU3MSwgMHhhYTY2NjZjYyxcbjB4ZDg0ODQ4OTAsIDB4MDUwMzAzMDYsIDB4MDFmNmY2ZjcsIDB4MTIwZTBlMWMsXG4weGEzNjE2MWMyLCAweDVmMzUzNTZhLCAweGY5NTc1N2FlLCAweGQwYjliOTY5LFxuMHg5MTg2ODYxNywgMHg1OGMxYzE5OSwgMHgyNzFkMWQzYSwgMHhiOTllOWUyNyxcbjB4MzhlMWUxZDksIDB4MTNmOGY4ZWIsIDB4YjM5ODk4MmIsIDB4MzMxMTExMjIsXG4weGJiNjk2OWQyLCAweDcwZDlkOWE5LCAweDg5OGU4ZTA3LCAweGE3OTQ5NDMzLFxuMHhiNjliOWIyZCwgMHgyMjFlMWUzYywgMHg5Mjg3ODcxNSwgMHgyMGU5ZTljOSxcbjB4NDljZWNlODcsIDB4ZmY1NTU1YWEsIDB4NzgyODI4NTAsIDB4N2FkZmRmYTUsXG4weDhmOGM4YzAzLCAweGY4YTFhMTU5LCAweDgwODk4OTA5LCAweDE3MGQwZDFhLFxuMHhkYWJmYmY2NSwgMHgzMWU2ZTZkNywgMHhjNjQyNDI4NCwgMHhiODY4NjhkMCxcbjB4YzM0MTQxODIsIDB4YjA5OTk5MjksIDB4NzcyZDJkNWEsIDB4MTEwZjBmMWUsXG4weGNiYjBiMDdiLCAweGZjNTQ1NGE4LCAweGQ2YmJiYjZkLCAweDNhMTYxNjJjIF07XG5cbnZhciBUMiA9IFtcbjB4NjM2M2M2YTUsIDB4N2M3Y2Y4ODQsIDB4Nzc3N2VlOTksIDB4N2I3YmY2OGQsXG4weGYyZjJmZjBkLCAweDZiNmJkNmJkLCAweDZmNmZkZWIxLCAweGM1YzU5MTU0LFxuMHgzMDMwNjA1MCwgMHgwMTAxMDIwMywgMHg2NzY3Y2VhOSwgMHgyYjJiNTY3ZCxcbjB4ZmVmZWU3MTksIDB4ZDdkN2I1NjIsIDB4YWJhYjRkZTYsIDB4NzY3NmVjOWEsXG4weGNhY2E4ZjQ1LCAweDgyODIxZjlkLCAweGM5Yzk4OTQwLCAweDdkN2RmYTg3LFxuMHhmYWZhZWYxNSwgMHg1OTU5YjJlYiwgMHg0NzQ3OGVjOSwgMHhmMGYwZmIwYixcbjB4YWRhZDQxZWMsIDB4ZDRkNGIzNjcsIDB4YTJhMjVmZmQsIDB4YWZhZjQ1ZWEsXG4weDljOWMyM2JmLCAweGE0YTQ1M2Y3LCAweDcyNzJlNDk2LCAweGMwYzA5YjViLFxuMHhiN2I3NzVjMiwgMHhmZGZkZTExYywgMHg5MzkzM2RhZSwgMHgyNjI2NGM2YSxcbjB4MzYzNjZjNWEsIDB4M2YzZjdlNDEsIDB4ZjdmN2Y1MDIsIDB4Y2NjYzgzNGYsXG4weDM0MzQ2ODVjLCAweGE1YTU1MWY0LCAweGU1ZTVkMTM0LCAweGYxZjFmOTA4LFxuMHg3MTcxZTI5MywgMHhkOGQ4YWI3MywgMHgzMTMxNjI1MywgMHgxNTE1MmEzZixcbjB4MDQwNDA4MGMsIDB4YzdjNzk1NTIsIDB4MjMyMzQ2NjUsIDB4YzNjMzlkNWUsXG4weDE4MTgzMDI4LCAweDk2OTYzN2ExLCAweDA1MDUwYTBmLCAweDlhOWEyZmI1LFxuMHgwNzA3MGUwOSwgMHgxMjEyMjQzNiwgMHg4MDgwMWI5YiwgMHhlMmUyZGYzZCxcbjB4ZWJlYmNkMjYsIDB4MjcyNzRlNjksIDB4YjJiMjdmY2QsIDB4NzU3NWVhOWYsXG4weDA5MDkxMjFiLCAweDgzODMxZDllLCAweDJjMmM1ODc0LCAweDFhMWEzNDJlLFxuMHgxYjFiMzYyZCwgMHg2ZTZlZGNiMiwgMHg1YTVhYjRlZSwgMHhhMGEwNWJmYixcbjB4NTI1MmE0ZjYsIDB4M2IzYjc2NGQsIDB4ZDZkNmI3NjEsIDB4YjNiMzdkY2UsXG4weDI5Mjk1MjdiLCAweGUzZTNkZDNlLCAweDJmMmY1ZTcxLCAweDg0ODQxMzk3LFxuMHg1MzUzYTZmNSwgMHhkMWQxYjk2OCwgMHgwMDAwMDAwMCwgMHhlZGVkYzEyYyxcbjB4MjAyMDQwNjAsIDB4ZmNmY2UzMWYsIDB4YjFiMTc5YzgsIDB4NWI1YmI2ZWQsXG4weDZhNmFkNGJlLCAweGNiY2I4ZDQ2LCAweGJlYmU2N2Q5LCAweDM5Mzk3MjRiLFxuMHg0YTRhOTRkZSwgMHg0YzRjOThkNCwgMHg1ODU4YjBlOCwgMHhjZmNmODU0YSxcbjB4ZDBkMGJiNmIsIDB4ZWZlZmM1MmEsIDB4YWFhYTRmZTUsIDB4ZmJmYmVkMTYsXG4weDQzNDM4NmM1LCAweDRkNGQ5YWQ3LCAweDMzMzM2NjU1LCAweDg1ODUxMTk0LFxuMHg0NTQ1OGFjZiwgMHhmOWY5ZTkxMCwgMHgwMjAyMDQwNiwgMHg3ZjdmZmU4MSxcbjB4NTA1MGEwZjAsIDB4M2MzYzc4NDQsIDB4OWY5ZjI1YmEsIDB4YThhODRiZTMsXG4weDUxNTFhMmYzLCAweGEzYTM1ZGZlLCAweDQwNDA4MGMwLCAweDhmOGYwNThhLFxuMHg5MjkyM2ZhZCwgMHg5ZDlkMjFiYywgMHgzODM4NzA0OCwgMHhmNWY1ZjEwNCxcbjB4YmNiYzYzZGYsIDB4YjZiNjc3YzEsIDB4ZGFkYWFmNzUsIDB4MjEyMTQyNjMsXG4weDEwMTAyMDMwLCAweGZmZmZlNTFhLCAweGYzZjNmZDBlLCAweGQyZDJiZjZkLFxuMHhjZGNkODE0YywgMHgwYzBjMTgxNCwgMHgxMzEzMjYzNSwgMHhlY2VjYzMyZixcbjB4NWY1ZmJlZTEsIDB4OTc5NzM1YTIsIDB4NDQ0NDg4Y2MsIDB4MTcxNzJlMzksXG4weGM0YzQ5MzU3LCAweGE3YTc1NWYyLCAweDdlN2VmYzgyLCAweDNkM2Q3YTQ3LFxuMHg2NDY0YzhhYywgMHg1ZDVkYmFlNywgMHgxOTE5MzIyYiwgMHg3MzczZTY5NSxcbjB4NjA2MGMwYTAsIDB4ODE4MTE5OTgsIDB4NGY0ZjllZDEsIDB4ZGNkY2EzN2YsXG4weDIyMjI0NDY2LCAweDJhMmE1NDdlLCAweDkwOTAzYmFiLCAweDg4ODgwYjgzLFxuMHg0NjQ2OGNjYSwgMHhlZWVlYzcyOSwgMHhiOGI4NmJkMywgMHgxNDE0MjgzYyxcbjB4ZGVkZWE3NzksIDB4NWU1ZWJjZTIsIDB4MGIwYjE2MWQsIDB4ZGJkYmFkNzYsXG4weGUwZTBkYjNiLCAweDMyMzI2NDU2LCAweDNhM2E3NDRlLCAweDBhMGExNDFlLFxuMHg0OTQ5OTJkYiwgMHgwNjA2MGMwYSwgMHgyNDI0NDg2YywgMHg1YzVjYjhlNCxcbjB4YzJjMjlmNWQsIDB4ZDNkM2JkNmUsIDB4YWNhYzQzZWYsIDB4NjI2MmM0YTYsXG4weDkxOTEzOWE4LCAweDk1OTUzMWE0LCAweGU0ZTRkMzM3LCAweDc5NzlmMjhiLFxuMHhlN2U3ZDUzMiwgMHhjOGM4OGI0MywgMHgzNzM3NmU1OSwgMHg2ZDZkZGFiNyxcbjB4OGQ4ZDAxOGMsIDB4ZDVkNWIxNjQsIDB4NGU0ZTljZDIsIDB4YTlhOTQ5ZTAsXG4weDZjNmNkOGI0LCAweDU2NTZhY2ZhLCAweGY0ZjRmMzA3LCAweGVhZWFjZjI1LFxuMHg2NTY1Y2FhZiwgMHg3YTdhZjQ4ZSwgMHhhZWFlNDdlOSwgMHgwODA4MTAxOCxcbjB4YmFiYTZmZDUsIDB4Nzg3OGYwODgsIDB4MjUyNTRhNmYsIDB4MmUyZTVjNzIsXG4weDFjMWMzODI0LCAweGE2YTY1N2YxLCAweGI0YjQ3M2M3LCAweGM2YzY5NzUxLFxuMHhlOGU4Y2IyMywgMHhkZGRkYTE3YywgMHg3NDc0ZTg5YywgMHgxZjFmM2UyMSxcbjB4NGI0Yjk2ZGQsIDB4YmRiZDYxZGMsIDB4OGI4YjBkODYsIDB4OGE4YTBmODUsXG4weDcwNzBlMDkwLCAweDNlM2U3YzQyLCAweGI1YjU3MWM0LCAweDY2NjZjY2FhLFxuMHg0ODQ4OTBkOCwgMHgwMzAzMDYwNSwgMHhmNmY2ZjcwMSwgMHgwZTBlMWMxMixcbjB4NjE2MWMyYTMsIDB4MzUzNTZhNWYsIDB4NTc1N2FlZjksIDB4YjliOTY5ZDAsXG4weDg2ODYxNzkxLCAweGMxYzE5OTU4LCAweDFkMWQzYTI3LCAweDllOWUyN2I5LFxuMHhlMWUxZDkzOCwgMHhmOGY4ZWIxMywgMHg5ODk4MmJiMywgMHgxMTExMjIzMyxcbjB4Njk2OWQyYmIsIDB4ZDlkOWE5NzAsIDB4OGU4ZTA3ODksIDB4OTQ5NDMzYTcsXG4weDliOWIyZGI2LCAweDFlMWUzYzIyLCAweDg3ODcxNTkyLCAweGU5ZTljOTIwLFxuMHhjZWNlODc0OSwgMHg1NTU1YWFmZiwgMHgyODI4NTA3OCwgMHhkZmRmYTU3YSxcbjB4OGM4YzAzOGYsIDB4YTFhMTU5ZjgsIDB4ODk4OTA5ODAsIDB4MGQwZDFhMTcsXG4weGJmYmY2NWRhLCAweGU2ZTZkNzMxLCAweDQyNDI4NGM2LCAweDY4NjhkMGI4LFxuMHg0MTQxODJjMywgMHg5OTk5MjliMCwgMHgyZDJkNWE3NywgMHgwZjBmMWUxMSxcbjB4YjBiMDdiY2IsIDB4NTQ1NGE4ZmMsIDB4YmJiYjZkZDYsIDB4MTYxNjJjM2EgXTtcblxudmFyIFQzID0gW1xuMHg2M2M2YTU2MywgMHg3Y2Y4ODQ3YywgMHg3N2VlOTk3NywgMHg3YmY2OGQ3YixcbjB4ZjJmZjBkZjIsIDB4NmJkNmJkNmIsIDB4NmZkZWIxNmYsIDB4YzU5MTU0YzUsXG4weDMwNjA1MDMwLCAweDAxMDIwMzAxLCAweDY3Y2VhOTY3LCAweDJiNTY3ZDJiLFxuMHhmZWU3MTlmZSwgMHhkN2I1NjJkNywgMHhhYjRkZTZhYiwgMHg3NmVjOWE3NixcbjB4Y2E4ZjQ1Y2EsIDB4ODIxZjlkODIsIDB4Yzk4OTQwYzksIDB4N2RmYTg3N2QsXG4weGZhZWYxNWZhLCAweDU5YjJlYjU5LCAweDQ3OGVjOTQ3LCAweGYwZmIwYmYwLFxuMHhhZDQxZWNhZCwgMHhkNGIzNjdkNCwgMHhhMjVmZmRhMiwgMHhhZjQ1ZWFhZixcbjB4OWMyM2JmOWMsIDB4YTQ1M2Y3YTQsIDB4NzJlNDk2NzIsIDB4YzA5YjViYzAsXG4weGI3NzVjMmI3LCAweGZkZTExY2ZkLCAweDkzM2RhZTkzLCAweDI2NGM2YTI2LFxuMHgzNjZjNWEzNiwgMHgzZjdlNDEzZiwgMHhmN2Y1MDJmNywgMHhjYzgzNGZjYyxcbjB4MzQ2ODVjMzQsIDB4YTU1MWY0YTUsIDB4ZTVkMTM0ZTUsIDB4ZjFmOTA4ZjEsXG4weDcxZTI5MzcxLCAweGQ4YWI3M2Q4LCAweDMxNjI1MzMxLCAweDE1MmEzZjE1LFxuMHgwNDA4MGMwNCwgMHhjNzk1NTJjNywgMHgyMzQ2NjUyMywgMHhjMzlkNWVjMyxcbjB4MTgzMDI4MTgsIDB4OTYzN2ExOTYsIDB4MDUwYTBmMDUsIDB4OWEyZmI1OWEsXG4weDA3MGUwOTA3LCAweDEyMjQzNjEyLCAweDgwMWI5YjgwLCAweGUyZGYzZGUyLFxuMHhlYmNkMjZlYiwgMHgyNzRlNjkyNywgMHhiMjdmY2RiMiwgMHg3NWVhOWY3NSxcbjB4MDkxMjFiMDksIDB4ODMxZDllODMsIDB4MmM1ODc0MmMsIDB4MWEzNDJlMWEsXG4weDFiMzYyZDFiLCAweDZlZGNiMjZlLCAweDVhYjRlZTVhLCAweGEwNWJmYmEwLFxuMHg1MmE0ZjY1MiwgMHgzYjc2NGQzYiwgMHhkNmI3NjFkNiwgMHhiMzdkY2ViMyxcbjB4Mjk1MjdiMjksIDB4ZTNkZDNlZTMsIDB4MmY1ZTcxMmYsIDB4ODQxMzk3ODQsXG4weDUzYTZmNTUzLCAweGQxYjk2OGQxLCAweDAwMDAwMDAwLCAweGVkYzEyY2VkLFxuMHgyMDQwNjAyMCwgMHhmY2UzMWZmYywgMHhiMTc5YzhiMSwgMHg1YmI2ZWQ1YixcbjB4NmFkNGJlNmEsIDB4Y2I4ZDQ2Y2IsIDB4YmU2N2Q5YmUsIDB4Mzk3MjRiMzksXG4weDRhOTRkZTRhLCAweDRjOThkNDRjLCAweDU4YjBlODU4LCAweGNmODU0YWNmLFxuMHhkMGJiNmJkMCwgMHhlZmM1MmFlZiwgMHhhYTRmZTVhYSwgMHhmYmVkMTZmYixcbjB4NDM4NmM1NDMsIDB4NGQ5YWQ3NGQsIDB4MzM2NjU1MzMsIDB4ODUxMTk0ODUsXG4weDQ1OGFjZjQ1LCAweGY5ZTkxMGY5LCAweDAyMDQwNjAyLCAweDdmZmU4MTdmLFxuMHg1MGEwZjA1MCwgMHgzYzc4NDQzYywgMHg5ZjI1YmE5ZiwgMHhhODRiZTNhOCxcbjB4NTFhMmYzNTEsIDB4YTM1ZGZlYTMsIDB4NDA4MGMwNDAsIDB4OGYwNThhOGYsXG4weDkyM2ZhZDkyLCAweDlkMjFiYzlkLCAweDM4NzA0ODM4LCAweGY1ZjEwNGY1LFxuMHhiYzYzZGZiYywgMHhiNjc3YzFiNiwgMHhkYWFmNzVkYSwgMHgyMTQyNjMyMSxcbjB4MTAyMDMwMTAsIDB4ZmZlNTFhZmYsIDB4ZjNmZDBlZjMsIDB4ZDJiZjZkZDIsXG4weGNkODE0Y2NkLCAweDBjMTgxNDBjLCAweDEzMjYzNTEzLCAweGVjYzMyZmVjLFxuMHg1ZmJlZTE1ZiwgMHg5NzM1YTI5NywgMHg0NDg4Y2M0NCwgMHgxNzJlMzkxNyxcbjB4YzQ5MzU3YzQsIDB4YTc1NWYyYTcsIDB4N2VmYzgyN2UsIDB4M2Q3YTQ3M2QsXG4weDY0YzhhYzY0LCAweDVkYmFlNzVkLCAweDE5MzIyYjE5LCAweDczZTY5NTczLFxuMHg2MGMwYTA2MCwgMHg4MTE5OTg4MSwgMHg0ZjllZDE0ZiwgMHhkY2EzN2ZkYyxcbjB4MjI0NDY2MjIsIDB4MmE1NDdlMmEsIDB4OTAzYmFiOTAsIDB4ODgwYjgzODgsXG4weDQ2OGNjYTQ2LCAweGVlYzcyOWVlLCAweGI4NmJkM2I4LCAweDE0MjgzYzE0LFxuMHhkZWE3NzlkZSwgMHg1ZWJjZTI1ZSwgMHgwYjE2MWQwYiwgMHhkYmFkNzZkYixcbjB4ZTBkYjNiZTAsIDB4MzI2NDU2MzIsIDB4M2E3NDRlM2EsIDB4MGExNDFlMGEsXG4weDQ5OTJkYjQ5LCAweDA2MGMwYTA2LCAweDI0NDg2YzI0LCAweDVjYjhlNDVjLFxuMHhjMjlmNWRjMiwgMHhkM2JkNmVkMywgMHhhYzQzZWZhYywgMHg2MmM0YTY2MixcbjB4OTEzOWE4OTEsIDB4OTUzMWE0OTUsIDB4ZTRkMzM3ZTQsIDB4NzlmMjhiNzksXG4weGU3ZDUzMmU3LCAweGM4OGI0M2M4LCAweDM3NmU1OTM3LCAweDZkZGFiNzZkLFxuMHg4ZDAxOGM4ZCwgMHhkNWIxNjRkNSwgMHg0ZTljZDI0ZSwgMHhhOTQ5ZTBhOSxcbjB4NmNkOGI0NmMsIDB4NTZhY2ZhNTYsIDB4ZjRmMzA3ZjQsIDB4ZWFjZjI1ZWEsXG4weDY1Y2FhZjY1LCAweDdhZjQ4ZTdhLCAweGFlNDdlOWFlLCAweDA4MTAxODA4LFxuMHhiYTZmZDViYSwgMHg3OGYwODg3OCwgMHgyNTRhNmYyNSwgMHgyZTVjNzIyZSxcbjB4MWMzODI0MWMsIDB4YTY1N2YxYTYsIDB4YjQ3M2M3YjQsIDB4YzY5NzUxYzYsXG4weGU4Y2IyM2U4LCAweGRkYTE3Y2RkLCAweDc0ZTg5Yzc0LCAweDFmM2UyMTFmLFxuMHg0Yjk2ZGQ0YiwgMHhiZDYxZGNiZCwgMHg4YjBkODY4YiwgMHg4YTBmODU4YSxcbjB4NzBlMDkwNzAsIDB4M2U3YzQyM2UsIDB4YjU3MWM0YjUsIDB4NjZjY2FhNjYsXG4weDQ4OTBkODQ4LCAweDAzMDYwNTAzLCAweGY2ZjcwMWY2LCAweDBlMWMxMjBlLFxuMHg2MWMyYTM2MSwgMHgzNTZhNWYzNSwgMHg1N2FlZjk1NywgMHhiOTY5ZDBiOSxcbjB4ODYxNzkxODYsIDB4YzE5OTU4YzEsIDB4MWQzYTI3MWQsIDB4OWUyN2I5OWUsXG4weGUxZDkzOGUxLCAweGY4ZWIxM2Y4LCAweDk4MmJiMzk4LCAweDExMjIzMzExLFxuMHg2OWQyYmI2OSwgMHhkOWE5NzBkOSwgMHg4ZTA3ODk4ZSwgMHg5NDMzYTc5NCxcbjB4OWIyZGI2OWIsIDB4MWUzYzIyMWUsIDB4ODcxNTkyODcsIDB4ZTljOTIwZTksXG4weGNlODc0OWNlLCAweDU1YWFmZjU1LCAweDI4NTA3ODI4LCAweGRmYTU3YWRmLFxuMHg4YzAzOGY4YywgMHhhMTU5ZjhhMSwgMHg4OTA5ODA4OSwgMHgwZDFhMTcwZCxcbjB4YmY2NWRhYmYsIDB4ZTZkNzMxZTYsIDB4NDI4NGM2NDIsIDB4NjhkMGI4NjgsXG4weDQxODJjMzQxLCAweDk5MjliMDk5LCAweDJkNWE3NzJkLCAweDBmMWUxMTBmLFxuMHhiMDdiY2JiMCwgMHg1NGE4ZmM1NCwgMHhiYjZkZDZiYiwgMHgxNjJjM2ExNiBdO1xuXG52YXIgVDQgPSBbXG4weGM2YTU2MzYzLCAweGY4ODQ3YzdjLCAweGVlOTk3Nzc3LCAweGY2OGQ3YjdiLFxuMHhmZjBkZjJmMiwgMHhkNmJkNmI2YiwgMHhkZWIxNmY2ZiwgMHg5MTU0YzVjNSxcbjB4NjA1MDMwMzAsIDB4MDIwMzAxMDEsIDB4Y2VhOTY3NjcsIDB4NTY3ZDJiMmIsXG4weGU3MTlmZWZlLCAweGI1NjJkN2Q3LCAweDRkZTZhYmFiLCAweGVjOWE3Njc2LFxuMHg4ZjQ1Y2FjYSwgMHgxZjlkODI4MiwgMHg4OTQwYzljOSwgMHhmYTg3N2Q3ZCxcbjB4ZWYxNWZhZmEsIDB4YjJlYjU5NTksIDB4OGVjOTQ3NDcsIDB4ZmIwYmYwZjAsXG4weDQxZWNhZGFkLCAweGIzNjdkNGQ0LCAweDVmZmRhMmEyLCAweDQ1ZWFhZmFmLFxuMHgyM2JmOWM5YywgMHg1M2Y3YTRhNCwgMHhlNDk2NzI3MiwgMHg5YjViYzBjMCxcbjB4NzVjMmI3YjcsIDB4ZTExY2ZkZmQsIDB4M2RhZTkzOTMsIDB4NGM2YTI2MjYsXG4weDZjNWEzNjM2LCAweDdlNDEzZjNmLCAweGY1MDJmN2Y3LCAweDgzNGZjY2NjLFxuMHg2ODVjMzQzNCwgMHg1MWY0YTVhNSwgMHhkMTM0ZTVlNSwgMHhmOTA4ZjFmMSxcbjB4ZTI5MzcxNzEsIDB4YWI3M2Q4ZDgsIDB4NjI1MzMxMzEsIDB4MmEzZjE1MTUsXG4weDA4MGMwNDA0LCAweDk1NTJjN2M3LCAweDQ2NjUyMzIzLCAweDlkNWVjM2MzLFxuMHgzMDI4MTgxOCwgMHgzN2ExOTY5NiwgMHgwYTBmMDUwNSwgMHgyZmI1OWE5YSxcbjB4MGUwOTA3MDcsIDB4MjQzNjEyMTIsIDB4MWI5YjgwODAsIDB4ZGYzZGUyZTIsXG4weGNkMjZlYmViLCAweDRlNjkyNzI3LCAweDdmY2RiMmIyLCAweGVhOWY3NTc1LFxuMHgxMjFiMDkwOSwgMHgxZDllODM4MywgMHg1ODc0MmMyYywgMHgzNDJlMWExYSxcbjB4MzYyZDFiMWIsIDB4ZGNiMjZlNmUsIDB4YjRlZTVhNWEsIDB4NWJmYmEwYTAsXG4weGE0ZjY1MjUyLCAweDc2NGQzYjNiLCAweGI3NjFkNmQ2LCAweDdkY2ViM2IzLFxuMHg1MjdiMjkyOSwgMHhkZDNlZTNlMywgMHg1ZTcxMmYyZiwgMHgxMzk3ODQ4NCxcbjB4YTZmNTUzNTMsIDB4Yjk2OGQxZDEsIDB4MDAwMDAwMDAsIDB4YzEyY2VkZWQsXG4weDQwNjAyMDIwLCAweGUzMWZmY2ZjLCAweDc5YzhiMWIxLCAweGI2ZWQ1YjViLFxuMHhkNGJlNmE2YSwgMHg4ZDQ2Y2JjYiwgMHg2N2Q5YmViZSwgMHg3MjRiMzkzOSxcbjB4OTRkZTRhNGEsIDB4OThkNDRjNGMsIDB4YjBlODU4NTgsIDB4ODU0YWNmY2YsXG4weGJiNmJkMGQwLCAweGM1MmFlZmVmLCAweDRmZTVhYWFhLCAweGVkMTZmYmZiLFxuMHg4NmM1NDM0MywgMHg5YWQ3NGQ0ZCwgMHg2NjU1MzMzMywgMHgxMTk0ODU4NSxcbjB4OGFjZjQ1NDUsIDB4ZTkxMGY5ZjksIDB4MDQwNjAyMDIsIDB4ZmU4MTdmN2YsXG4weGEwZjA1MDUwLCAweDc4NDQzYzNjLCAweDI1YmE5ZjlmLCAweDRiZTNhOGE4LFxuMHhhMmYzNTE1MSwgMHg1ZGZlYTNhMywgMHg4MGMwNDA0MCwgMHgwNThhOGY4ZixcbjB4M2ZhZDkyOTIsIDB4MjFiYzlkOWQsIDB4NzA0ODM4MzgsIDB4ZjEwNGY1ZjUsXG4weDYzZGZiY2JjLCAweDc3YzFiNmI2LCAweGFmNzVkYWRhLCAweDQyNjMyMTIxLFxuMHgyMDMwMTAxMCwgMHhlNTFhZmZmZiwgMHhmZDBlZjNmMywgMHhiZjZkZDJkMixcbjB4ODE0Y2NkY2QsIDB4MTgxNDBjMGMsIDB4MjYzNTEzMTMsIDB4YzMyZmVjZWMsXG4weGJlZTE1ZjVmLCAweDM1YTI5Nzk3LCAweDg4Y2M0NDQ0LCAweDJlMzkxNzE3LFxuMHg5MzU3YzRjNCwgMHg1NWYyYTdhNywgMHhmYzgyN2U3ZSwgMHg3YTQ3M2QzZCxcbjB4YzhhYzY0NjQsIDB4YmFlNzVkNWQsIDB4MzIyYjE5MTksIDB4ZTY5NTczNzMsXG4weGMwYTA2MDYwLCAweDE5OTg4MTgxLCAweDllZDE0ZjRmLCAweGEzN2ZkY2RjLFxuMHg0NDY2MjIyMiwgMHg1NDdlMmEyYSwgMHgzYmFiOTA5MCwgMHgwYjgzODg4OCxcbjB4OGNjYTQ2NDYsIDB4YzcyOWVlZWUsIDB4NmJkM2I4YjgsIDB4MjgzYzE0MTQsXG4weGE3NzlkZWRlLCAweGJjZTI1ZTVlLCAweDE2MWQwYjBiLCAweGFkNzZkYmRiLFxuMHhkYjNiZTBlMCwgMHg2NDU2MzIzMiwgMHg3NDRlM2EzYSwgMHgxNDFlMGEwYSxcbjB4OTJkYjQ5NDksIDB4MGMwYTA2MDYsIDB4NDg2YzI0MjQsIDB4YjhlNDVjNWMsXG4weDlmNWRjMmMyLCAweGJkNmVkM2QzLCAweDQzZWZhY2FjLCAweGM0YTY2MjYyLFxuMHgzOWE4OTE5MSwgMHgzMWE0OTU5NSwgMHhkMzM3ZTRlNCwgMHhmMjhiNzk3OSxcbjB4ZDUzMmU3ZTcsIDB4OGI0M2M4YzgsIDB4NmU1OTM3MzcsIDB4ZGFiNzZkNmQsXG4weDAxOGM4ZDhkLCAweGIxNjRkNWQ1LCAweDljZDI0ZTRlLCAweDQ5ZTBhOWE5LFxuMHhkOGI0NmM2YywgMHhhY2ZhNTY1NiwgMHhmMzA3ZjRmNCwgMHhjZjI1ZWFlYSxcbjB4Y2FhZjY1NjUsIDB4ZjQ4ZTdhN2EsIDB4NDdlOWFlYWUsIDB4MTAxODA4MDgsXG4weDZmZDViYWJhLCAweGYwODg3ODc4LCAweDRhNmYyNTI1LCAweDVjNzIyZTJlLFxuMHgzODI0MWMxYywgMHg1N2YxYTZhNiwgMHg3M2M3YjRiNCwgMHg5NzUxYzZjNixcbjB4Y2IyM2U4ZTgsIDB4YTE3Y2RkZGQsIDB4ZTg5Yzc0NzQsIDB4M2UyMTFmMWYsXG4weDk2ZGQ0YjRiLCAweDYxZGNiZGJkLCAweDBkODY4YjhiLCAweDBmODU4YThhLFxuMHhlMDkwNzA3MCwgMHg3YzQyM2UzZSwgMHg3MWM0YjViNSwgMHhjY2FhNjY2NixcbjB4OTBkODQ4NDgsIDB4MDYwNTAzMDMsIDB4ZjcwMWY2ZjYsIDB4MWMxMjBlMGUsXG4weGMyYTM2MTYxLCAweDZhNWYzNTM1LCAweGFlZjk1NzU3LCAweDY5ZDBiOWI5LFxuMHgxNzkxODY4NiwgMHg5OTU4YzFjMSwgMHgzYTI3MWQxZCwgMHgyN2I5OWU5ZSxcbjB4ZDkzOGUxZTEsIDB4ZWIxM2Y4ZjgsIDB4MmJiMzk4OTgsIDB4MjIzMzExMTEsXG4weGQyYmI2OTY5LCAweGE5NzBkOWQ5LCAweDA3ODk4ZThlLCAweDMzYTc5NDk0LFxuMHgyZGI2OWI5YiwgMHgzYzIyMWUxZSwgMHgxNTkyODc4NywgMHhjOTIwZTllOSxcbjB4ODc0OWNlY2UsIDB4YWFmZjU1NTUsIDB4NTA3ODI4MjgsIDB4YTU3YWRmZGYsXG4weDAzOGY4YzhjLCAweDU5ZjhhMWExLCAweDA5ODA4OTg5LCAweDFhMTcwZDBkLFxuMHg2NWRhYmZiZiwgMHhkNzMxZTZlNiwgMHg4NGM2NDI0MiwgMHhkMGI4Njg2OCxcbjB4ODJjMzQxNDEsIDB4MjliMDk5OTksIDB4NWE3NzJkMmQsIDB4MWUxMTBmMGYsXG4weDdiY2JiMGIwLCAweGE4ZmM1NDU0LCAweDZkZDZiYmJiLCAweDJjM2ExNjE2IF07XG5cbmZ1bmN0aW9uIEIwKHgpIHsgcmV0dXJuICh4JjI1NSk7IH1cbmZ1bmN0aW9uIEIxKHgpIHsgcmV0dXJuICgoeD4+OCkmMjU1KTsgfVxuZnVuY3Rpb24gQjIoeCkgeyByZXR1cm4gKCh4Pj4xNikmMjU1KTsgfVxuZnVuY3Rpb24gQjMoeCkgeyByZXR1cm4gKCh4Pj4yNCkmMjU1KTsgfVxuXG5mdW5jdGlvbiBGMSh4MCwgeDEsIHgyLCB4MylcbntcbiAgcmV0dXJuIEIxKFQxW3gwJjI1NV0pIHwgKEIxKFQxWyh4MT4+OCkmMjU1XSk8PDgpXG4gICAgICB8IChCMShUMVsoeDI+PjE2KSYyNTVdKTw8MTYpIHwgKEIxKFQxW3gzPj4+MjRdKTw8MjQpO1xufVxuXG5mdW5jdGlvbiBwYWNrQnl0ZXMob2N0ZXRzKVxue1xuICB2YXIgaSwgajtcbiAgdmFyIGxlbj1vY3RldHMubGVuZ3RoO1xuICB2YXIgYj1uZXcgQXJyYXkobGVuLzQpO1xuXG4gIGlmICghb2N0ZXRzIHx8IGxlbiAlIDQpIHJldHVybjtcblxuICBmb3IgKGk9MCwgaj0wOyBqPGxlbjsgais9IDQpXG4gICAgIGJbaSsrXSA9IG9jdGV0c1tqXSB8IChvY3RldHNbaisxXTw8OCkgfCAob2N0ZXRzW2orMl08PDE2KSB8IChvY3RldHNbaiszXTw8MjQpO1xuXG4gIHJldHVybiBiOyAgXG59XG5cbmZ1bmN0aW9uIHVucGFja0J5dGVzKHBhY2tlZClcbntcbiAgdmFyIGo7XG4gIHZhciBpPTAsIGwgPSBwYWNrZWQubGVuZ3RoO1xuICB2YXIgciA9IG5ldyBBcnJheShsKjQpO1xuXG4gIGZvciAoaj0wOyBqPGw7IGorKylcbiAge1xuICAgIHJbaSsrXSA9IEIwKHBhY2tlZFtqXSk7XG4gICAgcltpKytdID0gQjEocGFja2VkW2pdKTtcbiAgICByW2krK10gPSBCMihwYWNrZWRbal0pO1xuICAgIHJbaSsrXSA9IEIzKHBhY2tlZFtqXSk7XG4gIH1cbiAgcmV0dXJuIHI7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG52YXIgbWF4a2M9ODtcbnZhciBtYXhyaz0xNDtcblxuZnVuY3Rpb24ga2V5RXhwYW5zaW9uKGtleSlcbntcbiAgdmFyIGtjLCBpLCBqLCByLCB0O1xuICB2YXIgcm91bmRzO1xuICB2YXIga2V5U2NoZWQ9bmV3IEFycmF5KG1heHJrKzEpO1xuICB2YXIga2V5bGVuPWtleS5sZW5ndGg7XG4gIHZhciBrPW5ldyBBcnJheShtYXhrYyk7XG4gIHZhciB0az1uZXcgQXJyYXkobWF4a2MpO1xuICB2YXIgcmNvbnBvaW50ZXI9MDtcblxuICBpZihrZXlsZW49PTE2KVxuICB7XG4gICByb3VuZHM9MTA7XG4gICBrYz00O1xuICB9XG4gIGVsc2UgaWYoa2V5bGVuPT0yNClcbiAge1xuICAgcm91bmRzPTEyO1xuICAga2M9NjtcbiAgfVxuICBlbHNlIGlmKGtleWxlbj09MzIpXG4gIHtcbiAgIHJvdW5kcz0xNDtcbiAgIGtjPTg7XG4gIH1cbiAgZWxzZVxuICB7XG5cdHV0aWwucHJpbnRfZXJyb3IoJ2Flcy5qczogSW52YWxpZCBrZXktbGVuZ3RoIGZvciBBRVMga2V5Oicra2V5bGVuKTtcbiAgIHJldHVybjtcbiAgfVxuXG4gIGZvcihpPTA7IGk8bWF4cmsrMTsgaSsrKSBrZXlTY2hlZFtpXT1uZXcgQXJyYXkoNCk7XG5cbiAgZm9yKGk9MCxqPTA7IGo8a2V5bGVuOyBqKyssaSs9NClcbiAgICBrW2pdID0ga2V5LmNoYXJDb2RlQXQoaSkgfCAoa2V5LmNoYXJDb2RlQXQoaSsxKTw8OClcbiAgICAgICAgICAgICAgICAgICAgIHwgKGtleS5jaGFyQ29kZUF0KGkrMik8PDE2KSB8IChrZXkuY2hhckNvZGVBdChpKzMpPDwyNCk7XG5cbiAgZm9yKGo9a2MtMTsgaj49MDsgai0tKSB0a1tqXSA9IGtbal07XG5cbiAgcj0wO1xuICB0PTA7XG4gIGZvcihqPTA7IChqPGtjKSYmKHI8cm91bmRzKzEpOyApXG4gIHtcbiAgICBmb3IoOyAoajxrYykmJih0PDQpOyBqKyssdCsrKVxuICAgIHtcbiAgICAgIGtleVNjaGVkW3JdW3RdPXRrW2pdO1xuICAgIH1cbiAgICBpZih0PT00KVxuICAgIHtcbiAgICAgIHIrKztcbiAgICAgIHQ9MDtcbiAgICB9XG4gIH1cblxuICB3aGlsZShyPHJvdW5kcysxKVxuICB7XG4gICAgdmFyIHRlbXAgPSB0a1trYy0xXTtcblxuICAgIHRrWzBdIF49IFNbQjEodGVtcCldIHwgKFNbQjIodGVtcCldPDw4KSB8IChTW0IzKHRlbXApXTw8MTYpIHwgKFNbQjAodGVtcCldPDwyNCk7XG4gICAgdGtbMF0gXj0gUmNvbltyY29ucG9pbnRlcisrXTtcblxuICAgIGlmKGtjICE9IDgpXG4gICAge1xuICAgICAgZm9yKGo9MTsgajxrYzsgaisrKSB0a1tqXSBePSB0a1tqLTFdO1xuICAgIH1cbiAgICBlbHNlXG4gICAge1xuICAgICAgZm9yKGo9MTsgajxrYy8yOyBqKyspIHRrW2pdIF49IHRrW2otMV07XG4gXG4gICAgICB0ZW1wID0gdGtba2MvMi0xXTtcbiAgICAgIHRrW2tjLzJdIF49IFNbQjAodGVtcCldIHwgKFNbQjEodGVtcCldPDw4KSB8IChTW0IyKHRlbXApXTw8MTYpIHwgKFNbQjModGVtcCldPDwyNCk7XG5cbiAgICAgIGZvcihqPWtjLzIrMTsgajxrYzsgaisrKSB0a1tqXSBePSB0a1tqLTFdO1xuICAgIH1cblxuICAgIGZvcihqPTA7IChqPGtjKSYmKHI8cm91bmRzKzEpOyApXG4gICAge1xuICAgICAgZm9yKDsgKGo8a2MpJiYodDw0KTsgaisrLHQrKylcbiAgICAgIHtcbiAgICAgICAga2V5U2NoZWRbcl1bdF09dGtbal07XG4gICAgICB9XG4gICAgICBpZih0PT00KVxuICAgICAge1xuICAgICAgICByKys7XG4gICAgICAgIHQ9MDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdGhpcy5yb3VuZHMgPSByb3VuZHM7XG4gIHRoaXMucmsgPSBrZXlTY2hlZDtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbmZ1bmN0aW9uIEFFU2VuY3J5cHQoYmxvY2ssIGN0eClcbntcbiAgdmFyIHI7XG4gIHZhciB0MCx0MSx0Mix0MztcblxuICB2YXIgYiA9IHBhY2tCeXRlcyhibG9jayk7XG4gIHZhciByb3VuZHMgPSBjdHgucm91bmRzO1xuICB2YXIgYjAgPSBiWzBdO1xuICB2YXIgYjEgPSBiWzFdO1xuICB2YXIgYjIgPSBiWzJdO1xuICB2YXIgYjMgPSBiWzNdO1xuXG4gIGZvcihyPTA7IHI8cm91bmRzLTE7IHIrKylcbiAge1xuICAgIHQwID0gYjAgXiBjdHgucmtbcl1bMF07XG4gICAgdDEgPSBiMSBeIGN0eC5ya1tyXVsxXTtcbiAgICB0MiA9IGIyIF4gY3R4LnJrW3JdWzJdO1xuICAgIHQzID0gYjMgXiBjdHgucmtbcl1bM107XG5cbiAgICBiMCA9IFQxW3QwJjI1NV0gXiBUMlsodDE+PjgpJjI1NV0gXiBUM1sodDI+PjE2KSYyNTVdIF4gVDRbdDM+Pj4yNF07XG4gICAgYjEgPSBUMVt0MSYyNTVdIF4gVDJbKHQyPj44KSYyNTVdIF4gVDNbKHQzPj4xNikmMjU1XSBeIFQ0W3QwPj4+MjRdO1xuICAgIGIyID0gVDFbdDImMjU1XSBeIFQyWyh0Mz4+OCkmMjU1XSBeIFQzWyh0MD4+MTYpJjI1NV0gXiBUNFt0MT4+PjI0XTtcbiAgICBiMyA9IFQxW3QzJjI1NV0gXiBUMlsodDA+PjgpJjI1NV0gXiBUM1sodDE+PjE2KSYyNTVdIF4gVDRbdDI+Pj4yNF07XG4gIH1cblxuICAvLyBsYXN0IHJvdW5kIGlzIHNwZWNpYWxcbiAgciA9IHJvdW5kcy0xO1xuXG4gIHQwID0gYjAgXiBjdHgucmtbcl1bMF07XG4gIHQxID0gYjEgXiBjdHgucmtbcl1bMV07XG4gIHQyID0gYjIgXiBjdHgucmtbcl1bMl07XG4gIHQzID0gYjMgXiBjdHgucmtbcl1bM107XG5cbiAgYlswXSA9IEYxKHQwLCB0MSwgdDIsIHQzKSBeIGN0eC5ya1tyb3VuZHNdWzBdO1xuICBiWzFdID0gRjEodDEsIHQyLCB0MywgdDApIF4gY3R4LnJrW3JvdW5kc11bMV07XG4gIGJbMl0gPSBGMSh0MiwgdDMsIHQwLCB0MSkgXiBjdHgucmtbcm91bmRzXVsyXTtcbiAgYlszXSA9IEYxKHQzLCB0MCwgdDEsIHQyKSBeIGN0eC5ya1tyb3VuZHNdWzNdO1xuXG4gIHJldHVybiB1bnBhY2tCeXRlcyhiKTtcbn1cblxuZnVuY3Rpb24gbWFrZUNsYXNzKGxlbmd0aCkge1xuXG5cdHZhciBjID0gZnVuY3Rpb24oa2V5KSB7XG5cdFx0dGhpcy5rZXkgPSBrZXlFeHBhbnNpb24oa2V5KTtcblxuXHRcdHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGJsb2NrKSB7XG5cdFx0XHRyZXR1cm4gQUVTZW5jcnlwdChibG9jaywgdGhpcy5rZXkpO1xuXHRcdH1cblx0fVxuXG5cdGMuYmxvY2tTaXplID0gYy5wcm90b3R5cGUuYmxvY2tTaXplID0gMTY7XG5cdGMua2V5U2l6ZSA9IGMucHJvdG90eXBlLmtleVNpemUgPSBsZW5ndGggLyA4O1xuXG5cdHJldHVybiBjO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHt9XG5cbnZhciB0eXBlcyA9IFsxMjgsIDE5MiwgMjU2XTtcblxuZm9yKHZhciBpIGluIHR5cGVzICkge1xuXHRtb2R1bGUuZXhwb3J0c1t0eXBlc1tpXV0gPSBtYWtlQ2xhc3ModHlwZXNbaV0pO1xufVxuIiwiLyogTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIIFxuICogXG4gKiBPcmlnaW5hbGx5IHdyaXR0ZW4gYnkgbmtsZWluIHNvZnR3YXJlIChua2xlaW4uY29tKVxuICovXG5cbi8qIFxuICogSmF2YXNjcmlwdCBpbXBsZW1lbnRhdGlvbiBiYXNlZCBvbiBCcnVjZSBTY2huZWllcidzIHJlZmVyZW5jZSBpbXBsZW1lbnRhdGlvbi5cbiAqXG4gKlxuICogVGhlIGNvbnN0cnVjdG9yIGRvZXNuJ3QgZG8gbXVjaCBvZiBhbnl0aGluZy4gIEl0J3MganVzdCBoZXJlXG4gKiBzbyB3ZSBjYW4gc3RhcnQgZGVmaW5pbmcgcHJvcGVydGllcyBhbmQgbWV0aG9kcyBhbmQgc3VjaC5cbiAqL1xuZnVuY3Rpb24gQmxvd2Zpc2goKSB7XG59O1xuXG4vKlxuICogRGVjbGFyZSB0aGUgYmxvY2sgc2l6ZSBzbyB0aGF0IHByb3RvY29scyBrbm93IHdoYXQgc2l6ZVxuICogSW5pdGlhbGl6YXRpb24gVmVjdG9yIChJVikgdGhleSB3aWxsIG5lZWQuXG4gKi9cbkJsb3dmaXNoLnByb3RvdHlwZS5CTE9DS1NJWkUgPSA4O1xuXG4vKlxuICogVGhlc2UgYXJlIHRoZSBkZWZhdWx0IFNCT1hFUy5cbiAqL1xuQmxvd2Zpc2gucHJvdG90eXBlLlNCT1hFUyA9IFtcbiAgICBbXG5cdDB4ZDEzMTBiYTYsIDB4OThkZmI1YWMsIDB4MmZmZDcyZGIsIDB4ZDAxYWRmYjcsIDB4YjhlMWFmZWQsIDB4NmEyNjdlOTYsXG5cdDB4YmE3YzkwNDUsIDB4ZjEyYzdmOTksIDB4MjRhMTk5NDcsIDB4YjM5MTZjZjcsIDB4MDgwMWYyZTIsIDB4ODU4ZWZjMTYsXG5cdDB4NjM2OTIwZDgsIDB4NzE1NzRlNjksIDB4YTQ1OGZlYTMsIDB4ZjQ5MzNkN2UsIDB4MGQ5NTc0OGYsIDB4NzI4ZWI2NTgsXG5cdDB4NzE4YmNkNTgsIDB4ODIxNTRhZWUsIDB4N2I1NGE0MWQsIDB4YzI1YTU5YjUsIDB4OWMzMGQ1MzksIDB4MmFmMjYwMTMsXG5cdDB4YzVkMWIwMjMsIDB4Mjg2MDg1ZjAsIDB4Y2E0MTc5MTgsIDB4YjhkYjM4ZWYsIDB4OGU3OWRjYjAsIDB4NjAzYTE4MGUsXG5cdDB4NmM5ZTBlOGIsIDB4YjAxZThhM2UsIDB4ZDcxNTc3YzEsIDB4YmQzMTRiMjcsIDB4NzhhZjJmZGEsIDB4NTU2MDVjNjAsXG5cdDB4ZTY1NTI1ZjMsIDB4YWE1NWFiOTQsIDB4NTc0ODk4NjIsIDB4NjNlODE0NDAsIDB4NTVjYTM5NmEsIDB4MmFhYjEwYjYsXG5cdDB4YjRjYzVjMzQsIDB4MTE0MWU4Y2UsIDB4YTE1NDg2YWYsIDB4N2M3MmU5OTMsIDB4YjNlZTE0MTEsIDB4NjM2ZmJjMmEsXG5cdDB4MmJhOWM1NWQsIDB4NzQxODMxZjYsIDB4Y2U1YzNlMTYsIDB4OWI4NzkzMWUsIDB4YWZkNmJhMzMsIDB4NmMyNGNmNWMsXG5cdDB4N2EzMjUzODEsIDB4Mjg5NTg2NzcsIDB4M2I4ZjQ4OTgsIDB4NmI0YmI5YWYsIDB4YzRiZmU4MWIsIDB4NjYyODIxOTMsXG5cdDB4NjFkODA5Y2MsIDB4ZmIyMWE5OTEsIDB4NDg3Y2FjNjAsIDB4NWRlYzgwMzIsIDB4ZWY4NDVkNWQsIDB4ZTk4NTc1YjEsXG5cdDB4ZGMyNjIzMDIsIDB4ZWI2NTFiODgsIDB4MjM4OTNlODEsIDB4ZDM5NmFjYzUsIDB4MGY2ZDZmZjMsIDB4ODNmNDQyMzksXG5cdDB4MmUwYjQ0ODIsIDB4YTQ4NDIwMDQsIDB4NjljOGYwNGEsIDB4OWUxZjliNWUsIDB4MjFjNjY4NDIsIDB4ZjZlOTZjOWEsXG5cdDB4NjcwYzljNjEsIDB4YWJkMzg4ZjAsIDB4NmE1MWEwZDIsIDB4ZDg1NDJmNjgsIDB4OTYwZmE3MjgsIDB4YWI1MTMzYTMsXG5cdDB4NmVlZjBiNmMsIDB4MTM3YTNiZTQsIDB4YmEzYmYwNTAsIDB4N2VmYjJhOTgsIDB4YTFmMTY1MWQsIDB4MzlhZjAxNzYsXG5cdDB4NjZjYTU5M2UsIDB4ODI0MzBlODgsIDB4OGNlZTg2MTksIDB4NDU2ZjlmYjQsIDB4N2Q4NGE1YzMsIDB4M2I4YjVlYmUsXG5cdDB4ZTA2Zjc1ZDgsIDB4ODVjMTIwNzMsIDB4NDAxYTQ0OWYsIDB4NTZjMTZhYTYsIDB4NGVkM2FhNjIsIDB4MzYzZjc3MDYsXG5cdDB4MWJmZWRmNzIsIDB4NDI5YjAyM2QsIDB4MzdkMGQ3MjQsIDB4ZDAwYTEyNDgsIDB4ZGIwZmVhZDMsIDB4NDlmMWMwOWIsXG5cdDB4MDc1MzcyYzksIDB4ODA5OTFiN2IsIDB4MjVkNDc5ZDgsIDB4ZjZlOGRlZjcsIDB4ZTNmZTUwMWEsIDB4YjY3OTRjM2IsXG5cdDB4OTc2Y2UwYmQsIDB4MDRjMDA2YmEsIDB4YzFhOTRmYjYsIDB4NDA5ZjYwYzQsIDB4NWU1YzllYzIsIDB4MTk2YTI0NjMsXG5cdDB4NjhmYjZmYWYsIDB4M2U2YzUzYjUsIDB4MTMzOWIyZWIsIDB4M2I1MmVjNmYsIDB4NmRmYzUxMWYsIDB4OWIzMDk1MmMsXG5cdDB4Y2M4MTQ1NDQsIDB4YWY1ZWJkMDksIDB4YmVlM2QwMDQsIDB4ZGUzMzRhZmQsIDB4NjYwZjI4MDcsIDB4MTkyZTRiYjMsXG5cdDB4YzBjYmE4NTcsIDB4NDVjODc0MGYsIDB4ZDIwYjVmMzksIDB4YjlkM2ZiZGIsIDB4NTU3OWMwYmQsIDB4MWE2MDMyMGEsXG5cdDB4ZDZhMTAwYzYsIDB4NDAyYzcyNzksIDB4Njc5ZjI1ZmUsIDB4ZmIxZmEzY2MsIDB4OGVhNWU5ZjgsIDB4ZGIzMjIyZjgsXG5cdDB4M2M3NTE2ZGYsIDB4ZmQ2MTZiMTUsIDB4MmY1MDFlYzgsIDB4YWQwNTUyYWIsIDB4MzIzZGI1ZmEsIDB4ZmQyMzg3NjAsXG5cdDB4NTMzMTdiNDgsIDB4M2UwMGRmODIsIDB4OWU1YzU3YmIsIDB4Y2E2ZjhjYTAsIDB4MWE4NzU2MmUsIDB4ZGYxNzY5ZGIsXG5cdDB4ZDU0MmE4ZjYsIDB4Mjg3ZWZmYzMsIDB4YWM2NzMyYzYsIDB4OGM0ZjU1NzMsIDB4Njk1YjI3YjAsIDB4YmJjYTU4YzgsXG5cdDB4ZTFmZmEzNWQsIDB4YjhmMDExYTAsIDB4MTBmYTNkOTgsIDB4ZmQyMTgzYjgsIDB4NGFmY2I1NmMsIDB4MmRkMWQzNWIsXG5cdDB4OWE1M2U0NzksIDB4YjZmODQ1NjUsIDB4ZDI4ZTQ5YmMsIDB4NGJmYjk3OTAsIDB4ZTFkZGYyZGEsIDB4YTRjYjdlMzMsXG5cdDB4NjJmYjEzNDEsIDB4Y2VlNGM2ZTgsIDB4ZWYyMGNhZGEsIDB4MzY3NzRjMDEsIDB4ZDA3ZTllZmUsIDB4MmJmMTFmYjQsXG5cdDB4OTVkYmRhNGQsIDB4YWU5MDkxOTgsIDB4ZWFhZDhlNzEsIDB4NmI5M2Q1YTAsIDB4ZDA4ZWQxZDAsIDB4YWZjNzI1ZTAsXG5cdDB4OGUzYzViMmYsIDB4OGU3NTk0YjcsIDB4OGZmNmUyZmIsIDB4ZjIxMjJiNjQsIDB4ODg4OGI4MTIsIDB4OTAwZGYwMWMsXG5cdDB4NGZhZDVlYTAsIDB4Njg4ZmMzMWMsIDB4ZDFjZmYxOTEsIDB4YjNhOGMxYWQsIDB4MmYyZjIyMTgsIDB4YmUwZTE3NzcsXG5cdDB4ZWE3NTJkZmUsIDB4OGIwMjFmYTEsIDB4ZTVhMGNjMGYsIDB4YjU2Zjc0ZTgsIDB4MThhY2YzZDYsIDB4Y2U4OWUyOTksXG5cdDB4YjRhODRmZTAsIDB4ZmQxM2UwYjcsIDB4N2NjNDNiODEsIDB4ZDJhZGE4ZDksIDB4MTY1ZmEyNjYsIDB4ODA5NTc3MDUsXG5cdDB4OTNjYzczMTQsIDB4MjExYTE0NzcsIDB4ZTZhZDIwNjUsIDB4NzdiNWZhODYsIDB4Yzc1NDQyZjUsIDB4ZmI5ZDM1Y2YsXG5cdDB4ZWJjZGFmMGMsIDB4N2IzZTg5YTAsIDB4ZDY0MTFiZDMsIDB4YWUxZTdlNDksIDB4MDAyNTBlMmQsIDB4MjA3MWIzNWUsXG5cdDB4MjI2ODAwYmIsIDB4NTdiOGUwYWYsIDB4MjQ2NDM2OWIsIDB4ZjAwOWI5MWUsIDB4NTU2MzkxMWQsIDB4NTlkZmE2YWEsXG5cdDB4NzhjMTQzODksIDB4ZDk1YTUzN2YsIDB4MjA3ZDViYTIsIDB4MDJlNWI5YzUsIDB4ODMyNjAzNzYsIDB4NjI5NWNmYTksXG5cdDB4MTFjODE5NjgsIDB4NGU3MzRhNDEsIDB4YjM0NzJkY2EsIDB4N2IxNGE5NGEsIDB4MWI1MTAwNTIsIDB4OWE1MzI5MTUsXG5cdDB4ZDYwZjU3M2YsIDB4YmM5YmM2ZTQsIDB4MmI2MGE0NzYsIDB4ODFlNjc0MDAsIDB4MDhiYTZmYjUsIDB4NTcxYmU5MWYsXG5cdDB4ZjI5NmVjNmIsIDB4MmEwZGQ5MTUsIDB4YjY2MzY1MjEsIDB4ZTdiOWY5YjYsIDB4ZmYzNDA1MmUsIDB4YzU4NTU2NjQsXG5cdDB4NTNiMDJkNWQsIDB4YTk5ZjhmYTEsIDB4MDhiYTQ3OTksIDB4NmU4NTA3NmFcbiAgICBdLCBbXG5cdDB4NGI3YTcwZTksIDB4YjViMzI5NDQsIDB4ZGI3NTA5MmUsIDB4YzQxOTI2MjMsIDB4YWQ2ZWE2YjAsIDB4NDlhN2RmN2QsXG5cdDB4OWNlZTYwYjgsIDB4OGZlZGIyNjYsIDB4ZWNhYThjNzEsIDB4Njk5YTE3ZmYsIDB4NTY2NDUyNmMsIDB4YzJiMTllZTEsXG5cdDB4MTkzNjAyYTUsIDB4NzUwOTRjMjksIDB4YTA1OTEzNDAsIDB4ZTQxODNhM2UsIDB4M2Y1NDk4OWEsIDB4NWI0MjlkNjUsXG5cdDB4NmI4ZmU0ZDYsIDB4OTlmNzNmZDYsIDB4YTFkMjljMDcsIDB4ZWZlODMwZjUsIDB4NGQyZDM4ZTYsIDB4ZjAyNTVkYzEsXG5cdDB4NGNkZDIwODYsIDB4ODQ3MGViMjYsIDB4NjM4MmU5YzYsIDB4MDIxZWNjNWUsIDB4MDk2ODZiM2YsIDB4M2ViYWVmYzksXG5cdDB4M2M5NzE4MTQsIDB4NmI2YTcwYTEsIDB4Njg3ZjM1ODQsIDB4NTJhMGUyODYsIDB4Yjc5YzUzMDUsIDB4YWE1MDA3MzcsXG5cdDB4M2UwNzg0MWMsIDB4N2ZkZWFlNWMsIDB4OGU3ZDQ0ZWMsIDB4NTcxNmYyYjgsIDB4YjAzYWRhMzcsIDB4ZjA1MDBjMGQsXG5cdDB4ZjAxYzFmMDQsIDB4MDIwMGIzZmYsIDB4YWUwY2Y1MWEsIDB4M2NiNTc0YjIsIDB4MjU4MzdhNTgsIDB4ZGMwOTIxYmQsXG5cdDB4ZDE5MTEzZjksIDB4N2NhOTJmZjYsIDB4OTQzMjQ3NzMsIDB4MjJmNTQ3MDEsIDB4M2FlNWU1ODEsIDB4MzdjMmRhZGMsXG5cdDB4YzhiNTc2MzQsIDB4OWFmM2RkYTcsIDB4YTk0NDYxNDYsIDB4MGZkMDAzMGUsIDB4ZWNjOGM3M2UsIDB4YTQ3NTFlNDEsXG5cdDB4ZTIzOGNkOTksIDB4M2JlYTBlMmYsIDB4MzI4MGJiYTEsIDB4MTgzZWIzMzEsIDB4NGU1NDhiMzgsIDB4NGY2ZGI5MDgsXG5cdDB4NmY0MjBkMDMsIDB4ZjYwYTA0YmYsIDB4MmNiODEyOTAsIDB4MjQ5NzdjNzksIDB4NTY3OWIwNzIsIDB4YmNhZjg5YWYsXG5cdDB4ZGU5YTc3MWYsIDB4ZDk5MzA4MTAsIDB4YjM4YmFlMTIsIDB4ZGNjZjNmMmUsIDB4NTUxMjcyMWYsIDB4MmU2YjcxMjQsXG5cdDB4NTAxYWRkZTYsIDB4OWY4NGNkODcsIDB4N2E1ODQ3MTgsIDB4NzQwOGRhMTcsIDB4YmM5ZjlhYmMsIDB4ZTk0YjdkOGMsXG5cdDB4ZWM3YWVjM2EsIDB4ZGI4NTFkZmEsIDB4NjMwOTQzNjYsIDB4YzQ2NGMzZDIsIDB4ZWYxYzE4NDcsIDB4MzIxNWQ5MDgsXG5cdDB4ZGQ0MzNiMzcsIDB4MjRjMmJhMTYsIDB4MTJhMTRkNDMsIDB4MmE2NWM0NTEsIDB4NTA5NDAwMDIsIDB4MTMzYWU0ZGQsXG5cdDB4NzFkZmY4OWUsIDB4MTAzMTRlNTUsIDB4ODFhYzc3ZDYsIDB4NWYxMTE5OWIsIDB4MDQzNTU2ZjEsIDB4ZDdhM2M3NmIsXG5cdDB4M2MxMTE4M2IsIDB4NTkyNGE1MDksIDB4ZjI4ZmU2ZWQsIDB4OTdmMWZiZmEsIDB4OWViYWJmMmMsIDB4MWUxNTNjNmUsXG5cdDB4ODZlMzQ1NzAsIDB4ZWFlOTZmYjEsIDB4ODYwZTVlMGEsIDB4NWEzZTJhYjMsIDB4NzcxZmU3MWMsIDB4NGUzZDA2ZmEsXG5cdDB4Mjk2NWRjYjksIDB4OTllNzFkMGYsIDB4ODAzZTg5ZDYsIDB4NTI2NmM4MjUsIDB4MmU0Y2M5NzgsIDB4OWMxMGIzNmEsXG5cdDB4YzYxNTBlYmEsIDB4OTRlMmVhNzgsIDB4YTVmYzNjNTMsIDB4MWUwYTJkZjQsIDB4ZjJmNzRlYTcsIDB4MzYxZDJiM2QsXG5cdDB4MTkzOTI2MGYsIDB4MTljMjc5NjAsIDB4NTIyM2E3MDgsIDB4ZjcxMzEyYjYsIDB4ZWJhZGZlNmUsIDB4ZWFjMzFmNjYsXG5cdDB4ZTNiYzQ1OTUsIDB4YTY3YmM4ODMsIDB4YjE3ZjM3ZDEsIDB4MDE4Y2ZmMjgsIDB4YzMzMmRkZWYsIDB4YmU2YzVhYTUsXG5cdDB4NjU1ODIxODUsIDB4NjhhYjk4MDIsIDB4ZWVjZWE1MGYsIDB4ZGIyZjk1M2IsIDB4MmFlZjdkYWQsIDB4NWI2ZTJmODQsXG5cdDB4MTUyMWI2MjgsIDB4MjkwNzYxNzAsIDB4ZWNkZDQ3NzUsIDB4NjE5ZjE1MTAsIDB4MTNjY2E4MzAsIDB4ZWI2MWJkOTYsXG5cdDB4MDMzNGZlMWUsIDB4YWEwMzYzY2YsIDB4YjU3MzVjOTAsIDB4NGM3MGEyMzksIDB4ZDU5ZTllMGIsIDB4Y2JhYWRlMTQsXG5cdDB4ZWVjYzg2YmMsIDB4NjA2MjJjYTcsIDB4OWNhYjVjYWIsIDB4YjJmMzg0NmUsIDB4NjQ4YjFlYWYsIDB4MTliZGYwY2EsXG5cdDB4YTAyMzY5YjksIDB4NjU1YWJiNTAsIDB4NDA2ODVhMzIsIDB4M2MyYWI0YjMsIDB4MzE5ZWU5ZDUsIDB4YzAyMWI4ZjcsXG5cdDB4OWI1NDBiMTksIDB4ODc1ZmEwOTksIDB4OTVmNzk5N2UsIDB4NjIzZDdkYTgsIDB4ZjgzNzg4OWEsIDB4OTdlMzJkNzcsXG5cdDB4MTFlZDkzNWYsIDB4MTY2ODEyODEsIDB4MGUzNTg4MjksIDB4YzdlNjFmZDYsIDB4OTZkZWRmYTEsIDB4Nzg1OGJhOTksXG5cdDB4NTdmNTg0YTUsIDB4MWIyMjcyNjMsIDB4OWI4M2MzZmYsIDB4MWFjMjQ2OTYsIDB4Y2RiMzBhZWIsIDB4NTMyZTMwNTQsXG5cdDB4OGZkOTQ4ZTQsIDB4NmRiYzMxMjgsIDB4NThlYmYyZWYsIDB4MzRjNmZmZWEsIDB4ZmUyOGVkNjEsIDB4ZWU3YzNjNzMsXG5cdDB4NWQ0YTE0ZDksIDB4ZTg2NGI3ZTMsIDB4NDIxMDVkMTQsIDB4MjAzZTEzZTAsIDB4NDVlZWUyYjYsIDB4YTNhYWFiZWEsXG5cdDB4ZGI2YzRmMTUsIDB4ZmFjYjRmZDAsIDB4Yzc0MmY0NDIsIDB4ZWY2YWJiYjUsIDB4NjU0ZjNiMWQsIDB4NDFjZDIxMDUsXG5cdDB4ZDgxZTc5OWUsIDB4ODY4NTRkYzcsIDB4ZTQ0YjQ3NmEsIDB4M2Q4MTYyNTAsIDB4Y2Y2MmExZjIsIDB4NWI4ZDI2NDYsXG5cdDB4ZmM4ODgzYTAsIDB4YzFjN2I2YTMsIDB4N2YxNTI0YzMsIDB4NjljYjc0OTIsIDB4NDc4NDhhMGIsIDB4NTY5MmIyODUsXG5cdDB4MDk1YmJmMDAsIDB4YWQxOTQ4OWQsIDB4MTQ2MmIxNzQsIDB4MjM4MjBlMDAsIDB4NTg0MjhkMmEsIDB4MGM1NWY1ZWEsXG5cdDB4MWRhZGY0M2UsIDB4MjMzZjcwNjEsIDB4MzM3MmYwOTIsIDB4OGQ5MzdlNDEsIDB4ZDY1ZmVjZjEsIDB4NmMyMjNiZGIsXG5cdDB4N2NkZTM3NTksIDB4Y2JlZTc0NjAsIDB4NDA4NWYyYTcsIDB4Y2U3NzMyNmUsIDB4YTYwNzgwODQsIDB4MTlmODUwOWUsXG5cdDB4ZThlZmQ4NTUsIDB4NjFkOTk3MzUsIDB4YTk2OWE3YWEsIDB4YzUwYzA2YzIsIDB4NWEwNGFiZmMsIDB4ODAwYmNhZGMsXG5cdDB4OWU0NDdhMmUsIDB4YzM0NTM0ODQsIDB4ZmRkNTY3MDUsIDB4MGUxZTllYzksIDB4ZGI3M2RiZDMsIDB4MTA1NTg4Y2QsXG5cdDB4Njc1ZmRhNzksIDB4ZTM2NzQzNDAsIDB4YzVjNDM0NjUsIDB4NzEzZTM4ZDgsIDB4M2QyOGY4OWUsIDB4ZjE2ZGZmMjAsXG5cdDB4MTUzZTIxZTcsIDB4OGZiMDNkNGEsIDB4ZTZlMzlmMmIsIDB4ZGI4M2FkZjdcbiAgICBdLCBbXG5cdDB4ZTkzZDVhNjgsIDB4OTQ4MTQwZjcsIDB4ZjY0YzI2MWMsIDB4OTQ2OTI5MzQsIDB4NDExNTIwZjcsIDB4NzYwMmQ0ZjcsXG5cdDB4YmNmNDZiMmUsIDB4ZDRhMjAwNjgsIDB4ZDQwODI0NzEsIDB4MzMyMGY0NmEsIDB4NDNiN2Q0YjcsIDB4NTAwMDYxYWYsXG5cdDB4MWUzOWY2MmUsIDB4OTcyNDQ1NDYsIDB4MTQyMTRmNzQsIDB4YmY4Yjg4NDAsIDB4NGQ5NWZjMWQsIDB4OTZiNTkxYWYsXG5cdDB4NzBmNGRkZDMsIDB4NjZhMDJmNDUsIDB4YmZiYzA5ZWMsIDB4MDNiZDk3ODUsIDB4N2ZhYzZkZDAsIDB4MzFjYjg1MDQsXG5cdDB4OTZlYjI3YjMsIDB4NTVmZDM5NDEsIDB4ZGEyNTQ3ZTYsIDB4YWJjYTBhOWEsIDB4Mjg1MDc4MjUsIDB4NTMwNDI5ZjQsXG5cdDB4MGEyYzg2ZGEsIDB4ZTliNjZkZmIsIDB4NjhkYzE0NjIsIDB4ZDc0ODY5MDAsIDB4NjgwZWMwYTQsIDB4MjdhMThkZWUsXG5cdDB4NGYzZmZlYTIsIDB4ZTg4N2FkOGMsIDB4YjU4Y2UwMDYsIDB4N2FmNGQ2YjYsIDB4YWFjZTFlN2MsIDB4ZDMzNzVmZWMsXG5cdDB4Y2U3OGEzOTksIDB4NDA2YjJhNDIsIDB4MjBmZTllMzUsIDB4ZDlmMzg1YjksIDB4ZWUzOWQ3YWIsIDB4M2IxMjRlOGIsXG5cdDB4MWRjOWZhZjcsIDB4NGI2ZDE4NTYsIDB4MjZhMzY2MzEsIDB4ZWFlMzk3YjIsIDB4M2E2ZWZhNzQsIDB4ZGQ1YjQzMzIsXG5cdDB4Njg0MWU3ZjcsIDB4Y2E3ODIwZmIsIDB4ZmIwYWY1NGUsIDB4ZDhmZWIzOTcsIDB4NDU0MDU2YWMsIDB4YmE0ODk1MjcsXG5cdDB4NTU1MzNhM2EsIDB4MjA4MzhkODcsIDB4ZmU2YmE5YjcsIDB4ZDA5Njk1NGIsIDB4NTVhODY3YmMsIDB4YTExNTlhNTgsXG5cdDB4Y2NhOTI5NjMsIDB4OTllMWRiMzMsIDB4YTYyYTRhNTYsIDB4M2YzMTI1ZjksIDB4NWVmNDdlMWMsIDB4OTAyOTMxN2MsXG5cdDB4ZmRmOGU4MDIsIDB4MDQyNzJmNzAsIDB4ODBiYjE1NWMsIDB4MDUyODJjZTMsIDB4OTVjMTE1NDgsIDB4ZTRjNjZkMjIsXG5cdDB4NDhjMTEzM2YsIDB4YzcwZjg2ZGMsIDB4MDdmOWM5ZWUsIDB4NDEwNDFmMGYsIDB4NDA0Nzc5YTQsIDB4NWQ4ODZlMTcsXG5cdDB4MzI1ZjUxZWIsIDB4ZDU5YmMwZDEsIDB4ZjJiY2MxOGYsIDB4NDExMTM1NjQsIDB4MjU3Yjc4MzQsIDB4NjAyYTljNjAsXG5cdDB4ZGZmOGU4YTMsIDB4MWY2MzZjMWIsIDB4MGUxMmI0YzIsIDB4MDJlMTMyOWUsIDB4YWY2NjRmZDEsIDB4Y2FkMTgxMTUsXG5cdDB4NmIyMzk1ZTAsIDB4MzMzZTkyZTEsIDB4M2IyNDBiNjIsIDB4ZWViZWI5MjIsIDB4ODViMmEyMGUsIDB4ZTZiYTBkOTksXG5cdDB4ZGU3MjBjOGMsIDB4MmRhMmY3MjgsIDB4ZDAxMjc4NDUsIDB4OTViNzk0ZmQsIDB4NjQ3ZDA4NjIsIDB4ZTdjY2Y1ZjAsXG5cdDB4NTQ0OWEzNmYsIDB4ODc3ZDQ4ZmEsIDB4YzM5ZGZkMjcsIDB4ZjMzZThkMWUsIDB4MGE0NzYzNDEsIDB4OTkyZWZmNzQsXG5cdDB4M2E2ZjZlYWIsIDB4ZjRmOGZkMzcsIDB4YTgxMmRjNjAsIDB4YTFlYmRkZjgsIDB4OTkxYmUxNGMsIDB4ZGI2ZTZiMGQsXG5cdDB4YzY3YjU1MTAsIDB4NmQ2NzJjMzcsIDB4Mjc2NWQ0M2IsIDB4ZGNkMGU4MDQsIDB4ZjEyOTBkYzcsIDB4Y2MwMGZmYTMsXG5cdDB4YjUzOTBmOTIsIDB4NjkwZmVkMGIsIDB4NjY3YjlmZmIsIDB4Y2VkYjdkOWMsIDB4YTA5MWNmMGIsIDB4ZDkxNTVlYTMsXG5cdDB4YmIxMzJmODgsIDB4NTE1YmFkMjQsIDB4N2I5NDc5YmYsIDB4NzYzYmQ2ZWIsIDB4MzczOTJlYjMsIDB4Y2MxMTU5NzksXG5cdDB4ODAyNmUyOTcsIDB4ZjQyZTMxMmQsIDB4Njg0MmFkYTcsIDB4YzY2YTJiM2IsIDB4MTI3NTRjY2MsIDB4NzgyZWYxMWMsXG5cdDB4NmExMjQyMzcsIDB4Yjc5MjUxZTcsIDB4MDZhMWJiZTYsIDB4NGJmYjYzNTAsIDB4MWE2YjEwMTgsIDB4MTFjYWVkZmEsXG5cdDB4M2QyNWJkZDgsIDB4ZTJlMWMzYzksIDB4NDQ0MjE2NTksIDB4MGExMjEzODYsIDB4ZDkwY2VjNmUsIDB4ZDVhYmVhMmEsXG5cdDB4NjRhZjY3NGUsIDB4ZGE4NmE4NWYsIDB4YmViZmU5ODgsIDB4NjRlNGMzZmUsIDB4OWRiYzgwNTcsIDB4ZjBmN2MwODYsXG5cdDB4NjA3ODdiZjgsIDB4NjAwMzYwNGQsIDB4ZDFmZDgzNDYsIDB4ZjYzODFmYjAsIDB4Nzc0NWFlMDQsIDB4ZDczNmZjY2MsXG5cdDB4ODM0MjZiMzMsIDB4ZjAxZWFiNzEsIDB4YjA4MDQxODcsIDB4M2MwMDVlNWYsIDB4NzdhMDU3YmUsIDB4YmRlOGFlMjQsXG5cdDB4NTU0NjQyOTksIDB4YmY1ODJlNjEsIDB4NGU1OGY0OGYsIDB4ZjJkZGZkYTIsIDB4ZjQ3NGVmMzgsIDB4ODc4OWJkYzIsXG5cdDB4NTM2NmY5YzMsIDB4YzhiMzhlNzQsIDB4YjQ3NWYyNTUsIDB4NDZmY2Q5YjksIDB4N2FlYjI2NjEsIDB4OGIxZGRmODQsXG5cdDB4ODQ2YTBlNzksIDB4OTE1Zjk1ZTIsIDB4NDY2ZTU5OGUsIDB4MjBiNDU3NzAsIDB4OGNkNTU1OTEsIDB4YzkwMmRlNGMsXG5cdDB4YjkwYmFjZTEsIDB4YmI4MjA1ZDAsIDB4MTFhODYyNDgsIDB4NzU3NGE5OWUsIDB4Yjc3ZjE5YjYsIDB4ZTBhOWRjMDksXG5cdDB4NjYyZDA5YTEsIDB4YzQzMjQ2MzMsIDB4ZTg1YTFmMDIsIDB4MDlmMGJlOGMsIDB4NGE5OWEwMjUsIDB4MWQ2ZWZlMTAsXG5cdDB4MWFiOTNkMWQsIDB4MGJhNWE0ZGYsIDB4YTE4NmYyMGYsIDB4Mjg2OGYxNjksIDB4ZGNiN2RhODMsIDB4NTczOTA2ZmUsXG5cdDB4YTFlMmNlOWIsIDB4NGZjZDdmNTIsIDB4NTAxMTVlMDEsIDB4YTcwNjgzZmEsIDB4YTAwMmI1YzQsIDB4MGRlNmQwMjcsXG5cdDB4OWFmODhjMjcsIDB4NzczZjg2NDEsIDB4YzM2MDRjMDYsIDB4NjFhODA2YjUsIDB4ZjAxNzdhMjgsIDB4YzBmNTg2ZTAsXG5cdDB4MDA2MDU4YWEsIDB4MzBkYzdkNjIsIDB4MTFlNjllZDcsIDB4MjMzOGVhNjMsIDB4NTNjMmRkOTQsIDB4YzJjMjE2MzQsXG5cdDB4YmJjYmVlNTYsIDB4OTBiY2I2ZGUsIDB4ZWJmYzdkYTEsIDB4Y2U1OTFkNzYsIDB4NmYwNWU0MDksIDB4NGI3YzAxODgsXG5cdDB4Mzk3MjBhM2QsIDB4N2M5MjdjMjQsIDB4ODZlMzcyNWYsIDB4NzI0ZDlkYjksIDB4MWFjMTViYjQsIDB4ZDM5ZWI4ZmMsXG5cdDB4ZWQ1NDU1NzgsIDB4MDhmY2E1YjUsIDB4ZDgzZDdjZDMsIDB4NGRhZDBmYzQsIDB4MWU1MGVmNWUsIDB4YjE2MWU2ZjgsXG5cdDB4YTI4NTE0ZDksIDB4NmM1MTEzM2MsIDB4NmZkNWM3ZTcsIDB4NTZlMTRlYzQsIDB4MzYyYWJmY2UsIDB4ZGRjNmM4MzcsXG5cdDB4ZDc5YTMyMzQsIDB4OTI2MzgyMTIsIDB4NjcwZWZhOGUsIDB4NDA2MDAwZTBcbiAgICBdLCBbXG5cdDB4M2EzOWNlMzcsIDB4ZDNmYWY1Y2YsIDB4YWJjMjc3MzcsIDB4NWFjNTJkMWIsIDB4NWNiMDY3OWUsIDB4NGZhMzM3NDIsXG5cdDB4ZDM4MjI3NDAsIDB4OTliYzliYmUsIDB4ZDUxMThlOWQsIDB4YmYwZjczMTUsIDB4ZDYyZDFjN2UsIDB4YzcwMGM0N2IsXG5cdDB4Yjc4YzFiNmIsIDB4MjFhMTkwNDUsIDB4YjI2ZWIxYmUsIDB4NmEzNjZlYjQsIDB4NTc0OGFiMmYsIDB4YmM5NDZlNzksXG5cdDB4YzZhMzc2ZDIsIDB4NjU0OWMyYzgsIDB4NTMwZmY4ZWUsIDB4NDY4ZGRlN2QsIDB4ZDU3MzBhMWQsIDB4NGNkMDRkYzYsXG5cdDB4MjkzOWJiZGIsIDB4YTliYTQ2NTAsIDB4YWM5NTI2ZTgsIDB4YmU1ZWUzMDQsIDB4YTFmYWQ1ZjAsIDB4NmEyZDUxOWEsXG5cdDB4NjNlZjhjZTIsIDB4OWE4NmVlMjIsIDB4YzA4OWMyYjgsIDB4NDMyNDJlZjYsIDB4YTUxZTAzYWEsIDB4OWNmMmQwYTQsXG5cdDB4ODNjMDYxYmEsIDB4OWJlOTZhNGQsIDB4OGZlNTE1NTAsIDB4YmE2NDViZDYsIDB4MjgyNmEyZjksIDB4YTczYTNhZTEsXG5cdDB4NGJhOTk1ODYsIDB4ZWY1NTYyZTksIDB4YzcyZmVmZDMsIDB4Zjc1MmY3ZGEsIDB4M2YwNDZmNjksIDB4NzdmYTBhNTksXG5cdDB4ODBlNGE5MTUsIDB4ODdiMDg2MDEsIDB4OWIwOWU2YWQsIDB4M2IzZWU1OTMsIDB4ZTk5MGZkNWEsIDB4OWUzNGQ3OTcsXG5cdDB4MmNmMGI3ZDksIDB4MDIyYjhiNTEsIDB4OTZkNWFjM2EsIDB4MDE3ZGE2N2QsIDB4ZDFjZjNlZDYsIDB4N2M3ZDJkMjgsXG5cdDB4MWY5ZjI1Y2YsIDB4YWRmMmI4OWIsIDB4NWFkNmI0NzIsIDB4NWE4OGY1NGMsIDB4ZTAyOWFjNzEsIDB4ZTAxOWE1ZTYsXG5cdDB4NDdiMGFjZmQsIDB4ZWQ5M2ZhOWIsIDB4ZThkM2M0OGQsIDB4MjgzYjU3Y2MsIDB4ZjhkNTY2MjksIDB4NzkxMzJlMjgsXG5cdDB4Nzg1ZjAxOTEsIDB4ZWQ3NTYwNTUsIDB4Zjc5NjBlNDQsIDB4ZTNkMzVlOGMsIDB4MTUwNTZkZDQsIDB4ODhmNDZkYmEsXG5cdDB4MDNhMTYxMjUsIDB4MDU2NGYwYmQsIDB4YzNlYjllMTUsIDB4M2M5MDU3YTIsIDB4OTcyNzFhZWMsIDB4YTkzYTA3MmEsXG5cdDB4MWIzZjZkOWIsIDB4MWU2MzIxZjUsIDB4ZjU5YzY2ZmIsIDB4MjZkY2YzMTksIDB4NzUzM2Q5MjgsIDB4YjE1NWZkZjUsXG5cdDB4MDM1NjM0ODIsIDB4OGFiYTNjYmIsIDB4Mjg1MTc3MTEsIDB4YzIwYWQ5ZjgsIDB4YWJjYzUxNjcsIDB4Y2NhZDkyNWYsXG5cdDB4NGRlODE3NTEsIDB4MzgzMGRjOGUsIDB4Mzc5ZDU4NjIsIDB4OTMyMGY5OTEsIDB4ZWE3YTkwYzIsIDB4ZmIzZTdiY2UsXG5cdDB4NTEyMWNlNjQsIDB4Nzc0ZmJlMzIsIDB4YThiNmUzN2UsIDB4YzMyOTNkNDYsIDB4NDhkZTUzNjksIDB4NjQxM2U2ODAsXG5cdDB4YTJhZTA4MTAsIDB4ZGQ2ZGIyMjQsIDB4Njk4NTJkZmQsIDB4MDkwNzIxNjYsIDB4YjM5YTQ2MGEsIDB4NjQ0NWMwZGQsXG5cdDB4NTg2Y2RlY2YsIDB4MWMyMGM4YWUsIDB4NWJiZWY3ZGQsIDB4MWI1ODhkNDAsIDB4Y2NkMjAxN2YsIDB4NmJiNGUzYmIsXG5cdDB4ZGRhMjZhN2UsIDB4M2E1OWZmNDUsIDB4M2UzNTBhNDQsIDB4YmNiNGNkZDUsIDB4NzJlYWNlYTgsIDB4ZmE2NDg0YmIsXG5cdDB4OGQ2NjEyYWUsIDB4YmYzYzZmNDcsIDB4ZDI5YmU0NjMsIDB4NTQyZjVkOWUsIDB4YWVjMjc3MWIsIDB4ZjY0ZTYzNzAsXG5cdDB4NzQwZTBkOGQsIDB4ZTc1YjEzNTcsIDB4Zjg3MjE2NzEsIDB4YWY1MzdkNWQsIDB4NDA0MGNiMDgsIDB4NGViNGUyY2MsXG5cdDB4MzRkMjQ2NmEsIDB4MDExNWFmODQsIDB4ZTFiMDA0MjgsIDB4OTU5ODNhMWQsIDB4MDZiODlmYjQsIDB4Y2U2ZWEwNDgsXG5cdDB4NmYzZjNiODIsIDB4MzUyMGFiODIsIDB4MDExYTFkNGIsIDB4Mjc3MjI3ZjgsIDB4NjExNTYwYjEsIDB4ZTc5MzNmZGMsXG5cdDB4YmIzYTc5MmIsIDB4MzQ0NTI1YmQsIDB4YTA4ODM5ZTEsIDB4NTFjZTc5NGIsIDB4MmYzMmM5YjcsIDB4YTAxZmJhYzksXG5cdDB4ZTAxY2M4N2UsIDB4YmNjN2QxZjYsIDB4Y2YwMTExYzMsIDB4YTFlOGFhYzcsIDB4MWE5MDg3NDksIDB4ZDQ0ZmJkOWEsXG5cdDB4ZDBkYWRlY2IsIDB4ZDUwYWRhMzgsIDB4MDMzOWMzMmEsIDB4YzY5MTM2NjcsIDB4OGRmOTMxN2MsIDB4ZTBiMTJiNGYsXG5cdDB4Zjc5ZTU5YjcsIDB4NDNmNWJiM2EsIDB4ZjJkNTE5ZmYsIDB4MjdkOTQ1OWMsIDB4YmY5NzIyMmMsIDB4MTVlNmZjMmEsXG5cdDB4MGY5MWZjNzEsIDB4OWI5NDE1MjUsIDB4ZmFlNTkzNjEsIDB4Y2ViNjljZWIsIDB4YzJhODY0NTksIDB4MTJiYWE4ZDEsXG5cdDB4YjZjMTA3NWUsIDB4ZTMwNTZhMGMsIDB4MTBkMjUwNjUsIDB4Y2IwM2E0NDIsIDB4ZTBlYzZlMGUsIDB4MTY5OGRiM2IsXG5cdDB4NGM5OGEwYmUsIDB4MzI3OGU5NjQsIDB4OWYxZjk1MzIsIDB4ZTBkMzkyZGYsIDB4ZDNhMDM0MmIsIDB4ODk3MWYyMWUsXG5cdDB4MWIwYTc0NDEsIDB4NGJhMzM0OGMsIDB4YzViZTcxMjAsIDB4YzM3NjMyZDgsIDB4ZGYzNTlmOGQsIDB4OWI5OTJmMmUsXG5cdDB4ZTYwYjZmNDcsIDB4MGZlM2YxMWQsIDB4ZTU0Y2RhNTQsIDB4MWVkYWQ4OTEsIDB4Y2U2Mjc5Y2YsIDB4Y2QzZTdlNmYsXG5cdDB4MTYxOGIxNjYsIDB4ZmQyYzFkMDUsIDB4ODQ4ZmQyYzUsIDB4ZjZmYjIyOTksIDB4ZjUyM2YzNTcsIDB4YTYzMjc2MjMsXG5cdDB4OTNhODM1MzEsIDB4NTZjY2NkMDIsIDB4YWNmMDgxNjIsIDB4NWE3NWViYjUsIDB4NmUxNjM2OTcsIDB4ODhkMjczY2MsXG5cdDB4ZGU5NjYyOTIsIDB4ODFiOTQ5ZDAsIDB4NGM1MDkwMWIsIDB4NzFjNjU2MTQsIDB4ZTZjNmM3YmQsIDB4MzI3YTE0MGEsXG5cdDB4NDVlMWQwMDYsIDB4YzNmMjdiOWEsIDB4YzlhYTUzZmQsIDB4NjJhODBmMDAsIDB4YmIyNWJmZTIsIDB4MzViZGQyZjYsXG5cdDB4NzExMjY5MDUsIDB4YjIwNDAyMjIsIDB4YjZjYmNmN2MsIDB4Y2Q3NjljMmIsIDB4NTMxMTNlYzAsIDB4MTY0MGUzZDMsXG5cdDB4MzhhYmJkNjAsIDB4MjU0N2FkZjAsIDB4YmEzODIwOWMsIDB4Zjc0NmNlNzYsIDB4NzdhZmExYzUsIDB4MjA3NTYwNjAsXG5cdDB4ODVjYmZlNGUsIDB4OGFlODhkZDgsIDB4N2FhYWY5YjAsIDB4NGNmOWFhN2UsIDB4MTk0OGMyNWMsIDB4MDJmYjhhOGMsXG5cdDB4MDFjMzZhZTQsIDB4ZDZlYmUxZjksIDB4OTBkNGY4NjksIDB4YTY1Y2RlYTAsIDB4M2YwOTI1MmQsIDB4YzIwOGU2OWYsXG5cdDB4Yjc0ZTYxMzIsIDB4Y2U3N2UyNWIsIDB4NTc4ZmRmZTMsIDB4M2FjMzcyZTZcbiAgICBdXG5dO1xuXG4vLypcbi8vKiBUaGlzIGlzIHRoZSBkZWZhdWx0IFBBUlJBWVxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuUEFSUkFZID0gW1xuICAgIDB4MjQzZjZhODgsIDB4ODVhMzA4ZDMsIDB4MTMxOThhMmUsIDB4MDM3MDczNDQsIDB4YTQwOTM4MjIsIDB4Mjk5ZjMxZDAsXG4gICAgMHgwODJlZmE5OCwgMHhlYzRlNmM4OSwgMHg0NTI4MjFlNiwgMHgzOGQwMTM3NywgMHhiZTU0NjZjZiwgMHgzNGU5MGM2YyxcbiAgICAweGMwYWMyOWI3LCAweGM5N2M1MGRkLCAweDNmODRkNWI1LCAweGI1NDcwOTE3LCAweDkyMTZkNWQ5LCAweDg5NzlmYjFiXG5dO1xuXG4vLypcbi8vKiBUaGlzIGlzIHRoZSBudW1iZXIgb2Ygcm91bmRzIHRoZSBjaXBoZXIgd2lsbCBnb1xuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuTk4gPSAxNjtcblxuLy8qXG4vLyogVGhpcyBmdW5jdGlvbiBpcyBuZWVkZWQgdG8gZ2V0IHJpZCBvZiBwcm9ibGVtc1xuLy8qIHdpdGggdGhlIGhpZ2gtYml0IGdldHRpbmcgc2V0LiAgSWYgd2UgZG9uJ3QgZG9cbi8vKiB0aGlzLCB0aGVuIHNvbWV0aW1lcyAoIGFhICYgMHgwMEZGRkZGRkZGICkgaXMgbm90XG4vLyogZXF1YWwgdG8gKCBiYiAmIDB4MDBGRkZGRkZGRiApIGV2ZW4gd2hlbiB0aGV5XG4vLyogYWdyZWUgYml0LWZvci1iaXQgZm9yIHRoZSBmaXJzdCAzMiBiaXRzLlxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuX2NsZWFuID0gZnVuY3Rpb24oIHh4ICkge1xuICAgIGlmICggeHggPCAwICkge1xuXHR2YXIgeXkgPSB4eCAmIDB4N0ZGRkZGRkY7XG5cdHh4ID0geXkgKyAweDgwMDAwMDAwO1xuICAgIH1cbiAgICByZXR1cm4geHg7XG59O1xuXG4vLypcbi8vKiBUaGlzIGlzIHRoZSBtaXhpbmcgZnVuY3Rpb24gdGhhdCB1c2VzIHRoZSBzYm94ZXNcbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLl9GID0gZnVuY3Rpb24gKCB4eCApIHtcbiAgICB2YXIgYWE7XG4gICAgdmFyIGJiO1xuICAgIHZhciBjYztcbiAgICB2YXIgZGQ7XG4gICAgdmFyIHl5O1xuXG4gICAgZGQgPSB4eCAmIDB4MDBGRjtcbiAgICB4eCA+Pj49IDg7XG4gICAgY2MgPSB4eCAmIDB4MDBGRjtcbiAgICB4eCA+Pj49IDg7XG4gICAgYmIgPSB4eCAmIDB4MDBGRjtcbiAgICB4eCA+Pj49IDg7XG4gICAgYWEgPSB4eCAmIDB4MDBGRjtcblxuICAgIHl5ID0gdGhpcy5zYm94ZXNbIDAgXVsgYWEgXSArIHRoaXMuc2JveGVzWyAxIF1bIGJiIF07XG4gICAgeXkgPSB5eSBeIHRoaXMuc2JveGVzWyAyIF1bIGNjIF07XG4gICAgeXkgPSB5eSArIHRoaXMuc2JveGVzWyAzIF1bIGRkIF07XG5cbiAgICByZXR1cm4geXk7XG59O1xuXG4vLypcbi8vKiBUaGlzIG1ldGhvZCB0YWtlcyBhbiBhcnJheSB3aXRoIHR3byB2YWx1ZXMsIGxlZnQgYW5kIHJpZ2h0XG4vLyogYW5kIGRvZXMgTk4gcm91bmRzIG9mIEJsb3dmaXNoIG9uIHRoZW0uXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5fZW5jcnlwdF9ibG9jayA9IGZ1bmN0aW9uICggdmFscyApIHtcbiAgICB2YXIgZGF0YUwgPSB2YWxzWyAwIF07XG4gICAgdmFyIGRhdGFSID0gdmFsc1sgMSBdO1xuXG4gICAgdmFyIGlpO1xuXG4gICAgZm9yICggaWk9MDsgaWkgPCB0aGlzLk5OOyArK2lpICkge1xuXHRkYXRhTCA9IGRhdGFMIF4gdGhpcy5wYXJyYXlbIGlpIF07XG5cdGRhdGFSID0gdGhpcy5fRiggZGF0YUwgKSBeIGRhdGFSO1xuXG5cdHZhciB0bXAgPSBkYXRhTDtcblx0ZGF0YUwgPSBkYXRhUjtcblx0ZGF0YVIgPSB0bXA7XG4gICAgfVxuXG4gICAgZGF0YUwgPSBkYXRhTCBeIHRoaXMucGFycmF5WyB0aGlzLk5OICsgMCBdO1xuICAgIGRhdGFSID0gZGF0YVIgXiB0aGlzLnBhcnJheVsgdGhpcy5OTiArIDEgXTtcblxuICAgIHZhbHNbIDAgXSA9IHRoaXMuX2NsZWFuKCBkYXRhUiApO1xuICAgIHZhbHNbIDEgXSA9IHRoaXMuX2NsZWFuKCBkYXRhTCApO1xufTtcblxuLy8qXG4vLyogVGhpcyBtZXRob2QgdGFrZXMgYSB2ZWN0b3Igb2YgbnVtYmVycyBhbmQgdHVybnMgdGhlbVxuLy8qIGludG8gbG9uZyB3b3JkcyBzbyB0aGF0IHRoZXkgY2FuIGJlIHByb2Nlc3NlZCBieSB0aGVcbi8vKiByZWFsIGFsZ29yaXRobS5cbi8vKlxuLy8qIE1heWJlIEkgc2hvdWxkIG1ha2UgdGhlIHJlYWwgYWxnb3JpdGhtIGFib3ZlIHRha2UgYSB2ZWN0b3Jcbi8vKiBpbnN0ZWFkLiAgVGhhdCB3aWxsIGludm9sdmUgbW9yZSBsb29waW5nLCBidXQgaXQgd29uJ3QgcmVxdWlyZVxuLy8qIHRoZSBGKCkgbWV0aG9kIHRvIGRlY29uc3RydWN0IHRoZSB2ZWN0b3IuXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5lbmNyeXB0X2Jsb2NrID0gZnVuY3Rpb24gKCB2ZWN0b3IgKSB7XG4gICAgdmFyIGlpO1xuICAgIHZhciB2YWxzID0gWyAwLCAwIF07XG4gICAgdmFyIG9mZiAgPSB0aGlzLkJMT0NLU0laRS8yO1xuICAgIGZvciAoIGlpID0gMDsgaWkgPCB0aGlzLkJMT0NLU0laRS8yOyArK2lpICkge1xuXHR2YWxzWzBdID0gKCB2YWxzWzBdIDw8IDggKSB8ICggdmVjdG9yWyBpaSArIDAgICBdICYgMHgwMEZGICk7XG5cdHZhbHNbMV0gPSAoIHZhbHNbMV0gPDwgOCApIHwgKCB2ZWN0b3JbIGlpICsgb2ZmIF0gJiAweDAwRkYgKTtcbiAgICB9XG5cbiAgICB0aGlzLl9lbmNyeXB0X2Jsb2NrKCB2YWxzICk7XG5cbiAgICB2YXIgcmV0ID0gWyBdO1xuICAgIGZvciAoIGlpID0gMDsgaWkgPCB0aGlzLkJMT0NLU0laRS8yOyArK2lpICkge1xuXHRyZXRbIGlpICsgMCAgIF0gPSAoIHZhbHNbIDAgXSA+Pj4gKDI0IC0gOCooaWkpKSAmIDB4MDBGRiApO1xuXHRyZXRbIGlpICsgb2ZmIF0gPSAoIHZhbHNbIDEgXSA+Pj4gKDI0IC0gOCooaWkpKSAmIDB4MDBGRiApO1xuXHQvLyB2YWxzWyAwIF0gPSAoIHZhbHNbIDAgXSA+Pj4gOCApO1xuXHQvLyB2YWxzWyAxIF0gPSAoIHZhbHNbIDEgXSA+Pj4gOCApO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG59O1xuXG4vLypcbi8vKiBUaGlzIG1ldGhvZCB0YWtlcyBhbiBhcnJheSB3aXRoIHR3byB2YWx1ZXMsIGxlZnQgYW5kIHJpZ2h0XG4vLyogYW5kIHVuZG9lcyBOTiByb3VuZHMgb2YgQmxvd2Zpc2ggb24gdGhlbS5cbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLl9kZWNyeXB0X2Jsb2NrID0gZnVuY3Rpb24gKCB2YWxzICkge1xuICAgIHZhciBkYXRhTCA9IHZhbHNbIDAgXTtcbiAgICB2YXIgZGF0YVIgPSB2YWxzWyAxIF07XG5cbiAgICB2YXIgaWk7XG5cbiAgICBmb3IgKCBpaT10aGlzLk5OKzE7IGlpID4gMTsgLS1paSApIHtcblx0ZGF0YUwgPSBkYXRhTCBeIHRoaXMucGFycmF5WyBpaSBdO1xuXHRkYXRhUiA9IHRoaXMuX0YoIGRhdGFMICkgXiBkYXRhUjtcblxuXHR2YXIgdG1wID0gZGF0YUw7XG5cdGRhdGFMID0gZGF0YVI7XG5cdGRhdGFSID0gdG1wO1xuICAgIH1cblxuICAgIGRhdGFMID0gZGF0YUwgXiB0aGlzLnBhcnJheVsgMSBdO1xuICAgIGRhdGFSID0gZGF0YVIgXiB0aGlzLnBhcnJheVsgMCBdO1xuXG4gICAgdmFsc1sgMCBdID0gdGhpcy5fY2xlYW4oIGRhdGFSICk7XG4gICAgdmFsc1sgMSBdID0gdGhpcy5fY2xlYW4oIGRhdGFMICk7XG59O1xuXG4vLypcbi8vKiBUaGlzIG1ldGhvZCB0YWtlcyBhIGtleSBhcnJheSBhbmQgaW5pdGlhbGl6ZXMgdGhlXG4vLyogc2JveGVzIGFuZCBwYXJyYXkgZm9yIHRoaXMgZW5jcnlwdGlvbi5cbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoIGtleSApIHtcbiAgICB2YXIgaWk7XG4gICAgdmFyIGpqID0gMDtcblxuICAgIHRoaXMucGFycmF5ID0gW107XG4gICAgZm9yICggaWk9MDsgaWkgPCB0aGlzLk5OICsgMjsgKytpaSApIHtcblx0dmFyIGRhdGEgPSAweDAwMDAwMDAwO1xuXHR2YXIga2s7XG5cdGZvciAoIGtrPTA7IGtrIDwgNDsgKytrayApIHtcblx0ICAgIGRhdGEgPSAoIGRhdGEgPDwgOCApIHwgKCBrZXlbIGpqIF0gJiAweDAwRkYgKTtcblx0ICAgIGlmICggKytqaiA+PSBrZXkubGVuZ3RoICkge1xuXHRcdGpqID0gMDtcblx0ICAgIH1cblx0fVxuXHR0aGlzLnBhcnJheVsgaWkgXSA9IHRoaXMuUEFSUkFZWyBpaSBdIF4gZGF0YTtcbiAgICB9XG5cbiAgICB0aGlzLnNib3hlcyA9IFtdO1xuICAgIGZvciAoIGlpPTA7IGlpIDwgNDsgKytpaSApIHtcblx0dGhpcy5zYm94ZXNbIGlpIF0gPSBbXTtcblx0Zm9yICggamo9MDsgamogPCAyNTY7ICsramogKSB7XG5cdCAgICB0aGlzLnNib3hlc1sgaWkgXVsgamogXSA9IHRoaXMuU0JPWEVTWyBpaSBdWyBqaiBdO1xuXHR9XG4gICAgfVxuXG4gICAgdmFyIHZhbHMgPSBbIDB4MDAwMDAwMDAsIDB4MDAwMDAwMDAgXTtcblxuICAgIGZvciAoIGlpPTA7IGlpIDwgdGhpcy5OTisyOyBpaSArPSAyICkge1xuXHR0aGlzLl9lbmNyeXB0X2Jsb2NrKCB2YWxzICk7XG5cdHRoaXMucGFycmF5WyBpaSArIDAgXSA9IHZhbHNbIDAgXTtcblx0dGhpcy5wYXJyYXlbIGlpICsgMSBdID0gdmFsc1sgMSBdO1xuICAgIH1cblxuICAgIGZvciAoIGlpPTA7IGlpIDwgNDsgKytpaSApIHtcblx0Zm9yICggamo9MDsgamogPCAyNTY7IGpqICs9IDIgKSB7XG5cdCAgICB0aGlzLl9lbmNyeXB0X2Jsb2NrKCB2YWxzICk7XG5cdCAgICB0aGlzLnNib3hlc1sgaWkgXVsgamogKyAwIF0gPSB2YWxzWyAwIF07XG5cdCAgICB0aGlzLnNib3hlc1sgaWkgXVsgamogKyAxIF0gPSB2YWxzWyAxIF07XG5cdH1cbiAgICB9XG59O1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuZnVuY3Rpb24gQkZlbmNyeXB0KGJsb2NrLGtleSkge1xuXHR2YXIgYmYgPSBuZXcgQmxvd2Zpc2goKTtcblx0YmYuaW5pdCh1dGlsLnN0cjJiaW4oa2V5KSk7XG5cdHJldHVybiBiZi5lbmNyeXB0X2Jsb2NrKGJsb2NrKTtcbn1cblxuZnVuY3Rpb24gQkYoa2V5KSB7XG5cdHRoaXMuYmYgPSBuZXcgQmxvd2Zpc2goKTtcblx0dGhpcy5iZi5pbml0KHV0aWwuc3RyMmJpbihrZXkpKTtcblxuXHR0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihibG9jaykge1xuXHRcdHJldHVybiB0aGlzLmJmLmVuY3J5cHRfYmxvY2soYmxvY2spO1xuXHR9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBCRjtcbm1vZHVsZS5leHBvcnRzLmtleVNpemUgPSBCRi5wcm90b3R5cGUua2V5U2l6ZSA9IDE2O1xubW9kdWxlLmV4cG9ydHMuYmxvY2tTaXplID0gQkYucHJvdG90eXBlLmJsb2NrU2l6ZSA9IDE2O1xuXG5cbiIsIlxyXG4vLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZVxyXG4vLyBsaWNlbnNlIHRoYXQgY2FuIGJlIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUuXHJcblxyXG4vLyBDb3B5cmlnaHQgMjAxMCBwamFjb2JzQHhlZWtyLmNvbSAuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXHJcblxyXG4vLyBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkhcclxuXHJcbi8vIGZpeGVkL21vZGlmaWVkIGJ5IEhlcmJlcnQgSGFuZXdpbmtlbCwgd3d3LmhhbmVXSU4uZGVcclxuLy8gY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxyXG5cclxuLy8gY2FzdDUuanMgaXMgYSBKYXZhc2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIENBU1QtMTI4LCBhcyBkZWZpbmVkIGluIFJGQyAyMTQ0LlxyXG4vLyBDQVNULTEyOCBpcyBhIGNvbW1vbiBPcGVuUEdQIGNpcGhlci5cclxuXHJcblxyXG4vLyBDQVNUNSBjb25zdHJ1Y3RvclxyXG5cclxuXHJcblxyXG5mdW5jdGlvbiBvcGVucGdwX3N5bWVuY19jYXN0NSgpIHtcclxuXHR0aGlzLkJsb2NrU2l6ZT0gODtcclxuXHR0aGlzLktleVNpemUgPSAxNjtcclxuXHJcblx0dGhpcy5zZXRLZXkgPSBmdW5jdGlvbiAoa2V5KSB7XHJcblx0XHQgdGhpcy5tYXNraW5nID0gbmV3IEFycmF5KDE2KTtcclxuXHRcdCB0aGlzLnJvdGF0ZSA9IG5ldyBBcnJheSgxNik7XHJcblxyXG5cdFx0IHRoaXMucmVzZXQoKTtcclxuXHJcblx0XHQgaWYgKGtleS5sZW5ndGggPT0gdGhpcy5LZXlTaXplKVxyXG5cdFx0IHtcclxuXHRcdCAgIHRoaXMua2V5U2NoZWR1bGUoa2V5KTtcclxuXHRcdCB9XHJcblx0XHQgZWxzZVxyXG5cdFx0IHtcclxuXHRcdCAgIHV0aWwucHJpbnRfZXJyb3IoJ2Nhc3Q1LmpzOiBDQVNULTEyODoga2V5cyBtdXN0IGJlIDE2IGJ5dGVzJyk7XHJcblx0XHQgICByZXR1cm4gZmFsc2U7XHJcblx0XHQgfVxyXG5cdFx0IHJldHVybiB0cnVlO1xyXG5cdH07XHJcblx0XHJcblx0dGhpcy5yZXNldCA9IGZ1bmN0aW9uKCkge1xyXG5cdFx0IGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKylcclxuXHRcdCB7XHJcblx0XHQgIHRoaXMubWFza2luZ1tpXSA9IDA7XHJcblx0XHQgIHRoaXMucm90YXRlW2ldID0gMDtcclxuXHRcdCB9XHJcblx0fTtcclxuXHJcblx0dGhpcy5nZXRCbG9ja1NpemUgPSBmdW5jdGlvbigpIHtcclxuXHRcdCByZXR1cm4gQmxvY2tTaXplO1xyXG5cdH07XHJcblxyXG5cdHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKHNyYykge1xyXG5cdFx0IHZhciBkc3QgPSBuZXcgQXJyYXkoc3JjLmxlbmd0aCk7XHJcblxyXG5cdFx0IGZvcih2YXIgaSA9IDA7IGkgPCBzcmMubGVuZ3RoOyBpKz04KVxyXG5cdFx0IHtcclxuXHRcdCAgdmFyIGwgPSBzcmNbaV08PDI0IHwgc3JjW2krMV08PDE2IHwgc3JjW2krMl08PDggfCBzcmNbaSszXTtcclxuXHRcdCAgdmFyIHIgPSBzcmNbaSs0XTw8MjQgfCBzcmNbaSs1XTw8MTYgfCBzcmNbaSs2XTw8OCB8IHNyY1tpKzddO1xyXG5cdFx0ICB2YXIgdDtcclxuXHJcblx0XHQgIHQgPSByOyByID0gbF5mMShyLCB0aGlzLm1hc2tpbmdbMF0sIHRoaXMucm90YXRlWzBdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMihyLCB0aGlzLm1hc2tpbmdbMV0sIHRoaXMucm90YXRlWzFdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMyhyLCB0aGlzLm1hc2tpbmdbMl0sIHRoaXMucm90YXRlWzJdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMShyLCB0aGlzLm1hc2tpbmdbM10sIHRoaXMucm90YXRlWzNdKTsgbCA9IHQ7XHJcblxyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjIociwgdGhpcy5tYXNraW5nWzRdLCB0aGlzLnJvdGF0ZVs0XSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjMociwgdGhpcy5tYXNraW5nWzVdLCB0aGlzLnJvdGF0ZVs1XSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzZdLCB0aGlzLnJvdGF0ZVs2XSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjIociwgdGhpcy5tYXNraW5nWzddLCB0aGlzLnJvdGF0ZVs3XSk7IGwgPSB0O1xyXG5cclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYzKHIsIHRoaXMubWFza2luZ1s4XSwgdGhpcy5yb3RhdGVbOF0pOyBsID0gdDtcclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYxKHIsIHRoaXMubWFza2luZ1s5XSwgdGhpcy5yb3RhdGVbOV0pOyBsID0gdDtcclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYyKHIsIHRoaXMubWFza2luZ1sxMF0sIHRoaXMucm90YXRlWzEwXSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjMociwgdGhpcy5tYXNraW5nWzExXSwgdGhpcy5yb3RhdGVbMTFdKTsgbCA9IHQ7XHJcblxyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzEyXSwgdGhpcy5yb3RhdGVbMTJdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMihyLCB0aGlzLm1hc2tpbmdbMTNdLCB0aGlzLnJvdGF0ZVsxM10pOyBsID0gdDtcclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYzKHIsIHRoaXMubWFza2luZ1sxNF0sIHRoaXMucm90YXRlWzE0XSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzE1XSwgdGhpcy5yb3RhdGVbMTVdKTsgbCA9IHQ7XHJcblxyXG5cdFx0ICBkc3RbaV0gICA9IChyID4+PiAyNCkmMjU1O1xyXG5cdFx0ICBkc3RbaSsxXSA9IChyID4+PiAxNikmMjU1O1xyXG5cdFx0ICBkc3RbaSsyXSA9IChyID4+PiA4KSYyNTU7XHJcblx0XHQgIGRzdFtpKzNdID0gciYyNTU7XHJcblx0XHQgIGRzdFtpKzRdID0gKGwgPj4+IDI0KSYyNTU7XHJcblx0XHQgIGRzdFtpKzVdID0gKGwgPj4+IDE2KSYyNTU7XHJcblx0XHQgIGRzdFtpKzZdID0gKGwgPj4+IDgpJjI1NTtcclxuXHRcdCAgZHN0W2krN10gPSBsJjI1NTtcclxuXHRcdCB9XHJcblxyXG5cdFx0IHJldHVybiBkc3Q7XHJcblx0fTtcclxuXHRcclxuXHR0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihzcmMpIHtcclxuXHRcdCB2YXIgZHN0ID0gbmV3IEFycmF5KHNyYy5sZW5ndGgpO1xyXG5cclxuXHRcdCBmb3IodmFyIGkgPSAwOyBpIDwgc3JjLmxlbmd0aDsgaSs9OClcclxuXHRcdCB7XHJcblx0XHQgIHZhciBsID0gc3JjW2ldPDwyNCB8IHNyY1tpKzFdPDwxNiB8IHNyY1tpKzJdPDw4IHwgc3JjW2krM107XHJcblx0XHQgIHZhciByID0gc3JjW2krNF08PDI0IHwgc3JjW2krNV08PDE2IHwgc3JjW2krNl08PDggfCBzcmNbaSs3XTtcclxuXHRcdCAgdmFyIHQ7XHJcblxyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzE1XSwgdGhpcy5yb3RhdGVbMTVdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMyhyLCB0aGlzLm1hc2tpbmdbMTRdLCB0aGlzLnJvdGF0ZVsxNF0pOyBsID0gdDtcclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYyKHIsIHRoaXMubWFza2luZ1sxM10sIHRoaXMucm90YXRlWzEzXSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzEyXSwgdGhpcy5yb3RhdGVbMTJdKTsgbCA9IHQ7XHJcblxyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjMociwgdGhpcy5tYXNraW5nWzExXSwgdGhpcy5yb3RhdGVbMTFdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMihyLCB0aGlzLm1hc2tpbmdbMTBdLCB0aGlzLnJvdGF0ZVsxMF0pOyBsID0gdDtcclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYxKHIsIHRoaXMubWFza2luZ1s5XSwgdGhpcy5yb3RhdGVbOV0pOyBsID0gdDtcclxuXHRcdCAgdCA9IHI7IHIgPSBsXmYzKHIsIHRoaXMubWFza2luZ1s4XSwgdGhpcy5yb3RhdGVbOF0pOyBsID0gdDtcclxuXHJcblx0XHQgIHQgPSByOyByID0gbF5mMihyLCB0aGlzLm1hc2tpbmdbN10sIHRoaXMucm90YXRlWzddKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMShyLCB0aGlzLm1hc2tpbmdbNl0sIHRoaXMucm90YXRlWzZdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMyhyLCB0aGlzLm1hc2tpbmdbNV0sIHRoaXMucm90YXRlWzVdKTsgbCA9IHQ7XHJcblx0XHQgIHQgPSByOyByID0gbF5mMihyLCB0aGlzLm1hc2tpbmdbNF0sIHRoaXMucm90YXRlWzRdKTsgbCA9IHQ7XHJcblxyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzNdLCB0aGlzLnJvdGF0ZVszXSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjMociwgdGhpcy5tYXNraW5nWzJdLCB0aGlzLnJvdGF0ZVsyXSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjIociwgdGhpcy5tYXNraW5nWzFdLCB0aGlzLnJvdGF0ZVsxXSk7IGwgPSB0O1xyXG5cdFx0ICB0ID0gcjsgciA9IGxeZjEociwgdGhpcy5tYXNraW5nWzBdLCB0aGlzLnJvdGF0ZVswXSk7IGwgPSB0O1xyXG5cclxuXHRcdCAgZHN0W2ldICAgPSAociA+Pj4gMjQpJjI1NTtcclxuXHRcdCAgZHN0W2krMV0gPSAociA+Pj4gMTYpJjI1NTtcclxuXHRcdCAgZHN0W2krMl0gPSAociA+Pj4gOCkmMjU1O1xyXG5cdFx0ICBkc3RbaSszXSA9IHImMjU1O1xyXG5cdFx0ICBkc3RbaSs0XSA9IChsID4+PiAyNCkmMjU1O1xyXG5cdFx0ICBkc3RbaSs1XSA9IChsID4+IDE2KSYyNTU7XHJcblx0XHQgIGRzdFtpKzZdID0gKGwgPj4gOCkmMjU1O1xyXG5cdFx0ICBkc3RbaSs3XSA9IGwmMjU1O1xyXG5cdFx0IH1cclxuXHJcblx0XHQgcmV0dXJuIGRzdDtcclxuXHRcdH07XHJcblx0XHR2YXIgc2NoZWR1bGVBID0gbmV3IEFycmF5KDQpO1xyXG5cclxuXHRcdHNjaGVkdWxlQVswXSA9IG5ldyBBcnJheSg0KTtcclxuXHRcdHNjaGVkdWxlQVswXVswXSA9IG5ldyBBcnJheSg0LCAwLCAweGQsIDB4ZiwgMHhjLCAweGUsIDB4OCk7XHJcblx0XHRzY2hlZHVsZUFbMF1bMV0gPSBuZXcgQXJyYXkoNSwgMiwgMTYgKyAwLCAxNiArIDIsIDE2ICsgMSwgMTYgKyAzLCAweGEpO1xyXG5cdFx0c2NoZWR1bGVBWzBdWzJdID0gbmV3IEFycmF5KDYsIDMsIDE2ICsgNywgMTYgKyA2LCAxNiArIDUsIDE2ICsgNCwgOSk7XHJcblx0XHRzY2hlZHVsZUFbMF1bM10gPSBuZXcgQXJyYXkoNywgMSwgMTYgKyAweGEsIDE2ICsgOSwgMTYgKyAweGIsIDE2ICsgOCwgMHhiKTtcclxuXHJcblx0XHRzY2hlZHVsZUFbMV0gPSBuZXcgQXJyYXkoNCk7XHJcblx0XHRzY2hlZHVsZUFbMV1bMF0gPSBuZXcgQXJyYXkoMCwgNiwgMTYgKyA1LCAxNiArIDcsIDE2ICsgNCwgMTYgKyA2LCAxNiArIDApO1xyXG5cdFx0c2NoZWR1bGVBWzFdWzFdID0gbmV3IEFycmF5KDEsIDQsIDAsIDIsIDEsIDMsIDE2ICsgMik7XHJcblx0XHRzY2hlZHVsZUFbMV1bMl0gPSBuZXcgQXJyYXkoMiwgNSwgNywgNiwgNSwgNCwgMTYgKyAxKTtcclxuXHRcdHNjaGVkdWxlQVsxXVszXSA9IG5ldyBBcnJheSgzLCA3LCAweGEsIDksIDB4YiwgOCwgMTYgKyAzKTtcclxuXHJcblx0XHRzY2hlZHVsZUFbMl0gPSBuZXcgQXJyYXkoNCk7XHJcblx0XHRzY2hlZHVsZUFbMl1bMF0gPSBuZXcgQXJyYXkoNCwgMCwgMHhkLCAweGYsIDB4YywgMHhlLCA4KTtcclxuXHRcdHNjaGVkdWxlQVsyXVsxXSA9IG5ldyBBcnJheSg1LCAyLCAxNiArIDAsIDE2ICsgMiwgMTYgKyAxLCAxNiArIDMsIDB4YSk7XHJcblx0XHRzY2hlZHVsZUFbMl1bMl0gPSBuZXcgQXJyYXkoNiwgMywgMTYgKyA3LCAxNiArIDYsIDE2ICsgNSwgMTYgKyA0LCA5KTtcclxuXHRcdHNjaGVkdWxlQVsyXVszXSA9IG5ldyBBcnJheSg3LCAxLCAxNiArIDB4YSwgMTYgKyA5LCAxNiArIDB4YiwgMTYgKyA4LCAweGIpO1xyXG5cclxuXHJcblx0XHRzY2hlZHVsZUFbM10gPSBuZXcgQXJyYXkoNCk7XHJcblx0XHRzY2hlZHVsZUFbM11bMF0gPSBuZXcgQXJyYXkoMCwgNiwgMTYgKyA1LCAxNiArIDcsIDE2ICsgNCwgMTYgKyA2LCAxNiArIDApO1xyXG5cdFx0c2NoZWR1bGVBWzNdWzFdID0gbmV3IEFycmF5KDEsIDQsIDAsIDIsIDEsIDMsIDE2ICsgMik7XHJcblx0XHRzY2hlZHVsZUFbM11bMl0gPSBuZXcgQXJyYXkoMiwgNSwgNywgNiwgNSwgNCwgMTYgKyAxKTtcclxuXHRcdHNjaGVkdWxlQVszXVszXSA9IG5ldyBBcnJheSgzLCA3LCAweGEsIDksIDB4YiwgOCwgMTYgKyAzKTtcclxuXHJcblx0XHR2YXIgc2NoZWR1bGVCID0gbmV3IEFycmF5KDQpO1xyXG5cclxuXHRcdHNjaGVkdWxlQlswXSA9IG5ldyBBcnJheSg0KTtcclxuXHRcdHNjaGVkdWxlQlswXVswXSA9IG5ldyBBcnJheSgxNiArIDgsIDE2ICsgOSwgMTYgKyA3LCAxNiArIDYsIDE2ICsgMik7XHJcblx0XHRzY2hlZHVsZUJbMF1bMV0gPSBuZXcgQXJyYXkoMTYgKyAweGEsIDE2ICsgMHhiLCAxNiArIDUsIDE2ICsgNCwgMTYgKyA2KTtcclxuXHRcdHNjaGVkdWxlQlswXVsyXSA9IG5ldyBBcnJheSgxNiArIDB4YywgMTYgKyAweGQsIDE2ICsgMywgMTYgKyAyLCAxNiArIDkpO1xyXG5cdFx0c2NoZWR1bGVCWzBdWzNdID0gbmV3IEFycmF5KDE2ICsgMHhlLCAxNiArIDB4ZiwgMTYgKyAxLCAxNiArIDAsIDE2ICsgMHhjKTtcclxuXHJcblx0XHRzY2hlZHVsZUJbMV0gPSBuZXcgQXJyYXkoNCk7XHJcblx0XHRzY2hlZHVsZUJbMV1bMF0gPSBuZXcgQXJyYXkoMywgMiwgMHhjLCAweGQsIDgpO1xyXG5cdFx0c2NoZWR1bGVCWzFdWzFdID0gbmV3IEFycmF5KDEsIDAsIDB4ZSwgMHhmLCAweGQpO1xyXG5cdFx0c2NoZWR1bGVCWzFdWzJdID0gbmV3IEFycmF5KDcsIDYsIDgsIDksIDMpO1xyXG5cdFx0c2NoZWR1bGVCWzFdWzNdID0gbmV3IEFycmF5KDUsIDQsIDB4YSwgMHhiLCA3KTtcclxuXHJcblxyXG5cdFx0c2NoZWR1bGVCWzJdID0gbmV3IEFycmF5KDQpO1xyXG5cdFx0c2NoZWR1bGVCWzJdWzBdID0gbmV3IEFycmF5KDE2ICsgMywgMTYgKyAyLCAxNiArIDB4YywgMTYgKyAweGQsIDE2ICsgOSk7XHJcblx0XHRzY2hlZHVsZUJbMl1bMV0gPSBuZXcgQXJyYXkoMTYgKyAxLCAxNiArIDAsIDE2ICsgMHhlLCAxNiArIDB4ZiwgMTYgKyAweGMpO1xyXG5cdFx0c2NoZWR1bGVCWzJdWzJdID0gbmV3IEFycmF5KDE2ICsgNywgMTYgKyA2LCAxNiArIDgsIDE2ICsgOSwgMTYgKyAyKTtcclxuXHRcdHNjaGVkdWxlQlsyXVszXSA9IG5ldyBBcnJheSgxNiArIDUsIDE2ICsgNCwgMTYgKyAweGEsIDE2ICsgMHhiLCAxNiArIDYpO1xyXG5cclxuXHJcblx0XHRzY2hlZHVsZUJbM10gPSBuZXcgQXJyYXkoNCk7XHJcblx0XHRzY2hlZHVsZUJbM11bMF0gPSBuZXcgQXJyYXkoOCwgOSwgNywgNiwgMyk7XHJcblx0XHRzY2hlZHVsZUJbM11bMV0gPSBuZXcgQXJyYXkoMHhhLCAweGIsIDUsIDQsIDcpO1xyXG5cdFx0c2NoZWR1bGVCWzNdWzJdID0gbmV3IEFycmF5KDB4YywgMHhkLCAzLCAyLCA4KTtcclxuXHRcdHNjaGVkdWxlQlszXVszXSA9IG5ldyBBcnJheSgweGUsIDB4ZiwgMSwgMCwgMHhkKTtcclxuXHJcblx0XHQvLyBjaGFuZ2VkICdpbicgdG8gJ2lubicgKGluIGphdmFzY3JpcHQgJ2luJyBpcyBhIHJlc2VydmVkIHdvcmQpXHJcblx0XHR0aGlzLmtleVNjaGVkdWxlID0gZnVuY3Rpb24oaW5uKVxyXG5cdFx0e1xyXG5cdFx0IHZhciB0ID0gbmV3IEFycmF5KDgpO1xyXG5cdFx0IHZhciBrID0gbmV3IEFycmF5KDMyKTtcclxuXHJcblx0XHQgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpKyspXHJcblx0XHQge1xyXG5cdFx0ICB2YXIgaiA9IGkgKiA0O1xyXG5cdFx0ICB0W2ldID0gaW5uW2pdPDwyNCB8IGlubltqKzFdPDwxNiB8IGlubltqKzJdPDw4IHwgaW5uW2orM107XHJcblx0XHQgfVxyXG5cclxuXHRcdCB2YXIgeCA9IFs2LCA3LCA0LCA1XTtcclxuXHRcdCB2YXIga2kgPSAwO1xyXG5cclxuXHRcdCBmb3IgKHZhciBoYWxmID0gMDsgaGFsZiA8IDI7IGhhbGYrKylcclxuXHRcdCB7XHJcblx0XHQgIGZvciAodmFyIHJvdW5kID0gMDsgcm91bmQgPCA0OyByb3VuZCsrKVxyXG5cdFx0ICB7XHJcblx0XHQgICBmb3IgKHZhciBqID0gMDsgaiA8IDQ7IGorKylcclxuXHRcdCAgIHtcclxuXHRcdCAgICB2YXIgYSA9IHNjaGVkdWxlQVtyb3VuZF1bal07XHJcblx0XHQgICAgdmFyIHcgPSB0W2FbMV1dO1xyXG5cclxuXHRcdCAgICB3IF49IHNCb3hbNF1bKHRbYVsyXT4+PjJdPj4+KDI0LTgqKGFbMl0mMykpKSYweGZmXTtcclxuXHRcdCAgICB3IF49IHNCb3hbNV1bKHRbYVszXT4+PjJdPj4+KDI0LTgqKGFbM10mMykpKSYweGZmXTtcclxuXHRcdCAgICB3IF49IHNCb3hbNl1bKHRbYVs0XT4+PjJdPj4+KDI0LTgqKGFbNF0mMykpKSYweGZmXTtcclxuXHRcdCAgICB3IF49IHNCb3hbN11bKHRbYVs1XT4+PjJdPj4+KDI0LTgqKGFbNV0mMykpKSYweGZmXTtcclxuXHRcdCAgICB3IF49IHNCb3hbeFtqXV1bKHRbYVs2XT4+PjJdPj4+KDI0LTgqKGFbNl0mMykpKSYweGZmXTtcclxuXHRcdCAgICB0W2FbMF1dID0gdztcclxuXHRcdCAgIH1cclxuXHJcblx0XHQgICBmb3IgKHZhciBqID0gMDsgaiA8IDQ7IGorKylcclxuXHRcdCAgIHtcclxuXHRcdCAgICB2YXIgYiA9IHNjaGVkdWxlQltyb3VuZF1bal07XHJcblx0XHQgICAgdmFyIHcgPSBzQm94WzRdWyh0W2JbMF0+Pj4yXT4+PigyNC04KihiWzBdJjMpKSkmMHhmZl07XHJcblxyXG5cdFx0ICAgIHcgXj0gc0JveFs1XVsodFtiWzFdPj4+Ml0+Pj4oMjQtOCooYlsxXSYzKSkpJjB4ZmZdO1xyXG5cdFx0ICAgIHcgXj0gc0JveFs2XVsodFtiWzJdPj4+Ml0+Pj4oMjQtOCooYlsyXSYzKSkpJjB4ZmZdO1xyXG5cdFx0ICAgIHcgXj0gc0JveFs3XVsodFtiWzNdPj4+Ml0+Pj4oMjQtOCooYlszXSYzKSkpJjB4ZmZdO1xyXG5cdFx0ICAgIHcgXj0gc0JveFs0K2pdWyh0W2JbNF0+Pj4yXT4+PigyNC04KihiWzRdJjMpKSkmMHhmZl07XHJcblx0XHQgICAga1traV0gPSB3O1xyXG5cdFx0ICAgIGtpKys7XHJcblx0XHQgICB9XHJcblx0XHQgIH1cclxuXHRcdCB9XHJcblxyXG5cdFx0IGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKylcclxuXHRcdCB7XHJcblx0XHQgIHRoaXMubWFza2luZ1tpXSA9IGtbaV07XHJcblx0XHQgIHRoaXMucm90YXRlW2ldICA9IGtbMTYraV0gJiAweDFmO1xyXG5cdFx0IH1cclxuXHRcdH07XHJcblxyXG5cdFx0Ly8gVGhlc2UgYXJlIHRoZSB0aHJlZSAnZicgZnVuY3Rpb25zLiBTZWUgUkZDIDIxNDQsIHNlY3Rpb24gMi4yLlxyXG5cclxuXHRcdGZ1bmN0aW9uIGYxKGQsIG0sIHIpXHJcblx0XHR7XHJcblx0XHQgdmFyIHQgPSBtICsgZDtcclxuXHRcdCB2YXIgSSA9ICh0IDw8IHIpIHwgKHQgPj4+ICgzMiAtIHIpKTtcclxuXHRcdCByZXR1cm4gKChzQm94WzBdW0k+Pj4yNF0gXiBzQm94WzFdWyhJPj4+MTYpJjI1NV0pIC0gc0JveFsyXVsoST4+PjgpJjI1NV0pICsgc0JveFszXVtJJjI1NV07XHJcblx0XHR9XHJcblxyXG5cdFx0ZnVuY3Rpb24gZjIoZCwgbSwgcilcclxuXHRcdHtcclxuXHRcdCB2YXIgdCA9IG0gXiBkO1xyXG5cdFx0IHZhciBJID0gKHQgPDwgcikgfCAodCA+Pj4gKDMyIC0gcikpO1xyXG5cdFx0IHJldHVybiAoKHNCb3hbMF1bST4+PjI0XSAtIHNCb3hbMV1bKEk+Pj4xNikmMjU1XSkgKyBzQm94WzJdWyhJPj4+OCkmMjU1XSkgXiBzQm94WzNdW0kmMjU1XTtcclxuXHRcdH1cclxuXHJcblx0XHRmdW5jdGlvbiBmMyhkLCBtLCByKVxyXG5cdFx0e1xyXG5cdFx0IHZhciB0ID0gbSAtIGQ7XHJcblx0XHQgdmFyIEkgPSAodCA8PCByKSB8ICh0ID4+PiAoMzIgLSByKSk7XHJcblx0XHQgcmV0dXJuICgoc0JveFswXVtJPj4+MjRdICsgc0JveFsxXVsoST4+PjE2KSYyNTVdKSBeIHNCb3hbMl1bKEk+Pj44KSYyNTVdKSAtIHNCb3hbM11bSSYyNTVdO1xyXG5cdFx0fVxyXG5cclxuXHRcdHZhciBzQm94ID0gbmV3IEFycmF5KDgpO1xyXG5cdFx0c0JveFswXSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHgzMGZiNDBkNCwgMHg5ZmEwZmYwYiwgMHg2YmVjY2QyZiwgMHgzZjI1OGM3YSwgMHgxZTIxM2YyZiwgMHg5YzAwNGRkMywgMHg2MDAzZTU0MCwgMHhjZjlmYzk0OSxcclxuXHRcdCAgMHhiZmQ0YWYyNywgMHg4OGJiYmRiNSwgMHhlMjAzNDA5MCwgMHg5OGQwOTY3NSwgMHg2ZTYzYTBlMCwgMHgxNWMzNjFkMiwgMHhjMmU3NjYxZCwgMHgyMmQ0ZmY4ZSxcclxuXHRcdCAgMHgyODY4M2I2ZiwgMHhjMDdmZDA1OSwgMHhmZjIzNzljOCwgMHg3NzVmNTBlMiwgMHg0M2MzNDBkMywgMHhkZjJmODY1NiwgMHg4ODdjYTQxYSwgMHhhMmQyYmQyZCxcclxuXHRcdCAgMHhhMWM5ZTBkNiwgMHgzNDZjNDgxOSwgMHg2MWI3NmQ4NywgMHgyMjU0MGYyZiwgMHgyYWJlMzJlMSwgMHhhYTU0MTY2YiwgMHgyMjU2OGUzYSwgMHhhMmQzNDFkMCxcclxuXHRcdCAgMHg2NmRiNDBjOCwgMHhhNzg0MzkyZiwgMHgwMDRkZmYyZiwgMHgyZGI5ZDJkZSwgMHg5Nzk0M2ZhYywgMHg0YTk3YzFkOCwgMHg1Mjc2NDRiNywgMHhiNWY0MzdhNyxcclxuXHRcdCAgMHhiODJjYmFlZiwgMHhkNzUxZDE1OSwgMHg2ZmY3ZjBlZCwgMHg1YTA5N2ExZiwgMHg4MjdiNjhkMCwgMHg5MGVjZjUyZSwgMHgyMmIwYzA1NCwgMHhiYzhlNTkzNSxcclxuXHRcdCAgMHg0YjZkMmY3ZiwgMHg1MGJiNjRhMiwgMHhkMjY2NDkxMCwgMHhiZWU1ODEyZCwgMHhiNzMzMjI5MCwgMHhlOTNiMTU5ZiwgMHhiNDhlZTQxMSwgMHg0YmZmMzQ1ZCxcclxuXHRcdCAgMHhmZDQ1YzI0MCwgMHhhZDMxOTczZiwgMHhjNGY2ZDAyZSwgMHg1NWZjODE2NSwgMHhkNWIxY2FhZCwgMHhhMWFjMmRhZSwgMHhhMmQ0Yjc2ZCwgMHhjMTliMGM1MCxcclxuXHRcdCAgMHg4ODIyNDBmMiwgMHgwYzZlNGYzOCwgMHhhNGU0YmZkNywgMHg0ZjViYTI3MiwgMHg1NjRjMWQyZiwgMHhjNTljNTMxOSwgMHhiOTQ5ZTM1NCwgMHhiMDQ2NjlmZSxcclxuXHRcdCAgMHhiMWI2YWI4YSwgMHhjNzEzNThkZCwgMHg2Mzg1YzU0NSwgMHgxMTBmOTM1ZCwgMHg1NzUzOGFkNSwgMHg2YTM5MDQ5MywgMHhlNjNkMzdlMCwgMHgyYTU0ZjZiMyxcclxuXHRcdCAgMHgzYTc4N2Q1ZiwgMHg2Mjc2YTBiNSwgMHgxOWE2ZmNkZiwgMHg3YTQyMjA2YSwgMHgyOWY5ZDRkNSwgMHhmNjFiMTg5MSwgMHhiYjcyMjc1ZSwgMHhhYTUwODE2NyxcclxuXHRcdCAgMHgzODkwMTA5MSwgMHhjNmI1MDVlYiwgMHg4NGM3Y2I4YywgMHgyYWQ3NWEwZiwgMHg4NzRhMTQyNywgMHhhMmQxOTM2YiwgMHgyYWQyODZhZiwgMHhhYTU2ZDI5MSxcclxuXHRcdCAgMHhkNzg5NDM2MCwgMHg0MjVjNzUwZCwgMHg5M2IzOWUyNiwgMHgxODcxODRjOSwgMHg2YzAwYjMyZCwgMHg3M2UyYmIxNCwgMHhhMGJlYmMzYywgMHg1NDYyMzc3OSxcclxuXHRcdCAgMHg2NDQ1OWVhYiwgMHgzZjMyOGI4MiwgMHg3NzE4Y2Y4MiwgMHg1OWEyY2VhNiwgMHgwNGVlMDAyZSwgMHg4OWZlNzhlNiwgMHgzZmFiMDk1MCwgMHgzMjVmZjZjMixcclxuXHRcdCAgMHg4MTM4M2YwNSwgMHg2OTYzYzVjOCwgMHg3NmNiNWFkNiwgMHhkNDk5NzRjOSwgMHhjYTE4MGRjZiwgMHgzODA3ODJkNSwgMHhjN2ZhNWNmNiwgMHg4YWMzMTUxMSxcclxuXHRcdCAgMHgzNWU3OWUxMywgMHg0N2RhOTFkMCwgMHhmNDBmOTA4NiwgMHhhN2UyNDE5ZSwgMHgzMTM2NjI0MSwgMHgwNTFlZjQ5NSwgMHhhYTU3M2IwNCwgMHg0YTgwNWQ4ZCxcclxuXHRcdCAgMHg1NDgzMDBkMCwgMHgwMDMyMmEzYywgMHhiZjY0Y2RkZiwgMHhiYTU3YTY4ZSwgMHg3NWM2MzcyYiwgMHg1MGFmZDM0MSwgMHhhN2MxMzI3NSwgMHg5MTVhMGJmNSxcclxuXHRcdCAgMHg2YjU0YmZhYiwgMHgyYjBiMTQyNiwgMHhhYjRjYzlkNywgMHg0NDljY2Q4MiwgMHhmN2ZiZjI2NSwgMHhhYjg1YzVmMywgMHgxYjU1ZGI5NCwgMHhhYWQ0ZTMyNCxcclxuXHRcdCAgMHhjZmE0YmQzZiwgMHgyZGVhYTNlMiwgMHg5ZTIwNGQwMiwgMHhjOGJkMjVhYywgMHhlYWRmNTViMywgMHhkNWJkOWU5OCwgMHhlMzEyMzFiMiwgMHgyYWQ1YWQ2YyxcclxuXHRcdCAgMHg5NTQzMjlkZSwgMHhhZGJlNDUyOCwgMHhkODcxMGY2OSwgMHhhYTUxYzkwZiwgMHhhYTc4NmJmNiwgMHgyMjUxM2YxZSwgMHhhYTUxYTc5YiwgMHgyYWQzNDRjYyxcclxuXHRcdCAgMHg3YjVhNDFmMCwgMHhkMzdjZmJhZCwgMHgxYjA2OTUwNSwgMHg0MWVjZTQ5MSwgMHhiNGMzMzJlNiwgMHgwMzIyNjhkNCwgMHhjOTYwMGFjYywgMHhjZTM4N2U2ZCxcclxuXHRcdCAgMHhiZjZiYjE2YywgMHg2YTcwZmI3OCwgMHgwZDAzZDljOSwgMHhkNGRmMzlkZSwgMHhlMDEwNjNkYSwgMHg0NzM2ZjQ2NCwgMHg1YWQzMjhkOCwgMHhiMzQ3Y2M5NixcclxuXHRcdCAgMHg3NWJiMGZjMywgMHg5ODUxMWJmYiwgMHg0ZmZiY2MzNSwgMHhiNThiY2Y2YSwgMHhlMTFmMGFiYywgMHhiZmM1ZmU0YSwgMHhhNzBhZWMxMCwgMHhhYzM5NTcwYSxcclxuXHRcdCAgMHgzZjA0NDQyZiwgMHg2MTg4YjE1MywgMHhlMDM5N2EyZSwgMHg1NzI3Y2I3OSwgMHg5Y2ViNDE4ZiwgMHgxY2FjZDY4ZCwgMHgyYWQzN2M5NiwgMHgwMTc1Y2I5ZCxcclxuXHRcdCAgMHhjNjlkZmYwOSwgMHhjNzViNjVmMCwgMHhkOWRiNDBkOCwgMHhlYzBlNzc3OSwgMHg0NzQ0ZWFkNCwgMHhiMTFjMzI3NCwgMHhkZDI0Y2I5ZSwgMHg3ZTFjNTRiZCxcclxuXHRcdCAgMHhmMDExNDRmOSwgMHhkMjI0MGViMSwgMHg5Njc1YjNmZCwgMHhhM2FjMzc1NSwgMHhkNDdjMjdhZiwgMHg1MWM4NWY0ZCwgMHg1NjkwNzU5NiwgMHhhNWJiMTVlNixcclxuXHRcdCAgMHg1ODAzMDRmMCwgMHhjYTA0MmNmMSwgMHgwMTFhMzdlYSwgMHg4ZGJmYWFkYiwgMHgzNWJhM2U0YSwgMHgzNTI2ZmZhMCwgMHhjMzdiNGQwOSwgMHhiYzMwNmVkOSxcclxuXHRcdCAgMHg5OGE1MjY2NiwgMHg1NjQ4ZjcyNSwgMHhmZjVlNTY5ZCwgMHgwY2VkNjNkMCwgMHg3YzYzYjJjZiwgMHg3MDBiNDVlMSwgMHhkNWVhNTBmMSwgMHg4NWE5Mjg3MixcclxuXHRcdCAgMHhhZjFmYmRhNywgMHhkNDIzNDg3MCwgMHhhNzg3MGJmMywgMHgyZDNiNGQ3OSwgMHg0MmUwNDE5OCwgMHgwY2QwZWRlNywgMHgyNjQ3MGRiOCwgMHhmODgxODE0YyxcclxuXHRcdCAgMHg0NzRkNmFkNywgMHg3YzBjNWU1YywgMHhkMTIzMTk1OSwgMHgzODFiNzI5OCwgMHhmNWQyZjRkYiwgMHhhYjgzODY1MywgMHg2ZTJmMWUyMywgMHg4MzcxOWM5ZSxcclxuXHRcdCAgMHhiZDkxZTA0NiwgMHg5YTU2NDU2ZSwgMHhkYzM5MjAwYywgMHgyMGM4YzU3MSwgMHg5NjJiZGExYywgMHhlMWU2OTZmZiwgMHhiMTQxYWIwOCwgMHg3Y2NhODliOSxcclxuXHRcdCAgMHgxYTY5ZTc4MywgMHgwMmNjNDg0MywgMHhhMmY3YzU3OSwgMHg0MjllZjQ3ZCwgMHg0MjdiMTY5YywgMHg1YWM5ZjA0OSwgMHhkZDhmMGYwMCwgMHg1YzgxNjViZik7XHJcblxyXG5cdFx0c0JveFsxXSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHgxZjIwMTA5NCwgMHhlZjBiYTc1YiwgMHg2OWUzY2Y3ZSwgMHgzOTNmNDM4MCwgMHhmZTYxY2Y3YSwgMHhlZWM1MjA3YSwgMHg1NTg4OWM5NCwgMHg3MmZjMDY1MSxcclxuXHRcdCAgMHhhZGE3ZWY3OSwgMHg0ZTFkNzIzNSwgMHhkNTVhNjNjZSwgMHhkZTA0MzZiYSwgMHg5OWM0MzBlZiwgMHg1ZjBjMDc5NCwgMHgxOGRjZGI3ZCwgMHhhMWQ2ZWZmMyxcclxuXHRcdCAgMHhhMGI1MmY3YiwgMHg1OWU4MzYwNSwgMHhlZTE1YjA5NCwgMHhlOWZmZDkwOSwgMHhkYzQ0MDA4NiwgMHhlZjk0NDQ1OSwgMHhiYTgzY2NiMywgMHhlMGMzY2RmYixcclxuXHRcdCAgMHhkMWRhNDE4MSwgMHgzYjA5MmFiMSwgMHhmOTk3ZjFjMSwgMHhhNWU2Y2Y3YiwgMHgwMTQyMGRkYiwgMHhlNGU3ZWY1YiwgMHgyNWExZmY0MSwgMHhlMTgwZjgwNixcclxuXHRcdCAgMHgxZmM0MTA4MCwgMHgxNzliZWU3YSwgMHhkMzdhYzZhOSwgMHhmZTU4MzBhNCwgMHg5OGRlOGI3ZiwgMHg3N2U4M2Y0ZSwgMHg3OTkyOTI2OSwgMHgyNGZhOWY3YixcclxuXHRcdCAgMHhlMTEzYzg1YiwgMHhhY2M0MDA4MywgMHhkNzUwMzUyNSwgMHhmN2VhNjE1ZiwgMHg2MjE0MzE1NCwgMHgwZDU1NGI2MywgMHg1ZDY4MTEyMSwgMHhjODY2YzM1OSxcclxuXHRcdCAgMHgzZDYzY2Y3MywgMHhjZWUyMzRjMCwgMHhkNGQ4N2U4NywgMHg1YzY3MmIyMSwgMHgwNzFmNjE4MSwgMHgzOWY3NjI3ZiwgMHgzNjFlMzA4NCwgMHhlNGViNTczYixcclxuXHRcdCAgMHg2MDJmNjRhNCwgMHhkNjNhY2Q5YywgMHgxYmJjNDYzNSwgMHg5ZTgxMDMyZCwgMHgyNzAxZjUwYywgMHg5OTg0N2FiNCwgMHhhMGUzZGY3OSwgMHhiYTZjZjM4YyxcclxuXHRcdCAgMHgxMDg0MzA5NCwgMHgyNTM3YTk1ZSwgMHhmNDZmNmZmZSwgMHhhMWZmM2IxZiwgMHgyMDhjZmI2YSwgMHg4ZjQ1OGM3NCwgMHhkOWUwYTIyNywgMHg0ZWM3M2EzNCxcclxuXHRcdCAgMHhmYzg4NGY2OSwgMHgzZTRkZThkZiwgMHhlZjBlMDA4OCwgMHgzNTU5NjQ4ZCwgMHg4YTQ1Mzg4YywgMHgxZDgwNDM2NiwgMHg3MjFkOWJmZCwgMHhhNTg2ODRiYixcclxuXHRcdCAgMHhlODI1NjMzMywgMHg4NDRlODIxMiwgMHgxMjhkODA5OCwgMHhmZWQzM2ZiNCwgMHhjZTI4MGFlMSwgMHgyN2UxOWJhNSwgMHhkNWE2YzI1MiwgMHhlNDk3NTRiZCxcclxuXHRcdCAgMHhjNWQ2NTVkZCwgMHhlYjY2NzA2NCwgMHg3Nzg0MGI0ZCwgMHhhMWI2YTgwMSwgMHg4NGRiMjZhOSwgMHhlMGI1NjcxNCwgMHgyMWYwNDNiNywgMHhlNWQwNTg2MCxcclxuXHRcdCAgMHg1NGYwMzA4NCwgMHgwNjZmZjQ3MiwgMHhhMzFhYTE1MywgMHhkYWRjNDc1NSwgMHhiNTYyNWRiZiwgMHg2ODU2MWJlNiwgMHg4M2NhNmI5NCwgMHgyZDZlZDIzYixcclxuXHRcdCAgMHhlY2NmMDFkYiwgMHhhNmQzZDBiYSwgMHhiNjgwM2Q1YywgMHhhZjc3YTcwOSwgMHgzM2I0YTM0YywgMHgzOTdiYzhkNiwgMHg1ZWUyMmI5NSwgMHg1ZjBlNTMwNCxcclxuXHRcdCAgMHg4MWVkNmY2MSwgMHgyMGU3NDM2NCwgMHhiNDVlMTM3OCwgMHhkZTE4NjM5YiwgMHg4ODFjYTEyMiwgMHhiOTY3MjZkMSwgMHg4MDQ5YTdlOCwgMHgyMmI3ZGE3YixcclxuXHRcdCAgMHg1ZTU1MmQyNSwgMHg1MjcyZDIzNywgMHg3OWQyOTUxYywgMHhjNjBkODk0YywgMHg0ODhjYjQwMiwgMHgxYmE0ZmU1YiwgMHhhNGIwOWY2YiwgMHgxY2E4MTVjZixcclxuXHRcdCAgMHhhMjBjMzAwNSwgMHg4ODcxZGY2MywgMHhiOWRlMmZjYiwgMHgwY2M2YzllOSwgMHgwYmVlZmY1MywgMHhlMzIxNDUxNywgMHhiNDU0MjgzNSwgMHg5ZjYzMjkzYyxcclxuXHRcdCAgMHhlZTQxZTcyOSwgMHg2ZTFkMmQ3YywgMHg1MDA0NTI4NiwgMHgxZTY2ODVmMywgMHhmMzM0MDFjNiwgMHgzMGEyMmM5NSwgMHgzMWE3MDg1MCwgMHg2MDkzMGYxMyxcclxuXHRcdCAgMHg3M2Y5ODQxNywgMHhhMTI2OTg1OSwgMHhlYzY0NWM0NCwgMHg1MmM4NzdhOSwgMHhjZGZmMzNhNiwgMHhhMDJiMTc0MSwgMHg3Y2JhZDlhMiwgMHgyMTgwMDM2ZixcclxuXHRcdCAgMHg1MGQ5OWMwOCwgMHhjYjNmNDg2MSwgMHhjMjZiZDc2NSwgMHg2NGEzZjZhYiwgMHg4MDM0MjY3NiwgMHgyNWE3NWU3YiwgMHhlNGU2ZDFmYywgMHgyMGM3MTBlNixcclxuXHRcdCAgMHhjZGYwYjY4MCwgMHgxNzg0NGQzYiwgMHgzMWVlZjg0ZCwgMHg3ZTA4MjRlNCwgMHgyY2NiNDllYiwgMHg4NDZhM2JhZSwgMHg4ZmY3Nzg4OCwgMHhlZTVkNjBmNixcclxuXHRcdCAgMHg3YWY3NTY3MywgMHgyZmRkNWNkYiwgMHhhMTE2MzFjMSwgMHgzMGY2NmY0MywgMHhiM2ZhZWM1NCwgMHgxNTdmZDdmYSwgMHhlZjg1NzljYywgMHhkMTUyZGU1OCxcclxuXHRcdCAgMHhkYjJmZmQ1ZSwgMHg4ZjMyY2UxOSwgMHgzMDZhZjk3YSwgMHgwMmYwM2VmOCwgMHg5OTMxOWFkNSwgMHhjMjQyZmEwZiwgMHhhN2UzZWJiMCwgMHhjNjhlNDkwNixcclxuXHRcdCAgMHhiOGRhMjMwYywgMHg4MDgyMzAyOCwgMHhkY2RlZjNjOCwgMHhkMzVmYjE3MSwgMHgwODhhMWJjOCwgMHhiZWMwYzU2MCwgMHg2MWEzYzllOCwgMHhiY2E4ZjU0ZCxcclxuXHRcdCAgMHhjNzJmZWZmYSwgMHgyMjgyMmU5OSwgMHg4MmM1NzBiNCwgMHhkOGQ5NGU4OSwgMHg4YjFjMzRiYywgMHgzMDFlMTZlNiwgMHgyNzNiZTk3OSwgMHhiMGZmZWFhNixcclxuXHRcdCAgMHg2MWQ5YjhjNiwgMHgwMGIyNDg2OSwgMHhiN2ZmY2UzZiwgMHgwOGRjMjgzYiwgMHg0M2RhZjY1YSwgMHhmN2UxOTc5OCwgMHg3NjE5YjcyZiwgMHg4ZjFjOWJhNCxcclxuXHRcdCAgMHhkYzg2MzdhMCwgMHgxNmE3ZDNiMSwgMHg5ZmMzOTNiNywgMHhhNzEzNmVlYiwgMHhjNmJjYzYzZSwgMHgxYTUxMzc0MiwgMHhlZjY4MjhiYywgMHg1MjAzNjVkNixcclxuXHRcdCAgMHgyZDZhNzdhYiwgMHgzNTI3ZWQ0YiwgMHg4MjFmZDIxNiwgMHgwOTVjNmUyZSwgMHhkYjkyZjJmYiwgMHg1ZWVhMjljYiwgMHgxNDU4OTJmNSwgMHg5MTU4NGY3ZixcclxuXHRcdCAgMHg1NDgzNjk3YiwgMHgyNjY3YThjYywgMHg4NTE5NjA0OCwgMHg4YzRiYWNlYSwgMHg4MzM4NjBkNCwgMHgwZDIzZTBmOSwgMHg2YzM4N2U4YSwgMHgwYWU2ZDI0OSxcclxuXHRcdCAgMHhiMjg0NjAwYywgMHhkODM1NzMxZCwgMHhkY2IxYzY0NywgMHhhYzRjNTZlYSwgMHgzZWJkODFiMywgMHgyMzBlYWJiMCwgMHg2NDM4YmM4NywgMHhmMGI1YjFmYSxcclxuXHRcdCAgMHg4ZjVlYTJiMywgMHhmYzE4NDY0MiwgMHgwYTAzNmI3YSwgMHg0ZmIwODliZCwgMHg2NDlkYTU4OSwgMHhhMzQ1NDE1ZSwgMHg1YzAzODMyMywgMHgzZTVkM2JiOSxcclxuXHRcdCAgMHg0M2Q3OTU3MiwgMHg3ZTZkZDA3YywgMHgwNmRmZGYxZSwgMHg2YzZjYzRlZiwgMHg3MTYwYTUzOSwgMHg3M2JmYmU3MCwgMHg4Mzg3NzYwNSwgMHg0NTIzZWNmMSk7XHJcblxyXG5cdFx0c0JveFsyXSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHg4ZGVmYzI0MCwgMHgyNWZhNWQ5ZiwgMHhlYjkwM2RiZiwgMHhlODEwYzkwNywgMHg0NzYwN2ZmZiwgMHgzNjlmZTQ0YiwgMHg4YzFmYzY0NCwgMHhhZWNlY2E5MCxcclxuXHRcdCAgMHhiZWIxZjliZiwgMHhlZWZiY2FlYSwgMHhlOGNmMTk1MCwgMHg1MWRmMDdhZSwgMHg5MjBlODgwNiwgMHhmMGFkMDU0OCwgMHhlMTNjOGQ4MywgMHg5MjcwMTBkNSxcclxuXHRcdCAgMHgxMTEwN2Q5ZiwgMHgwNzY0N2RiOSwgMHhiMmUzZTRkNCwgMHgzZDRmMjg1ZSwgMHhiOWFmYTgyMCwgMHhmYWRlODJlMCwgMHhhMDY3MjY4YiwgMHg4MjcyNzkyZSxcclxuXHRcdCAgMHg1NTNmYjJjMCwgMHg0ODlhZTIyYiwgMHhkNGVmOTc5NCwgMHgxMjVlM2ZiYywgMHgyMWZmZmNlZSwgMHg4MjViMWJmZCwgMHg5MjU1YzVlZCwgMHgxMjU3YTI0MCxcclxuXHRcdCAgMHg0ZTFhODMwMiwgMHhiYWUwN2ZmZiwgMHg1MjgyNDZlNywgMHg4ZTU3MTQwZSwgMHgzMzczZjdiZiwgMHg4YzlmODE4OCwgMHhhNmZjNGVlOCwgMHhjOTgyYjVhNSxcclxuXHRcdCAgMHhhOGMwMWRiNywgMHg1NzlmYzI2NCwgMHg2NzA5NGYzMSwgMHhmMmJkM2Y1ZiwgMHg0MGZmZjdjMSwgMHgxZmI3OGRmYywgMHg4ZTZiZDJjMSwgMHg0MzdiZTU5YixcclxuXHRcdCAgMHg5OWIwM2RiZiwgMHhiNWRiYzY0YiwgMHg2MzhkYzBlNiwgMHg1NTgxOWQ5OSwgMHhhMTk3YzgxYywgMHg0YTAxMmQ2ZSwgMHhjNTg4NGEyOCwgMHhjY2MzNmY3MSxcclxuXHRcdCAgMHhiODQzYzIxMywgMHg2YzA3NDNmMSwgMHg4MzA5ODkzYywgMHgwZmVkZGQ1ZiwgMHgyZjdmZTg1MCwgMHhkN2MwN2Y3ZSwgMHgwMjUwN2ZiZiwgMHg1YWZiOWEwNCxcclxuXHRcdCAgMHhhNzQ3ZDJkMCwgMHgxNjUxMTkyZSwgMHhhZjcwYmYzZSwgMHg1OGMzMTM4MCwgMHg1Zjk4MzAyZSwgMHg3MjdjYzNjNCwgMHgwYTBmYjQwMiwgMHgwZjdmZWY4MixcclxuXHRcdCAgMHg4Yzk2ZmRhZCwgMHg1ZDJjMmFhZSwgMHg4ZWU5OWE0OSwgMHg1MGRhODhiOCwgMHg4NDI3ZjRhMCwgMHgxZWFjNTc5MCwgMHg3OTZmYjQ0OSwgMHg4MjUyZGMxNSxcclxuXHRcdCAgMHhlZmJkN2Q5YiwgMHhhNjcyNTk3ZCwgMHhhZGE4NDBkOCwgMHg0NWY1NDUwNCwgMHhmYTVkNzQwMywgMHhlODNlYzMwNSwgMHg0ZjkxNzUxYSwgMHg5MjU2NjljMixcclxuXHRcdCAgMHgyM2VmZTk0MSwgMHhhOTAzZjEyZSwgMHg2MDI3MGRmMiwgMHgwMjc2ZTRiNiwgMHg5NGZkNjU3NCwgMHg5Mjc5ODViMiwgMHg4Mjc2ZGJjYiwgMHgwMjc3ODE3NixcclxuXHRcdCAgMHhmOGFmOTE4ZCwgMHg0ZTQ4Zjc5ZSwgMHg4ZjYxNmRkZiwgMHhlMjlkODQwZSwgMHg4NDJmN2Q4MywgMHgzNDBjZTVjOCwgMHg5NmJiYjY4MiwgMHg5M2I0YjE0OCxcclxuXHRcdCAgMHhlZjMwM2NhYiwgMHg5ODRmYWYyOCwgMHg3NzlmYWY5YiwgMHg5MmRjNTYwZCwgMHgyMjRkMWUyMCwgMHg4NDM3YWE4OCwgMHg3ZDI5ZGM5NiwgMHgyNzU2ZDNkYyxcclxuXHRcdCAgMHg4YjkwN2NlZSwgMHhiNTFmZDI0MCwgMHhlN2MwN2NlMywgMHhlNTY2YjRhMSwgMHhjM2U5NjE1ZSwgMHgzY2Y4MjA5ZCwgMHg2MDk0ZDFlMywgMHhjZDljYTM0MSxcclxuXHRcdCAgMHg1Yzc2NDYwZSwgMHgwMGVhOTgzYiwgMHhkNGQ2Nzg4MSwgMHhmZDQ3NTcyYywgMHhmNzZjZWRkOSwgMHhiZGE4MjI5YywgMHgxMjdkYWRhYSwgMHg0MzhhMDc0ZSxcclxuXHRcdCAgMHgxZjk3YzA5MCwgMHgwODFiZGI4YSwgMHg5M2EwN2ViZSwgMHhiOTM4Y2ExNSwgMHg5N2IwM2NmZiwgMHgzZGMyYzBmOCwgMHg4ZDFhYjJlYywgMHg2NDM4MGU1MSxcclxuXHRcdCAgMHg2OGNjN2JmYiwgMHhkOTBmMjc4OCwgMHgxMjQ5MDE4MSwgMHg1ZGU1ZmZkNCwgMHhkZDdlZjg2YSwgMHg3NmEyZTIxNCwgMHhiOWE0MDM2OCwgMHg5MjVkOTU4ZixcclxuXHRcdCAgMHg0YjM5ZmZmYSwgMHhiYTM5YWVlOSwgMHhhNGZmZDMwYiwgMHhmYWY3OTMzYiwgMHg2ZDQ5ODYyMywgMHgxOTNjYmNmYSwgMHgyNzYyNzU0NSwgMHg4MjVjZjQ3YSxcclxuXHRcdCAgMHg2MWJkOGJhMCwgMHhkMTFlNDJkMSwgMHhjZWFkMDRmNCwgMHgxMjdlYTM5MiwgMHgxMDQyOGRiNywgMHg4MjcyYTk3MiwgMHg5MjcwYzRhOCwgMHgxMjdkZTUwYixcclxuXHRcdCAgMHgyODViYTFjOCwgMHgzYzYyZjQ0ZiwgMHgzNWMwZWFhNSwgMHhlODA1ZDIzMSwgMHg0Mjg5MjlmYiwgMHhiNGZjZGY4MiwgMHg0ZmI2NmE1MywgMHgwZTdkYzE1YixcclxuXHRcdCAgMHgxZjA4MWZhYiwgMHgxMDg2MThhZSwgMHhmY2ZkMDg2ZCwgMHhmOWZmMjg4OSwgMHg2OTRiY2MxMSwgMHgyMzZhNWNhZSwgMHgxMmRlY2E0ZCwgMHgyYzNmOGNjNSxcclxuXHRcdCAgMHhkMmQwMmRmZSwgMHhmOGVmNTg5NiwgMHhlNGNmNTJkYSwgMHg5NTE1NWI2NywgMHg0OTRhNDg4YywgMHhiOWI2YTgwYywgMHg1YzhmODJiYywgMHg4OWQzNmI0NSxcclxuXHRcdCAgMHgzYTYwOTQzNywgMHhlYzAwYzlhOSwgMHg0NDcxNTI1MywgMHgwYTg3NGI0OSwgMHhkNzczYmM0MCwgMHg3YzM0NjcxYywgMHgwMjcxN2VmNiwgMHg0ZmViNTUzNixcclxuXHRcdCAgMHhhMmQwMmZmZiwgMHhkMmJmNjBjNCwgMHhkNDNmMDNjMCwgMHg1MGI0ZWY2ZCwgMHgwNzQ3OGNkMSwgMHgwMDZlMTg4OCwgMHhhMmU1M2Y1NSwgMHhiOWU2ZDRiYyxcclxuXHRcdCAgMHhhMjA0ODAxNiwgMHg5NzU3MzgzMywgMHhkNzIwN2Q2NywgMHhkZTBmOGYzZCwgMHg3MmY4N2IzMywgMHhhYmNjNGYzMywgMHg3Njg4YzU1ZCwgMHg3YjAwYTZiMCxcclxuXHRcdCAgMHg5NDdiMDAwMSwgMHg1NzAwNzVkMiwgMHhmOWJiODhmOCwgMHg4OTQyMDE5ZSwgMHg0MjY0YTVmZiwgMHg4NTYzMDJlMCwgMHg3MmRiZDkyYiwgMHhlZTk3MWI2OSxcclxuXHRcdCAgMHg2ZWEyMmZkZSwgMHg1ZjA4YWUyYiwgMHhhZjdhNjE2ZCwgMHhlNWM5ODc2NywgMHhjZjFmZWJkMiwgMHg2MWVmYzhjMiwgMHhmMWFjMjU3MSwgMHhjYzgyMzljMixcclxuXHRcdCAgMHg2NzIxNGNiOCwgMHhiMWU1ODNkMSwgMHhiN2RjM2U2MiwgMHg3ZjEwYmRjZSwgMHhmOTBhNWMzOCwgMHgwZmYwNDQzZCwgMHg2MDZlNmRjNiwgMHg2MDU0M2E0OSxcclxuXHRcdCAgMHg1NzI3YzE0OCwgMHgyYmU5OGExZCwgMHg4YWI0MTczOCwgMHgyMGUxYmUyNCwgMHhhZjk2ZGEwZiwgMHg2ODQ1ODQyNSwgMHg5OTgzM2JlNSwgMHg2MDBkNDU3ZCxcclxuXHRcdCAgMHgyODJmOTM1MCwgMHg4MzM0YjM2MiwgMHhkOTFkMTEyMCwgMHgyYjZkOGRhMCwgMHg2NDJiMWUzMSwgMHg5YzMwNWEwMCwgMHg1MmJjZTY4OCwgMHgxYjAzNTg4YSxcclxuXHRcdCAgMHhmN2JhZWZkNSwgMHg0MTQyZWQ5YywgMHhhNDMxNWMxMSwgMHg4MzMyM2VjNSwgMHhkZmVmNDYzNiwgMHhhMTMzYzUwMSwgMHhlOWQzNTMxYywgMHhlZTM1Mzc4Myk7XHJcblxyXG5cdFx0c0JveFszXSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHg5ZGIzMDQyMCwgMHgxZmI2ZTlkZSwgMHhhN2JlN2JlZiwgMHhkMjczYTI5OCwgMHg0YTRmN2JkYiwgMHg2NGFkOGM1NywgMHg4NTUxMDQ0MywgMHhmYTAyMGVkMSxcclxuXHRcdCAgMHg3ZTI4N2FmZiwgMHhlNjBmYjY2MywgMHgwOTVmMzVhMSwgMHg3OWViZjEyMCwgMHhmZDA1OWQ0MywgMHg2NDk3YjdiMSwgMHhmMzY0MWY2MywgMHgyNDFlNGFkZixcclxuXHRcdCAgMHgyODE0N2Y1ZiwgMHg0ZmEyYjhjZCwgMHhjOTQzMDA0MCwgMHgwY2MzMjIyMCwgMHhmZGQzMGIzMCwgMHhjMGE1Mzc0ZiwgMHgxZDJkMDBkOSwgMHgyNDE0N2IxNSxcclxuXHRcdCAgMHhlZTRkMTExYSwgMHgwZmNhNTE2NywgMHg3MWZmOTA0YywgMHgyZDE5NWZmZSwgMHgxYTA1NjQ1ZiwgMHgwYzEzZmVmZSwgMHgwODFiMDhjYSwgMHgwNTE3MDEyMSxcclxuXHRcdCAgMHg4MDUzMDEwMCwgMHhlODNlNWVmZSwgMHhhYzlhZjRmOCwgMHg3ZmU3MjcwMSwgMHhkMmI4ZWU1ZiwgMHgwNmRmNDI2MSwgMHhiYjllOWI4YSwgMHg3MjkzZWEyNSxcclxuXHRcdCAgMHhjZTg0ZmZkZiwgMHhmNTcxODgwMSwgMHgzZGQ2NGIwNCwgMHhhMjZmMjYzYiwgMHg3ZWQ0ODQwMCwgMHg1NDdlZWJlNiwgMHg0NDZkNGNhMCwgMHg2Y2YzZDZmNSxcclxuXHRcdCAgMHgyNjQ5YWJkZiwgMHhhZWEwYzdmNSwgMHgzNjMzOGNjMSwgMHg1MDNmN2U5MywgMHhkMzc3MjA2MSwgMHgxMWI2MzhlMSwgMHg3MjUwMGUwMywgMHhmODBlYjJiYixcclxuXHRcdCAgMHhhYmUwNTAyZSwgMHhlYzhkNzdkZSwgMHg1Nzk3MWU4MSwgMHhlMTRmNjc0NiwgMHhjOTMzNTQwMCwgMHg2OTIwMzE4ZiwgMHgwODFkYmI5OSwgMHhmZmMzMDRhNSxcclxuXHRcdCAgMHg0ZDM1MTgwNSwgMHg3ZjNkNWNlMywgMHhhNmM4NjZjNiwgMHg1ZDViY2NhOSwgMHhkYWVjNmZlYSwgMHg5ZjkyNmY5MSwgMHg5ZjQ2MjIyZiwgMHgzOTkxNDY3ZCxcclxuXHRcdCAgMHhhNWJmNmQ4ZSwgMHgxMTQzYzQ0ZiwgMHg0Mzk1ODMwMiwgMHhkMDIxNGVlYiwgMHgwMjIwODNiOCwgMHgzZmI2MTgwYywgMHgxOGY4OTMxZSwgMHgyODE2NThlNixcclxuXHRcdCAgMHgyNjQ4NmUzZSwgMHg4YmQ3OGE3MCwgMHg3NDc3ZTRjMSwgMHhiNTA2ZTA3YywgMHhmMzJkMGEyNSwgMHg3OTA5OGIwMiwgMHhlNGVhYmI4MSwgMHgyODEyM2IyMyxcclxuXHRcdCAgMHg2OWRlYWQzOCwgMHgxNTc0Y2ExNiwgMHhkZjg3MWI2MiwgMHgyMTFjNDBiNywgMHhhNTFhOWVmOSwgMHgwMDE0Mzc3YiwgMHgwNDFlOGFjOCwgMHgwOTExNDAwMyxcclxuXHRcdCAgMHhiZDU5ZTRkMiwgMHhlM2QxNTZkNSwgMHg0ZmU4NzZkNSwgMHgyZjkxYTM0MCwgMHg1NTdiZThkZSwgMHgwMGVhZTRhNywgMHgwY2U1YzJlYywgMHg0ZGI0YmJhNixcclxuXHRcdCAgMHhlNzU2YmRmZiwgMHhkZDMzNjlhYywgMHhlYzE3YjAzNSwgMHgwNjU3MjMyNywgMHg5OWFmYzhiMCwgMHg1NmM4YzM5MSwgMHg2YjY1ODExYywgMHg1ZTE0NjExOSxcclxuXHRcdCAgMHg2ZTg1Y2I3NSwgMHhiZTA3YzAwMiwgMHhjMjMyNTU3NywgMHg4OTNmZjRlYywgMHg1YmJmYzkyZCwgMHhkMGVjM2IyNSwgMHhiNzgwMWFiNywgMHg4ZDZkM2IyNCxcclxuXHRcdCAgMHgyMGM3NjNlZiwgMHhjMzY2YTVmYywgMHg5YzM4Mjg4MCwgMHgwYWNlMzIwNSwgMHhhYWM5NTQ4YSwgMHhlY2ExZDdjNywgMHgwNDFhZmEzMiwgMHgxZDE2NjI1YSxcclxuXHRcdCAgMHg2NzAxOTAyYywgMHg5Yjc1N2E1NCwgMHgzMWQ0NzdmNywgMHg5MTI2YjAzMSwgMHgzNmNjNmZkYiwgMHhjNzBiOGI0NiwgMHhkOWU2NmE0OCwgMHg1NmU1NWE3OSxcclxuXHRcdCAgMHgwMjZhNGNlYiwgMHg1MjQzN2VmZiwgMHgyZjhmNzZiNCwgMHgwZGY5ODBhNSwgMHg4Njc0Y2RlMywgMHhlZGRhMDRlYiwgMHgxN2E5YmUwNCwgMHgyYzE4ZjRkZixcclxuXHRcdCAgMHhiNzc0N2Y5ZCwgMHhhYjJhZjdiNCwgMHhlZmMzNGQyMCwgMHgyZTA5NmI3YywgMHgxNzQxYTI1NCwgMHhlNWI2YTAzNSwgMHgyMTNkNDJmNiwgMHgyYzFjN2MyNixcclxuXHRcdCAgMHg2MWMyZjUwZiwgMHg2NTUyZGFmOSwgMHhkMmMyMzFmOCwgMHgyNTEzMGY2OSwgMHhkODE2N2ZhMiwgMHgwNDE4ZjJjOCwgMHgwMDFhOTZhNiwgMHgwZDE1MjZhYixcclxuXHRcdCAgMHg2MzMxNWMyMSwgMHg1ZTBhNzJlYywgMHg0OWJhZmVmZCwgMHgxODc5MDhkOSwgMHg4ZDBkYmQ4NiwgMHgzMTExNzBhNywgMHgzZTliNjQwYywgMHhjYzNlMTBkNyxcclxuXHRcdCAgMHhkNWNhZDNiNiwgMHgwY2FlYzM4OCwgMHhmNzMwMDFlMSwgMHg2YzcyOGFmZiwgMHg3MWVhZTJhMSwgMHgxZjlhZjM2ZSwgMHhjZmNiZDEyZiwgMHhjMWRlODQxNyxcclxuXHRcdCAgMHhhYzA3YmU2YiwgMHhjYjQ0YTFkOCwgMHg4YjliMGY1NiwgMHgwMTM5ODhjMywgMHhiMWM1MmZjYSwgMHhiNGJlMzFjZCwgMHhkODc4MjgwNiwgMHgxMmEzYTRlMixcclxuXHRcdCAgMHg2ZjdkZTUzMiwgMHg1OGZkN2ViNiwgMHhkMDFlZTkwMCwgMHgyNGFkZmZjMiwgMHhmNDk5MGZjNSwgMHg5NzExYWFjNSwgMHgwMDFkN2I5NSwgMHg4MmU1ZTdkMixcclxuXHRcdCAgMHgxMDk4NzNmNiwgMHgwMDYxMzA5NiwgMHhjMzJkOTUyMSwgMHhhZGExMjFmZiwgMHgyOTkwODQxNSwgMHg3ZmJiOTc3ZiwgMHhhZjllYjNkYiwgMHgyOWM5ZWQyYSxcclxuXHRcdCAgMHg1Y2UyYTQ2NSwgMHhhNzMwZjMyYywgMHhkMGFhM2ZlOCwgMHg4YTVjYzA5MSwgMHhkNDllMmNlNywgMHgwY2U0NTRhOSwgMHhkNjBhY2Q4NiwgMHgwMTVmMTkxOSxcclxuXHRcdCAgMHg3NzA3OTEwMywgMHhkZWEwM2FmNiwgMHg3OGE4NTY1ZSwgMHhkZWUzNTZkZiwgMHgyMWYwNWNiZSwgMHg4Yjc1ZTM4NywgMHhiM2M1MDY1MSwgMHhiOGE1YzNlZixcclxuXHRcdCAgMHhkOGVlYjZkMiwgMHhlNTIzYmU3NywgMHhjMjE1NDUyOSwgMHgyZjY5ZWZkZiwgMHhhZmU2N2FmYiwgMHhmNDcwYzRiMiwgMHhmM2UwZWI1YiwgMHhkNmNjOTg3NixcclxuXHRcdCAgMHgzOWU0NDYwYywgMHgxZmRhODUzOCwgMHgxOTg3ODMyZiwgMHhjYTAwNzM2NywgMHhhOTkxNDRmOCwgMHgyOTZiMjk5ZSwgMHg0OTJmYzI5NSwgMHg5MjY2YmVhYixcclxuXHRcdCAgMHhiNTY3NmU2OSwgMHg5YmQzZGRkYSwgMHhkZjdlMDUyZiwgMHhkYjI1NzAxYywgMHgxYjVlNTFlZSwgMHhmNjUzMjRlNiwgMHg2YWZjZTM2YywgMHgwMzE2Y2MwNCxcclxuXHRcdCAgMHg4NjQ0MjEzZSwgMHhiN2RjNTlkMCwgMHg3OTY1MjkxZiwgMHhjY2Q2ZmQ0MywgMHg0MTgyMzk3OSwgMHg5MzJiY2RmNiwgMHhiNjU3YzM0ZCwgMHg0ZWRmZDI4MixcclxuXHRcdCAgMHg3YWU1MjkwYywgMHgzY2I5NTM2YiwgMHg4NTFlMjBmZSwgMHg5ODMzNTU3ZSwgMHgxM2VjZjBiMCwgMHhkM2ZmYjM3MiwgMHgzZjg1YzVjMSwgMHgwYWVmN2VkMik7XHJcblxyXG5cdFx0c0JveFs0XSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHg3ZWM5MGMwNCwgMHgyYzZlNzRiOSwgMHg5YjBlNjZkZiwgMHhhNjMzNzkxMSwgMHhiODZhN2ZmZiwgMHgxZGQzNThmNSwgMHg0NGRkOWQ0NCwgMHgxNzMxMTY3ZixcclxuXHRcdCAgMHgwOGZiZjFmYSwgMHhlN2Y1MTFjYywgMHhkMjA1MWIwMCwgMHg3MzVhYmEwMCwgMHgyYWI3MjJkOCwgMHgzODYzODFjYiwgMHhhY2Y2MjQzYSwgMHg2OWJlZmQ3YSxcclxuXHRcdCAgMHhlNmEyZTc3ZiwgMHhmMGM3MjBjZCwgMHhjNDQ5NDgxNiwgMHhjY2Y1YzE4MCwgMHgzODg1MTY0MCwgMHgxNWIwYTg0OCwgMHhlNjhiMThjYiwgMHg0Y2FhZGVmZixcclxuXHRcdCAgMHg1ZjQ4MGEwMSwgMHgwNDEyYjJhYSwgMHgyNTk4MTRmYywgMHg0MWQwZWZlMiwgMHg0ZTQwYjQ4ZCwgMHgyNDhlYjZmYiwgMHg4ZGJhMWNmZSwgMHg0MWE5OWIwMixcclxuXHRcdCAgMHgxYTU1MGEwNCwgMHhiYThmNjVjYiwgMHg3MjUxZjRlNywgMHg5NWE1MTcyNSwgMHhjMTA2ZWNkNywgMHg5N2E1OTgwYSwgMHhjNTM5YjlhYSwgMHg0ZDc5ZmU2YSxcclxuXHRcdCAgMHhmMmYzZjc2MywgMHg2OGFmODA0MCwgMHhlZDBjOWU1NiwgMHgxMWI0OTU4YiwgMHhlMWViNWE4OCwgMHg4NzA5ZTZiMCwgMHhkN2UwNzE1NiwgMHg0ZTI5ZmVhNyxcclxuXHRcdCAgMHg2MzY2ZTUyZCwgMHgwMmQxYzAwMCwgMHhjNGFjOGUwNSwgMHg5Mzc3ZjU3MSwgMHgwYzA1MzcyYSwgMHg1Nzg1MzVmMiwgMHgyMjYxYmUwMiwgMHhkNjQyYTBjOSxcclxuXHRcdCAgMHhkZjEzYTI4MCwgMHg3NGI1NWJkMiwgMHg2ODIxOTljMCwgMHhkNDIxZTVlYywgMHg1M2ZiM2NlOCwgMHhjOGFkZWRiMywgMHgyOGE4N2ZjOSwgMHgzZDk1OTk4MSxcclxuXHRcdCAgMHg1YzFmZjkwMCwgMHhmZTM4ZDM5OSwgMHgwYzRlZmYwYiwgMHgwNjI0MDdlYSwgMHhhYTJmNGZiMSwgMHg0ZmI5Njk3NiwgMHg5MGM3OTUwNSwgMHhiMGE4YTc3NCxcclxuXHRcdCAgMHhlZjU1YTFmZiwgMHhlNTljYTJjMiwgMHhhNmI2MmQyNywgMHhlNjZhNDI2MywgMHhkZjY1MDAxZiwgMHgwZWM1MDk2NiwgMHhkZmRkNTViYywgMHgyOWRlMDY1NSxcclxuXHRcdCAgMHg5MTFlNzM5YSwgMHgxN2FmODk3NSwgMHgzMmM3OTExYywgMHg4OWY4OTQ2OCwgMHgwZDAxZTk4MCwgMHg1MjQ3NTVmNCwgMHgwM2I2M2NjOSwgMHgwY2M4NDRiMixcclxuXHRcdCAgMHhiY2YzZjBhYSwgMHg4N2FjMzZlOSwgMHhlNTNhNzQyNiwgMHgwMWIzZDgyYiwgMHgxYTllNzQ0OSwgMHg2NGVlMmQ3ZSwgMHhjZGRiYjFkYSwgMHgwMWM5NDkxMCxcclxuXHRcdCAgMHhiODY4YmY4MCwgMHgwZDI2ZjNmZCwgMHg5MzQyZWRlNywgMHgwNGE1YzI4NCwgMHg2MzY3MzdiNiwgMHg1MGY1YjYxNiwgMHhmMjQ3NjZlMywgMHg4ZWNhMzZjMSxcclxuXHRcdCAgMHgxMzZlMDVkYiwgMHhmZWYxODM5MSwgMHhmYjg4N2EzNywgMHhkNmU3ZjdkNCwgMHhjN2ZiN2RjOSwgMHgzMDYzZmNkZiwgMHhiNmY1ODlkZSwgMHhlYzI5NDFkYSxcclxuXHRcdCAgMHgyNmU0NjY5NSwgMHhiNzU2NjQxOSwgMHhmNjU0ZWZjNSwgMHhkMDhkNThiNywgMHg0ODkyNTQwMSwgMHhjMWJhY2I3ZiwgMHhlNWZmNTUwZiwgMHhiNjA4MzA0OSxcclxuXHRcdCAgMHg1YmI1ZDBlOCwgMHg4N2Q3MmU1YSwgMHhhYjZhNmVlMSwgMHgyMjNhNjZjZSwgMHhjNjJiZjNjZCwgMHg5ZTA4ODVmOSwgMHg2OGNiM2U0NywgMHgwODZjMDEwZixcclxuXHRcdCAgMHhhMjFkZTgyMCwgMHhkMThiNjlkZSwgMHhmM2Y2NTc3NywgMHhmYTAyYzNmNiwgMHg0MDdlZGFjMywgMHhjYmIzZDU1MCwgMHgxNzkzMDg0ZCwgMHhiMGQ3MGViYSxcclxuXHRcdCAgMHgwYWIzNzhkNSwgMHhkOTUxZmIwYywgMHhkZWQ3ZGE1NiwgMHg0MTI0YmJlNCwgMHg5NGNhMGI1NiwgMHgwZjU3NTVkMSwgMHhlMGUxZTU2ZSwgMHg2MTg0YjViZSxcclxuXHRcdCAgMHg1ODBhMjQ5ZiwgMHg5NGY3NGJjMCwgMHhlMzI3ODg4ZSwgMHg5ZjdiNTU2MSwgMHhjM2RjMDI4MCwgMHgwNTY4NzcxNSwgMHg2NDZjNmJkNywgMHg0NDkwNGRiMyxcclxuXHRcdCAgMHg2NmI0ZjBhMywgMHhjMGYxNjQ4YSwgMHg2OTdlZDVhZiwgMHg0OWU5MmZmNiwgMHgzMDllMzc0ZiwgMHgyY2I2MzU2YSwgMHg4NTgwODU3MywgMHg0OTkxZjg0MCxcclxuXHRcdCAgMHg3NmYwYWUwMiwgMHgwODNiZTg0ZCwgMHgyODQyMWM5YSwgMHg0NDQ4OTQwNiwgMHg3MzZlNGNiOCwgMHhjMTA5MjkxMCwgMHg4YmM5NWZjNiwgMHg3ZDg2OWNmNCxcclxuXHRcdCAgMHgxMzRmNjE2ZiwgMHgyZTc3MTE4ZCwgMHhiMzFiMmJlMSwgMHhhYTkwYjQ3MiwgMHgzY2E1ZDcxNywgMHg3ZDE2MWJiYSwgMHg5Y2FkOTAxMCwgMHhhZjQ2MmJhMixcclxuXHRcdCAgMHg5ZmU0NTlkMiwgMHg0NWQzNDU1OSwgMHhkOWYyZGExMywgMHhkYmM2NTQ4NywgMHhmM2U0Zjk0ZSwgMHgxNzZkNDg2ZiwgMHgwOTdjMTNlYSwgMHg2MzFkYTVjNyxcclxuXHRcdCAgMHg0NDVmNzM4MiwgMHgxNzU2ODNmNCwgMHhjZGM2NmE5NywgMHg3MGJlMDI4OCwgMHhiM2NkY2Y3MiwgMHg2ZTVkZDJmMywgMHgyMDkzNjA3OSwgMHg0NTliODBhNSxcclxuXHRcdCAgMHhiZTYwZTJkYiwgMHhhOWMyMzEwMSwgMHhlYmE1MzE1YywgMHgyMjRlNDJmMiwgMHgxYzVjMTU3MiwgMHhmNjcyMWIyYywgMHgxYWQyZmZmMywgMHg4YzI1NDA0ZSxcclxuXHRcdCAgMHgzMjRlZDcyZiwgMHg0MDY3YjdmZCwgMHgwNTIzMTM4ZSwgMHg1Y2EzYmM3OCwgMHhkYzBmZDY2ZSwgMHg3NTkyMjI4MywgMHg3ODRkNmIxNywgMHg1OGViYjE2ZSxcclxuXHRcdCAgMHg0NDA5NGY4NSwgMHgzZjQ4MWQ4NywgMHhmY2ZlYWU3YiwgMHg3N2I1ZmY3NiwgMHg4YzIzMDJiZiwgMHhhYWY0NzU1NiwgMHg1ZjQ2YjAyYSwgMHgyYjA5MjgwMSxcclxuXHRcdCAgMHgzZDM4ZjVmNywgMHgwY2E4MWYzNiwgMHg1MmFmNGE4YSwgMHg2NmQ1ZTdjMCwgMHhkZjNiMDg3NCwgMHg5NTA1NTExMCwgMHgxYjVhZDdhOCwgMHhmNjFlZDVhZCxcclxuXHRcdCAgMHg2Y2Y2ZTQ3OSwgMHgyMDc1ODE4NCwgMHhkMGNlZmE2NSwgMHg4OGY3YmU1OCwgMHg0YTA0NjgyNiwgMHgwZmY2ZjhmMywgMHhhMDljN2Y3MCwgMHg1MzQ2YWJhMCxcclxuXHRcdCAgMHg1Y2U5NmMyOCwgMHhlMTc2ZWRhMywgMHg2YmFjMzA3ZiwgMHgzNzY4MjlkMiwgMHg4NTM2MGZhOSwgMHgxN2UzZmUyYSwgMHgyNGI3OTc2NywgMHhmNWE5NmIyMCxcclxuXHRcdCAgMHhkNmNkMjU5NSwgMHg2OGZmMWViZiwgMHg3NTU1NDQyYywgMHhmMTlmMDZiZSwgMHhmOWUwNjU5YSwgMHhlZWI5NDkxZCwgMHgzNDAxMDcxOCwgMHhiYjMwY2FiOCxcclxuXHRcdCAgMHhlODIyZmUxNSwgMHg4ODU3MDk4MywgMHg3NTBlNjI0OSwgMHhkYTYyN2U1NSwgMHg1ZTc2ZmZhOCwgMHhiMTUzNDU0NiwgMHg2ZDQ3ZGUwOCwgMHhlZmU5ZTdkNCk7XHJcblxyXG5cdFx0c0JveFs1XSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHhmNmZhOGY5ZCwgMHgyY2FjNmNlMSwgMHg0Y2EzNDg2NywgMHhlMjMzN2Y3YywgMHg5NWRiMDhlNywgMHgwMTY4NDNiNCwgMHhlY2VkNWNiYywgMHgzMjU1NTNhYyxcclxuXHRcdCAgMHhiZjlmMDk2MCwgMHhkZmExZTJlZCwgMHg4M2YwNTc5ZCwgMHg2M2VkODZiOSwgMHgxYWI2YTZiOCwgMHhkZTVlYmUzOSwgMHhmMzhmZjczMiwgMHg4OTg5YjEzOCxcclxuXHRcdCAgMHgzM2YxNDk2MSwgMHhjMDE5MzdiZCwgMHhmNTA2YzZkYSwgMHhlNDYyNWU3ZSwgMHhhMzA4ZWE5OSwgMHg0ZTIzZTMzYywgMHg3OWNiZDdjYywgMHg0OGExNDM2NyxcclxuXHRcdCAgMHhhMzE0OTYxOSwgMHhmZWM5NGJkNSwgMHhhMTE0MTc0YSwgMHhlYWEwMTg2NiwgMHhhMDg0ZGIyZCwgMHgwOWE4NDg2ZiwgMHhhODg4NjE0YSwgMHgyOTAwYWY5OCxcclxuXHRcdCAgMHgwMTY2NTk5MSwgMHhlMTk5Mjg2MywgMHhjOGYzMGM2MCwgMHgyZTc4ZWYzYywgMHhkMGQ1MTkzMiwgMHhjZjBmZWMxNCwgMHhmN2NhMDdkMiwgMHhkMGE4MjA3MixcclxuXHRcdCAgMHhmZDQxMTk3ZSwgMHg5MzA1YTZiMCwgMHhlODZiZTNkYSwgMHg3NGJlZDNjZCwgMHgzNzJkYTUzYywgMHg0YzdmNDQ0OCwgMHhkYWI1ZDQ0MCwgMHg2ZGJhMGVjMyxcclxuXHRcdCAgMHgwODM5MTlhNywgMHg5ZmJhZWVkOSwgMHg0OWRiY2ZiMCwgMHg0ZTY3MGM1MywgMHg1YzNkOWMwMSwgMHg2NGJkYjk0MSwgMHgyYzBlNjM2YSwgMHhiYTdkZDljZCxcclxuXHRcdCAgMHhlYTZmNzM4OCwgMHhlNzBiYzc2MiwgMHgzNWYyOWFkYiwgMHg1YzRjZGQ4ZCwgMHhmMGQ0OGQ4YywgMHhiODgxNTNlMiwgMHgwOGExOTg2NiwgMHgxYWUyZWFjOCxcclxuXHRcdCAgMHgyODRjYWY4OSwgMHhhYTkyODIyMywgMHg5MzM0YmU1MywgMHgzYjNhMjFiZiwgMHgxNjQzNGJlMywgMHg5YWVhMzkwNiwgMHhlZmU4YzM2ZSwgMHhmODkwY2RkOSxcclxuXHRcdCAgMHg4MDIyNmRhZSwgMHhjMzQwYTRhMywgMHhkZjdlOWMwOSwgMHhhNjk0YTgwNywgMHg1YjdjNWVjYywgMHgyMjFkYjNhNiwgMHg5YTY5YTAyZiwgMHg2ODgxOGE1NCxcclxuXHRcdCAgMHhjZWIyMjk2ZiwgMHg1M2MwODQzYSwgMHhmZTg5MzY1NSwgMHgyNWJmZTY4YSwgMHhiNDYyOGFiYywgMHhjZjIyMmViZiwgMHgyNWFjNmY0OCwgMHhhOWE5OTM4NyxcclxuXHRcdCAgMHg1M2JkZGI2NSwgMHhlNzZmZmJlNywgMHhlOTY3ZmQ3OCwgMHgwYmE5MzU2MywgMHg4ZTM0MmJjMSwgMHhlOGExMWJlOSwgMHg0OTgwNzQwZCwgMHhjODA4N2RmYyxcclxuXHRcdCAgMHg4ZGU0YmY5OSwgMHhhMTExMDFhMCwgMHg3ZmQzNzk3NSwgMHhkYTVhMjZjMCwgMHhlODFmOTk0ZiwgMHg5NTI4Y2Q4OSwgMHhmZDMzOWZlZCwgMHhiODc4MzRiZixcclxuXHRcdCAgMHg1ZjA0NDU2ZCwgMHgyMjI1ODY5OCwgMHhjOWM0YzgzYiwgMHgyZGMxNTZiZSwgMHg0ZjYyOGRhYSwgMHg1N2Y1NWVjNSwgMHhlMjIyMGFiZSwgMHhkMjkxNmViZixcclxuXHRcdCAgMHg0ZWM3NWI5NSwgMHgyNGYyYzNjMCwgMHg0MmQxNWQ5OSwgMHhjZDBkN2ZhMCwgMHg3YjZlMjdmZiwgMHhhOGRjOGFmMCwgMHg3MzQ1YzEwNiwgMHhmNDFlMjMyZixcclxuXHRcdCAgMHgzNTE2MjM4NiwgMHhlNmVhODkyNiwgMHgzMzMzYjA5NCwgMHgxNTdlYzZmMiwgMHgzNzJiNzRhZiwgMHg2OTI1NzNlNCwgMHhlOWE5ZDg0OCwgMHhmMzE2MDI4OSxcclxuXHRcdCAgMHgzYTYyZWYxZCwgMHhhNzg3ZTIzOCwgMHhmM2E1ZjY3NiwgMHg3NDM2NDg1MywgMHgyMDk1MTA2MywgMHg0NTc2Njk4ZCwgMHhiNmZhZDQwNywgMHg1OTJhZjk1MCxcclxuXHRcdCAgMHgzNmY3MzUyMywgMHg0Y2ZiNmU4NywgMHg3ZGE0Y2VjMCwgMHg2YzE1MmRhYSwgMHhjYjAzOTZhOCwgMHhjNTBkZmU1ZCwgMHhmY2Q3MDdhYiwgMHgwOTIxYzQyZixcclxuXHRcdCAgMHg4OWRmZjBiYiwgMHg1ZmUyYmU3OCwgMHg0NDhmNGYzMywgMHg3NTQ2MTNjOSwgMHgyYjA1ZDA4ZCwgMHg0OGI5ZDU4NSwgMHhkYzA0OTQ0MSwgMHhjODA5OGY5YixcclxuXHRcdCAgMHg3ZGVkZTc4NiwgMHhjMzlhMzM3MywgMHg0MjQxMDAwNSwgMHg2YTA5MTc1MSwgMHgwZWYzYzhhNiwgMHg4OTAwNzJkNiwgMHgyODIwNzY4MiwgMHhhOWE5ZjdiZSxcclxuXHRcdCAgMHhiZjMyNjc5ZCwgMHhkNDViNWI3NSwgMHhiMzUzZmQwMCwgMHhjYmIwZTM1OCwgMHg4MzBmMjIwYSwgMHgxZjhmYjIxNCwgMHhkMzcyY2YwOCwgMHhjYzNjNGExMyxcclxuXHRcdCAgMHg4Y2Y2MzE2NiwgMHgwNjFjODdiZSwgMHg4OGM5OGY4OCwgMHg2MDYyZTM5NywgMHg0N2NmOGU3YSwgMHhiNmM4NTI4MywgMHgzY2MyYWNmYiwgMHgzZmMwNjk3NixcclxuXHRcdCAgMHg0ZThmMDI1MiwgMHg2NGQ4MzE0ZCwgMHhkYTM4NzBlMywgMHgxZTY2NTQ1OSwgMHhjMTA5MDhmMCwgMHg1MTMwMjFhNSwgMHg2YzViNjhiNywgMHg4MjJmOGFhMCxcclxuXHRcdCAgMHgzMDA3Y2QzZSwgMHg3NDcxOWVlZiwgMHhkYzg3MjY4MSwgMHgwNzMzNDBkNCwgMHg3ZTQzMmZkOSwgMHgwYzVlYzI0MSwgMHg4ODA5Mjg2YywgMHhmNTkyZDg5MSxcclxuXHRcdCAgMHgwOGE5MzBmNiwgMHg5NTdlZjMwNSwgMHhiN2ZiZmZiZCwgMHhjMjY2ZTk2ZiwgMHg2ZmU0YWM5OCwgMHhiMTczZWNjMCwgMHhiYzYwYjQyYSwgMHg5NTM0OThkYSxcclxuXHRcdCAgMHhmYmExYWUxMiwgMHgyZDRiZDczNiwgMHgwZjI1ZmFhYiwgMHhhNGYzZmNlYiwgMHhlMjk2OTEyMywgMHgyNTdmMGMzZCwgMHg5MzQ4YWY0OSwgMHgzNjE0MDBiYyxcclxuXHRcdCAgMHhlODgxNmY0YSwgMHgzODE0ZjIwMCwgMHhhM2Y5NDA0MywgMHg5YzdhNTRjMiwgMHhiYzcwNGY1NywgMHhkYTQxZTdmOSwgMHhjMjVhZDMzYSwgMHg1NGY0YTA4NCxcclxuXHRcdCAgMHhiMTdmNTUwNSwgMHg1OTM1N2NiZSwgMHhlZGJkMTVjOCwgMHg3Zjk3YzVhYiwgMHhiYTVhYzdiNSwgMHhiNmY2ZGVhZiwgMHgzYTQ3OWMzYSwgMHg1MzAyZGEyNSxcclxuXHRcdCAgMHg2NTNkN2U2YSwgMHg1NDI2OGQ0OSwgMHg1MWE0NzdlYSwgMHg1MDE3ZDU1YiwgMHhkN2QyNWQ4OCwgMHg0NDEzNmM3NiwgMHgwNDA0YThjOCwgMHhiOGU1YTEyMSxcclxuXHRcdCAgMHhiODFhOTI4YSwgMHg2MGVkNTg2OSwgMHg5N2M1NWI5NiwgMHhlYWVjOTkxYiwgMHgyOTkzNTkxMywgMHgwMWZkYjdmMSwgMHgwODhlOGRmYSwgMHg5YWI2ZjZmNSxcclxuXHRcdCAgMHgzYjRjYmY5ZiwgMHg0YTVkZTNhYiwgMHhlNjA1MWQzNSwgMHhhMGUxZDg1NSwgMHhkMzZiNGNmMSwgMHhmNTQ0ZWRlYiwgMHhiMGU5MzUyNCwgMHhiZWJiOGZiZCxcclxuXHRcdCAgMHhhMmQ3NjJjZiwgMHg0OWM5MmY1NCwgMHgzOGI1ZjMzMSwgMHg3MTI4YTQ1NCwgMHg0ODM5MjkwNSwgMHhhNjViMWRiOCwgMHg4NTFjOTdiZCwgMHhkNjc1Y2YyZik7XHJcblxyXG5cdFx0c0JveFs2XSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHg4NWUwNDAxOSwgMHgzMzJiZjU2NywgMHg2NjJkYmZmZiwgMHhjZmM2NTY5MywgMHgyYThkN2Y2ZiwgMHhhYjliYzkxMiwgMHhkZTYwMDhhMSwgMHgyMDI4ZGExZixcclxuXHRcdCAgMHgwMjI3YmNlNywgMHg0ZDY0MjkxNiwgMHgxOGZhYzMwMCwgMHg1MGYxOGI4MiwgMHgyY2IyY2IxMSwgMHhiMjMyZTc1YywgMHg0YjM2OTVmMiwgMHhiMjg3MDdkZSxcclxuXHRcdCAgMHhhMDVmYmNmNiwgMHhjZDQxODFlOSwgMHhlMTUwMjEwYywgMHhlMjRlZjFiZCwgMHhiMTY4YzM4MSwgMHhmZGU0ZTc4OSwgMHg1Yzc5YjBkOCwgMHgxZThiZmQ0MyxcclxuXHRcdCAgMHg0ZDQ5NTAwMSwgMHgzOGJlNDM0MSwgMHg5MTNjZWUxZCwgMHg5MmE3OWMzZiwgMHgwODk3NjZiZSwgMHhiYWVlYWRmNCwgMHgxMjg2YmVjZiwgMHhiNmVhY2IxOSxcclxuXHRcdCAgMHgyNjYwYzIwMCwgMHg3NTY1YmRlNCwgMHg2NDI0MWY3YSwgMHg4MjQ4ZGNhOSwgMHhjM2IzYWQ2NiwgMHgyODEzNjA4NiwgMHgwYmQ4ZGZhOCwgMHgzNTZkMWNmMixcclxuXHRcdCAgMHgxMDc3ODliZSwgMHhiM2IyZTljZSwgMHgwNTAyYWE4ZiwgMHgwYmMwMzUxZSwgMHgxNjZiZjUyYSwgMHhlYjEyZmY4MiwgMHhlMzQ4NjkxMSwgMHhkMzRkNzUxNixcclxuXHRcdCAgMHg0ZTdiM2FmZiwgMHg1ZjQzNjcxYiwgMHg5Y2Y2ZTAzNywgMHg0OTgxYWM4MywgMHgzMzQyNjZjZSwgMHg4YzkzNDFiNywgMHhkMGQ4NTRjMCwgMHhjYjNhNmM4OCxcclxuXHRcdCAgMHg0N2JjMjgyOSwgMHg0NzI1YmEzNywgMHhhNjZhZDIyYiwgMHg3YWQ2MWYxZSwgMHgwYzVjYmFmYSwgMHg0NDM3ZjEwNywgMHhiNmU3OTk2MiwgMHg0MmQyZDgxNixcclxuXHRcdCAgMHgwYTk2MTI4OCwgMHhlMWE1YzA2ZSwgMHgxMzc0OWU2NywgMHg3MmZjMDgxYSwgMHhiMWQxMzlmNywgMHhmOTU4Mzc0NSwgMHhjZjE5ZGY1OCwgMHhiZWMzZjc1NixcclxuXHRcdCAgMHhjMDZlYmEzMCwgMHgwNzIxMWIyNCwgMHg0NWMyODgyOSwgMHhjOTVlMzE3ZiwgMHhiYzhlYzUxMSwgMHgzOGJjNDZlOSwgMHhjNmU2ZmExNCwgMHhiYWU4NTg0YSxcclxuXHRcdCAgMHhhZDRlYmM0NiwgMHg0NjhmNTA4YiwgMHg3ODI5NDM1ZiwgMHhmMTI0MTgzYiwgMHg4MjFkYmE5ZiwgMHhhZmY2MGZmNCwgMHhlYTJjNGU2ZCwgMHgxNmUzOTI2NCxcclxuXHRcdCAgMHg5MjU0NGE4YiwgMHgwMDliNGZjMywgMHhhYmE2OGNlZCwgMHg5YWM5NmY3OCwgMHgwNmE1Yjc5YSwgMHhiMjg1NmU2ZSwgMHgxYWVjM2NhOSwgMHhiZTgzODY4OCxcclxuXHRcdCAgMHgwZTA4MDRlOSwgMHg1NWYxYmU1NiwgMHhlN2U1MzYzYiwgMHhiM2ExZjI1ZCwgMHhmN2RlYmI4NSwgMHg2MWZlMDMzYywgMHgxNjc0NjIzMywgMHgzYzAzNGMyOCxcclxuXHRcdCAgMHhkYTZkMGM3NCwgMHg3OWFhYzU2YywgMHgzY2U0ZTFhZCwgMHg1MWYwYzgwMiwgMHg5OGY4ZjM1YSwgMHgxNjI2YTQ5ZiwgMHhlZWQ4MmIyOSwgMHgxZDM4MmZlMyxcclxuXHRcdCAgMHgwYzRmYjk5YSwgMHhiYjMyNTc3OCwgMHgzZWM2ZDk3YiwgMHg2ZTc3YTZhOSwgMHhjYjY1OGI1YywgMHhkNDUyMzBjNywgMHgyYmQxNDA4YiwgMHg2MGMwM2ViNyxcclxuXHRcdCAgMHhiOTA2OGQ3OCwgMHhhMzM3NTRmNCwgMHhmNDMwYzg3ZCwgMHhjOGE3MTMwMiwgMHhiOTZkOGMzMiwgMHhlYmQ0ZTdiZSwgMHhiZThiOWQyZCwgMHg3OTc5ZmIwNixcclxuXHRcdCAgMHhlNzIyNTMwOCwgMHg4Yjc1Y2Y3NywgMHgxMWVmOGRhNCwgMHhlMDgzYzg1OCwgMHg4ZDZiNzg2ZiwgMHg1YTYzMTdhNiwgMHhmYTVjZjdhMCwgMHg1ZGRhMDAzMyxcclxuXHRcdCAgMHhmMjhlYmZiMCwgMHhmNWI5YzMxMCwgMHhhMGVhYzI4MCwgMHgwOGI5NzY3YSwgMHhhM2Q5ZDJiMCwgMHg3OWQzNDIxNywgMHgwMjFhNzE4ZCwgMHg5YWM2MzM2YSxcclxuXHRcdCAgMHgyNzExZmQ2MCwgMHg0MzgwNTBlMywgMHgwNjk5MDhhOCwgMHgzZDdmZWRjNCwgMHg4MjZkMmJlZiwgMHg0ZWViODQ3NiwgMHg0ODhkY2YyNSwgMHgzNmM5ZDU2NixcclxuXHRcdCAgMHgyOGU3NGU0MSwgMHhjMjYxMGFjYSwgMHgzZDQ5YTljZiwgMHhiYWUzYjlkZiwgMHhiNjVmOGRlNiwgMHg5MmFlYWY2NCwgMHgzYWM3ZDVlNiwgMHg5ZWE4MDUwOSxcclxuXHRcdCAgMHhmMjJiMDE3ZCwgMHhhNDE3M2Y3MCwgMHhkZDFlMTZjMywgMHgxNWUwZDdmOSwgMHg1MGIxYjg4NywgMHgyYjlmNGZkNSwgMHg2MjVhYmE4MiwgMHg2YTAxNzk2MixcclxuXHRcdCAgMHgyZWMwMWI5YywgMHgxNTQ4OGFhOSwgMHhkNzE2ZTc0MCwgMHg0MDA1NWEyYywgMHg5M2QyOWEyMiwgMHhlMzJkYmY5YSwgMHgwNTg3NDViOSwgMHgzNDUzZGMxZSxcclxuXHRcdCAgMHhkNjk5Mjk2ZSwgMHg0OTZjZmY2ZiwgMHgxYzlmNDk4NiwgMHhkZmUyZWQwNywgMHhiODcyNDJkMSwgMHgxOWRlN2VhZSwgMHgwNTNlNTYxYSwgMHgxNWFkNmY4YyxcclxuXHRcdCAgMHg2NjYyNmMxYywgMHg3MTU0YzI0YywgMHhlYTA4MmIyYSwgMHg5M2ViMjkzOSwgMHgxN2RjYjBmMCwgMHg1OGQ0ZjJhZSwgMHg5ZWEyOTRmYiwgMHg1MmNmNTY0YyxcclxuXHRcdCAgMHg5ODgzZmU2NiwgMHgyZWM0MDU4MSwgMHg3NjM5NTNjMywgMHgwMWQ2NjkyZSwgMHhkM2EwYzEwOCwgMHhhMWU3MTYwZSwgMHhlNGYyZGZhNiwgMHg2OTNlZDI4NSxcclxuXHRcdCAgMHg3NDkwNDY5OCwgMHg0YzJiMGVkZCwgMHg0Zjc1NzY1NiwgMHg1ZDM5MzM3OCwgMHhhMTMyMjM0ZiwgMHgzZDMyMWM1ZCwgMHhjM2Y1ZTE5NCwgMHg0YjI2OTMwMSxcclxuXHRcdCAgMHhjNzlmMDIyZiwgMHgzYzk5N2U3ZSwgMHg1ZTRmOTUwNCwgMHgzZmZhZmJiZCwgMHg3NmY3YWQwZSwgMHgyOTY2OTNmNCwgMHgzZDFmY2U2ZiwgMHhjNjFlNDViZSxcclxuXHRcdCAgMHhkM2I1YWIzNCwgMHhmNzJiZjliNywgMHgxYjA0MzRjMCwgMHg0ZTcyYjU2NywgMHg1NTkyYTMzZCwgMHhiNTIyOTMwMSwgMHhjZmQyYTg3ZiwgMHg2MGFlYjc2NyxcclxuXHRcdCAgMHgxODE0Mzg2YiwgMHgzMGJjYzMzZCwgMHgzOGEwYzA3ZCwgMHhmZDE2MDZmMiwgMHhjMzYzNTE5YiwgMHg1ODlkZDM5MCwgMHg1NDc5ZjhlNiwgMHgxY2I4ZDY0NyxcclxuXHRcdCAgMHg5N2ZkNjFhOSwgMHhlYTc3NTlmNCwgMHgyZDU3NTM5ZCwgMHg1NjlhNThjZiwgMHhlODRlNjNhZCwgMHg0NjJlMWI3OCwgMHg2NTgwZjg3ZSwgMHhmMzgxNzkxNCxcclxuXHRcdCAgMHg5MWRhNTVmNCwgMHg0MGEyMzBmMywgMHhkMTk4OGYzNSwgMHhiNmUzMThkMiwgMHgzZmZhNTBiYywgMHgzZDQwZjAyMSwgMHhjM2MwYmRhZSwgMHg0OTU4YzI0YyxcclxuXHRcdCAgMHg1MThmMzZiMiwgMHg4NGIxZDM3MCwgMHgwZmVkY2U4MywgMHg4NzhkZGFkYSwgMHhmMmEyNzljNywgMHg5NGUwMWJlOCwgMHg5MDcxNmY0YiwgMHg5NTRiOGFhMyk7XHJcblxyXG5cdFx0c0JveFs3XSA9IG5ldyBBcnJheShcclxuXHRcdCAgMHhlMjE2MzAwZCwgMHhiYmRkZmZmYywgMHhhN2ViZGFiZCwgMHgzNTY0ODA5NSwgMHg3Nzg5ZjhiNywgMHhlNmMxMTIxYiwgMHgwZTI0MTYwMCwgMHgwNTJjZThiNSxcclxuXHRcdCAgMHgxMWE5Y2ZiMCwgMHhlNTk1MmYxMSwgMHhlY2U3OTkwYSwgMHg5Mzg2ZDE3NCwgMHgyYTQyOTMxYywgMHg3NmUzODExMSwgMHhiMTJkZWYzYSwgMHgzN2RkZGRmYyxcclxuXHRcdCAgMHhkZTlhZGViMSwgMHgwYTBjYzMyYywgMHhiZTE5NzAyOSwgMHg4NGEwMDk0MCwgMHhiYjI0M2EwZiwgMHhiNGQxMzdjZiwgMHhiNDRlNzlmMCwgMHgwNDllZWRmZCxcclxuXHRcdCAgMHgwYjE1YTE1ZCwgMHg0ODBkMzE2OCwgMHg4YmJiZGU1YSwgMHg2NjlkZWQ0MiwgMHhjN2VjZTgzMSwgMHgzZjhmOTVlNywgMHg3MmRmMTkxYiwgMHg3NTgwMzMwZCxcclxuXHRcdCAgMHg5NDA3NDI1MSwgMHg1YzdkY2RmYSwgMHhhYmJlNmQ2MywgMHhhYTQwMjE2NCwgMHhiMzAxZDQwYSwgMHgwMmU3ZDFjYSwgMHg1MzU3MWRhZSwgMHg3YTMxODJhMixcclxuXHRcdCAgMHgxMmE4ZGRlYywgMHhmZGFhMzM1ZCwgMHgxNzZmNDNlOCwgMHg3MWZiNDZkNCwgMHgzODEyOTAyMiwgMHhjZTk0OWFkNCwgMHhiODQ3NjlhZCwgMHg5NjViZDg2MixcclxuXHRcdCAgMHg4MmYzZDA1NSwgMHg2NmZiOTc2NywgMHgxNWI4MGI0ZSwgMHgxZDViNDdhMCwgMHg0Y2ZkZTA2ZiwgMHhjMjhlYzRiOCwgMHg1N2U4NzI2ZSwgMHg2NDdhNzhmYyxcclxuXHRcdCAgMHg5OTg2NWQ0NCwgMHg2MDhiZDU5MywgMHg2YzIwMGUwMywgMHgzOWRjNWZmNiwgMHg1ZDBiMDBhMywgMHhhZTYzYWZmMiwgMHg3ZThiZDYzMiwgMHg3MDEwOGMwYyxcclxuXHRcdCAgMHhiYmQzNTA0OSwgMHgyOTk4ZGYwNCwgMHg5ODBjZjQyYSwgMHg5YjZkZjQ5MSwgMHg5ZTdlZGQ1MywgMHgwNjkxODU0OCwgMHg1OGNiN2UwNywgMHgzYjc0ZWYyZSxcclxuXHRcdCAgMHg1MjJmZmZiMSwgMHhkMjQ3MDhjYywgMHgxYzdlMjdjZCwgMHhhNGViMjE1YiwgMHgzY2YxZDJlMiwgMHgxOWI0N2EzOCwgMHg0MjRmNzYxOCwgMHgzNTg1NjAzOSxcclxuXHRcdCAgMHg5ZDE3ZGVlNywgMHgyN2ViMzVlNiwgMHhjOWFmZjY3YiwgMHgzNmJhZjViOCwgMHgwOWM0NjdjZCwgMHhjMTg5MTBiMSwgMHhlMTFkYmY3YiwgMHgwNmNkMWFmOCxcclxuXHRcdCAgMHg3MTcwYzYwOCwgMHgyZDVlMzM1NCwgMHhkNGRlNDk1YSwgMHg2NGM2ZDAwNiwgMHhiY2MwYzYyYywgMHgzZGQwMGRiMywgMHg3MDhmOGYzNCwgMHg3N2Q1MWI0MixcclxuXHRcdCAgMHgyNjRmNjIwZiwgMHgyNGI4ZDJiZiwgMHgxNWMxYjc5ZSwgMHg0NmE1MjU2NCwgMHhmOGQ3ZTU0ZSwgMHgzZTM3ODE2MCwgMHg3ODk1Y2RhNSwgMHg4NTljMTVhNSxcclxuXHRcdCAgMHhlNjQ1OTc4OCwgMHhjMzdiYzc1ZiwgMHhkYjA3YmEwYywgMHgwNjc2YTNhYiwgMHg3ZjIyOWIxZSwgMHgzMTg0MmU3YiwgMHgyNDI1OWZkNywgMHhmOGJlZjQ3MixcclxuXHRcdCAgMHg4MzVmZmNiOCwgMHg2ZGY0YzFmMiwgMHg5NmY1YjE5NSwgMHhmZDBhZjBmYywgMHhiMGZlMTM0YywgMHhlMjUwNmQzZCwgMHg0ZjliMTJlYSwgMHhmMjE1ZjIyNSxcclxuXHRcdCAgMHhhMjIzNzM2ZiwgMHg5ZmI0YzQyOCwgMHgyNWQwNDk3OSwgMHgzNGM3MTNmOCwgMHhjNDYxODE4NywgMHhlYTdhNmU5OCwgMHg3Y2QxNmVmYywgMHgxNDM2ODc2YyxcclxuXHRcdCAgMHhmMTU0NDEwNywgMHhiZWRlZWUxNCwgMHg1NmU5YWYyNywgMHhhMDRhYTQ0MSwgMHgzY2Y3Yzg5OSwgMHg5MmVjYmFlNiwgMHhkZDY3MDE2ZCwgMHgxNTE2ODJlYixcclxuXHRcdCAgMHhhODQyZWVkZiwgMHhmZGJhNjBiNCwgMHhmMTkwN2I3NSwgMHgyMGUzMDMwZiwgMHgyNGQ4YzI5ZSwgMHhlMTM5NjczYiwgMHhlZmE2M2ZiOCwgMHg3MTg3MzA1NCxcclxuXHRcdCAgMHhiNmYyY2YzYiwgMHg5ZjMyNjQ0MiwgMHhjYjE1YTRjYywgMHhiMDFhNDUwNCwgMHhmMWU0N2Q4ZCwgMHg4NDRhMWJlNSwgMHhiYWU3ZGZkYywgMHg0MmNiZGE3MCxcclxuXHRcdCAgMHhjZDdkYWUwYSwgMHg1N2U4NWI3YSwgMHhkNTNmNWFmNiwgMHgyMGNmNGQ4YywgMHhjZWE0ZDQyOCwgMHg3OWQxMzBhNCwgMHgzNDg2ZWJmYiwgMHgzM2QzY2RkYyxcclxuXHRcdCAgMHg3Nzg1M2I1MywgMHgzN2VmZmNiNSwgMHhjNTA2ODc3OCwgMHhlNTgwYjNlNiwgMHg0ZTY4YjhmNCwgMHhjNWM4YjM3ZSwgMHgwZDgwOWVhMiwgMHgzOThmZWI3YyxcclxuXHRcdCAgMHgxMzJhNGY5NCwgMHg0M2I3OTUwZSwgMHgyZmVlN2QxYywgMHgyMjM2MTNiZCwgMHhkZDA2Y2FhMiwgMHgzN2RmOTMyYiwgMHhjNDI0ODI4OSwgMHhhY2YzZWJjMyxcclxuXHRcdCAgMHg1NzE1ZjZiNywgMHhlZjM0NzhkZCwgMHhmMjY3NjE2ZiwgMHhjMTQ4Y2JlNCwgMHg5MDUyODE1ZSwgMHg1ZTQxMGZhYiwgMHhiNDhhMjQ2NSwgMHgyZWRhN2ZhNCxcclxuXHRcdCAgMHhlODdiNDBlNCwgMHhlOThlYTA4NCwgMHg1ODg5ZTllMSwgMHhlZmQzOTBmYywgMHhkZDA3ZDM1YiwgMHhkYjQ4NTY5NCwgMHgzOGQ3ZTViMiwgMHg1NzcyMDEwMSxcclxuXHRcdCAgMHg3MzBlZGViYywgMHg1YjY0MzExMywgMHg5NDkxN2U0ZiwgMHg1MDNjMmZiYSwgMHg2NDZmMTI4MiwgMHg3NTIzZDI0YSwgMHhlMDc3OTY5NSwgMHhmOWMxN2E4ZixcclxuXHRcdCAgMHg3YTViMjEyMSwgMHhkMTg3Yjg5NiwgMHgyOTI2M2E0ZCwgMHhiYTUxMGNkZiwgMHg4MWY0N2M5ZiwgMHhhZDExNjNlZCwgMHhlYTdiNTk2NSwgMHgxYTAwNzI2ZSxcclxuXHRcdCAgMHgxMTQwMzA5MiwgMHgwMGRhNmQ3NywgMHg0YTBjZGQ2MSwgMHhhZDFmNDYwMywgMHg2MDViZGZiMCwgMHg5ZWVkYzM2NCwgMHgyMmViZTZhOCwgMHhjZWU3ZDI4YSxcclxuXHRcdCAgMHhhMGU3MzZhMCwgMHg1NTY0YTZiOSwgMHgxMDg1MzIwOSwgMHhjN2ViOGYzNywgMHgyZGU3MDVjYSwgMHg4OTUxNTcwZiwgMHhkZjA5ODIyYiwgMHhiZDY5MWE2YyxcclxuXHRcdCAgMHhhYTEyZTRmMiwgMHg4NzQ1MWMwZiwgMHhlMGY2YTI3YSwgMHgzYWRhNDgxOSwgMHg0Y2YxNzY0ZiwgMHgwZDc3MWMyYiwgMHg2N2NkYjE1NiwgMHgzNTBkODM4NCxcclxuXHRcdCAgMHg1OTM4ZmEwZiwgMHg0MjM5OWVmMywgMHgzNjk5N2IwNywgMHgwZTg0MDkzZCwgMHg0YWE5M2U2MSwgMHg4MzYwZDg3YiwgMHgxZmE5OGIwYywgMHgxMTQ5MzgyYyxcclxuXHRcdCAgMHhlOTc2MjVhNSwgMHgwNjE0ZDFiNywgMHgwZTI1MjQ0YiwgMHgwYzc2ODM0NywgMHg1ODllOGQ4MiwgMHgwZDIwNTlkMSwgMHhhNDY2YmIxZSwgMHhmOGRhMGE4MixcclxuXHRcdCAgMHgwNGYxOTEzMCwgMHhiYTZlNGVjMCwgMHg5OTI2NTE2NCwgMHgxZWU3MjMwZCwgMHg1MGIyYWQ4MCwgMHhlYWVlNjgwMSwgMHg4ZGIyYTI4MywgMHhlYThiZjU5ZSk7XHJcblxyXG59O1xyXG5cclxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XHJcblxyXG5mdW5jdGlvbiBjYXN0NShrZXkpIHtcclxuXHR0aGlzLmNhc3Q1ID0gbmV3IG9wZW5wZ3Bfc3ltZW5jX2Nhc3Q1KCk7XHJcblx0dGhpcy5jYXN0NS5zZXRLZXkodXRpbC5zdHIyYmluKGtleSkpO1xyXG5cclxuXHR0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihibG9jaykge1xyXG5cdFx0cmV0dXJuIHRoaXMuY2FzdDUuZW5jcnlwdChibG9jayk7XHJcblx0fVxyXG59XHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGNhc3Q1O1xyXG5tb2R1bGUuZXhwb3J0cy5ibG9ja1NpemUgPSBjYXN0NS5wcm90b3R5cGUuYmxvY2tTaXplID0gODtcclxubW9kdWxlLmV4cG9ydHMua2V5U2l6ZSA9IGNhc3Q1LnByb3RvdHlwZS5rZXlTaXplID0gMTY7XHJcbiIsIi8vUGF1bCBUZXJvLCBKdWx5IDIwMDFcbi8vaHR0cDovL3d3dy50ZXJvLmNvLnVrL2Rlcy9cbi8vXG4vL09wdGltaXNlZCBmb3IgcGVyZm9ybWFuY2Ugd2l0aCBsYXJnZSBibG9ja3MgYnkgTWljaGFlbCBIYXl3b3J0aCwgTm92ZW1iZXIgMjAwMVxuLy9odHRwOi8vd3d3Lm5ldGRlYWxpbmcuY29tXG4vL1xuLy8gTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIXG5cbi8vVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EXG4vL0FOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuLy9JTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRVxuLy9BUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRVxuLy9GT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTFxuLy9EQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EU1xuLy9PUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTilcbi8vSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1Rcbi8vTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWVxuLy9PVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GXG4vL1NVQ0ggREFNQUdFLlxuXG4vL2Rlc1xuLy90aGlzIHRha2VzIHRoZSBrZXksIHRoZSBtZXNzYWdlLCBhbmQgd2hldGhlciB0byBlbmNyeXB0IG9yIGRlY3J5cHRcblxuXG5cblxuZnVuY3Rpb24gZGVzIChrZXlzLCBtZXNzYWdlLCBlbmNyeXB0LCBtb2RlLCBpdiwgcGFkZGluZykge1xuICAvL2RlY2xhcmluZyB0aGlzIGxvY2FsbHkgc3BlZWRzIHRoaW5ncyB1cCBhIGJpdFxuICB2YXIgc3BmdW5jdGlvbjEgPSBuZXcgQXJyYXkgKDB4MTAxMDQwMCwwLDB4MTAwMDAsMHgxMDEwNDA0LDB4MTAxMDAwNCwweDEwNDA0LDB4NCwweDEwMDAwLDB4NDAwLDB4MTAxMDQwMCwweDEwMTA0MDQsMHg0MDAsMHgxMDAwNDA0LDB4MTAxMDAwNCwweDEwMDAwMDAsMHg0LDB4NDA0LDB4MTAwMDQwMCwweDEwMDA0MDAsMHgxMDQwMCwweDEwNDAwLDB4MTAxMDAwMCwweDEwMTAwMDAsMHgxMDAwNDA0LDB4MTAwMDQsMHgxMDAwMDA0LDB4MTAwMDAwNCwweDEwMDA0LDAsMHg0MDQsMHgxMDQwNCwweDEwMDAwMDAsMHgxMDAwMCwweDEwMTA0MDQsMHg0LDB4MTAxMDAwMCwweDEwMTA0MDAsMHgxMDAwMDAwLDB4MTAwMDAwMCwweDQwMCwweDEwMTAwMDQsMHgxMDAwMCwweDEwNDAwLDB4MTAwMDAwNCwweDQwMCwweDQsMHgxMDAwNDA0LDB4MTA0MDQsMHgxMDEwNDA0LDB4MTAwMDQsMHgxMDEwMDAwLDB4MTAwMDQwNCwweDEwMDAwMDQsMHg0MDQsMHgxMDQwNCwweDEwMTA0MDAsMHg0MDQsMHgxMDAwNDAwLDB4MTAwMDQwMCwwLDB4MTAwMDQsMHgxMDQwMCwwLDB4MTAxMDAwNCk7XG4gIHZhciBzcGZ1bmN0aW9uMiA9IG5ldyBBcnJheSAoLTB4N2ZlZjdmZTAsLTB4N2ZmZjgwMDAsMHg4MDAwLDB4MTA4MDIwLDB4MTAwMDAwLDB4MjAsLTB4N2ZlZmZmZTAsLTB4N2ZmZjdmZTAsLTB4N2ZmZmZmZTAsLTB4N2ZlZjdmZTAsLTB4N2ZlZjgwMDAsLTB4ODAwMDAwMDAsLTB4N2ZmZjgwMDAsMHgxMDAwMDAsMHgyMCwtMHg3ZmVmZmZlMCwweDEwODAwMCwweDEwMDAyMCwtMHg3ZmZmN2ZlMCwwLC0weDgwMDAwMDAwLDB4ODAwMCwweDEwODAyMCwtMHg3ZmYwMDAwMCwweDEwMDAyMCwtMHg3ZmZmZmZlMCwwLDB4MTA4MDAwLDB4ODAyMCwtMHg3ZmVmODAwMCwtMHg3ZmYwMDAwMCwweDgwMjAsMCwweDEwODAyMCwtMHg3ZmVmZmZlMCwweDEwMDAwMCwtMHg3ZmZmN2ZlMCwtMHg3ZmYwMDAwMCwtMHg3ZmVmODAwMCwweDgwMDAsLTB4N2ZmMDAwMDAsLTB4N2ZmZjgwMDAsMHgyMCwtMHg3ZmVmN2ZlMCwweDEwODAyMCwweDIwLDB4ODAwMCwtMHg4MDAwMDAwMCwweDgwMjAsLTB4N2ZlZjgwMDAsMHgxMDAwMDAsLTB4N2ZmZmZmZTAsMHgxMDAwMjAsLTB4N2ZmZjdmZTAsLTB4N2ZmZmZmZTAsMHgxMDAwMjAsMHgxMDgwMDAsMCwtMHg3ZmZmODAwMCwweDgwMjAsLTB4ODAwMDAwMDAsLTB4N2ZlZmZmZTAsLTB4N2ZlZjdmZTAsMHgxMDgwMDApO1xuICB2YXIgc3BmdW5jdGlvbjMgPSBuZXcgQXJyYXkgKDB4MjA4LDB4ODAyMDIwMCwwLDB4ODAyMDAwOCwweDgwMDAyMDAsMCwweDIwMjA4LDB4ODAwMDIwMCwweDIwMDA4LDB4ODAwMDAwOCwweDgwMDAwMDgsMHgyMDAwMCwweDgwMjAyMDgsMHgyMDAwOCwweDgwMjAwMDAsMHgyMDgsMHg4MDAwMDAwLDB4OCwweDgwMjAyMDAsMHgyMDAsMHgyMDIwMCwweDgwMjAwMDAsMHg4MDIwMDA4LDB4MjAyMDgsMHg4MDAwMjA4LDB4MjAyMDAsMHgyMDAwMCwweDgwMDAyMDgsMHg4LDB4ODAyMDIwOCwweDIwMCwweDgwMDAwMDAsMHg4MDIwMjAwLDB4ODAwMDAwMCwweDIwMDA4LDB4MjA4LDB4MjAwMDAsMHg4MDIwMjAwLDB4ODAwMDIwMCwwLDB4MjAwLDB4MjAwMDgsMHg4MDIwMjA4LDB4ODAwMDIwMCwweDgwMDAwMDgsMHgyMDAsMCwweDgwMjAwMDgsMHg4MDAwMjA4LDB4MjAwMDAsMHg4MDAwMDAwLDB4ODAyMDIwOCwweDgsMHgyMDIwOCwweDIwMjAwLDB4ODAwMDAwOCwweDgwMjAwMDAsMHg4MDAwMjA4LDB4MjA4LDB4ODAyMDAwMCwweDIwMjA4LDB4OCwweDgwMjAwMDgsMHgyMDIwMCk7XG4gIHZhciBzcGZ1bmN0aW9uNCA9IG5ldyBBcnJheSAoMHg4MDIwMDEsMHgyMDgxLDB4MjA4MSwweDgwLDB4ODAyMDgwLDB4ODAwMDgxLDB4ODAwMDAxLDB4MjAwMSwwLDB4ODAyMDAwLDB4ODAyMDAwLDB4ODAyMDgxLDB4ODEsMCwweDgwMDA4MCwweDgwMDAwMSwweDEsMHgyMDAwLDB4ODAwMDAwLDB4ODAyMDAxLDB4ODAsMHg4MDAwMDAsMHgyMDAxLDB4MjA4MCwweDgwMDA4MSwweDEsMHgyMDgwLDB4ODAwMDgwLDB4MjAwMCwweDgwMjA4MCwweDgwMjA4MSwweDgxLDB4ODAwMDgwLDB4ODAwMDAxLDB4ODAyMDAwLDB4ODAyMDgxLDB4ODEsMCwwLDB4ODAyMDAwLDB4MjA4MCwweDgwMDA4MCwweDgwMDA4MSwweDEsMHg4MDIwMDEsMHgyMDgxLDB4MjA4MSwweDgwLDB4ODAyMDgxLDB4ODEsMHgxLDB4MjAwMCwweDgwMDAwMSwweDIwMDEsMHg4MDIwODAsMHg4MDAwODEsMHgyMDAxLDB4MjA4MCwweDgwMDAwMCwweDgwMjAwMSwweDgwLDB4ODAwMDAwLDB4MjAwMCwweDgwMjA4MCk7XG4gIHZhciBzcGZ1bmN0aW9uNSA9IG5ldyBBcnJheSAoMHgxMDAsMHgyMDgwMTAwLDB4MjA4MDAwMCwweDQyMDAwMTAwLDB4ODAwMDAsMHgxMDAsMHg0MDAwMDAwMCwweDIwODAwMDAsMHg0MDA4MDEwMCwweDgwMDAwLDB4MjAwMDEwMCwweDQwMDgwMTAwLDB4NDIwMDAxMDAsMHg0MjA4MDAwMCwweDgwMTAwLDB4NDAwMDAwMDAsMHgyMDAwMDAwLDB4NDAwODAwMDAsMHg0MDA4MDAwMCwwLDB4NDAwMDAxMDAsMHg0MjA4MDEwMCwweDQyMDgwMTAwLDB4MjAwMDEwMCwweDQyMDgwMDAwLDB4NDAwMDAxMDAsMCwweDQyMDAwMDAwLDB4MjA4MDEwMCwweDIwMDAwMDAsMHg0MjAwMDAwMCwweDgwMTAwLDB4ODAwMDAsMHg0MjAwMDEwMCwweDEwMCwweDIwMDAwMDAsMHg0MDAwMDAwMCwweDIwODAwMDAsMHg0MjAwMDEwMCwweDQwMDgwMTAwLDB4MjAwMDEwMCwweDQwMDAwMDAwLDB4NDIwODAwMDAsMHgyMDgwMTAwLDB4NDAwODAxMDAsMHgxMDAsMHgyMDAwMDAwLDB4NDIwODAwMDAsMHg0MjA4MDEwMCwweDgwMTAwLDB4NDIwMDAwMDAsMHg0MjA4MDEwMCwweDIwODAwMDAsMCwweDQwMDgwMDAwLDB4NDIwMDAwMDAsMHg4MDEwMCwweDIwMDAxMDAsMHg0MDAwMDEwMCwweDgwMDAwLDAsMHg0MDA4MDAwMCwweDIwODAxMDAsMHg0MDAwMDEwMCk7XG4gIHZhciBzcGZ1bmN0aW9uNiA9IG5ldyBBcnJheSAoMHgyMDAwMDAxMCwweDIwNDAwMDAwLDB4NDAwMCwweDIwNDA0MDEwLDB4MjA0MDAwMDAsMHgxMCwweDIwNDA0MDEwLDB4NDAwMDAwLDB4MjAwMDQwMDAsMHg0MDQwMTAsMHg0MDAwMDAsMHgyMDAwMDAxMCwweDQwMDAxMCwweDIwMDA0MDAwLDB4MjAwMDAwMDAsMHg0MDEwLDAsMHg0MDAwMTAsMHgyMDAwNDAxMCwweDQwMDAsMHg0MDQwMDAsMHgyMDAwNDAxMCwweDEwLDB4MjA0MDAwMTAsMHgyMDQwMDAxMCwwLDB4NDA0MDEwLDB4MjA0MDQwMDAsMHg0MDEwLDB4NDA0MDAwLDB4MjA0MDQwMDAsMHgyMDAwMDAwMCwweDIwMDA0MDAwLDB4MTAsMHgyMDQwMDAxMCwweDQwNDAwMCwweDIwNDA0MDEwLDB4NDAwMDAwLDB4NDAxMCwweDIwMDAwMDEwLDB4NDAwMDAwLDB4MjAwMDQwMDAsMHgyMDAwMDAwMCwweDQwMTAsMHgyMDAwMDAxMCwweDIwNDA0MDEwLDB4NDA0MDAwLDB4MjA0MDAwMDAsMHg0MDQwMTAsMHgyMDQwNDAwMCwwLDB4MjA0MDAwMTAsMHgxMCwweDQwMDAsMHgyMDQwMDAwMCwweDQwNDAxMCwweDQwMDAsMHg0MDAwMTAsMHgyMDAwNDAxMCwwLDB4MjA0MDQwMDAsMHgyMDAwMDAwMCwweDQwMDAxMCwweDIwMDA0MDEwKTtcbiAgdmFyIHNwZnVuY3Rpb243ID0gbmV3IEFycmF5ICgweDIwMDAwMCwweDQyMDAwMDIsMHg0MDAwODAyLDAsMHg4MDAsMHg0MDAwODAyLDB4MjAwODAyLDB4NDIwMDgwMCwweDQyMDA4MDIsMHgyMDAwMDAsMCwweDQwMDAwMDIsMHgyLDB4NDAwMDAwMCwweDQyMDAwMDIsMHg4MDIsMHg0MDAwODAwLDB4MjAwODAyLDB4MjAwMDAyLDB4NDAwMDgwMCwweDQwMDAwMDIsMHg0MjAwMDAwLDB4NDIwMDgwMCwweDIwMDAwMiwweDQyMDAwMDAsMHg4MDAsMHg4MDIsMHg0MjAwODAyLDB4MjAwODAwLDB4MiwweDQwMDAwMDAsMHgyMDA4MDAsMHg0MDAwMDAwLDB4MjAwODAwLDB4MjAwMDAwLDB4NDAwMDgwMiwweDQwMDA4MDIsMHg0MjAwMDAyLDB4NDIwMDAwMiwweDIsMHgyMDAwMDIsMHg0MDAwMDAwLDB4NDAwMDgwMCwweDIwMDAwMCwweDQyMDA4MDAsMHg4MDIsMHgyMDA4MDIsMHg0MjAwODAwLDB4ODAyLDB4NDAwMDAwMiwweDQyMDA4MDIsMHg0MjAwMDAwLDB4MjAwODAwLDAsMHgyLDB4NDIwMDgwMiwwLDB4MjAwODAyLDB4NDIwMDAwMCwweDgwMCwweDQwMDAwMDIsMHg0MDAwODAwLDB4ODAwLDB4MjAwMDAyKTtcbiAgdmFyIHNwZnVuY3Rpb244ID0gbmV3IEFycmF5ICgweDEwMDAxMDQwLDB4MTAwMCwweDQwMDAwLDB4MTAwNDEwNDAsMHgxMDAwMDAwMCwweDEwMDAxMDQwLDB4NDAsMHgxMDAwMDAwMCwweDQwMDQwLDB4MTAwNDAwMDAsMHgxMDA0MTA0MCwweDQxMDAwLDB4MTAwNDEwMDAsMHg0MTA0MCwweDEwMDAsMHg0MCwweDEwMDQwMDAwLDB4MTAwMDAwNDAsMHgxMDAwMTAwMCwweDEwNDAsMHg0MTAwMCwweDQwMDQwLDB4MTAwNDAwNDAsMHgxMDA0MTAwMCwweDEwNDAsMCwwLDB4MTAwNDAwNDAsMHgxMDAwMDA0MCwweDEwMDAxMDAwLDB4NDEwNDAsMHg0MDAwMCwweDQxMDQwLDB4NDAwMDAsMHgxMDA0MTAwMCwweDEwMDAsMHg0MCwweDEwMDQwMDQwLDB4MTAwMCwweDQxMDQwLDB4MTAwMDEwMDAsMHg0MCwweDEwMDAwMDQwLDB4MTAwNDAwMDAsMHgxMDA0MDA0MCwweDEwMDAwMDAwLDB4NDAwMDAsMHgxMDAwMTA0MCwwLDB4MTAwNDEwNDAsMHg0MDA0MCwweDEwMDAwMDQwLDB4MTAwNDAwMDAsMHgxMDAwMTAwMCwweDEwMDAxMDQwLDAsMHgxMDA0MTA0MCwweDQxMDAwLDB4NDEwMDAsMHgxMDQwLDB4MTA0MCwweDQwMDQwLDB4MTAwMDAwMDAsMHgxMDA0MTAwMCk7XG5cbiAgLy9jcmVhdGUgdGhlIDE2IG9yIDQ4IHN1YmtleXMgd2Ugd2lsbCBuZWVkXG4gIHZhciBtPTAsIGksIGosIHRlbXAsIHRlbXAyLCByaWdodDEsIHJpZ2h0MiwgbGVmdCwgcmlnaHQsIGxvb3Bpbmc7XG4gIHZhciBjYmNsZWZ0LCBjYmNsZWZ0MiwgY2JjcmlnaHQsIGNiY3JpZ2h0MlxuICB2YXIgZW5kbG9vcCwgbG9vcGluYztcbiAgdmFyIGxlbiA9IG1lc3NhZ2UubGVuZ3RoO1xuICB2YXIgY2h1bmsgPSAwO1xuICAvL3NldCB1cCB0aGUgbG9vcHMgZm9yIHNpbmdsZSBhbmQgdHJpcGxlIGRlc1xuICB2YXIgaXRlcmF0aW9ucyA9IGtleXMubGVuZ3RoID09IDMyID8gMyA6IDk7IC8vc2luZ2xlIG9yIHRyaXBsZSBkZXNcbiAgaWYgKGl0ZXJhdGlvbnMgPT0gMykge2xvb3BpbmcgPSBlbmNyeXB0ID8gbmV3IEFycmF5ICgwLCAzMiwgMikgOiBuZXcgQXJyYXkgKDMwLCAtMiwgLTIpO31cbiAgZWxzZSB7bG9vcGluZyA9IGVuY3J5cHQgPyBuZXcgQXJyYXkgKDAsIDMyLCAyLCA2MiwgMzAsIC0yLCA2NCwgOTYsIDIpIDogbmV3IEFycmF5ICg5NCwgNjIsIC0yLCAzMiwgNjQsIDIsIDMwLCAtMiwgLTIpO31cblxuICAvL3BhZCB0aGUgbWVzc2FnZSBkZXBlbmRpbmcgb24gdGhlIHBhZGRpbmcgcGFyYW1ldGVyXG4gIGlmIChwYWRkaW5nID09IDIpIG1lc3NhZ2UgKz0gXCIgICAgICAgIFwiOyAvL3BhZCB0aGUgbWVzc2FnZSB3aXRoIHNwYWNlc1xuICBlbHNlIGlmIChwYWRkaW5nID09IDEpIHt0ZW1wID0gOC0obGVuJTgpOyBtZXNzYWdlICs9IFN0cmluZy5mcm9tQ2hhckNvZGUgKHRlbXAsdGVtcCx0ZW1wLHRlbXAsdGVtcCx0ZW1wLHRlbXAsdGVtcCk7IGlmICh0ZW1wPT04KSBsZW4rPTg7fSAvL1BLQ1M3IHBhZGRpbmdcbiAgZWxzZSBpZiAoIXBhZGRpbmcpIG1lc3NhZ2UgKz0gXCJcXDBcXDBcXDBcXDBcXDBcXDBcXDBcXDBcIjsgLy9wYWQgdGhlIG1lc3NhZ2Ugb3V0IHdpdGggbnVsbCBieXRlc1xuXG4gIC8vc3RvcmUgdGhlIHJlc3VsdCBoZXJlXG4gIHJlc3VsdCA9IFwiXCI7XG4gIHRlbXByZXN1bHQgPSBcIlwiO1xuXG4gIGlmIChtb2RlID09IDEpIHsgLy9DQkMgbW9kZVxuICAgIGNiY2xlZnQgPSAoaXYuY2hhckNvZGVBdChtKyspIDw8IDI0KSB8IChpdi5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKGl2LmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8IGl2LmNoYXJDb2RlQXQobSsrKTtcbiAgICBjYmNyaWdodCA9IChpdi5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKGl2LmNoYXJDb2RlQXQobSsrKSA8PCAxNikgfCAoaXYuY2hhckNvZGVBdChtKyspIDw8IDgpIHwgaXYuY2hhckNvZGVBdChtKyspO1xuICAgIG09MDtcbiAgfVxuXG4gIC8vbG9vcCB0aHJvdWdoIGVhY2ggNjQgYml0IGNodW5rIG9mIHRoZSBtZXNzYWdlXG4gIHdoaWxlIChtIDwgbGVuKSB7XG4gICAgbGVmdCA9IChtZXNzYWdlLmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAobWVzc2FnZS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKG1lc3NhZ2UuY2hhckNvZGVBdChtKyspIDw8IDgpIHwgbWVzc2FnZS5jaGFyQ29kZUF0KG0rKyk7XG4gICAgcmlnaHQgPSAobWVzc2FnZS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKG1lc3NhZ2UuY2hhckNvZGVBdChtKyspIDw8IDE2KSB8IChtZXNzYWdlLmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8IG1lc3NhZ2UuY2hhckNvZGVBdChtKyspO1xuXG4gICAgLy9mb3IgQ2lwaGVyIEJsb2NrIENoYWluaW5nIG1vZGUsIHhvciB0aGUgbWVzc2FnZSB3aXRoIHRoZSBwcmV2aW91cyByZXN1bHRcbiAgICBpZiAobW9kZSA9PSAxKSB7aWYgKGVuY3J5cHQpIHtsZWZ0IF49IGNiY2xlZnQ7IHJpZ2h0IF49IGNiY3JpZ2h0O30gZWxzZSB7Y2JjbGVmdDIgPSBjYmNsZWZ0OyBjYmNyaWdodDIgPSBjYmNyaWdodDsgY2JjbGVmdCA9IGxlZnQ7IGNiY3JpZ2h0ID0gcmlnaHQ7fX1cblxuICAgIC8vZmlyc3QgZWFjaCA2NCBidXQgY2h1bmsgb2YgdGhlIG1lc3NhZ2UgbXVzdCBiZSBwZXJtdXRlZCBhY2NvcmRpbmcgdG8gSVBcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiA0KSBeIHJpZ2h0KSAmIDB4MGYwZjBmMGY7IHJpZ2h0IF49IHRlbXA7IGxlZnQgXj0gKHRlbXAgPDwgNCk7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gMTYpIF4gcmlnaHQpICYgMHgwMDAwZmZmZjsgcmlnaHQgXj0gdGVtcDsgbGVmdCBePSAodGVtcCA8PCAxNik7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IDIpIF4gbGVmdCkgJiAweDMzMzMzMzMzOyBsZWZ0IF49IHRlbXA7IHJpZ2h0IF49ICh0ZW1wIDw8IDIpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiA4KSBeIGxlZnQpICYgMHgwMGZmMDBmZjsgbGVmdCBePSB0ZW1wOyByaWdodCBePSAodGVtcCA8PCA4KTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAxKSBeIHJpZ2h0KSAmIDB4NTU1NTU1NTU7IHJpZ2h0IF49IHRlbXA7IGxlZnQgXj0gKHRlbXAgPDwgMSk7XG5cbiAgICBsZWZ0ID0gKChsZWZ0IDw8IDEpIHwgKGxlZnQgPj4+IDMxKSk7IFxuICAgIHJpZ2h0ID0gKChyaWdodCA8PCAxKSB8IChyaWdodCA+Pj4gMzEpKTsgXG5cbiAgICAvL2RvIHRoaXMgZWl0aGVyIDEgb3IgMyB0aW1lcyBmb3IgZWFjaCBjaHVuayBvZiB0aGUgbWVzc2FnZVxuICAgIGZvciAoaj0wOyBqPGl0ZXJhdGlvbnM7IGorPTMpIHtcbiAgICAgIGVuZGxvb3AgPSBsb29waW5nW2orMV07XG4gICAgICBsb29waW5jID0gbG9vcGluZ1tqKzJdO1xuICAgICAgLy9ub3cgZ28gdGhyb3VnaCBhbmQgcGVyZm9ybSB0aGUgZW5jcnlwdGlvbiBvciBkZWNyeXB0aW9uICBcbiAgICAgIGZvciAoaT1sb29waW5nW2pdOyBpIT1lbmRsb29wOyBpKz1sb29waW5jKSB7IC8vZm9yIGVmZmljaWVuY3lcbiAgICAgICAgcmlnaHQxID0gcmlnaHQgXiBrZXlzW2ldOyBcbiAgICAgICAgcmlnaHQyID0gKChyaWdodCA+Pj4gNCkgfCAocmlnaHQgPDwgMjgpKSBeIGtleXNbaSsxXTtcbiAgICAgICAgLy90aGUgcmVzdWx0IGlzIGF0dGFpbmVkIGJ5IHBhc3NpbmcgdGhlc2UgYnl0ZXMgdGhyb3VnaCB0aGUgUyBzZWxlY3Rpb24gZnVuY3Rpb25zXG4gICAgICAgIHRlbXAgPSBsZWZ0O1xuICAgICAgICBsZWZ0ID0gcmlnaHQ7XG4gICAgICAgIHJpZ2h0ID0gdGVtcCBeIChzcGZ1bmN0aW9uMlsocmlnaHQxID4+PiAyNCkgJiAweDNmXSB8IHNwZnVuY3Rpb240WyhyaWdodDEgPj4+IDE2KSAmIDB4M2ZdXG4gICAgICAgICAgICAgIHwgc3BmdW5jdGlvbjZbKHJpZ2h0MSA+Pj4gIDgpICYgMHgzZl0gfCBzcGZ1bmN0aW9uOFtyaWdodDEgJiAweDNmXVxuICAgICAgICAgICAgICB8IHNwZnVuY3Rpb24xWyhyaWdodDIgPj4+IDI0KSAmIDB4M2ZdIHwgc3BmdW5jdGlvbjNbKHJpZ2h0MiA+Pj4gMTYpICYgMHgzZl1cbiAgICAgICAgICAgICAgfCBzcGZ1bmN0aW9uNVsocmlnaHQyID4+PiAgOCkgJiAweDNmXSB8IHNwZnVuY3Rpb243W3JpZ2h0MiAmIDB4M2ZdKTtcbiAgICAgIH1cbiAgICAgIHRlbXAgPSBsZWZ0OyBsZWZ0ID0gcmlnaHQ7IHJpZ2h0ID0gdGVtcDsgLy91bnJldmVyc2UgbGVmdCBhbmQgcmlnaHRcbiAgICB9IC8vZm9yIGVpdGhlciAxIG9yIDMgaXRlcmF0aW9uc1xuXG4gICAgLy9tb3ZlIHRoZW4gZWFjaCBvbmUgYml0IHRvIHRoZSByaWdodFxuICAgIGxlZnQgPSAoKGxlZnQgPj4+IDEpIHwgKGxlZnQgPDwgMzEpKTsgXG4gICAgcmlnaHQgPSAoKHJpZ2h0ID4+PiAxKSB8IChyaWdodCA8PCAzMSkpOyBcblxuICAgIC8vbm93IHBlcmZvcm0gSVAtMSwgd2hpY2ggaXMgSVAgaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvblxuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDEpIF4gcmlnaHQpICYgMHg1NTU1NTU1NTsgcmlnaHQgXj0gdGVtcDsgbGVmdCBePSAodGVtcCA8PCAxKTtcbiAgICB0ZW1wID0gKChyaWdodCA+Pj4gOCkgXiBsZWZ0KSAmIDB4MDBmZjAwZmY7IGxlZnQgXj0gdGVtcDsgcmlnaHQgXj0gKHRlbXAgPDwgOCk7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IDIpIF4gbGVmdCkgJiAweDMzMzMzMzMzOyBsZWZ0IF49IHRlbXA7IHJpZ2h0IF49ICh0ZW1wIDw8IDIpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDE2KSBeIHJpZ2h0KSAmIDB4MDAwMGZmZmY7IHJpZ2h0IF49IHRlbXA7IGxlZnQgXj0gKHRlbXAgPDwgMTYpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDQpIF4gcmlnaHQpICYgMHgwZjBmMGYwZjsgcmlnaHQgXj0gdGVtcDsgbGVmdCBePSAodGVtcCA8PCA0KTtcblxuICAgIC8vZm9yIENpcGhlciBCbG9jayBDaGFpbmluZyBtb2RlLCB4b3IgdGhlIG1lc3NhZ2Ugd2l0aCB0aGUgcHJldmlvdXMgcmVzdWx0XG4gICAgaWYgKG1vZGUgPT0gMSkge2lmIChlbmNyeXB0KSB7Y2JjbGVmdCA9IGxlZnQ7IGNiY3JpZ2h0ID0gcmlnaHQ7fSBlbHNlIHtsZWZ0IF49IGNiY2xlZnQyOyByaWdodCBePSBjYmNyaWdodDI7fX1cbiAgICB0ZW1wcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUgKChsZWZ0Pj4+MjQpLCAoKGxlZnQ+Pj4xNikgJiAweGZmKSwgKChsZWZ0Pj4+OCkgJiAweGZmKSwgKGxlZnQgJiAweGZmKSwgKHJpZ2h0Pj4+MjQpLCAoKHJpZ2h0Pj4+MTYpICYgMHhmZiksICgocmlnaHQ+Pj44KSAmIDB4ZmYpLCAocmlnaHQgJiAweGZmKSk7XG5cbiAgICBjaHVuayArPSA4O1xuICAgIGlmIChjaHVuayA9PSA1MTIpIHtyZXN1bHQgKz0gdGVtcHJlc3VsdDsgdGVtcHJlc3VsdCA9IFwiXCI7IGNodW5rID0gMDt9XG4gIH0gLy9mb3IgZXZlcnkgOCBjaGFyYWN0ZXJzLCBvciA2NCBiaXRzIGluIHRoZSBtZXNzYWdlXG5cbiAgLy9yZXR1cm4gdGhlIHJlc3VsdCBhcyBhbiBhcnJheVxuICByZXN1bHQgKz0gdGVtcHJlc3VsdDtcbiAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UoL1xcMCokL2csIFwiXCIpO1xuICByZXR1cm4gcmVzdWx0O1xufSAvL2VuZCBvZiBkZXNcblxuXG5cbi8vZGVzX2NyZWF0ZUtleXNcbi8vdGhpcyB0YWtlcyBhcyBpbnB1dCBhIDY0IGJpdCBrZXkgKGV2ZW4gdGhvdWdoIG9ubHkgNTYgYml0cyBhcmUgdXNlZClcbi8vYXMgYW4gYXJyYXkgb2YgMiBpbnRlZ2VycywgYW5kIHJldHVybnMgMTYgNDggYml0IGtleXNcbmZ1bmN0aW9uIGRlc19jcmVhdGVLZXlzIChrZXkpIHtcbiAgLy9kZWNsYXJpbmcgdGhpcyBsb2NhbGx5IHNwZWVkcyB0aGluZ3MgdXAgYSBiaXRcbiAgcGMyYnl0ZXMwICA9IG5ldyBBcnJheSAoMCwweDQsMHgyMDAwMDAwMCwweDIwMDAwMDA0LDB4MTAwMDAsMHgxMDAwNCwweDIwMDEwMDAwLDB4MjAwMTAwMDQsMHgyMDAsMHgyMDQsMHgyMDAwMDIwMCwweDIwMDAwMjA0LDB4MTAyMDAsMHgxMDIwNCwweDIwMDEwMjAwLDB4MjAwMTAyMDQpO1xuICBwYzJieXRlczEgID0gbmV3IEFycmF5ICgwLDB4MSwweDEwMDAwMCwweDEwMDAwMSwweDQwMDAwMDAsMHg0MDAwMDAxLDB4NDEwMDAwMCwweDQxMDAwMDEsMHgxMDAsMHgxMDEsMHgxMDAxMDAsMHgxMDAxMDEsMHg0MDAwMTAwLDB4NDAwMDEwMSwweDQxMDAxMDAsMHg0MTAwMTAxKTtcbiAgcGMyYnl0ZXMyICA9IG5ldyBBcnJheSAoMCwweDgsMHg4MDAsMHg4MDgsMHgxMDAwMDAwLDB4MTAwMDAwOCwweDEwMDA4MDAsMHgxMDAwODA4LDAsMHg4LDB4ODAwLDB4ODA4LDB4MTAwMDAwMCwweDEwMDAwMDgsMHgxMDAwODAwLDB4MTAwMDgwOCk7XG4gIHBjMmJ5dGVzMyAgPSBuZXcgQXJyYXkgKDAsMHgyMDAwMDAsMHg4MDAwMDAwLDB4ODIwMDAwMCwweDIwMDAsMHgyMDIwMDAsMHg4MDAyMDAwLDB4ODIwMjAwMCwweDIwMDAwLDB4MjIwMDAwLDB4ODAyMDAwMCwweDgyMjAwMDAsMHgyMjAwMCwweDIyMjAwMCwweDgwMjIwMDAsMHg4MjIyMDAwKTtcbiAgcGMyYnl0ZXM0ICA9IG5ldyBBcnJheSAoMCwweDQwMDAwLDB4MTAsMHg0MDAxMCwwLDB4NDAwMDAsMHgxMCwweDQwMDEwLDB4MTAwMCwweDQxMDAwLDB4MTAxMCwweDQxMDEwLDB4MTAwMCwweDQxMDAwLDB4MTAxMCwweDQxMDEwKTtcbiAgcGMyYnl0ZXM1ICA9IG5ldyBBcnJheSAoMCwweDQwMCwweDIwLDB4NDIwLDAsMHg0MDAsMHgyMCwweDQyMCwweDIwMDAwMDAsMHgyMDAwNDAwLDB4MjAwMDAyMCwweDIwMDA0MjAsMHgyMDAwMDAwLDB4MjAwMDQwMCwweDIwMDAwMjAsMHgyMDAwNDIwKTtcbiAgcGMyYnl0ZXM2ICA9IG5ldyBBcnJheSAoMCwweDEwMDAwMDAwLDB4ODAwMDAsMHgxMDA4MDAwMCwweDIsMHgxMDAwMDAwMiwweDgwMDAyLDB4MTAwODAwMDIsMCwweDEwMDAwMDAwLDB4ODAwMDAsMHgxMDA4MDAwMCwweDIsMHgxMDAwMDAwMiwweDgwMDAyLDB4MTAwODAwMDIpO1xuICBwYzJieXRlczcgID0gbmV3IEFycmF5ICgwLDB4MTAwMDAsMHg4MDAsMHgxMDgwMCwweDIwMDAwMDAwLDB4MjAwMTAwMDAsMHgyMDAwMDgwMCwweDIwMDEwODAwLDB4MjAwMDAsMHgzMDAwMCwweDIwODAwLDB4MzA4MDAsMHgyMDAyMDAwMCwweDIwMDMwMDAwLDB4MjAwMjA4MDAsMHgyMDAzMDgwMCk7XG4gIHBjMmJ5dGVzOCAgPSBuZXcgQXJyYXkgKDAsMHg0MDAwMCwwLDB4NDAwMDAsMHgyLDB4NDAwMDIsMHgyLDB4NDAwMDIsMHgyMDAwMDAwLDB4MjA0MDAwMCwweDIwMDAwMDAsMHgyMDQwMDAwLDB4MjAwMDAwMiwweDIwNDAwMDIsMHgyMDAwMDAyLDB4MjA0MDAwMik7XG4gIHBjMmJ5dGVzOSAgPSBuZXcgQXJyYXkgKDAsMHgxMDAwMDAwMCwweDgsMHgxMDAwMDAwOCwwLDB4MTAwMDAwMDAsMHg4LDB4MTAwMDAwMDgsMHg0MDAsMHgxMDAwMDQwMCwweDQwOCwweDEwMDAwNDA4LDB4NDAwLDB4MTAwMDA0MDAsMHg0MDgsMHgxMDAwMDQwOCk7XG4gIHBjMmJ5dGVzMTAgPSBuZXcgQXJyYXkgKDAsMHgyMCwwLDB4MjAsMHgxMDAwMDAsMHgxMDAwMjAsMHgxMDAwMDAsMHgxMDAwMjAsMHgyMDAwLDB4MjAyMCwweDIwMDAsMHgyMDIwLDB4MTAyMDAwLDB4MTAyMDIwLDB4MTAyMDAwLDB4MTAyMDIwKTtcbiAgcGMyYnl0ZXMxMSA9IG5ldyBBcnJheSAoMCwweDEwMDAwMDAsMHgyMDAsMHgxMDAwMjAwLDB4MjAwMDAwLDB4MTIwMDAwMCwweDIwMDIwMCwweDEyMDAyMDAsMHg0MDAwMDAwLDB4NTAwMDAwMCwweDQwMDAyMDAsMHg1MDAwMjAwLDB4NDIwMDAwMCwweDUyMDAwMDAsMHg0MjAwMjAwLDB4NTIwMDIwMCk7XG4gIHBjMmJ5dGVzMTIgPSBuZXcgQXJyYXkgKDAsMHgxMDAwLDB4ODAwMDAwMCwweDgwMDEwMDAsMHg4MDAwMCwweDgxMDAwLDB4ODA4MDAwMCwweDgwODEwMDAsMHgxMCwweDEwMTAsMHg4MDAwMDEwLDB4ODAwMTAxMCwweDgwMDEwLDB4ODEwMTAsMHg4MDgwMDEwLDB4ODA4MTAxMCk7XG4gIHBjMmJ5dGVzMTMgPSBuZXcgQXJyYXkgKDAsMHg0LDB4MTAwLDB4MTA0LDAsMHg0LDB4MTAwLDB4MTA0LDB4MSwweDUsMHgxMDEsMHgxMDUsMHgxLDB4NSwweDEwMSwweDEwNSk7XG5cbiAgLy9ob3cgbWFueSBpdGVyYXRpb25zICgxIGZvciBkZXMsIDMgZm9yIHRyaXBsZSBkZXMpXG4gIHZhciBpdGVyYXRpb25zID0ga2V5Lmxlbmd0aCA+IDggPyAzIDogMTsgLy9jaGFuZ2VkIGJ5IFBhdWwgMTYvNi8yMDA3IHRvIHVzZSBUcmlwbGUgREVTIGZvciA5KyBieXRlIGtleXNcbiAgLy9zdG9yZXMgdGhlIHJldHVybiBrZXlzXG4gIHZhciBrZXlzID0gbmV3IEFycmF5ICgzMiAqIGl0ZXJhdGlvbnMpO1xuICAvL25vdyBkZWZpbmUgdGhlIGxlZnQgc2hpZnRzIHdoaWNoIG5lZWQgdG8gYmUgZG9uZVxuICB2YXIgc2hpZnRzID0gbmV3IEFycmF5ICgwLCAwLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAxLCAxLCAxLCAxLCAxLCAxLCAwKTtcbiAgLy9vdGhlciB2YXJpYWJsZXNcbiAgdmFyIGxlZnR0ZW1wLCByaWdodHRlbXAsIG09MCwgbj0wLCB0ZW1wO1xuXG4gIGZvciAodmFyIGo9MDsgajxpdGVyYXRpb25zOyBqKyspIHsgLy9laXRoZXIgMSBvciAzIGl0ZXJhdGlvbnNcbiAgICBsZWZ0ID0gKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgOCkgfCBrZXkuY2hhckNvZGVBdChtKyspO1xuICAgIHJpZ2h0ID0gKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgOCkgfCBrZXkuY2hhckNvZGVBdChtKyspO1xuXG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gNCkgXiByaWdodCkgJiAweDBmMGYwZjBmOyByaWdodCBePSB0ZW1wOyBsZWZ0IF49ICh0ZW1wIDw8IDQpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiAtMTYpIF4gbGVmdCkgJiAweDAwMDBmZmZmOyBsZWZ0IF49IHRlbXA7IHJpZ2h0IF49ICh0ZW1wIDw8IC0xNik7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gMikgXiByaWdodCkgJiAweDMzMzMzMzMzOyByaWdodCBePSB0ZW1wOyBsZWZ0IF49ICh0ZW1wIDw8IDIpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiAtMTYpIF4gbGVmdCkgJiAweDAwMDBmZmZmOyBsZWZ0IF49IHRlbXA7IHJpZ2h0IF49ICh0ZW1wIDw8IC0xNik7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gMSkgXiByaWdodCkgJiAweDU1NTU1NTU1OyByaWdodCBePSB0ZW1wOyBsZWZ0IF49ICh0ZW1wIDw8IDEpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiA4KSBeIGxlZnQpICYgMHgwMGZmMDBmZjsgbGVmdCBePSB0ZW1wOyByaWdodCBePSAodGVtcCA8PCA4KTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAxKSBeIHJpZ2h0KSAmIDB4NTU1NTU1NTU7IHJpZ2h0IF49IHRlbXA7IGxlZnQgXj0gKHRlbXAgPDwgMSk7XG5cbiAgICAvL3RoZSByaWdodCBzaWRlIG5lZWRzIHRvIGJlIHNoaWZ0ZWQgYW5kIHRvIGdldCB0aGUgbGFzdCBmb3VyIGJpdHMgb2YgdGhlIGxlZnQgc2lkZVxuICAgIHRlbXAgPSAobGVmdCA8PCA4KSB8ICgocmlnaHQgPj4+IDIwKSAmIDB4MDAwMDAwZjApO1xuICAgIC8vbGVmdCBuZWVkcyB0byBiZSBwdXQgdXBzaWRlIGRvd25cbiAgICBsZWZ0ID0gKHJpZ2h0IDw8IDI0KSB8ICgocmlnaHQgPDwgOCkgJiAweGZmMDAwMCkgfCAoKHJpZ2h0ID4+PiA4KSAmIDB4ZmYwMCkgfCAoKHJpZ2h0ID4+PiAyNCkgJiAweGYwKTtcbiAgICByaWdodCA9IHRlbXA7XG5cbiAgICAvL25vdyBnbyB0aHJvdWdoIGFuZCBwZXJmb3JtIHRoZXNlIHNoaWZ0cyBvbiB0aGUgbGVmdCBhbmQgcmlnaHQga2V5c1xuICAgIGZvciAoaT0wOyBpIDwgc2hpZnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAvL3NoaWZ0IHRoZSBrZXlzIGVpdGhlciBvbmUgb3IgdHdvIGJpdHMgdG8gdGhlIGxlZnRcbiAgICAgIGlmIChzaGlmdHNbaV0pIHtsZWZ0ID0gKGxlZnQgPDwgMikgfCAobGVmdCA+Pj4gMjYpOyByaWdodCA9IChyaWdodCA8PCAyKSB8IChyaWdodCA+Pj4gMjYpO31cbiAgICAgIGVsc2Uge2xlZnQgPSAobGVmdCA8PCAxKSB8IChsZWZ0ID4+PiAyNyk7IHJpZ2h0ID0gKHJpZ2h0IDw8IDEpIHwgKHJpZ2h0ID4+PiAyNyk7fVxuICAgICAgbGVmdCAmPSAtMHhmOyByaWdodCAmPSAtMHhmO1xuXG4gICAgICAvL25vdyBhcHBseSBQQy0yLCBpbiBzdWNoIGEgd2F5IHRoYXQgRSBpcyBlYXNpZXIgd2hlbiBlbmNyeXB0aW5nIG9yIGRlY3J5cHRpbmdcbiAgICAgIC8vdGhpcyBjb252ZXJzaW9uIHdpbGwgbG9vayBsaWtlIFBDLTIgZXhjZXB0IG9ubHkgdGhlIGxhc3QgNiBiaXRzIG9mIGVhY2ggYnl0ZSBhcmUgdXNlZFxuICAgICAgLy9yYXRoZXIgdGhhbiA0OCBjb25zZWN1dGl2ZSBiaXRzIGFuZCB0aGUgb3JkZXIgb2YgbGluZXMgd2lsbCBiZSBhY2NvcmRpbmcgdG8gXG4gICAgICAvL2hvdyB0aGUgUyBzZWxlY3Rpb24gZnVuY3Rpb25zIHdpbGwgYmUgYXBwbGllZDogUzIsIFM0LCBTNiwgUzgsIFMxLCBTMywgUzUsIFM3XG4gICAgICBsZWZ0dGVtcCA9IHBjMmJ5dGVzMFtsZWZ0ID4+PiAyOF0gfCBwYzJieXRlczFbKGxlZnQgPj4+IDI0KSAmIDB4Zl1cbiAgICAgICAgICAgICAgfCBwYzJieXRlczJbKGxlZnQgPj4+IDIwKSAmIDB4Zl0gfCBwYzJieXRlczNbKGxlZnQgPj4+IDE2KSAmIDB4Zl1cbiAgICAgICAgICAgICAgfCBwYzJieXRlczRbKGxlZnQgPj4+IDEyKSAmIDB4Zl0gfCBwYzJieXRlczVbKGxlZnQgPj4+IDgpICYgMHhmXVxuICAgICAgICAgICAgICB8IHBjMmJ5dGVzNlsobGVmdCA+Pj4gNCkgJiAweGZdO1xuICAgICAgcmlnaHR0ZW1wID0gcGMyYnl0ZXM3W3JpZ2h0ID4+PiAyOF0gfCBwYzJieXRlczhbKHJpZ2h0ID4+PiAyNCkgJiAweGZdXG4gICAgICAgICAgICAgICAgfCBwYzJieXRlczlbKHJpZ2h0ID4+PiAyMCkgJiAweGZdIHwgcGMyYnl0ZXMxMFsocmlnaHQgPj4+IDE2KSAmIDB4Zl1cbiAgICAgICAgICAgICAgICB8IHBjMmJ5dGVzMTFbKHJpZ2h0ID4+PiAxMikgJiAweGZdIHwgcGMyYnl0ZXMxMlsocmlnaHQgPj4+IDgpICYgMHhmXVxuICAgICAgICAgICAgICAgIHwgcGMyYnl0ZXMxM1socmlnaHQgPj4+IDQpICYgMHhmXTtcbiAgICAgIHRlbXAgPSAoKHJpZ2h0dGVtcCA+Pj4gMTYpIF4gbGVmdHRlbXApICYgMHgwMDAwZmZmZjsgXG4gICAgICBrZXlzW24rK10gPSBsZWZ0dGVtcCBeIHRlbXA7IGtleXNbbisrXSA9IHJpZ2h0dGVtcCBeICh0ZW1wIDw8IDE2KTtcbiAgICB9XG4gIH0gLy9mb3IgZWFjaCBpdGVyYXRpb25zXG4gIC8vcmV0dXJuIHRoZSBrZXlzIHdlJ3ZlIGNyZWF0ZWRcbiAgcmV0dXJuIGtleXM7XG59IC8vZW5kIG9mIGRlc19jcmVhdGVLZXlzXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG4vLyBhZGRlZCBieSBSZWN1cml0eSBMYWJzXG5mdW5jdGlvbiBEZXMoa2V5KSB7XG5cdHRoaXMua2V5ID0gW107XG5cblx0Zm9yKHZhciBpID0gMDsgaSA8IDM7IGkrKykge1xuXHRcdHRoaXMua2V5LnB1c2goa2V5LnN1YnN0cihpICogOCwgOCkpO1xuXHR9XG5cblx0dGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oYmxvY2spIHtcblx0XHRyZXR1cm4gdXRpbC5zdHIyYmluKGRlcyhkZXNfY3JlYXRlS2V5cyh0aGlzLmtleVsyXSksXG5cdFx0XHRkZXMoZGVzX2NyZWF0ZUtleXModGhpcy5rZXlbMV0pLFxuXHRcdFx0ZGVzKGRlc19jcmVhdGVLZXlzKHRoaXMua2V5WzBdKSxcblx0XHRcdHV0aWwuYmluMnN0cihibG9jayksIHRydWUsIDAsbnVsbCxudWxsKSwgXG5cdFx0XHRmYWxzZSwgMCxudWxsLG51bGwpLCB0cnVlLCAwLG51bGwsbnVsbCkpO1xuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gRGVzO1xubW9kdWxlLmV4cG9ydHMua2V5U2l6ZSA9IERlcy5wcm90b3R5cGUua2V5U2l6ZSA9IDI0O1xubW9kdWxlLmV4cG9ydHMuYmxvY2tTaXplID0gRGVzLnByb3RvdHlwZS5ibG9ja1NpemUgPSA4O1xuXG4iLCJcbm1vZHVsZS5leHBvcnRzID0ge1xuXHRkZXM6IHJlcXVpcmUoJy4vZGVzLmpzJyksXG5cdGNhc3Q1OiByZXF1aXJlKCcuL2Nhc3Q1LmpzJyksXG5cdHR3b2Zpc2g6IHJlcXVpcmUoJy4vdHdvZmlzaC5qcycpLFxuXHRibG93ZmlzaDogcmVxdWlyZSgnLi9ibG93ZmlzaC5qcycpXG59XG5cbnZhciBhZXMgPSByZXF1aXJlKCcuL2Flcy5qcycpO1xuXG5mb3IodmFyIGkgaW4gYWVzKSB7XG5cdG1vZHVsZS5leHBvcnRzWydhZXMnICsgaV0gPSBhZXNbaV07XG59XG4iLCIvKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkggXG4gKiBcbiAqIENpcGhlci5qc1xuICogQSBibG9jay1jaXBoZXIgYWxnb3JpdGhtIGltcGxlbWVudGF0aW9uIG9uIEphdmFTY3JpcHRcbiAqIFNlZSBDaXBoZXIucmVhZG1lLnR4dCBmb3IgZnVydGhlciBpbmZvcm1hdGlvbi5cbiAqXG4gKiBDb3B5cmlnaHQoYykgMjAwOSBBdHN1c2hpIE9rYSBbIGh0dHA6Ly9va2EubnUvIF1cbiAqIFRoaXMgc2NyaXB0IGZpbGUgaXMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExHUExcbiAqXG4gKiBBQ0tOT1dMRURHTUVOVFxuICpcbiAqICAgICBUaGUgbWFpbiBzdWJyb3V0aW5lcyBhcmUgd3JpdHRlbiBieSBNaWNoaWVsIHZhbiBFdmVyZGluZ2VuLlxuICogXG4gKiAgICAgTWljaGllbCB2YW4gRXZlcmRpbmdlblxuICogICAgIGh0dHA6Ly9ob21lLnZlcnNhdGVsLm5sL01BdmFuRXZlcmRpbmdlbi9pbmRleC5odG1sXG4gKiBcbiAqICAgICBBbGwgcmlnaHRzIGZvciB0aGVzZSByb3V0aW5lcyBhcmUgcmVzZXJ2ZWQgdG8gTWljaGllbCB2YW4gRXZlcmRpbmdlbi5cbiAqXG4gKi9cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy9NYXRoXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxudmFyIE1BWElOVCA9IDB4RkZGRkZGRkY7XG5cbmZ1bmN0aW9uIHJvdGIoYixuKXsgcmV0dXJuICggYjw8biB8IGI+Pj4oIDgtbikgKSAmIDB4RkY7IH1cbmZ1bmN0aW9uIHJvdHcodyxuKXsgcmV0dXJuICggdzw8biB8IHc+Pj4oMzItbikgKSAmIE1BWElOVDsgfVxuZnVuY3Rpb24gZ2V0VyhhLGkpeyByZXR1cm4gYVtpXXxhW2krMV08PDh8YVtpKzJdPDwxNnxhW2krM108PDI0OyB9XG5mdW5jdGlvbiBzZXRXKGEsaSx3KXsgYS5zcGxpY2UoaSw0LHcmMHhGRiwodz4+PjgpJjB4RkYsKHc+Pj4xNikmMHhGRiwodz4+PjI0KSYweEZGKTsgfVxuZnVuY3Rpb24gc2V0V0ludihhLGksdyl7IGEuc3BsaWNlKGksNCwodz4+PjI0KSYweEZGLCh3Pj4+MTYpJjB4RkYsKHc+Pj44KSYweEZGLHcmMHhGRik7IH1cbmZ1bmN0aW9uIGdldEIoeCxuKXsgcmV0dXJuICh4Pj4+KG4qOCkpJjB4RkY7IH1cblxuZnVuY3Rpb24gZ2V0TnJCaXRzKGkpeyB2YXIgbj0wOyB3aGlsZSAoaT4wKXsgbisrOyBpPj4+PTE7IH0gcmV0dXJuIG47IH1cbmZ1bmN0aW9uIGdldE1hc2sobil7IHJldHVybiAoMTw8biktMTsgfVxuXG4vL2FkZGVkIDIwMDgvMTEvMTMgWFhYIE1VU1QgVVNFIE9ORS1XQVkgSEFTSCBGVU5DVElPTiBGT1IgU0VDVVJJVFkgUkVBU09OXG5mdW5jdGlvbiByYW5kQnl0ZSgpIHtcbiByZXR1cm4gTWF0aC5mbG9vciggTWF0aC5yYW5kb20oKSAqIDI1NiApO1xufVxuLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gVHdvZmlzaFxuLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG5mdW5jdGlvbiBjcmVhdGVUd29maXNoKCkge1xuXHQvL1xuXHR2YXIga2V5Qnl0ZXMgPSBudWxsO1xuXHR2YXIgZGF0YUJ5dGVzID0gbnVsbDtcblx0dmFyIGRhdGFPZmZzZXQgPSAtMTtcblx0Ly8gdmFyIGRhdGFMZW5ndGggPSAtMTtcblx0dmFyIGFsZ29yaXRobU5hbWUgPSBudWxsO1xuXHQvLyB2YXIgaWR4MiA9IC0xO1xuXHQvL1xuXG5cdGFsZ29yaXRobU5hbWUgPSBcInR3b2Zpc2hcIjtcblxuXHR2YXIgdGZzS2V5ID0gW107XG5cdHZhciB0ZnNNID0gWyBbXSwgW10sIFtdLCBbXSBdO1xuXG5cdGZ1bmN0aW9uIHRmc0luaXQoa2V5KSB7XG5cdFx0a2V5Qnl0ZXMgPSBrZXk7XG5cdFx0dmFyIGksIGEsIGIsIGMsIGQsIG1lS2V5ID0gW10sIG1vS2V5ID0gW10sIGluS2V5ID0gW107XG5cdFx0dmFyIGtMZW47XG5cdFx0dmFyIHNLZXkgPSBbXTtcblx0XHR2YXIgZjAxLCBmNWIsIGZlZjtcblxuXHRcdHZhciBxMCA9IFsgWyA4LCAxLCA3LCAxMywgNiwgMTUsIDMsIDIsIDAsIDExLCA1LCA5LCAxNCwgMTIsIDEwLCA0IF0sXG5cdFx0XHRcdFsgMiwgOCwgMTEsIDEzLCAxNSwgNywgNiwgMTQsIDMsIDEsIDksIDQsIDAsIDEwLCAxMiwgNSBdIF07XG5cdFx0dmFyIHExID0gWyBbIDE0LCAxMiwgMTEsIDgsIDEsIDIsIDMsIDUsIDE1LCA0LCAxMCwgNiwgNywgMCwgOSwgMTMgXSxcblx0XHRcdFx0WyAxLCAxNCwgMiwgMTEsIDQsIDEyLCAzLCA3LCA2LCAxMywgMTAsIDUsIDE1LCA5LCAwLCA4IF0gXTtcblx0XHR2YXIgcTIgPSBbIFsgMTEsIDEwLCA1LCAxNCwgNiwgMTMsIDksIDAsIDEyLCA4LCAxNSwgMywgMiwgNCwgNywgMSBdLFxuXHRcdFx0XHRbIDQsIDEyLCA3LCA1LCAxLCA2LCA5LCAxMCwgMCwgMTQsIDEzLCA4LCAyLCAxMSwgMywgMTUgXSBdO1xuXHRcdHZhciBxMyA9IFsgWyAxMywgNywgMTUsIDQsIDEsIDIsIDYsIDE0LCA5LCAxMSwgMywgMCwgOCwgNSwgMTIsIDEwIF0sXG5cdFx0XHRcdFsgMTEsIDksIDUsIDEsIDEyLCAzLCAxMywgMTQsIDYsIDQsIDcsIDE1LCAyLCAwLCA4LCAxMCBdIF07XG5cdFx0dmFyIHJvcjQgPSBbIDAsIDgsIDEsIDksIDIsIDEwLCAzLCAxMSwgNCwgMTIsIDUsIDEzLCA2LCAxNCwgNywgMTUgXTtcblx0XHR2YXIgYXNoeCA9IFsgMCwgOSwgMiwgMTEsIDQsIDEzLCA2LCAxNSwgOCwgMSwgMTAsIDMsIDEyLCA1LCAxNCwgNyBdO1xuXHRcdHZhciBxID0gWyBbXSwgW10gXTtcblx0XHR2YXIgbSA9IFsgW10sIFtdLCBbXSwgW10gXTtcblxuXHRcdGZ1bmN0aW9uIGZmbTViKHgpIHtcblx0XHRcdHJldHVybiB4IF4gKHggPj4gMikgXiBbIDAsIDkwLCAxODAsIDIzOCBdW3ggJiAzXTtcblx0XHR9XG5cdFx0ZnVuY3Rpb24gZmZtRWYoeCkge1xuXHRcdFx0cmV0dXJuIHggXiAoeCA+PiAxKSBeICh4ID4+IDIpIF4gWyAwLCAyMzgsIDE4MCwgOTAgXVt4ICYgM107XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gbWRzUmVtKHAsIHEpIHtcblx0XHRcdHZhciBpLCB0LCB1O1xuXHRcdFx0Zm9yIChpID0gMDsgaSA8IDg7IGkrKykge1xuXHRcdFx0XHR0ID0gcSA+Pj4gMjQ7XG5cdFx0XHRcdHEgPSAoKHEgPDwgOCkgJiBNQVhJTlQpIHwgcCA+Pj4gMjQ7XG5cdFx0XHRcdHAgPSAocCA8PCA4KSAmIE1BWElOVDtcblx0XHRcdFx0dSA9IHQgPDwgMTtcblx0XHRcdFx0aWYgKHQgJiAxMjgpIHtcblx0XHRcdFx0XHR1IF49IDMzMztcblx0XHRcdFx0fVxuXHRcdFx0XHRxIF49IHQgXiAodSA8PCAxNik7XG5cdFx0XHRcdHUgXj0gdCA+Pj4gMTtcblx0XHRcdFx0aWYgKHQgJiAxKSB7XG5cdFx0XHRcdFx0dSBePSAxNjY7XG5cdFx0XHRcdH1cblx0XHRcdFx0cSBePSB1IDw8IDI0IHwgdSA8PCA4O1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHE7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gcXAobiwgeCkge1xuXHRcdFx0dmFyIGEsIGIsIGMsIGQ7XG5cdFx0XHRhID0geCA+PiA0O1xuXHRcdFx0YiA9IHggJiAxNTtcblx0XHRcdGMgPSBxMFtuXVthIF4gYl07XG5cdFx0XHRkID0gcTFbbl1bcm9yNFtiXSBeIGFzaHhbYV1dO1xuXHRcdFx0cmV0dXJuIHEzW25dW3JvcjRbZF0gXiBhc2h4W2NdXSA8PCA0IHwgcTJbbl1bYyBeIGRdO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGhGdW4oeCwga2V5KSB7XG5cdFx0XHR2YXIgYSA9IGdldEIoeCwgMCksIGIgPSBnZXRCKHgsIDEpLCBjID0gZ2V0Qih4LCAyKSwgZCA9IGdldEIoeCwgMyk7XG5cdFx0XHRzd2l0Y2ggKGtMZW4pIHtcblx0XHRcdGNhc2UgNDpcblx0XHRcdFx0YSA9IHFbMV1bYV0gXiBnZXRCKGtleVszXSwgMCk7XG5cdFx0XHRcdGIgPSBxWzBdW2JdIF4gZ2V0QihrZXlbM10sIDEpO1xuXHRcdFx0XHRjID0gcVswXVtjXSBeIGdldEIoa2V5WzNdLCAyKTtcblx0XHRcdFx0ZCA9IHFbMV1bZF0gXiBnZXRCKGtleVszXSwgMyk7XG5cdFx0XHRjYXNlIDM6XG5cdFx0XHRcdGEgPSBxWzFdW2FdIF4gZ2V0QihrZXlbMl0sIDApO1xuXHRcdFx0XHRiID0gcVsxXVtiXSBeIGdldEIoa2V5WzJdLCAxKTtcblx0XHRcdFx0YyA9IHFbMF1bY10gXiBnZXRCKGtleVsyXSwgMik7XG5cdFx0XHRcdGQgPSBxWzBdW2RdIF4gZ2V0QihrZXlbMl0sIDMpO1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHRhID0gcVswXVtxWzBdW2FdIF4gZ2V0QihrZXlbMV0sIDApXSBeIGdldEIoa2V5WzBdLCAwKTtcblx0XHRcdFx0YiA9IHFbMF1bcVsxXVtiXSBeIGdldEIoa2V5WzFdLCAxKV0gXiBnZXRCKGtleVswXSwgMSk7XG5cdFx0XHRcdGMgPSBxWzFdW3FbMF1bY10gXiBnZXRCKGtleVsxXSwgMildIF4gZ2V0QihrZXlbMF0sIDIpO1xuXHRcdFx0XHRkID0gcVsxXVtxWzFdW2RdIF4gZ2V0QihrZXlbMV0sIDMpXSBeIGdldEIoa2V5WzBdLCAzKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtWzBdW2FdIF4gbVsxXVtiXSBeIG1bMl1bY10gXiBtWzNdW2RdO1xuXHRcdH1cblxuXHRcdGtleUJ5dGVzID0ga2V5Qnl0ZXMuc2xpY2UoMCwgMzIpO1xuXHRcdGkgPSBrZXlCeXRlcy5sZW5ndGg7XG5cdFx0d2hpbGUgKGkgIT0gMTYgJiYgaSAhPSAyNCAmJiBpICE9IDMyKVxuXHRcdFx0a2V5Qnl0ZXNbaSsrXSA9IDA7XG5cblx0XHRmb3IgKGkgPSAwOyBpIDwga2V5Qnl0ZXMubGVuZ3RoOyBpICs9IDQpIHtcblx0XHRcdGluS2V5W2kgPj4gMl0gPSBnZXRXKGtleUJ5dGVzLCBpKTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG5cdFx0XHRxWzBdW2ldID0gcXAoMCwgaSk7XG5cdFx0XHRxWzFdW2ldID0gcXAoMSwgaSk7XG5cdFx0fVxuXHRcdGZvciAoaSA9IDA7IGkgPCAyNTY7IGkrKykge1xuXHRcdFx0ZjAxID0gcVsxXVtpXTtcblx0XHRcdGY1YiA9IGZmbTViKGYwMSk7XG5cdFx0XHRmZWYgPSBmZm1FZihmMDEpO1xuXHRcdFx0bVswXVtpXSA9IGYwMSArIChmNWIgPDwgOCkgKyAoZmVmIDw8IDE2KSArIChmZWYgPDwgMjQpO1xuXHRcdFx0bVsyXVtpXSA9IGY1YiArIChmZWYgPDwgOCkgKyAoZjAxIDw8IDE2KSArIChmZWYgPDwgMjQpO1xuXHRcdFx0ZjAxID0gcVswXVtpXTtcblx0XHRcdGY1YiA9IGZmbTViKGYwMSk7XG5cdFx0XHRmZWYgPSBmZm1FZihmMDEpO1xuXHRcdFx0bVsxXVtpXSA9IGZlZiArIChmZWYgPDwgOCkgKyAoZjViIDw8IDE2KSArIChmMDEgPDwgMjQpO1xuXHRcdFx0bVszXVtpXSA9IGY1YiArIChmMDEgPDwgOCkgKyAoZmVmIDw8IDE2KSArIChmNWIgPDwgMjQpO1xuXHRcdH1cblxuXHRcdGtMZW4gPSBpbktleS5sZW5ndGggLyAyO1xuXHRcdGZvciAoaSA9IDA7IGkgPCBrTGVuOyBpKyspIHtcblx0XHRcdGEgPSBpbktleVtpICsgaV07XG5cdFx0XHRtZUtleVtpXSA9IGE7XG5cdFx0XHRiID0gaW5LZXlbaSArIGkgKyAxXTtcblx0XHRcdG1vS2V5W2ldID0gYjtcblx0XHRcdHNLZXlba0xlbiAtIGkgLSAxXSA9IG1kc1JlbShhLCBiKTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMDsgaSA8IDQwOyBpICs9IDIpIHtcblx0XHRcdGEgPSAweDEwMTAxMDEgKiBpO1xuXHRcdFx0YiA9IGEgKyAweDEwMTAxMDE7XG5cdFx0XHRhID0gaEZ1bihhLCBtZUtleSk7XG5cdFx0XHRiID0gcm90dyhoRnVuKGIsIG1vS2V5KSwgOCk7XG5cdFx0XHR0ZnNLZXlbaV0gPSAoYSArIGIpICYgTUFYSU5UO1xuXHRcdFx0dGZzS2V5W2kgKyAxXSA9IHJvdHcoYSArIDIgKiBiLCA5KTtcblx0XHR9XG5cdFx0Zm9yIChpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG5cdFx0XHRhID0gYiA9IGMgPSBkID0gaTtcblx0XHRcdHN3aXRjaCAoa0xlbikge1xuXHRcdFx0Y2FzZSA0OlxuXHRcdFx0XHRhID0gcVsxXVthXSBeIGdldEIoc0tleVszXSwgMCk7XG5cdFx0XHRcdGIgPSBxWzBdW2JdIF4gZ2V0QihzS2V5WzNdLCAxKTtcblx0XHRcdFx0YyA9IHFbMF1bY10gXiBnZXRCKHNLZXlbM10sIDIpO1xuXHRcdFx0XHRkID0gcVsxXVtkXSBeIGdldEIoc0tleVszXSwgMyk7XG5cdFx0XHRjYXNlIDM6XG5cdFx0XHRcdGEgPSBxWzFdW2FdIF4gZ2V0QihzS2V5WzJdLCAwKTtcblx0XHRcdFx0YiA9IHFbMV1bYl0gXiBnZXRCKHNLZXlbMl0sIDEpO1xuXHRcdFx0XHRjID0gcVswXVtjXSBeIGdldEIoc0tleVsyXSwgMik7XG5cdFx0XHRcdGQgPSBxWzBdW2RdIF4gZ2V0QihzS2V5WzJdLCAzKTtcblx0XHRcdGNhc2UgMjpcblx0XHRcdFx0dGZzTVswXVtpXSA9IG1bMF1bcVswXVtxWzBdW2FdIF4gZ2V0QihzS2V5WzFdLCAwKV1cblx0XHRcdFx0XHRcdF4gZ2V0QihzS2V5WzBdLCAwKV07XG5cdFx0XHRcdHRmc01bMV1baV0gPSBtWzFdW3FbMF1bcVsxXVtiXSBeIGdldEIoc0tleVsxXSwgMSldXG5cdFx0XHRcdFx0XHReIGdldEIoc0tleVswXSwgMSldO1xuXHRcdFx0XHR0ZnNNWzJdW2ldID0gbVsyXVtxWzFdW3FbMF1bY10gXiBnZXRCKHNLZXlbMV0sIDIpXVxuXHRcdFx0XHRcdFx0XiBnZXRCKHNLZXlbMF0sIDIpXTtcblx0XHRcdFx0dGZzTVszXVtpXSA9IG1bM11bcVsxXVtxWzFdW2RdIF4gZ2V0QihzS2V5WzFdLCAzKV1cblx0XHRcdFx0XHRcdF4gZ2V0QihzS2V5WzBdLCAzKV07XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gdGZzRzAoeCkge1xuXHRcdHJldHVybiB0ZnNNWzBdW2dldEIoeCwgMCldIF4gdGZzTVsxXVtnZXRCKHgsIDEpXSBeIHRmc01bMl1bZ2V0Qih4LCAyKV1cblx0XHRcdFx0XiB0ZnNNWzNdW2dldEIoeCwgMyldO1xuXHR9XG5cdGZ1bmN0aW9uIHRmc0cxKHgpIHtcblx0XHRyZXR1cm4gdGZzTVswXVtnZXRCKHgsIDMpXSBeIHRmc01bMV1bZ2V0Qih4LCAwKV0gXiB0ZnNNWzJdW2dldEIoeCwgMSldXG5cdFx0XHRcdF4gdGZzTVszXVtnZXRCKHgsIDIpXTtcblx0fVxuXG5cdGZ1bmN0aW9uIHRmc0ZybmQociwgYmxrKSB7XG5cdFx0dmFyIGEgPSB0ZnNHMChibGtbMF0pO1xuXHRcdHZhciBiID0gdGZzRzEoYmxrWzFdKTtcblx0XHRibGtbMl0gPSByb3R3KGJsa1syXSBeIChhICsgYiArIHRmc0tleVs0ICogciArIDhdKSAmIE1BWElOVCwgMzEpO1xuXHRcdGJsa1szXSA9IHJvdHcoYmxrWzNdLCAxKSBeIChhICsgMiAqIGIgKyB0ZnNLZXlbNCAqIHIgKyA5XSkgJiBNQVhJTlQ7XG5cdFx0YSA9IHRmc0cwKGJsa1syXSk7XG5cdFx0YiA9IHRmc0cxKGJsa1szXSk7XG5cdFx0YmxrWzBdID0gcm90dyhibGtbMF0gXiAoYSArIGIgKyB0ZnNLZXlbNCAqIHIgKyAxMF0pICYgTUFYSU5ULCAzMSk7XG5cdFx0YmxrWzFdID0gcm90dyhibGtbMV0sIDEpIF4gKGEgKyAyICogYiArIHRmc0tleVs0ICogciArIDExXSkgJiBNQVhJTlQ7XG5cdH1cblxuXHRmdW5jdGlvbiB0ZnNJcm5kKGksIGJsaykge1xuXHRcdHZhciBhID0gdGZzRzAoYmxrWzBdKTtcblx0XHR2YXIgYiA9IHRmc0cxKGJsa1sxXSk7XG5cdFx0YmxrWzJdID0gcm90dyhibGtbMl0sIDEpIF4gKGEgKyBiICsgdGZzS2V5WzQgKiBpICsgMTBdKSAmIE1BWElOVDtcblx0XHRibGtbM10gPSByb3R3KGJsa1szXSBeIChhICsgMiAqIGIgKyB0ZnNLZXlbNCAqIGkgKyAxMV0pICYgTUFYSU5ULCAzMSk7XG5cdFx0YSA9IHRmc0cwKGJsa1syXSk7XG5cdFx0YiA9IHRmc0cxKGJsa1szXSk7XG5cdFx0YmxrWzBdID0gcm90dyhibGtbMF0sIDEpIF4gKGEgKyBiICsgdGZzS2V5WzQgKiBpICsgOF0pICYgTUFYSU5UO1xuXHRcdGJsa1sxXSA9IHJvdHcoYmxrWzFdIF4gKGEgKyAyICogYiArIHRmc0tleVs0ICogaSArIDldKSAmIE1BWElOVCwgMzEpO1xuXHR9XG5cblx0ZnVuY3Rpb24gdGZzQ2xvc2UoKSB7XG5cdFx0dGZzS2V5ID0gW107XG5cdFx0dGZzTSA9IFsgW10sIFtdLCBbXSwgW10gXTtcblx0fVxuXG5cdGZ1bmN0aW9uIHRmc0VuY3J5cHQoZGF0YSwgb2Zmc2V0KSB7XG5cdFx0ZGF0YUJ5dGVzID0gZGF0YTtcblx0XHRkYXRhT2Zmc2V0ID0gb2Zmc2V0O1xuXHRcdHZhciBibGsgPSBbIGdldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0KSBeIHRmc0tleVswXSxcblx0XHRcdFx0Z2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA0KSBeIHRmc0tleVsxXSxcblx0XHRcdFx0Z2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA4KSBeIHRmc0tleVsyXSxcblx0XHRcdFx0Z2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMikgXiB0ZnNLZXlbM10gXTtcblx0XHRmb3IgKCB2YXIgaiA9IDA7IGogPCA4OyBqKyspIHtcblx0XHRcdHRmc0ZybmQoaiwgYmxrKTtcblx0XHR9XG5cdFx0c2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQsIGJsa1syXSBeIHRmc0tleVs0XSk7XG5cdFx0c2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA0LCBibGtbM10gXiB0ZnNLZXlbNV0pO1xuXHRcdHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0ICsgOCwgYmxrWzBdIF4gdGZzS2V5WzZdKTtcblx0XHRzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDEyLCBibGtbMV0gXiB0ZnNLZXlbN10pO1xuXHRcdGRhdGFPZmZzZXQgKz0gMTY7XG5cdFx0cmV0dXJuIGRhdGFCeXRlcztcblx0fVxuXG5cdGZ1bmN0aW9uIHRmc0RlY3J5cHQoZGF0YSwgb2Zmc2V0KSB7XG5cdFx0ZGF0YUJ5dGVzID0gZGF0YTtcblx0XHRkYXRhT2Zmc2V0ID0gb2Zmc2V0O1xuXHRcdHZhciBibGsgPSBbIGdldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0KSBeIHRmc0tleVs0XSxcblx0XHRcdFx0Z2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA0KSBeIHRmc0tleVs1XSxcblx0XHRcdFx0Z2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA4KSBeIHRmc0tleVs2XSxcblx0XHRcdFx0Z2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMikgXiB0ZnNLZXlbN10gXTtcblx0XHRmb3IgKCB2YXIgaiA9IDc7IGogPj0gMDsgai0tKSB7XG5cdFx0XHR0ZnNJcm5kKGosIGJsayk7XG5cdFx0fVxuXHRcdHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0LCBibGtbMl0gXiB0ZnNLZXlbMF0pO1xuXHRcdHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0ICsgNCwgYmxrWzNdIF4gdGZzS2V5WzFdKTtcblx0XHRzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDgsIGJsa1swXSBeIHRmc0tleVsyXSk7XG5cdFx0c2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMiwgYmxrWzFdIF4gdGZzS2V5WzNdKTtcblx0XHRkYXRhT2Zmc2V0ICs9IDE2O1xuXHR9XG5cdFxuXHQvLyBhZGRlZCBieSBSZWN1cml0eSBMYWJzXG5cdGZ1bmN0aW9uIHRmc0ZpbmFsKCkge1xuXHRcdHJldHVybiBkYXRhQnl0ZXM7XG5cdH1cblxuXHRyZXR1cm4ge1xuXHRcdG5hbWUgOiBcInR3b2Zpc2hcIixcblx0XHRibG9ja3NpemUgOiAxMjggLyA4LFxuXHRcdG9wZW4gOiB0ZnNJbml0LFxuXHRcdGNsb3NlIDogdGZzQ2xvc2UsXG5cdFx0ZW5jcnlwdCA6IHRmc0VuY3J5cHQsXG5cdFx0ZGVjcnlwdCA6IHRmc0RlY3J5cHQsXG5cdFx0Ly8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuXHRcdGZpbmFsaXplOiB0ZnNGaW5hbFxuXHR9O1xufVxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuZnVuY3Rpb24gVEZlbmNyeXB0KGJsb2NrLCBrZXkpIHtcblx0dmFyIGJsb2NrX2NvcHkgPSBbXS5jb25jYXQoYmxvY2spO1xuXHR2YXIgdGYgPSBjcmVhdGVUd29maXNoKCk7XG5cdHRmLm9wZW4odXRpbC5zdHIyYmluKGtleSksMCk7XG5cdHZhciByZXN1bHQgPSB0Zi5lbmNyeXB0KGJsb2NrX2NvcHksIDApO1xuXHR0Zi5jbG9zZSgpO1xuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBURihrZXkpIHtcblx0dGhpcy50ZiA9IGNyZWF0ZVR3b2Zpc2goKTtcblx0dGhpcy50Zi5vcGVuKHV0aWwuc3RyMmJpbihrZXkpLDApO1xuXG5cdHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGJsb2NrKSB7XG5cdFx0cmV0dXJuIHRoaXMudGYuZW5jcnlwdChbXS5jb25jYXQoYmxvY2spLCAwKTtcblx0fVxufVxuXG5cbm1vZHVsZS5leHBvcnRzID0gVEY7XG5tb2R1bGUuZXhwb3J0cy5rZXlTaXplID0gVEYucHJvdG90eXBlLmtleVNpemUgPSAzMjtcbm1vZHVsZS5leHBvcnRzLmJsb2NrU2l6ZSA9IFRGLnByb3RvdHlwZS5ibG9ja1NpemUgPSAxNjtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBIFxuXG4vLyBUaGUgR1BHNEJyb3dzZXJzIGNyeXB0byBpbnRlcmZhY2VcblxudmFyIHJhbmRvbSA9IHJlcXVpcmUoJy4vcmFuZG9tLmpzJyksXG4gIGNpcGhlciA9IHJlcXVpcmUoJy4vY2lwaGVyJyksXG4gIGNmYiA9IHJlcXVpcmUoJy4vY2ZiLmpzJyksXG4gIHB1YmxpY0tleT0gcmVxdWlyZSgnLi9wdWJsaWNfa2V5JyksXG4gIHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4vKipcbiAqIEVuY3J5cHRzIGRhdGEgdXNpbmcgdGhlIHNwZWNpZmllZCBwdWJsaWMga2V5IG11bHRpcHJlY2lzaW9uIGludGVnZXJzIFxuICogYW5kIHRoZSBzcGVjaWZpZWQgYWxnb3JpdGhtLlxuICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEFsZ29yaXRobSB0byBiZSB1c2VkIChTZWUgUkZDNDg4MCA5LjEpXG4gKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gcHVibGljTVBJcyBBbGdvcml0aG0gZGVwZW5kZW50IG11bHRpcHJlY2lzaW9uIGludGVnZXJzXG4gKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGl9IGRhdGEgRGF0YSB0byBiZSBlbmNyeXB0ZWQgYXMgTVBJXG4gKiBAcmV0dXJuIHtvcGVucGdwX3R5cGVfbXBpW119IGlmIFJTQSBhbiBvcGVucGdwX3R5cGVfbXBpOyBcbiAqIGlmIGVsZ2FtYWwgZW5jcnlwdGlvbiBhbiBhcnJheSBvZiB0d28gb3BlbnBncF90eXBlX21waSBpcyByZXR1cm5lZDsgb3RoZXJ3aXNlIG51bGxcbiAqL1xucHVibGljS2V5RW5jcnlwdDogZnVuY3Rpb24oYWxnbywgcHVibGljTVBJcywgZGF0YSkge1xuICB2YXIgcmVzdWx0ID0gKGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaChhbGdvKSB7XG4gICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICB2YXIgbiA9IHB1YmxpY01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgZSA9IHB1YmxpY01QSXNbMV0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgbSA9IGRhdGEudG9CaWdJbnRlZ2VyKCk7XG4gICAgICByZXR1cm4gW3JzYS5lbmNyeXB0KG0sZSxuKV07XG5cbiAgICBjYXNlICdlbGdhbWFsJzpcbiAgICAgIHZhciBlbGdhbWFsID0gbmV3IHB1YmxpY0tleS5lbGdhbWFsKCk7XG4gICAgICB2YXIgcCA9IHB1YmxpY01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgZyA9IHB1YmxpY01QSXNbMV0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgeSA9IHB1YmxpY01QSXNbMl0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgbSA9IGRhdGEudG9CaWdJbnRlZ2VyKCk7XG4gICAgICByZXR1cm4gZWxnYW1hbC5lbmNyeXB0KG0sZyxwLHkpO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gIH0pKCk7XG5cbiAgcmV0dXJuIHJlc3VsdC5tYXAoZnVuY3Rpb24oYm4pIHtcbiAgICB2YXIgbXBpID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgbXBpLmZyb21CaWdJbnRlZ2VyKGJuKTtcbiAgICByZXR1cm4gbXBpO1xuICB9KTtcbn0sXG5cbi8qKlxuICogRGVjcnlwdHMgZGF0YSB1c2luZyB0aGUgc3BlY2lmaWVkIHB1YmxpYyBrZXkgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgb2YgdGhlIHByaXZhdGUga2V5LFxuICogdGhlIHNwZWNpZmllZCBzZWNyZXRNUElzIG9mIHRoZSBwcml2YXRlIGtleSBhbmQgdGhlIHNwZWNpZmllZCBhbGdvcml0aG0uXG4gKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIGJlIHVzZWQgKFNlZSBSRkM0ODgwIDkuMSlcbiAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBwdWJsaWNNUElzIEFsZ29yaXRobSBkZXBlbmRlbnQgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgXG4gKiBvZiB0aGUgcHVibGljIGtleSBwYXJ0IG9mIHRoZSBwcml2YXRlIGtleVxuICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IHNlY3JldE1QSXMgQWxnb3JpdGhtIGRlcGVuZGVudCBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBcbiAqIG9mIHRoZSBwcml2YXRlIGtleSB1c2VkXG4gKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGl9IGRhdGEgRGF0YSB0byBiZSBlbmNyeXB0ZWQgYXMgTVBJXG4gKiBAcmV0dXJuIHtvcGVucGdwX3R5cGVfbXBpfSByZXR1cm5zIGEgYmlnIGludGVnZXIgY29udGFpbmluZyB0aGUgZGVjcnlwdGVkIGRhdGE7IG90aGVyd2lzZSBudWxsXG4gKi9cblxucHVibGljS2V5RGVjcnlwdDogZnVuY3Rpb24gKGFsZ28sIGtleUludGVnZXJzLCBkYXRhSW50ZWdlcnMpIHtcbiAgdmFyIGJuID0gKGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaChhbGdvKSB7XG4gICAgY2FzZSAncnNhX2VuY3J5cHRfc2lnbic6XG4gICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICAvLyAwIGFuZCAxIGFyZSB0aGUgcHVibGljIGtleS5cbiAgICAgIHZhciBkID0ga2V5SW50ZWdlcnNbMl0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgcCA9IGtleUludGVnZXJzWzNdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgdmFyIHEgPSBrZXlJbnRlZ2Vyc1s0XS50b0JpZ0ludGVnZXIoKTtcbiAgICAgIHZhciB1ID0ga2V5SW50ZWdlcnNbNV0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICB2YXIgbSA9IGRhdGFJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgIHJldHVybiByc2EuZGVjcnlwdChtLCBkLCBwLCBxLCB1KTtcbiAgICBjYXNlICdlbGdhbWFsJzpcbiAgICAgIHZhciBlbGdhbWFsID0gbmV3IHB1YmxpY0tleS5lbGdhbWFsKCk7XG4gICAgICB2YXIgeCA9IGtleUludGVnZXJzWzNdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgdmFyIGMxID0gZGF0YUludGVnZXJzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgdmFyIGMyID0gZGF0YUludGVnZXJzWzFdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgdmFyIHAgPSBrZXlJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgIHJldHVybiBlbGdhbWFsLmRlY3J5cHQoYzEsYzIscCx4KTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9KSgpO1xuXG4gIHZhciByZXN1bHQgPSBuZXcgdHlwZV9tcGkoKTtcbiAgcmVzdWx0LmZyb21CaWdJbnRlZ2VyKGJuKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn0sXG5cbi8qKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgaW50ZWdlcnMgY29tcHJpc2luZyB0aGUgcHJpdmF0ZSBrZXkgb2YgYW4gYWxnb3JpdGhtXG4gKiBAcGFyYW0ge29wZW5wZ3AucHVibGlja2V5fSBhbGdvIFRoZSBwdWJsaWMga2V5IGFsZ29yaXRobVxuICogQHJldHVybiB7SW50ZWdlcn0gVGhlIG51bWJlciBvZiBpbnRlZ2Vycy5cbiAqL1xuZ2V0UHJpdmF0ZU1waUNvdW50OiBmdW5jdGlvbihhbGdvKSB7XG4gIHN3aXRjaChhbGdvKSB7XG4gICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgIGNhc2UgJ3JzYV9zaWduJzpcbiAgICAvLyAgIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIFJTQSBzZWNyZXQga2V5czpcbiAgICAvLyAgIC0gbXVsdGlwcmVjaXNpb24gaW50ZWdlciAoTVBJKSBvZiBSU0Egc2VjcmV0IGV4cG9uZW50IGQuXG4gICAgLy8gICAtIE1QSSBvZiBSU0Egc2VjcmV0IHByaW1lIHZhbHVlIHAuXG4gICAgLy8gICAtIE1QSSBvZiBSU0Egc2VjcmV0IHByaW1lIHZhbHVlIHEgKHAgPCBxKS5cbiAgICAvLyAgIC0gTVBJIG9mIHUsIHRoZSBtdWx0aXBsaWNhdGl2ZSBpbnZlcnNlIG9mIHAsIG1vZCBxLlxuICAgIHJldHVybiA0O1xuICBjYXNlICdlbGdhbWFsJzpcbiAgICAvLyBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBFbGdhbWFsIHNlY3JldCBrZXlzOlxuICAgIC8vICAgLSBNUEkgb2YgRWxnYW1hbCBzZWNyZXQgZXhwb25lbnQgeC5cbiAgICByZXR1cm4gMTtcbiAgY2FzZSAnZHNhJzpcbiAgICAvLyBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBEU0Egc2VjcmV0IGtleXM6XG4gICAgLy8gICAtIE1QSSBvZiBEU0Egc2VjcmV0IGV4cG9uZW50IHguXG4gICAgcmV0dXJuIDE7XG4gIGRlZmF1bHQ6XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGFsZ29yaXRobScpO1xuICB9XG59LFxuICBcbmdldFB1YmxpY01waUNvdW50OiBmdW5jdGlvbihhbGdvKSB7XG4gIC8vIC0gQSBzZXJpZXMgb2YgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgY29tcHJpc2luZyB0aGUga2V5IG1hdGVyaWFsOlxuICAvLyAgIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIFJTQSBwdWJsaWMga2V5czpcbiAgLy8gICAgICAgLSBhIG11bHRpcHJlY2lzaW9uIGludGVnZXIgKE1QSSkgb2YgUlNBIHB1YmxpYyBtb2R1bHVzIG47XG4gIC8vICAgICAgIC0gYW4gTVBJIG9mIFJTQSBwdWJsaWMgZW5jcnlwdGlvbiBleHBvbmVudCBlLlxuICBzd2l0Y2goYWxnbykge1xuICAgIGNhc2UgJ3JzYV9lbmNyeXB0JzpcbiAgICBjYXNlICdyc2FfZW5jcnlwdF9zaWduJzpcbiAgICBjYXNlICdyc2Ffc2lnbic6XG4gICAgcmV0dXJuIDI7XG5cbiAgLy8gICBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBFbGdhbWFsIHB1YmxpYyBrZXlzOlxuICAvLyAgICAgLSBNUEkgb2YgRWxnYW1hbCBwcmltZSBwO1xuICAvLyAgICAgLSBNUEkgb2YgRWxnYW1hbCBncm91cCBnZW5lcmF0b3IgZztcbiAgLy8gICAgIC0gTVBJIG9mIEVsZ2FtYWwgcHVibGljIGtleSB2YWx1ZSB5ICg9IGcqKnggbW9kIHAgd2hlcmUgeCAgaXMgc2VjcmV0KS5cbiAgICBjYXNlICdlbGdhbWFsJzpcbiAgICByZXR1cm4gMztcblxuICAvLyAgIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIERTQSBwdWJsaWMga2V5czpcbiAgLy8gICAgICAgLSBNUEkgb2YgRFNBIHByaW1lIHA7XG4gIC8vICAgICAgIC0gTVBJIG9mIERTQSBncm91cCBvcmRlciBxIChxIGlzIGEgcHJpbWUgZGl2aXNvciBvZiBwLTEpO1xuICAvLyAgICAgICAtIE1QSSBvZiBEU0EgZ3JvdXAgZ2VuZXJhdG9yIGc7XG4gIC8vICAgICAgIC0gTVBJIG9mIERTQSBwdWJsaWMta2V5IHZhbHVlIHkgKD0gZyoqeCBtb2QgcCB3aGVyZSB4ICBpcyBzZWNyZXQpLlxuICAgIGNhc2UgJ2RzYSc6XG4gICAgcmV0dXJuIDQ7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGFsZ29yaXRobS4nKTtcbiAgfVxufSxcblxuXG4vKipcbiAqIGdlbmVyYXRlIHJhbmRvbSBieXRlIHByZWZpeCBhcyBzdHJpbmcgZm9yIHRoZSBzcGVjaWZpZWQgYWxnb3JpdGhtXG4gKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIHVzZSAoc2VlIFJGQzQ4ODAgOS4yKVxuICogQHJldHVybiB7U3RyaW5nfSBSYW5kb20gYnl0ZXMgd2l0aCBsZW5ndGggZXF1YWwgdG8gdGhlIGJsb2NrXG4gKiBzaXplIG9mIHRoZSBjaXBoZXJcbiAqL1xuZ2V0UHJlZml4UmFuZG9tOiBmdW5jdGlvbihhbGdvKSB7XG4gIHJldHVybiByYW5kb20uZ2V0UmFuZG9tQnl0ZXMoY2lwaGVyW2FsZ29dLmJsb2NrU2l6ZSk7XG59LFxuXG4vKipcbiAqIEdlbmVyYXRpbmcgYSBzZXNzaW9uIGtleSBmb3IgdGhlIHNwZWNpZmllZCBzeW1tZXRyaWMgYWxnb3JpdGhtXG4gKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIHVzZSAoc2VlIFJGQzQ4ODAgOS4yKVxuICogQHJldHVybiB7U3RyaW5nfSBSYW5kb20gYnl0ZXMgYXMgYSBzdHJpbmcgdG8gYmUgdXNlZCBhcyBhIGtleVxuICovXG5nZW5lcmF0ZVNlc3Npb25LZXk6IGZ1bmN0aW9uKGFsZ28pIHtcbiAgcmV0dXJuIHJhbmRvbS5nZXRSYW5kb21CeXRlcyh0aGlzLmdldEtleUxlbmd0aChhbGdvKSk7IFxufSxcblxuLyoqXG4gKiBDcmVhdGUgYSBzZWN1cmUgcmFuZG9tIGJpZyBpbnRlZ2VyIG9mIGJpdHMgbGVuZ3RoXG4gKiBAcGFyYW0ge0ludGVnZXJ9IGJpdHMgQml0IGxlbmd0aCBvZiB0aGUgTVBJIHRvIGNyZWF0ZVxuICogQHJldHVybiB7QmlnSW50ZWdlcn0gUmVzdWx0aW5nIGJpZyBpbnRlZ2VyXG4gKi9cbmdldFJhbmRvbUJpZ0ludGVnZXI6IGZ1bmN0aW9uKGJpdHMpIHtcbiAgaWYgKGJpdHMgPCAwKSB7XG4gICAgIHJldHVybiBudWxsO1xuICB9XG4gIHZhciBudW1CeXRlcyA9IE1hdGguZmxvb3IoKGJpdHMrNykvOCk7XG5cbiAgdmFyIHJhbmRvbUJpdHMgPSByYW5kb20uZ2V0UmFuZG9tQnl0ZXMobnVtQnl0ZXMpO1xuICBpZiAoYml0cyAlIDggPiAwKSB7XG4gICAgXG4gICAgcmFuZG9tQml0cyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICAgICAgICAoTWF0aC5wb3coMixiaXRzICUgOCktMSkgJlxuICAgICAgICAgICAgcmFuZG9tQml0cy5jaGFyQ29kZUF0KDApKSArXG4gICAgICByYW5kb21CaXRzLnN1YnN0cmluZygxKTtcbiAgfVxuICB2YXIgbXBpID0gbmV3IHR5cGVfbXBpKCk7XG4gIG1waS5mcm9tQnl0ZXMocmFuZG9tQml0cyk7XG4gIHJldHVybiBtcGkudG9CaWdJbnRlZ2VyKCk7XG59LFxuXG5nZXRSYW5kb21CaWdJbnRlZ2VySW5SYW5nZTogZnVuY3Rpb24obWluLCBtYXgpIHtcbiAgaWYgKG1heC5jb21wYXJlVG8obWluKSA8PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIHJhbmdlID0gbWF4LnN1YnRyYWN0KG1pbik7XG4gIHZhciByID0gdGhpcy5nZXRSYW5kb21CaWdJbnRlZ2VyKHJhbmdlLmJpdExlbmd0aCgpKTtcbiAgd2hpbGUgKHIgPiByYW5nZSkge1xuICAgIHIgPSB0aGlzLmdldFJhbmRvbUJpZ0ludGVnZXIocmFuZ2UuYml0TGVuZ3RoKCkpO1xuICB9XG4gIHJldHVybiBtaW4uYWRkKHIpO1xufSxcblxufVxuIiwiXG52YXIgc2hhID0gcmVxdWlyZSgnLi9zaGEuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cdG1kNTogcmVxdWlyZSgnLi9tZDUuanMnKSxcblx0c2hhMTogc2hhLnNoYTEsXG5cdHNoYTI1Njogc2hhLnNoYTI1Nixcblx0c2hhMjI0OiBzaGEuc2hhMjI0LFxuXHRzaGEzODQ6IHNoYS5zaGEzODQsXG5cdHNoYTUxMjogc2hhLnNoYTUxMixcblx0cmlwZW1kOiByZXF1aXJlKCcuL3JpcGUtbWQuanMnKSxcblxuXHQvKipcblx0ICogQ3JlYXRlIGEgaGFzaCBvbiB0aGUgc3BlY2lmaWVkIGRhdGEgdXNpbmcgdGhlIHNwZWNpZmllZCBhbGdvcml0aG1cblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEhhc2ggYWxnb3JpdGhtIHR5cGUgKHNlZSBSRkM0ODgwIDkuNClcblx0ICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBiZSBoYXNoZWRcblx0ICogQHJldHVybiB7U3RyaW5nfSBoYXNoIHZhbHVlXG5cdCAqL1xuXHRkaWdlc3Q6IGZ1bmN0aW9uKGFsZ28sIGRhdGEpIHtcblx0XHRzd2l0Y2goYWxnbykge1xuXHRcdGNhc2UgMTogLy8gLSBNRDUgW0hBQ11cblx0XHRcdHJldHVybiB0aGlzLm1kNShkYXRhKTtcblx0XHRjYXNlIDI6IC8vIC0gU0hBLTEgW0ZJUFMxODBdXG5cdFx0XHRyZXR1cm4gdGhpcy5zaGExKGRhdGEpO1xuXHRcdGNhc2UgMzogLy8gLSBSSVBFLU1ELzE2MCBbSEFDXVxuXHRcdFx0cmV0dXJuIHRoaXMucmlwZW1kKGRhdGEpO1xuXHRcdGNhc2UgODogLy8gLSBTSEEyNTYgW0ZJUFMxODBdXG5cdFx0XHRyZXR1cm4gdGhpcy5zaGEyNTYoZGF0YSk7XG5cdFx0Y2FzZSA5OiAvLyAtIFNIQTM4NCBbRklQUzE4MF1cblx0XHRcdHJldHVybiB0aGlzLnNoYTM4NChkYXRhKTtcblx0XHRjYXNlIDEwOi8vIC0gU0hBNTEyIFtGSVBTMTgwXVxuXHRcdFx0cmV0dXJuIHRoaXMuc2hhNTEyKGRhdGEpO1xuXHRcdGNhc2UgMTE6Ly8gLSBTSEEyMjQgW0ZJUFMxODBdXG5cdFx0XHRyZXR1cm4gdGhpcy5zaGEyMjQoZGF0YSk7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoYXNoIGZ1bmN0aW9uLicpO1xuXHRcdH1cblx0fSxcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgaGFzaCBzaXplIGluIGJ5dGVzIG9mIHRoZSBzcGVjaWZpZWQgaGFzaCBhbGdvcml0aG0gdHlwZVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gSGFzaCBhbGdvcml0aG0gdHlwZSAoU2VlIFJGQzQ4ODAgOS40KVxuXHQgKiBAcmV0dXJuIHtJbnRlZ2VyfSBTaXplIGluIGJ5dGVzIG9mIHRoZSByZXN1bHRpbmcgaGFzaFxuXHQgKi9cblx0Z2V0SGFzaEJ5dGVMZW5ndGg6IGZ1bmN0aW9uKGFsZ28pIHtcblx0XHRzd2l0Y2goYWxnbykge1xuXHRcdGNhc2UgMTogLy8gLSBNRDUgW0hBQ11cblx0XHRcdHJldHVybiAxNjtcblx0XHRjYXNlIDI6IC8vIC0gU0hBLTEgW0ZJUFMxODBdXG5cdFx0Y2FzZSAzOiAvLyAtIFJJUEUtTUQvMTYwIFtIQUNdXG5cdFx0XHRyZXR1cm4gMjA7XG5cdFx0Y2FzZSA4OiAvLyAtIFNIQTI1NiBbRklQUzE4MF1cblx0XHRcdHJldHVybiAzMjtcblx0XHRjYXNlIDk6IC8vIC0gU0hBMzg0IFtGSVBTMTgwXVxuXHRcdFx0cmV0dXJuIDQ4XG5cdFx0Y2FzZSAxMDovLyAtIFNIQTUxMiBbRklQUzE4MF1cblx0XHRcdHJldHVybiA2NDtcblx0XHRjYXNlIDExOi8vIC0gU0hBMjI0IFtGSVBTMTgwXVxuXHRcdFx0cmV0dXJuIDI4O1xuXHRcdGRlZmF1bHQ6XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaGFzaCBhbGdvcml0aG0uJyk7XG5cdFx0fVxuXHR9XG5cbn1cblxuIiwiLyoqXG4gKiBBIGZhc3QgTUQ1IEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb25cbiAqIENvcHlyaWdodCAoYykgMjAxMiBKb3NlcGggTXllcnNcbiAqIGh0dHA6Ly93d3cubXllcnNkYWlseS5vcmcvam9zZXBoL2phdmFzY3JpcHQvbWQ1LXRleHQuaHRtbFxuICpcbiAqIFBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZCBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmVcbiAqIGFuZCBpdHMgZG9jdW1lbnRhdGlvbiBmb3IgYW55IHB1cnBvc2VzIGFuZCB3aXRob3V0XG4gKiBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQgcHJvdmlkZWQgdGhhdCB0aGlzIGNvcHlyaWdodCBub3RpY2VcbiAqIGFwcGVhcnMgaW4gYWxsIGNvcGllcy5cbiAqXG4gKiBPZiBjb3Vyc2UsIHRoaXMgc29mdCBpcyBwcm92aWRlZCBcImFzIGlzXCIgd2l0aG91dCBleHByZXNzIG9yIGltcGxpZWRcbiAqIHdhcnJhbnR5IG9mIGFueSBraW5kLlxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsLmpzJyk7XG5cbmZ1bmN0aW9uIE1ENShlbnRyZWUpIHtcblx0dmFyIGhleCA9IG1kNShlbnRyZWUpO1xuXHR2YXIgYmluID0gdXRpbC5oZXgyYmluKGhleCk7XG5cdHJldHVybiBiaW47XG59XG5cbmZ1bmN0aW9uIG1kNWN5Y2xlKHgsIGspIHtcbnZhciBhID0geFswXSwgYiA9IHhbMV0sIGMgPSB4WzJdLCBkID0geFszXTtcblxuYSA9IGZmKGEsIGIsIGMsIGQsIGtbMF0sIDcsIC02ODA4NzY5MzYpO1xuZCA9IGZmKGQsIGEsIGIsIGMsIGtbMV0sIDEyLCAtMzg5NTY0NTg2KTtcbmMgPSBmZihjLCBkLCBhLCBiLCBrWzJdLCAxNywgIDYwNjEwNTgxOSk7XG5iID0gZmYoYiwgYywgZCwgYSwga1szXSwgMjIsIC0xMDQ0NTI1MzMwKTtcbmEgPSBmZihhLCBiLCBjLCBkLCBrWzRdLCA3LCAtMTc2NDE4ODk3KTtcbmQgPSBmZihkLCBhLCBiLCBjLCBrWzVdLCAxMiwgIDEyMDAwODA0MjYpO1xuYyA9IGZmKGMsIGQsIGEsIGIsIGtbNl0sIDE3LCAtMTQ3MzIzMTM0MSk7XG5iID0gZmYoYiwgYywgZCwgYSwga1s3XSwgMjIsIC00NTcwNTk4Myk7XG5hID0gZmYoYSwgYiwgYywgZCwga1s4XSwgNywgIDE3NzAwMzU0MTYpO1xuZCA9IGZmKGQsIGEsIGIsIGMsIGtbOV0sIDEyLCAtMTk1ODQxNDQxNyk7XG5jID0gZmYoYywgZCwgYSwgYiwga1sxMF0sIDE3LCAtNDIwNjMpO1xuYiA9IGZmKGIsIGMsIGQsIGEsIGtbMTFdLCAyMiwgLTE5OTA0MDQxNjIpO1xuYSA9IGZmKGEsIGIsIGMsIGQsIGtbMTJdLCA3LCAgMTgwNDYwMzY4Mik7XG5kID0gZmYoZCwgYSwgYiwgYywga1sxM10sIDEyLCAtNDAzNDExMDEpO1xuYyA9IGZmKGMsIGQsIGEsIGIsIGtbMTRdLCAxNywgLTE1MDIwMDIyOTApO1xuYiA9IGZmKGIsIGMsIGQsIGEsIGtbMTVdLCAyMiwgIDEyMzY1MzUzMjkpO1xuXG5hID0gZ2coYSwgYiwgYywgZCwga1sxXSwgNSwgLTE2NTc5NjUxMCk7XG5kID0gZ2coZCwgYSwgYiwgYywga1s2XSwgOSwgLTEwNjk1MDE2MzIpO1xuYyA9IGdnKGMsIGQsIGEsIGIsIGtbMTFdLCAxNCwgIDY0MzcxNzcxMyk7XG5iID0gZ2coYiwgYywgZCwgYSwga1swXSwgMjAsIC0zNzM4OTczMDIpO1xuYSA9IGdnKGEsIGIsIGMsIGQsIGtbNV0sIDUsIC03MDE1NTg2OTEpO1xuZCA9IGdnKGQsIGEsIGIsIGMsIGtbMTBdLCA5LCAgMzgwMTYwODMpO1xuYyA9IGdnKGMsIGQsIGEsIGIsIGtbMTVdLCAxNCwgLTY2MDQ3ODMzNSk7XG5iID0gZ2coYiwgYywgZCwgYSwga1s0XSwgMjAsIC00MDU1Mzc4NDgpO1xuYSA9IGdnKGEsIGIsIGMsIGQsIGtbOV0sIDUsICA1Njg0NDY0MzgpO1xuZCA9IGdnKGQsIGEsIGIsIGMsIGtbMTRdLCA5LCAtMTAxOTgwMzY5MCk7XG5jID0gZ2coYywgZCwgYSwgYiwga1szXSwgMTQsIC0xODczNjM5NjEpO1xuYiA9IGdnKGIsIGMsIGQsIGEsIGtbOF0sIDIwLCAgMTE2MzUzMTUwMSk7XG5hID0gZ2coYSwgYiwgYywgZCwga1sxM10sIDUsIC0xNDQ0NjgxNDY3KTtcbmQgPSBnZyhkLCBhLCBiLCBjLCBrWzJdLCA5LCAtNTE0MDM3ODQpO1xuYyA9IGdnKGMsIGQsIGEsIGIsIGtbN10sIDE0LCAgMTczNTMyODQ3Myk7XG5iID0gZ2coYiwgYywgZCwgYSwga1sxMl0sIDIwLCAtMTkyNjYwNzczNCk7XG5cbmEgPSBoaChhLCBiLCBjLCBkLCBrWzVdLCA0LCAtMzc4NTU4KTtcbmQgPSBoaChkLCBhLCBiLCBjLCBrWzhdLCAxMSwgLTIwMjI1NzQ0NjMpO1xuYyA9IGhoKGMsIGQsIGEsIGIsIGtbMTFdLCAxNiwgIDE4MzkwMzA1NjIpO1xuYiA9IGhoKGIsIGMsIGQsIGEsIGtbMTRdLCAyMywgLTM1MzA5NTU2KTtcbmEgPSBoaChhLCBiLCBjLCBkLCBrWzFdLCA0LCAtMTUzMDk5MjA2MCk7XG5kID0gaGgoZCwgYSwgYiwgYywga1s0XSwgMTEsICAxMjcyODkzMzUzKTtcbmMgPSBoaChjLCBkLCBhLCBiLCBrWzddLCAxNiwgLTE1NTQ5NzYzMik7XG5iID0gaGgoYiwgYywgZCwgYSwga1sxMF0sIDIzLCAtMTA5NDczMDY0MCk7XG5hID0gaGgoYSwgYiwgYywgZCwga1sxM10sIDQsICA2ODEyNzkxNzQpO1xuZCA9IGhoKGQsIGEsIGIsIGMsIGtbMF0sIDExLCAtMzU4NTM3MjIyKTtcbmMgPSBoaChjLCBkLCBhLCBiLCBrWzNdLCAxNiwgLTcyMjUyMTk3OSk7XG5iID0gaGgoYiwgYywgZCwgYSwga1s2XSwgMjMsICA3NjAyOTE4OSk7XG5hID0gaGgoYSwgYiwgYywgZCwga1s5XSwgNCwgLTY0MDM2NDQ4Nyk7XG5kID0gaGgoZCwgYSwgYiwgYywga1sxMl0sIDExLCAtNDIxODE1ODM1KTtcbmMgPSBoaChjLCBkLCBhLCBiLCBrWzE1XSwgMTYsICA1MzA3NDI1MjApO1xuYiA9IGhoKGIsIGMsIGQsIGEsIGtbMl0sIDIzLCAtOTk1MzM4NjUxKTtcblxuYSA9IGlpKGEsIGIsIGMsIGQsIGtbMF0sIDYsIC0xOTg2MzA4NDQpO1xuZCA9IGlpKGQsIGEsIGIsIGMsIGtbN10sIDEwLCAgMTEyNjg5MTQxNSk7XG5jID0gaWkoYywgZCwgYSwgYiwga1sxNF0sIDE1LCAtMTQxNjM1NDkwNSk7XG5iID0gaWkoYiwgYywgZCwgYSwga1s1XSwgMjEsIC01NzQzNDA1NSk7XG5hID0gaWkoYSwgYiwgYywgZCwga1sxMl0sIDYsICAxNzAwNDg1NTcxKTtcbmQgPSBpaShkLCBhLCBiLCBjLCBrWzNdLCAxMCwgLTE4OTQ5ODY2MDYpO1xuYyA9IGlpKGMsIGQsIGEsIGIsIGtbMTBdLCAxNSwgLTEwNTE1MjMpO1xuYiA9IGlpKGIsIGMsIGQsIGEsIGtbMV0sIDIxLCAtMjA1NDkyMjc5OSk7XG5hID0gaWkoYSwgYiwgYywgZCwga1s4XSwgNiwgIDE4NzMzMTMzNTkpO1xuZCA9IGlpKGQsIGEsIGIsIGMsIGtbMTVdLCAxMCwgLTMwNjExNzQ0KTtcbmMgPSBpaShjLCBkLCBhLCBiLCBrWzZdLCAxNSwgLTE1NjAxOTgzODApO1xuYiA9IGlpKGIsIGMsIGQsIGEsIGtbMTNdLCAyMSwgIDEzMDkxNTE2NDkpO1xuYSA9IGlpKGEsIGIsIGMsIGQsIGtbNF0sIDYsIC0xNDU1MjMwNzApO1xuZCA9IGlpKGQsIGEsIGIsIGMsIGtbMTFdLCAxMCwgLTExMjAyMTAzNzkpO1xuYyA9IGlpKGMsIGQsIGEsIGIsIGtbMl0sIDE1LCAgNzE4Nzg3MjU5KTtcbmIgPSBpaShiLCBjLCBkLCBhLCBrWzldLCAyMSwgLTM0MzQ4NTU1MSk7XG5cbnhbMF0gPSBhZGQzMihhLCB4WzBdKTtcbnhbMV0gPSBhZGQzMihiLCB4WzFdKTtcbnhbMl0gPSBhZGQzMihjLCB4WzJdKTtcbnhbM10gPSBhZGQzMihkLCB4WzNdKTtcblxufVxuXG5mdW5jdGlvbiBjbW4ocSwgYSwgYiwgeCwgcywgdCkge1xuYSA9IGFkZDMyKGFkZDMyKGEsIHEpLCBhZGQzMih4LCB0KSk7XG5yZXR1cm4gYWRkMzIoKGEgPDwgcykgfCAoYSA+Pj4gKDMyIC0gcykpLCBiKTtcbn1cblxuZnVuY3Rpb24gZmYoYSwgYiwgYywgZCwgeCwgcywgdCkge1xucmV0dXJuIGNtbigoYiAmIGMpIHwgKCh+YikgJiBkKSwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIGdnKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbnJldHVybiBjbW4oKGIgJiBkKSB8IChjICYgKH5kKSksIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBoaChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG5yZXR1cm4gY21uKGIgXiBjIF4gZCwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIGlpKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbnJldHVybiBjbW4oYyBeIChiIHwgKH5kKSksIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBtZDUxKHMpIHtcbnR4dCA9ICcnO1xudmFyIG4gPSBzLmxlbmd0aCxcbnN0YXRlID0gWzE3MzI1ODQxOTMsIC0yNzE3MzM4NzksIC0xNzMyNTg0MTk0LCAyNzE3MzM4NzhdLCBpO1xuZm9yIChpPTY0OyBpPD1zLmxlbmd0aDsgaSs9NjQpIHtcbm1kNWN5Y2xlKHN0YXRlLCBtZDVibGsocy5zdWJzdHJpbmcoaS02NCwgaSkpKTtcbn1cbnMgPSBzLnN1YnN0cmluZyhpLTY0KTtcbnZhciB0YWlsID0gWzAsMCwwLDAsIDAsMCwwLDAsIDAsMCwwLDAsIDAsMCwwLDBdO1xuZm9yIChpPTA7IGk8cy5sZW5ndGg7IGkrKylcbnRhaWxbaT4+Ml0gfD0gcy5jaGFyQ29kZUF0KGkpIDw8ICgoaSU0KSA8PCAzKTtcbnRhaWxbaT4+Ml0gfD0gMHg4MCA8PCAoKGklNCkgPDwgMyk7XG5pZiAoaSA+IDU1KSB7XG5tZDVjeWNsZShzdGF0ZSwgdGFpbCk7XG5mb3IgKGk9MDsgaTwxNjsgaSsrKSB0YWlsW2ldID0gMDtcbn1cbnRhaWxbMTRdID0gbio4O1xubWQ1Y3ljbGUoc3RhdGUsIHRhaWwpO1xucmV0dXJuIHN0YXRlO1xufVxuXG4vKiB0aGVyZSBuZWVkcyB0byBiZSBzdXBwb3J0IGZvciBVbmljb2RlIGhlcmUsXG4gKiB1bmxlc3Mgd2UgcHJldGVuZCB0aGF0IHdlIGNhbiByZWRlZmluZSB0aGUgTUQtNVxuICogYWxnb3JpdGhtIGZvciBtdWx0aS1ieXRlIGNoYXJhY3RlcnMgKHBlcmhhcHNcbiAqIGJ5IGFkZGluZyBldmVyeSBmb3VyIDE2LWJpdCBjaGFyYWN0ZXJzIGFuZFxuICogc2hvcnRlbmluZyB0aGUgc3VtIHRvIDMyIGJpdHMpLiBPdGhlcndpc2VcbiAqIEkgc3VnZ2VzdCBwZXJmb3JtaW5nIE1ELTUgYXMgaWYgZXZlcnkgY2hhcmFjdGVyXG4gKiB3YXMgdHdvIGJ5dGVzLS1lLmcuLCAwMDQwIDAwMjUgPSBAJS0tYnV0IHRoZW5cbiAqIGhvdyB3aWxsIGFuIG9yZGluYXJ5IE1ELTUgc3VtIGJlIG1hdGNoZWQ/XG4gKiBUaGVyZSBpcyBubyB3YXkgdG8gc3RhbmRhcmRpemUgdGV4dCB0byBzb21ldGhpbmdcbiAqIGxpa2UgVVRGLTggYmVmb3JlIHRyYW5zZm9ybWF0aW9uOyBzcGVlZCBjb3N0IGlzXG4gKiB1dHRlcmx5IHByb2hpYml0aXZlLiBUaGUgSmF2YVNjcmlwdCBzdGFuZGFyZFxuICogaXRzZWxmIG5lZWRzIHRvIGxvb2sgYXQgdGhpczogaXQgc2hvdWxkIHN0YXJ0XG4gKiBwcm92aWRpbmcgYWNjZXNzIHRvIHN0cmluZ3MgYXMgcHJlZm9ybWVkIFVURi04XG4gKiA4LWJpdCB1bnNpZ25lZCB2YWx1ZSBhcnJheXMuXG4gKi9cbmZ1bmN0aW9uIG1kNWJsayhzKSB7IC8qIEkgZmlndXJlZCBnbG9iYWwgd2FzIGZhc3Rlci4gICAqL1xudmFyIG1kNWJsa3MgPSBbXSwgaTsgLyogQW5keSBLaW5nIHNhaWQgZG8gaXQgdGhpcyB3YXkuICovXG5mb3IgKGk9MDsgaTw2NDsgaSs9NCkge1xubWQ1Ymxrc1tpPj4yXSA9IHMuY2hhckNvZGVBdChpKVxuKyAocy5jaGFyQ29kZUF0KGkrMSkgPDwgOClcbisgKHMuY2hhckNvZGVBdChpKzIpIDw8IDE2KVxuKyAocy5jaGFyQ29kZUF0KGkrMykgPDwgMjQpO1xufVxucmV0dXJuIG1kNWJsa3M7XG59XG5cbnZhciBoZXhfY2hyID0gJzAxMjM0NTY3ODlhYmNkZWYnLnNwbGl0KCcnKTtcblxuZnVuY3Rpb24gcmhleChuKVxue1xudmFyIHM9JycsIGo9MDtcbmZvcig7IGo8NDsgaisrKVxucyArPSBoZXhfY2hyWyhuID4+IChqICogOCArIDQpKSAmIDB4MEZdXG4rIGhleF9jaHJbKG4gPj4gKGogKiA4KSkgJiAweDBGXTtcbnJldHVybiBzO1xufVxuXG5mdW5jdGlvbiBoZXgoeCkge1xuZm9yICh2YXIgaT0wOyBpPHgubGVuZ3RoOyBpKyspXG54W2ldID0gcmhleCh4W2ldKTtcbnJldHVybiB4LmpvaW4oJycpO1xufVxuXG5mdW5jdGlvbiBtZDUocykge1xucmV0dXJuIGhleChtZDUxKHMpKTtcbn1cblxuLyogdGhpcyBmdW5jdGlvbiBpcyBtdWNoIGZhc3RlcixcbnNvIGlmIHBvc3NpYmxlIHdlIHVzZSBpdC4gU29tZSBJRXNcbmFyZSB0aGUgb25seSBvbmVzIEkga25vdyBvZiB0aGF0XG5uZWVkIHRoZSBpZGlvdGljIHNlY29uZCBmdW5jdGlvbixcbmdlbmVyYXRlZCBieSBhbiBpZiBjbGF1c2UuICAqL1xuXG5mdW5jdGlvbiBhZGQzMihhLCBiKSB7XG5yZXR1cm4gKGEgKyBiKSAmIDB4RkZGRkZGRkY7XG59XG5cbmlmIChtZDUoJ2hlbGxvJykgIT0gJzVkNDE0MDJhYmM0YjJhNzZiOTcxOWQ5MTEwMTdjNTkyJykge1xuZnVuY3Rpb24gYWRkMzIoeCwgeSkge1xudmFyIGxzdyA9ICh4ICYgMHhGRkZGKSArICh5ICYgMHhGRkZGKSxcbm1zdyA9ICh4ID4+IDE2KSArICh5ID4+IDE2KSArIChsc3cgPj4gMTYpO1xucmV0dXJuIChtc3cgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG59XG59XG5cbm1vZHVsZS5leHBvcnRzID0gTUQ1XG4iLCIvKlxuICogQ3J5cHRvTVggVG9vbHNcbiAqIENvcHlyaWdodCAoQykgMjAwNCAtIDIwMDYgRGVyZWsgQnVpdGVuaHVpc1xuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMlxuICogb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSAtIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNywgVVNBLlxuICovXG5cbi8qIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSFxuICovXG5cbnZhciBSTURzaXplICAgPSAxNjA7XG52YXIgWCA9IG5ldyBBcnJheSgpO1xuXG5mdW5jdGlvbiBST0woeCwgbilcbntcbiAgcmV0dXJuIG5ldyBOdW1iZXIgKCh4IDw8IG4pIHwgKCB4ID4+PiAoMzIgLSBuKSkpO1xufVxuXG5mdW5jdGlvbiBGKHgsIHksIHopXG57XG4gIHJldHVybiBuZXcgTnVtYmVyKHggXiB5IF4geik7XG59XG5cbmZ1bmN0aW9uIEcoeCwgeSwgeilcbntcbiAgcmV0dXJuIG5ldyBOdW1iZXIoKHggJiB5KSB8ICh+eCAmIHopKTtcbn1cblxuZnVuY3Rpb24gSCh4LCB5LCB6KVxue1xuICByZXR1cm4gbmV3IE51bWJlcigoeCB8IH55KSBeIHopO1xufVxuXG5mdW5jdGlvbiBJKHgsIHksIHopXG57XG4gIHJldHVybiBuZXcgTnVtYmVyKCh4ICYgeikgfCAoeSAmIH56KSk7XG59XG5cbmZ1bmN0aW9uIEooeCwgeSwgeilcbntcbiAgcmV0dXJuIG5ldyBOdW1iZXIoeCBeICh5IHwgfnopKTtcbn1cblxuZnVuY3Rpb24gbWl4T25lUm91bmQoYSwgYiwgYywgZCwgZSwgeCwgcywgcm91bmROdW1iZXIpXG57XG4gIHN3aXRjaCAocm91bmROdW1iZXIpXG4gIHtcbiAgICBjYXNlIDAgOiBhICs9IEYoYiwgYywgZCkgKyB4ICsgMHgwMDAwMDAwMDsgYnJlYWs7XG4gICAgY2FzZSAxIDogYSArPSBHKGIsIGMsIGQpICsgeCArIDB4NWE4Mjc5OTk7IGJyZWFrO1xuICAgIGNhc2UgMiA6IGEgKz0gSChiLCBjLCBkKSArIHggKyAweDZlZDllYmExOyBicmVhaztcbiAgICBjYXNlIDMgOiBhICs9IEkoYiwgYywgZCkgKyB4ICsgMHg4ZjFiYmNkYzsgYnJlYWs7XG4gICAgY2FzZSA0IDogYSArPSBKKGIsIGMsIGQpICsgeCArIDB4YTk1M2ZkNGU7IGJyZWFrO1xuICAgIGNhc2UgNSA6IGEgKz0gSihiLCBjLCBkKSArIHggKyAweDUwYTI4YmU2OyBicmVhaztcbiAgICBjYXNlIDYgOiBhICs9IEkoYiwgYywgZCkgKyB4ICsgMHg1YzRkZDEyNDsgYnJlYWs7XG4gICAgY2FzZSA3IDogYSArPSBIKGIsIGMsIGQpICsgeCArIDB4NmQ3MDNlZjM7IGJyZWFrO1xuICAgIGNhc2UgOCA6IGEgKz0gRyhiLCBjLCBkKSArIHggKyAweDdhNmQ3NmU5OyBicmVhaztcbiAgICBjYXNlIDkgOiBhICs9IEYoYiwgYywgZCkgKyB4ICsgMHgwMDAwMDAwMDsgYnJlYWs7XG4gICAgXG4gICAgZGVmYXVsdCA6IGRvY3VtZW50LndyaXRlKFwiQm9ndXMgcm91bmQgbnVtYmVyXCIpOyBicmVhaztcbiAgfSAgXG4gIFxuICBhID0gUk9MKGEsIHMpICsgZTtcbiAgYyA9IFJPTChjLCAxMCk7XG5cbiAgYSAmPSAweGZmZmZmZmZmO1xuICBiICY9IDB4ZmZmZmZmZmY7XG4gIGMgJj0gMHhmZmZmZmZmZjtcbiAgZCAmPSAweGZmZmZmZmZmO1xuICBlICY9IDB4ZmZmZmZmZmY7XG5cbiAgdmFyIHJldEJsb2NrID0gbmV3IEFycmF5KCk7XG4gIHJldEJsb2NrWzBdID0gYTtcbiAgcmV0QmxvY2tbMV0gPSBiO1xuICByZXRCbG9ja1syXSA9IGM7XG4gIHJldEJsb2NrWzNdID0gZDtcbiAgcmV0QmxvY2tbNF0gPSBlO1xuICByZXRCbG9ja1s1XSA9IHg7XG4gIHJldEJsb2NrWzZdID0gcztcblxuICByZXR1cm4gcmV0QmxvY2s7XG59XG5cbmZ1bmN0aW9uIE1EaW5pdCAoTURidWYpXG57XG4gIE1EYnVmWzBdID0gMHg2NzQ1MjMwMTtcbiAgTURidWZbMV0gPSAweGVmY2RhYjg5O1xuICBNRGJ1ZlsyXSA9IDB4OThiYWRjZmU7XG4gIE1EYnVmWzNdID0gMHgxMDMyNTQ3NjtcbiAgTURidWZbNF0gPSAweGMzZDJlMWYwO1xufVxuXG52YXIgUk9McyA9IFtcbiAgWzExLCAxNCwgMTUsIDEyLCAgNSwgIDgsICA3LCAgOSwgMTEsIDEzLCAxNCwgMTUsICA2LCAgNywgIDksICA4XSxcbiAgWyA3LCAgNiwgIDgsIDEzLCAxMSwgIDksICA3LCAxNSwgIDcsIDEyLCAxNSwgIDksIDExLCAgNywgMTMsIDEyXSxcbiAgWzExLCAxMywgIDYsICA3LCAxNCwgIDksIDEzLCAxNSwgMTQsICA4LCAxMywgIDYsICA1LCAxMiwgIDcsICA1XSxcbiAgWzExLCAxMiwgMTQsIDE1LCAxNCwgMTUsICA5LCAgOCwgIDksIDE0LCAgNSwgIDYsICA4LCAgNiwgIDUsIDEyXSxcbiAgWyA5LCAxNSwgIDUsIDExLCAgNiwgIDgsIDEzLCAxMiwgIDUsIDEyLCAxMywgMTQsIDExLCAgOCwgIDUsICA2XSxcbiAgWyA4LCAgOSwgIDksIDExLCAxMywgMTUsIDE1LCAgNSwgIDcsICA3LCAgOCwgMTEsIDE0LCAxNCwgMTIsICA2XSxcbiAgWyA5LCAxMywgMTUsICA3LCAxMiwgIDgsICA5LCAxMSwgIDcsICA3LCAxMiwgIDcsICA2LCAxNSwgMTMsIDExXSxcbiAgWyA5LCAgNywgMTUsIDExLCAgOCwgIDYsICA2LCAxNCwgMTIsIDEzLCAgNSwgMTQsIDEzLCAxMywgIDcsICA1XSxcbiAgWzE1LCAgNSwgIDgsIDExLCAxNCwgMTQsICA2LCAxNCwgIDYsICA5LCAxMiwgIDksIDEyLCAgNSwgMTUsICA4XSxcbiAgWyA4LCAgNSwgMTIsICA5LCAxMiwgIDUsIDE0LCAgNiwgIDgsIDEzLCAgNiwgIDUsIDE1LCAxMywgMTEsIDExXVxuXTtcblxudmFyIGluZGV4ZXMgPSBbXG4gIFsgMCwgIDEsICAyLCAgMywgIDQsICA1LCAgNiwgIDcsICA4LCAgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNV0sXG4gIFsgNywgIDQsIDEzLCAgMSwgMTAsICA2LCAxNSwgIDMsIDEyLCAgMCwgIDksICA1LCAgMiwgMTQsIDExLCAgOF0sXG4gIFsgMywgMTAsIDE0LCAgNCwgIDksIDE1LCAgOCwgIDEsICAyLCAgNywgIDAsICA2LCAxMywgMTEsICA1LCAxMl0sXG4gIFsgMSwgIDksIDExLCAxMCwgIDAsICA4LCAxMiwgIDQsIDEzLCAgMywgIDcsIDE1LCAxNCwgIDUsICA2LCAgMl0sXG4gIFsgNCwgIDAsICA1LCAgOSwgIDcsIDEyLCAgMiwgMTAsIDE0LCAgMSwgIDMsICA4LCAxMSwgIDYsIDE1LCAxM10sXG4gIFsgNSwgMTQsICA3LCAgMCwgIDksICAyLCAxMSwgIDQsIDEzLCAgNiwgMTUsICA4LCAgMSwgMTAsICAzLCAxMl0sXG4gIFsgNiwgMTEsICAzLCAgNywgIDAsIDEzLCAgNSwgMTAsIDE0LCAxNSwgIDgsIDEyLCAgNCwgIDksICAxLCAgMl0sXG4gIFsxNSwgIDUsICAxLCAgMywgIDcsIDE0LCAgNiwgIDksIDExLCAgOCwgMTIsICAyLCAxMCwgIDAsICA0LCAxM10sXG4gIFsgOCwgIDYsICA0LCAgMSwgIDMsIDExLCAxNSwgIDAsICA1LCAxMiwgIDIsIDEzLCAgOSwgIDcsIDEwLCAxNF0sXG4gIFsxMiwgMTUsIDEwLCAgNCwgIDEsICA1LCAgOCwgIDcsICA2LCAgMiwgMTMsIDE0LCAgMCwgIDMsICA5LCAxMV1cbl07XG5cbmZ1bmN0aW9uIGNvbXByZXNzIChNRGJ1ZiwgWClcbntcbiAgYmxvY2tBID0gbmV3IEFycmF5KCk7XG4gIGJsb2NrQiA9IG5ldyBBcnJheSgpO1xuXG4gIHZhciByZXRCbG9jaztcblxuICBmb3IgKHZhciBpPTA7IGkgPCA1OyBpKyspXG4gIHtcbiAgICBibG9ja0FbaV0gPSBuZXcgTnVtYmVyKE1EYnVmW2ldKTtcbiAgICBibG9ja0JbaV0gPSBuZXcgTnVtYmVyKE1EYnVmW2ldKTtcbiAgfVxuXG4gIHZhciBzdGVwID0gMDtcbiAgZm9yICh2YXIgaiA9IDA7IGogPCA1OyBqKyspXG4gIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspXG4gICAge1xuICAgICAgcmV0QmxvY2sgPSBtaXhPbmVSb3VuZChcbiAgICAgICAgYmxvY2tBWyhzdGVwKzApICUgNV0sXG4gICAgICAgIGJsb2NrQVsoc3RlcCsxKSAlIDVdLCAgIFxuICAgICAgICBibG9ja0FbKHN0ZXArMikgJSA1XSwgICBcbiAgICAgICAgYmxvY2tBWyhzdGVwKzMpICUgNV0sICAgXG4gICAgICAgIGJsb2NrQVsoc3RlcCs0KSAlIDVdLCAgXG4gICAgICAgIFhbaW5kZXhlc1tqXVtpXV0sIFxuICAgICAgICBST0xzW2pdW2ldLFxuICAgICAgICBqXG4gICAgICApO1xuXG4gICAgICBibG9ja0FbKHN0ZXArMCkgJSA1XSA9IHJldEJsb2NrWzBdO1xuICAgICAgYmxvY2tBWyhzdGVwKzEpICUgNV0gPSByZXRCbG9ja1sxXTtcbiAgICAgIGJsb2NrQVsoc3RlcCsyKSAlIDVdID0gcmV0QmxvY2tbMl07XG4gICAgICBibG9ja0FbKHN0ZXArMykgJSA1XSA9IHJldEJsb2NrWzNdO1xuICAgICAgYmxvY2tBWyhzdGVwKzQpICUgNV0gPSByZXRCbG9ja1s0XTtcblxuICAgICAgc3RlcCArPSA0O1xuICAgIH1cbiAgfVxuXG4gIHN0ZXAgPSAwO1xuICBmb3IgKHZhciBqID0gNTsgaiA8IDEwOyBqKyspXG4gIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspXG4gICAgeyAgXG4gICAgICByZXRCbG9jayA9IG1peE9uZVJvdW5kKFxuICAgICAgICBibG9ja0JbKHN0ZXArMCkgJSA1XSwgXG4gICAgICAgIGJsb2NrQlsoc3RlcCsxKSAlIDVdLCBcbiAgICAgICAgYmxvY2tCWyhzdGVwKzIpICUgNV0sIFxuICAgICAgICBibG9ja0JbKHN0ZXArMykgJSA1XSwgXG4gICAgICAgIGJsb2NrQlsoc3RlcCs0KSAlIDVdLCAgXG4gICAgICAgIFhbaW5kZXhlc1tqXVtpXV0sIFxuICAgICAgICBST0xzW2pdW2ldLFxuICAgICAgICBqXG4gICAgICApO1xuXG4gICAgICBibG9ja0JbKHN0ZXArMCkgJSA1XSA9IHJldEJsb2NrWzBdO1xuICAgICAgYmxvY2tCWyhzdGVwKzEpICUgNV0gPSByZXRCbG9ja1sxXTtcbiAgICAgIGJsb2NrQlsoc3RlcCsyKSAlIDVdID0gcmV0QmxvY2tbMl07XG4gICAgICBibG9ja0JbKHN0ZXArMykgJSA1XSA9IHJldEJsb2NrWzNdO1xuICAgICAgYmxvY2tCWyhzdGVwKzQpICUgNV0gPSByZXRCbG9ja1s0XTtcblxuICAgICAgc3RlcCArPSA0O1xuICAgIH1cbiAgfVxuXG4gIGJsb2NrQlszXSArPSBibG9ja0FbMl0gKyBNRGJ1ZlsxXTtcbiAgTURidWZbMV0gID0gTURidWZbMl0gKyBibG9ja0FbM10gKyBibG9ja0JbNF07XG4gIE1EYnVmWzJdICA9IE1EYnVmWzNdICsgYmxvY2tBWzRdICsgYmxvY2tCWzBdO1xuICBNRGJ1ZlszXSAgPSBNRGJ1Zls0XSArIGJsb2NrQVswXSArIGJsb2NrQlsxXTtcbiAgTURidWZbNF0gID0gTURidWZbMF0gKyBibG9ja0FbMV0gKyBibG9ja0JbMl07XG4gIE1EYnVmWzBdICA9IGJsb2NrQlszXTtcbn1cblxuZnVuY3Rpb24gemVyb1goWClcbntcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7IFhbaV0gPSAwOyB9XG59XG5cbmZ1bmN0aW9uIE1EZmluaXNoIChNRGJ1Ziwgc3RycHRyLCBsc3dsZW4sIG1zd2xlbilcbntcbiAgdmFyIFggPSBuZXcgQXJyYXkoMTYpO1xuICB6ZXJvWChYKTtcblxuICB2YXIgaiA9IDA7XG4gIGZvciAodmFyIGk9MDsgaSA8IChsc3dsZW4gJiA2Myk7IGkrKylcbiAge1xuICAgIFhbaSA+Pj4gMl0gXj0gKHN0cnB0ci5jaGFyQ29kZUF0KGorKykgJiAyNTUpIDw8ICg4ICogKGkgJiAzKSk7XG4gIH1cblxuICBYWyhsc3dsZW4gPj4+IDIpICYgMTVdIF49IDEgPDwgKDggKiAobHN3bGVuICYgMykgKyA3KTtcblxuICBpZiAoKGxzd2xlbiAmIDYzKSA+IDU1KVxuICB7XG4gICAgY29tcHJlc3MoTURidWYsIFgpO1xuICAgIHZhciBYID0gbmV3IEFycmF5KDE2KTtcbiAgICB6ZXJvWChYKTtcbiAgfVxuXG4gIFhbMTRdID0gbHN3bGVuIDw8IDM7XG4gIFhbMTVdID0gKGxzd2xlbiA+Pj4gMjkpIHwgKG1zd2xlbiA8PCAzKTtcblxuICBjb21wcmVzcyhNRGJ1ZiwgWCk7XG59XG5cbmZ1bmN0aW9uIEJZVEVTX1RPX0RXT1JEKGZvdXJDaGFycylcbntcbiAgdmFyIHRtcCAgPSAoZm91ckNoYXJzLmNoYXJDb2RlQXQoMykgJiAyNTUpIDw8IDI0O1xuICB0bXAgICB8PSAoZm91ckNoYXJzLmNoYXJDb2RlQXQoMikgJiAyNTUpIDw8IDE2O1xuICB0bXAgICB8PSAoZm91ckNoYXJzLmNoYXJDb2RlQXQoMSkgJiAyNTUpIDw8IDg7XG4gIHRtcCAgIHw9IChmb3VyQ2hhcnMuY2hhckNvZGVBdCgwKSAmIDI1NSk7ICBcblxuICByZXR1cm4gdG1wO1xufVxuXG5mdW5jdGlvbiBSTUQobWVzc2FnZSlcbntcbiAgdmFyIE1EYnVmICAgPSBuZXcgQXJyYXkoUk1Ec2l6ZSAvIDMyKTtcbiAgdmFyIGhhc2hjb2RlICAgPSBuZXcgQXJyYXkoUk1Ec2l6ZSAvIDgpO1xuICB2YXIgbGVuZ3RoOyAgXG4gIHZhciBuYnl0ZXM7XG5cbiAgTURpbml0KE1EYnVmKTtcbiAgbGVuZ3RoID0gbWVzc2FnZS5sZW5ndGg7XG5cbiAgdmFyIFggPSBuZXcgQXJyYXkoMTYpO1xuICB6ZXJvWChYKTtcblxuICB2YXIgaj0wO1xuICBmb3IgKHZhciBuYnl0ZXM9bGVuZ3RoOyBuYnl0ZXMgPiA2MzsgbmJ5dGVzIC09IDY0KVxuICB7XG4gICAgZm9yICh2YXIgaT0wOyBpIDwgMTY7IGkrKylcbiAgICB7XG4gICAgICBYW2ldID0gQllURVNfVE9fRFdPUkQobWVzc2FnZS5zdWJzdHIoaiwgNCkpO1xuICAgICAgaiArPSA0O1xuICAgIH1cbiAgICBjb21wcmVzcyhNRGJ1ZiwgWCk7XG4gIH1cblxuICBNRGZpbmlzaChNRGJ1ZiwgbWVzc2FnZS5zdWJzdHIoaiksIGxlbmd0aCwgMCk7XG5cbiAgZm9yICh2YXIgaT0wOyBpIDwgUk1Ec2l6ZSAvIDg7IGkgKz0gNClcbiAge1xuICAgIGhhc2hjb2RlW2ldICAgPSAgTURidWZbaSA+Pj4gMl0gICAmIDI1NTtcbiAgICBoYXNoY29kZVtpKzFdID0gKE1EYnVmW2kgPj4+IDJdID4+PiA4KSAgICYgMjU1O1xuICAgIGhhc2hjb2RlW2krMl0gPSAoTURidWZbaSA+Pj4gMl0gPj4+IDE2KSAmIDI1NTtcbiAgICBoYXNoY29kZVtpKzNdID0gKE1EYnVmW2kgPj4+IDJdID4+PiAyNCkgJiAyNTU7XG4gIH1cblxuICByZXR1cm4gaGFzaGNvZGU7XG59XG5cblxuZnVuY3Rpb24gUk1Ec3RyaW5nKG1lc3NhZ2UpXG57XG4gIHZhciBoYXNoY29kZSA9IFJNRChtZXNzYWdlKTtcbiAgdmFyIHJldFN0cmluZyA9IFwiXCI7XG5cbiAgZm9yICh2YXIgaT0wOyBpIDwgUk1Ec2l6ZS84OyBpKyspXG4gIHtcbiAgICByZXRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShoYXNoY29kZVtpXSk7XG4gIH0gIFxuXG4gIHJldHVybiByZXRTdHJpbmc7ICBcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBSTURzdHJpbmc7XG4iLCIvKiBBIEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgdGhlIFNIQSBmYW1pbHkgb2YgaGFzaGVzLCBhcyBkZWZpbmVkIGluIEZJUFMgXG4gKiBQVUIgMTgwLTIgYXMgd2VsbCBhcyB0aGUgY29ycmVzcG9uZGluZyBITUFDIGltcGxlbWVudGF0aW9uIGFzIGRlZmluZWQgaW5cbiAqIEZJUFMgUFVCIDE5OGFcbiAqXG4gKiBWZXJzaW9uIDEuMyBDb3B5cmlnaHQgQnJpYW4gVHVyZWsgMjAwOC0yMDEwXG4gKiBEaXN0cmlidXRlZCB1bmRlciB0aGUgQlNEIExpY2Vuc2VcbiAqIFNlZSBodHRwOi8vanNzaGEuc291cmNlZm9yZ2UubmV0LyBmb3IgbW9yZSBpbmZvcm1hdGlvblxuICpcbiAqIFNldmVyYWwgZnVuY3Rpb25zIHRha2VuIGZyb20gUGF1bCBKb2huc29uXG4gKi9cblxuLyogTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIXG4gKiBcbiAqIFRoaXMgY29kZSBoYXMgYmVlbiBzbGlnaHRseSBtb2RpZmllZCBkaXJlY3Qgc3RyaW5nIG91dHB1dDpcbiAqIC0gYmluMmJzdHIgaGFzIGJlZW4gYWRkZWRcbiAqIC0gZm9sbG93aW5nIHdyYXBwZXJzIG9mIHRoaXMgbGlicmFyeSBoYXZlIGJlZW4gYWRkZWQ6XG4gKiAgIC0gc3RyX3NoYTFcbiAqICAgLSBzdHJfc2hhMjU2XG4gKiAgIC0gc3RyX3NoYTIyNFxuICogICAtIHN0cl9zaGEzODRcbiAqICAgLSBzdHJfc2hhNTEyXG4gKi9cblxudmFyIGpzU0hBID0gKGZ1bmN0aW9uICgpIHtcblx0XG5cdC8qXG5cdCAqIENvbmZpZ3VyYWJsZSB2YXJpYWJsZXMuIERlZmF1bHRzIHR5cGljYWxseSB3b3JrXG5cdCAqL1xuXHQvKiBOdW1iZXIgb2YgQml0cyBQZXIgY2hhcmFjdGVyICg4IGZvciBBU0NJSSwgMTYgZm9yIFVuaWNvZGUpICovXG5cdHZhciBjaGFyU2l6ZSA9IDgsIFxuXHQvKiBiYXNlLTY0IHBhZCBjaGFyYWN0ZXIuIFwiPVwiIGZvciBzdHJpY3QgUkZDIGNvbXBsaWFuY2UgKi9cblx0YjY0cGFkID0gXCJcIiwgXG5cdC8qIGhleCBvdXRwdXQgZm9ybWF0LiAwIC0gbG93ZXJjYXNlOyAxIC0gdXBwZXJjYXNlICovXG5cdGhleENhc2UgPSAwLCBcblxuXHQvKlxuXHQgKiBJbnRfNjQgaXMgYSBvYmplY3QgZm9yIDIgMzItYml0IG51bWJlcnMgZW11bGF0aW5nIGEgNjQtYml0IG51bWJlclxuXHQgKlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHtOdW1iZXJ9IG1zaW50XzMyIFRoZSBtb3N0IHNpZ25pZmljYW50IDMyLWJpdHMgb2YgYSA2NC1iaXQgbnVtYmVyXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBsc2ludF8zMiBUaGUgbGVhc3Qgc2lnbmlmaWNhbnQgMzItYml0cyBvZiBhIDY0LWJpdCBudW1iZXJcblx0ICovXG5cdEludF82NCA9IGZ1bmN0aW9uIChtc2ludF8zMiwgbHNpbnRfMzIpXG5cdHtcblx0XHR0aGlzLmhpZ2hPcmRlciA9IG1zaW50XzMyO1xuXHRcdHRoaXMubG93T3JkZXIgPSBsc2ludF8zMjtcblx0fSxcblxuXHQvKlxuXHQgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGFuIGFycmF5IG9mIGJpZy1lbmRpYW4gd29yZHNcblx0ICogSWYgY2hhclNpemUgaXMgQVNDSUksIGNoYXJhY3RlcnMgPjI1NSBoYXZlIHRoZWlyIGhpLWJ5dGUgc2lsZW50bHlcblx0ICogaWdub3JlZC5cblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gYmUgY29udmVydGVkIHRvIGJpbmFyeSByZXByZXNlbnRhdGlvblxuXHQgKiBAcmV0dXJuIEludGVnZXIgYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhcmFtZXRlclxuXHQgKi9cblx0c3RyMmJpbmIgPSBmdW5jdGlvbiAoc3RyKVxuXHR7XG5cdFx0dmFyIGJpbiA9IFtdLCBtYXNrID0gKDEgPDwgY2hhclNpemUpIC0gMSxcblx0XHRcdGxlbmd0aCA9IHN0ci5sZW5ndGggKiBjaGFyU2l6ZSwgaTtcblxuXHRcdGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gY2hhclNpemUpXG5cdFx0e1xuXHRcdFx0YmluW2kgPj4gNV0gfD0gKHN0ci5jaGFyQ29kZUF0KGkgLyBjaGFyU2l6ZSkgJiBtYXNrKSA8PFxuXHRcdFx0XHQoMzIgLSBjaGFyU2l6ZSAtIChpICUgMzIpKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gYmluO1xuXHR9LFxuXG5cdC8qXG5cdCAqIENvbnZlcnQgYSBoZXggc3RyaW5nIHRvIGFuIGFycmF5IG9mIGJpZy1lbmRpYW4gd29yZHNcblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gYmUgY29udmVydGVkIHRvIGJpbmFyeSByZXByZXNlbnRhdGlvblxuXHQgKiBAcmV0dXJuIEludGVnZXIgYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhcmFtZXRlclxuXHQgKi9cblx0aGV4MmJpbmIgPSBmdW5jdGlvbiAoc3RyKVxuXHR7XG5cdFx0dmFyIGJpbiA9IFtdLCBsZW5ndGggPSBzdHIubGVuZ3RoLCBpLCBudW07XG5cblx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDIpXG5cdFx0e1xuXHRcdFx0bnVtID0gcGFyc2VJbnQoc3RyLnN1YnN0cihpLCAyKSwgMTYpO1xuXHRcdFx0aWYgKCFpc05hTihudW0pKVxuXHRcdFx0e1xuXHRcdFx0XHRiaW5baSA+PiAzXSB8PSBudW0gPDwgKDI0IC0gKDQgKiAoaSAlIDgpKSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiBcIklOVkFMSUQgSEVYIFNUUklOR1wiO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBiaW47XG5cdH0sXG5cblx0Lypcblx0ICogQ29udmVydCBhbiBhcnJheSBvZiBiaWctZW5kaWFuIHdvcmRzIHRvIGEgaGV4IHN0cmluZy5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtBcnJheX0gYmluYXJyYXkgQXJyYXkgb2YgaW50ZWdlcnMgdG8gYmUgY29udmVydGVkIHRvIGhleGlkZWNpbWFsXG5cdCAqXHQgcmVwcmVzZW50YXRpb25cblx0ICogQHJldHVybiBIZXhpZGVjaW1hbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcGFyYW1ldGVyIGluIFN0cmluZyBmb3JtXG5cdCAqL1xuXHRiaW5iMmhleCA9IGZ1bmN0aW9uIChiaW5hcnJheSlcblx0e1xuXHRcdHZhciBoZXhfdGFiID0gKGhleENhc2UpID8gXCIwMTIzNDU2Nzg5QUJDREVGXCIgOiBcIjAxMjM0NTY3ODlhYmNkZWZcIixcblx0XHRcdHN0ciA9IFwiXCIsIGxlbmd0aCA9IGJpbmFycmF5Lmxlbmd0aCAqIDQsIGksIHNyY0J5dGU7XG5cblx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpXG5cdFx0e1xuXHRcdFx0c3JjQnl0ZSA9IGJpbmFycmF5W2kgPj4gMl0gPj4gKCgzIC0gKGkgJSA0KSkgKiA4KTtcblx0XHRcdHN0ciArPSBoZXhfdGFiLmNoYXJBdCgoc3JjQnl0ZSA+PiA0KSAmIDB4RikgK1xuXHRcdFx0XHRoZXhfdGFiLmNoYXJBdChzcmNCeXRlICYgMHhGKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gc3RyO1xuXHR9LFxuXG5cdC8qXG5cdCAqIENvbnZlcnQgYW4gYXJyYXkgb2YgYmlnLWVuZGlhbiB3b3JkcyB0byBhIGJhc2UtNjQgc3RyaW5nXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7QXJyYXl9IGJpbmFycmF5IEFycmF5IG9mIGludGVnZXJzIHRvIGJlIGNvbnZlcnRlZCB0byBiYXNlLTY0XG5cdCAqXHQgcmVwcmVzZW50YXRpb25cblx0ICogQHJldHVybiBCYXNlLTY0IGVuY29kZWQgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhcmFtZXRlciBpbiBTdHJpbmcgZm9ybVxuXHQgKi9cblx0YmluYjJiNjQgPSBmdW5jdGlvbiAoYmluYXJyYXkpXG5cdHtcblx0XHR2YXIgdGFiID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XCIgK1xuXHRcdFx0XCIwMTIzNDU2Nzg5Ky9cIiwgc3RyID0gXCJcIiwgbGVuZ3RoID0gYmluYXJyYXkubGVuZ3RoICogNCwgaSwgaixcblx0XHRcdHRyaXBsZXQ7XG5cblx0XHRmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpXG5cdFx0e1xuXHRcdFx0dHJpcGxldCA9ICgoKGJpbmFycmF5W2kgPj4gMl0gPj4gOCAqICgzIC0gaSAlIDQpKSAmIDB4RkYpIDw8IDE2KSB8XG5cdFx0XHRcdCgoKGJpbmFycmF5W2kgKyAxID4+IDJdID4+IDggKiAoMyAtIChpICsgMSkgJSA0KSkgJiAweEZGKSA8PCA4KSB8XG5cdFx0XHRcdCgoYmluYXJyYXlbaSArIDIgPj4gMl0gPj4gOCAqICgzIC0gKGkgKyAyKSAlIDQpKSAmIDB4RkYpO1xuXHRcdFx0Zm9yIChqID0gMDsgaiA8IDQ7IGogKz0gMSlcblx0XHRcdHtcblx0XHRcdFx0aWYgKGkgKiA4ICsgaiAqIDYgPD0gYmluYXJyYXkubGVuZ3RoICogMzIpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRzdHIgKz0gdGFiLmNoYXJBdCgodHJpcGxldCA+PiA2ICogKDMgLSBqKSkgJiAweDNGKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRzdHIgKz0gYjY0cGFkO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBzdHI7XG5cdH0sXG5cblx0Lypcblx0ICogQ29udmVydCBhbiBhcnJheSBvZiBiaWctZW5kaWFuIHdvcmRzIHRvIGEgc3RyaW5nXG5cdCAqL1xuXHRiaW5iMnN0ciA9IGZ1bmN0aW9uIChiaW4pXG5cdHtcblx0ICB2YXIgc3RyID0gXCJcIjtcblx0ICB2YXIgbWFzayA9ICgxIDw8IDgpIC0gMTtcblx0ICBmb3IodmFyIGkgPSAwOyBpIDwgYmluLmxlbmd0aCAqIDMyOyBpICs9IDgpXG5cdCAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoYmluW2k+PjVdID4+PiAoMjQgLSBpJTMyKSkgJiBtYXNrKTtcblx0ICByZXR1cm4gc3RyO1xuXHR9LFxuXHQvKlxuXHQgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIGNpcmN1bGFyIHJvdGF0ZSBsZWZ0XG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcblx0ICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGNpcmN1bGFybHkgYnkgbiBiaXRzXG5cdCAqL1xuXHRyb3RsXzMyID0gZnVuY3Rpb24gKHgsIG4pXG5cdHtcblx0XHRyZXR1cm4gKHggPDwgbikgfCAoeCA+Pj4gKDMyIC0gbikpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgY2lyY3VsYXIgcm90YXRlIHJpZ2h0XG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcblx0ICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGNpcmN1bGFybHkgYnkgbiBiaXRzXG5cdCAqL1xuXHRyb3RyXzMyID0gZnVuY3Rpb24gKHgsIG4pXG5cdHtcblx0XHRyZXR1cm4gKHggPj4+IG4pIHwgKHggPDwgKDMyIC0gbikpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgY2lyY3VsYXIgcm90YXRlIHJpZ2h0XG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcblx0ICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGNpcmN1bGFybHkgYnkgbiBiaXRzXG5cdCAqL1xuXHRyb3RyXzY0ID0gZnVuY3Rpb24gKHgsIG4pXG5cdHtcblx0XHRpZiAobiA8PSAzMilcblx0XHR7XG5cdFx0XHRyZXR1cm4gbmV3IEludF82NChcblx0XHRcdFx0XHQoeC5oaWdoT3JkZXIgPj4+IG4pIHwgKHgubG93T3JkZXIgPDwgKDMyIC0gbikpLFxuXHRcdFx0XHRcdCh4Lmxvd09yZGVyID4+PiBuKSB8ICh4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKSlcblx0XHRcdFx0KTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdHJldHVybiBuZXcgSW50XzY0KFxuXHRcdFx0XHRcdCh4Lmxvd09yZGVyID4+PiBuKSB8ICh4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKSksXG5cdFx0XHRcdFx0KHguaGlnaE9yZGVyID4+PiBuKSB8ICh4Lmxvd09yZGVyIDw8ICgzMiAtIG4pKVxuXHRcdFx0XHQpO1xuXHRcdH1cblx0fSxcblxuXHQvKlxuXHQgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHNoaWZ0IHJpZ2h0XG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcblx0ICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGJ5IG4gYml0c1xuXHQgKi9cblx0c2hyXzMyID0gZnVuY3Rpb24gKHgsIG4pXG5cdHtcblx0XHRyZXR1cm4geCA+Pj4gbjtcblx0fSxcblxuXHQvKlxuXHQgKiBUaGUgNjQtYml0IGltcGxlbWVudGF0aW9uIG9mIHNoaWZ0IHJpZ2h0XG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcblx0ICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGJ5IG4gYml0c1xuXHQgKi9cblx0c2hyXzY0ID0gZnVuY3Rpb24gKHgsIG4pXG5cdHtcblx0XHRpZiAobiA8PSAzMilcblx0XHR7XG5cdFx0XHRyZXR1cm4gbmV3IEludF82NChcblx0XHRcdFx0XHR4LmhpZ2hPcmRlciA+Pj4gbixcblx0XHRcdFx0XHR4Lmxvd09yZGVyID4+PiBuIHwgKHguaGlnaE9yZGVyIDw8ICgzMiAtIG4pKVxuXHRcdFx0XHQpO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0cmV0dXJuIG5ldyBJbnRfNjQoXG5cdFx0XHRcdFx0MCxcblx0XHRcdFx0XHR4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKVxuXHRcdFx0XHQpO1xuXHRcdH1cblx0fSxcblxuXHQvKlxuXHQgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBQYXJpdHkgZnVuY3Rpb25cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG5cdCAqIEBwYXJhbSB7TnVtYmVyfSB5IFRoZSBzZWNvbmQgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHBhcmFtIHtOdW1iZXJ9IHogVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG5cdCAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cblx0ICovXG5cdHBhcml0eV8zMiA9IGZ1bmN0aW9uICh4LCB5LCB6KVxuXHR7XG5cdFx0cmV0dXJuIHggXiB5IF4gejtcblx0fSxcblxuXHQvKlxuXHQgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBDaCBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHBhcmFtIHtOdW1iZXJ9IHkgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0geiBUaGUgdGhpcmQgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0Y2hfMzIgPSBmdW5jdGlvbiAoeCwgeSwgeilcblx0e1xuXHRcdHJldHVybiAoeCAmIHkpIF4gKH54ICYgeik7XG5cdH0sXG5cblx0Lypcblx0ICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgQ2ggZnVuY3Rpb25cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIGZpcnN0IDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG5cdCAqIEBwYXJhbSB7SW50XzY0fSB5IFRoZSBzZWNvbmQgNjQtYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHBhcmFtIHtJbnRfNjR9IHogVGhlIHRoaXJkIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG5cdCAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cblx0ICovXG5cdGNoXzY0ID0gZnVuY3Rpb24gKHgsIHksIHopXG5cdHtcblx0XHRyZXR1cm4gbmV3IEludF82NChcblx0XHRcdFx0KHguaGlnaE9yZGVyICYgeS5oaWdoT3JkZXIpIF4gKH54LmhpZ2hPcmRlciAmIHouaGlnaE9yZGVyKSxcblx0XHRcdFx0KHgubG93T3JkZXIgJiB5Lmxvd09yZGVyKSBeICh+eC5sb3dPcmRlciAmIHoubG93T3JkZXIpXG5cdFx0XHQpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIE1haiBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHBhcmFtIHtOdW1iZXJ9IHkgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge051bWJlcn0geiBUaGUgdGhpcmQgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0bWFqXzMyID0gZnVuY3Rpb24gKHgsIHksIHopXG5cdHtcblx0XHRyZXR1cm4gKHggJiB5KSBeICh4ICYgeikgXiAoeSAmIHopO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIE1haiBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgZmlyc3QgNjQtYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHBhcmFtIHtJbnRfNjR9IHkgVGhlIHNlY29uZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcGFyYW0ge0ludF82NH0geiBUaGUgdGhpcmQgNjQtYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0bWFqXzY0ID0gZnVuY3Rpb24gKHgsIHksIHopXG5cdHtcblx0XHRyZXR1cm4gbmV3IEludF82NChcblx0XHRcdFx0KHguaGlnaE9yZGVyICYgeS5oaWdoT3JkZXIpIF5cblx0XHRcdFx0KHguaGlnaE9yZGVyICYgei5oaWdoT3JkZXIpIF5cblx0XHRcdFx0KHkuaGlnaE9yZGVyICYgei5oaWdoT3JkZXIpLFxuXHRcdFx0XHQoeC5sb3dPcmRlciAmIHkubG93T3JkZXIpIF5cblx0XHRcdFx0KHgubG93T3JkZXIgJiB6Lmxvd09yZGVyKSBeXG5cdFx0XHRcdCh5Lmxvd09yZGVyICYgei5sb3dPcmRlcilcblx0XHRcdCk7XG5cdH0sXG5cblx0Lypcblx0ICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgU2lnbWEwIGZ1bmN0aW9uXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG5cdCAqL1xuXHRzaWdtYTBfMzIgPSBmdW5jdGlvbiAoeClcblx0e1xuXHRcdHJldHVybiByb3RyXzMyKHgsIDIpIF4gcm90cl8zMih4LCAxMykgXiByb3RyXzMyKHgsIDIyKTtcblx0fSxcblxuXHQvKlxuXHQgKiBUaGUgNjQtYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBTaWdtYTAgZnVuY3Rpb25cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG5cdCAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cblx0ICovXG5cdHNpZ21hMF82NCA9IGZ1bmN0aW9uICh4KVxuXHR7XG5cdFx0dmFyIHJvdHIyOCA9IHJvdHJfNjQoeCwgMjgpLCByb3RyMzQgPSByb3RyXzY0KHgsIDM0KSxcblx0XHRcdHJvdHIzOSA9IHJvdHJfNjQoeCwgMzkpO1xuXG5cdFx0cmV0dXJuIG5ldyBJbnRfNjQoXG5cdFx0XHRcdHJvdHIyOC5oaWdoT3JkZXIgXiByb3RyMzQuaGlnaE9yZGVyIF4gcm90cjM5LmhpZ2hPcmRlcixcblx0XHRcdFx0cm90cjI4Lmxvd09yZGVyIF4gcm90cjM0Lmxvd09yZGVyIF4gcm90cjM5Lmxvd09yZGVyKTtcblx0fSxcblxuXHQvKlxuXHQgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBTaWdtYTEgZnVuY3Rpb25cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG5cdCAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cblx0ICovXG5cdHNpZ21hMV8zMiA9IGZ1bmN0aW9uICh4KVxuXHR7XG5cdFx0cmV0dXJuIHJvdHJfMzIoeCwgNikgXiByb3RyXzMyKHgsIDExKSBeIHJvdHJfMzIoeCwgMjUpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIFNpZ21hMSBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgNjQtYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0c2lnbWExXzY0ID0gZnVuY3Rpb24gKHgpXG5cdHtcblx0XHR2YXIgcm90cjE0ID0gcm90cl82NCh4LCAxNCksIHJvdHIxOCA9IHJvdHJfNjQoeCwgMTgpLFxuXHRcdFx0cm90cjQxID0gcm90cl82NCh4LCA0MSk7XG5cblx0XHRyZXR1cm4gbmV3IEludF82NChcblx0XHRcdFx0cm90cjE0LmhpZ2hPcmRlciBeIHJvdHIxOC5oaWdoT3JkZXIgXiByb3RyNDEuaGlnaE9yZGVyLFxuXHRcdFx0XHRyb3RyMTQubG93T3JkZXIgXiByb3RyMTgubG93T3JkZXIgXiByb3RyNDEubG93T3JkZXIpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIEdhbW1hMCBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0Z2FtbWEwXzMyID0gZnVuY3Rpb24gKHgpXG5cdHtcblx0XHRyZXR1cm4gcm90cl8zMih4LCA3KSBeIHJvdHJfMzIoeCwgMTgpIF4gc2hyXzMyKHgsIDMpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIEdhbW1hMCBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgNjQtYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0Z2FtbWEwXzY0ID0gZnVuY3Rpb24gKHgpXG5cdHtcblx0XHR2YXIgcm90cjEgPSByb3RyXzY0KHgsIDEpLCByb3RyOCA9IHJvdHJfNjQoeCwgOCksIHNocjcgPSBzaHJfNjQoeCwgNyk7XG5cblx0XHRyZXR1cm4gbmV3IEludF82NChcblx0XHRcdFx0cm90cjEuaGlnaE9yZGVyIF4gcm90cjguaGlnaE9yZGVyIF4gc2hyNy5oaWdoT3JkZXIsXG5cdFx0XHRcdHJvdHIxLmxvd09yZGVyIF4gcm90cjgubG93T3JkZXIgXiBzaHI3Lmxvd09yZGVyXG5cdFx0XHQpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIEdhbW1hMSBmdW5jdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcblx0ICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuXHQgKi9cblx0Z2FtbWExXzMyID0gZnVuY3Rpb24gKHgpXG5cdHtcblx0XHRyZXR1cm4gcm90cl8zMih4LCAxNykgXiByb3RyXzMyKHgsIDE5KSBeIHNocl8zMih4LCAxMCk7XG5cdH0sXG5cblx0Lypcblx0ICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgR2FtbWExIGZ1bmN0aW9uXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuXHQgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG5cdCAqL1xuXHRnYW1tYTFfNjQgPSBmdW5jdGlvbiAoeClcblx0e1xuXHRcdHZhciByb3RyMTkgPSByb3RyXzY0KHgsIDE5KSwgcm90cjYxID0gcm90cl82NCh4LCA2MSksXG5cdFx0XHRzaHI2ID0gc2hyXzY0KHgsIDYpO1xuXG5cdFx0cmV0dXJuIG5ldyBJbnRfNjQoXG5cdFx0XHRcdHJvdHIxOS5oaWdoT3JkZXIgXiByb3RyNjEuaGlnaE9yZGVyIF4gc2hyNi5oaWdoT3JkZXIsXG5cdFx0XHRcdHJvdHIxOS5sb3dPcmRlciBeIHJvdHI2MS5sb3dPcmRlciBeIHNocjYubG93T3JkZXJcblx0XHRcdCk7XG5cdH0sXG5cblx0Lypcblx0ICogQWRkIHR3byAzMi1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeMzIuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuXHQgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSBmaXJzdCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuXHQgKiBAcGFyYW0ge051bWJlcn0geSBUaGUgc2Vjb25kIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEByZXR1cm4gVGhlIHN1bSBvZiB4ICsgeVxuXHQgKi9cblx0c2FmZUFkZF8zMl8yID0gZnVuY3Rpb24gKHgsIHkpXG5cdHtcblx0XHR2YXIgbHN3ID0gKHggJiAweEZGRkYpICsgKHkgJiAweEZGRkYpLFxuXHRcdFx0bXN3ID0gKHggPj4+IDE2KSArICh5ID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG5cblx0XHRyZXR1cm4gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIEFkZCBmb3VyIDMyLWJpdCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zXG5cdCAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGEgVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBiIFRoZSBzZWNvbmQgMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBkIFRoZSBmb3VydGggMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHJldHVybiBUaGUgc3VtIG9mIGEgKyBiICsgYyArIGRcblx0ICovXG5cdHNhZmVBZGRfMzJfNCA9IGZ1bmN0aW9uIChhLCBiLCBjLCBkKVxuXHR7XG5cdFx0dmFyIGxzdyA9IChhICYgMHhGRkZGKSArIChiICYgMHhGRkZGKSArIChjICYgMHhGRkZGKSArIChkICYgMHhGRkZGKSxcblx0XHRcdG1zdyA9IChhID4+PiAxNikgKyAoYiA+Pj4gMTYpICsgKGMgPj4+IDE2KSArIChkID4+PiAxNikgK1xuXHRcdFx0XHQobHN3ID4+PiAxNik7XG5cblx0XHRyZXR1cm4gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIEFkZCBmaXZlIDMyLWJpdCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zXG5cdCAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cblx0ICpcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGEgVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBiIFRoZSBzZWNvbmQgMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSBkIFRoZSBmb3VydGggMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGUgVGhlIGZpZnRoIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEByZXR1cm4gVGhlIHN1bSBvZiBhICsgYiArIGMgKyBkICsgZVxuXHQgKi9cblx0c2FmZUFkZF8zMl81ID0gZnVuY3Rpb24gKGEsIGIsIGMsIGQsIGUpXG5cdHtcblx0XHR2YXIgbHN3ID0gKGEgJiAweEZGRkYpICsgKGIgJiAweEZGRkYpICsgKGMgJiAweEZGRkYpICsgKGQgJiAweEZGRkYpICtcblx0XHRcdFx0KGUgJiAweEZGRkYpLFxuXHRcdFx0bXN3ID0gKGEgPj4+IDE2KSArIChiID4+PiAxNikgKyAoYyA+Pj4gMTYpICsgKGQgPj4+IDE2KSArXG5cdFx0XHRcdChlID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG5cblx0XHRyZXR1cm4gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXHR9LFxuXG5cdC8qXG5cdCAqIEFkZCB0d28gNjQtYml0IGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjY0LiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnNcblx0ICogaW50ZXJuYWxseSB0byB3b3JrIGFyb3VuZCBidWdzIGluIHNvbWUgSlMgaW50ZXJwcmV0ZXJzLlxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgZmlyc3QgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHBhcmFtIHtJbnRfNjR9IHkgVGhlIHNlY29uZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuXHQgKiBAcmV0dXJuIFRoZSBzdW0gb2YgeCArIHlcblx0ICovXG5cdHNhZmVBZGRfNjRfMiA9IGZ1bmN0aW9uICh4LCB5KVxuXHR7XG5cdFx0dmFyIGxzdywgbXN3LCBsb3dPcmRlciwgaGlnaE9yZGVyO1xuXG5cdFx0bHN3ID0gKHgubG93T3JkZXIgJiAweEZGRkYpICsgKHkubG93T3JkZXIgJiAweEZGRkYpO1xuXHRcdG1zdyA9ICh4Lmxvd09yZGVyID4+PiAxNikgKyAoeS5sb3dPcmRlciA+Pj4gMTYpICsgKGxzdyA+Pj4gMTYpO1xuXHRcdGxvd09yZGVyID0gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXG5cdFx0bHN3ID0gKHguaGlnaE9yZGVyICYgMHhGRkZGKSArICh5LmhpZ2hPcmRlciAmIDB4RkZGRikgKyAobXN3ID4+PiAxNik7XG5cdFx0bXN3ID0gKHguaGlnaE9yZGVyID4+PiAxNikgKyAoeS5oaWdoT3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcblx0XHRoaWdoT3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cblx0XHRyZXR1cm4gbmV3IEludF82NChoaWdoT3JkZXIsIGxvd09yZGVyKTtcblx0fSxcblxuXHQvKlxuXHQgKiBBZGQgZm91ciA2NC1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeNjQuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuXHQgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7SW50XzY0fSBhIFRoZSBmaXJzdCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuXHQgKiBAcGFyYW0ge0ludF82NH0gYiBUaGUgc2Vjb25kIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEBwYXJhbSB7SW50XzY0fSBjIFRoZSB0aGlyZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuXHQgKiBAcGFyYW0ge0ludF82NH0gZCBUaGUgZm91dGggNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHJldHVybiBUaGUgc3VtIG9mIGEgKyBiICsgYyArIGRcblx0ICovXG5cdHNhZmVBZGRfNjRfNCA9IGZ1bmN0aW9uIChhLCBiLCBjLCBkKVxuXHR7XG5cdFx0dmFyIGxzdywgbXN3LCBsb3dPcmRlciwgaGlnaE9yZGVyO1xuXG5cdFx0bHN3ID0gKGEubG93T3JkZXIgJiAweEZGRkYpICsgKGIubG93T3JkZXIgJiAweEZGRkYpICtcblx0XHRcdChjLmxvd09yZGVyICYgMHhGRkZGKSArIChkLmxvd09yZGVyICYgMHhGRkZGKTtcblx0XHRtc3cgPSAoYS5sb3dPcmRlciA+Pj4gMTYpICsgKGIubG93T3JkZXIgPj4+IDE2KSArXG5cdFx0XHQoYy5sb3dPcmRlciA+Pj4gMTYpICsgKGQubG93T3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcblx0XHRsb3dPcmRlciA9ICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcblxuXHRcdGxzdyA9IChhLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoYi5oaWdoT3JkZXIgJiAweEZGRkYpICtcblx0XHRcdChjLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoZC5oaWdoT3JkZXIgJiAweEZGRkYpICsgKG1zdyA+Pj4gMTYpO1xuXHRcdG1zdyA9IChhLmhpZ2hPcmRlciA+Pj4gMTYpICsgKGIuaGlnaE9yZGVyID4+PiAxNikgK1xuXHRcdFx0KGMuaGlnaE9yZGVyID4+PiAxNikgKyAoZC5oaWdoT3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcblx0XHRoaWdoT3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cblx0XHRyZXR1cm4gbmV3IEludF82NChoaWdoT3JkZXIsIGxvd09yZGVyKTtcblx0fSxcblxuXHQvKlxuXHQgKiBBZGQgZml2ZSA2NC1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeNjQuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuXHQgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7SW50XzY0fSBhIFRoZSBmaXJzdCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuXHQgKiBAcGFyYW0ge0ludF82NH0gYiBUaGUgc2Vjb25kIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEBwYXJhbSB7SW50XzY0fSBjIFRoZSB0aGlyZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuXHQgKiBAcGFyYW0ge0ludF82NH0gZCBUaGUgZm91dGggNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcblx0ICogQHBhcmFtIHtJbnRfNjR9IGUgVGhlIGZvdXRoIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG5cdCAqIEByZXR1cm4gVGhlIHN1bSBvZiBhICsgYiArIGMgKyBkICsgZVxuXHQgKi9cblx0c2FmZUFkZF82NF81ID0gZnVuY3Rpb24gKGEsIGIsIGMsIGQsIGUpXG5cdHtcblx0XHR2YXIgbHN3LCBtc3csIGxvd09yZGVyLCBoaWdoT3JkZXI7XG5cblx0XHRsc3cgPSAoYS5sb3dPcmRlciAmIDB4RkZGRikgKyAoYi5sb3dPcmRlciAmIDB4RkZGRikgK1xuXHRcdFx0KGMubG93T3JkZXIgJiAweEZGRkYpICsgKGQubG93T3JkZXIgJiAweEZGRkYpICtcblx0XHRcdChlLmxvd09yZGVyICYgMHhGRkZGKTtcblx0XHRtc3cgPSAoYS5sb3dPcmRlciA+Pj4gMTYpICsgKGIubG93T3JkZXIgPj4+IDE2KSArXG5cdFx0XHQoYy5sb3dPcmRlciA+Pj4gMTYpICsgKGQubG93T3JkZXIgPj4+IDE2KSArIChlLmxvd09yZGVyID4+PiAxNikgK1xuXHRcdFx0KGxzdyA+Pj4gMTYpO1xuXHRcdGxvd09yZGVyID0gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXG5cdFx0bHN3ID0gKGEuaGlnaE9yZGVyICYgMHhGRkZGKSArIChiLmhpZ2hPcmRlciAmIDB4RkZGRikgK1xuXHRcdFx0KGMuaGlnaE9yZGVyICYgMHhGRkZGKSArIChkLmhpZ2hPcmRlciAmIDB4RkZGRikgK1xuXHRcdFx0KGUuaGlnaE9yZGVyICYgMHhGRkZGKSArIChtc3cgPj4+IDE2KTtcblx0XHRtc3cgPSAoYS5oaWdoT3JkZXIgPj4+IDE2KSArIChiLmhpZ2hPcmRlciA+Pj4gMTYpICtcblx0XHRcdChjLmhpZ2hPcmRlciA+Pj4gMTYpICsgKGQuaGlnaE9yZGVyID4+PiAxNikgK1xuXHRcdFx0KGUuaGlnaE9yZGVyID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG5cdFx0aGlnaE9yZGVyID0gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXG5cdFx0cmV0dXJuIG5ldyBJbnRfNjQoaGlnaE9yZGVyLCBsb3dPcmRlcik7XG5cdH0sXG5cblx0Lypcblx0ICogQ2FsY3VsYXRlcyB0aGUgU0hBLTEgaGFzaCBvZiB0aGUgc3RyaW5nIHNldCBhdCBpbnN0YW50aWF0aW9uXG5cdCAqXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7QXJyYXl9IG1lc3NhZ2UgVGhlIGJpbmFyeSBhcnJheSByZXByZXNlbnRhdGlvbiBvZiB0aGUgc3RyaW5nIHRvXG5cdCAqXHQgaGFzaFxuXHQgKiBAcGFyYW0ge051bWJlcn0gbWVzc2FnZUxlbiBUaGUgbnVtYmVyIG9mIGJpdHMgaW4gdGhlIG1lc3NhZ2Vcblx0ICogQHJldHVybiBUaGUgYXJyYXkgb2YgaW50ZWdlcnMgcmVwcmVzZW50aW5nIHRoZSBTSEEtMSBoYXNoIG9mIG1lc3NhZ2Vcblx0ICovXG5cdGNvcmVTSEExID0gZnVuY3Rpb24gKG1lc3NhZ2UsIG1lc3NhZ2VMZW4pXG5cdHtcblx0XHR2YXIgVyA9IFtdLCBhLCBiLCBjLCBkLCBlLCBULCBjaCA9IGNoXzMyLCBwYXJpdHkgPSBwYXJpdHlfMzIsXG5cdFx0XHRtYWogPSBtYWpfMzIsIHJvdGwgPSByb3RsXzMyLCBzYWZlQWRkXzIgPSBzYWZlQWRkXzMyXzIsIGksIHQsXG5cdFx0XHRzYWZlQWRkXzUgPSBzYWZlQWRkXzMyXzUsIGFwcGVuZGVkTWVzc2FnZUxlbmd0aCxcblx0XHRcdEggPSBbXG5cdFx0XHRcdDB4Njc0NTIzMDEsIDB4ZWZjZGFiODksIDB4OThiYWRjZmUsIDB4MTAzMjU0NzYsIDB4YzNkMmUxZjBcblx0XHRcdF0sXG5cdFx0XHRLID0gW1xuXHRcdFx0XHQweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuXHRcdFx0XHQweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuXHRcdFx0XHQweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuXHRcdFx0XHQweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuXHRcdFx0XHQweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuXHRcdFx0XHQweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuXHRcdFx0XHQweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuXHRcdFx0XHQweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuXHRcdFx0XHQweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuXHRcdFx0XHQweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuXHRcdFx0XHQweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuXHRcdFx0XHQweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuXHRcdFx0XHQweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuXHRcdFx0XHQweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuXHRcdFx0XHQweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuXHRcdFx0XHQweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuXHRcdFx0XHQweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuXHRcdFx0XHQweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuXHRcdFx0XHQweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuXHRcdFx0XHQweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2XG5cdFx0XHRdO1xuXG5cdFx0LyogQXBwZW5kICcxJyBhdCB0aGUgZW5kIG9mIHRoZSBiaW5hcnkgc3RyaW5nICovXG5cdFx0bWVzc2FnZVttZXNzYWdlTGVuID4+IDVdIHw9IDB4ODAgPDwgKDI0IC0gKG1lc3NhZ2VMZW4gJSAzMikpO1xuXHRcdC8qIEFwcGVuZCBsZW5ndGggb2YgYmluYXJ5IHN0cmluZyBpbiB0aGUgcG9zaXRpb24gc3VjaCB0aGF0IHRoZSBuZXdcblx0XHRsZW5ndGggaXMgYSBtdWx0aXBsZSBvZiA1MTIuICBMb2dpYyBkb2VzIG5vdCB3b3JrIGZvciBldmVuIG11bHRpcGxlc1xuXHRcdG9mIDUxMiBidXQgdGhlcmUgY2FuIG5ldmVyIGJlIGV2ZW4gbXVsdGlwbGVzIG9mIDUxMiAqL1xuXHRcdG1lc3NhZ2VbKCgobWVzc2FnZUxlbiArIDY1KSA+PiA5KSA8PCA0KSArIDE1XSA9IG1lc3NhZ2VMZW47XG5cblx0XHRhcHBlbmRlZE1lc3NhZ2VMZW5ndGggPSBtZXNzYWdlLmxlbmd0aDtcblxuXHRcdGZvciAoaSA9IDA7IGkgPCBhcHBlbmRlZE1lc3NhZ2VMZW5ndGg7IGkgKz0gMTYpXG5cdFx0e1xuXHRcdFx0YSA9IEhbMF07XG5cdFx0XHRiID0gSFsxXTtcblx0XHRcdGMgPSBIWzJdO1xuXHRcdFx0ZCA9IEhbM107XG5cdFx0XHRlID0gSFs0XTtcblxuXHRcdFx0Zm9yICh0ID0gMDsgdCA8IDgwOyB0ICs9IDEpXG5cdFx0XHR7XG5cdFx0XHRcdGlmICh0IDwgMTYpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRXW3RdID0gbWVzc2FnZVt0ICsgaV07XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0V1t0XSA9IHJvdGwoV1t0IC0gM10gXiBXW3QgLSA4XSBeIFdbdCAtIDE0XSBeIFdbdCAtIDE2XSwgMSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAodCA8IDIwKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0VCA9IHNhZmVBZGRfNShyb3RsKGEsIDUpLCBjaChiLCBjLCBkKSwgZSwgS1t0XSwgV1t0XSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAodCA8IDQwKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0VCA9IHNhZmVBZGRfNShyb3RsKGEsIDUpLCBwYXJpdHkoYiwgYywgZCksIGUsIEtbdF0sIFdbdF0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKHQgPCA2MClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdFQgPSBzYWZlQWRkXzUocm90bChhLCA1KSwgbWFqKGIsIGMsIGQpLCBlLCBLW3RdLCBXW3RdKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRUID0gc2FmZUFkZF81KHJvdGwoYSwgNSksIHBhcml0eShiLCBjLCBkKSwgZSwgS1t0XSwgV1t0XSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRlID0gZDtcblx0XHRcdFx0ZCA9IGM7XG5cdFx0XHRcdGMgPSByb3RsKGIsIDMwKTtcblx0XHRcdFx0YiA9IGE7XG5cdFx0XHRcdGEgPSBUO1xuXHRcdFx0fVxuXG5cdFx0XHRIWzBdID0gc2FmZUFkZF8yKGEsIEhbMF0pO1xuXHRcdFx0SFsxXSA9IHNhZmVBZGRfMihiLCBIWzFdKTtcblx0XHRcdEhbMl0gPSBzYWZlQWRkXzIoYywgSFsyXSk7XG5cdFx0XHRIWzNdID0gc2FmZUFkZF8yKGQsIEhbM10pO1xuXHRcdFx0SFs0XSA9IHNhZmVBZGRfMihlLCBIWzRdKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gSDtcblx0fSxcblxuXHQvKlxuXHQgKiBDYWxjdWxhdGVzIHRoZSBkZXNpcmVkIFNIQS0yIGhhc2ggb2YgdGhlIHN0cmluZyBzZXQgYXQgaW5zdGFudGlhdGlvblxuXHQgKlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge0FycmF5fSBUaGUgYmluYXJ5IGFycmF5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBzdHJpbmcgdG8gaGFzaFxuXHQgKiBAcGFyYW0ge051bWJlcn0gVGhlIG51bWJlciBvZiBiaXRzIGluIG1lc3NhZ2Vcblx0ICogQHBhcmFtIHtTdHJpbmd9IHZhcmlhbnQgVGhlIGRlc2lyZWQgU0hBLTIgdmFyaWFudFxuXHQgKiBAcmV0dXJuIFRoZSBhcnJheSBvZiBpbnRlZ2VycyByZXByZXNlbnRpbmcgdGhlIFNIQS0yIGhhc2ggb2YgbWVzc2FnZVxuXHQgKi9cblx0Y29yZVNIQTIgPSBmdW5jdGlvbiAobWVzc2FnZSwgbWVzc2FnZUxlbiwgdmFyaWFudClcblx0e1xuXHRcdHZhciBhLCBiLCBjLCBkLCBlLCBmLCBnLCBoLCBUMSwgVDIsIEgsIG51bVJvdW5kcywgbGVuZ3RoUG9zaXRpb24sIGksIHQsXG5cdFx0XHRiaW5hcnlTdHJpbmdJbmMsIGJpbmFyeVN0cmluZ011bHQsIHNhZmVBZGRfMiwgc2FmZUFkZF80LCBzYWZlQWRkXzUsXG5cdFx0XHRnYW1tYTAsIGdhbW1hMSwgc2lnbWEwLCBzaWdtYTEsIGNoLCBtYWosIEludCwgSywgVyA9IFtdLFxuXHRcdFx0YXBwZW5kZWRNZXNzYWdlTGVuZ3RoO1xuXG5cdFx0LyogU2V0IHVwIHRoZSB2YXJpb3VzIGZ1bmN0aW9uIGhhbmRsZXMgYW5kIHZhcmlhYmxlIGZvciB0aGUgc3BlY2lmaWMgXG5cdFx0ICogdmFyaWFudCAqL1xuXHRcdGlmICh2YXJpYW50ID09PSBcIlNIQS0yMjRcIiB8fCB2YXJpYW50ID09PSBcIlNIQS0yNTZcIilcblx0XHR7XG5cdFx0XHQvKiAzMi1iaXQgdmFyaWFudCAqL1xuXHRcdFx0bnVtUm91bmRzID0gNjQ7XG5cdFx0XHRsZW5ndGhQb3NpdGlvbiA9ICgoKG1lc3NhZ2VMZW4gKyA2NSkgPj4gOSkgPDwgNCkgKyAxNTtcblx0XHRcdGJpbmFyeVN0cmluZ0luYyA9IDE2O1xuXHRcdFx0YmluYXJ5U3RyaW5nTXVsdCA9IDE7XG5cdFx0XHRJbnQgPSBOdW1iZXI7XG5cdFx0XHRzYWZlQWRkXzIgPSBzYWZlQWRkXzMyXzI7XG5cdFx0XHRzYWZlQWRkXzQgPSBzYWZlQWRkXzMyXzQ7XG5cdFx0XHRzYWZlQWRkXzUgPSBzYWZlQWRkXzMyXzU7XG5cdFx0XHRnYW1tYTAgPSBnYW1tYTBfMzI7XG5cdFx0XHRnYW1tYTEgPSBnYW1tYTFfMzI7XG5cdFx0XHRzaWdtYTAgPSBzaWdtYTBfMzI7XG5cdFx0XHRzaWdtYTEgPSBzaWdtYTFfMzI7XG5cdFx0XHRtYWogPSBtYWpfMzI7XG5cdFx0XHRjaCA9IGNoXzMyO1xuXHRcdFx0SyA9IFtcblx0XHRcdFx0XHQweDQyOEEyRjk4LCAweDcxMzc0NDkxLCAweEI1QzBGQkNGLCAweEU5QjVEQkE1LFxuXHRcdFx0XHRcdDB4Mzk1NkMyNUIsIDB4NTlGMTExRjEsIDB4OTIzRjgyQTQsIDB4QUIxQzVFRDUsXG5cdFx0XHRcdFx0MHhEODA3QUE5OCwgMHgxMjgzNUIwMSwgMHgyNDMxODVCRSwgMHg1NTBDN0RDMyxcblx0XHRcdFx0XHQweDcyQkU1RDc0LCAweDgwREVCMUZFLCAweDlCREMwNkE3LCAweEMxOUJGMTc0LFxuXHRcdFx0XHRcdDB4RTQ5QjY5QzEsIDB4RUZCRTQ3ODYsIDB4MEZDMTlEQzYsIDB4MjQwQ0ExQ0MsXG5cdFx0XHRcdFx0MHgyREU5MkM2RiwgMHg0QTc0ODRBQSwgMHg1Q0IwQTlEQywgMHg3NkY5ODhEQSxcblx0XHRcdFx0XHQweDk4M0U1MTUyLCAweEE4MzFDNjZELCAweEIwMDMyN0M4LCAweEJGNTk3RkM3LFxuXHRcdFx0XHRcdDB4QzZFMDBCRjMsIDB4RDVBNzkxNDcsIDB4MDZDQTYzNTEsIDB4MTQyOTI5NjcsXG5cdFx0XHRcdFx0MHgyN0I3MEE4NSwgMHgyRTFCMjEzOCwgMHg0RDJDNkRGQywgMHg1MzM4MEQxMyxcblx0XHRcdFx0XHQweDY1MEE3MzU0LCAweDc2NkEwQUJCLCAweDgxQzJDOTJFLCAweDkyNzIyQzg1LFxuXHRcdFx0XHRcdDB4QTJCRkU4QTEsIDB4QTgxQTY2NEIsIDB4QzI0QjhCNzAsIDB4Qzc2QzUxQTMsXG5cdFx0XHRcdFx0MHhEMTkyRTgxOSwgMHhENjk5MDYyNCwgMHhGNDBFMzU4NSwgMHgxMDZBQTA3MCxcblx0XHRcdFx0XHQweDE5QTRDMTE2LCAweDFFMzc2QzA4LCAweDI3NDg3NzRDLCAweDM0QjBCQ0I1LFxuXHRcdFx0XHRcdDB4MzkxQzBDQjMsIDB4NEVEOEFBNEEsIDB4NUI5Q0NBNEYsIDB4NjgyRTZGRjMsXG5cdFx0XHRcdFx0MHg3NDhGODJFRSwgMHg3OEE1NjM2RiwgMHg4NEM4NzgxNCwgMHg4Q0M3MDIwOCxcblx0XHRcdFx0XHQweDkwQkVGRkZBLCAweEE0NTA2Q0VCLCAweEJFRjlBM0Y3LCAweEM2NzE3OEYyXG5cdFx0XHRcdF07XG5cblx0XHRcdGlmICh2YXJpYW50ID09PSBcIlNIQS0yMjRcIilcblx0XHRcdHtcblx0XHRcdFx0SCA9IFtcblx0XHRcdFx0XHRcdDB4YzEwNTllZDgsIDB4MzY3Y2Q1MDcsIDB4MzA3MGRkMTcsIDB4ZjcwZTU5MzksXG5cdFx0XHRcdFx0XHQweGZmYzAwYjMxLCAweDY4NTgxNTExLCAweDY0Zjk4ZmE3LCAweGJlZmE0ZmE0XG5cdFx0XHRcdFx0XTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0SCA9IFtcblx0XHRcdFx0XHRcdDB4NkEwOUU2NjcsIDB4QkI2N0FFODUsIDB4M0M2RUYzNzIsIDB4QTU0RkY1M0EsXG5cdFx0XHRcdFx0XHQweDUxMEU1MjdGLCAweDlCMDU2ODhDLCAweDFGODNEOUFCLCAweDVCRTBDRDE5XG5cdFx0XHRcdFx0XTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSBpZiAodmFyaWFudCA9PT0gXCJTSEEtMzg0XCIgfHwgdmFyaWFudCA9PT0gXCJTSEEtNTEyXCIpXG5cdFx0e1xuXHRcdFx0LyogNjQtYml0IHZhcmlhbnQgKi9cblx0XHRcdG51bVJvdW5kcyA9IDgwO1xuXHRcdFx0bGVuZ3RoUG9zaXRpb24gPSAoKChtZXNzYWdlTGVuICsgMTI4KSA+PiAxMCkgPDwgNSkgKyAzMTtcblx0XHRcdGJpbmFyeVN0cmluZ0luYyA9IDMyO1xuXHRcdFx0YmluYXJ5U3RyaW5nTXVsdCA9IDI7XG5cdFx0XHRJbnQgPSBJbnRfNjQ7XG5cdFx0XHRzYWZlQWRkXzIgPSBzYWZlQWRkXzY0XzI7XG5cdFx0XHRzYWZlQWRkXzQgPSBzYWZlQWRkXzY0XzQ7XG5cdFx0XHRzYWZlQWRkXzUgPSBzYWZlQWRkXzY0XzU7XG5cdFx0XHRnYW1tYTAgPSBnYW1tYTBfNjQ7XG5cdFx0XHRnYW1tYTEgPSBnYW1tYTFfNjQ7XG5cdFx0XHRzaWdtYTAgPSBzaWdtYTBfNjQ7XG5cdFx0XHRzaWdtYTEgPSBzaWdtYTFfNjQ7XG5cdFx0XHRtYWogPSBtYWpfNjQ7XG5cdFx0XHRjaCA9IGNoXzY0O1xuXG5cdFx0XHRLID0gW1xuXHRcdFx0XHRuZXcgSW50KDB4NDI4YTJmOTgsIDB4ZDcyOGFlMjIpLCBuZXcgSW50KDB4NzEzNzQ0OTEsIDB4MjNlZjY1Y2QpLFxuXHRcdFx0XHRuZXcgSW50KDB4YjVjMGZiY2YsIDB4ZWM0ZDNiMmYpLCBuZXcgSW50KDB4ZTliNWRiYTUsIDB4ODE4OWRiYmMpLFxuXHRcdFx0XHRuZXcgSW50KDB4Mzk1NmMyNWIsIDB4ZjM0OGI1MzgpLCBuZXcgSW50KDB4NTlmMTExZjEsIDB4YjYwNWQwMTkpLFxuXHRcdFx0XHRuZXcgSW50KDB4OTIzZjgyYTQsIDB4YWYxOTRmOWIpLCBuZXcgSW50KDB4YWIxYzVlZDUsIDB4ZGE2ZDgxMTgpLFxuXHRcdFx0XHRuZXcgSW50KDB4ZDgwN2FhOTgsIDB4YTMwMzAyNDIpLCBuZXcgSW50KDB4MTI4MzViMDEsIDB4NDU3MDZmYmUpLFxuXHRcdFx0XHRuZXcgSW50KDB4MjQzMTg1YmUsIDB4NGVlNGIyOGMpLCBuZXcgSW50KDB4NTUwYzdkYzMsIDB4ZDVmZmI0ZTIpLFxuXHRcdFx0XHRuZXcgSW50KDB4NzJiZTVkNzQsIDB4ZjI3Yjg5NmYpLCBuZXcgSW50KDB4ODBkZWIxZmUsIDB4M2IxNjk2YjEpLFxuXHRcdFx0XHRuZXcgSW50KDB4OWJkYzA2YTcsIDB4MjVjNzEyMzUpLCBuZXcgSW50KDB4YzE5YmYxNzQsIDB4Y2Y2OTI2OTQpLFxuXHRcdFx0XHRuZXcgSW50KDB4ZTQ5YjY5YzEsIDB4OWVmMTRhZDIpLCBuZXcgSW50KDB4ZWZiZTQ3ODYsIDB4Mzg0ZjI1ZTMpLFxuXHRcdFx0XHRuZXcgSW50KDB4MGZjMTlkYzYsIDB4OGI4Y2Q1YjUpLCBuZXcgSW50KDB4MjQwY2ExY2MsIDB4NzdhYzljNjUpLFxuXHRcdFx0XHRuZXcgSW50KDB4MmRlOTJjNmYsIDB4NTkyYjAyNzUpLCBuZXcgSW50KDB4NGE3NDg0YWEsIDB4NmVhNmU0ODMpLFxuXHRcdFx0XHRuZXcgSW50KDB4NWNiMGE5ZGMsIDB4YmQ0MWZiZDQpLCBuZXcgSW50KDB4NzZmOTg4ZGEsIDB4ODMxMTUzYjUpLFxuXHRcdFx0XHRuZXcgSW50KDB4OTgzZTUxNTIsIDB4ZWU2NmRmYWIpLCBuZXcgSW50KDB4YTgzMWM2NmQsIDB4MmRiNDMyMTApLFxuXHRcdFx0XHRuZXcgSW50KDB4YjAwMzI3YzgsIDB4OThmYjIxM2YpLCBuZXcgSW50KDB4YmY1OTdmYzcsIDB4YmVlZjBlZTQpLFxuXHRcdFx0XHRuZXcgSW50KDB4YzZlMDBiZjMsIDB4M2RhODhmYzIpLCBuZXcgSW50KDB4ZDVhNzkxNDcsIDB4OTMwYWE3MjUpLFxuXHRcdFx0XHRuZXcgSW50KDB4MDZjYTYzNTEsIDB4ZTAwMzgyNmYpLCBuZXcgSW50KDB4MTQyOTI5NjcsIDB4MGEwZTZlNzApLFxuXHRcdFx0XHRuZXcgSW50KDB4MjdiNzBhODUsIDB4NDZkMjJmZmMpLCBuZXcgSW50KDB4MmUxYjIxMzgsIDB4NWMyNmM5MjYpLFxuXHRcdFx0XHRuZXcgSW50KDB4NGQyYzZkZmMsIDB4NWFjNDJhZWQpLCBuZXcgSW50KDB4NTMzODBkMTMsIDB4OWQ5NWIzZGYpLFxuXHRcdFx0XHRuZXcgSW50KDB4NjUwYTczNTQsIDB4OGJhZjYzZGUpLCBuZXcgSW50KDB4NzY2YTBhYmIsIDB4M2M3N2IyYTgpLFxuXHRcdFx0XHRuZXcgSW50KDB4ODFjMmM5MmUsIDB4NDdlZGFlZTYpLCBuZXcgSW50KDB4OTI3MjJjODUsIDB4MTQ4MjM1M2IpLFxuXHRcdFx0XHRuZXcgSW50KDB4YTJiZmU4YTEsIDB4NGNmMTAzNjQpLCBuZXcgSW50KDB4YTgxYTY2NGIsIDB4YmM0MjMwMDEpLFxuXHRcdFx0XHRuZXcgSW50KDB4YzI0YjhiNzAsIDB4ZDBmODk3OTEpLCBuZXcgSW50KDB4Yzc2YzUxYTMsIDB4MDY1NGJlMzApLFxuXHRcdFx0XHRuZXcgSW50KDB4ZDE5MmU4MTksIDB4ZDZlZjUyMTgpLCBuZXcgSW50KDB4ZDY5OTA2MjQsIDB4NTU2NWE5MTApLFxuXHRcdFx0XHRuZXcgSW50KDB4ZjQwZTM1ODUsIDB4NTc3MTIwMmEpLCBuZXcgSW50KDB4MTA2YWEwNzAsIDB4MzJiYmQxYjgpLFxuXHRcdFx0XHRuZXcgSW50KDB4MTlhNGMxMTYsIDB4YjhkMmQwYzgpLCBuZXcgSW50KDB4MWUzNzZjMDgsIDB4NTE0MWFiNTMpLFxuXHRcdFx0XHRuZXcgSW50KDB4Mjc0ODc3NGMsIDB4ZGY4ZWViOTkpLCBuZXcgSW50KDB4MzRiMGJjYjUsIDB4ZTE5YjQ4YTgpLFxuXHRcdFx0XHRuZXcgSW50KDB4MzkxYzBjYjMsIDB4YzVjOTVhNjMpLCBuZXcgSW50KDB4NGVkOGFhNGEsIDB4ZTM0MThhY2IpLFxuXHRcdFx0XHRuZXcgSW50KDB4NWI5Y2NhNGYsIDB4Nzc2M2UzNzMpLCBuZXcgSW50KDB4NjgyZTZmZjMsIDB4ZDZiMmI4YTMpLFxuXHRcdFx0XHRuZXcgSW50KDB4NzQ4ZjgyZWUsIDB4NWRlZmIyZmMpLCBuZXcgSW50KDB4NzhhNTYzNmYsIDB4NDMxNzJmNjApLFxuXHRcdFx0XHRuZXcgSW50KDB4ODRjODc4MTQsIDB4YTFmMGFiNzIpLCBuZXcgSW50KDB4OGNjNzAyMDgsIDB4MWE2NDM5ZWMpLFxuXHRcdFx0XHRuZXcgSW50KDB4OTBiZWZmZmEsIDB4MjM2MzFlMjgpLCBuZXcgSW50KDB4YTQ1MDZjZWIsIDB4ZGU4MmJkZTkpLFxuXHRcdFx0XHRuZXcgSW50KDB4YmVmOWEzZjcsIDB4YjJjNjc5MTUpLCBuZXcgSW50KDB4YzY3MTc4ZjIsIDB4ZTM3MjUzMmIpLFxuXHRcdFx0XHRuZXcgSW50KDB4Y2EyNzNlY2UsIDB4ZWEyNjYxOWMpLCBuZXcgSW50KDB4ZDE4NmI4YzcsIDB4MjFjMGMyMDcpLFxuXHRcdFx0XHRuZXcgSW50KDB4ZWFkYTdkZDYsIDB4Y2RlMGViMWUpLCBuZXcgSW50KDB4ZjU3ZDRmN2YsIDB4ZWU2ZWQxNzgpLFxuXHRcdFx0XHRuZXcgSW50KDB4MDZmMDY3YWEsIDB4NzIxNzZmYmEpLCBuZXcgSW50KDB4MGE2MzdkYzUsIDB4YTJjODk4YTYpLFxuXHRcdFx0XHRuZXcgSW50KDB4MTEzZjk4MDQsIDB4YmVmOTBkYWUpLCBuZXcgSW50KDB4MWI3MTBiMzUsIDB4MTMxYzQ3MWIpLFxuXHRcdFx0XHRuZXcgSW50KDB4MjhkYjc3ZjUsIDB4MjMwNDdkODQpLCBuZXcgSW50KDB4MzJjYWFiN2IsIDB4NDBjNzI0OTMpLFxuXHRcdFx0XHRuZXcgSW50KDB4M2M5ZWJlMGEsIDB4MTVjOWJlYmMpLCBuZXcgSW50KDB4NDMxZDY3YzQsIDB4OWMxMDBkNGMpLFxuXHRcdFx0XHRuZXcgSW50KDB4NGNjNWQ0YmUsIDB4Y2IzZTQyYjYpLCBuZXcgSW50KDB4NTk3ZjI5OWMsIDB4ZmM2NTdlMmEpLFxuXHRcdFx0XHRuZXcgSW50KDB4NWZjYjZmYWIsIDB4M2FkNmZhZWMpLCBuZXcgSW50KDB4NmM0NDE5OGMsIDB4NGE0NzU4MTcpXG5cdFx0XHRdO1xuXG5cdFx0XHRpZiAodmFyaWFudCA9PT0gXCJTSEEtMzg0XCIpXG5cdFx0XHR7XG5cdFx0XHRcdEggPSBbXG5cdFx0XHRcdFx0bmV3IEludCgweGNiYmI5ZDVkLCAweGMxMDU5ZWQ4KSwgbmV3IEludCgweDA2MjlhMjkyYSwgMHgzNjdjZDUwNyksXG5cdFx0XHRcdFx0bmV3IEludCgweDkxNTkwMTVhLCAweDMwNzBkZDE3KSwgbmV3IEludCgweDAxNTJmZWNkOCwgMHhmNzBlNTkzOSksXG5cdFx0XHRcdFx0bmV3IEludCgweDY3MzMyNjY3LCAweGZmYzAwYjMxKSwgbmV3IEludCgweDk4ZWI0NGE4NywgMHg2ODU4MTUxMSksXG5cdFx0XHRcdFx0bmV3IEludCgweGRiMGMyZTBkLCAweDY0Zjk4ZmE3KSwgbmV3IEludCgweDA0N2I1NDgxZCwgMHhiZWZhNGZhNClcblx0XHRcdFx0XTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0SCA9IFtcblx0XHRcdFx0XHRuZXcgSW50KDB4NmEwOWU2NjcsIDB4ZjNiY2M5MDgpLCBuZXcgSW50KDB4YmI2N2FlODUsIDB4ODRjYWE3M2IpLFxuXHRcdFx0XHRcdG5ldyBJbnQoMHgzYzZlZjM3MiwgMHhmZTk0ZjgyYiksIG5ldyBJbnQoMHhhNTRmZjUzYSwgMHg1ZjFkMzZmMSksXG5cdFx0XHRcdFx0bmV3IEludCgweDUxMGU1MjdmLCAweGFkZTY4MmQxKSwgbmV3IEludCgweDliMDU2ODhjLCAweDJiM2U2YzFmKSxcblx0XHRcdFx0XHRuZXcgSW50KDB4MWY4M2Q5YWIsIDB4ZmI0MWJkNmIpLCBuZXcgSW50KDB4NWJlMGNkMTksIDB4MTM3ZTIxNzkpXG5cdFx0XHRcdF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0LyogQXBwZW5kICcxJyBhdCB0aGUgZW5kIG9mIHRoZSBiaW5hcnkgc3RyaW5nICovXG5cdFx0bWVzc2FnZVttZXNzYWdlTGVuID4+IDVdIHw9IDB4ODAgPDwgKDI0IC0gbWVzc2FnZUxlbiAlIDMyKTtcblx0XHQvKiBBcHBlbmQgbGVuZ3RoIG9mIGJpbmFyeSBzdHJpbmcgaW4gdGhlIHBvc2l0aW9uIHN1Y2ggdGhhdCB0aGUgbmV3XG5cdFx0ICogbGVuZ3RoIGlzIGNvcnJlY3QgKi9cblx0XHRtZXNzYWdlW2xlbmd0aFBvc2l0aW9uXSA9IG1lc3NhZ2VMZW47XG5cblx0XHRhcHBlbmRlZE1lc3NhZ2VMZW5ndGggPSBtZXNzYWdlLmxlbmd0aDtcblxuXHRcdGZvciAoaSA9IDA7IGkgPCBhcHBlbmRlZE1lc3NhZ2VMZW5ndGg7IGkgKz0gYmluYXJ5U3RyaW5nSW5jKVxuXHRcdHtcblx0XHRcdGEgPSBIWzBdO1xuXHRcdFx0YiA9IEhbMV07XG5cdFx0XHRjID0gSFsyXTtcblx0XHRcdGQgPSBIWzNdO1xuXHRcdFx0ZSA9IEhbNF07XG5cdFx0XHRmID0gSFs1XTtcblx0XHRcdGcgPSBIWzZdO1xuXHRcdFx0aCA9IEhbN107XG5cblx0XHRcdGZvciAodCA9IDA7IHQgPCBudW1Sb3VuZHM7IHQgKz0gMSlcblx0XHRcdHtcblx0XHRcdFx0aWYgKHQgPCAxNilcblx0XHRcdFx0e1xuXHRcdFx0XHRcdC8qIEJpdCBvZiBhIGhhY2sgLSBmb3IgMzItYml0LCB0aGUgc2Vjb25kIHRlcm0gaXMgaWdub3JlZCAqL1xuXHRcdFx0XHRcdFdbdF0gPSBuZXcgSW50KG1lc3NhZ2VbdCAqIGJpbmFyeVN0cmluZ011bHQgKyBpXSxcblx0XHRcdFx0XHRcdFx0bWVzc2FnZVt0ICogYmluYXJ5U3RyaW5nTXVsdCArIGkgKyAxXSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0V1t0XSA9IHNhZmVBZGRfNChcblx0XHRcdFx0XHRcdFx0Z2FtbWExKFdbdCAtIDJdKSwgV1t0IC0gN10sXG5cdFx0XHRcdFx0XHRcdGdhbW1hMChXW3QgLSAxNV0pLCBXW3QgLSAxNl1cblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRUMSA9IHNhZmVBZGRfNShoLCBzaWdtYTEoZSksIGNoKGUsIGYsIGcpLCBLW3RdLCBXW3RdKTtcblx0XHRcdFx0VDIgPSBzYWZlQWRkXzIoc2lnbWEwKGEpLCBtYWooYSwgYiwgYykpO1xuXHRcdFx0XHRoID0gZztcblx0XHRcdFx0ZyA9IGY7XG5cdFx0XHRcdGYgPSBlO1xuXHRcdFx0XHRlID0gc2FmZUFkZF8yKGQsIFQxKTtcblx0XHRcdFx0ZCA9IGM7XG5cdFx0XHRcdGMgPSBiO1xuXHRcdFx0XHRiID0gYTtcblx0XHRcdFx0YSA9IHNhZmVBZGRfMihUMSwgVDIpO1xuXHRcdFx0fVxuXG5cdFx0XHRIWzBdID0gc2FmZUFkZF8yKGEsIEhbMF0pO1xuXHRcdFx0SFsxXSA9IHNhZmVBZGRfMihiLCBIWzFdKTtcblx0XHRcdEhbMl0gPSBzYWZlQWRkXzIoYywgSFsyXSk7XG5cdFx0XHRIWzNdID0gc2FmZUFkZF8yKGQsIEhbM10pO1xuXHRcdFx0SFs0XSA9IHNhZmVBZGRfMihlLCBIWzRdKTtcblx0XHRcdEhbNV0gPSBzYWZlQWRkXzIoZiwgSFs1XSk7XG5cdFx0XHRIWzZdID0gc2FmZUFkZF8yKGcsIEhbNl0pO1xuXHRcdFx0SFs3XSA9IHNhZmVBZGRfMihoLCBIWzddKTtcblx0XHR9XG5cblx0XHRzd2l0Y2ggKHZhcmlhbnQpXG5cdFx0e1xuXHRcdGNhc2UgXCJTSEEtMjI0XCI6XG5cdFx0XHRyZXR1cm5cdFtcblx0XHRcdFx0SFswXSwgSFsxXSwgSFsyXSwgSFszXSxcblx0XHRcdFx0SFs0XSwgSFs1XSwgSFs2XVxuXHRcdFx0XTtcblx0XHRjYXNlIFwiU0hBLTI1NlwiOlxuXHRcdFx0cmV0dXJuIEg7XG5cdFx0Y2FzZSBcIlNIQS0zODRcIjpcblx0XHRcdHJldHVybiBbXG5cdFx0XHRcdEhbMF0uaGlnaE9yZGVyLCBIWzBdLmxvd09yZGVyLFxuXHRcdFx0XHRIWzFdLmhpZ2hPcmRlciwgSFsxXS5sb3dPcmRlcixcblx0XHRcdFx0SFsyXS5oaWdoT3JkZXIsIEhbMl0ubG93T3JkZXIsXG5cdFx0XHRcdEhbM10uaGlnaE9yZGVyLCBIWzNdLmxvd09yZGVyLFxuXHRcdFx0XHRIWzRdLmhpZ2hPcmRlciwgSFs0XS5sb3dPcmRlcixcblx0XHRcdFx0SFs1XS5oaWdoT3JkZXIsIEhbNV0ubG93T3JkZXJcblx0XHRcdF07XG5cdFx0Y2FzZSBcIlNIQS01MTJcIjpcblx0XHRcdHJldHVybiBbXG5cdFx0XHRcdEhbMF0uaGlnaE9yZGVyLCBIWzBdLmxvd09yZGVyLFxuXHRcdFx0XHRIWzFdLmhpZ2hPcmRlciwgSFsxXS5sb3dPcmRlcixcblx0XHRcdFx0SFsyXS5oaWdoT3JkZXIsIEhbMl0ubG93T3JkZXIsXG5cdFx0XHRcdEhbM10uaGlnaE9yZGVyLCBIWzNdLmxvd09yZGVyLFxuXHRcdFx0XHRIWzRdLmhpZ2hPcmRlciwgSFs0XS5sb3dPcmRlcixcblx0XHRcdFx0SFs1XS5oaWdoT3JkZXIsIEhbNV0ubG93T3JkZXIsXG5cdFx0XHRcdEhbNl0uaGlnaE9yZGVyLCBIWzZdLmxvd09yZGVyLFxuXHRcdFx0XHRIWzddLmhpZ2hPcmRlciwgSFs3XS5sb3dPcmRlclxuXHRcdFx0XTtcblx0XHRkZWZhdWx0OlxuXHRcdFx0LyogVGhpcyBzaG91bGQgbmV2ZXIgYmUgcmVhY2hlZCAqL1xuXHRcdFx0cmV0dXJuIFtdOyBcblx0XHR9XG5cdH0sXG5cblx0Lypcblx0ICoganNTSEEgaXMgdGhlIHdvcmtob3JzZSBvZiB0aGUgbGlicmFyeS4gIEluc3RhbnRpYXRlIGl0IHdpdGggdGhlIHN0cmluZyB0b1xuXHQgKiBiZSBoYXNoZWQgYXMgdGhlIHBhcmFtZXRlclxuXHQgKlxuXHQgKiBAY29uc3RydWN0b3Jcblx0ICogQHBhcmFtIHtTdHJpbmd9IHNyY1N0cmluZyBUaGUgc3RyaW5nIHRvIGJlIGhhc2hlZFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXRGb3JtYXQgVGhlIGZvcm1hdCBvZiBzcmNTdHJpbmcsIEFTQ0lJIG9yIEhFWFxuXHQgKi9cblx0anNTSEEgPSBmdW5jdGlvbiAoc3JjU3RyaW5nLCBpbnB1dEZvcm1hdClcblx0e1xuXG5cdFx0dGhpcy5zaGExID0gbnVsbDtcblx0XHR0aGlzLnNoYTIyNCA9IG51bGw7XG5cdFx0dGhpcy5zaGEyNTYgPSBudWxsO1xuXHRcdHRoaXMuc2hhMzg0ID0gbnVsbDtcblx0XHR0aGlzLnNoYTUxMiA9IG51bGw7XG5cblx0XHR0aGlzLnN0ckJpbkxlbiA9IG51bGw7XG5cdFx0dGhpcy5zdHJUb0hhc2ggPSBudWxsO1xuXG5cdFx0LyogQ29udmVydCB0aGUgaW5wdXQgc3RyaW5nIGludG8gdGhlIGNvcnJlY3QgdHlwZSAqL1xuXHRcdGlmIChcIkhFWFwiID09PSBpbnB1dEZvcm1hdClcblx0XHR7XG5cdFx0XHRpZiAoMCAhPT0gKHNyY1N0cmluZy5sZW5ndGggJSAyKSlcblx0XHRcdHtcblx0XHRcdFx0cmV0dXJuIFwiVEVYVCBNVVNUIEJFIElOIEJZVEUgSU5DUkVNRU5UU1wiO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5zdHJCaW5MZW4gPSBzcmNTdHJpbmcubGVuZ3RoICogNDtcblx0XHRcdHRoaXMuc3RyVG9IYXNoID0gaGV4MmJpbmIoc3JjU3RyaW5nKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoKFwiQVNDSUlcIiA9PT0gaW5wdXRGb3JtYXQpIHx8XG5cdFx0XHQgKCd1bmRlZmluZWQnID09PSB0eXBlb2YoaW5wdXRGb3JtYXQpKSlcblx0XHR7XG5cdFx0XHR0aGlzLnN0ckJpbkxlbiA9IHNyY1N0cmluZy5sZW5ndGggKiBjaGFyU2l6ZTtcblx0XHRcdHRoaXMuc3RyVG9IYXNoID0gc3RyMmJpbmIoc3JjU3RyaW5nKTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdHJldHVybiBcIlVOS05PV04gVEVYVCBJTlBVVCBUWVBFXCI7XG5cdFx0fVxuXHR9O1xuXG5cdGpzU0hBLnByb3RvdHlwZSA9IHtcblx0XHQvKlxuXHRcdCAqIFJldHVybnMgdGhlIGRlc2lyZWQgU0hBIGhhc2ggb2YgdGhlIHN0cmluZyBzcGVjaWZpZWQgYXQgaW5zdGFudGlhdGlvblxuXHRcdCAqIHVzaW5nIHRoZSBzcGVjaWZpZWQgcGFyYW1ldGVyc1xuXHRcdCAqXG5cdFx0ICogQHBhcmFtIHtTdHJpbmd9IHZhcmlhbnQgVGhlIGRlc2lyZWQgU0hBIHZhcmlhbnQgKFNIQS0xLCBTSEEtMjI0LFxuXHRcdCAqXHQgU0hBLTI1NiwgU0hBLTM4NCwgb3IgU0hBLTUxMilcblx0XHQgKiBAcGFyYW0ge1N0cmluZ30gZm9ybWF0IFRoZSBkZXNpcmVkIG91dHB1dCBmb3JtYXR0aW5nIChCNjQgb3IgSEVYKVxuXHRcdCAqIEByZXR1cm4gVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgaGFzaCBpbiB0aGUgZm9ybWF0IHNwZWNpZmllZFxuXHRcdCAqL1xuXHRcdGdldEhhc2ggOiBmdW5jdGlvbiAodmFyaWFudCwgZm9ybWF0KVxuXHRcdHtcblx0XHRcdHZhciBmb3JtYXRGdW5jID0gbnVsbCwgbWVzc2FnZSA9IHRoaXMuc3RyVG9IYXNoLnNsaWNlKCk7XG5cblx0XHRcdHN3aXRjaCAoZm9ybWF0KVxuXHRcdFx0e1xuXHRcdFx0Y2FzZSBcIkhFWFwiOlxuXHRcdFx0XHRmb3JtYXRGdW5jID0gYmluYjJoZXg7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcIkI2NFwiOlxuXHRcdFx0XHRmb3JtYXRGdW5jID0gYmluYjJiNjQ7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcIkFTQ0lJXCI6XG5cdFx0XHRcdGZvcm1hdEZ1bmMgPSBiaW5iMnN0cjtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRyZXR1cm4gXCJGT1JNQVQgTk9UIFJFQ09HTklaRURcIjtcblx0XHRcdH1cblxuXHRcdFx0c3dpdGNoICh2YXJpYW50KVxuXHRcdFx0e1xuXHRcdFx0Y2FzZSBcIlNIQS0xXCI6XG5cdFx0XHRcdGlmIChudWxsID09PSB0aGlzLnNoYTEpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLnNoYTEgPSBjb3JlU0hBMShtZXNzYWdlLCB0aGlzLnN0ckJpbkxlbik7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIGZvcm1hdEZ1bmModGhpcy5zaGExKTtcblx0XHRcdGNhc2UgXCJTSEEtMjI0XCI6XG5cdFx0XHRcdGlmIChudWxsID09PSB0aGlzLnNoYTIyNClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuc2hhMjI0ID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhMjI0KTtcblx0XHRcdGNhc2UgXCJTSEEtMjU2XCI6XG5cdFx0XHRcdGlmIChudWxsID09PSB0aGlzLnNoYTI1Nilcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuc2hhMjU2ID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhMjU2KTtcblx0XHRcdGNhc2UgXCJTSEEtMzg0XCI6XG5cdFx0XHRcdGlmIChudWxsID09PSB0aGlzLnNoYTM4NClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuc2hhMzg0ID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhMzg0KTtcblx0XHRcdGNhc2UgXCJTSEEtNTEyXCI6XG5cdFx0XHRcdGlmIChudWxsID09PSB0aGlzLnNoYTUxMilcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRoaXMuc2hhNTEyID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhNTEyKTtcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHJldHVybiBcIkhBU0ggTk9UIFJFQ09HTklaRURcIjtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0Lypcblx0XHQgKiBSZXR1cm5zIHRoZSBkZXNpcmVkIEhNQUMgb2YgdGhlIHN0cmluZyBzcGVjaWZpZWQgYXQgaW5zdGFudGlhdGlvblxuXHRcdCAqIHVzaW5nIHRoZSBrZXkgYW5kIHZhcmlhbnQgcGFyYW0uXG5cdFx0ICpcblx0XHQgKiBAcGFyYW0ge1N0cmluZ30ga2V5IFRoZSBrZXkgdXNlZCB0byBjYWxjdWxhdGUgdGhlIEhNQUNcblx0XHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXRGb3JtYXQgVGhlIGZvcm1hdCBvZiBrZXksIEFTQ0lJIG9yIEhFWFxuXHRcdCAqIEBwYXJhbSB7U3RyaW5nfSB2YXJpYW50IFRoZSBkZXNpcmVkIFNIQSB2YXJpYW50IChTSEEtMSwgU0hBLTIyNCxcblx0XHQgKlx0IFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIpXG5cdFx0ICogQHBhcmFtIHtTdHJpbmd9IG91dHB1dEZvcm1hdCBUaGUgZGVzaXJlZCBvdXRwdXQgZm9ybWF0dGluZ1xuXHRcdCAqXHQgKEI2NCBvciBIRVgpXG5cdFx0ICogQHJldHVybiBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBoYXNoIGluIHRoZSBmb3JtYXQgc3BlY2lmaWVkXG5cdFx0ICovXG5cdFx0Z2V0SE1BQyA6IGZ1bmN0aW9uIChrZXksIGlucHV0Rm9ybWF0LCB2YXJpYW50LCBvdXRwdXRGb3JtYXQpXG5cdFx0e1xuXHRcdFx0dmFyIGZvcm1hdEZ1bmMsIGtleVRvVXNlLCBibG9ja0J5dGVTaXplLCBibG9ja0JpdFNpemUsIGksXG5cdFx0XHRcdHJldFZhbCwgbGFzdEFycmF5SW5kZXgsIGtleUJpbkxlbiwgaGFzaEJpdFNpemUsXG5cdFx0XHRcdGtleVdpdGhJUGFkID0gW10sIGtleVdpdGhPUGFkID0gW107XG5cblx0XHRcdC8qIFZhbGlkYXRlIHRoZSBvdXRwdXQgZm9ybWF0IHNlbGVjdGlvbiAqL1xuXHRcdFx0c3dpdGNoIChvdXRwdXRGb3JtYXQpXG5cdFx0XHR7XG5cdFx0XHRjYXNlIFwiSEVYXCI6XG5cdFx0XHRcdGZvcm1hdEZ1bmMgPSBiaW5iMmhleDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwiQjY0XCI6XG5cdFx0XHRcdGZvcm1hdEZ1bmMgPSBiaW5iMmI2NDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwiQVNDSUlcIjpcblx0XHRcdFx0Zm9ybWF0RnVuYyA9IGJpbmIyc3RyO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHJldHVybiBcIkZPUk1BVCBOT1QgUkVDT0dOSVpFRFwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvKiBWYWxpZGF0ZSB0aGUgaGFzaCB2YXJpYW50IHNlbGVjdGlvbiBhbmQgc2V0IG5lZWRlZCB2YXJpYWJsZXMgKi9cblx0XHRcdHN3aXRjaCAodmFyaWFudClcblx0XHRcdHtcblx0XHRcdGNhc2UgXCJTSEEtMVwiOlxuXHRcdFx0XHRibG9ja0J5dGVTaXplID0gNjQ7XG5cdFx0XHRcdGhhc2hCaXRTaXplID0gMTYwO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgXCJTSEEtMjI0XCI6XG5cdFx0XHRcdGJsb2NrQnl0ZVNpemUgPSA2NDtcblx0XHRcdFx0aGFzaEJpdFNpemUgPSAyMjQ7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSBcIlNIQS0yNTZcIjpcblx0XHRcdFx0YmxvY2tCeXRlU2l6ZSA9IDY0O1xuXHRcdFx0XHRoYXNoQml0U2l6ZSA9IDI1Njtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwiU0hBLTM4NFwiOlxuXHRcdFx0XHRibG9ja0J5dGVTaXplID0gMTI4O1xuXHRcdFx0XHRoYXNoQml0U2l6ZSA9IDM4NDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIFwiU0hBLTUxMlwiOlxuXHRcdFx0XHRibG9ja0J5dGVTaXplID0gMTI4O1xuXHRcdFx0XHRoYXNoQml0U2l6ZSA9IDUxMjtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRyZXR1cm4gXCJIQVNIIE5PVCBSRUNPR05JWkVEXCI7XG5cdFx0XHR9XG5cblx0XHRcdC8qIFZhbGlkYXRlIGlucHV0IGZvcm1hdCBzZWxlY3Rpb24gKi9cblx0XHRcdGlmIChcIkhFWFwiID09PSBpbnB1dEZvcm1hdClcblx0XHRcdHtcblx0XHRcdFx0LyogTmliYmxlcyBtdXN0IGNvbWUgaW4gcGFpcnMgKi9cblx0XHRcdFx0aWYgKDAgIT09IChrZXkubGVuZ3RoICUgMikpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRyZXR1cm4gXCJLRVkgTVVTVCBCRSBJTiBCWVRFIElOQ1JFTUVOVFNcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRrZXlUb1VzZSA9IGhleDJiaW5iKGtleSk7XG5cdFx0XHRcdGtleUJpbkxlbiA9IGtleS5sZW5ndGggKiA0O1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoXCJBU0NJSVwiID09PSBpbnB1dEZvcm1hdClcblx0XHRcdHtcblx0XHRcdFx0a2V5VG9Vc2UgPSBzdHIyYmluYihrZXkpO1xuXHRcdFx0XHRrZXlCaW5MZW4gPSBrZXkubGVuZ3RoICogY2hhclNpemU7XG5cdFx0XHR9XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdHJldHVybiBcIlVOS05PV04gS0VZIElOUFVUIFRZUEVcIjtcblx0XHRcdH1cblxuXHRcdFx0LyogVGhlc2UgYXJlIHVzZWQgbXVsdGlwbGUgdGltZXMsIGNhbGN1bGF0ZSBhbmQgc3RvcmUgdGhlbSAqL1xuXHRcdFx0YmxvY2tCaXRTaXplID0gYmxvY2tCeXRlU2l6ZSAqIDg7XG5cdFx0XHRsYXN0QXJyYXlJbmRleCA9IChibG9ja0J5dGVTaXplIC8gNCkgLSAxO1xuXG5cdFx0XHQvKiBGaWd1cmUgb3V0IHdoYXQgdG8gZG8gd2l0aCB0aGUga2V5IGJhc2VkIG9uIGl0cyBzaXplIHJlbGF0aXZlIHRvXG5cdFx0XHQgKiB0aGUgaGFzaCdzIGJsb2NrIHNpemUgKi9cblx0XHRcdGlmIChibG9ja0J5dGVTaXplIDwgKGtleUJpbkxlbiAvIDgpKVxuXHRcdFx0e1xuXHRcdFx0XHRpZiAoXCJTSEEtMVwiID09PSB2YXJpYW50KVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0a2V5VG9Vc2UgPSBjb3JlU0hBMShrZXlUb1VzZSwga2V5QmluTGVuKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRrZXlUb1VzZSA9IGNvcmVTSEEyKGtleVRvVXNlLCBrZXlCaW5MZW4sIHZhcmlhbnQpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdC8qIEZvciBhbGwgdmFyaWFudHMsIHRoZSBibG9jayBzaXplIGlzIGJpZ2dlciB0aGFuIHRoZSBvdXRwdXRcblx0XHRcdFx0ICogc2l6ZSBzbyB0aGVyZSB3aWxsIG5ldmVyIGJlIGEgdXNlZnVsIGJ5dGUgYXQgdGhlIGVuZCBvZiB0aGVcblx0XHRcdFx0ICogc3RyaW5nICovXG5cdFx0XHRcdGtleVRvVXNlW2xhc3RBcnJheUluZGV4XSAmPSAweEZGRkZGRjAwO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoYmxvY2tCeXRlU2l6ZSA+IChrZXlCaW5MZW4gLyA4KSlcblx0XHRcdHtcblx0XHRcdFx0LyogSWYgdGhlIGJsb2NrQnl0ZVNpemUgaXMgZ3JlYXRlciB0aGFuIHRoZSBrZXkgbGVuZ3RoLCB0aGVyZVxuXHRcdFx0XHQgKiB3aWxsIGFsd2F5cyBiZSBhdCBMRUFTVCBvbmUgXCJ1c2VsZXNzXCIgYnl0ZSBhdCB0aGUgZW5kIG9mIHRoZVxuXHRcdFx0XHQgKiBzdHJpbmcgKi9cblx0XHRcdFx0a2V5VG9Vc2VbbGFzdEFycmF5SW5kZXhdICY9IDB4RkZGRkZGMDA7XG5cdFx0XHR9XG5cblx0XHRcdC8qIENyZWF0ZSBpcGFkIGFuZCBvcGFkICovXG5cdFx0XHRmb3IgKGkgPSAwOyBpIDw9IGxhc3RBcnJheUluZGV4OyBpICs9IDEpXG5cdFx0XHR7XG5cdFx0XHRcdGtleVdpdGhJUGFkW2ldID0ga2V5VG9Vc2VbaV0gXiAweDM2MzYzNjM2O1xuXHRcdFx0XHRrZXlXaXRoT1BhZFtpXSA9IGtleVRvVXNlW2ldIF4gMHg1QzVDNUM1Qztcblx0XHRcdH1cblxuXHRcdFx0LyogQ2FsY3VsYXRlIHRoZSBITUFDICovXG5cdFx0XHRpZiAoXCJTSEEtMVwiID09PSB2YXJpYW50KVxuXHRcdFx0e1xuXHRcdFx0XHRyZXRWYWwgPSBjb3JlU0hBMShcblx0XHRcdFx0XHRcdFx0a2V5V2l0aElQYWQuY29uY2F0KHRoaXMuc3RyVG9IYXNoKSxcblx0XHRcdFx0XHRcdFx0YmxvY2tCaXRTaXplICsgdGhpcy5zdHJCaW5MZW4pO1xuXHRcdFx0XHRyZXRWYWwgPSBjb3JlU0hBMShcblx0XHRcdFx0XHRcdFx0a2V5V2l0aE9QYWQuY29uY2F0KHJldFZhbCksXG5cdFx0XHRcdFx0XHRcdGJsb2NrQml0U2l6ZSArIGhhc2hCaXRTaXplKTtcblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0cmV0VmFsID0gY29yZVNIQTIoXG5cdFx0XHRcdFx0XHRcdGtleVdpdGhJUGFkLmNvbmNhdCh0aGlzLnN0clRvSGFzaCksXG5cdFx0XHRcdFx0XHRcdGJsb2NrQml0U2l6ZSArIHRoaXMuc3RyQmluTGVuLCB2YXJpYW50KTtcblx0XHRcdFx0cmV0VmFsID0gY29yZVNIQTIoXG5cdFx0XHRcdFx0XHRcdGtleVdpdGhPUGFkLmNvbmNhdChyZXRWYWwpLFxuXHRcdFx0XHRcdFx0XHRibG9ja0JpdFNpemUgKyBoYXNoQml0U2l6ZSwgdmFyaWFudCk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiAoZm9ybWF0RnVuYyhyZXRWYWwpKTtcblx0XHR9XG5cdH07XG5cblx0cmV0dXJuIGpzU0hBO1xufSgpKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cdHNoYTE6IGZ1bmN0aW9uKHN0cikge1xuXHRcdHZhciBzaGFPYmogPSBuZXcganNTSEEoc3RyLCBcIkFTQ0lJXCIpO1xuXHRcdHJldHVybiBzaGFPYmouZ2V0SGFzaChcIlNIQS0xXCIsIFwiQVNDSUlcIik7XG5cdH0sXG5cdHNoYTIyNDogZnVuY3Rpb24oc3RyKSB7XG5cdFx0dmFyIHNoYU9iaiA9IG5ldyBqc1NIQShzdHIsIFwiQVNDSUlcIik7XG5cdFx0cmV0dXJuIHNoYU9iai5nZXRIYXNoKFwiU0hBLTIyNFwiLCBcIkFTQ0lJXCIpO1xuXHR9LFxuXHRzaGEyNTY6IGZ1bmN0aW9uKHN0cikge1xuXHRcdHZhciBzaGFPYmogPSBuZXcganNTSEEoc3RyLCBcIkFTQ0lJXCIpO1xuXHRcdHJldHVybiBzaGFPYmouZ2V0SGFzaChcIlNIQS0yNTZcIiwgXCJBU0NJSVwiKTtcblx0fSxcblx0c2hhMzg0OiBmdW5jdGlvbihzdHIpIHtcblx0XHR2YXIgc2hhT2JqID0gbmV3IGpzU0hBKHN0ciwgXCJBU0NJSVwiKTtcblx0XHRyZXR1cm4gc2hhT2JqLmdldEhhc2goXCJTSEEtMzg0XCIsIFwiQVNDSUlcIik7XG5cblx0fSxcblx0c2hhNTEyOiBmdW5jdGlvbihzdHIpIHtcblx0XHR2YXIgc2hhT2JqID0gbmV3IGpzU0hBKHN0ciwgXCJBU0NJSVwiKTtcblx0XHRyZXR1cm4gc2hhT2JqLmdldEhhc2goXCJTSEEtNTEyXCIsIFwiQVNDSUlcIik7XG5cdH1cbn1cbiIsIlxubW9kdWxlLmV4cG9ydHMgPSB7XG5cdGNpcGhlcjogcmVxdWlyZSgnLi9jaXBoZXInKSxcblx0aGFzaDogcmVxdWlyZSgnLi9oYXNoJyksXG5cdGNmYjogcmVxdWlyZSgnLi9jZmIuanMnKSxcblx0cHVibGljS2V5OiByZXF1aXJlKCcuL3B1YmxpY19rZXknKSxcblx0c2lnbmF0dXJlOiByZXF1aXJlKCcuL3NpZ25hdHVyZS5qcycpLFxuXHRyYW5kb206IHJlcXVpcmUoJy4vcmFuZG9tLmpzJyksXG5cdHBrY3MxOiByZXF1aXJlKCcuL3BrY3MxLmpzJylcblxufVxuXG52YXIgY3J5cHRvID0gcmVxdWlyZSgnLi9jcnlwdG8uanMnKTtcblxuZm9yKHZhciBpIGluIGNyeXB0bylcblx0bW9kdWxlLmV4cG9ydHNbaV0gPSBjcnlwdG9baV07XG5cblxuXG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKipcbiAqIEFTTjEgb2JqZWN0IGlkZW50aWZpZXJzIGZvciBoYXNoZXMgKFNlZSBSRkM0ODgwIDUuMi4yKVxuICovXG5oYXNoX2hlYWRlcnMgPSBuZXcgQXJyYXkoKTtcbmhhc2hfaGVhZGVyc1sxXSAgPSBbMHgzMCwweDIwLDB4MzAsMHgwYywweDA2LDB4MDgsMHgyYSwweDg2LDB4NDgsMHg4NiwweGY3LDB4MGQsMHgwMiwweDA1LDB4MDUsMHgwMCwweDA0LDB4MTBdO1xuaGFzaF9oZWFkZXJzWzNdICA9IFsweDMwLDB4MjEsMHgzMCwweDA5LDB4MDYsMHgwNSwweDJCLDB4MjQsMHgwMywweDAyLDB4MDEsMHgwNSwweDAwLDB4MDQsMHgxNF07XG5oYXNoX2hlYWRlcnNbMl0gID0gWzB4MzAsMHgyMSwweDMwLDB4MDksMHgwNiwweDA1LDB4MmIsMHgwZSwweDAzLDB4MDIsMHgxYSwweDA1LDB4MDAsMHgwNCwweDE0XTtcbmhhc2hfaGVhZGVyc1s4XSAgPSBbMHgzMCwweDMxLDB4MzAsMHgwZCwweDA2LDB4MDksMHg2MCwweDg2LDB4NDgsMHgwMSwweDY1LDB4MDMsMHgwNCwweDAyLDB4MDEsMHgwNSwweDAwLDB4MDQsMHgyMF07XG5oYXNoX2hlYWRlcnNbOV0gID0gWzB4MzAsMHg0MSwweDMwLDB4MGQsMHgwNiwweDA5LDB4NjAsMHg4NiwweDQ4LDB4MDEsMHg2NSwweDAzLDB4MDQsMHgwMiwweDAyLDB4MDUsMHgwMCwweDA0LDB4MzBdO1xuaGFzaF9oZWFkZXJzWzEwXSA9IFsweDMwLDB4NTEsMHgzMCwweDBkLDB4MDYsMHgwOSwweDYwLDB4ODYsMHg0OCwweDAxLDB4NjUsMHgwMywweDA0LDB4MDIsMHgwMywweDA1LDB4MDAsMHgwNCwweDQwXTtcbmhhc2hfaGVhZGVyc1sxMV0gPSBbMHgzMCwweDMxLDB4MzAsMHgwZCwweDA2LDB4MDksMHg2MCwweDg2LDB4NDgsMHgwMSwweDY1LDB4MDMsMHgwNCwweDAyLDB4MDQsMHgwNSwweDAwLDB4MDQsMHgxQ107XG5cblxudmFyIGNyeXB0byA9IHJlcXVpcmUoJy4vY3J5cHRvLmpzJyksXG5cdHJhbmRvbSA9IHJlcXVpcmUoJy4vcmFuZG9tLmpzJyksXG5cdHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG5cdEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL3B1YmxpY19rZXkvanNibi5qcycpLFxuXHRoYXNoID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cdFxubW9kdWxlLmV4cG9ydHMgPSB7XG5cdGVtZToge1xuXHQvKipcblx0ICogY3JlYXRlIGEgRU1FLVBLQ1MxLXYxXzUgcGFkZGluZyAoU2VlIFJGQzQ4ODAgMTMuMS4xKVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBtZXNzYWdlIHRvIGJlIHBhZGRlZFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBMZW5ndGggdG8gdGhlIHJlc3VsdGluZyBtZXNzYWdlXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gRU1FLVBLQ1MxIHBhZGRlZCBtZXNzYWdlXG5cdCAqL1xuXHRlbmNvZGU6IGZ1bmN0aW9uKG1lc3NhZ2UsIGxlbmd0aCkge1xuXHRcdGlmIChtZXNzYWdlLmxlbmd0aCA+IGxlbmd0aC0xMSlcblx0XHRcdHJldHVybiAtMTtcblx0XHR2YXIgcmVzdWx0ID0gXCJcIjtcblx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcblx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgyKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aCAtIG1lc3NhZ2UubGVuZ3RoIC0gMzsgaSsrKSB7XG5cdFx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShyYW5kb20uZ2V0UHNldWRvUmFuZG9tKDEsMjU1KSk7XG5cdFx0fVxuXHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuXHRcdHJlc3VsdCArPSBtZXNzYWdlO1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0LyoqXG5cdCAqIGRlY29kZXMgYSBFTUUtUEtDUzEtdjFfNSBwYWRkaW5nIChTZWUgUkZDNDg4MCAxMy4xLjIpXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIEVNRS1QS0NTMSBwYWRkZWQgbWVzc2FnZVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IGRlY29kZWQgbWVzc2FnZSBcblx0ICovXG5cdCBkZWNvZGU6IGZ1bmN0aW9uKG1lc3NhZ2UsIGxlbikge1xuXHRcdGlmIChtZXNzYWdlLmxlbmd0aCA8IGxlbilcblx0XHRcdG1lc3NhZ2UgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApK21lc3NhZ2U7XG5cdFx0aWYgKG1lc3NhZ2UubGVuZ3RoIDwgMTIgfHwgbWVzc2FnZS5jaGFyQ29kZUF0KDApICE9IDAgfHwgbWVzc2FnZS5jaGFyQ29kZUF0KDEpICE9IDIpXG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0dmFyIGkgPSAyO1xuXHRcdHdoaWxlIChtZXNzYWdlLmNoYXJDb2RlQXQoaSkgIT0gMCAmJiBtZXNzYWdlLmxlbmd0aCA+IGkpXG5cdFx0XHRpKys7XG5cdFx0cmV0dXJuIG1lc3NhZ2Uuc3Vic3RyaW5nKGkrMSwgbWVzc2FnZS5sZW5ndGgpO1xuXHR9LFxuXHR9LFxuXG5cdGVtc2E6IHtcblxuXHQvKipcblx0ICogY3JlYXRlIGEgRU1TQS1QS0NTMS12MV81IHBhZGRpbmcgKFNlZSBSRkM0ODgwIDEzLjEuMylcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEhhc2ggYWxnb3JpdGhtIHR5cGUgdXNlZFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIHRvIGJlIGhhc2hlZFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGtleWxlbmd0aCBLZXkgc2l6ZSBvZiB0aGUgcHVibGljIG1waSBpbiBieXRlc1xuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBIYXNoY29kZSB3aXRoIHBrY3MxcGFkZGluZyBhcyBzdHJpbmdcblx0ICovXG5cdGVuY29kZTogZnVuY3Rpb24oYWxnbywgZGF0YSwga2V5bGVuZ3RoKSB7XG5cdFx0dmFyIGRhdGEyID0gXCJcIjtcblx0XHRkYXRhMiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MDApO1xuXHRcdGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHgwMSk7XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCAoa2V5bGVuZ3RoIC0gaGFzaF9oZWFkZXJzW2FsZ29dLmxlbmd0aCAtIDMgLSBcblx0XHRcdGhhc2guZ2V0SGFzaEJ5dGVMZW5ndGgoYWxnbykpOyBpKyspXG5cblx0XHRcdGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhmZik7XG5cblx0XHRkYXRhMiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MDApO1xuXHRcdFxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgaGFzaF9oZWFkZXJzW2FsZ29dLmxlbmd0aDsgaSsrKVxuXHRcdFx0ZGF0YTIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShoYXNoX2hlYWRlcnNbYWxnb11baV0pO1xuXHRcdFxuXHRcdGRhdGEyICs9IGhhc2guZGlnZXN0KGFsZ28sIGRhdGEpO1xuXHRcdHJldHVybiBuZXcgQmlnSW50ZWdlcih1dGlsLmhleHN0cmR1bXAoZGF0YTIpLDE2KTtcblx0fSxcblxuXHQvKipcblx0ICogZXh0cmFjdCB0aGUgaGFzaCBvdXQgb2YgYW4gRU1TQS1QS0NTMS12MS41IHBhZGRpbmcgKFNlZSBSRkM0ODgwIDEzLjEuMykgXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIEhhc2ggaW4gcGtjczEgZW5jb2Rpbmdcblx0ICogQHJldHVybnMge1N0cmluZ30gVGhlIGhhc2ggYXMgc3RyaW5nXG5cdCAqL1xuXHRkZWNvZGU6IGZ1bmN0aW9uKGFsZ28sIGRhdGEpIHsgXG5cdFx0dmFyIGkgPSAwO1xuXHRcdGlmIChkYXRhLmNoYXJDb2RlQXQoMCkgPT0gMCkgaSsrO1xuXHRcdGVsc2UgaWYgKGRhdGEuY2hhckNvZGVBdCgwKSAhPSAxKSByZXR1cm4gLTE7XG5cdFx0ZWxzZSBpKys7XG5cblx0XHR3aGlsZSAoZGF0YS5jaGFyQ29kZUF0KGkpID09IDB4RkYpIGkrKztcblx0XHRpZiAoZGF0YS5jaGFyQ29kZUF0KGkrKykgIT0gMCkgcmV0dXJuIC0xO1xuXHRcdHZhciBqID0gMDtcblx0XHRmb3IgKGogPSAwOyBqIDwgaGFzaF9oZWFkZXJzW2FsZ29dLmxlbmd0aCAmJiBqK2kgPCBkYXRhLmxlbmd0aDsgaisrKSB7XG5cdFx0XHRpZiAoZGF0YS5jaGFyQ29kZUF0KGoraSkgIT0gaGFzaF9oZWFkZXJzW2FsZ29dW2pdKSByZXR1cm4gLTE7XG5cdFx0fVxuXHRcdGkrPSBqO1x0XG5cdFx0aWYgKGRhdGEuc3Vic3RyaW5nKGkpLmxlbmd0aCA8IGhhc2guZ2V0SGFzaEJ5dGVMZW5ndGgoYWxnbykpIHJldHVybiAtMTtcblx0XHRyZXR1cm4gZGF0YS5zdWJzdHJpbmcoaSk7XG5cdH1cblx0fVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0Fcbi8vXG4vLyBBIERpZ2l0YWwgc2lnbmF0dXJlIGFsZ29yaXRobSBpbXBsZW1lbnRhdGlvblxuXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4vanNibi5qcycpLFxuICBjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8uanMnKSxcbiAgaGFzaE1vZHVsZSA9IHJlcXVpcmUoJy4uL2hhc2gnKSxcblx0dXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuZnVuY3Rpb24gRFNBKCkge1xuXHQvLyBzMSA9ICgoZyoqcykgbW9kIHApIG1vZCBxXG5cdC8vIHMxID0gKChzKiotMSkqKHNoYS0xKG0pKyhzMSp4KSBtb2QgcSlcblx0ZnVuY3Rpb24gc2lnbihoYXNoYWxnbywgbSwgZywgcCwgcSwgeCkge1xuXHRcdC8vIElmIHRoZSBvdXRwdXQgc2l6ZSBvZiB0aGUgY2hvc2VuIGhhc2ggaXMgbGFyZ2VyIHRoYW4gdGhlIG51bWJlciBvZlxuXHRcdC8vIGJpdHMgb2YgcSwgdGhlIGhhc2ggcmVzdWx0IGlzIHRydW5jYXRlZCB0byBmaXQgYnkgdGFraW5nIHRoZSBudW1iZXJcblx0XHQvLyBvZiBsZWZ0bW9zdCBiaXRzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgYml0cyBvZiBxLiAgVGhpcyAocG9zc2libHlcblx0XHQvLyB0cnVuY2F0ZWQpIGhhc2ggZnVuY3Rpb24gcmVzdWx0IGlzIHRyZWF0ZWQgYXMgYSBudW1iZXIgYW5kIHVzZWRcblx0XHQvLyBkaXJlY3RseSBpbiB0aGUgRFNBIHNpZ25hdHVyZSBhbGdvcml0aG0uXG5cdFx0dmFyIGhhc2hlZF9kYXRhID0gdXRpbC5nZXRMZWZ0TkJpdHMoaGFzaE1vZHVsZS5kaWdlc3QoaGFzaGFsZ28sbSkscS5iaXRMZW5ndGgoKSk7XG5cdFx0dmFyIGhhc2ggPSBuZXcgQmlnSW50ZWdlcih1dGlsLmhleHN0cmR1bXAoaGFzaGVkX2RhdGEpLCAxNik7XG5cdFx0dmFyIGsgPSBjcnlwdG8uZ2V0UmFuZG9tQmlnSW50ZWdlckluUmFuZ2UoQmlnSW50ZWdlci5PTkUuYWRkKEJpZ0ludGVnZXIuT05FKSwgcS5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkpO1xuXHRcdHZhciBzMSA9IChnLm1vZFBvdyhrLHApKS5tb2QocSk7IFxuXHRcdHZhciBzMiA9IChrLm1vZEludmVyc2UocSkubXVsdGlwbHkoaGFzaC5hZGQoeC5tdWx0aXBseShzMSkpKSkubW9kKHEpO1xuXHRcdHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblx0XHRyZXN1bHRbMF0gPSBzMS50b01QSSgpO1xuXHRcdHJlc3VsdFsxXSA9IHMyLnRvTVBJKCk7XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXHRmdW5jdGlvbiBzZWxlY3RfaGFzaF9hbGdvcml0aG0ocSkge1xuXHRcdHZhciB1c2Vyc2V0dGluZyA9IG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5wcmVmZXJfaGFzaF9hbGdvcml0aG07XG5cdFx0Lypcblx0XHQgKiAxMDI0LWJpdCBrZXksIDE2MC1iaXQgcSwgU0hBLTEsIFNIQS0yMjQsIFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIgaGFzaFxuXHRcdCAqIDIwNDgtYml0IGtleSwgMjI0LWJpdCBxLCBTSEEtMjI0LCBTSEEtMjU2LCBTSEEtMzg0LCBvciBTSEEtNTEyIGhhc2hcblx0XHQgKiAyMDQ4LWJpdCBrZXksIDI1Ni1iaXQgcSwgU0hBLTI1NiwgU0hBLTM4NCwgb3IgU0hBLTUxMiBoYXNoXG5cdFx0ICogMzA3Mi1iaXQga2V5LCAyNTYtYml0IHEsIFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIgaGFzaFxuXHRcdCAqL1xuXHRcdHN3aXRjaCAoTWF0aC5yb3VuZChxLmJpdExlbmd0aCgpIC8gOCkpIHtcblx0XHRjYXNlIDIwOiAvLyAxMDI0IGJpdFxuXHRcdFx0aWYgKHVzZXJzZXR0aW5nICE9IDIgJiZcblx0XHRcdFx0dXNlcnNldHRpbmcgPiAxMSAmJlxuXHRcdFx0XHR1c2Vyc2V0dGluZyAhPSAxMCAmJlxuXHRcdFx0XHR1c2Vyc2V0dGluZyA8IDgpXG5cdFx0XHRcdHJldHVybiAyOyAvLyBwcmVmZXIgc2hhMVxuXHRcdFx0cmV0dXJuIHVzZXJzZXR0aW5nO1xuXHRcdGNhc2UgMjg6IC8vIDIwNDggYml0XG5cdFx0XHRpZiAodXNlcnNldHRpbmcgPiAxMSAmJlxuXHRcdFx0XHRcdHVzZXJzZXR0aW5nIDwgOClcblx0XHRcdFx0XHRyZXR1cm4gMTE7XG5cdFx0XHRyZXR1cm4gdXNlcnNldHRpbmc7XG5cdFx0Y2FzZSAzMjogLy8gNDA5NiBiaXQgLy8gcHJlZmVyIHNoYTIyNFxuXHRcdFx0aWYgKHVzZXJzZXR0aW5nID4gMTAgJiZcblx0XHRcdFx0XHR1c2Vyc2V0dGluZyA8IDgpXG5cdFx0XHRcdFx0cmV0dXJuIDg7IC8vIHByZWZlciBzaGEyNTZcblx0XHRcdHJldHVybiB1c2Vyc2V0dGluZztcblx0XHRkZWZhdWx0OlxuXHRcdFx0dXRpbC5wcmludF9kZWJ1ZyhcIkRTQSBzZWxlY3QgaGFzaCBhbGdvcml0aG06IHJldHVybmluZyBudWxsIGZvciBhbiB1bmtub3duIGxlbmd0aCBvZiBxXCIpO1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHRcblx0XHR9XG5cdH1cblx0dGhpcy5zZWxlY3RfaGFzaF9hbGdvcml0aG0gPSBzZWxlY3RfaGFzaF9hbGdvcml0aG07XG5cdFxuXHRmdW5jdGlvbiB2ZXJpZnkoaGFzaGFsZ28sIHMxLHMyLG0scCxxLGcseSkge1xuXHRcdHZhciBoYXNoZWRfZGF0YSA9IHV0aWwuZ2V0TGVmdE5CaXRzKGhhc2hNb2R1bGUuZGlnZXN0KGhhc2hhbGdvLG0pLHEuYml0TGVuZ3RoKCkpO1xuXHRcdHZhciBoYXNoID0gbmV3IEJpZ0ludGVnZXIodXRpbC5oZXhzdHJkdW1wKGhhc2hlZF9kYXRhKSwgMTYpOyBcblx0XHRpZiAoQmlnSW50ZWdlci5aRVJPLmNvbXBhcmVUbyhzMSkgPiAwIHx8XG5cdFx0XHRcdHMxLmNvbXBhcmVUbyhxKSA+IDAgfHxcblx0XHRcdFx0QmlnSW50ZWdlci5aRVJPLmNvbXBhcmVUbyhzMikgPiAwIHx8XG5cdFx0XHRcdHMyLmNvbXBhcmVUbyhxKSA+IDApIHtcblx0XHRcdHV0aWwucHJpbnRfZXJyb3IoXCJpbnZhbGlkIERTQSBTaWduYXR1cmVcIik7XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdFx0dmFyIHcgPSBzMi5tb2RJbnZlcnNlKHEpO1xuXHRcdHZhciB1MSA9IGhhc2gubXVsdGlwbHkodykubW9kKHEpO1xuXHRcdHZhciB1MiA9IHMxLm11bHRpcGx5KHcpLm1vZChxKTtcblx0XHRyZXR1cm4gZy5tb2RQb3codTEscCkubXVsdGlwbHkoeS5tb2RQb3codTIscCkpLm1vZChwKS5tb2QocSk7XG5cdH1cblx0XG5cdC8qXG5cdCAqIHVudXNlZCBjb2RlLiBUaGlzIGNhbiBiZSB1c2VkIGFzIGEgc3RhcnQgdG8gd3JpdGUgYSBrZXkgZ2VuZXJhdG9yXG5cdCAqIGZ1bmN0aW9uLlxuXHRcblx0ZnVuY3Rpb24gZ2VuZXJhdGVLZXkoYml0Y291bnQpIHtcblx0ICAgIHZhciBxaSA9IG5ldyBCaWdJbnRlZ2VyKGJpdGNvdW50LCBwcmltZUNlbnRlcmllKTtcblx0ICAgIHZhciBwaSA9IGdlbmVyYXRlUChxLCA1MTIpO1xuXHQgICAgdmFyIGdpID0gZ2VuZXJhdGVHKHAsIHEsIGJpdGNvdW50KTtcblx0ICAgIHZhciB4aTtcblx0ICAgIGRvIHtcblx0ICAgICAgICB4aSA9IG5ldyBCaWdJbnRlZ2VyKHEuYml0Q291bnQoKSwgcmFuZCk7XG5cdCAgICB9IHdoaWxlICh4LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pICE9IDEgJiYgeC5jb21wYXJlVG8ocSkgIT0gLTEpO1xuXHQgICAgdmFyIHlpID0gZy5tb2RQb3coeCwgcCk7XG5cdCAgICByZXR1cm4ge3g6IHhpLCBxOiBxaSwgcDogcGksIGc6IGdpLCB5OiB5aX07XG5cdH1cblxuXHRmdW5jdGlvbiBnZW5lcmF0ZVAocSwgYml0bGVuZ3RoLCByYW5kb21mbikge1xuXHQgICAgaWYgKGJpdGxlbmd0aCAlIDY0ICE9IDApIHtcblx0ICAgIFx0cmV0dXJuIGZhbHNlO1xuXHQgICAgfVxuXHQgICAgdmFyIHBUZW1wO1xuXHQgICAgdmFyIHBUZW1wMjtcblx0ICAgIGRvIHtcblx0ICAgICAgICBwVGVtcCA9IHJhbmRvbWZuKGJpdGNvdW50LCB0cnVlKTtcblx0ICAgICAgICBwVGVtcDIgPSBwVGVtcC5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSk7XG5cdCAgICAgICAgcFRlbXAgPSBwVGVtcC5zdWJ0cmFjdChwVGVtcDIucmVtYWluZGVyKHEpKTtcblx0ICAgIH0gd2hpbGUgKCFwVGVtcC5pc1Byb2JhYmxlUHJpbWUocHJpbWVDZW50ZXJpZSkgfHwgcFRlbXAuYml0TGVuZ3RoKCkgIT0gbCk7XG5cdCAgICByZXR1cm4gcFRlbXA7XG5cdH1cblx0XG5cdGZ1bmN0aW9uIGdlbmVyYXRlRyhwLCBxLCBiaXRsZW5ndGgsIHJhbmRvbWZuKSB7XG5cdCAgICB2YXIgYXV4ID0gcC5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSk7XG5cdCAgICB2YXIgcG93ID0gYXV4LmRpdmlkZShxKTtcblx0ICAgIHZhciBnVGVtcDtcblx0ICAgIGRvIHtcblx0ICAgICAgICBnVGVtcCA9IHJhbmRvbWZuKGJpdGxlbmd0aCk7XG5cdCAgICB9IHdoaWxlIChnVGVtcC5jb21wYXJlVG8oYXV4KSAhPSAtMSAmJiBnVGVtcC5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpICE9IDEpO1xuXHQgICAgcmV0dXJuIGdUZW1wLm1vZFBvdyhwb3csIHApO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2VuZXJhdGVLKHEsIGJpdGxlbmd0aCwgcmFuZG9tZm4pIHtcblx0ICAgIHZhciB0ZW1wSztcblx0ICAgIGRvIHtcblx0ICAgICAgICB0ZW1wSyA9IHJhbmRvbWZuKGJpdGxlbmd0aCwgZmFsc2UpO1xuXHQgICAgfSB3aGlsZSAodGVtcEsuY29tcGFyZVRvKHEpICE9IC0xICYmIHRlbXBLLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pICE9IDEpO1xuXHQgICAgcmV0dXJuIHRlbXBLO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2VuZXJhdGVSKHEscCkge1xuXHQgICAgayA9IGdlbmVyYXRlSyhxKTtcblx0ICAgIHZhciByID0gZy5tb2RQb3coaywgcCkubW9kKHEpO1xuXHQgICAgcmV0dXJuIHI7XG5cdH1cblxuXHRmdW5jdGlvbiBnZW5lcmF0ZVMoaGFzaGZuLGsscixtLHEseCkge1xuICAgICAgICB2YXIgaGFzaCA9IGhhc2hmbihtKTtcbiAgICAgICAgcyA9IChrLm1vZEludmVyc2UocSkubXVsdGlwbHkoaGFzaC5hZGQoeC5tdWx0aXBseShyKSkpKS5tb2QocSk7XG5cdCAgICByZXR1cm4gcztcblx0fSAqL1xuXHR0aGlzLnNpZ24gPSBzaWduO1xuXHR0aGlzLnZlcmlmeSA9IHZlcmlmeTtcblx0Ly8gdGhpcy5nZW5lcmF0ZSA9IGdlbmVyYXRlS2V5O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IERTQTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBPbmUtUGFzcyBTaWduYXR1cmUgUGFja2V0cyAoVGFnIDQpXG4gKiBcbiAqIFJGQzQ4ODAgNS40OlxuICogVGhlIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQgcHJlY2VkZXMgdGhlIHNpZ25lZCBkYXRhIGFuZCBjb250YWluc1xuICogZW5vdWdoIGluZm9ybWF0aW9uIHRvIGFsbG93IHRoZSByZWNlaXZlciB0byBiZWdpbiBjYWxjdWxhdGluZyBhbnlcbiAqIGhhc2hlcyBuZWVkZWQgdG8gdmVyaWZ5IHRoZSBzaWduYXR1cmUuICBJdCBhbGxvd3MgdGhlIFNpZ25hdHVyZVxuICogcGFja2V0IHRvIGJlIHBsYWNlZCBhdCB0aGUgZW5kIG9mIHRoZSBtZXNzYWdlLCBzbyB0aGF0IHRoZSBzaWduZXJcbiAqIGNhbiBjb21wdXRlIHRoZSBlbnRpcmUgc2lnbmVkIG1lc3NhZ2UgaW4gb25lIHBhc3MuXG4gKi9cblxudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcblx0dHlwZV9rZXlpZCA9IHJlcXVpcmUoJy4uL3R5cGUva2V5aWQuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfb25lX3Bhc3Nfc2lnbmF0dXJlKCkge1xuXHR0aGlzLnZlcnNpb24gPSBudWxsOyAvLyBBIG9uZS1vY3RldCB2ZXJzaW9uIG51bWJlci4gIFRoZSBjdXJyZW50IHZlcnNpb24gaXMgMy5cblx0dGhpcy50eXBlID0gbnVsbDsgXHQgLy8gQSBvbmUtb2N0ZXQgc2lnbmF0dXJlIHR5cGUuICBTaWduYXR1cmUgdHlwZXMgYXJlIGRlc2NyaWJlZCBpbiBSRkM0ODgwIFNlY3Rpb24gNS4yLjEuXG5cdHRoaXMuaGFzaEFsZ29yaXRobSA9IG51bGw7IFx0ICAgLy8gQSBvbmUtb2N0ZXQgbnVtYmVyIGRlc2NyaWJpbmcgdGhlIGhhc2ggYWxnb3JpdGhtIHVzZWQuIChTZWUgUkZDNDg4MCA5LjQpXG5cdHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gbnVsbDtcdCAgICAgLy8gQSBvbmUtb2N0ZXQgbnVtYmVyIGRlc2NyaWJpbmcgdGhlIHB1YmxpYy1rZXkgYWxnb3JpdGhtIHVzZWQuIChTZWUgUkZDNDg4MCA5LjEpXG5cdHRoaXMuc2lnbmluZ0tleUlkID0gbnVsbDsgLy8gQW4gZWlnaHQtb2N0ZXQgbnVtYmVyIGhvbGRpbmcgdGhlIEtleSBJRCBvZiB0aGUgc2lnbmluZyBrZXkuXG5cdHRoaXMuZmxhZ3MgPSBudWxsOyBcdC8vICBBIG9uZS1vY3RldCBudW1iZXIgaG9sZGluZyBhIGZsYWcgc2hvd2luZyB3aGV0aGVyIHRoZSBzaWduYXR1cmUgaXMgbmVzdGVkLiAgQSB6ZXJvIHZhbHVlIGluZGljYXRlcyB0aGF0IHRoZSBuZXh0IHBhY2tldCBpcyBhbm90aGVyIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQgdGhhdCBkZXNjcmliZXMgYW5vdGhlciBzaWduYXR1cmUgdG8gYmUgYXBwbGllZCB0byB0aGUgc2FtZSBtZXNzYWdlIGRhdGEuXG5cblx0LyoqXG5cdCAqIHBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgb25lLXBhc3Mgc2lnbmF0dXJlIHBhY2tldCAodGFnIDQpLlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gYnl0ZXMgcGF5bG9hZCBvZiBhIHRhZyA0IHBhY2tldFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIHBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgYnl0ZXMgc3RyaW5nXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIGxlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mIGJ5dGVzIGF0IHBvc2l0aW9uXG5cdCAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IG9iamVjdCByZXByZXNlbnRhdGlvblxuXHQgKi9cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0XHR2YXIgbXlwb3MgPSAwO1xuXHRcdC8vIEEgb25lLW9jdGV0IHZlcnNpb24gbnVtYmVyLiAgVGhlIGN1cnJlbnQgdmVyc2lvbiBpcyAzLlxuXHRcdHRoaXMudmVyc2lvbiA9IGJ5dGVzLmNoYXJDb2RlQXQobXlwb3MrKyk7XG5cblx0ICAgICAvLyBBIG9uZS1vY3RldCBzaWduYXR1cmUgdHlwZS4gIFNpZ25hdHVyZSB0eXBlcyBhcmUgZGVzY3JpYmVkIGluXG5cdCAgICAgLy8gICBTZWN0aW9uIDUuMi4xLlxuXHRcdHRoaXMudHlwZSA9IGVudW1zLnJlYWQoZW51bXMuc2lnbmF0dXJlLCBieXRlcy5jaGFyQ29kZUF0KG15cG9zKyspKTtcblxuXHQgICAgIC8vIEEgb25lLW9jdGV0IG51bWJlciBkZXNjcmliaW5nIHRoZSBoYXNoIGFsZ29yaXRobSB1c2VkLlxuXHRcdHRoaXMuaGFzaEFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMuaGFzaCwgYnl0ZXMuY2hhckNvZGVBdChteXBvcysrKSk7XG5cblx0ICAgICAvLyBBIG9uZS1vY3RldCBudW1iZXIgZGVzY3JpYmluZyB0aGUgcHVibGljLWtleSBhbGdvcml0aG0gdXNlZC5cblx0XHR0aGlzLnB1YmxpY0tleUFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMucHVibGljS2V5LCBieXRlcy5jaGFyQ29kZUF0KG15cG9zKyspKTtcblxuXHQgICAgIC8vIEFuIGVpZ2h0LW9jdGV0IG51bWJlciBob2xkaW5nIHRoZSBLZXkgSUQgb2YgdGhlIHNpZ25pbmcga2V5LlxuXHRcdHRoaXMuc2lnbmluZ0tleUlkID0gbmV3IHR5cGVfa2V5aWQoKTtcblx0XHR0aGlzLnNpZ25pbmdLZXlJZC5yZWFkKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXHRcdG15cG9zICs9IDg7XG5cdFx0XG5cdCAgICAgLy8gQSBvbmUtb2N0ZXQgbnVtYmVyIGhvbGRpbmcgYSBmbGFnIHNob3dpbmcgd2hldGhlciB0aGUgc2lnbmF0dXJlXG5cdCAgICAgLy8gICBpcyBuZXN0ZWQuICBBIHplcm8gdmFsdWUgaW5kaWNhdGVzIHRoYXQgdGhlIG5leHQgcGFja2V0IGlzXG5cdCAgICAgLy8gICBhbm90aGVyIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQgdGhhdCBkZXNjcmliZXMgYW5vdGhlclxuXHQgICAgIC8vICAgc2lnbmF0dXJlIHRvIGJlIGFwcGxpZWQgdG8gdGhlIHNhbWUgbWVzc2FnZSBkYXRhLlxuXHRcdHRoaXMuZmxhZ3MgPSBieXRlcy5jaGFyQ29kZUF0KG15cG9zKyspO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9XG5cblx0LyoqXG5cdCAqIGNyZWF0ZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBvbmUtcGFzcyBzaWduYXR1cmUgcGFja2V0XG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gdHlwZSBTaWduYXR1cmUgdHlwZXMgYXMgZGVzY3JpYmVkIGluIFJGQzQ4ODAgU2VjdGlvbiA1LjIuMS5cblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBoYXNoYWxnb3JpdGhtIHRoZSBoYXNoIGFsZ29yaXRobSB1c2VkIHdpdGhpbiB0aGUgc2lnbmF0dXJlXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0gcHJpdmF0ZWtleSB0aGUgcHJpdmF0ZSBrZXkgdXNlZCB0byBnZW5lcmF0ZSB0aGUgc2lnbmF0dXJlXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuZ3RoIGxlbmd0aCBvZiBkYXRhIHRvIGJlIHNpZ25lZFxuXHQgKiBAcGFyYW0ge2Jvb2xlYW59IG5lc3RlZCBib29sZWFuIHNob3dpbmcgd2hldGhlciB0aGUgc2lnbmF0dXJlIGlzIG5lc3RlZC4gXG5cdCAqICBcInRydWVcIiBpbmRpY2F0ZXMgdGhhdCB0aGUgbmV4dCBwYWNrZXQgaXMgYW5vdGhlciBPbmUtUGFzcyBTaWduYXR1cmUgcGFja2V0XG5cdCAqICAgdGhhdCBkZXNjcmliZXMgYW5vdGhlciBzaWduYXR1cmUgdG8gYmUgYXBwbGllZCB0byB0aGUgc2FtZSBtZXNzYWdlIGRhdGEuIFxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgb25lLXBhc3Mgc2lnbmF0dXJlIHBhY2tldFxuXHQgKi9cblx0dGhpcy53cml0ZSA9IGZ1bmN0aW9uKHR5cGUsIGhhc2hhbGdvcml0aG0sIHByaXZhdGVrZXksIGxlbmd0aCwgbmVzdGVkKSB7XG5cdFx0dmFyIHJlc3VsdCA9XCJcIjsgXG5cdFx0XG5cdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMyk7XG5cdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuc2lnbmF0dXJlLCB0eXBlKSk7XG5cdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuaGFzaCwgdGhpcy5oYXNoQWxnb3JpdGhtKSk7XG5cdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMucHVibGljS2V5LCBwcml2YXRla2V5LmFsZ29yaXRobSkpO1xuXHRcdHJlc3VsdCArPSBwcml2YXRla2V5LmdldEtleUlkKCk7XG5cdFx0aWYgKG5lc3RlZClcblx0XHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuXHRcdGVsc2Vcblx0XHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDEpO1xuXHRcdFxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cbn07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuLy9cbi8vIEVsR2FtYWwgaW1wbGVtZW50YXRpb25cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2pzYm4uanMnKSxcblx0dXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuZnVuY3Rpb24gRWxnYW1hbCgpIHtcblx0XG5cdGZ1bmN0aW9uIGVuY3J5cHQobSxnLHAseSkge1xuXHRcdC8vICBjaG9vc2UgayBpbiB7MiwuLi4scC0yfVxuXHRcdHZhciB0d28gPSBCaWdJbnRlZ2VyLk9ORS5hZGQoQmlnSW50ZWdlci5PTkUpO1xuXHRcdHZhciBwTWludXMyID0gcC5zdWJ0cmFjdCh0d28pO1xuXHRcdHZhciBrID0gb3BlbnBncF9jcnlwdG9fZ2V0UmFuZG9tQmlnSW50ZWdlckluUmFuZ2UodHdvLCBwTWludXMyKTtcblx0XHR2YXIgayA9IGsubW9kKHBNaW51czIpLmFkZChCaWdJbnRlZ2VyLk9ORSk7XG5cdFx0dmFyIGMgPSBuZXcgQXJyYXkoKTtcblx0XHRjWzBdID0gZy5tb2RQb3coaywgcCk7XG5cdFx0Y1sxXSA9IHkubW9kUG93KGssIHApLm11bHRpcGx5KG0pLm1vZChwKS50b01QSSgpO1xuXHRcdGNbMF0gPSBjWzBdLnRvTVBJKCk7XG5cdFx0cmV0dXJuIGM7XG5cdH1cblx0XG5cdGZ1bmN0aW9uIGRlY3J5cHQoYzEsYzIscCx4KSB7XG5cdFx0dXRpbC5wcmludF9kZWJ1ZyhcIkVsZ2FtYWwgRGVjcnlwdDpcXG5jMTpcIit1dGlsLmhleHN0cmR1bXAoYzEudG9NUEkoKSkrXCJcXG5cIitcblx0XHRcdCAgXCJjMjpcIit1dGlsLmhleHN0cmR1bXAoYzIudG9NUEkoKSkrXCJcXG5cIitcblx0XHRcdCAgXCJwOlwiK3V0aWwuaGV4c3RyZHVtcChwLnRvTVBJKCkpK1wiXFxuXCIrXG5cdFx0XHQgIFwieDpcIit1dGlsLmhleHN0cmR1bXAoeC50b01QSSgpKSk7XG5cdFx0cmV0dXJuIChjMS5tb2RQb3coeCwgcCkubW9kSW52ZXJzZShwKSkubXVsdGlwbHkoYzIpLm1vZChwKTtcblx0XHQvL3ZhciBjID0gYzEucG93KHgpLm1vZEludmVyc2UocCk7IC8vIGMwXi1hIG1vZCBwXG5cdCAgICAvL3JldHVybiBjLm11bHRpcGx5KGMyKS5tb2QocCk7XG5cdH1cblx0XG5cdC8vIHNpZ25pbmcgYW5kIHNpZ25hdHVyZSB2ZXJpZmljYXRpb24gdXNpbmcgRWxnYW1hbCBpcyBub3QgcmVxdWlyZWQgYnkgT3BlblBHUC5cblx0dGhpcy5lbmNyeXB0ID0gZW5jcnlwdDtcblx0dGhpcy5kZWNyeXB0ID0gZGVjcnlwdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBFbGdhbWFsO1xuIiwiXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0cnNhOiByZXF1aXJlKCcuL3JzYS5qcycpLFxuXHRlbGdhbWFsOiByZXF1aXJlKCcuL2VsZ2FtYWwuanMnKSxcblx0ZHNhOiByZXF1aXJlKCcuL2RzYS5qcycpXG59XG5cbiIsIi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMDMtMjAwNSAgVG9tIFd1ICh0andAY3MuU3RhbmZvcmQuRURVKSBcbiAqIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIIFxuICogXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmdcbiAqIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuICogXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4gKiB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4gKiBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG9cbiAqIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0b1xuICogdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUy1JU1wiIEFORCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBcbiAqIEVYUFJFU1MsIElNUExJRUQgT1IgT1RIRVJXSVNFLCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OLCBBTlkgXG4gKiBXQVJSQU5UWSBPRiBNRVJDSEFOVEFCSUxJVFkgT1IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBcbiAqXG4gKiBJTiBOTyBFVkVOVCBTSEFMTCBUT00gV1UgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgSU5DSURFTlRBTCxcbiAqIElORElSRUNUIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPRiBBTlkgS0lORCwgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUlxuICogUkVTVUxUSU5HIEZST00gTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBPUiBOT1QgQURWSVNFRCBPRlxuICogVEhFIFBPU1NJQklMSVRZIE9GIERBTUFHRSwgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBBUklTSU5HIE9VVFxuICogT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IgUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cbiAqXG4gKiBJbiBhZGRpdGlvbiwgdGhlIGZvbGxvd2luZyBjb25kaXRpb24gYXBwbGllczpcbiAqXG4gKiBBbGwgcmVkaXN0cmlidXRpb25zIG11c3QgcmV0YWluIGFuIGludGFjdCBjb3B5IG9mIHRoaXMgY29weXJpZ2h0IG5vdGljZVxuICogYW5kIGRpc2NsYWltZXIuXG4gKi9cblxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gQmFzaWMgSmF2YVNjcmlwdCBCTiBsaWJyYXJ5IC0gc3Vic2V0IHVzZWZ1bCBmb3IgUlNBIGVuY3J5cHRpb24uXG5cbi8vIEJpdHMgcGVyIGRpZ2l0XG52YXIgZGJpdHM7XG5cbi8vIEphdmFTY3JpcHQgZW5naW5lIGFuYWx5c2lzXG52YXIgY2FuYXJ5ID0gMHhkZWFkYmVlZmNhZmU7XG52YXIgal9sbSA9ICgoY2FuYXJ5JjB4ZmZmZmZmKT09MHhlZmNhZmUpO1xuXG4vLyAocHVibGljKSBDb25zdHJ1Y3RvclxuZnVuY3Rpb24gQmlnSW50ZWdlcihhLGIsYykge1xuICBpZihhICE9IG51bGwpXG4gICAgaWYoXCJudW1iZXJcIiA9PSB0eXBlb2YgYSkgdGhpcy5mcm9tTnVtYmVyKGEsYixjKTtcbiAgICBlbHNlIGlmKGIgPT0gbnVsbCAmJiBcInN0cmluZ1wiICE9IHR5cGVvZiBhKSB0aGlzLmZyb21TdHJpbmcoYSwyNTYpO1xuICAgIGVsc2UgdGhpcy5mcm9tU3RyaW5nKGEsYik7XG59XG5cbi8vIHJldHVybiBuZXcsIHVuc2V0IEJpZ0ludGVnZXJcbmZ1bmN0aW9uIG5iaSgpIHsgcmV0dXJuIG5ldyBCaWdJbnRlZ2VyKG51bGwpOyB9XG5cbi8vIGFtOiBDb21wdXRlIHdfaiArPSAoeCp0aGlzX2kpLCBwcm9wYWdhdGUgY2Fycmllcyxcbi8vIGMgaXMgaW5pdGlhbCBjYXJyeSwgcmV0dXJucyBmaW5hbCBjYXJyeS5cbi8vIGMgPCAzKmR2YWx1ZSwgeCA8IDIqZHZhbHVlLCB0aGlzX2kgPCBkdmFsdWVcbi8vIFdlIG5lZWQgdG8gc2VsZWN0IHRoZSBmYXN0ZXN0IG9uZSB0aGF0IHdvcmtzIGluIHRoaXMgZW52aXJvbm1lbnQuXG5cbi8vIGFtMTogdXNlIGEgc2luZ2xlIG11bHQgYW5kIGRpdmlkZSB0byBnZXQgdGhlIGhpZ2ggYml0cyxcbi8vIG1heCBkaWdpdCBiaXRzIHNob3VsZCBiZSAyNiBiZWNhdXNlXG4vLyBtYXggaW50ZXJuYWwgdmFsdWUgPSAyKmR2YWx1ZV4yLTIqZHZhbHVlICg8IDJeNTMpXG5mdW5jdGlvbiBhbTEoaSx4LHcsaixjLG4pIHtcbiAgd2hpbGUoLS1uID49IDApIHtcbiAgICB2YXIgdiA9IHgqdGhpc1tpKytdK3dbal0rYztcbiAgICBjID0gTWF0aC5mbG9vcih2LzB4NDAwMDAwMCk7XG4gICAgd1tqKytdID0gdiYweDNmZmZmZmY7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG4vLyBhbTIgYXZvaWRzIGEgYmlnIG11bHQtYW5kLWV4dHJhY3QgY29tcGxldGVseS5cbi8vIE1heCBkaWdpdCBiaXRzIHNob3VsZCBiZSA8PSAzMCBiZWNhdXNlIHdlIGRvIGJpdHdpc2Ugb3BzXG4vLyBvbiB2YWx1ZXMgdXAgdG8gMipoZHZhbHVlXjItaGR2YWx1ZS0xICg8IDJeMzEpXG5mdW5jdGlvbiBhbTIoaSx4LHcsaixjLG4pIHtcbiAgdmFyIHhsID0geCYweDdmZmYsIHhoID0geD4+MTU7XG4gIHdoaWxlKC0tbiA+PSAwKSB7XG4gICAgdmFyIGwgPSB0aGlzW2ldJjB4N2ZmZjtcbiAgICB2YXIgaCA9IHRoaXNbaSsrXT4+MTU7XG4gICAgdmFyIG0gPSB4aCpsK2gqeGw7XG4gICAgbCA9IHhsKmwrKChtJjB4N2ZmZik8PDE1KSt3W2pdKyhjJjB4M2ZmZmZmZmYpO1xuICAgIGMgPSAobD4+PjMwKSsobT4+PjE1KSt4aCpoKyhjPj4+MzApO1xuICAgIHdbaisrXSA9IGwmMHgzZmZmZmZmZjtcbiAgfVxuICByZXR1cm4gYztcbn1cbi8vIEFsdGVybmF0ZWx5LCBzZXQgbWF4IGRpZ2l0IGJpdHMgdG8gMjggc2luY2Ugc29tZVxuLy8gYnJvd3NlcnMgc2xvdyBkb3duIHdoZW4gZGVhbGluZyB3aXRoIDMyLWJpdCBudW1iZXJzLlxuZnVuY3Rpb24gYW0zKGkseCx3LGosYyxuKSB7XG4gIHZhciB4bCA9IHgmMHgzZmZmLCB4aCA9IHg+PjE0O1xuICB3aGlsZSgtLW4gPj0gMCkge1xuICAgIHZhciBsID0gdGhpc1tpXSYweDNmZmY7XG4gICAgdmFyIGggPSB0aGlzW2krK10+PjE0O1xuICAgIHZhciBtID0geGgqbCtoKnhsO1xuICAgIGwgPSB4bCpsKygobSYweDNmZmYpPDwxNCkrd1tqXStjO1xuICAgIGMgPSAobD4+MjgpKyhtPj4xNCkreGgqaDtcbiAgICB3W2orK10gPSBsJjB4ZmZmZmZmZjtcbiAgfVxuICByZXR1cm4gYztcbn1cbi8qaWYoal9sbSAmJiAobmF2aWdhdG9yICE9IHVuZGVmaW5lZCAmJiBcblx0bmF2aWdhdG9yLmFwcE5hbWUgPT0gXCJNaWNyb3NvZnQgSW50ZXJuZXQgRXhwbG9yZXJcIikpIHtcbiAgQmlnSW50ZWdlci5wcm90b3R5cGUuYW0gPSBhbTI7XG4gIGRiaXRzID0gMzA7XG59XG5lbHNlIGlmKGpfbG0gJiYgKG5hdmlnYXRvciAhPSB1bmRlZmluZWQgJiYgbmF2aWdhdG9yLmFwcE5hbWUgIT0gXCJOZXRzY2FwZVwiKSkgeyovXG4gIEJpZ0ludGVnZXIucHJvdG90eXBlLmFtID0gYW0xO1xuICBkYml0cyA9IDI2O1xuLyp9XG5lbHNlIHsgLy8gTW96aWxsYS9OZXRzY2FwZSBzZWVtcyB0byBwcmVmZXIgYW0zXG4gIEJpZ0ludGVnZXIucHJvdG90eXBlLmFtID0gYW0zO1xuICBkYml0cyA9IDI4O1xufSovXG5cbkJpZ0ludGVnZXIucHJvdG90eXBlLkRCID0gZGJpdHM7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5ETSA9ICgoMTw8ZGJpdHMpLTEpO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuRFYgPSAoMTw8ZGJpdHMpO1xuXG52YXIgQklfRlAgPSA1MjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLkZWID0gTWF0aC5wb3coMixCSV9GUCk7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5GMSA9IEJJX0ZQLWRiaXRzO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuRjIgPSAyKmRiaXRzLUJJX0ZQO1xuXG4vLyBEaWdpdCBjb252ZXJzaW9uc1xudmFyIEJJX1JNID0gXCIwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpcIjtcbnZhciBCSV9SQyA9IG5ldyBBcnJheSgpO1xudmFyIHJyLHZ2O1xucnIgPSBcIjBcIi5jaGFyQ29kZUF0KDApO1xuZm9yKHZ2ID0gMDsgdnYgPD0gOTsgKyt2dikgQklfUkNbcnIrK10gPSB2djtcbnJyID0gXCJhXCIuY2hhckNvZGVBdCgwKTtcbmZvcih2diA9IDEwOyB2diA8IDM2OyArK3Z2KSBCSV9SQ1tycisrXSA9IHZ2O1xucnIgPSBcIkFcIi5jaGFyQ29kZUF0KDApO1xuZm9yKHZ2ID0gMTA7IHZ2IDwgMzY7ICsrdnYpIEJJX1JDW3JyKytdID0gdnY7XG5cbmZ1bmN0aW9uIGludDJjaGFyKG4pIHsgcmV0dXJuIEJJX1JNLmNoYXJBdChuKTsgfVxuZnVuY3Rpb24gaW50QXQocyxpKSB7XG4gIHZhciBjID0gQklfUkNbcy5jaGFyQ29kZUF0KGkpXTtcbiAgcmV0dXJuIChjPT1udWxsKT8tMTpjO1xufVxuXG4vLyAocHJvdGVjdGVkKSBjb3B5IHRoaXMgdG8gclxuZnVuY3Rpb24gYm5wQ29weVRvKHIpIHtcbiAgZm9yKHZhciBpID0gdGhpcy50LTE7IGkgPj0gMDsgLS1pKSByW2ldID0gdGhpc1tpXTtcbiAgci50ID0gdGhpcy50O1xuICByLnMgPSB0aGlzLnM7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHNldCBmcm9tIGludGVnZXIgdmFsdWUgeCwgLURWIDw9IHggPCBEVlxuZnVuY3Rpb24gYm5wRnJvbUludCh4KSB7XG4gIHRoaXMudCA9IDE7XG4gIHRoaXMucyA9ICh4PDApPy0xOjA7XG4gIGlmKHggPiAwKSB0aGlzWzBdID0geDtcbiAgZWxzZSBpZih4IDwgLTEpIHRoaXNbMF0gPSB4K0RWO1xuICBlbHNlIHRoaXMudCA9IDA7XG59XG5cbi8vIHJldHVybiBiaWdpbnQgaW5pdGlhbGl6ZWQgdG8gdmFsdWVcbmZ1bmN0aW9uIG5idihpKSB7IHZhciByID0gbmJpKCk7IHIuZnJvbUludChpKTsgcmV0dXJuIHI7IH1cblxuLy8gKHByb3RlY3RlZCkgc2V0IGZyb20gc3RyaW5nIGFuZCByYWRpeFxuZnVuY3Rpb24gYm5wRnJvbVN0cmluZyhzLGIpIHtcbiAgdmFyIGs7XG4gIGlmKGIgPT0gMTYpIGsgPSA0O1xuICBlbHNlIGlmKGIgPT0gOCkgayA9IDM7XG4gIGVsc2UgaWYoYiA9PSAyNTYpIGsgPSA4OyAvLyBieXRlIGFycmF5XG4gIGVsc2UgaWYoYiA9PSAyKSBrID0gMTtcbiAgZWxzZSBpZihiID09IDMyKSBrID0gNTtcbiAgZWxzZSBpZihiID09IDQpIGsgPSAyO1xuICBlbHNlIHsgdGhpcy5mcm9tUmFkaXgocyxiKTsgcmV0dXJuOyB9XG4gIHRoaXMudCA9IDA7XG4gIHRoaXMucyA9IDA7XG4gIHZhciBpID0gcy5sZW5ndGgsIG1pID0gZmFsc2UsIHNoID0gMDtcbiAgd2hpbGUoLS1pID49IDApIHtcbiAgICB2YXIgeCA9IChrPT04KT9zW2ldJjB4ZmY6aW50QXQocyxpKTtcbiAgICBpZih4IDwgMCkge1xuICAgICAgaWYocy5jaGFyQXQoaSkgPT0gXCItXCIpIG1pID0gdHJ1ZTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBtaSA9IGZhbHNlO1xuICAgIGlmKHNoID09IDApXG4gICAgICB0aGlzW3RoaXMudCsrXSA9IHg7XG4gICAgZWxzZSBpZihzaCtrID4gdGhpcy5EQikge1xuICAgICAgdGhpc1t0aGlzLnQtMV0gfD0gKHgmKCgxPDwodGhpcy5EQi1zaCkpLTEpKTw8c2g7XG4gICAgICB0aGlzW3RoaXMudCsrXSA9ICh4Pj4odGhpcy5EQi1zaCkpO1xuICAgIH1cbiAgICBlbHNlXG4gICAgICB0aGlzW3RoaXMudC0xXSB8PSB4PDxzaDtcbiAgICBzaCArPSBrO1xuICAgIGlmKHNoID49IHRoaXMuREIpIHNoIC09IHRoaXMuREI7XG4gIH1cbiAgaWYoayA9PSA4ICYmIChzWzBdJjB4ODApICE9IDApIHtcbiAgICB0aGlzLnMgPSAtMTtcbiAgICBpZihzaCA+IDApIHRoaXNbdGhpcy50LTFdIHw9ICgoMTw8KHRoaXMuREItc2gpKS0xKTw8c2g7XG4gIH1cbiAgdGhpcy5jbGFtcCgpO1xuICBpZihtaSkgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHRoaXMsdGhpcyk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNsYW1wIG9mZiBleGNlc3MgaGlnaCB3b3Jkc1xuZnVuY3Rpb24gYm5wQ2xhbXAoKSB7XG4gIHZhciBjID0gdGhpcy5zJnRoaXMuRE07XG4gIHdoaWxlKHRoaXMudCA+IDAgJiYgdGhpc1t0aGlzLnQtMV0gPT0gYykgLS10aGlzLnQ7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiBzdHJpbmcgcmVwcmVzZW50YXRpb24gaW4gZ2l2ZW4gcmFkaXhcbmZ1bmN0aW9uIGJuVG9TdHJpbmcoYikge1xuICBpZih0aGlzLnMgPCAwKSByZXR1cm4gXCItXCIrdGhpcy5uZWdhdGUoKS50b1N0cmluZyhiKTtcbiAgdmFyIGs7XG4gIGlmKGIgPT0gMTYpIGsgPSA0O1xuICBlbHNlIGlmKGIgPT0gOCkgayA9IDM7XG4gIGVsc2UgaWYoYiA9PSAyKSBrID0gMTtcbiAgZWxzZSBpZihiID09IDMyKSBrID0gNTtcbiAgZWxzZSBpZihiID09IDQpIGsgPSAyO1xuICBlbHNlIHJldHVybiB0aGlzLnRvUmFkaXgoYik7XG4gIHZhciBrbSA9ICgxPDxrKS0xLCBkLCBtID0gZmFsc2UsIHIgPSBcIlwiLCBpID0gdGhpcy50O1xuICB2YXIgcCA9IHRoaXMuREItKGkqdGhpcy5EQiklaztcbiAgaWYoaS0tID4gMCkge1xuICAgIGlmKHAgPCB0aGlzLkRCICYmIChkID0gdGhpc1tpXT4+cCkgPiAwKSB7IG0gPSB0cnVlOyByID0gaW50MmNoYXIoZCk7IH1cbiAgICB3aGlsZShpID49IDApIHtcbiAgICAgIGlmKHAgPCBrKSB7XG4gICAgICAgIGQgPSAodGhpc1tpXSYoKDE8PHApLTEpKTw8KGstcCk7XG4gICAgICAgIGQgfD0gdGhpc1stLWldPj4ocCs9dGhpcy5EQi1rKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICBkID0gKHRoaXNbaV0+PihwLT1rKSkma207XG4gICAgICAgIGlmKHAgPD0gMCkgeyBwICs9IHRoaXMuREI7IC0taTsgfVxuICAgICAgfVxuICAgICAgaWYoZCA+IDApIG0gPSB0cnVlO1xuICAgICAgaWYobSkgciArPSBpbnQyY2hhcihkKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG0/cjpcIjBcIjtcbn1cblxuLy8gKHB1YmxpYykgLXRoaXNcbmZ1bmN0aW9uIGJuTmVnYXRlKCkgeyB2YXIgciA9IG5iaSgpOyBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8odGhpcyxyKTsgcmV0dXJuIHI7IH1cblxuLy8gKHB1YmxpYykgfHRoaXN8XG5mdW5jdGlvbiBibkFicygpIHsgcmV0dXJuICh0aGlzLnM8MCk/dGhpcy5uZWdhdGUoKTp0aGlzOyB9XG5cbi8vIChwdWJsaWMpIHJldHVybiArIGlmIHRoaXMgPiBhLCAtIGlmIHRoaXMgPCBhLCAwIGlmIGVxdWFsXG5mdW5jdGlvbiBibkNvbXBhcmVUbyhhKSB7XG4gIHZhciByID0gdGhpcy5zLWEucztcbiAgaWYociAhPSAwKSByZXR1cm4gcjtcbiAgdmFyIGkgPSB0aGlzLnQ7XG4gIHIgPSBpLWEudDtcbiAgaWYociAhPSAwKSByZXR1cm4gcjtcbiAgd2hpbGUoLS1pID49IDApIGlmKChyPXRoaXNbaV0tYVtpXSkgIT0gMCkgcmV0dXJuIHI7XG4gIHJldHVybiAwO1xufVxuXG4vLyByZXR1cm5zIGJpdCBsZW5ndGggb2YgdGhlIGludGVnZXIgeFxuZnVuY3Rpb24gbmJpdHMoeCkge1xuICB2YXIgciA9IDEsIHQ7XG4gIGlmKCh0PXg+Pj4xNikgIT0gMCkgeyB4ID0gdDsgciArPSAxNjsgfVxuICBpZigodD14Pj44KSAhPSAwKSB7IHggPSB0OyByICs9IDg7IH1cbiAgaWYoKHQ9eD4+NCkgIT0gMCkgeyB4ID0gdDsgciArPSA0OyB9XG4gIGlmKCh0PXg+PjIpICE9IDApIHsgeCA9IHQ7IHIgKz0gMjsgfVxuICBpZigodD14Pj4xKSAhPSAwKSB7IHggPSB0OyByICs9IDE7IH1cbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiB0aGUgbnVtYmVyIG9mIGJpdHMgaW4gXCJ0aGlzXCJcbmZ1bmN0aW9uIGJuQml0TGVuZ3RoKCkge1xuICBpZih0aGlzLnQgPD0gMCkgcmV0dXJuIDA7XG4gIHJldHVybiB0aGlzLkRCKih0aGlzLnQtMSkrbmJpdHModGhpc1t0aGlzLnQtMV1eKHRoaXMucyZ0aGlzLkRNKSk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIDw8IG4qREJcbmZ1bmN0aW9uIGJucERMU2hpZnRUbyhuLHIpIHtcbiAgdmFyIGk7XG4gIGZvcihpID0gdGhpcy50LTE7IGkgPj0gMDsgLS1pKSByW2krbl0gPSB0aGlzW2ldO1xuICBmb3IoaSA9IG4tMTsgaSA+PSAwOyAtLWkpIHJbaV0gPSAwO1xuICByLnQgPSB0aGlzLnQrbjtcbiAgci5zID0gdGhpcy5zO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA+PiBuKkRCXG5mdW5jdGlvbiBibnBEUlNoaWZ0VG8obixyKSB7XG4gIGZvcih2YXIgaSA9IG47IGkgPCB0aGlzLnQ7ICsraSkgcltpLW5dID0gdGhpc1tpXTtcbiAgci50ID0gTWF0aC5tYXgodGhpcy50LW4sMCk7XG4gIHIucyA9IHRoaXMucztcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXMgPDwgblxuZnVuY3Rpb24gYm5wTFNoaWZ0VG8obixyKSB7XG4gIHZhciBicyA9IG4ldGhpcy5EQjtcbiAgdmFyIGNicyA9IHRoaXMuREItYnM7XG4gIHZhciBibSA9ICgxPDxjYnMpLTE7XG4gIHZhciBkcyA9IE1hdGguZmxvb3Iobi90aGlzLkRCKSwgYyA9ICh0aGlzLnM8PGJzKSZ0aGlzLkRNLCBpO1xuICBmb3IoaSA9IHRoaXMudC0xOyBpID49IDA7IC0taSkge1xuICAgIHJbaStkcysxXSA9ICh0aGlzW2ldPj5jYnMpfGM7XG4gICAgYyA9ICh0aGlzW2ldJmJtKTw8YnM7XG4gIH1cbiAgZm9yKGkgPSBkcy0xOyBpID49IDA7IC0taSkgcltpXSA9IDA7XG4gIHJbZHNdID0gYztcbiAgci50ID0gdGhpcy50K2RzKzE7XG4gIHIucyA9IHRoaXMucztcbiAgci5jbGFtcCgpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA+PiBuXG5mdW5jdGlvbiBibnBSU2hpZnRUbyhuLHIpIHtcbiAgci5zID0gdGhpcy5zO1xuICB2YXIgZHMgPSBNYXRoLmZsb29yKG4vdGhpcy5EQik7XG4gIGlmKGRzID49IHRoaXMudCkgeyByLnQgPSAwOyByZXR1cm47IH1cbiAgdmFyIGJzID0gbiV0aGlzLkRCO1xuICB2YXIgY2JzID0gdGhpcy5EQi1icztcbiAgdmFyIGJtID0gKDE8PGJzKS0xO1xuICByWzBdID0gdGhpc1tkc10+PmJzO1xuICBmb3IodmFyIGkgPSBkcysxOyBpIDwgdGhpcy50OyArK2kpIHtcbiAgICByW2ktZHMtMV0gfD0gKHRoaXNbaV0mYm0pPDxjYnM7XG4gICAgcltpLWRzXSA9IHRoaXNbaV0+PmJzO1xuICB9XG4gIGlmKGJzID4gMCkgclt0aGlzLnQtZHMtMV0gfD0gKHRoaXMucyZibSk8PGNicztcbiAgci50ID0gdGhpcy50LWRzO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIC0gYVxuZnVuY3Rpb24gYm5wU3ViVG8oYSxyKSB7XG4gIHZhciBpID0gMCwgYyA9IDAsIG0gPSBNYXRoLm1pbihhLnQsdGhpcy50KTtcbiAgd2hpbGUoaSA8IG0pIHtcbiAgICBjICs9IHRoaXNbaV0tYVtpXTtcbiAgICByW2krK10gPSBjJnRoaXMuRE07XG4gICAgYyA+Pj0gdGhpcy5EQjtcbiAgfVxuICBpZihhLnQgPCB0aGlzLnQpIHtcbiAgICBjIC09IGEucztcbiAgICB3aGlsZShpIDwgdGhpcy50KSB7XG4gICAgICBjICs9IHRoaXNbaV07XG4gICAgICByW2krK10gPSBjJnRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjICs9IHRoaXMucztcbiAgfVxuICBlbHNlIHtcbiAgICBjICs9IHRoaXMucztcbiAgICB3aGlsZShpIDwgYS50KSB7XG4gICAgICBjIC09IGFbaV07XG4gICAgICByW2krK10gPSBjJnRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjIC09IGEucztcbiAgfVxuICByLnMgPSAoYzwwKT8tMTowO1xuICBpZihjIDwgLTEpIHJbaSsrXSA9IHRoaXMuRFYrYztcbiAgZWxzZSBpZihjID4gMCkgcltpKytdID0gYztcbiAgci50ID0gaTtcbiAgci5jbGFtcCgpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyAqIGEsIHIgIT0gdGhpcyxhIChIQUMgMTQuMTIpXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5mdW5jdGlvbiBibnBNdWx0aXBseVRvKGEscikge1xuICB2YXIgeCA9IHRoaXMuYWJzKCksIHkgPSBhLmFicygpO1xuICB2YXIgaSA9IHgudDtcbiAgci50ID0gaSt5LnQ7XG4gIHdoaWxlKC0taSA+PSAwKSByW2ldID0gMDtcbiAgZm9yKGkgPSAwOyBpIDwgeS50OyArK2kpIHJbaSt4LnRdID0geC5hbSgwLHlbaV0scixpLDAseC50KTtcbiAgci5zID0gMDtcbiAgci5jbGFtcCgpO1xuICBpZih0aGlzLnMgIT0gYS5zKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8ocixyKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXNeMiwgciAhPSB0aGlzIChIQUMgMTQuMTYpXG5mdW5jdGlvbiBibnBTcXVhcmVUbyhyKSB7XG4gIHZhciB4ID0gdGhpcy5hYnMoKTtcbiAgdmFyIGkgPSByLnQgPSAyKngudDtcbiAgd2hpbGUoLS1pID49IDApIHJbaV0gPSAwO1xuICBmb3IoaSA9IDA7IGkgPCB4LnQtMTsgKytpKSB7XG4gICAgdmFyIGMgPSB4LmFtKGkseFtpXSxyLDIqaSwwLDEpO1xuICAgIGlmKChyW2kreC50XSs9eC5hbShpKzEsMip4W2ldLHIsMippKzEsYyx4LnQtaS0xKSkgPj0geC5EVikge1xuICAgICAgcltpK3gudF0gLT0geC5EVjtcbiAgICAgIHJbaSt4LnQrMV0gPSAxO1xuICAgIH1cbiAgfVxuICBpZihyLnQgPiAwKSByW3IudC0xXSArPSB4LmFtKGkseFtpXSxyLDIqaSwwLDEpO1xuICByLnMgPSAwO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGRpdmlkZSB0aGlzIGJ5IG0sIHF1b3RpZW50IGFuZCByZW1haW5kZXIgdG8gcSwgciAoSEFDIDE0LjIwKVxuLy8gciAhPSBxLCB0aGlzICE9IG0uICBxIG9yIHIgbWF5IGJlIG51bGwuXG5mdW5jdGlvbiBibnBEaXZSZW1UbyhtLHEscikge1xuICB2YXIgcG0gPSBtLmFicygpO1xuICBpZihwbS50IDw9IDApIHJldHVybjtcbiAgdmFyIHB0ID0gdGhpcy5hYnMoKTtcbiAgaWYocHQudCA8IHBtLnQpIHtcbiAgICBpZihxICE9IG51bGwpIHEuZnJvbUludCgwKTtcbiAgICBpZihyICE9IG51bGwpIHRoaXMuY29weVRvKHIpO1xuICAgIHJldHVybjtcbiAgfVxuICBpZihyID09IG51bGwpIHIgPSBuYmkoKTtcbiAgdmFyIHkgPSBuYmkoKSwgdHMgPSB0aGlzLnMsIG1zID0gbS5zO1xuICB2YXIgbnNoID0gdGhpcy5EQi1uYml0cyhwbVtwbS50LTFdKTtcdC8vIG5vcm1hbGl6ZSBtb2R1bHVzXG4gIGlmKG5zaCA+IDApIHsgcG0ubFNoaWZ0VG8obnNoLHkpOyBwdC5sU2hpZnRUbyhuc2gscik7IH1cbiAgZWxzZSB7IHBtLmNvcHlUbyh5KTsgcHQuY29weVRvKHIpOyB9XG4gIHZhciB5cyA9IHkudDtcbiAgdmFyIHkwID0geVt5cy0xXTtcbiAgaWYoeTAgPT0gMCkgcmV0dXJuO1xuICB2YXIgeXQgPSB5MCooMTw8dGhpcy5GMSkrKCh5cz4xKT95W3lzLTJdPj50aGlzLkYyOjApO1xuICB2YXIgZDEgPSB0aGlzLkZWL3l0LCBkMiA9ICgxPDx0aGlzLkYxKS95dCwgZSA9IDE8PHRoaXMuRjI7XG4gIHZhciBpID0gci50LCBqID0gaS15cywgdCA9IChxPT1udWxsKT9uYmkoKTpxO1xuICB5LmRsU2hpZnRUbyhqLHQpO1xuICBpZihyLmNvbXBhcmVUbyh0KSA+PSAwKSB7XG4gICAgcltyLnQrK10gPSAxO1xuICAgIHIuc3ViVG8odCxyKTtcbiAgfVxuICBCaWdJbnRlZ2VyLk9ORS5kbFNoaWZ0VG8oeXMsdCk7XG4gIHQuc3ViVG8oeSx5KTtcdC8vIFwibmVnYXRpdmVcIiB5IHNvIHdlIGNhbiByZXBsYWNlIHN1YiB3aXRoIGFtIGxhdGVyXG4gIHdoaWxlKHkudCA8IHlzKSB5W3kudCsrXSA9IDA7XG4gIHdoaWxlKC0taiA+PSAwKSB7XG4gICAgLy8gRXN0aW1hdGUgcXVvdGllbnQgZGlnaXRcbiAgICB2YXIgcWQgPSAoclstLWldPT15MCk/dGhpcy5ETTpNYXRoLmZsb29yKHJbaV0qZDErKHJbaS0xXStlKSpkMik7XG4gICAgaWYoKHJbaV0rPXkuYW0oMCxxZCxyLGosMCx5cykpIDwgcWQpIHtcdC8vIFRyeSBpdCBvdXRcbiAgICAgIHkuZGxTaGlmdFRvKGosdCk7XG4gICAgICByLnN1YlRvKHQscik7XG4gICAgICB3aGlsZShyW2ldIDwgLS1xZCkgci5zdWJUbyh0LHIpO1xuICAgIH1cbiAgfVxuICBpZihxICE9IG51bGwpIHtcbiAgICByLmRyU2hpZnRUbyh5cyxxKTtcbiAgICBpZih0cyAhPSBtcykgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHEscSk7XG4gIH1cbiAgci50ID0geXM7XG4gIHIuY2xhbXAoKTtcbiAgaWYobnNoID4gMCkgci5yU2hpZnRUbyhuc2gscik7XHQvLyBEZW5vcm1hbGl6ZSByZW1haW5kZXJcbiAgaWYodHMgPCAwKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8ocixyKTtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyBtb2QgYVxuZnVuY3Rpb24gYm5Nb2QoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmFicygpLmRpdlJlbVRvKGEsbnVsbCxyKTtcbiAgaWYodGhpcy5zIDwgMCAmJiByLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pID4gMCkgYS5zdWJUbyhyLHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gTW9kdWxhciByZWR1Y3Rpb24gdXNpbmcgXCJjbGFzc2ljXCIgYWxnb3JpdGhtXG5mdW5jdGlvbiBDbGFzc2ljKG0pIHsgdGhpcy5tID0gbTsgfVxuZnVuY3Rpb24gY0NvbnZlcnQoeCkge1xuICBpZih4LnMgPCAwIHx8IHguY29tcGFyZVRvKHRoaXMubSkgPj0gMCkgcmV0dXJuIHgubW9kKHRoaXMubSk7XG4gIGVsc2UgcmV0dXJuIHg7XG59XG5mdW5jdGlvbiBjUmV2ZXJ0KHgpIHsgcmV0dXJuIHg7IH1cbmZ1bmN0aW9uIGNSZWR1Y2UoeCkgeyB4LmRpdlJlbVRvKHRoaXMubSxudWxsLHgpOyB9XG5mdW5jdGlvbiBjTXVsVG8oeCx5LHIpIHsgeC5tdWx0aXBseVRvKHkscik7IHRoaXMucmVkdWNlKHIpOyB9XG5mdW5jdGlvbiBjU3FyVG8oeCxyKSB7IHguc3F1YXJlVG8ocik7IHRoaXMucmVkdWNlKHIpOyB9XG5cbkNsYXNzaWMucHJvdG90eXBlLmNvbnZlcnQgPSBjQ29udmVydDtcbkNsYXNzaWMucHJvdG90eXBlLnJldmVydCA9IGNSZXZlcnQ7XG5DbGFzc2ljLnByb3RvdHlwZS5yZWR1Y2UgPSBjUmVkdWNlO1xuQ2xhc3NpYy5wcm90b3R5cGUubXVsVG8gPSBjTXVsVG87XG5DbGFzc2ljLnByb3RvdHlwZS5zcXJUbyA9IGNTcXJUbztcblxuLy8gKHByb3RlY3RlZCkgcmV0dXJuIFwiLTEvdGhpcyAlIDJeREJcIjsgdXNlZnVsIGZvciBNb250LiByZWR1Y3Rpb25cbi8vIGp1c3RpZmljYXRpb246XG4vLyAgICAgICAgIHh5ID09IDEgKG1vZCBtKVxuLy8gICAgICAgICB4eSA9ICAxK2ttXG4vLyAgIHh5KDIteHkpID0gKDEra20pKDEta20pXG4vLyB4W3koMi14eSldID0gMS1rXjJtXjJcbi8vIHhbeSgyLXh5KV0gPT0gMSAobW9kIG1eMilcbi8vIGlmIHkgaXMgMS94IG1vZCBtLCB0aGVuIHkoMi14eSkgaXMgMS94IG1vZCBtXjJcbi8vIHNob3VsZCByZWR1Y2UgeCBhbmQgeSgyLXh5KSBieSBtXjIgYXQgZWFjaCBzdGVwIHRvIGtlZXAgc2l6ZSBib3VuZGVkLlxuLy8gSlMgbXVsdGlwbHkgXCJvdmVyZmxvd3NcIiBkaWZmZXJlbnRseSBmcm9tIEMvQysrLCBzbyBjYXJlIGlzIG5lZWRlZCBoZXJlLlxuZnVuY3Rpb24gYm5wSW52RGlnaXQoKSB7XG4gIGlmKHRoaXMudCA8IDEpIHJldHVybiAwO1xuICB2YXIgeCA9IHRoaXNbMF07XG4gIGlmKCh4JjEpID09IDApIHJldHVybiAwO1xuICB2YXIgeSA9IHgmMztcdFx0Ly8geSA9PSAxL3ggbW9kIDJeMlxuICB5ID0gKHkqKDItKHgmMHhmKSp5KSkmMHhmO1x0Ly8geSA9PSAxL3ggbW9kIDJeNFxuICB5ID0gKHkqKDItKHgmMHhmZikqeSkpJjB4ZmY7XHQvLyB5ID09IDEveCBtb2QgMl44XG4gIHkgPSAoeSooMi0oKCh4JjB4ZmZmZikqeSkmMHhmZmZmKSkpJjB4ZmZmZjtcdC8vIHkgPT0gMS94IG1vZCAyXjE2XG4gIC8vIGxhc3Qgc3RlcCAtIGNhbGN1bGF0ZSBpbnZlcnNlIG1vZCBEViBkaXJlY3RseTtcbiAgLy8gYXNzdW1lcyAxNiA8IERCIDw9IDMyIGFuZCBhc3N1bWVzIGFiaWxpdHkgdG8gaGFuZGxlIDQ4LWJpdCBpbnRzXG4gIHkgPSAoeSooMi14KnkldGhpcy5EVikpJXRoaXMuRFY7XHRcdC8vIHkgPT0gMS94IG1vZCAyXmRiaXRzXG4gIC8vIHdlIHJlYWxseSB3YW50IHRoZSBuZWdhdGl2ZSBpbnZlcnNlLCBhbmQgLURWIDwgeSA8IERWXG4gIHJldHVybiAoeT4wKT90aGlzLkRWLXk6LXk7XG59XG5cbi8vIE1vbnRnb21lcnkgcmVkdWN0aW9uXG5mdW5jdGlvbiBNb250Z29tZXJ5KG0pIHtcbiAgdGhpcy5tID0gbTtcbiAgdGhpcy5tcCA9IG0uaW52RGlnaXQoKTtcbiAgdGhpcy5tcGwgPSB0aGlzLm1wJjB4N2ZmZjtcbiAgdGhpcy5tcGggPSB0aGlzLm1wPj4xNTtcbiAgdGhpcy51bSA9ICgxPDwobS5EQi0xNSkpLTE7XG4gIHRoaXMubXQyID0gMiptLnQ7XG59XG5cbi8vIHhSIG1vZCBtXG5mdW5jdGlvbiBtb250Q29udmVydCh4KSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHguYWJzKCkuZGxTaGlmdFRvKHRoaXMubS50LHIpO1xuICByLmRpdlJlbVRvKHRoaXMubSxudWxsLHIpO1xuICBpZih4LnMgPCAwICYmIHIuY29tcGFyZVRvKEJpZ0ludGVnZXIuWkVSTykgPiAwKSB0aGlzLm0uc3ViVG8ocixyKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIHgvUiBtb2QgbVxuZnVuY3Rpb24gbW9udFJldmVydCh4KSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHguY29weVRvKHIpO1xuICB0aGlzLnJlZHVjZShyKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIHggPSB4L1IgbW9kIG0gKEhBQyAxNC4zMilcbmZ1bmN0aW9uIG1vbnRSZWR1Y2UoeCkge1xuICB3aGlsZSh4LnQgPD0gdGhpcy5tdDIpXHQvLyBwYWQgeCBzbyBhbSBoYXMgZW5vdWdoIHJvb20gbGF0ZXJcbiAgICB4W3gudCsrXSA9IDA7XG4gIGZvcih2YXIgaSA9IDA7IGkgPCB0aGlzLm0udDsgKytpKSB7XG4gICAgLy8gZmFzdGVyIHdheSBvZiBjYWxjdWxhdGluZyB1MCA9IHhbaV0qbXAgbW9kIERWXG4gICAgdmFyIGogPSB4W2ldJjB4N2ZmZjtcbiAgICB2YXIgdTAgPSAoaip0aGlzLm1wbCsoKChqKnRoaXMubXBoKyh4W2ldPj4xNSkqdGhpcy5tcGwpJnRoaXMudW0pPDwxNSkpJnguRE07XG4gICAgLy8gdXNlIGFtIHRvIGNvbWJpbmUgdGhlIG11bHRpcGx5LXNoaWZ0LWFkZCBpbnRvIG9uZSBjYWxsXG4gICAgaiA9IGkrdGhpcy5tLnQ7XG4gICAgeFtqXSArPSB0aGlzLm0uYW0oMCx1MCx4LGksMCx0aGlzLm0udCk7XG4gICAgLy8gcHJvcGFnYXRlIGNhcnJ5XG4gICAgd2hpbGUoeFtqXSA+PSB4LkRWKSB7IHhbal0gLT0geC5EVjsgeFsrK2pdKys7IH1cbiAgfVxuICB4LmNsYW1wKCk7XG4gIHguZHJTaGlmdFRvKHRoaXMubS50LHgpO1xuICBpZih4LmNvbXBhcmVUbyh0aGlzLm0pID49IDApIHguc3ViVG8odGhpcy5tLHgpO1xufVxuXG4vLyByID0gXCJ4XjIvUiBtb2QgbVwiOyB4ICE9IHJcbmZ1bmN0aW9uIG1vbnRTcXJUbyh4LHIpIHsgeC5zcXVhcmVUbyhyKTsgdGhpcy5yZWR1Y2Uocik7IH1cblxuLy8gciA9IFwieHkvUiBtb2QgbVwiOyB4LHkgIT0gclxuZnVuY3Rpb24gbW9udE11bFRvKHgseSxyKSB7IHgubXVsdGlwbHlUbyh5LHIpOyB0aGlzLnJlZHVjZShyKTsgfVxuXG5Nb250Z29tZXJ5LnByb3RvdHlwZS5jb252ZXJ0ID0gbW9udENvbnZlcnQ7XG5Nb250Z29tZXJ5LnByb3RvdHlwZS5yZXZlcnQgPSBtb250UmV2ZXJ0O1xuTW9udGdvbWVyeS5wcm90b3R5cGUucmVkdWNlID0gbW9udFJlZHVjZTtcbk1vbnRnb21lcnkucHJvdG90eXBlLm11bFRvID0gbW9udE11bFRvO1xuTW9udGdvbWVyeS5wcm90b3R5cGUuc3FyVG8gPSBtb250U3FyVG87XG5cbi8vIChwcm90ZWN0ZWQpIHRydWUgaWZmIHRoaXMgaXMgZXZlblxuZnVuY3Rpb24gYm5wSXNFdmVuKCkgeyByZXR1cm4gKCh0aGlzLnQ+MCk/KHRoaXNbMF0mMSk6dGhpcy5zKSA9PSAwOyB9XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXNeZSwgZSA8IDJeMzIsIGRvaW5nIHNxciBhbmQgbXVsIHdpdGggXCJyXCIgKEhBQyAxNC43OSlcbmZ1bmN0aW9uIGJucEV4cChlLHopIHtcbiAgaWYoZSA+IDB4ZmZmZmZmZmYgfHwgZSA8IDEpIHJldHVybiBCaWdJbnRlZ2VyLk9ORTtcbiAgdmFyIHIgPSBuYmkoKSwgcjIgPSBuYmkoKSwgZyA9IHouY29udmVydCh0aGlzKSwgaSA9IG5iaXRzKGUpLTE7XG4gIGcuY29weVRvKHIpO1xuICB3aGlsZSgtLWkgPj0gMCkge1xuICAgIHouc3FyVG8ocixyMik7XG4gICAgaWYoKGUmKDE8PGkpKSA+IDApIHoubXVsVG8ocjIsZyxyKTtcbiAgICBlbHNlIHsgdmFyIHQgPSByOyByID0gcjI7IHIyID0gdDsgfVxuICB9XG4gIHJldHVybiB6LnJldmVydChyKTtcbn1cblxuLy8gKHB1YmxpYykgdGhpc15lICUgbSwgMCA8PSBlIDwgMl4zMlxuZnVuY3Rpb24gYm5Nb2RQb3dJbnQoZSxtKSB7XG4gIHZhciB6O1xuICBpZihlIDwgMjU2IHx8IG0uaXNFdmVuKCkpIHogPSBuZXcgQ2xhc3NpYyhtKTsgZWxzZSB6ID0gbmV3IE1vbnRnb21lcnkobSk7XG4gIHJldHVybiB0aGlzLmV4cChlLHopO1xufVxuXG4vLyBwcm90ZWN0ZWRcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNvcHlUbyA9IGJucENvcHlUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmZyb21JbnQgPSBibnBGcm9tSW50O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZnJvbVN0cmluZyA9IGJucEZyb21TdHJpbmc7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jbGFtcCA9IGJucENsYW1wO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZGxTaGlmdFRvID0gYm5wRExTaGlmdFRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZHJTaGlmdFRvID0gYm5wRFJTaGlmdFRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubFNoaWZ0VG8gPSBibnBMU2hpZnRUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLnJTaGlmdFRvID0gYm5wUlNoaWZ0VG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zdWJUbyA9IGJucFN1YlRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubXVsdGlwbHlUbyA9IGJucE11bHRpcGx5VG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zcXVhcmVUbyA9IGJucFNxdWFyZVRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZGl2UmVtVG8gPSBibnBEaXZSZW1UbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmludkRpZ2l0ID0gYm5wSW52RGlnaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5pc0V2ZW4gPSBibnBJc0V2ZW47XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5leHAgPSBibnBFeHA7XG5cbi8vIHB1YmxpY1xuQmlnSW50ZWdlci5wcm90b3R5cGUudG9TdHJpbmcgPSBiblRvU3RyaW5nO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubmVnYXRlID0gYm5OZWdhdGU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hYnMgPSBibkFicztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNvbXBhcmVUbyA9IGJuQ29tcGFyZVRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYml0TGVuZ3RoID0gYm5CaXRMZW5ndGg7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tb2QgPSBibk1vZDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1vZFBvd0ludCA9IGJuTW9kUG93SW50O1xuXG4vLyBcImNvbnN0YW50c1wiXG5CaWdJbnRlZ2VyLlpFUk8gPSBuYnYoMCk7XG5CaWdJbnRlZ2VyLk9ORSA9IG5idigxKTtcblxubW9kdWxlLmV4cG9ydHMgPSBCaWdJbnRlZ2VyO1xuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG4vKlxuICogQ29weXJpZ2h0IChjKSAyMDAzLTIwMDUgIFRvbSBXdSAodGp3QGNzLlN0YW5mb3JkLkVEVSkgXG4gKiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSFxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZ1xuICogYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4gKiBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbiAqIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbiAqIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0b1xuICogcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvXG4gKiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTLUlTXCIgQU5EIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIFxuICogRVhQUkVTUywgSU1QTElFRCBPUiBPVEhFUldJU0UsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04sIEFOWSBcbiAqIFdBUlJBTlRZIE9GIE1FUkNIQU5UQUJJTElUWSBPUiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFxuICpcbiAqIElOIE5PIEVWRU5UIFNIQUxMIFRPTSBXVSBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBJTkNJREVOVEFMLFxuICogSU5ESVJFQ1QgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9GIEFOWSBLSU5ELCBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSXG4gKiBSRVNVTFRJTkcgRlJPTSBMT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIE9SIE5PVCBBRFZJU0VEIE9GXG4gKiBUSEUgUE9TU0lCSUxJVFkgT0YgREFNQUdFLCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIEFSSVNJTkcgT1VUXG4gKiBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUiBQRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxuICpcbiAqIEluIGFkZGl0aW9uLCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbiBhcHBsaWVzOlxuICpcbiAqIEFsbCByZWRpc3RyaWJ1dGlvbnMgbXVzdCByZXRhaW4gYW4gaW50YWN0IGNvcHkgb2YgdGhpcyBjb3B5cmlnaHQgbm90aWNlXG4gKiBhbmQgZGlzY2xhaW1lci5cbiAqL1xuXG5cbi8vIEV4dGVuZGVkIEphdmFTY3JpcHQgQk4gZnVuY3Rpb25zLCByZXF1aXJlZCBmb3IgUlNBIHByaXZhdGUgb3BzLlxuXG4vLyBWZXJzaW9uIDEuMTogbmV3IEJpZ0ludGVnZXIoXCIwXCIsIDEwKSByZXR1cm5zIFwicHJvcGVyXCIgemVyb1xuLy8gVmVyc2lvbiAxLjI6IHNxdWFyZSgpIEFQSSwgaXNQcm9iYWJsZVByaW1lIGZpeFxuXG4vLyAocHVibGljKVxuZnVuY3Rpb24gYm5DbG9uZSgpIHsgdmFyIHIgPSBuYmkoKTsgdGhpcy5jb3B5VG8ocik7IHJldHVybiByOyB9XG5cbi8vIChwdWJsaWMpIHJldHVybiB2YWx1ZSBhcyBpbnRlZ2VyXG5mdW5jdGlvbiBibkludFZhbHVlKCkge1xuICBpZih0aGlzLnMgPCAwKSB7XG4gICAgaWYodGhpcy50ID09IDEpIHJldHVybiB0aGlzWzBdLXRoaXMuRFY7XG4gICAgZWxzZSBpZih0aGlzLnQgPT0gMCkgcmV0dXJuIC0xO1xuICB9XG4gIGVsc2UgaWYodGhpcy50ID09IDEpIHJldHVybiB0aGlzWzBdO1xuICBlbHNlIGlmKHRoaXMudCA9PSAwKSByZXR1cm4gMDtcbiAgLy8gYXNzdW1lcyAxNiA8IERCIDwgMzJcbiAgcmV0dXJuICgodGhpc1sxXSYoKDE8PCgzMi10aGlzLkRCKSktMSkpPDx0aGlzLkRCKXx0aGlzWzBdO1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gdmFsdWUgYXMgYnl0ZVxuZnVuY3Rpb24gYm5CeXRlVmFsdWUoKSB7IHJldHVybiAodGhpcy50PT0wKT90aGlzLnM6KHRoaXNbMF08PDI0KT4+MjQ7IH1cblxuLy8gKHB1YmxpYykgcmV0dXJuIHZhbHVlIGFzIHNob3J0IChhc3N1bWVzIERCPj0xNilcbmZ1bmN0aW9uIGJuU2hvcnRWYWx1ZSgpIHsgcmV0dXJuICh0aGlzLnQ9PTApP3RoaXMuczoodGhpc1swXTw8MTYpPj4xNjsgfVxuXG4vLyAocHJvdGVjdGVkKSByZXR1cm4geCBzLnQuIHJeeCA8IERWXG5mdW5jdGlvbiBibnBDaHVua1NpemUocikgeyByZXR1cm4gTWF0aC5mbG9vcihNYXRoLkxOMip0aGlzLkRCL01hdGgubG9nKHIpKTsgfVxuXG4vLyAocHVibGljKSAwIGlmIHRoaXMgPT0gMCwgMSBpZiB0aGlzID4gMFxuZnVuY3Rpb24gYm5TaWdOdW0oKSB7XG4gIGlmKHRoaXMucyA8IDApIHJldHVybiAtMTtcbiAgZWxzZSBpZih0aGlzLnQgPD0gMCB8fCAodGhpcy50ID09IDEgJiYgdGhpc1swXSA8PSAwKSkgcmV0dXJuIDA7XG4gIGVsc2UgcmV0dXJuIDE7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvbnZlcnQgdG8gcmFkaXggc3RyaW5nXG5mdW5jdGlvbiBibnBUb1JhZGl4KGIpIHtcbiAgaWYoYiA9PSBudWxsKSBiID0gMTA7XG4gIGlmKHRoaXMuc2lnbnVtKCkgPT0gMCB8fCBiIDwgMiB8fCBiID4gMzYpIHJldHVybiBcIjBcIjtcbiAgdmFyIGNzID0gdGhpcy5jaHVua1NpemUoYik7XG4gIHZhciBhID0gTWF0aC5wb3coYixjcyk7XG4gIHZhciBkID0gbmJ2KGEpLCB5ID0gbmJpKCksIHogPSBuYmkoKSwgciA9IFwiXCI7XG4gIHRoaXMuZGl2UmVtVG8oZCx5LHopO1xuICB3aGlsZSh5LnNpZ251bSgpID4gMCkge1xuICAgIHIgPSAoYSt6LmludFZhbHVlKCkpLnRvU3RyaW5nKGIpLnN1YnN0cigxKSArIHI7XG4gICAgeS5kaXZSZW1UbyhkLHkseik7XG4gIH1cbiAgcmV0dXJuIHouaW50VmFsdWUoKS50b1N0cmluZyhiKSArIHI7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvbnZlcnQgZnJvbSByYWRpeCBzdHJpbmdcbmZ1bmN0aW9uIGJucEZyb21SYWRpeChzLGIpIHtcbiAgdGhpcy5mcm9tSW50KDApO1xuICBpZihiID09IG51bGwpIGIgPSAxMDtcbiAgdmFyIGNzID0gdGhpcy5jaHVua1NpemUoYik7XG4gIHZhciBkID0gTWF0aC5wb3coYixjcyksIG1pID0gZmFsc2UsIGogPSAwLCB3ID0gMDtcbiAgZm9yKHZhciBpID0gMDsgaSA8IHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgeCA9IGludEF0KHMsaSk7XG4gICAgaWYoeCA8IDApIHtcbiAgICAgIGlmKHMuY2hhckF0KGkpID09IFwiLVwiICYmIHRoaXMuc2lnbnVtKCkgPT0gMCkgbWkgPSB0cnVlO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHcgPSBiKncreDtcbiAgICBpZigrK2ogPj0gY3MpIHtcbiAgICAgIHRoaXMuZE11bHRpcGx5KGQpO1xuICAgICAgdGhpcy5kQWRkT2Zmc2V0KHcsMCk7XG4gICAgICBqID0gMDtcbiAgICAgIHcgPSAwO1xuICAgIH1cbiAgfVxuICBpZihqID4gMCkge1xuICAgIHRoaXMuZE11bHRpcGx5KE1hdGgucG93KGIsaikpO1xuICAgIHRoaXMuZEFkZE9mZnNldCh3LDApO1xuICB9XG4gIGlmKG1pKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8odGhpcyx0aGlzKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgYWx0ZXJuYXRlIGNvbnN0cnVjdG9yXG5mdW5jdGlvbiBibnBGcm9tTnVtYmVyKGEsYixjKSB7XG4gIGlmKFwibnVtYmVyXCIgPT0gdHlwZW9mIGIpIHtcbiAgICAvLyBuZXcgQmlnSW50ZWdlcihpbnQsaW50LFJORylcbiAgICBpZihhIDwgMikgdGhpcy5mcm9tSW50KDEpO1xuICAgIGVsc2Uge1xuICAgICAgdGhpcy5mcm9tTnVtYmVyKGEsYyk7XG4gICAgICBpZighdGhpcy50ZXN0Qml0KGEtMSkpXHQvLyBmb3JjZSBNU0Igc2V0XG4gICAgICAgIHRoaXMuYml0d2lzZVRvKEJpZ0ludGVnZXIuT05FLnNoaWZ0TGVmdChhLTEpLG9wX29yLHRoaXMpO1xuICAgICAgaWYodGhpcy5pc0V2ZW4oKSkgdGhpcy5kQWRkT2Zmc2V0KDEsMCk7IC8vIGZvcmNlIG9kZFxuICAgICAgd2hpbGUoIXRoaXMuaXNQcm9iYWJsZVByaW1lKGIpKSB7XG4gICAgICAgIHRoaXMuZEFkZE9mZnNldCgyLDApO1xuICAgICAgICBpZih0aGlzLmJpdExlbmd0aCgpID4gYSkgdGhpcy5zdWJUbyhCaWdJbnRlZ2VyLk9ORS5zaGlmdExlZnQoYS0xKSx0aGlzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZWxzZSB7XG4gICAgLy8gbmV3IEJpZ0ludGVnZXIoaW50LFJORylcbiAgICB2YXIgeCA9IG5ldyBBcnJheSgpLCB0ID0gYSY3O1xuICAgIHgubGVuZ3RoID0gKGE+PjMpKzE7XG4gICAgYi5uZXh0Qnl0ZXMoeCk7XG4gICAgaWYodCA+IDApIHhbMF0gJj0gKCgxPDx0KS0xKTsgZWxzZSB4WzBdID0gMDtcbiAgICB0aGlzLmZyb21TdHJpbmcoeCwyNTYpO1xuICB9XG59XG5cbi8vIChwdWJsaWMpIGNvbnZlcnQgdG8gYmlnZW5kaWFuIGJ5dGUgYXJyYXlcbmZ1bmN0aW9uIGJuVG9CeXRlQXJyYXkoKSB7XG4gIHZhciBpID0gdGhpcy50LCByID0gbmV3IEFycmF5KCk7XG4gIHJbMF0gPSB0aGlzLnM7XG4gIHZhciBwID0gdGhpcy5EQi0oaSp0aGlzLkRCKSU4LCBkLCBrID0gMDtcbiAgaWYoaS0tID4gMCkge1xuICAgIGlmKHAgPCB0aGlzLkRCICYmIChkID0gdGhpc1tpXT4+cCkgIT0gKHRoaXMucyZ0aGlzLkRNKT4+cClcbiAgICAgIHJbaysrXSA9IGR8KHRoaXMuczw8KHRoaXMuREItcCkpO1xuICAgIHdoaWxlKGkgPj0gMCkge1xuICAgICAgaWYocCA8IDgpIHtcbiAgICAgICAgZCA9ICh0aGlzW2ldJigoMTw8cCktMSkpPDwoOC1wKTtcbiAgICAgICAgZCB8PSB0aGlzWy0taV0+PihwKz10aGlzLkRCLTgpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGQgPSAodGhpc1tpXT4+KHAtPTgpKSYweGZmO1xuICAgICAgICBpZihwIDw9IDApIHsgcCArPSB0aGlzLkRCOyAtLWk7IH1cbiAgICAgIH1cbiAgICAgIC8vaWYoKGQmMHg4MCkgIT0gMCkgZCB8PSAtMjU2O1xuICAgICAgLy9pZihrID09IDAgJiYgKHRoaXMucyYweDgwKSAhPSAoZCYweDgwKSkgKytrO1xuICAgICAgaWYoayA+IDAgfHwgZCAhPSB0aGlzLnMpIHJbaysrXSA9IGQ7XG4gICAgfVxuICB9XG4gIHJldHVybiByO1xufVxuXG5mdW5jdGlvbiBibkVxdWFscyhhKSB7IHJldHVybih0aGlzLmNvbXBhcmVUbyhhKT09MCk7IH1cbmZ1bmN0aW9uIGJuTWluKGEpIHsgcmV0dXJuKHRoaXMuY29tcGFyZVRvKGEpPDApP3RoaXM6YTsgfVxuZnVuY3Rpb24gYm5NYXgoYSkgeyByZXR1cm4odGhpcy5jb21wYXJlVG8oYSk+MCk/dGhpczphOyB9XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIG9wIGEgKGJpdHdpc2UpXG5mdW5jdGlvbiBibnBCaXR3aXNlVG8oYSxvcCxyKSB7XG4gIHZhciBpLCBmLCBtID0gTWF0aC5taW4oYS50LHRoaXMudCk7XG4gIGZvcihpID0gMDsgaSA8IG07ICsraSkgcltpXSA9IG9wKHRoaXNbaV0sYVtpXSk7XG4gIGlmKGEudCA8IHRoaXMudCkge1xuICAgIGYgPSBhLnMmdGhpcy5ETTtcbiAgICBmb3IoaSA9IG07IGkgPCB0aGlzLnQ7ICsraSkgcltpXSA9IG9wKHRoaXNbaV0sZik7XG4gICAgci50ID0gdGhpcy50O1xuICB9XG4gIGVsc2Uge1xuICAgIGYgPSB0aGlzLnMmdGhpcy5ETTtcbiAgICBmb3IoaSA9IG07IGkgPCBhLnQ7ICsraSkgcltpXSA9IG9wKGYsYVtpXSk7XG4gICAgci50ID0gYS50O1xuICB9XG4gIHIucyA9IG9wKHRoaXMucyxhLnMpO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgJiBhXG5mdW5jdGlvbiBvcF9hbmQoeCx5KSB7IHJldHVybiB4Jnk7IH1cbmZ1bmN0aW9uIGJuQW5kKGEpIHsgdmFyIHIgPSBuYmkoKTsgdGhpcy5iaXR3aXNlVG8oYSxvcF9hbmQscik7IHJldHVybiByOyB9XG5cbi8vIChwdWJsaWMpIHRoaXMgfCBhXG5mdW5jdGlvbiBvcF9vcih4LHkpIHsgcmV0dXJuIHh8eTsgfVxuZnVuY3Rpb24gYm5PcihhKSB7IHZhciByID0gbmJpKCk7IHRoaXMuYml0d2lzZVRvKGEsb3Bfb3Iscik7IHJldHVybiByOyB9XG5cbi8vIChwdWJsaWMpIHRoaXMgXiBhXG5mdW5jdGlvbiBvcF94b3IoeCx5KSB7IHJldHVybiB4Xnk7IH1cbmZ1bmN0aW9uIGJuWG9yKGEpIHsgdmFyIHIgPSBuYmkoKTsgdGhpcy5iaXR3aXNlVG8oYSxvcF94b3Iscik7IHJldHVybiByOyB9XG5cbi8vIChwdWJsaWMpIHRoaXMgJiB+YVxuZnVuY3Rpb24gb3BfYW5kbm90KHgseSkgeyByZXR1cm4geCZ+eTsgfVxuZnVuY3Rpb24gYm5BbmROb3QoYSkgeyB2YXIgciA9IG5iaSgpOyB0aGlzLmJpdHdpc2VUbyhhLG9wX2FuZG5vdCxyKTsgcmV0dXJuIHI7IH1cblxuLy8gKHB1YmxpYykgfnRoaXNcbmZ1bmN0aW9uIGJuTm90KCkge1xuICB2YXIgciA9IG5iaSgpO1xuICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy50OyArK2kpIHJbaV0gPSB0aGlzLkRNJn50aGlzW2ldO1xuICByLnQgPSB0aGlzLnQ7XG4gIHIucyA9IH50aGlzLnM7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzIDw8IG5cbmZ1bmN0aW9uIGJuU2hpZnRMZWZ0KG4pIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgaWYobiA8IDApIHRoaXMuclNoaWZ0VG8oLW4scik7IGVsc2UgdGhpcy5sU2hpZnRUbyhuLHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyA+PiBuXG5mdW5jdGlvbiBiblNoaWZ0UmlnaHQobikge1xuICB2YXIgciA9IG5iaSgpO1xuICBpZihuIDwgMCkgdGhpcy5sU2hpZnRUbygtbixyKTsgZWxzZSB0aGlzLnJTaGlmdFRvKG4scik7XG4gIHJldHVybiByO1xufVxuXG4vLyByZXR1cm4gaW5kZXggb2YgbG93ZXN0IDEtYml0IGluIHgsIHggPCAyXjMxXG5mdW5jdGlvbiBsYml0KHgpIHtcbiAgaWYoeCA9PSAwKSByZXR1cm4gLTE7XG4gIHZhciByID0gMDtcbiAgaWYoKHgmMHhmZmZmKSA9PSAwKSB7IHggPj49IDE2OyByICs9IDE2OyB9XG4gIGlmKCh4JjB4ZmYpID09IDApIHsgeCA+Pj0gODsgciArPSA4OyB9XG4gIGlmKCh4JjB4ZikgPT0gMCkgeyB4ID4+PSA0OyByICs9IDQ7IH1cbiAgaWYoKHgmMykgPT0gMCkgeyB4ID4+PSAyOyByICs9IDI7IH1cbiAgaWYoKHgmMSkgPT0gMCkgKytyO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgcmV0dXJucyBpbmRleCBvZiBsb3dlc3QgMS1iaXQgKG9yIC0xIGlmIG5vbmUpXG5mdW5jdGlvbiBibkdldExvd2VzdFNldEJpdCgpIHtcbiAgZm9yKHZhciBpID0gMDsgaSA8IHRoaXMudDsgKytpKVxuICAgIGlmKHRoaXNbaV0gIT0gMCkgcmV0dXJuIGkqdGhpcy5EQitsYml0KHRoaXNbaV0pO1xuICBpZih0aGlzLnMgPCAwKSByZXR1cm4gdGhpcy50KnRoaXMuREI7XG4gIHJldHVybiAtMTtcbn1cblxuLy8gcmV0dXJuIG51bWJlciBvZiAxIGJpdHMgaW4geFxuZnVuY3Rpb24gY2JpdCh4KSB7XG4gIHZhciByID0gMDtcbiAgd2hpbGUoeCAhPSAwKSB7IHggJj0geC0xOyArK3I7IH1cbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiBudW1iZXIgb2Ygc2V0IGJpdHNcbmZ1bmN0aW9uIGJuQml0Q291bnQoKSB7XG4gIHZhciByID0gMCwgeCA9IHRoaXMucyZ0aGlzLkRNO1xuICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy50OyArK2kpIHIgKz0gY2JpdCh0aGlzW2ldXngpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdHJ1ZSBpZmYgbnRoIGJpdCBpcyBzZXRcbmZ1bmN0aW9uIGJuVGVzdEJpdChuKSB7XG4gIHZhciBqID0gTWF0aC5mbG9vcihuL3RoaXMuREIpO1xuICBpZihqID49IHRoaXMudCkgcmV0dXJuKHRoaXMucyE9MCk7XG4gIHJldHVybigodGhpc1tqXSYoMTw8KG4ldGhpcy5EQikpKSE9MCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgb3AgKDE8PG4pXG5mdW5jdGlvbiBibnBDaGFuZ2VCaXQobixvcCkge1xuICB2YXIgciA9IEJpZ0ludGVnZXIuT05FLnNoaWZ0TGVmdChuKTtcbiAgdGhpcy5iaXR3aXNlVG8ocixvcCxyKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgfCAoMTw8bilcbmZ1bmN0aW9uIGJuU2V0Qml0KG4pIHsgcmV0dXJuIHRoaXMuY2hhbmdlQml0KG4sb3Bfb3IpOyB9XG5cbi8vIChwdWJsaWMpIHRoaXMgJiB+KDE8PG4pXG5mdW5jdGlvbiBibkNsZWFyQml0KG4pIHsgcmV0dXJuIHRoaXMuY2hhbmdlQml0KG4sb3BfYW5kbm90KTsgfVxuXG4vLyAocHVibGljKSB0aGlzIF4gKDE8PG4pXG5mdW5jdGlvbiBibkZsaXBCaXQobikgeyByZXR1cm4gdGhpcy5jaGFuZ2VCaXQobixvcF94b3IpOyB9XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzICsgYVxuZnVuY3Rpb24gYm5wQWRkVG8oYSxyKSB7XG4gIHZhciBpID0gMCwgYyA9IDAsIG0gPSBNYXRoLm1pbihhLnQsdGhpcy50KTtcbiAgd2hpbGUoaSA8IG0pIHtcbiAgICBjICs9IHRoaXNbaV0rYVtpXTtcbiAgICByW2krK10gPSBjJnRoaXMuRE07XG4gICAgYyA+Pj0gdGhpcy5EQjtcbiAgfVxuICBpZihhLnQgPCB0aGlzLnQpIHtcbiAgICBjICs9IGEucztcbiAgICB3aGlsZShpIDwgdGhpcy50KSB7XG4gICAgICBjICs9IHRoaXNbaV07XG4gICAgICByW2krK10gPSBjJnRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjICs9IHRoaXMucztcbiAgfVxuICBlbHNlIHtcbiAgICBjICs9IHRoaXMucztcbiAgICB3aGlsZShpIDwgYS50KSB7XG4gICAgICBjICs9IGFbaV07XG4gICAgICByW2krK10gPSBjJnRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjICs9IGEucztcbiAgfVxuICByLnMgPSAoYzwwKT8tMTowO1xuICBpZihjID4gMCkgcltpKytdID0gYztcbiAgZWxzZSBpZihjIDwgLTEpIHJbaSsrXSA9IHRoaXMuRFYrYztcbiAgci50ID0gaTtcbiAgci5jbGFtcCgpO1xufVxuXG4vLyAocHVibGljKSB0aGlzICsgYVxuZnVuY3Rpb24gYm5BZGQoYSkgeyB2YXIgciA9IG5iaSgpOyB0aGlzLmFkZFRvKGEscik7IHJldHVybiByOyB9XG5cbi8vIChwdWJsaWMpIHRoaXMgLSBhXG5mdW5jdGlvbiBiblN1YnRyYWN0KGEpIHsgdmFyIHIgPSBuYmkoKTsgdGhpcy5zdWJUbyhhLHIpOyByZXR1cm4gcjsgfVxuXG4vLyAocHVibGljKSB0aGlzICogYVxuZnVuY3Rpb24gYm5NdWx0aXBseShhKSB7IHZhciByID0gbmJpKCk7IHRoaXMubXVsdGlwbHlUbyhhLHIpOyByZXR1cm4gcjsgfVxuXG4vLyAocHVibGljKSB0aGlzXjJcbmZ1bmN0aW9uIGJuU3F1YXJlKCkgeyB2YXIgciA9IG5iaSgpOyB0aGlzLnNxdWFyZVRvKHIpOyByZXR1cm4gcjsgfVxuXG4vLyAocHVibGljKSB0aGlzIC8gYVxuZnVuY3Rpb24gYm5EaXZpZGUoYSkgeyB2YXIgciA9IG5iaSgpOyB0aGlzLmRpdlJlbVRvKGEscixudWxsKTsgcmV0dXJuIHI7IH1cblxuLy8gKHB1YmxpYykgdGhpcyAlIGFcbmZ1bmN0aW9uIGJuUmVtYWluZGVyKGEpIHsgdmFyIHIgPSBuYmkoKTsgdGhpcy5kaXZSZW1UbyhhLG51bGwscik7IHJldHVybiByOyB9XG5cbi8vIChwdWJsaWMpIFt0aGlzL2EsdGhpcyVhXVxuZnVuY3Rpb24gYm5EaXZpZGVBbmRSZW1haW5kZXIoYSkge1xuICB2YXIgcSA9IG5iaSgpLCByID0gbmJpKCk7XG4gIHRoaXMuZGl2UmVtVG8oYSxxLHIpO1xuICByZXR1cm4gbmV3IEFycmF5KHEscik7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgKj0gbiwgdGhpcyA+PSAwLCAxIDwgbiA8IERWXG5mdW5jdGlvbiBibnBETXVsdGlwbHkobikge1xuICB0aGlzW3RoaXMudF0gPSB0aGlzLmFtKDAsbi0xLHRoaXMsMCwwLHRoaXMudCk7XG4gICsrdGhpcy50O1xuICB0aGlzLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgKz0gbiA8PCB3IHdvcmRzLCB0aGlzID49IDBcbmZ1bmN0aW9uIGJucERBZGRPZmZzZXQobix3KSB7XG4gIGlmKG4gPT0gMCkgcmV0dXJuO1xuICB3aGlsZSh0aGlzLnQgPD0gdykgdGhpc1t0aGlzLnQrK10gPSAwO1xuICB0aGlzW3ddICs9IG47XG4gIHdoaWxlKHRoaXNbd10gPj0gdGhpcy5EVikge1xuICAgIHRoaXNbd10gLT0gdGhpcy5EVjtcbiAgICBpZigrK3cgPj0gdGhpcy50KSB0aGlzW3RoaXMudCsrXSA9IDA7XG4gICAgKyt0aGlzW3ddO1xuICB9XG59XG5cbi8vIEEgXCJudWxsXCIgcmVkdWNlclxuZnVuY3Rpb24gTnVsbEV4cCgpIHt9XG5mdW5jdGlvbiBuTm9wKHgpIHsgcmV0dXJuIHg7IH1cbmZ1bmN0aW9uIG5NdWxUbyh4LHkscikgeyB4Lm11bHRpcGx5VG8oeSxyKTsgfVxuZnVuY3Rpb24gblNxclRvKHgscikgeyB4LnNxdWFyZVRvKHIpOyB9XG5cbk51bGxFeHAucHJvdG90eXBlLmNvbnZlcnQgPSBuTm9wO1xuTnVsbEV4cC5wcm90b3R5cGUucmV2ZXJ0ID0gbk5vcDtcbk51bGxFeHAucHJvdG90eXBlLm11bFRvID0gbk11bFRvO1xuTnVsbEV4cC5wcm90b3R5cGUuc3FyVG8gPSBuU3FyVG87XG5cbi8vIChwdWJsaWMpIHRoaXNeZVxuZnVuY3Rpb24gYm5Qb3coZSkgeyByZXR1cm4gdGhpcy5leHAoZSxuZXcgTnVsbEV4cCgpKTsgfVxuXG4vLyAocHJvdGVjdGVkKSByID0gbG93ZXIgbiB3b3JkcyBvZiBcInRoaXMgKiBhXCIsIGEudCA8PSBuXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5mdW5jdGlvbiBibnBNdWx0aXBseUxvd2VyVG8oYSxuLHIpIHtcbiAgdmFyIGkgPSBNYXRoLm1pbih0aGlzLnQrYS50LG4pO1xuICByLnMgPSAwOyAvLyBhc3N1bWVzIGEsdGhpcyA+PSAwXG4gIHIudCA9IGk7XG4gIHdoaWxlKGkgPiAwKSByWy0taV0gPSAwO1xuICB2YXIgajtcbiAgZm9yKGogPSByLnQtdGhpcy50OyBpIDwgajsgKytpKSByW2krdGhpcy50XSA9IHRoaXMuYW0oMCxhW2ldLHIsaSwwLHRoaXMudCk7XG4gIGZvcihqID0gTWF0aC5taW4oYS50LG4pOyBpIDwgajsgKytpKSB0aGlzLmFtKDAsYVtpXSxyLGksMCxuLWkpO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSBcInRoaXMgKiBhXCIgd2l0aG91dCBsb3dlciBuIHdvcmRzLCBuID4gMFxuLy8gXCJ0aGlzXCIgc2hvdWxkIGJlIHRoZSBsYXJnZXIgb25lIGlmIGFwcHJvcHJpYXRlLlxuZnVuY3Rpb24gYm5wTXVsdGlwbHlVcHBlclRvKGEsbixyKSB7XG4gIC0tbjtcbiAgdmFyIGkgPSByLnQgPSB0aGlzLnQrYS50LW47XG4gIHIucyA9IDA7IC8vIGFzc3VtZXMgYSx0aGlzID49IDBcbiAgd2hpbGUoLS1pID49IDApIHJbaV0gPSAwO1xuICBmb3IoaSA9IE1hdGgubWF4KG4tdGhpcy50LDApOyBpIDwgYS50OyArK2kpXG4gICAgclt0aGlzLnQraS1uXSA9IHRoaXMuYW0obi1pLGFbaV0sciwwLDAsdGhpcy50K2ktbik7XG4gIHIuY2xhbXAoKTtcbiAgci5kclNoaWZ0VG8oMSxyKTtcbn1cblxuLy8gQmFycmV0dCBtb2R1bGFyIHJlZHVjdGlvblxuZnVuY3Rpb24gQmFycmV0dChtKSB7XG4gIC8vIHNldHVwIEJhcnJldHRcbiAgdGhpcy5yMiA9IG5iaSgpO1xuICB0aGlzLnEzID0gbmJpKCk7XG4gIEJpZ0ludGVnZXIuT05FLmRsU2hpZnRUbygyKm0udCx0aGlzLnIyKTtcbiAgdGhpcy5tdSA9IHRoaXMucjIuZGl2aWRlKG0pO1xuICB0aGlzLm0gPSBtO1xufVxuXG5mdW5jdGlvbiBiYXJyZXR0Q29udmVydCh4KSB7XG4gIGlmKHgucyA8IDAgfHwgeC50ID4gMip0aGlzLm0udCkgcmV0dXJuIHgubW9kKHRoaXMubSk7XG4gIGVsc2UgaWYoeC5jb21wYXJlVG8odGhpcy5tKSA8IDApIHJldHVybiB4O1xuICBlbHNlIHsgdmFyIHIgPSBuYmkoKTsgeC5jb3B5VG8ocik7IHRoaXMucmVkdWNlKHIpOyByZXR1cm4gcjsgfVxufVxuXG5mdW5jdGlvbiBiYXJyZXR0UmV2ZXJ0KHgpIHsgcmV0dXJuIHg7IH1cblxuLy8geCA9IHggbW9kIG0gKEhBQyAxNC40MilcbmZ1bmN0aW9uIGJhcnJldHRSZWR1Y2UoeCkge1xuICB4LmRyU2hpZnRUbyh0aGlzLm0udC0xLHRoaXMucjIpO1xuICBpZih4LnQgPiB0aGlzLm0udCsxKSB7IHgudCA9IHRoaXMubS50KzE7IHguY2xhbXAoKTsgfVxuICB0aGlzLm11Lm11bHRpcGx5VXBwZXJUbyh0aGlzLnIyLHRoaXMubS50KzEsdGhpcy5xMyk7XG4gIHRoaXMubS5tdWx0aXBseUxvd2VyVG8odGhpcy5xMyx0aGlzLm0udCsxLHRoaXMucjIpO1xuICB3aGlsZSh4LmNvbXBhcmVUbyh0aGlzLnIyKSA8IDApIHguZEFkZE9mZnNldCgxLHRoaXMubS50KzEpO1xuICB4LnN1YlRvKHRoaXMucjIseCk7XG4gIHdoaWxlKHguY29tcGFyZVRvKHRoaXMubSkgPj0gMCkgeC5zdWJUbyh0aGlzLm0seCk7XG59XG5cbi8vIHIgPSB4XjIgbW9kIG07IHggIT0gclxuZnVuY3Rpb24gYmFycmV0dFNxclRvKHgscikgeyB4LnNxdWFyZVRvKHIpOyB0aGlzLnJlZHVjZShyKTsgfVxuXG4vLyByID0geCp5IG1vZCBtOyB4LHkgIT0gclxuZnVuY3Rpb24gYmFycmV0dE11bFRvKHgseSxyKSB7IHgubXVsdGlwbHlUbyh5LHIpOyB0aGlzLnJlZHVjZShyKTsgfVxuXG5CYXJyZXR0LnByb3RvdHlwZS5jb252ZXJ0ID0gYmFycmV0dENvbnZlcnQ7XG5CYXJyZXR0LnByb3RvdHlwZS5yZXZlcnQgPSBiYXJyZXR0UmV2ZXJ0O1xuQmFycmV0dC5wcm90b3R5cGUucmVkdWNlID0gYmFycmV0dFJlZHVjZTtcbkJhcnJldHQucHJvdG90eXBlLm11bFRvID0gYmFycmV0dE11bFRvO1xuQmFycmV0dC5wcm90b3R5cGUuc3FyVG8gPSBiYXJyZXR0U3FyVG87XG5cbi8vIChwdWJsaWMpIHRoaXNeZSAlIG0gKEhBQyAxNC44NSlcbmZ1bmN0aW9uIGJuTW9kUG93KGUsbSkge1xuICB2YXIgaSA9IGUuYml0TGVuZ3RoKCksIGssIHIgPSBuYnYoMSksIHo7XG4gIGlmKGkgPD0gMCkgcmV0dXJuIHI7XG4gIGVsc2UgaWYoaSA8IDE4KSBrID0gMTtcbiAgZWxzZSBpZihpIDwgNDgpIGsgPSAzO1xuICBlbHNlIGlmKGkgPCAxNDQpIGsgPSA0O1xuICBlbHNlIGlmKGkgPCA3NjgpIGsgPSA1O1xuICBlbHNlIGsgPSA2O1xuICBpZihpIDwgOClcbiAgICB6ID0gbmV3IENsYXNzaWMobSk7XG4gIGVsc2UgaWYobS5pc0V2ZW4oKSlcbiAgICB6ID0gbmV3IEJhcnJldHQobSk7XG4gIGVsc2VcbiAgICB6ID0gbmV3IE1vbnRnb21lcnkobSk7XG5cbiAgLy8gcHJlY29tcHV0YXRpb25cbiAgdmFyIGcgPSBuZXcgQXJyYXkoKSwgbiA9IDMsIGsxID0gay0xLCBrbSA9ICgxPDxrKS0xO1xuICBnWzFdID0gei5jb252ZXJ0KHRoaXMpO1xuICBpZihrID4gMSkge1xuICAgIHZhciBnMiA9IG5iaSgpO1xuICAgIHouc3FyVG8oZ1sxXSxnMik7XG4gICAgd2hpbGUobiA8PSBrbSkge1xuICAgICAgZ1tuXSA9IG5iaSgpO1xuICAgICAgei5tdWxUbyhnMixnW24tMl0sZ1tuXSk7XG4gICAgICBuICs9IDI7XG4gICAgfVxuICB9XG5cbiAgdmFyIGogPSBlLnQtMSwgdywgaXMxID0gdHJ1ZSwgcjIgPSBuYmkoKSwgdDtcbiAgaSA9IG5iaXRzKGVbal0pLTE7XG4gIHdoaWxlKGogPj0gMCkge1xuICAgIGlmKGkgPj0gazEpIHcgPSAoZVtqXT4+KGktazEpKSZrbTtcbiAgICBlbHNlIHtcbiAgICAgIHcgPSAoZVtqXSYoKDE8PChpKzEpKS0xKSk8PChrMS1pKTtcbiAgICAgIGlmKGogPiAwKSB3IHw9IGVbai0xXT4+KHRoaXMuREIraS1rMSk7XG4gICAgfVxuXG4gICAgbiA9IGs7XG4gICAgd2hpbGUoKHcmMSkgPT0gMCkgeyB3ID4+PSAxOyAtLW47IH1cbiAgICBpZigoaSAtPSBuKSA8IDApIHsgaSArPSB0aGlzLkRCOyAtLWo7IH1cbiAgICBpZihpczEpIHtcdC8vIHJldCA9PSAxLCBkb24ndCBib3RoZXIgc3F1YXJpbmcgb3IgbXVsdGlwbHlpbmcgaXRcbiAgICAgIGdbd10uY29weVRvKHIpO1xuICAgICAgaXMxID0gZmFsc2U7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgd2hpbGUobiA+IDEpIHsgei5zcXJUbyhyLHIyKTsgei5zcXJUbyhyMixyKTsgbiAtPSAyOyB9XG4gICAgICBpZihuID4gMCkgei5zcXJUbyhyLHIyKTsgZWxzZSB7IHQgPSByOyByID0gcjI7IHIyID0gdDsgfVxuICAgICAgei5tdWxUbyhyMixnW3ddLHIpO1xuICAgIH1cblxuICAgIHdoaWxlKGogPj0gMCAmJiAoZVtqXSYoMTw8aSkpID09IDApIHtcbiAgICAgIHouc3FyVG8ocixyMik7IHQgPSByOyByID0gcjI7IHIyID0gdDtcbiAgICAgIGlmKC0taSA8IDApIHsgaSA9IHRoaXMuREItMTsgLS1qOyB9XG4gICAgfVxuICB9XG4gIHJldHVybiB6LnJldmVydChyKTtcbn1cblxuLy8gKHB1YmxpYykgZ2NkKHRoaXMsYSkgKEhBQyAxNC41NClcbmZ1bmN0aW9uIGJuR0NEKGEpIHtcbiAgdmFyIHggPSAodGhpcy5zPDApP3RoaXMubmVnYXRlKCk6dGhpcy5jbG9uZSgpO1xuICB2YXIgeSA9IChhLnM8MCk/YS5uZWdhdGUoKTphLmNsb25lKCk7XG4gIGlmKHguY29tcGFyZVRvKHkpIDwgMCkgeyB2YXIgdCA9IHg7IHggPSB5OyB5ID0gdDsgfVxuICB2YXIgaSA9IHguZ2V0TG93ZXN0U2V0Qml0KCksIGcgPSB5LmdldExvd2VzdFNldEJpdCgpO1xuICBpZihnIDwgMCkgcmV0dXJuIHg7XG4gIGlmKGkgPCBnKSBnID0gaTtcbiAgaWYoZyA+IDApIHtcbiAgICB4LnJTaGlmdFRvKGcseCk7XG4gICAgeS5yU2hpZnRUbyhnLHkpO1xuICB9XG4gIHdoaWxlKHguc2lnbnVtKCkgPiAwKSB7XG4gICAgaWYoKGkgPSB4LmdldExvd2VzdFNldEJpdCgpKSA+IDApIHguclNoaWZ0VG8oaSx4KTtcbiAgICBpZigoaSA9IHkuZ2V0TG93ZXN0U2V0Qml0KCkpID4gMCkgeS5yU2hpZnRUbyhpLHkpO1xuICAgIGlmKHguY29tcGFyZVRvKHkpID49IDApIHtcbiAgICAgIHguc3ViVG8oeSx4KTtcbiAgICAgIHguclNoaWZ0VG8oMSx4KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB5LnN1YlRvKHgseSk7XG4gICAgICB5LnJTaGlmdFRvKDEseSk7XG4gICAgfVxuICB9XG4gIGlmKGcgPiAwKSB5LmxTaGlmdFRvKGcseSk7XG4gIHJldHVybiB5O1xufVxuXG4vLyAocHJvdGVjdGVkKSB0aGlzICUgbiwgbiA8IDJeMjZcbmZ1bmN0aW9uIGJucE1vZEludChuKSB7XG4gIGlmKG4gPD0gMCkgcmV0dXJuIDA7XG4gIHZhciBkID0gdGhpcy5EViVuLCByID0gKHRoaXMuczwwKT9uLTE6MDtcbiAgaWYodGhpcy50ID4gMClcbiAgICBpZihkID09IDApIHIgPSB0aGlzWzBdJW47XG4gICAgZWxzZSBmb3IodmFyIGkgPSB0aGlzLnQtMTsgaSA+PSAwOyAtLWkpIHIgPSAoZCpyK3RoaXNbaV0pJW47XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSAxL3RoaXMgJSBtIChIQUMgMTQuNjEpXG5mdW5jdGlvbiBibk1vZEludmVyc2UobSkge1xuICB2YXIgYWMgPSBtLmlzRXZlbigpO1xuICBpZigodGhpcy5pc0V2ZW4oKSAmJiBhYykgfHwgbS5zaWdudW0oKSA9PSAwKSByZXR1cm4gQmlnSW50ZWdlci5aRVJPO1xuICB2YXIgdSA9IG0uY2xvbmUoKSwgdiA9IHRoaXMuY2xvbmUoKTtcbiAgdmFyIGEgPSBuYnYoMSksIGIgPSBuYnYoMCksIGMgPSBuYnYoMCksIGQgPSBuYnYoMSk7XG4gIHdoaWxlKHUuc2lnbnVtKCkgIT0gMCkge1xuICAgIHdoaWxlKHUuaXNFdmVuKCkpIHtcbiAgICAgIHUuclNoaWZ0VG8oMSx1KTtcbiAgICAgIGlmKGFjKSB7XG4gICAgICAgIGlmKCFhLmlzRXZlbigpIHx8ICFiLmlzRXZlbigpKSB7IGEuYWRkVG8odGhpcyxhKTsgYi5zdWJUbyhtLGIpOyB9XG4gICAgICAgIGEuclNoaWZ0VG8oMSxhKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYoIWIuaXNFdmVuKCkpIGIuc3ViVG8obSxiKTtcbiAgICAgIGIuclNoaWZ0VG8oMSxiKTtcbiAgICB9XG4gICAgd2hpbGUodi5pc0V2ZW4oKSkge1xuICAgICAgdi5yU2hpZnRUbygxLHYpO1xuICAgICAgaWYoYWMpIHtcbiAgICAgICAgaWYoIWMuaXNFdmVuKCkgfHwgIWQuaXNFdmVuKCkpIHsgYy5hZGRUbyh0aGlzLGMpOyBkLnN1YlRvKG0sZCk7IH1cbiAgICAgICAgYy5yU2hpZnRUbygxLGMpO1xuICAgICAgfVxuICAgICAgZWxzZSBpZighZC5pc0V2ZW4oKSkgZC5zdWJUbyhtLGQpO1xuICAgICAgZC5yU2hpZnRUbygxLGQpO1xuICAgIH1cbiAgICBpZih1LmNvbXBhcmVUbyh2KSA+PSAwKSB7XG4gICAgICB1LnN1YlRvKHYsdSk7XG4gICAgICBpZihhYykgYS5zdWJUbyhjLGEpO1xuICAgICAgYi5zdWJUbyhkLGIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHYuc3ViVG8odSx2KTtcbiAgICAgIGlmKGFjKSBjLnN1YlRvKGEsYyk7XG4gICAgICBkLnN1YlRvKGIsZCk7XG4gICAgfVxuICB9XG4gIGlmKHYuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSAhPSAwKSByZXR1cm4gQmlnSW50ZWdlci5aRVJPO1xuICBpZihkLmNvbXBhcmVUbyhtKSA+PSAwKSByZXR1cm4gZC5zdWJ0cmFjdChtKTtcbiAgaWYoZC5zaWdudW0oKSA8IDApIGQuYWRkVG8obSxkKTsgZWxzZSByZXR1cm4gZDtcbiAgaWYoZC5zaWdudW0oKSA8IDApIHJldHVybiBkLmFkZChtKTsgZWxzZSByZXR1cm4gZDtcbn1cblxudmFyIGxvd3ByaW1lcyA9IFsyLDMsNSw3LDExLDEzLDE3LDE5LDIzLDI5LDMxLDM3LDQxLDQzLDQ3LDUzLDU5LDYxLDY3LDcxLDczLDc5LDgzLDg5LDk3LDEwMSwxMDMsMTA3LDEwOSwxMTMsMTI3LDEzMSwxMzcsMTM5LDE0OSwxNTEsMTU3LDE2MywxNjcsMTczLDE3OSwxODEsMTkxLDE5MywxOTcsMTk5LDIxMSwyMjMsMjI3LDIyOSwyMzMsMjM5LDI0MSwyNTEsMjU3LDI2MywyNjksMjcxLDI3NywyODEsMjgzLDI5MywzMDcsMzExLDMxMywzMTcsMzMxLDMzNywzNDcsMzQ5LDM1MywzNTksMzY3LDM3MywzNzksMzgzLDM4OSwzOTcsNDAxLDQwOSw0MTksNDIxLDQzMSw0MzMsNDM5LDQ0Myw0NDksNDU3LDQ2MSw0NjMsNDY3LDQ3OSw0ODcsNDkxLDQ5OSw1MDMsNTA5LDUyMSw1MjMsNTQxLDU0Nyw1NTcsNTYzLDU2OSw1NzEsNTc3LDU4Nyw1OTMsNTk5LDYwMSw2MDcsNjEzLDYxNyw2MTksNjMxLDY0MSw2NDMsNjQ3LDY1Myw2NTksNjYxLDY3Myw2NzcsNjgzLDY5MSw3MDEsNzA5LDcxOSw3MjcsNzMzLDczOSw3NDMsNzUxLDc1Nyw3NjEsNzY5LDc3Myw3ODcsNzk3LDgwOSw4MTEsODIxLDgyMyw4MjcsODI5LDgzOSw4NTMsODU3LDg1OSw4NjMsODc3LDg4MSw4ODMsODg3LDkwNyw5MTEsOTE5LDkyOSw5MzcsOTQxLDk0Nyw5NTMsOTY3LDk3MSw5NzcsOTgzLDk5MSw5OTddO1xudmFyIGxwbGltID0gKDE8PDI2KS9sb3dwcmltZXNbbG93cHJpbWVzLmxlbmd0aC0xXTtcblxuLy8gKHB1YmxpYykgdGVzdCBwcmltYWxpdHkgd2l0aCBjZXJ0YWludHkgPj0gMS0uNV50XG5mdW5jdGlvbiBibklzUHJvYmFibGVQcmltZSh0KSB7XG4gIHZhciBpLCB4ID0gdGhpcy5hYnMoKTtcbiAgaWYoeC50ID09IDEgJiYgeFswXSA8PSBsb3dwcmltZXNbbG93cHJpbWVzLmxlbmd0aC0xXSkge1xuICAgIGZvcihpID0gMDsgaSA8IGxvd3ByaW1lcy5sZW5ndGg7ICsraSlcbiAgICAgIGlmKHhbMF0gPT0gbG93cHJpbWVzW2ldKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYoeC5pc0V2ZW4oKSkgcmV0dXJuIGZhbHNlO1xuICBpID0gMTtcbiAgd2hpbGUoaSA8IGxvd3ByaW1lcy5sZW5ndGgpIHtcbiAgICB2YXIgbSA9IGxvd3ByaW1lc1tpXSwgaiA9IGkrMTtcbiAgICB3aGlsZShqIDwgbG93cHJpbWVzLmxlbmd0aCAmJiBtIDwgbHBsaW0pIG0gKj0gbG93cHJpbWVzW2orK107XG4gICAgbSA9IHgubW9kSW50KG0pO1xuICAgIHdoaWxlKGkgPCBqKSBpZihtJWxvd3ByaW1lc1tpKytdID09IDApIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4geC5taWxsZXJSYWJpbih0KTtcbn1cblxuLyogYWRkZWQgYnkgUmVjdXJpdHkgTGFicyAqL1xuXG5mdW5jdGlvbiBuYml0cyh4KSB7XG5cdHZhciBuID0gMSwgdDtcblx0aWYgKCh0ID0geCA+Pj4gMTYpICE9IDApIHtcblx0XHR4ID0gdDtcblx0XHRuICs9IDE2O1xuXHR9XG5cdGlmICgodCA9IHggPj4gOCkgIT0gMCkge1xuXHRcdHggPSB0O1xuXHRcdG4gKz0gODtcblx0fVxuXHRpZiAoKHQgPSB4ID4+IDQpICE9IDApIHtcblx0XHR4ID0gdDtcblx0XHRuICs9IDQ7XG5cdH1cblx0aWYgKCh0ID0geCA+PiAyKSAhPSAwKSB7XG5cdFx0eCA9IHQ7XG5cdFx0biArPSAyO1xuXHR9XG5cdGlmICgodCA9IHggPj4gMSkgIT0gMCkge1xuXHRcdHggPSB0O1xuXHRcdG4gKz0gMTtcblx0fVxuXHRyZXR1cm4gbjtcbn1cblxuZnVuY3Rpb24gYm5Ub01QSSAoKSB7XG5cdHZhciBiYSA9IHRoaXMudG9CeXRlQXJyYXkoKTtcblx0dmFyIHNpemUgPSAoYmEubGVuZ3RoLTEpKjgrbmJpdHMoYmFbMF0pO1xuXHR2YXIgcmVzdWx0ID0gXCJcIjtcblx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKHNpemUgJiAweEZGMDApID4+IDgpO1xuXHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShzaXplICYgMHhGRik7XG5cdHJlc3VsdCArPSB1dGlsLmJpbjJzdHIoYmEpO1xuXHRyZXR1cm4gcmVzdWx0O1xufVxuLyogRU5EIG9mIGFkZGl0aW9uICovXG5cbi8vIChwcm90ZWN0ZWQpIHRydWUgaWYgcHJvYmFibHkgcHJpbWUgKEhBQyA0LjI0LCBNaWxsZXItUmFiaW4pXG5mdW5jdGlvbiBibnBNaWxsZXJSYWJpbih0KSB7XG4gIHZhciBuMSA9IHRoaXMuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpO1xuICB2YXIgayA9IG4xLmdldExvd2VzdFNldEJpdCgpO1xuICBpZihrIDw9IDApIHJldHVybiBmYWxzZTtcbiAgdmFyIHIgPSBuMS5zaGlmdFJpZ2h0KGspO1xuICB0ID0gKHQrMSk+PjE7XG4gIGlmKHQgPiBsb3dwcmltZXMubGVuZ3RoKSB0ID0gbG93cHJpbWVzLmxlbmd0aDtcbiAgdmFyIGEgPSBuYmkoKTtcbiAgZm9yKHZhciBpID0gMDsgaSA8IHQ7ICsraSkge1xuICAgIC8vUGljayBiYXNlcyBhdCByYW5kb20sIGluc3RlYWQgb2Ygc3RhcnRpbmcgYXQgMlxuICAgIGEuZnJvbUludChsb3dwcmltZXNbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpKmxvd3ByaW1lcy5sZW5ndGgpXSk7XG4gICAgdmFyIHkgPSBhLm1vZFBvdyhyLHRoaXMpO1xuICAgIGlmKHkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSAhPSAwICYmIHkuY29tcGFyZVRvKG4xKSAhPSAwKSB7XG4gICAgICB2YXIgaiA9IDE7XG4gICAgICB3aGlsZShqKysgPCBrICYmIHkuY29tcGFyZVRvKG4xKSAhPSAwKSB7XG4gICAgICAgIHkgPSB5Lm1vZFBvd0ludCgyLHRoaXMpO1xuICAgICAgICBpZih5LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPT0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYoeS5jb21wYXJlVG8objEpICE9IDApIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnLi9qc2JuLmpzJyk7XG5cbi8vIHByb3RlY3RlZFxuQmlnSW50ZWdlci5wcm90b3R5cGUuY2h1bmtTaXplID0gYm5wQ2h1bmtTaXplO1xuQmlnSW50ZWdlci5wcm90b3R5cGUudG9SYWRpeCA9IGJucFRvUmFkaXg7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5mcm9tUmFkaXggPSBibnBGcm9tUmFkaXg7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5mcm9tTnVtYmVyID0gYm5wRnJvbU51bWJlcjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmJpdHdpc2VUbyA9IGJucEJpdHdpc2VUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNoYW5nZUJpdCA9IGJucENoYW5nZUJpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmFkZFRvID0gYm5wQWRkVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kTXVsdGlwbHkgPSBibnBETXVsdGlwbHk7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kQWRkT2Zmc2V0ID0gYm5wREFkZE9mZnNldDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm11bHRpcGx5TG93ZXJUbyA9IGJucE11bHRpcGx5TG93ZXJUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLm11bHRpcGx5VXBwZXJUbyA9IGJucE11bHRpcGx5VXBwZXJUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1vZEludCA9IGJucE1vZEludDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1pbGxlclJhYmluID0gYm5wTWlsbGVyUmFiaW47XG5cbi8vIHB1YmxpY1xuQmlnSW50ZWdlci5wcm90b3R5cGUuY2xvbmUgPSBibkNsb25lO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuaW50VmFsdWUgPSBibkludFZhbHVlO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYnl0ZVZhbHVlID0gYm5CeXRlVmFsdWU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zaG9ydFZhbHVlID0gYm5TaG9ydFZhbHVlO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc2lnbnVtID0gYm5TaWdOdW07XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS50b0J5dGVBcnJheSA9IGJuVG9CeXRlQXJyYXk7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5lcXVhbHMgPSBibkVxdWFscztcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1pbiA9IGJuTWluO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubWF4ID0gYm5NYXg7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hbmQgPSBibkFuZDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm9yID0gYm5PcjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnhvciA9IGJuWG9yO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYW5kTm90ID0gYm5BbmROb3Q7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5ub3QgPSBibk5vdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnNoaWZ0TGVmdCA9IGJuU2hpZnRMZWZ0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc2hpZnRSaWdodCA9IGJuU2hpZnRSaWdodDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmdldExvd2VzdFNldEJpdCA9IGJuR2V0TG93ZXN0U2V0Qml0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYml0Q291bnQgPSBibkJpdENvdW50O1xuQmlnSW50ZWdlci5wcm90b3R5cGUudGVzdEJpdCA9IGJuVGVzdEJpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnNldEJpdCA9IGJuU2V0Qml0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuY2xlYXJCaXQgPSBibkNsZWFyQml0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZmxpcEJpdCA9IGJuRmxpcEJpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmFkZCA9IGJuQWRkO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc3VidHJhY3QgPSBiblN1YnRyYWN0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUubXVsdGlwbHkgPSBibk11bHRpcGx5O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZGl2aWRlID0gYm5EaXZpZGU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5yZW1haW5kZXIgPSBiblJlbWFpbmRlcjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRpdmlkZUFuZFJlbWFpbmRlciA9IGJuRGl2aWRlQW5kUmVtYWluZGVyO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubW9kUG93ID0gYm5Nb2RQb3c7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tb2RJbnZlcnNlID0gYm5Nb2RJbnZlcnNlO1xuQmlnSW50ZWdlci5wcm90b3R5cGUucG93ID0gYm5Qb3c7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5nY2QgPSBibkdDRDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmlzUHJvYmFibGVQcmltZSA9IGJuSXNQcm9iYWJsZVByaW1lO1xuQmlnSW50ZWdlci5wcm90b3R5cGUudG9NUEkgPSBiblRvTVBJO1xuXG4vLyBKU0JOLXNwZWNpZmljIGV4dGVuc2lvblxuQmlnSW50ZWdlci5wcm90b3R5cGUuc3F1YXJlID0gYm5TcXVhcmU7XG5cblxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0Fcbi8vXG4vLyBSU0EgaW1wbGVtZW50YXRpb25cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2pzYm4uanMnKSxcblx0dXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKSxcblx0cmFuZG9tID0gcmVxdWlyZSgnLi4vcmFuZG9tLmpzJyk7XG5cbmZ1bmN0aW9uIFNlY3VyZVJhbmRvbSgpe1xuICAgIGZ1bmN0aW9uIG5leHRCeXRlcyhieXRlQXJyYXkpe1xuICAgICAgICBmb3IodmFyIG4gPSAwOyBuIDwgYnl0ZUFycmF5Lmxlbmd0aDtuKyspe1xuICAgICAgICAgICAgYnl0ZUFycmF5W25dID0gcmFuZG9tLmdldFNlY3VyZVJhbmRvbU9jdGV0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5uZXh0Qnl0ZXMgPSBuZXh0Qnl0ZXM7XG59XG5cbmZ1bmN0aW9uIFJTQSgpIHtcblx0LyoqXG5cdCAqIFRoaXMgZnVuY3Rpb24gdXNlcyBqc2JuIEJpZyBOdW0gbGlicmFyeSB0byBkZWNyeXB0IFJTQVxuXHQgKiBAcGFyYW0gbVxuXHQgKiAgICAgICAgICAgIG1lc3NhZ2Vcblx0ICogQHBhcmFtIGRcblx0ICogICAgICAgICAgICBSU0EgZCBhcyBCaWdJbnRlZ2VyXG5cdCAqIEBwYXJhbSBwXG5cdCAqICAgICAgICAgICAgUlNBIHAgYXMgQmlnSW50ZWdlclxuXHQgKiBAcGFyYW0gcVxuXHQgKiAgICAgICAgICAgIFJTQSBxIGFzIEJpZ0ludGVnZXJcblx0ICogQHBhcmFtIHVcblx0ICogICAgICAgICAgICBSU0EgdSBhcyBCaWdJbnRlZ2VyXG5cdCAqIEByZXR1cm4ge0JpZ0ludGVnZXJ9IFRoZSBkZWNyeXB0ZWQgdmFsdWUgb2YgdGhlIG1lc3NhZ2Vcblx0ICovXG5cdGZ1bmN0aW9uIGRlY3J5cHQobSwgZCwgcCwgcSwgdSkge1xuXHRcdHZhciB4cCA9IG0ubW9kKHApLm1vZFBvdyhkLm1vZChwLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKSksIHApO1xuXHRcdHZhciB4cSA9IG0ubW9kKHEpLm1vZFBvdyhkLm1vZChxLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKSksIHEpO1xuXHRcdHV0aWwucHJpbnRfZGVidWcoXCJyc2EuanMgZGVjcnlwdFxcbnhwbjpcIit1dGlsLmhleHN0cmR1bXAoeHAudG9NUEkoKSkrXCJcXG54cW46XCIrdXRpbC5oZXhzdHJkdW1wKHhxLnRvTVBJKCkpKTtcblxuXHRcdHZhciB0ID0geHEuc3VidHJhY3QoeHApO1xuXHRcdGlmICh0WzBdID09IDApIHtcblx0XHRcdHQgPSB4cC5zdWJ0cmFjdCh4cSk7XG5cdFx0XHR0ID0gdC5tdWx0aXBseSh1KS5tb2QocSk7XG5cdFx0XHR0ID0gcS5zdWJ0cmFjdCh0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dCA9IHQubXVsdGlwbHkodSkubW9kKHEpO1xuXHRcdH1cblx0XHRyZXR1cm4gdC5tdWx0aXBseShwKS5hZGQoeHApO1xuXHR9XG5cdFxuXHQvKipcblx0ICogZW5jcnlwdCBtZXNzYWdlXG5cdCAqIEBwYXJhbSBtIG1lc3NhZ2UgYXMgQmlnSW50ZWdlclxuXHQgKiBAcGFyYW0gZSBwdWJsaWMgTVBJIHBhcnQgYXMgQmlnSW50ZWdlclxuXHQgKiBAcGFyYW0gbiBwdWJsaWMgTVBJIHBhcnQgYXMgQmlnSW50ZWdlclxuXHQgKiBAcmV0dXJuIEJpZ0ludGVnZXJcblx0ICovXG5cdGZ1bmN0aW9uIGVuY3J5cHQobSxlLG4pIHtcblx0XHRyZXR1cm4gbS5tb2RQb3dJbnQoZSwgbik7XG5cdH1cblx0XG5cdC8qIFNpZ24gYW5kIFZlcmlmeSAqL1xuXHRmdW5jdGlvbiBzaWduKG0sZCxuKSB7XG5cdFx0cmV0dXJuIG0ubW9kUG93KGQsIG4pO1xuXHR9XG5cdFx0XG5cdGZ1bmN0aW9uIHZlcmlmeSh4LGUsbikge1xuXHRcdHJldHVybiB4Lm1vZFBvd0ludChlLCBuKTtcblx0fVxuXHRcblx0Ly8gXCJlbXB0eVwiIFJTQSBrZXkgY29uc3RydWN0b3JcbiAgICBmdW5jdGlvbiBrZXlPYmplY3QoKSB7XG4gICAgICAgIHRoaXMubiA9IG51bGw7XG4gICAgICAgIHRoaXMuZSA9IDA7XG4gICAgICAgIHRoaXMuZWUgPSBudWxsO1xuICAgICAgICB0aGlzLmQgPSBudWxsO1xuICAgICAgICB0aGlzLnAgPSBudWxsO1xuICAgICAgICB0aGlzLnEgPSBudWxsO1xuICAgICAgICB0aGlzLmRtcDEgPSBudWxsO1xuICAgICAgICB0aGlzLmRtcTEgPSBudWxsO1xuICAgICAgICB0aGlzLnUgPSBudWxsO1xuICAgIH1cblx0XG5cdC8vIEdlbmVyYXRlIGEgbmV3IHJhbmRvbSBwcml2YXRlIGtleSBCIGJpdHMgbG9uZywgdXNpbmcgcHVibGljIGV4cHQgRVxuICAgIGZ1bmN0aW9uIGdlbmVyYXRlKEIsRSkge1xuICAgICAgICB2YXIga2V5ID0gbmV3IGtleU9iamVjdCgpO1xuICAgICAgICB2YXIgcm5nID0gbmV3IFNlY3VyZVJhbmRvbSgpO1xuICAgICAgICB2YXIgcXMgPSBCPj4xO1xuICAgICAgICBrZXkuZSA9IHBhcnNlSW50KEUsMTYpO1xuICAgICAgICBrZXkuZWUgPSBuZXcgQmlnSW50ZWdlcihFLDE2KTtcbiAgICAgICAgZm9yKDs7KSB7XG4gICAgICAgICAgICBmb3IoOzspIHtcbiAgICAgICAgICAgICAgICBrZXkucCA9IG5ldyBCaWdJbnRlZ2VyKEItcXMsMSxybmcpO1xuICAgICAgICAgICAgICAgIGlmKGtleS5wLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKS5nY2Qoa2V5LmVlKS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpID09IDAgJiYga2V5LnAuaXNQcm9iYWJsZVByaW1lKDEwKSkgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IoOzspIHtcbiAgICAgICAgICAgICAgICBrZXkucSA9IG5ldyBCaWdJbnRlZ2VyKHFzLDEscm5nKTtcbiAgICAgICAgICAgICAgICBpZihrZXkucS5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkuZ2NkKGtleS5lZSkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA9PSAwICYmIGtleS5xLmlzUHJvYmFibGVQcmltZSgxMCkpIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYoa2V5LnAuY29tcGFyZVRvKGtleS5xKSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIHQgPSBrZXkucDtcbiAgICAgICAgICAgICAgICBrZXkucCA9IGtleS5xO1xuICAgICAgICAgICAgICAgIGtleS5xID0gdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwMSA9IGtleS5wLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKTtcbiAgICAgICAgICAgIHZhciBxMSA9IGtleS5xLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKTtcbiAgICAgICAgICAgIHZhciBwaGkgPSBwMS5tdWx0aXBseShxMSk7XG4gICAgICAgICAgICBpZihwaGkuZ2NkKGtleS5lZSkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA9PSAwKSB7XG4gICAgICAgICAgICAgICAga2V5Lm4gPSBrZXkucC5tdWx0aXBseShrZXkucSk7XG4gICAgICAgICAgICAgICAga2V5LmQgPSBrZXkuZWUubW9kSW52ZXJzZShwaGkpO1xuICAgICAgICAgICAgICAgIGtleS5kbXAxID0ga2V5LmQubW9kKHAxKTtcbiAgICAgICAgICAgICAgICBrZXkuZG1xMSA9IGtleS5kLm1vZChxMSk7XG4gICAgICAgICAgICAgICAga2V5LnUgPSBrZXkucC5tb2RJbnZlcnNlKGtleS5xKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4ga2V5O1xuICAgIH1cblx0XHRcblx0dGhpcy5lbmNyeXB0ID0gZW5jcnlwdDtcblx0dGhpcy5kZWNyeXB0ID0gZGVjcnlwdDtcblx0dGhpcy52ZXJpZnkgPSB2ZXJpZnk7XG5cdHRoaXMuc2lnbiA9IHNpZ247XG5cdHRoaXMuZ2VuZXJhdGUgPSBnZW5lcmF0ZTtcblx0dGhpcy5rZXlPYmplY3QgPSBrZXlPYmplY3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gUlNBO1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0EgXG5cbi8vIFRoZSBHUEc0QnJvd3NlcnMgY3J5cHRvIGludGVyZmFjZVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0LyoqXG5cdCAqIFJldHJpZXZlIHNlY3VyZSByYW5kb20gYnl0ZSBzdHJpbmcgb2YgdGhlIHNwZWNpZmllZCBsZW5ndGhcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5ndGggTGVuZ3RoIGluIGJ5dGVzIHRvIGdlbmVyYXRlXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gUmFuZG9tIGJ5dGUgc3RyaW5nXG5cdCAqL1xuXHRnZXRSYW5kb21CeXRlczogZnVuY3Rpb24obGVuZ3RoKSB7XG5cdFx0dmFyIHJlc3VsdCA9ICcnO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcblx0XHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMuZ2V0U2VjdXJlUmFuZG9tT2N0ZXQoKSk7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0LyoqXG5cdCAqIFJldHVybiBhIHBzZXVkby1yYW5kb20gbnVtYmVyIGluIHRoZSBzcGVjaWZpZWQgcmFuZ2Vcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBmcm9tIE1pbiBvZiB0aGUgcmFuZG9tIG51bWJlclxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHRvIE1heCBvZiB0aGUgcmFuZG9tIG51bWJlciAobWF4IDMyYml0KVxuXHQgKiBAcmV0dXJuIHtJbnRlZ2VyfSBBIHBzZXVkbyByYW5kb20gbnVtYmVyXG5cdCAqL1xuXHRnZXRQc2V1ZG9SYW5kb206IGZ1bmN0aW9uKGZyb20sIHRvKSB7XG5cdFx0cmV0dXJuIE1hdGgucm91bmQoTWF0aC5yYW5kb20oKSoodG8tZnJvbSkpK2Zyb207XG5cdH0sXG5cblx0LyoqXG5cdCAqIFJldHVybiBhIHNlY3VyZSByYW5kb20gbnVtYmVyIGluIHRoZSBzcGVjaWZpZWQgcmFuZ2Vcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBmcm9tIE1pbiBvZiB0aGUgcmFuZG9tIG51bWJlclxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHRvIE1heCBvZiB0aGUgcmFuZG9tIG51bWJlciAobWF4IDMyYml0KVxuXHQgKiBAcmV0dXJuIHtJbnRlZ2VyfSBBIHNlY3VyZSByYW5kb20gbnVtYmVyXG5cdCAqL1xuXHRnZXRTZWN1cmVSYW5kb206IGZ1bmN0aW9uKGZyb20sIHRvKSB7XG5cdFx0dmFyIGJ1ZiA9IG5ldyBVaW50MzJBcnJheSgxKTtcblx0XHR3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhidWYpO1xuXHRcdHZhciBiaXRzID0gKCh0by1mcm9tKSkudG9TdHJpbmcoMikubGVuZ3RoO1xuXHRcdHdoaWxlICgoYnVmWzBdICYgKE1hdGgucG93KDIsIGJpdHMpIC0xKSkgPiAodG8tZnJvbSkpXG5cdFx0XHR3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhidWYpO1xuXHRcdHJldHVybiBmcm9tKyhNYXRoLmFicyhidWZbMF0gJiAoTWF0aC5wb3coMiwgYml0cykgLTEpKSk7XG5cdH0sXG5cblx0Z2V0U2VjdXJlUmFuZG9tT2N0ZXQ6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBidWYgPSBuZXcgVWludDMyQXJyYXkoMSk7XG5cdFx0d2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYnVmKTtcblx0XHRyZXR1cm4gYnVmWzBdICYgMHhGRjtcblx0fVxufVxuIiwiXG52YXIgcHVibGljS2V5ID0gcmVxdWlyZSgnLi9wdWJsaWNfa2V5JyksXG5cdHBrY3MxID0gcmVxdWlyZSgnLi9wa2NzMS5qcycpLFxuXHRoYXNoTW9kdWxlID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHQvKipcblx0ICogXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gYWxnbyBwdWJsaWMgS2V5IGFsZ29yaXRobVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGhhc2hfYWxnbyBIYXNoIGFsZ29yaXRobVxuXHQgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gbXNnX01QSXMgU2lnbmF0dXJlIG11bHRpcHJlY2lzaW9uIGludGVnZXJzXG5cdCAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBwdWJsaWNrZXlfTVBJcyBQdWJsaWMga2V5IG11bHRpcHJlY2lzaW9uIGludGVnZXJzIFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIG9uIHdoZXJlIHRoZSBzaWduYXR1cmUgd2FzIGNvbXB1dGVkIG9uLlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHNpZ25hdHVyZSAoc2lnX2RhdGEgd2FzIGVxdWFsIHRvIGRhdGEgb3ZlciBoYXNoKVxuXHQgKi9cblx0dmVyaWZ5OiBmdW5jdGlvbihhbGdvLCBoYXNoX2FsZ28sIG1zZ19NUElzLCBwdWJsaWNrZXlfTVBJcywgZGF0YSkge1xuXHRcdHZhciBjYWxjX2hhc2ggPSBoYXNoTW9kdWxlLmRpZ2VzdChoYXNoX2FsZ28sIGRhdGEpO1xuXG5cdFx0c3dpdGNoKGFsZ28pIHtcblx0XHRjYXNlIDE6IC8vIFJTQSAoRW5jcnlwdCBvciBTaWduKSBbSEFDXSAgXG5cdFx0Y2FzZSAyOiAvLyBSU0EgRW5jcnlwdC1Pbmx5IFtIQUNdXG5cdFx0Y2FzZSAzOiAvLyBSU0EgU2lnbi1Pbmx5IFtIQUNdXG5cdFx0XHR2YXIgcnNhID0gbmV3IHB1YmxpY0tleS5yc2EoKTtcblx0XHRcdHZhciBuID0gcHVibGlja2V5X01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG5cdFx0XHR2YXIgZSA9IHB1YmxpY2tleV9NUElzWzFdLnRvQmlnSW50ZWdlcigpO1xuXHRcdFx0dmFyIHggPSBtc2dfTVBJc1swXS50b0JpZ0ludGVnZXIoKTtcblx0XHRcdHZhciBkb3B1YmxpYyA9IHJzYS52ZXJpZnkoeCxlLG4pO1xuXHRcdFx0dmFyIGhhc2ggID0gcGtjczEuZW1zYS5kZWNvZGUoaGFzaF9hbGdvLGRvcHVibGljLnRvTVBJKCkuc3Vic3RyaW5nKDIpKTtcblx0XHRcdGlmIChoYXNoID09IC0xKSB7XG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcignUEtDUzEgcGFkZGluZyBpbiBtZXNzYWdlIG9yIGtleSBpbmNvcnJlY3QuIEFib3J0aW5nLi4uJyk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gaGFzaCA9PSBjYWxjX2hhc2g7XG5cdFx0XHRcblx0XHRjYXNlIDE2OiAvLyBFbGdhbWFsIChFbmNyeXB0LU9ubHkpIFtFTEdBTUFMXSBbSEFDXVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKFwic2lnbmluZyB3aXRoIEVsZ2FtYWwgaXMgbm90IGRlZmluZWQgaW4gdGhlIE9wZW5QR1Agc3RhbmRhcmQuXCIpO1xuXHRcdGNhc2UgMTc6IC8vIERTQSAoRGlnaXRhbCBTaWduYXR1cmUgQWxnb3JpdGhtKSBbRklQUzE4Nl0gW0hBQ11cblx0XHRcdHZhciBkc2EgPSBuZXcgcHVibGljS2V5LmRzYSgpO1xuXHRcdFx0dmFyIHMxID0gbXNnX01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG5cdFx0XHR2YXIgczIgPSBtc2dfTVBJc1sxXS50b0JpZ0ludGVnZXIoKTtcblx0XHRcdHZhciBwID0gcHVibGlja2V5X01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG5cdFx0XHR2YXIgcSA9IHB1YmxpY2tleV9NUElzWzFdLnRvQmlnSW50ZWdlcigpO1xuXHRcdFx0dmFyIGcgPSBwdWJsaWNrZXlfTVBJc1syXS50b0JpZ0ludGVnZXIoKTtcblx0XHRcdHZhciB5ID0gcHVibGlja2V5X01QSXNbM10udG9CaWdJbnRlZ2VyKCk7XG5cdFx0XHR2YXIgbSA9IGRhdGE7XG5cdFx0XHR2YXIgZG9wdWJsaWMgPSBkc2EudmVyaWZ5KGhhc2hfYWxnbyxzMSxzMixtLHAscSxnLHkpO1xuXHRcdFx0cmV0dXJuIGRvcHVibGljLmNvbXBhcmVUbyhzMSkgPT0gMDtcblx0XHRkZWZhdWx0OlxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpZ25hdHVyZSBhbGdvcml0aG0uJyk7XG5cdFx0fVxuXHRcdFxuXHR9LFxuXHQgICBcblx0LyoqXG5cdCAqIENyZWF0ZSBhIHNpZ25hdHVyZSBvbiBkYXRhIHVzaW5nIHRoZSBzcGVjaWZpZWQgYWxnb3JpdGhtXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gaGFzaF9hbGdvIGhhc2ggQWxnb3JpdGhtIHRvIHVzZSAoU2VlIFJGQzQ4ODAgOS40KVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQXN5bW1ldHJpYyBjaXBoZXIgYWxnb3JpdGhtIHRvIHVzZSAoU2VlIFJGQzQ4ODAgOS4xKVxuXHQgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gcHVibGljTVBJcyBQdWJsaWMga2V5IG11bHRpcHJlY2lzaW9uIGludGVnZXJzIFxuXHQgKiBvZiB0aGUgcHJpdmF0ZSBrZXkgXG5cdCAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBzZWNyZXRNUElzIFByaXZhdGUga2V5IG11bHRpcHJlY2lzaW9uIFxuXHQgKiBpbnRlZ2VycyB3aGljaCBpcyB1c2VkIHRvIHNpZ24gdGhlIGRhdGFcblx0ICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBiZSBzaWduZWRcblx0ICogQHJldHVybiB7b3BlbnBncF90eXBlX21waVtdfVxuXHQgKi9cblx0c2lnbjogZnVuY3Rpb24oaGFzaF9hbGdvLCBhbGdvLCBrZXlJbnRlZ2VycywgZGF0YSkge1xuXHRcdFxuXHRcdHN3aXRjaChhbGdvKSB7XG5cdFx0Y2FzZSAxOiAvLyBSU0EgKEVuY3J5cHQgb3IgU2lnbikgW0hBQ10gIFxuXHRcdGNhc2UgMjogLy8gUlNBIEVuY3J5cHQtT25seSBbSEFDXVxuXHRcdGNhc2UgMzogLy8gUlNBIFNpZ24tT25seSBbSEFDXVxuXHRcdFx0dmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG5cdFx0XHR2YXIgZCA9IGtleUludGVnZXJzWzJdLnRvQmlnSW50ZWdlcigpO1xuXHRcdFx0dmFyIG4gPSBrZXlJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcblx0XHRcdHZhciBtID0gcGtjczEuZW1zYS5lbmNvZGUoaGFzaF9hbGdvLCBcblx0XHRcdFx0ZGF0YSwga2V5SW50ZWdlcnNbMF0uYnl0ZUxlbmd0aCgpKTtcblxuXHRcdFx0cmV0dXJuIHJzYS5zaWduKG0sIGQsIG4pLnRvTVBJKCk7XG5cblx0XHRjYXNlIDE3OiAvLyBEU0EgKERpZ2l0YWwgU2lnbmF0dXJlIEFsZ29yaXRobSkgW0ZJUFMxODZdIFtIQUNdXG5cdFx0XHR2YXIgZHNhID0gbmV3IHB1YmxpY0tleS5kc2EoKTtcblxuXHRcdFx0dmFyIHAgPSBrZXlJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcblx0XHRcdHZhciBxID0ga2V5SW50ZWdlcnNbMV0udG9CaWdJbnRlZ2VyKCk7XG5cdFx0XHR2YXIgZyA9IGtleUludGVnZXJzWzJdLnRvQmlnSW50ZWdlcigpO1xuXHRcdFx0dmFyIHkgPSBrZXlJbnRlZ2Vyc1szXS50b0JpZ0ludGVnZXIoKTtcblx0XHRcdHZhciB4ID0ga2V5SW50ZWdlcnNbNF0udG9CaWdJbnRlZ2VyKCk7XG5cdFx0XHR2YXIgbSA9IGRhdGE7XG5cdFx0XHR2YXIgcmVzdWx0ID0gZHNhLnNpZ24oaGFzaF9hbGdvLG0sIGcsIHAsIHEsIHgpO1xuXG5cdFx0XHRyZXR1cm4gcmVzdWx0WzBdLnRvU3RyaW5nKCkgKyByZXN1bHRbMV0udG9TdHJpbmcoKTtcblx0XHRjYXNlIDE2OiAvLyBFbGdhbWFsIChFbmNyeXB0LU9ubHkpIFtFTEdBTUFMXSBbSEFDXVxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdTaWduaW5nIHdpdGggRWxnYW1hbCBpcyBub3QgZGVmaW5lZCBpbiB0aGUgT3BlblBHUCBzdGFuZGFyZC4nKTtcblx0XHRkZWZhdWx0OlxuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpZ25hdHVyZSBhbGdvcml0aG0uJyk7XG5cdFx0fVx0XG5cdH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy9cbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vL1xuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vL1xuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCcuL2Jhc2U2NC5qcycpO1xuXG5cblxuLyoqXG4gKiBGaW5kcyBvdXQgd2hpY2ggQXNjaWkgQXJtb3JpbmcgdHlwZSBpcyB1c2VkLiBUaGlzIGlzIGFuIGludGVybmFsIGZ1bmN0aW9uXG4gKiBAcGFyYW0ge1N0cmluZ30gdGV4dCBbU3RyaW5nXSBhc2NpaSBhcm1vcmVkIHRleHRcbiAqIEByZXR1cm5zIHtJbnRlZ2VyfSAwID0gTUVTU0FHRSBQQVJUIG4gb2YgbVxuICogICAgICAgICAxID0gTUVTU0FHRSBQQVJUIG5cbiAqICAgICAgICAgMiA9IFNJR05FRCBNRVNTQUdFXG4gKiAgICAgICAgIDMgPSBQR1AgTUVTU0FHRVxuICogICAgICAgICA0ID0gUFVCTElDIEtFWSBCTE9DS1xuICogICAgICAgICA1ID0gUFJJVkFURSBLRVkgQkxPQ0tcbiAqICAgICAgICAgbnVsbCA9IHVua25vd25cbiAqL1xuZnVuY3Rpb24gZ2V0X3R5cGUodGV4dCkge1xuXHR2YXIgc3BsaXR0ZWR0ZXh0ID0gdGV4dC5zcGxpdCgnLS0tLS0nKTtcblx0Ly8gQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgWC9ZXG5cdC8vIFVzZWQgZm9yIG11bHRpLXBhcnQgbWVzc2FnZXMsIHdoZXJlIHRoZSBhcm1vciBpcyBzcGxpdCBhbW9uZ3N0IFlcblx0Ly8gcGFydHMsIGFuZCB0aGlzIGlzIHRoZSBYdGggcGFydCBvdXQgb2YgWS5cblx0aWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgXFxkK1xcL1xcZCsvKSkge1xuXHRcdHJldHVybiAwO1xuXHR9IGVsc2Vcblx0XHQvLyBCRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBYXG5cdFx0Ly8gVXNlZCBmb3IgbXVsdGktcGFydCBtZXNzYWdlcywgd2hlcmUgdGhpcyBpcyB0aGUgWHRoIHBhcnQgb2YgYW5cblx0XHQvLyB1bnNwZWNpZmllZCBudW1iZXIgb2YgcGFydHMuIFJlcXVpcmVzIHRoZSBNRVNTQUdFLUlEIEFybW9yXG5cdFx0Ly8gSGVhZGVyIHRvIGJlIHVzZWQuXG5cdGlmIChzcGxpdHRlZHRleHRbMV0ubWF0Y2goL0JFR0lOIFBHUCBNRVNTQUdFLCBQQVJUIFxcZCsvKSkge1xuXHRcdHJldHVybiAxO1xuXG5cdH0gZWxzZVxuXHRcdC8vIEJFR0lOIFBHUCBTSUdOQVRVUkVcblx0XHQvLyBVc2VkIGZvciBkZXRhY2hlZCBzaWduYXR1cmVzLCBPcGVuUEdQL01JTUUgc2lnbmF0dXJlcywgYW5kXG5cdFx0Ly8gY2xlYXJ0ZXh0IHNpZ25hdHVyZXMuIE5vdGUgdGhhdCBQR1AgMi54IHVzZXMgQkVHSU4gUEdQIE1FU1NBR0Vcblx0XHQvLyBmb3IgZGV0YWNoZWQgc2lnbmF0dXJlcy5cblx0aWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIFNJR05FRCBNRVNTQUdFLykpIHtcblx0XHRyZXR1cm4gMjtcblxuXHR9IGVsc2VcbiAgXHQgICAgLy8gQkVHSU4gUEdQIE1FU1NBR0Vcblx0ICAgIC8vIFVzZWQgZm9yIHNpZ25lZCwgZW5jcnlwdGVkLCBvciBjb21wcmVzc2VkIGZpbGVzLlxuXHRpZiAoc3BsaXR0ZWR0ZXh0WzFdLm1hdGNoKC9CRUdJTiBQR1AgTUVTU0FHRS8pKSB7XG5cdFx0cmV0dXJuIDM7XG5cblx0fSBlbHNlXG5cdFx0Ly8gQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0tcblx0XHQvLyBVc2VkIGZvciBhcm1vcmluZyBwdWJsaWMga2V5cy5cblx0aWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0svKSkge1xuXHRcdHJldHVybiA0O1xuXG5cdH0gZWxzZVxuXHRcdC8vIEJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DS1xuXHRcdC8vIFVzZWQgZm9yIGFybW9yaW5nIHByaXZhdGUga2V5cy5cblx0aWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIFBSSVZBVEUgS0VZIEJMT0NLLykpIHtcblx0XHRyZXR1cm4gNTtcblx0fVxufVxuXG4vKipcbiAqIEFkZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHRvIHRoZSBhcm1vciB2ZXJzaW9uIG9mIGFuIE9wZW5QR1AgYmluYXJ5XG4gKiBwYWNrZXQgYmxvY2suXG4gKiBAYXV0aG9yICBBbGV4XG4gKiBAdmVyc2lvbiAyMDExLTEyLTE2XG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgaGVhZGVyIGluZm9ybWF0aW9uXG4gKi9cbmZ1bmN0aW9uIGFybW9yX2FkZGhlYWRlcigpIHtcbiAgICB2YXIgcmVzdWx0ID0gXCJcIjtcblx0aWYgKG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5zaG93X3ZlcnNpb24pIHtcbiAgICAgICAgcmVzdWx0ICs9IFwiVmVyc2lvbjogXCIrb3BlbnBncC5jb25maWcudmVyc2lvbnN0cmluZysnXFxyXFxuJztcbiAgICB9XG5cdGlmIChvcGVucGdwLmNvbmZpZy5jb25maWcuc2hvd19jb21tZW50KSB7XG4gICAgICAgIHJlc3VsdCArPSBcIkNvbW1lbnQ6IFwiK29wZW5wZ3AuY29uZmlnLmNvbW1lbnRzdHJpbmcrJ1xcclxcbic7XG4gICAgfVxuICAgIHJlc3VsdCArPSAnXFxyXFxuJztcbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5cblxuLyoqXG4gKiBDYWxjdWxhdGVzIGEgY2hlY2tzdW0gb3ZlciB0aGUgZ2l2ZW4gZGF0YSBhbmQgcmV0dXJucyBpdCBiYXNlNjQgZW5jb2RlZFxuICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBjcmVhdGUgYSBDUkMtMjQgY2hlY2tzdW0gZm9yXG4gKiBAcmV0dXJuIHtTdHJpbmd9IEJhc2U2NCBlbmNvZGVkIGNoZWNrc3VtXG4gKi9cbmZ1bmN0aW9uIGdldENoZWNrU3VtKGRhdGEpIHtcblx0dmFyIGMgPSBjcmVhdGVjcmMyNChkYXRhKTtcblx0dmFyIHN0ciA9IFwiXCIgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGMgPj4gMTYpK1xuXHRcdFx0XHQgICBTdHJpbmcuZnJvbUNoYXJDb2RlKChjID4+IDgpICYgMHhGRikrXG5cdFx0XHRcdCAgIFN0cmluZy5mcm9tQ2hhckNvZGUoYyAmIDB4RkYpO1xuXHRyZXR1cm4gYmFzZTY0LmVuY29kZShzdHIpO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGNoZWNrc3VtIG92ZXIgdGhlIGdpdmVuIGRhdGEgYW5kIGNvbXBhcmVzIGl0IHdpdGggdGhlIFxuICogZ2l2ZW4gYmFzZTY0IGVuY29kZWQgY2hlY2tzdW1cbiAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIERhdGEgdG8gY3JlYXRlIGEgQ1JDLTI0IGNoZWNrc3VtIGZvclxuICogQHBhcmFtIHtTdHJpbmd9IGNoZWNrc3VtIEJhc2U2NCBlbmNvZGVkIGNoZWNrc3VtXG4gKiBAcmV0dXJuIHtCb29sZWFufSBUcnVlIGlmIHRoZSBnaXZlbiBjaGVja3N1bSBpcyBjb3JyZWN0OyBvdGhlcndpc2UgZmFsc2VcbiAqL1xuZnVuY3Rpb24gdmVyaWZ5Q2hlY2tTdW0oZGF0YSwgY2hlY2tzdW0pIHtcblx0dmFyIGMgPSBnZXRDaGVja1N1bShkYXRhKTtcblx0dmFyIGQgPSBjaGVja3N1bTtcblx0cmV0dXJuIGNbMF0gPT0gZFswXSAmJiBjWzFdID09IGRbMV0gJiYgY1syXSA9PSBkWzJdO1xufVxuLyoqXG4gKiBJbnRlcm5hbCBmdW5jdGlvbiB0byBjYWxjdWxhdGUgYSBDUkMtMjQgY2hlY2tzdW0gb3ZlciBhIGdpdmVuIHN0cmluZyAoZGF0YSlcbiAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIERhdGEgdG8gY3JlYXRlIGEgQ1JDLTI0IGNoZWNrc3VtIGZvclxuICogQHJldHVybiB7SW50ZWdlcn0gVGhlIENSQy0yNCBjaGVja3N1bSBhcyBudW1iZXJcbiAqL1xudmFyIGNyY190YWJsZSA9IFtcbjB4MDAwMDAwMDAsIDB4MDA4NjRjZmIsIDB4MDE4YWQ1MGQsIDB4MDEwYzk5ZjYsIDB4MDM5M2U2ZTEsIDB4MDMxNWFhMWEsIDB4MDIxOTMzZWMsIDB4MDI5ZjdmMTcsIDB4MDdhMTgxMzksIDB4MDcyN2NkYzIsIDB4MDYyYjU0MzQsIDB4MDZhZDE4Y2YsIDB4MDQzMjY3ZDgsIDB4MDRiNDJiMjMsIDB4MDViOGIyZDUsIDB4MDUzZWZlMmUsIDB4MGZjNTRlODksIDB4MGY0MzAyNzIsIDB4MGU0ZjliODQsIDB4MGVjOWQ3N2YsIDB4MGM1NmE4NjgsIDB4MGNkMGU0OTMsIDB4MGRkYzdkNjUsIDB4MGQ1YTMxOWUsIDB4MDg2NGNmYjAsIDB4MDhlMjgzNGIsIDB4MDllZTFhYmQsIDB4MDk2ODU2NDYsIDB4MGJmNzI5NTEsIDB4MGI3MTY1YWEsIDB4MGE3ZGZjNWMsIDB4MGFmYmIwYTcsIDB4MWYwY2QxZTksIDB4MWY4YTlkMTIsIDB4MWU4NjA0ZTQsIDB4MWUwMDQ4MWYsIDB4MWM5ZjM3MDgsIDB4MWMxOTdiZjMsIDB4MWQxNWUyMDUsIDB4MWQ5M2FlZmUsIDB4MThhZDUwZDAsIDB4MTgyYjFjMmIsIDB4MTkyNzg1ZGQsIDB4MTlhMWM5MjYsIDB4MWIzZWI2MzEsIDB4MWJiOGZhY2EsIDB4MWFiNDYzM2MsIDB4MWEzMjJmYzcsIDB4MTBjOTlmNjAsIDB4MTA0ZmQzOWIsIDB4MTE0MzRhNmQsIDB4MTFjNTA2OTYsIDB4MTM1YTc5ODEsIDB4MTNkYzM1N2EsIDB4MTJkMGFjOGMsIDB4MTI1NmUwNzcsIDB4MTc2ODFlNTksIDB4MTdlZTUyYTIsIDB4MTZlMmNiNTQsIDB4MTY2NDg3YWYsIDB4MTRmYmY4YjgsIDB4MTQ3ZGI0NDMsIDB4MTU3MTJkYjUsIDB4MTVmNzYxNGUsIDB4M2UxOWEzZDIsIDB4M2U5ZmVmMjksIDB4M2Y5Mzc2ZGYsIDB4M2YxNTNhMjQsIDB4M2Q4YTQ1MzMsIDB4M2QwYzA5YzgsIDB4M2MwMDkwM2UsIDB4M2M4NmRjYzUsIDB4MzliODIyZWIsIDB4MzkzZTZlMTAsIDB4MzgzMmY3ZTYsIDB4MzhiNGJiMWQsIDB4M2EyYmM0MGEsIDB4M2FhZDg4ZjEsIDB4M2JhMTExMDcsIDB4M2IyNzVkZmMsIDB4MzFkY2VkNWIsIDB4MzE1YWExYTAsXG4weDMwNTYzODU2LCAweDMwZDA3NGFkLCAweDMyNGYwYmJhLCAweDMyYzk0NzQxLCAweDMzYzVkZWI3LCAweDMzNDM5MjRjLCAweDM2N2Q2YzYyLCAweDM2ZmIyMDk5LCAweDM3ZjdiOTZmLCAweDM3NzFmNTk0LCAweDM1ZWU4YTgzLCAweDM1NjhjNjc4LCAweDM0NjQ1ZjhlLCAweDM0ZTIxMzc1LCAweDIxMTU3MjNiLCAweDIxOTMzZWMwLCAweDIwOWZhNzM2LCAweDIwMTllYmNkLCAweDIyODY5NGRhLCAweDIyMDBkODIxLCAweDIzMGM0MWQ3LCAweDIzOGEwZDJjLCAweDI2YjRmMzAyLCAweDI2MzJiZmY5LCAweDI3M2UyNjBmLCAweDI3Yjg2YWY0LCAweDI1MjcxNWUzLCAweDI1YTE1OTE4LCAweDI0YWRjMGVlLCAweDI0MmI4YzE1LCAweDJlZDAzY2IyLCAweDJlNTY3MDQ5LCAweDJmNWFlOWJmLCAweDJmZGNhNTQ0LCAweDJkNDNkYTUzLCAweDJkYzU5NmE4LCAweDJjYzkwZjVlLCAweDJjNGY0M2E1LCAweDI5NzFiZDhiLCAweDI5ZjdmMTcwLCAweDI4ZmI2ODg2LCAweDI4N2QyNDdkLCAweDJhZTI1YjZhLCAweDJhNjQxNzkxLCAweDJiNjg4ZTY3LCAweDJiZWVjMjljLCAweDdjMzM0N2E0LCAweDdjYjUwYjVmLCAweDdkYjk5MmE5LCAweDdkM2ZkZTUyLCAweDdmYTBhMTQ1LCAweDdmMjZlZGJlLCAweDdlMmE3NDQ4LCAweDdlYWMzOGIzLCAweDdiOTJjNjlkLCAweDdiMTQ4YTY2LCAweDdhMTgxMzkwLCAweDdhOWU1ZjZiLCAweDc4MDEyMDdjLCAweDc4ODc2Yzg3LCAweDc5OGJmNTcxLCAweDc5MGRiOThhLCAweDczZjYwOTJkLCAweDczNzA0NWQ2LCAweDcyN2NkYzIwLCAweDcyZmE5MGRiLCAweDcwNjVlZmNjLCAweDcwZTNhMzM3LCAweDcxZWYzYWMxLCAweDcxNjk3NjNhLCAweDc0NTc4ODE0LCAweDc0ZDFjNGVmLCAweDc1ZGQ1ZDE5LCAweDc1NWIxMWUyLCAweDc3YzQ2ZWY1LCAweDc3NDIyMjBlLCAweDc2NGViYmY4LCAweDc2YzhmNzAzLCAweDYzM2Y5NjRkLCAweDYzYjlkYWI2LCAweDYyYjU0MzQwLCAweDYyMzMwZmJiLFxuMHg2MGFjNzBhYywgMHg2MDJhM2M1NywgMHg2MTI2YTVhMSwgMHg2MWEwZTk1YSwgMHg2NDllMTc3NCwgMHg2NDE4NWI4ZiwgMHg2NTE0YzI3OSwgMHg2NTkyOGU4MiwgMHg2NzBkZjE5NSwgMHg2NzhiYmQ2ZSwgMHg2Njg3MjQ5OCwgMHg2NjAxNjg2MywgMHg2Y2ZhZDhjNCwgMHg2YzdjOTQzZiwgMHg2ZDcwMGRjOSwgMHg2ZGY2NDEzMiwgMHg2ZjY5M2UyNSwgMHg2ZmVmNzJkZSwgMHg2ZWUzZWIyOCwgMHg2ZTY1YTdkMywgMHg2YjViNTlmZCwgMHg2YmRkMTUwNiwgMHg2YWQxOGNmMCwgMHg2YTU3YzAwYiwgMHg2OGM4YmYxYywgMHg2ODRlZjNlNywgMHg2OTQyNmExMSwgMHg2OWM0MjZlYSwgMHg0MjJhZTQ3NiwgMHg0MmFjYTg4ZCwgMHg0M2EwMzE3YiwgMHg0MzI2N2Q4MCwgMHg0MWI5MDI5NywgMHg0MTNmNGU2YywgMHg0MDMzZDc5YSwgMHg0MGI1OWI2MSwgMHg0NThiNjU0ZiwgMHg0NTBkMjliNCwgMHg0NDAxYjA0MiwgMHg0NDg3ZmNiOSwgMHg0NjE4ODNhZSwgMHg0NjllY2Y1NSwgMHg0NzkyNTZhMywgMHg0NzE0MWE1OCwgMHg0ZGVmYWFmZiwgMHg0ZDY5ZTYwNCwgMHg0YzY1N2ZmMiwgMHg0Y2UzMzMwOSwgMHg0ZTdjNGMxZSwgMHg0ZWZhMDBlNSwgMHg0ZmY2OTkxMywgMHg0ZjcwZDVlOCwgMHg0YTRlMmJjNiwgMHg0YWM4NjczZCwgMHg0YmM0ZmVjYiwgMHg0YjQyYjIzMCwgMHg0OWRkY2QyNywgMHg0OTViODFkYywgMHg0ODU3MTgyYSwgMHg0OGQxNTRkMSwgMHg1ZDI2MzU5ZiwgMHg1ZGEwNzk2NCwgMHg1Y2FjZTA5MiwgMHg1YzJhYWM2OSwgMHg1ZWI1ZDM3ZSwgMHg1ZTMzOWY4NSwgMHg1ZjNmMDY3MywgMHg1ZmI5NGE4OCwgMHg1YTg3YjRhNiwgMHg1YTAxZjg1ZCwgMHg1YjBkNjFhYiwgMHg1YjhiMmQ1MCwgMHg1OTE0NTI0NywgMHg1OTkyMWViYywgMHg1ODllODc0YSwgMHg1ODE4Y2JiMSwgMHg1MmUzN2IxNiwgMHg1MjY1MzdlZCwgMHg1MzY5YWUxYiwgMHg1M2VmZTJlMCwgMHg1MTcwOWRmNywgMHg1MWY2ZDEwYyxcbjB4NTBmYTQ4ZmEsIDB4NTA3YzA0MDEsIDB4NTU0MmZhMmYsIDB4NTVjNGI2ZDQsIDB4NTRjODJmMjIsIDB4NTQ0ZTYzZDksIDB4NTZkMTFjY2UsIDB4NTY1NzUwMzUsIDB4NTc1YmM5YzMsIDB4NTdkZDg1MzhdO1xuXG5mdW5jdGlvbiBjcmVhdGVjcmMyNChpbnB1dCkge1xuICB2YXIgY3JjID0gMHhCNzA0Q0U7XG4gIHZhciBpbmRleCA9IDA7XG5cbiAgd2hpbGUoKGlucHV0Lmxlbmd0aCAtIGluZGV4KSA+IDE2KSAge1xuICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCsxKSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCsyKSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCszKSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCs0KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCs1KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCs2KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCs3KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCs4KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCs5KSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCsxMCkpICYgMHhmZl07XG4gICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXgrMTEpKSAmIDB4ZmZdO1xuICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4KzEyKSkgJiAweGZmXTtcbiAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCsxMykpICYgMHhmZl07XG4gICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXgrMTQpKSAmIDB4ZmZdO1xuICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4KzE1KSkgJiAweGZmXTtcbiAgIGluZGV4ICs9IDE2O1xuICB9XG5cbiAgZm9yKHZhciBqID0gaW5kZXg7IGogPCBpbnB1dC5sZW5ndGg7IGorKykge1xuICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4KyspKSAmIDB4ZmZdXG4gIH1cbiAgcmV0dXJuIGNyYyAmIDB4ZmZmZmZmO1xufVxuXG4vKipcbiAqIERlQXJtb3IgYW4gT3BlblBHUCBhcm1vcmVkIG1lc3NhZ2U7IHZlcmlmeSB0aGUgY2hlY2tzdW0gYW5kIHJldHVybiBcbiAqIHRoZSBlbmNvZGVkIGJ5dGVzXG4gKiBAcGFyYW0ge1N0cmluZ30gdGV4dCBPcGVuUEdQIGFybW9yZWQgbWVzc2FnZVxuICogQHJldHVybnMgeyhCb29sZWFufE9iamVjdCl9IEVpdGhlciBmYWxzZSBpbiBjYXNlIG9mIGFuIGVycm9yIFxuICogb3IgYW4gb2JqZWN0IHdpdGggYXR0cmlidXRlIFwidGV4dFwiIGNvbnRhaW5pbmcgdGhlIG1lc3NhZ2UgdGV4dFxuICogYW5kIGFuIGF0dHJpYnV0ZSBcIm9wZW5wZ3BcIiBjb250YWluaW5nIHRoZSBieXRlcy5cbiAqL1xuZnVuY3Rpb24gZGVhcm1vcih0ZXh0KSB7XG5cdHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcci9nLCAnJylcblxuXHR2YXIgdHlwZSA9IGdldF90eXBlKHRleHQpO1xuXG5cdGlmICh0eXBlICE9IDIpIHtcblx0XHR2YXIgc3BsaXR0ZWR0ZXh0ID0gdGV4dC5zcGxpdCgnLS0tLS0nKTtcblxuXHRcdHZhciBkYXRhID0geyBcblx0XHRcdG9wZW5wZ3A6IGJhc2U2NC5kZWNvZGUoXG5cdFx0XHRcdHNwbGl0dGVkdGV4dFsyXVxuXHRcdFx0XHRcdC5zcGxpdCgnXFxuXFxuJylbMV1cblx0XHRcdFx0XHQuc3BsaXQoXCJcXG49XCIpWzBdXG5cdFx0XHRcdFx0LnJlcGxhY2UoL1xcbi0gL2csXCJcXG5cIikpLFxuXHRcdFx0dHlwZTogdHlwZVxuXHRcdH07XG5cblx0XHRpZiAodmVyaWZ5Q2hlY2tTdW0oZGF0YS5vcGVucGdwLCBcblx0XHRcdHNwbGl0dGVkdGV4dFsyXVxuXHRcdFx0XHQuc3BsaXQoJ1xcblxcbicpWzFdXG5cdFx0XHRcdC5zcGxpdChcIlxcbj1cIilbMV1cblx0XHRcdFx0LnNwbGl0KCdcXG4nKVswXSkpXG5cblx0XHRcdHJldHVybiBkYXRhO1xuXHRcdGVsc2Uge1xuXHRcdFx0dXRpbC5wcmludF9lcnJvcihcIkFzY2lpIGFybW9yIGludGVncml0eSBjaGVjayBvbiBtZXNzYWdlIGZhaWxlZDogJ1wiXG5cdFx0XHRcdCsgc3BsaXR0ZWR0ZXh0WzJdXG5cdFx0XHRcdFx0LnNwbGl0KCdcXG5cXG4nKVsxXVxuXHRcdFx0XHRcdC5zcGxpdChcIlxcbj1cIilbMV1cblx0XHRcdFx0XHQuc3BsaXQoJ1xcbicpWzBdIFxuXHRcdFx0XHQrIFwiJyBzaG91bGQgYmUgJ1wiXG5cdFx0XHRcdCsgZ2V0Q2hlY2tTdW0oZGF0YSkpICsgXCInXCI7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9IGVsc2Uge1xuXHRcdHZhciBzcGxpdHRlZHRleHQgPSB0ZXh0LnNwbGl0KCctLS0tLScpO1xuXG5cdFx0dmFyIHJlc3VsdCA9IHtcblx0XHRcdHRleHQ6IHNwbGl0dGVkdGV4dFsyXVxuXHRcdFx0XHQucmVwbGFjZSgvXFxuLSAvZyxcIlxcblwiKVxuXHRcdFx0XHQuc3BsaXQoXCJcXG5cXG5cIilbMV0sXG5cdFx0XHRvcGVucGdwOiBiYXNlNjRfZGVjb2RlKHNwbGl0dGVkdGV4dFs0XVxuXHRcdFx0XHQuc3BsaXQoXCJcXG5cXG5cIilbMV1cblx0XHRcdFx0LnNwbGl0KFwiXFxuPVwiKVswXSksXG5cdFx0XHR0eXBlOiB0eXBlXG5cdFx0fTtcblxuXHRcdGlmICh2ZXJpZnlDaGVja1N1bShyZXN1bHQub3BlbnBncCwgc3BsaXR0ZWR0ZXh0WzRdXG5cdFx0XHQuc3BsaXQoXCJcXG5cXG5cIilbMV1cblx0XHRcdC5zcGxpdChcIlxcbj1cIilbMV0pKVxuXG5cdFx0XHRcdHJldHVybiByZXN1bHQ7XG5cdFx0ZWxzZSB7XG5cdFx0XHR1dGlsLnByaW50X2Vycm9yKFwiQXNjaWkgYXJtb3IgaW50ZWdyaXR5IGNoZWNrIG9uIG1lc3NhZ2UgZmFpbGVkXCIpO1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fVxufVxuXG5cbi8qKlxuICogQXJtb3IgYW4gT3BlblBHUCBiaW5hcnkgcGFja2V0IGJsb2NrXG4gKiBAcGFyYW0ge0ludGVnZXJ9IG1lc3NhZ2V0eXBlIHR5cGUgb2YgdGhlIG1lc3NhZ2VcbiAqIEBwYXJhbSBkYXRhXG4gKiBAcGFyYW0ge0ludGVnZXJ9IHBhcnRpbmRleFxuICogQHBhcmFtIHtJbnRlZ2VyfSBwYXJ0dG90YWxcbiAqIEByZXR1cm5zIHtTdHJpbmd9IEFybW9yZWQgdGV4dFxuICovXG5mdW5jdGlvbiBhcm1vcihtZXNzYWdldHlwZSwgZGF0YSwgcGFydGluZGV4LCBwYXJ0dG90YWwpIHtcblx0dmFyIHJlc3VsdCA9IFwiXCI7XG5cdHN3aXRjaChtZXNzYWdldHlwZSkge1xuXHRjYXNlIDA6XG5cdFx0cmVzdWx0ICs9IFwiLS0tLS1CRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBcIitwYXJ0aW5kZXgrXCIvXCIrcGFydHRvdGFsK1wiLS0tLS1cXHJcXG5cIjtcblx0XHRyZXN1bHQgKz0gYXJtb3JfYWRkaGVhZGVyKCk7XG5cdFx0cmVzdWx0ICs9IGJhc2U2NC5lbmNvZGUoZGF0YSk7XG5cdFx0cmVzdWx0ICs9IFwiXFxyXFxuPVwiK2dldENoZWNrU3VtKGRhdGEpK1wiXFxyXFxuXCI7XG5cdFx0cmVzdWx0ICs9IFwiLS0tLS1FTkQgUEdQIE1FU1NBR0UsIFBBUlQgXCIrcGFydGluZGV4K1wiL1wiK3BhcnR0b3RhbCtcIi0tLS0tXFxyXFxuXCI7XG5cdFx0YnJlYWs7XG5cdGNhc2UgMTpcblx0XHRyZXN1bHQgKz0gXCItLS0tLUJFR0lOIFBHUCBNRVNTQUdFLCBQQVJUIFwiK3BhcnRpbmRleCtcIi0tLS0tXFxyXFxuXCI7XG5cdFx0cmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuXHRcdHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGRhdGEpO1xuXHRcdHJlc3VsdCArPSBcIlxcclxcbj1cIitnZXRDaGVja1N1bShkYXRhKStcIlxcclxcblwiO1xuXHRcdHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBNRVNTQUdFLCBQQVJUIFwiK3BhcnRpbmRleCtcIi0tLS0tXFxyXFxuXCI7XG5cdFx0YnJlYWs7XG5cdGNhc2UgMjpcblx0XHRyZXN1bHQgKz0gXCJcXHJcXG4tLS0tLUJFR0lOIFBHUCBTSUdORUQgTUVTU0FHRS0tLS0tXFxyXFxuSGFzaDogXCIrZGF0YS5oYXNoK1wiXFxyXFxuXFxyXFxuXCI7XG5cdFx0cmVzdWx0ICs9IGRhdGEudGV4dC5yZXBsYWNlKC9cXG4tL2csXCJcXG4tIC1cIik7XG5cdFx0cmVzdWx0ICs9IFwiXFxyXFxuLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS1cXHJcXG5cIjtcblx0XHRyZXN1bHQgKz0gYXJtb3JfYWRkaGVhZGVyKCk7XG5cdFx0cmVzdWx0ICs9IGJhc2U2NC5lbmNvZGUoZGF0YS5vcGVucGdwKTtcblx0XHRyZXN1bHQgKz0gXCJcXHJcXG49XCIrZ2V0Q2hlY2tTdW0oZGF0YS5vcGVucGdwKStcIlxcclxcblwiO1xuXHRcdHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBTSUdOQVRVUkUtLS0tLVxcclxcblwiO1xuXHRcdGJyZWFrO1xuXHRjYXNlIDM6XG5cdFx0cmVzdWx0ICs9IFwiLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tXFxyXFxuXCI7XG5cdFx0cmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuXHRcdHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGRhdGEpO1xuXHRcdHJlc3VsdCArPSBcIlxcclxcbj1cIitnZXRDaGVja1N1bShkYXRhKStcIlxcclxcblwiO1xuXHRcdHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBNRVNTQUdFLS0tLS1cXHJcXG5cIjtcblx0XHRicmVhaztcblx0Y2FzZSA0OlxuXHRcdHJlc3VsdCArPSBcIi0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLVxcclxcblwiO1xuXHRcdHJlc3VsdCArPSBhcm1vcl9hZGRoZWFkZXIoKTtcblx0XHRyZXN1bHQgKz0gYmFzZTY0LmVuY29kZShkYXRhKTtcblx0XHRyZXN1bHQgKz0gXCJcXHJcXG49XCIrZ2V0Q2hlY2tTdW0oZGF0YSkrXCJcXHJcXG5cIjtcblx0XHRyZXN1bHQgKz0gXCItLS0tLUVORCBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tXFxyXFxuXFxyXFxuXCI7XG5cdFx0YnJlYWs7XG5cdGNhc2UgNTpcblx0XHRyZXN1bHQgKz0gXCItLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tXFxyXFxuXCI7XG5cdFx0cmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuXHRcdHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGRhdGEpO1xuXHRcdHJlc3VsdCArPSBcIlxcclxcbj1cIitnZXRDaGVja1N1bShkYXRhKStcIlxcclxcblwiO1xuXHRcdHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tXFxyXFxuXCI7XG5cdFx0YnJlYWs7XG5cdH1cblxuXHRyZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0ZW5jb2RlOiBhcm1vcixcblx0ZGVjb2RlOiBkZWFybW9yXG59XG4iLCIvKiBPcGVuUEdQIHJhZGl4LTY0L2Jhc2U2NCBzdHJpbmcgZW5jb2RpbmcvZGVjb2RpbmdcclxuICogQ29weXJpZ2h0IDIwMDUgSGVyYmVydCBIYW5ld2lua2VsLCB3d3cuaGFuZVdJTi5kZVxyXG4gKiB2ZXJzaW9uIDEuMCwgY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxyXG4gKlxyXG4gKiBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkIGFzLWlzLCB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4gIFxyXG4gKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlIG9yIHNlbGwgdGhpcyBzb2Z0d2FyZSwgd2l0aCBvclxyXG4gKiB3aXRob3V0IGZlZSwgZm9yIGFueSBwdXJwb3NlIGFuZCBieSBhbnkgaW5kaXZpZHVhbCBvciBvcmdhbml6YXRpb24sIGlzIGhlcmVieVxyXG4gKiBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBhcmFncmFwaCBhcHBlYXIgXHJcbiAqIGluIGFsbCBjb3BpZXMuIERpc3RyaWJ1dGlvbiBhcyBhIHBhcnQgb2YgYW4gYXBwbGljYXRpb24gb3IgYmluYXJ5IG11c3RcclxuICogaW5jbHVkZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBpbiB0aGUgZG9jdW1lbnRhdGlvbiBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzXHJcbiAqIHByb3ZpZGVkIHdpdGggdGhlIGFwcGxpY2F0aW9uIG9yIGRpc3RyaWJ1dGlvbi5cclxuICovXHJcblxyXG52YXIgYjY0cyA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcclxuXHJcbmZ1bmN0aW9uIHMycih0KSB7XHJcblx0dmFyIGEsIGMsIG47XHJcblx0dmFyIHIgPSAnJywgbCA9IDAsIHMgPSAwO1xyXG5cdHZhciB0bCA9IHQubGVuZ3RoO1xyXG5cclxuXHRmb3IgKG4gPSAwOyBuIDwgdGw7IG4rKykge1xyXG5cdFx0YyA9IHQuY2hhckNvZGVBdChuKTtcclxuXHRcdGlmIChzID09IDApIHtcclxuXHRcdFx0ciArPSBiNjRzLmNoYXJBdCgoYyA+PiAyKSAmIDYzKTtcclxuXHRcdFx0YSA9IChjICYgMykgPDwgNDtcclxuXHRcdH0gZWxzZSBpZiAocyA9PSAxKSB7XHJcblx0XHRcdHIgKz0gYjY0cy5jaGFyQXQoKGEgfCAoYyA+PiA0KSAmIDE1KSk7XHJcblx0XHRcdGEgPSAoYyAmIDE1KSA8PCAyO1xyXG5cdFx0fSBlbHNlIGlmIChzID09IDIpIHtcclxuXHRcdFx0ciArPSBiNjRzLmNoYXJBdChhIHwgKChjID4+IDYpICYgMykpO1xyXG5cdFx0XHRsICs9IDE7XHJcblx0XHRcdGlmICgobCAlIDYwKSA9PSAwKVxyXG5cdFx0XHRcdHIgKz0gXCJcXG5cIjtcclxuXHRcdFx0ciArPSBiNjRzLmNoYXJBdChjICYgNjMpO1xyXG5cdFx0fVxyXG5cdFx0bCArPSAxO1xyXG5cdFx0aWYgKChsICUgNjApID09IDApXHJcblx0XHRcdHIgKz0gXCJcXG5cIjtcclxuXHJcblx0XHRzICs9IDE7XHJcblx0XHRpZiAocyA9PSAzKVxyXG5cdFx0XHRzID0gMDtcclxuXHR9XHJcblx0aWYgKHMgPiAwKSB7XHJcblx0XHRyICs9IGI2NHMuY2hhckF0KGEpO1xyXG5cdFx0bCArPSAxO1xyXG5cdFx0aWYgKChsICUgNjApID09IDApXHJcblx0XHRcdHIgKz0gXCJcXG5cIjtcclxuXHRcdHIgKz0gJz0nO1xyXG5cdFx0bCArPSAxO1xyXG5cdH1cclxuXHRpZiAocyA9PSAxKSB7XHJcblx0XHRpZiAoKGwgJSA2MCkgPT0gMClcclxuXHRcdFx0ciArPSBcIlxcblwiO1xyXG5cdFx0ciArPSAnPSc7XHJcblx0fVxyXG5cclxuXHRyZXR1cm4gcjtcclxufVxyXG5cclxuZnVuY3Rpb24gcjJzKHQpIHtcclxuXHR2YXIgYywgbjtcclxuXHR2YXIgciA9ICcnLCBzID0gMCwgYSA9IDA7XHJcblx0dmFyIHRsID0gdC5sZW5ndGg7XHJcblxyXG5cdGZvciAobiA9IDA7IG4gPCB0bDsgbisrKSB7XHJcblx0XHRjID0gYjY0cy5pbmRleE9mKHQuY2hhckF0KG4pKTtcclxuXHRcdGlmIChjID49IDApIHtcclxuXHRcdFx0aWYgKHMpXHJcblx0XHRcdFx0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGEgfCAoYyA+PiAoNiAtIHMpKSAmIDI1NSk7XHJcblx0XHRcdHMgPSAocyArIDIpICYgNztcclxuXHRcdFx0YSA9IChjIDw8IHMpICYgMjU1O1xyXG5cdFx0fVxyXG5cdH1cclxuXHRyZXR1cm4gcjtcclxufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSB7XHJcblx0ZW5jb2RlOiBzMnIsXHJcblx0ZGVjb2RlOiByMnNcclxufVxyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcblxuXG5cdC8qKiBBIHN0cmluZyB0byBrZXkgc3BlY2lmaWVyIHR5cGVcblx0ICogQGVudW0ge0ludGVnZXJ9XG5cdCAqL1xuXHRzMms6IHtcblx0XHRzaW1wbGU6IDAsXG5cdFx0c2FsdGVkOiAxLFxuXHRcdGl0ZXJhdGVkOiAzLFxuXHRcdGdudTogMTAxXG5cdH0sXG5cblx0LyoqIFJGQzQ4ODAsIHNlY3Rpb24gOS4xIFxuXHQgKiBAZW51bSB7U3RyaW5nfVxuXHQgKi9cblx0cHVibGljS2V5OiB7XG5cdFx0cnNhX2VuY3J5cHRfc2lnbjogMSxcblx0XHRyc2FfZW5jcnlwdDogMixcblx0XHRyc2Ffc2lnbjogMyxcblx0XHRlbGdhbWFsOiAxNixcblx0XHRkc2E6IDE3XG5cdH0sXG5cblx0LyoqIFJGQzQ4ODAsIHNlY3Rpb24gOS4yIFxuXHQgKiBAZW51bSB7U3RyaW5nfVxuXHQgKi9cblx0c3ltbWV0cmljOiB7XG5cdFx0cGxhaW50ZXh0OiAwLFxuXHRcdC8qKiBOb3QgaW1wbGVtZW50ZWQhICovXG5cdFx0aWRlYTogMSxcblx0XHR0cmlwbGVkZXM6IDIsXG5cdFx0Y2FzdDU6IDMsXG5cdFx0Ymxvd2Zpc2g6IDQsXG5cdFx0YWVzMTI4OiA3LFxuXHRcdGFlczE5MjogOCxcblx0XHRhZXMyNTY6IDksXG5cdFx0dHdvZmlzaDogMTBcblx0fSxcblxuXHQvKiogUkZDNDg4MCwgc2VjdGlvbiA5LjNcblx0ICogQGVudW0ge1N0cmluZ31cblx0ICovXG5cdGNvbXByZXNzaW9uOiB7XG5cdFx0dW5jb21wcmVzc2VkOiAwLFxuXHRcdC8qKiBSRkMxOTUxICovXG5cdFx0emlwOiAxLFxuXHRcdC8qKiBSRkMxOTUwICovXG5cdFx0emxpYjogMixcblx0XHRiemlwMjogM1xuXHR9LFxuXG5cdC8qKiBSRkM0ODgwLCBzZWN0aW9uIDkuNFxuXHQgKiBAZW51bSB7U3RyaW5nfVxuXHQgKi9cblx0aGFzaDoge1xuXHRcdG1kNTogMSxcblx0XHRzaGExOiAyLFxuXHRcdHJpcGVtZDogMyxcblx0XHRzaGEyNTY6IDgsXG5cdFx0c2hhMzg0OiA5LFxuXHRcdHNoYTUxMjogMTAsXG5cdFx0c2hhMjI0OiAxMVxuXHR9LFxuXG5cblx0LyoqXG5cdCAqIEBlbnVtIHtTdHJpbmd9XG5cdCAqIEEgbGlzdCBvZiBwYWNrZXQgdHlwZXMgYW5kIG51bWVyaWMgdGFncyBhc3NvY2lhdGVkIHdpdGggdGhlbS5cblx0ICovXG5cdHBhY2tldDoge1xuXHRcdHB1YmxpY19rZXlfZW5jcnlwdGVkX3Nlc3Npb25fa2V5OiAxLFxuXHRcdHNpZ25hdHVyZTogMixcblx0XHRzeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5OiAzLFxuXHRcdG9uZV9wYXNzX3NpZ25hdHVyZTogNCxcblx0XHRzZWNyZXRfa2V5OiA1LFxuXHRcdHB1YmxpY19rZXk6IDYsXG5cdFx0c2VjcmV0X3N1YmtleTogNyxcblx0XHRjb21wcmVzc2VkOiA4LFxuXHRcdHN5bW1ldHJpY2FsbHlfZW5jcnlwdGVkOiA5LFxuXHRcdG1hcmtlcjogMTAsXG5cdFx0bGl0ZXJhbDogMTEsXG5cdFx0dHJ1c3Q6IDEyLFxuXHRcdHVzZXJpZDogMTMsXG5cdFx0cHVibGljX3N1YmtleTogMTQsXG5cdFx0dXNlcl9hdHRyaWJ1dGU6IDE3LFxuXHRcdHN5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZDogMTgsXG5cdFx0bW9kaWZpY2F0aW9uX2RldGVjdGlvbl9jb2RlOiAxOVxuXHR9LFxuXG5cblx0LyoqXG5cdCAqIERhdGEgdHlwZXMgaW4gdGhlIGxpdGVyYWwgcGFja2V0XG5cdCAqIEByZWFkb25seVxuXHQgKiBAZW51bSB7U3RyaW5nfVxuXHQgKi9cblx0bGl0ZXJhbDoge1xuXHRcdC8qKiBCaW5hcnkgZGF0YSAqL1xuXHRcdGJpbmFyeTogJ2InLmNoYXJDb2RlQXQoKSxcblx0XHQvKiogVGV4dCBkYXRhICovXG5cdFx0dGV4dDogJ3QnLmNoYXJDb2RlQXQoKSxcblx0XHQvKiogVXRmOCBkYXRhICovXG5cdFx0dXRmODogJ3UnLmNoYXJDb2RlQXQoKVxuXHR9LFxuXG5cblx0LyoqIE9uZSBwYXNzIHNpZ25hdHVyZSBwYWNrZXQgdHlwZVxuXHQgKiBAZW51bSB7U3RyaW5nfSAqL1xuXHRzaWduYXR1cmU6IHtcblx0XHQvKiogMHgwMDogU2lnbmF0dXJlIG9mIGEgYmluYXJ5IGRvY3VtZW50LiAqL1xuXHRcdGJpbmFyeTogMCxcblx0XHQvKiogMHgwMTogU2lnbmF0dXJlIG9mIGEgY2Fub25pY2FsIHRleHQgZG9jdW1lbnQuXG5cdFx0ICogQ2Fub25pY2FseXppbmcgdGhlIGRvY3VtZW50IGJ5IGNvbnZlcnRpbmcgbGluZSBlbmRpbmdzLiAqL1xuXHRcdHRleHQ6IDEsXG5cdFx0LyoqIDB4MDI6IFN0YW5kYWxvbmUgc2lnbmF0dXJlLlxuXHRcdCogVGhpcyBzaWduYXR1cmUgaXMgYSBzaWduYXR1cmUgb2Ygb25seSBpdHMgb3duIHN1YnBhY2tldCBjb250ZW50cy5cblx0XHQqIEl0IGlzIGNhbGN1bGF0ZWQgaWRlbnRpY2FsbHkgdG8gYSBzaWduYXR1cmUgb3ZlciBhIHplcm8tbGVuZ2hcblx0XHQqIGJpbmFyeSBkb2N1bWVudC4gIE5vdGUgdGhhdCBpdCBkb2Vzbid0IG1ha2Ugc2Vuc2UgdG8gaGF2ZSBhIFYzXG5cdFx0KiBzdGFuZGFsb25lIHNpZ25hdHVyZS4gKi9cblx0XHRzdGFuZGFsb25lOiAyLFxuXHRcdC8qKiAweDEwOiBHZW5lcmljIGNlcnRpZmljYXRpb24gb2YgYSBVc2VyIElEIGFuZCBQdWJsaWMtS2V5IHBhY2tldC5cblx0XHQqIFRoZSBpc3N1ZXIgb2YgdGhpcyBjZXJ0aWZpY2F0aW9uIGRvZXMgbm90IG1ha2UgYW55IHBhcnRpY3VsYXJcblx0XHQqIGFzc2VydGlvbiBhcyB0byBob3cgd2VsbCB0aGUgY2VydGlmaWVyIGhhcyBjaGVja2VkIHRoYXQgdGhlIG93bmVyXG5cdFx0KiBvZiB0aGUga2V5IGlzIGluIGZhY3QgdGhlIHBlcnNvbiBkZXNjcmliZWQgYnkgdGhlIFVzZXIgSUQuICovXG5cdFx0Y2VydF9nZW5lcmljOiAxNixcblx0XHQvKiogMHgxMTogUGVyc29uYSBjZXJ0aWZpY2F0aW9uIG9mIGEgVXNlciBJRCBhbmQgUHVibGljLUtleSBwYWNrZXQuXG5cdFx0KiBUaGUgaXNzdWVyIG9mIHRoaXMgY2VydGlmaWNhdGlvbiBoYXMgbm90IGRvbmUgYW55IHZlcmlmaWNhdGlvbiBvZlxuXHRcdCogdGhlIGNsYWltIHRoYXQgdGhlIG93bmVyIG9mIHRoaXMga2V5IGlzIHRoZSBVc2VyIElEIHNwZWNpZmllZC4gKi9cblx0XHRjZXJ0X3BlcnNvbmE6IDE3LFxuXHRcdC8qKiAweDEyOiBDYXN1YWwgY2VydGlmaWNhdGlvbiBvZiBhIFVzZXIgSUQgYW5kIFB1YmxpYy1LZXkgcGFja2V0LlxuXHRcdCogVGhlIGlzc3VlciBvZiB0aGlzIGNlcnRpZmljYXRpb24gaGFzIGRvbmUgc29tZSBjYXN1YWxcblx0XHQqIHZlcmlmaWNhdGlvbiBvZiB0aGUgY2xhaW0gb2YgaWRlbnRpdHkuICovXG5cdFx0Y2VydF9jYXN1YWw6IDE4LFxuXHRcdC8qKiAweDEzOiBQb3NpdGl2ZSBjZXJ0aWZpY2F0aW9uIG9mIGEgVXNlciBJRCBhbmQgUHVibGljLUtleSBwYWNrZXQuXG5cdFx0KiBUaGUgaXNzdWVyIG9mIHRoaXMgY2VydGlmaWNhdGlvbiBoYXMgZG9uZSBzdWJzdGFudGlhbFxuXHRcdCogdmVyaWZpY2F0aW9uIG9mIHRoZSBjbGFpbSBvZiBpZGVudGl0eS5cblx0XHQqIFxuXHRcdCogTW9zdCBPcGVuUEdQIGltcGxlbWVudGF0aW9ucyBtYWtlIHRoZWlyIFwia2V5IHNpZ25hdHVyZXNcIiBhcyAweDEwXG5cdFx0KiBjZXJ0aWZpY2F0aW9ucy4gIFNvbWUgaW1wbGVtZW50YXRpb25zIGNhbiBpc3N1ZSAweDExLTB4MTNcblx0XHQqIGNlcnRpZmljYXRpb25zLCBidXQgZmV3IGRpZmZlcmVudGlhdGUgYmV0d2VlbiB0aGUgdHlwZXMuICovXG5cdFx0Y2VydF9wb3NpdGl2ZTogMTksXG5cdFx0LyoqIDB4MzA6IENlcnRpZmljYXRpb24gcmV2b2NhdGlvbiBzaWduYXR1cmVcblx0XHQqIFRoaXMgc2lnbmF0dXJlIHJldm9rZXMgYW4gZWFybGllciBVc2VyIElEIGNlcnRpZmljYXRpb24gc2lnbmF0dXJlXG5cdFx0KiAoc2lnbmF0dXJlIGNsYXNzIDB4MTAgdGhyb3VnaCAweDEzKSBvciBkaXJlY3Qta2V5IHNpZ25hdHVyZVxuXHRcdCogKDB4MUYpLiAgSXQgc2hvdWxkIGJlIGlzc3VlZCBieSB0aGUgc2FtZSBrZXkgdGhhdCBpc3N1ZWQgdGhlXG5cdFx0KiByZXZva2VkIHNpZ25hdHVyZSBvciBhbiBhdXRob3JpemVkIHJldm9jYXRpb24ga2V5LiAgVGhlIHNpZ25hdHVyZVxuXHRcdCogaXMgY29tcHV0ZWQgb3ZlciB0aGUgc2FtZSBkYXRhIGFzIHRoZSBjZXJ0aWZpY2F0ZSB0aGF0IGl0XG5cdFx0KiByZXZva2VzLCBhbmQgc2hvdWxkIGhhdmUgYSBsYXRlciBjcmVhdGlvbiBkYXRlIHRoYW4gdGhhdFxuXHRcdCogY2VydGlmaWNhdGUuICovXG5cdFx0Y2VydF9yZXZvY2F0aW9uOiA0OCxcblx0XHQvKiogMHgxODogU3Via2V5IEJpbmRpbmcgU2lnbmF0dXJlXG5cdFx0KiBUaGlzIHNpZ25hdHVyZSBpcyBhIHN0YXRlbWVudCBieSB0aGUgdG9wLWxldmVsIHNpZ25pbmcga2V5IHRoYXRcblx0XHQqIGluZGljYXRlcyB0aGF0IGl0IG93bnMgdGhlIHN1YmtleS4gIFRoaXMgc2lnbmF0dXJlIGlzIGNhbGN1bGF0ZWRcblx0XHQqIGRpcmVjdGx5IG9uIHRoZSBwcmltYXJ5IGtleSBhbmQgc3Via2V5LCBhbmQgbm90IG9uIGFueSBVc2VyIElEIG9yXG5cdFx0KiBvdGhlciBwYWNrZXRzLiAgQSBzaWduYXR1cmUgdGhhdCBiaW5kcyBhIHNpZ25pbmcgc3Via2V5IE1VU1QgaGF2ZVxuXHRcdCogYW4gRW1iZWRkZWQgU2lnbmF0dXJlIHN1YnBhY2tldCBpbiB0aGlzIGJpbmRpbmcgc2lnbmF0dXJlIHRoYXRcblx0XHQqIGNvbnRhaW5zIGEgMHgxOSBzaWduYXR1cmUgbWFkZSBieSB0aGUgc2lnbmluZyBzdWJrZXkgb24gdGhlXG5cdFx0KiBwcmltYXJ5IGtleSBhbmQgc3Via2V5LiAqL1xuXHRcdHN1YmtleV9iaW5kaW5nOiAyNCxcblx0XHQvKiogMHgxOTogUHJpbWFyeSBLZXkgQmluZGluZyBTaWduYXR1cmVcblx0XHQqIFRoaXMgc2lnbmF0dXJlIGlzIGEgc3RhdGVtZW50IGJ5IGEgc2lnbmluZyBzdWJrZXksIGluZGljYXRpbmdcblx0XHQqIHRoYXQgaXQgaXMgb3duZWQgYnkgdGhlIHByaW1hcnkga2V5IGFuZCBzdWJrZXkuICBUaGlzIHNpZ25hdHVyZVxuXHRcdCogaXMgY2FsY3VsYXRlZCB0aGUgc2FtZSB3YXkgYXMgYSAweDE4IHNpZ25hdHVyZTogZGlyZWN0bHkgb24gdGhlXG5cdFx0KiBwcmltYXJ5IGtleSBhbmQgc3Via2V5LCBhbmQgbm90IG9uIGFueSBVc2VyIElEIG9yIG90aGVyIHBhY2tldHMuXG5cdFx0XG5cdFx0KiBXaGVuIGEgc2lnbmF0dXJlIGlzIG1hZGUgb3ZlciBhIGtleSwgdGhlIGhhc2ggZGF0YSBzdGFydHMgd2l0aCB0aGVcblx0XHQqIG9jdGV0IDB4OTksIGZvbGxvd2VkIGJ5IGEgdHdvLW9jdGV0IGxlbmd0aCBvZiB0aGUga2V5LCBhbmQgdGhlbiBib2R5XG5cdFx0KiBvZiB0aGUga2V5IHBhY2tldC4gIChOb3RlIHRoYXQgdGhpcyBpcyBhbiBvbGQtc3R5bGUgcGFja2V0IGhlYWRlciBmb3Jcblx0XHQqIGEga2V5IHBhY2tldCB3aXRoIHR3by1vY3RldCBsZW5ndGguKSAgQSBzdWJrZXkgYmluZGluZyBzaWduYXR1cmVcblx0XHQqICh0eXBlIDB4MTgpIG9yIHByaW1hcnkga2V5IGJpbmRpbmcgc2lnbmF0dXJlICh0eXBlIDB4MTkpIHRoZW4gaGFzaGVzXG5cdFx0KiB0aGUgc3Via2V5IHVzaW5nIHRoZSBzYW1lIGZvcm1hdCBhcyB0aGUgbWFpbiBrZXkgKGFsc28gdXNpbmcgMHg5OSBhc1xuXHRcdCogdGhlIGZpcnN0IG9jdGV0KS4gKi9cblx0XHRrZXlfYmluZGluZzogMjUsXG5cdFx0LyoqIDB4MUY6IFNpZ25hdHVyZSBkaXJlY3RseSBvbiBhIGtleVxuXHRcdCogVGhpcyBzaWduYXR1cmUgaXMgY2FsY3VsYXRlZCBkaXJlY3RseSBvbiBhIGtleS4gIEl0IGJpbmRzIHRoZVxuXHRcdCogaW5mb3JtYXRpb24gaW4gdGhlIFNpZ25hdHVyZSBzdWJwYWNrZXRzIHRvIHRoZSBrZXksIGFuZCBpc1xuXHRcdCogYXBwcm9wcmlhdGUgdG8gYmUgdXNlZCBmb3Igc3VicGFja2V0cyB0aGF0IHByb3ZpZGUgaW5mb3JtYXRpb25cblx0XHQqIGFib3V0IHRoZSBrZXksIHN1Y2ggYXMgdGhlIFJldm9jYXRpb24gS2V5IHN1YnBhY2tldC4gIEl0IGlzIGFsc29cblx0XHQqIGFwcHJvcHJpYXRlIGZvciBzdGF0ZW1lbnRzIHRoYXQgbm9uLXNlbGYgY2VydGlmaWVycyB3YW50IHRvIG1ha2Vcblx0XHQqIGFib3V0IHRoZSBrZXkgaXRzZWxmLCByYXRoZXIgdGhhbiB0aGUgYmluZGluZyBiZXR3ZWVuIGEga2V5IGFuZCBhXG5cdFx0KiBuYW1lLiAqL1xuXHRcdGtleTogMzEsXG5cdFx0LyoqIDB4MjA6IEtleSByZXZvY2F0aW9uIHNpZ25hdHVyZVxuXHRcdCogVGhlIHNpZ25hdHVyZSBpcyBjYWxjdWxhdGVkIGRpcmVjdGx5IG9uIHRoZSBrZXkgYmVpbmcgcmV2b2tlZC4gIEFcblx0XHQqIHJldm9rZWQga2V5IGlzIG5vdCB0byBiZSB1c2VkLiAgT25seSByZXZvY2F0aW9uIHNpZ25hdHVyZXMgYnkgdGhlXG5cdFx0KiBrZXkgYmVpbmcgcmV2b2tlZCwgb3IgYnkgYW4gYXV0aG9yaXplZCByZXZvY2F0aW9uIGtleSwgc2hvdWxkIGJlXG5cdFx0KiBjb25zaWRlcmVkIHZhbGlkIHJldm9jYXRpb24gc2lnbmF0dXJlcy5hICovXG5cdFx0a2V5X3Jldm9jYXRpb246IDMyLFxuXHRcdC8qKiAweDI4OiBTdWJrZXkgcmV2b2NhdGlvbiBzaWduYXR1cmVcblx0XHQqIFRoZSBzaWduYXR1cmUgaXMgY2FsY3VsYXRlZCBkaXJlY3RseSBvbiB0aGUgc3Via2V5IGJlaW5nIHJldm9rZWQuXG5cdFx0KiBBIHJldm9rZWQgc3Via2V5IGlzIG5vdCB0byBiZSB1c2VkLiAgT25seSByZXZvY2F0aW9uIHNpZ25hdHVyZXNcblx0XHQqIGJ5IHRoZSB0b3AtbGV2ZWwgc2lnbmF0dXJlIGtleSB0aGF0IGlzIGJvdW5kIHRvIHRoaXMgc3Via2V5LCBvclxuXHRcdCogYnkgYW4gYXV0aG9yaXplZCByZXZvY2F0aW9uIGtleSwgc2hvdWxkIGJlIGNvbnNpZGVyZWQgdmFsaWRcblx0XHQqIHJldm9jYXRpb24gc2lnbmF0dXJlcy5cblx0XHQqIEtleSByZXZvY2F0aW9uIHNpZ25hdHVyZXMgKHR5cGVzIDB4MjAgYW5kIDB4MjgpXG5cdFx0KiBoYXNoIG9ubHkgdGhlIGtleSBiZWluZyByZXZva2VkLiAqL1xuXHRcdHN1YmtleV9yZXZvY2F0aW9uOiA0MCxcblx0XHQvKiogMHg0MDogVGltZXN0YW1wIHNpZ25hdHVyZS5cblx0XHQqIFRoaXMgc2lnbmF0dXJlIGlzIG9ubHkgbWVhbmluZ2Z1bCBmb3IgdGhlIHRpbWVzdGFtcCBjb250YWluZWQgaW5cblx0XHQqIGl0LiAqL1xuXHRcdHRpbWVzdGFtcDogNjQsXG5cdFx0LyoqICAgIDB4NTA6IFRoaXJkLVBhcnR5IENvbmZpcm1hdGlvbiBzaWduYXR1cmUuXG5cdFx0KiBUaGlzIHNpZ25hdHVyZSBpcyBhIHNpZ25hdHVyZSBvdmVyIHNvbWUgb3RoZXIgT3BlblBHUCBTaWduYXR1cmVcblx0XHQqIHBhY2tldChzKS4gIEl0IGlzIGFuYWxvZ291cyB0byBhIG5vdGFyeSBzZWFsIG9uIHRoZSBzaWduZWQgZGF0YS5cblx0XHQqIEEgdGhpcmQtcGFydHkgc2lnbmF0dXJlIFNIT1VMRCBpbmNsdWRlIFNpZ25hdHVyZSBUYXJnZXRcblx0XHQqIHN1YnBhY2tldChzKSB0byBnaXZlIGVhc3kgaWRlbnRpZmljYXRpb24uICBOb3RlIHRoYXQgd2UgcmVhbGx5IGRvXG5cdFx0KiBtZWFuIFNIT1VMRC4gIFRoZXJlIGFyZSBwbGF1c2libGUgdXNlcyBmb3IgdGhpcyAoc3VjaCBhcyBhIGJsaW5kXG5cdFx0KiBwYXJ0eSB0aGF0IG9ubHkgc2VlcyB0aGUgc2lnbmF0dXJlLCBub3QgdGhlIGtleSBvciBzb3VyY2Vcblx0XHQqIGRvY3VtZW50KSB0aGF0IGNhbm5vdCBpbmNsdWRlIGEgdGFyZ2V0IHN1YnBhY2tldC4gKi9cblx0XHR0aGlyZF9wYXJ0eTogODBcblx0fSxcblxuXHQvLyBBc3NlcnRzIHZhbGlkaXR5IGFuZCBjb252ZXJ0cyBmcm9tIHN0cmluZy9pbnRlZ2VyIHRvIGludGVnZXIuXG5cdHdyaXRlOiBmdW5jdGlvbih0eXBlLCBlKSB7XG5cdFx0aWYodHlwZW9mIGUgPT0gJ251bWJlcicpIHtcblx0XHRcdGUgPSB0aGlzLnJlYWQodHlwZSwgZSk7XG5cdFx0fVxuXHRcdFxuXHRcdGlmKHR5cGVbZV0gIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRyZXR1cm4gdHlwZVtlXTtcblx0XHR9IGVsc2UgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGVudW0gdmFsdWUuJyk7XG5cdH0sXG5cdC8vIENvbnZlcnRzIGZyb20gYW4gaW50ZWdlciB0byBzdHJpbmcuXG5cdHJlYWQ6IGZ1bmN0aW9uKHR5cGUsIGUpIHtcblx0XHRmb3IodmFyIGkgaW4gdHlwZSlcblx0XHRcdGlmKHR5cGVbaV0gPT0gZSkgcmV0dXJuIGk7XG5cblx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZW51bSB2YWx1ZS4nKTtcblx0fVxufVxuXG5cblxuXG4iLCJcblxuXG52YXIgY3J5cHRvID0gcmVxdWlyZSgnLi9jcnlwdG8nKTtcblxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL29wZW5wZ3AuanMnKTtcbm1vZHVsZS5leHBvcnRzLnV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcbm1vZHVsZS5leHBvcnRzLnBhY2tldCA9IHJlcXVpcmUoJy4vcGFja2V0Jyk7XG5tb2R1bGUuZXhwb3J0cy5tcGkgPSByZXF1aXJlKCcuL3R5cGUvbXBpLmpzJyk7XG5tb2R1bGUuZXhwb3J0cy5zMmsgPSByZXF1aXJlKCcuL3R5cGUvczJrLmpzJyk7XG5tb2R1bGUuZXhwb3J0cy5rZXlpZCA9IHJlcXVpcmUoJy4vdHlwZS9rZXlpZC5qcycpO1xubW9kdWxlLmV4cG9ydHMuYXJtb3IgPSByZXF1aXJlKCcuL2VuY29kaW5nL2FybW9yLmpzJyk7XG5cbmZvcih2YXIgaSBpbiBjcnlwdG8pXG5cdG1vZHVsZS5leHBvcnRzW2ldID0gY3J5cHRvW2ldO1xuXG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgVGhlIG9wZW5wZ3AgYmFzZSBjbGFzcyBzaG91bGQgcHJvdmlkZSBhbGwgb2YgdGhlIGZ1bmN0aW9uYWxpdHkgXG4gKiB0byBjb25zdW1lIHRoZSBvcGVucGdwLmpzIGxpYnJhcnkuIEFsbCBhZGRpdGlvbmFsIGNsYXNzZXMgYXJlIGRvY3VtZW50ZWQgXG4gKiBmb3IgZXh0ZW5kaW5nIGFuZCBkZXZlbG9waW5nIG9uIHRvcCBvZiB0aGUgYmFzZSBsaWJyYXJ5LlxuICovXG5cbi8qKlxuICogR1BHNEJyb3dzZXJzIENvcmUgaW50ZXJmYWNlLiBBIHNpbmdsZSBpbnN0YW5jZSBpcyBob2xkXG4gKiBmcm9tIHRoZSBiZWdpbm5pbmcuIFRvIHVzZSB0aGlzIGxpYnJhcnkgY2FsbCBcIm9wZW5wZ3AuaW5pdCgpXCJcbiAqIEBhbGlhcyBvcGVucGdwXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgTWFpbiBPcGVucGdwLmpzIGNsYXNzLiBVc2UgdGhpcyB0byBpbml0aWF0ZSBhbmQgbWFrZSBhbGwgY2FsbHMgdG8gdGhpcyBsaWJyYXJ5LlxuICovXG5mdW5jdGlvbiBfb3BlbnBncCAoKSB7XG5cdHRoaXMudG9zdHJpbmcgPSBcIlwiO1xuXHRcblx0LyoqXG5cdCAqIGluaXRpYWxpemVzIHRoZSBsaWJyYXJ5OlxuXHQgKiAtIHJlYWRpbmcgdGhlIGtleXJpbmcgZnJvbSBsb2NhbCBzdG9yYWdlXG5cdCAqIC0gcmVhZGluZyB0aGUgY29uZmlnIGZyb20gbG9jYWwgc3RvcmFnZVxuXHQgKi9cblx0ZnVuY3Rpb24gaW5pdCgpIHtcblx0XHR0aGlzLmNvbmZpZyA9IG5ldyBvcGVucGdwX2NvbmZpZygpO1xuXHRcdHRoaXMuY29uZmlnLnJlYWQoKTtcblx0XHR0aGlzLmtleXJpbmcgPSBuZXcgb3BlbnBncF9rZXlyaW5nKCk7XG5cdFx0dGhpcy5rZXlyaW5nLmluaXQoKTtcblx0fVxuXHRcblx0LyoqXG5cdCAqIHJlYWRzIHNldmVyYWwgcHVibGljS2V5IG9iamVjdHMgZnJvbSBhIGFzY2lpIGFybW9yZWRcblx0ICogcmVwcmVzZW50YXRpb24gYW4gcmV0dXJucyBvcGVucGdwX21zZ19wdWJsaWNrZXkgcGFja2V0c1xuXHQgKiBAcGFyYW0ge1N0cmluZ30gYXJtb3JlZFRleHQgT3BlblBHUCBhcm1vcmVkIHRleHQgY29udGFpbmluZ1xuXHQgKiB0aGUgcHVibGljIGtleShzKVxuXHQgKiBAcmV0dXJuIHtvcGVucGdwX21zZ19wdWJsaWNrZXlbXX0gb24gZXJyb3IgdGhlIGZ1bmN0aW9uXG5cdCAqIHJldHVybnMgbnVsbFxuXHQgKi9cblx0ZnVuY3Rpb24gcmVhZF9wdWJsaWNLZXkoYXJtb3JlZFRleHQpIHtcblx0XHR2YXIgbXlwb3MgPSAwO1xuXHRcdHZhciBwdWJsaWNLZXlzID0gbmV3IEFycmF5KCk7XG5cdFx0dmFyIHB1YmxpY0tleUNvdW50ID0gMDtcblx0XHR2YXIgaW5wdXQgPSBvcGVucGdwX2VuY29kaW5nX2RlQXJtb3IoYXJtb3JlZFRleHQucmVwbGFjZSgvXFxyL2csJycpKS5vcGVucGdwO1xuXHRcdHZhciBsID0gaW5wdXQubGVuZ3RoO1xuXHRcdHdoaWxlIChteXBvcyAhPSBpbnB1dC5sZW5ndGgpIHtcblx0XHRcdHZhciBmaXJzdF9wYWNrZXQgPSBvcGVucGdwX3BhY2tldC5yZWFkX3BhY2tldChpbnB1dCwgbXlwb3MsIGwpO1xuXHRcdFx0Ly8gcHVibGljIGtleSBwYXJzZXJcblx0XHRcdGlmIChpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpID09IDB4OTkgfHwgZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gNikge1xuXHRcdFx0XHRwdWJsaWNLZXlzW3B1YmxpY0tleUNvdW50XSA9IG5ldyBvcGVucGdwX21zZ19wdWJsaWNrZXkoKTtcdFx0XHRcdFxuXHRcdFx0XHRwdWJsaWNLZXlzW3B1YmxpY0tleUNvdW50XS5oZWFkZXIgPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MsbXlwb3MrMyk7XG5cdFx0XHRcdGlmIChpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpID09IDB4OTkpIHtcblx0XHRcdFx0XHQvLyBwYXJzZSB0aGUgbGVuZ3RoIGFuZCByZWFkIGEgdGFnNiBwYWNrZXRcblx0XHRcdFx0XHRteXBvcysrO1xuXHRcdFx0XHRcdHZhciBsID0gKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCA4KVxuXHRcdFx0XHRcdFx0XHR8IGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKTtcblx0XHRcdFx0XHRwdWJsaWNLZXlzW3B1YmxpY0tleUNvdW50XS5wdWJsaWNLZXlQYWNrZXQgPSBuZXcgb3BlbnBncF9wYWNrZXRfa2V5bWF0ZXJpYWwoKTtcblx0XHRcdFx0XHRwdWJsaWNLZXlzW3B1YmxpY0tleUNvdW50XS5wdWJsaWNLZXlQYWNrZXQuaGVhZGVyID0gcHVibGljS2V5c1twdWJsaWNLZXlDb3VudF0uaGVhZGVyO1xuXHRcdFx0XHRcdHB1YmxpY0tleXNbcHVibGljS2V5Q291bnRdLnB1YmxpY0tleVBhY2tldC5yZWFkX3RhZzYoaW5wdXQsIG15cG9zLCBsKTtcblx0XHRcdFx0XHRteXBvcyArPSBwdWJsaWNLZXlzW3B1YmxpY0tleUNvdW50XS5wdWJsaWNLZXlQYWNrZXQucGFja2V0TGVuZ3RoO1xuXHRcdFx0XHRcdG15cG9zICs9IHB1YmxpY0tleXNbcHVibGljS2V5Q291bnRdLnJlYWRfbm9kZXMocHVibGljS2V5c1twdWJsaWNLZXlDb3VudF0ucHVibGljS2V5UGFja2V0LCBpbnB1dCwgbXlwb3MsIChpbnB1dC5sZW5ndGggLSBteXBvcykpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHB1YmxpY0tleXNbcHVibGljS2V5Q291bnRdID0gbmV3IG9wZW5wZ3BfbXNnX3B1YmxpY2tleSgpO1xuXHRcdFx0XHRcdHB1YmxpY0tleXNbcHVibGljS2V5Q291bnRdLnB1YmxpY0tleVBhY2tldCA9IGZpcnN0X3BhY2tldDtcblx0XHRcdFx0XHRteXBvcyArPSBmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoK2ZpcnN0X3BhY2tldC5wYWNrZXRMZW5ndGg7XG5cdFx0XHRcdFx0bXlwb3MgKz0gcHVibGljS2V5c1twdWJsaWNLZXlDb3VudF0ucmVhZF9ub2RlcyhmaXJzdF9wYWNrZXQsIGlucHV0LCBteXBvcywgaW5wdXQubGVuZ3RoIC1teXBvcyk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHV0aWwucHJpbnRfZXJyb3IoXCJubyBwdWJsaWMga2V5IGZvdW5kIVwiKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHRwdWJsaWNLZXlzW3B1YmxpY0tleUNvdW50XS5kYXRhID0gaW5wdXQuc3Vic3RyaW5nKDAsbXlwb3MpO1xuXHRcdFx0cHVibGljS2V5Q291bnQrKztcblx0XHR9XG5cdFx0cmV0dXJuIHB1YmxpY0tleXM7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiByZWFkcyBzZXZlcmFsIHByaXZhdGVLZXkgb2JqZWN0cyBmcm9tIGEgYXNjaWkgYXJtb3JlZFxuXHQgKiByZXByZXNlbnRhdGlvbiBhbiByZXR1cm5zIG9wZW5wZ3BfbXNnX3ByaXZhdGVrZXkgb2JqZWN0c1xuXHQgKiBAcGFyYW0ge1N0cmluZ30gYXJtb3JlZFRleHQgT3BlblBHUCBhcm1vcmVkIHRleHQgY29udGFpbmluZ1xuXHQgKiB0aGUgcHJpdmF0ZSBrZXkocylcblx0ICogQHJldHVybiB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleVtdfSBvbiBlcnJvciB0aGUgZnVuY3Rpb25cblx0ICogcmV0dXJucyBudWxsXG5cdCAqL1xuXHRmdW5jdGlvbiByZWFkX3ByaXZhdGVLZXkoYXJtb3JlZFRleHQpIHtcblx0XHR2YXIgcHJpdmF0ZUtleXMgPSBuZXcgQXJyYXkoKTtcblx0XHR2YXIgcHJpdmF0ZUtleUNvdW50ID0gMDtcblx0XHR2YXIgbXlwb3MgPSAwO1xuXHRcdHZhciBpbnB1dCA9IG9wZW5wZ3BfZW5jb2RpbmdfZGVBcm1vcihhcm1vcmVkVGV4dC5yZXBsYWNlKC9cXHIvZywnJykpLm9wZW5wZ3A7XG5cdFx0dmFyIGwgPSBpbnB1dC5sZW5ndGg7XG5cdFx0d2hpbGUgKG15cG9zICE9IGlucHV0Lmxlbmd0aCkge1xuXHRcdFx0dmFyIGZpcnN0X3BhY2tldCA9IG9wZW5wZ3BfcGFja2V0LnJlYWRfcGFja2V0KGlucHV0LCBteXBvcywgbCk7XG5cdFx0XHRpZiAoZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gNSkge1xuXHRcdFx0XHRwcml2YXRlS2V5c1twcml2YXRlS2V5cy5sZW5ndGhdID0gbmV3IG9wZW5wZ3BfbXNnX3ByaXZhdGVrZXkoKTtcblx0XHRcdFx0bXlwb3MgKz0gZmlyc3RfcGFja2V0LmhlYWRlckxlbmd0aCtmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoO1xuXHRcdFx0XHRteXBvcyArPSBwcml2YXRlS2V5c1twcml2YXRlS2V5Q291bnRdLnJlYWRfbm9kZXMoZmlyc3RfcGFja2V0LCBpbnB1dCwgbXlwb3MsIGwpO1xuXHRcdFx0Ly8gb3RoZXIgYmxvY2tzXHQgICAgICAgICAgICBcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHV0aWwucHJpbnRfZXJyb3IoJ25vIGJsb2NrIHBhY2tldCBmb3VuZCEnKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHRwcml2YXRlS2V5c1twcml2YXRlS2V5Q291bnRdLmRhdGEgPSBpbnB1dC5zdWJzdHJpbmcoMCxteXBvcyk7XG5cdFx0XHRwcml2YXRlS2V5Q291bnQrKztcblx0XHR9XG5cdFx0cmV0dXJuIHByaXZhdGVLZXlzO1x0XHRcblx0fVxuXG5cdC8qKlxuXHQgKiByZWFkcyBtZXNzYWdlIHBhY2tldHMgb3V0IG9mIGFuIE9wZW5QR1AgYXJtb3JlZCB0ZXh0IGFuZFxuXHQgKiByZXR1cm5zIGFuIGFycmF5IG9mIG1lc3NhZ2Ugb2JqZWN0c1xuXHQgKiBAcGFyYW0ge1N0cmluZ30gYXJtb3JlZFRleHQgdGV4dCB0byBiZSBwYXJzZWRcblx0ICogQHJldHVybiB7b3BlbnBncF9tc2dfbWVzc2FnZVtdfSBvbiBlcnJvciB0aGUgZnVuY3Rpb25cblx0ICogcmV0dXJucyBudWxsXG5cdCAqL1xuXHRmdW5jdGlvbiByZWFkX21lc3NhZ2UoYXJtb3JlZFRleHQpIHtcblx0XHR2YXIgZGVhcm1vcmVkO1xuXHRcdHRyeXtcbiAgICBcdFx0ZGVhcm1vcmVkID0gb3BlbnBncF9lbmNvZGluZ19kZUFybW9yKGFybW9yZWRUZXh0LnJlcGxhY2UoL1xcci9nLCcnKSk7XG5cdFx0fVxuXHRcdGNhdGNoKGUpe1xuICAgIFx0XHR1dGlsLnByaW50X2Vycm9yKCdubyBtZXNzYWdlIGZvdW5kIScpO1xuICAgIFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9XG5cdFx0cmV0dXJuIHJlYWRfbWVzc2FnZXNfZGVhcm1vcmVkKGRlYXJtb3JlZCk7XG5cdFx0fVxuXHRcdFxuXHQvKipcblx0ICogcmVhZHMgbWVzc2FnZSBwYWNrZXRzIG91dCBvZiBhbiBPcGVuUEdQIGFybW9yZWQgdGV4dCBhbmRcblx0ICogcmV0dXJucyBhbiBhcnJheSBvZiBtZXNzYWdlIG9iamVjdHMuIENhbiBiZSBjYWxsZWQgZXh0ZXJuYWxseSBvciBpbnRlcm5hbGx5LlxuXHQgKiBFeHRlcm5hbCBjYWxsIHdpbGwgcGFyc2UgYSBkZS1hcm1vcmVkIG1lc3NhZ2VkIGFuZCByZXR1cm4gbWVzc2FnZXMgZm91bmQuXG5cdCAqIEludGVybmFsIHdpbGwgYmUgY2FsbGVkIHRvIHJlYWQgcGFja2V0cyB3cmFwcGVkIGluIG90aGVyIHBhY2tldHMgKGkuZS4gY29tcHJlc3NlZClcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IGRlYXJtb3JlZCB0ZXh0IG9mIE9wZW5QR1AgcGFja2V0cywgdG8gYmUgcGFyc2VkXG5cdCAqIEByZXR1cm4ge29wZW5wZ3BfbXNnX21lc3NhZ2VbXX0gb24gZXJyb3IgdGhlIGZ1bmN0aW9uXG5cdCAqIHJldHVybnMgbnVsbFxuXHQgKi9cblx0ZnVuY3Rpb24gcmVhZF9tZXNzYWdlc19kZWFybW9yZWQoaW5wdXQpe1xuXHRcdHZhciBtZXNzYWdlU3RyaW5nID0gaW5wdXQub3BlbnBncDtcblx0XHR2YXIgc2lnbmF0dXJlVGV4dCA9IGlucHV0LnRleHQ7IC8vdGV4dCB0byB2ZXJpZnkgc2lnbmF0dXJlcyBhZ2FpbnN0LiBNb2RpZmllZCBieSBUYWcxMS5cblx0XHR2YXIgbWVzc2FnZXMgPSBuZXcgQXJyYXkoKTtcblx0XHR2YXIgbWVzc2FnZUNvdW50ID0gMDtcblx0XHR2YXIgbXlwb3MgPSAwO1xuXHRcdHZhciBsID0gbWVzc2FnZVN0cmluZy5sZW5ndGg7XG5cdFx0d2hpbGUgKG15cG9zIDwgbWVzc2FnZVN0cmluZy5sZW5ndGgpIHtcblx0XHRcdHZhciBmaXJzdF9wYWNrZXQgPSBvcGVucGdwX3BhY2tldC5yZWFkX3BhY2tldChtZXNzYWdlU3RyaW5nLCBteXBvcywgbCk7XG5cdFx0XHRpZiAoIWZpcnN0X3BhY2tldCkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdC8vIHB1YmxpYyBrZXkgcGFyc2VyIChkZWZpbml0aW9uIGZyb20gdGhlIHN0YW5kYXJkOilcblx0XHRcdC8vIE9wZW5QR1AgTWVzc2FnZSAgICAgIDotIEVuY3J5cHRlZCBNZXNzYWdlIHwgU2lnbmVkIE1lc3NhZ2UgfFxuXHRcdFx0Ly8gICAgICAgICAgICAgICAgICAgICAgICAgQ29tcHJlc3NlZCBNZXNzYWdlIHwgTGl0ZXJhbCBNZXNzYWdlLlxuXHRcdFx0Ly8gQ29tcHJlc3NlZCBNZXNzYWdlICAgOi0gQ29tcHJlc3NlZCBEYXRhIFBhY2tldC5cblx0XHRcdC8vIFxuXHRcdFx0Ly8gTGl0ZXJhbCBNZXNzYWdlICAgICAgOi0gTGl0ZXJhbCBEYXRhIFBhY2tldC5cblx0XHRcdC8vIFxuXHRcdFx0Ly8gRVNLICAgICAgICAgICAgICAgICAgOi0gUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgUGFja2V0IHxcblx0XHRcdC8vICAgICAgICAgICAgICAgICAgICAgICAgIFN5bW1ldHJpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IFBhY2tldC5cblx0XHRcdC8vIFxuXHRcdFx0Ly8gRVNLIFNlcXVlbmNlICAgICAgICAgOi0gRVNLIHwgRVNLIFNlcXVlbmNlLCBFU0suXG5cdFx0XHQvLyBcblx0XHRcdC8vIEVuY3J5cHRlZCBEYXRhICAgICAgIDotIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgUGFja2V0IHxcblx0XHRcdC8vICAgICAgICAgICAgICAgICAgICAgICAgIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIEludGVncml0eSBQcm90ZWN0ZWQgRGF0YSBQYWNrZXRcblx0XHRcdC8vIFxuXHRcdFx0Ly8gRW5jcnlwdGVkIE1lc3NhZ2UgICAgOi0gRW5jcnlwdGVkIERhdGEgfCBFU0sgU2VxdWVuY2UsIEVuY3J5cHRlZCBEYXRhLlxuXHRcdFx0Ly8gXG5cdFx0XHQvLyBPbmUtUGFzcyBTaWduZWQgTWVzc2FnZSA6LSBPbmUtUGFzcyBTaWduYXR1cmUgUGFja2V0LFxuXHRcdFx0Ly8gICAgICAgICAgICAgICAgICAgICAgICAgT3BlblBHUCBNZXNzYWdlLCBDb3JyZXNwb25kaW5nIFNpZ25hdHVyZSBQYWNrZXQuXG5cblx0XHRcdC8vIFNpZ25lZCBNZXNzYWdlICAgICAgIDotIFNpZ25hdHVyZSBQYWNrZXQsIE9wZW5QR1AgTWVzc2FnZSB8XG5cdFx0XHQvLyAgICAgICAgICAgICAgICAgICAgICAgICBPbmUtUGFzcyBTaWduZWQgTWVzc2FnZS5cblx0XHRcdGlmIChmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAgMSB8fFxuXHRcdFx0ICAgIChmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAyICYmIGZpcnN0X3BhY2tldC5zaWduYXR1cmVUeXBlIDwgMTYpIHx8XG5cdFx0XHQgICAgIGZpcnN0X3BhY2tldC50YWdUeXBlID09ICAzIHx8XG5cdFx0XHQgICAgIGZpcnN0X3BhY2tldC50YWdUeXBlID09ICA0IHx8XG5cdFx0XHRcdCBmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAgOCB8fFxuXHRcdFx0XHQgZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gIDkgfHxcblx0XHRcdFx0IGZpcnN0X3BhY2tldC50YWdUeXBlID09IDEwIHx8XG5cdFx0XHRcdCBmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAxMSB8fFxuXHRcdFx0XHQgZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gMTggfHxcblx0XHRcdFx0IGZpcnN0X3BhY2tldC50YWdUeXBlID09IDE5KSB7XG5cdFx0XHRcdG1lc3NhZ2VzW21lc3NhZ2VzLmxlbmd0aF0gPSBuZXcgb3BlbnBncF9tc2dfbWVzc2FnZSgpO1xuXHRcdFx0XHRtZXNzYWdlc1ttZXNzYWdlQ291bnRdLm1lc3NhZ2VQYWNrZXQgPSBmaXJzdF9wYWNrZXQ7XG5cdFx0XHRcdG1lc3NhZ2VzW21lc3NhZ2VDb3VudF0udHlwZSA9IGlucHV0LnR5cGU7XG5cdFx0XHRcdC8vIEVuY3J5cHRlZCBNZXNzYWdlXG5cdFx0XHRcdGlmIChmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSA5IHx8XG5cdFx0XHRcdCAgICBmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAxIHx8XG5cdFx0XHRcdCAgICBmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAzIHx8XG5cdFx0XHRcdCAgICBmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSAxOCkge1xuXHRcdFx0XHRcdGlmIChmaXJzdF9wYWNrZXQudGFnVHlwZSA9PSA5KSB7XG5cdFx0XHRcdFx0XHR1dGlsLnByaW50X2Vycm9yKFwidW5leHBlY3RlZCBvcGVucGdwIHBhY2tldFwiKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH0gZWxzZSBpZiAoZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gMSkge1xuXHRcdFx0XHRcdFx0dXRpbC5wcmludF9kZWJ1ZyhcInNlc3Npb24ga2V5IGZvdW5kOlxcbiBcIitmaXJzdF9wYWNrZXQudG9TdHJpbmcoKSk7XG5cdFx0XHRcdFx0XHR2YXIgaXNzZXNzaW9ua2V5ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdG1lc3NhZ2VzW21lc3NhZ2VDb3VudF0uc2Vzc2lvbktleXMgPSBuZXcgQXJyYXkoKTtcblx0XHRcdFx0XHRcdHZhciBzZXNzaW9uS2V5Q291bnQgPSAwO1xuXHRcdFx0XHRcdFx0d2hpbGUgKGlzc2Vzc2lvbmtleSkge1xuXHRcdFx0XHRcdFx0XHRtZXNzYWdlc1ttZXNzYWdlQ291bnRdLnNlc3Npb25LZXlzW3Nlc3Npb25LZXlDb3VudF0gPSBmaXJzdF9wYWNrZXQ7XG5cdFx0XHRcdFx0XHRcdG15cG9zICs9IGZpcnN0X3BhY2tldC5wYWNrZXRMZW5ndGggKyBmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoO1xuXHRcdFx0XHRcdFx0XHRsIC09IChmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoICsgZmlyc3RfcGFja2V0LmhlYWRlckxlbmd0aCk7XG5cdFx0XHRcdFx0XHRcdGZpcnN0X3BhY2tldCA9IG9wZW5wZ3BfcGFja2V0LnJlYWRfcGFja2V0KG1lc3NhZ2VTdHJpbmcsIG15cG9zLCBsKTtcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHRcdGlmIChmaXJzdF9wYWNrZXQudGFnVHlwZSAhPSAxICYmIGZpcnN0X3BhY2tldC50YWdUeXBlICE9IDMpXG5cdFx0XHRcdFx0XHRcdFx0aXNzZXNzaW9ua2V5ID0gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdHNlc3Npb25LZXlDb3VudCsrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0aWYgKGZpcnN0X3BhY2tldC50YWdUeXBlID09IDE4IHx8IGZpcnN0X3BhY2tldC50YWdUeXBlID09IDkpIHtcblx0XHRcdFx0XHRcdFx0dXRpbC5wcmludF9kZWJ1ZyhcImVuY3J5cHRlZCBkYXRhIGZvdW5kOlxcbiBcIitmaXJzdF9wYWNrZXQudG9TdHJpbmcoKSk7XG5cdFx0XHRcdFx0XHRcdG1lc3NhZ2VzW21lc3NhZ2VDb3VudF0uZW5jcnlwdGVkRGF0YSA9IGZpcnN0X3BhY2tldDtcblx0XHRcdFx0XHRcdFx0bXlwb3MgKz0gZmlyc3RfcGFja2V0LnBhY2tldExlbmd0aCtmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoO1xuXHRcdFx0XHRcdFx0XHRsIC09IChmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoK2ZpcnN0X3BhY2tldC5oZWFkZXJMZW5ndGgpO1xuXHRcdFx0XHRcdFx0XHRtZXNzYWdlQ291bnQrKztcblx0XHRcdFx0XHRcdFx0XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHR1dGlsLnByaW50X2RlYnVnKFwic29tZXRoaW5nIGlzIHdyb25nOiBcIitmaXJzdF9wYWNrZXQudGFnVHlwZSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGZpcnN0X3BhY2tldC50YWdUeXBlID09IDE4KSB7XG5cdFx0XHRcdFx0XHR1dGlsLnByaW50X2RlYnVnKFwic3ltbWV0cmljIGVuY3J5cHRlZCBkYXRhXCIpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2UgXG5cdFx0XHRcdFx0aWYgKGZpcnN0X3BhY2tldC50YWdUeXBlID09IDIgJiYgZmlyc3RfcGFja2V0LnNpZ25hdHVyZVR5cGUgPCAzKSB7XG5cdFx0XHRcdFx0Ly8gU2lnbmVkIE1lc3NhZ2Vcblx0XHRcdFx0XHRcdG15cG9zICs9IGZpcnN0X3BhY2tldC5wYWNrZXRMZW5ndGggKyBmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoO1xuXHRcdFx0XHRcdFx0bCAtPSAoZmlyc3RfcGFja2V0LnBhY2tldExlbmd0aCArIGZpcnN0X3BhY2tldC5oZWFkZXJMZW5ndGgpO1xuXHRcdFx0XHRcdFx0bWVzc2FnZXNbbWVzc2FnZUNvdW50XS50ZXh0ID0gc2lnbmF0dXJlVGV4dDtcblx0XHRcdFx0XHRcdG1lc3NhZ2VzW21lc3NhZ2VDb3VudF0uc2lnbmF0dXJlID0gZmlyc3RfcGFja2V0O1xuXHRcdFx0XHQgICAgICAgIG1lc3NhZ2VDb3VudCsrO1xuXHRcdFx0XHR9IGVsc2UgXG5cdFx0XHRcdFx0Ly8gU2lnbmVkIE1lc3NhZ2Vcblx0XHRcdFx0XHRpZiAoZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gNCkge1xuXHRcdFx0XHRcdFx0Ly9UT0RPOiBJbXBsZW1lbnQgY2hlY2tcblx0XHRcdFx0XHRcdG15cG9zICs9IGZpcnN0X3BhY2tldC5wYWNrZXRMZW5ndGggKyBmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoO1xuXHRcdFx0XHRcdFx0bCAtPSAoZmlyc3RfcGFja2V0LnBhY2tldExlbmd0aCArIGZpcnN0X3BhY2tldC5oZWFkZXJMZW5ndGgpO1xuXHRcdFx0XHR9IGVsc2UgXG5cdFx0XHRcdFx0aWYgKGZpcnN0X3BhY2tldC50YWdUeXBlID09IDgpIHtcblx0XHRcdFx0XHQvLyBDb21wcmVzc2VkIE1lc3NhZ2Vcblx0XHRcdFx0XHRcdG15cG9zICs9IGZpcnN0X3BhY2tldC5wYWNrZXRMZW5ndGggKyBmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoO1xuXHRcdFx0XHRcdFx0bCAtPSAoZmlyc3RfcGFja2V0LnBhY2tldExlbmd0aCArIGZpcnN0X3BhY2tldC5oZWFkZXJMZW5ndGgpO1xuXHRcdFx0XHQgICAgICAgIHZhciBkZWNvbXByZXNzZWRUZXh0ID0gZmlyc3RfcGFja2V0LmRlY29tcHJlc3MoKTtcblx0XHRcdFx0ICAgICAgICBtZXNzYWdlcyA9IG1lc3NhZ2VzLmNvbmNhdChvcGVucGdwLnJlYWRfbWVzc2FnZXNfZGVhcm1vcmVkKHt0ZXh0OiBkZWNvbXByZXNzZWRUZXh0LCBvcGVucGdwOiBkZWNvbXByZXNzZWRUZXh0fSkpO1xuXHRcdFx0XHR9IGVsc2Vcblx0XHRcdFx0XHQvLyBNYXJrZXIgUGFja2V0IChPYnNvbGV0ZSBMaXRlcmFsIFBhY2tldCkgKFRhZyAxMClcblx0XHRcdFx0XHQvLyBcIlN1Y2ggYSBwYWNrZXQgTVVTVCBiZSBpZ25vcmVkIHdoZW4gcmVjZWl2ZWQuXCIgc2VlIGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzQ4ODAjc2VjdGlvbi01Ljhcblx0XHRcdFx0XHRpZiAoZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gMTApIHtcblx0XHRcdFx0XHRcdC8vIHJlc2V0IG1lc3NhZ2VzXG5cdFx0XHRcdFx0XHRtZXNzYWdlcy5sZW5ndGggPSAwO1xuXHRcdFx0XHRcdFx0Ly8gY29udGludWUgd2l0aCBuZXh0IHBhY2tldFxuXHRcdFx0XHRcdFx0bXlwb3MgKz0gZmlyc3RfcGFja2V0LnBhY2tldExlbmd0aCArIGZpcnN0X3BhY2tldC5oZWFkZXJMZW5ndGg7XG5cdFx0XHRcdFx0XHRsIC09IChmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoICsgZmlyc3RfcGFja2V0LmhlYWRlckxlbmd0aCk7XG5cdFx0XHRcdH0gZWxzZSBcblx0XHRcdFx0XHRpZiAoZmlyc3RfcGFja2V0LnRhZ1R5cGUgPT0gMTEpIHtcblx0XHRcdFx0XHQvLyBMaXRlcmFsIE1lc3NhZ2UgLS0gd29yayBpcyBhbHJlYWR5IGRvbmUgaW4gcmVhZF9wYWNrZXRcblx0XHRcdFx0XHRteXBvcyArPSBmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoICsgZmlyc3RfcGFja2V0LmhlYWRlckxlbmd0aDtcblx0XHRcdFx0XHRsIC09IChmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoICsgZmlyc3RfcGFja2V0LmhlYWRlckxlbmd0aCk7XG5cdFx0XHRcdFx0c2lnbmF0dXJlVGV4dCA9IGZpcnN0X3BhY2tldC5kYXRhO1xuXHRcdFx0XHRcdG1lc3NhZ2VzW21lc3NhZ2VDb3VudF0uZGF0YSA9IGZpcnN0X3BhY2tldC5kYXRhO1xuXHRcdFx0XHRcdG1lc3NhZ2VDb3VudCsrO1xuXHRcdFx0XHR9IGVsc2UgXG5cdFx0XHRcdFx0aWYgKGZpcnN0X3BhY2tldC50YWdUeXBlID09IDE5KSB7XG5cdFx0XHRcdFx0Ly8gTW9kaWZpY2F0aW9uIERldGVjdCBDb2RlXG5cdFx0XHRcdFx0XHRteXBvcyArPSBmaXJzdF9wYWNrZXQucGFja2V0TGVuZ3RoICsgZmlyc3RfcGFja2V0LmhlYWRlckxlbmd0aDtcblx0XHRcdFx0XHRcdGwgLT0gKGZpcnN0X3BhY2tldC5wYWNrZXRMZW5ndGggKyBmaXJzdF9wYWNrZXQuaGVhZGVyTGVuZ3RoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dXRpbC5wcmludF9lcnJvcignbm8gbWVzc2FnZSBmb3VuZCEnKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiBtZXNzYWdlcztcblx0fVxuXHRcblx0LyoqXG5cdCAqIGNyZWF0ZXMgYSBiaW5hcnkgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGFuIGVuY3J5cHRlZCBhbmQgc2lnbmVkIG1lc3NhZ2UuXG5cdCAqIFRoZSBtZXNzYWdlIHdpbGwgYmUgZW5jcnlwdGVkIHdpdGggdGhlIHB1YmxpYyBrZXlzIHNwZWNpZmllZCBhbmQgc2lnbmVkXG5cdCAqIHdpdGggdGhlIHNwZWNpZmllZCBwcml2YXRlIGtleS5cblx0ICogQHBhcmFtIHtPYmplY3R9IHByaXZhdGVrZXkge29iajogW29wZW5wZ3BfbXNnX3ByaXZhdGVrZXldfSBQcml2YXRlIGtleSBcblx0ICogdG8gYmUgdXNlZCB0byBzaWduIHRoZSBtZXNzYWdlXG5cdCAqIEBwYXJhbSB7T2JqZWN0W119IHB1YmxpY2tleXMgQW4gYXJyYWYgb2Yge29iajogW29wZW5wZ3BfbXNnX3B1YmxpY2tleV19XG5cdCAqIC0gcHVibGljIGtleXMgdG8gYmUgdXNlZCB0byBlbmNyeXB0IHRoZSBtZXNzYWdlIFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZXRleHQgbWVzc2FnZSB0ZXh0IHRvIGVuY3J5cHQgYW5kIHNpZ25cblx0ICogQHJldHVybiB7U3RyaW5nfSBhIGJpbmFyeSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1lc3NhZ2Ugd2hpY2ggXG5cdCAqIGNhbiBiZSBPcGVuUEdQIGFybW9yZWRcblx0ICovXG5cdGZ1bmN0aW9uIHdyaXRlX3NpZ25lZF9hbmRfZW5jcnlwdGVkX21lc3NhZ2UocHJpdmF0ZWtleSwgcHVibGlja2V5cywgbWVzc2FnZXRleHQpIHtcblx0XHR2YXIgcmVzdWx0ID0gXCJcIjtcblx0XHR2YXIgbGl0ZXJhbCA9IG5ldyBvcGVucGdwX3BhY2tldF9saXRlcmFsZGF0YSgpLndyaXRlX3BhY2tldChtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZyxcIlxcblwiKS5yZXBsYWNlKC9cXG4vZyxcIlxcclxcblwiKSk7XG5cdFx0dXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcImxpdGVyYWxfcGFja2V0OiB8XCIrbGl0ZXJhbCtcInxcXG5cIixsaXRlcmFsKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHB1YmxpY2tleXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdHZhciBvbmVwYXNzc2lnbmF0dXJlID0gbmV3IG9wZW5wZ3BfcGFja2V0X29uZXBhc3NzaWduYXR1cmUoKTtcblx0XHRcdHZhciBvbmVwYXNzc2lnc3RyID0gXCJcIjtcblx0XHRcdGlmIChpID09IDApXG5cdFx0XHRcdG9uZXBhc3NzaWdzdHIgPSBvbmVwYXNzc2lnbmF0dXJlLndyaXRlX3BhY2tldCgxLCBvcGVucGdwLmNvbmZpZy5jb25maWcucHJlZmVyX2hhc2hfYWxnb3JpdGhtLCAgcHJpdmF0ZWtleSwgZmFsc2UpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHRvbmVwYXNzc2lnc3RyID0gb25lcGFzc3NpZ25hdHVyZS53cml0ZV9wYWNrZXQoMSwgb3BlbnBncC5jb25maWcuY29uZmlnLnByZWZlcl9oYXNoX2FsZ29yaXRobSwgIHByaXZhdGVrZXksIGZhbHNlKTtcblx0XHRcdHV0aWwucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAoXCJvbmVwYXNzc2lnc3RyOiB8XCIrb25lcGFzc3NpZ3N0citcInxcXG5cIixvbmVwYXNzc2lnc3RyKTtcblx0XHRcdHZhciBkYXRhc2lnbmF0dXJlID0gbmV3IG9wZW5wZ3BfcGFja2V0X3NpZ25hdHVyZSgpLndyaXRlX21lc3NhZ2Vfc2lnbmF0dXJlKDEsIG1lc3NhZ2V0ZXh0LnJlcGxhY2UoL1xcclxcbi9nLFwiXFxuXCIpLnJlcGxhY2UoL1xcbi9nLFwiXFxyXFxuXCIpLCBwcml2YXRla2V5KTtcblx0XHRcdHV0aWwucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAoXCJkYXRhc2lnbmF0dXJlOiB8XCIrZGF0YXNpZ25hdHVyZS5vcGVucGdwK1wifFxcblwiLGRhdGFzaWduYXR1cmUub3BlbnBncCk7XG5cdFx0XHRpZiAoaSA9PSAwKSB7XG5cdFx0XHRcdHJlc3VsdCA9IG9uZXBhc3NzaWdzdHIrbGl0ZXJhbCtkYXRhc2lnbmF0dXJlLm9wZW5wZ3A7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXN1bHQgPSBvbmVwYXNzc2lnc3RyK3Jlc3VsdCtkYXRhc2lnbmF0dXJlLm9wZW5wZ3A7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdFxuXHRcdHV0aWwucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAoXCJzaWduZWQgcGFja2V0OiB8XCIrcmVzdWx0K1wifFxcblwiLHJlc3VsdCk7XG5cdFx0Ly8gc2lnbmF0dXJlcyBkb25lLi4gbm93IGVuY3J5cHRpb25cblx0XHR2YXIgc2Vzc2lvbmtleSA9IG9wZW5wZ3BfY3J5cHRvX2dlbmVyYXRlU2Vzc2lvbktleShvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIpOyBcblx0XHR2YXIgcmVzdWx0MiA9IFwiXCI7XG5cdFx0XG5cdFx0Ly8gY3JlYXRpbmcgc2Vzc2lvbiBrZXlzIGZvciBlYWNoIHJlY2lwaWVudFxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcHVibGlja2V5cy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIHBrZXkgPSBwdWJsaWNrZXlzW2ldLmdldEVuY3J5cHRpb25LZXkoKTtcblx0XHRcdGlmIChwa2V5ID09IG51bGwpIHtcblx0XHRcdFx0dXRpbC5wcmludF9lcnJvcihcIm5vIGVuY3J5cHRpb24ga2V5IGZvdW5kISBLZXkgaXMgZm9yIHNpZ25pbmcgb25seS5cIik7XG5cdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0fVxuXHRcdFx0cmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkc2Vzc2lvbmtleSgpLlxuXHRcdFx0XHRcdHdyaXRlX3B1Yl9rZXlfcGFja2V0KFxuXHRcdFx0XHRcdFx0cGtleS5nZXRLZXlJZCgpLFxuXHRcdFx0XHRcdFx0cGtleS5NUElzLFxuXHRcdFx0XHRcdFx0cGtleS5wdWJsaWNLZXlBbGdvcml0aG0sXG5cdFx0XHRcdFx0XHRvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsXG5cdFx0XHRcdFx0XHRzZXNzaW9ua2V5KTtcblx0XHR9XG5cdFx0aWYgKG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5pbnRlZ3JpdHlfcHJvdGVjdCkge1xuXHRcdFx0cmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkaW50ZWdyaXR5cHJvdGVjdGVkZGF0YSgpLndyaXRlX3BhY2tldChvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsIHNlc3Npb25rZXksIHJlc3VsdCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlc3VsdDIgKz0gbmV3IG9wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGEoKS53cml0ZV9wYWNrZXQob3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyLCBzZXNzaW9ua2V5LCByZXN1bHQpO1xuXHRcdH1cblx0XHRyZXR1cm4gb3BlbnBncF9lbmNvZGluZ19hcm1vcigzLHJlc3VsdDIsbnVsbCxudWxsKTtcblx0fVxuXHQvKipcblx0ICogY3JlYXRlcyBhIGJpbmFyeSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYW4gZW5jcnlwdGVkIG1lc3NhZ2UuXG5cdCAqIFRoZSBtZXNzYWdlIHdpbGwgYmUgZW5jcnlwdGVkIHdpdGggdGhlIHB1YmxpYyBrZXlzIHNwZWNpZmllZCBcblx0ICogQHBhcmFtIHtPYmplY3RbXX0gcHVibGlja2V5cyBBbiBhcnJheSBvZiB7b2JqOiBbb3BlbnBncF9tc2dfcHVibGlja2V5XX1cblx0ICogLXB1YmxpYyBrZXlzIHRvIGJlIHVzZWQgdG8gZW5jcnlwdCB0aGUgbWVzc2FnZSBcblx0ICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2V0ZXh0IG1lc3NhZ2UgdGV4dCB0byBlbmNyeXB0XG5cdCAqIEByZXR1cm4ge1N0cmluZ30gYSBiaW5hcnkgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtZXNzYWdlXG5cdCAqIHdoaWNoIGNhbiBiZSBPcGVuUEdQIGFybW9yZWRcblx0ICovXG5cdGZ1bmN0aW9uIHdyaXRlX2VuY3J5cHRlZF9tZXNzYWdlKHB1YmxpY2tleXMsIG1lc3NhZ2V0ZXh0KSB7XG5cdFx0dmFyIHJlc3VsdCA9IFwiXCI7XG5cdFx0dmFyIGxpdGVyYWwgPSBuZXcgb3BlbnBncF9wYWNrZXRfbGl0ZXJhbGRhdGEoKS53cml0ZV9wYWNrZXQobWVzc2FnZXRleHQucmVwbGFjZSgvXFxyXFxuL2csXCJcXG5cIikucmVwbGFjZSgvXFxuL2csXCJcXHJcXG5cIikpO1xuXHRcdHV0aWwucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAoXCJsaXRlcmFsX3BhY2tldDogfFwiK2xpdGVyYWwrXCJ8XFxuXCIsbGl0ZXJhbCk7XG5cdFx0cmVzdWx0ID0gbGl0ZXJhbDtcblx0XHRcblx0XHQvLyBzaWduYXR1cmVzIGRvbmUuLiBub3cgZW5jcnlwdGlvblxuXHRcdHZhciBzZXNzaW9ua2V5ID0gb3BlbnBncF9jcnlwdG9fZ2VuZXJhdGVTZXNzaW9uS2V5KG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcik7IFxuXHRcdHZhciByZXN1bHQyID0gXCJcIjtcblx0XHRcblx0XHQvLyBjcmVhdGluZyBzZXNzaW9uIGtleXMgZm9yIGVhY2ggcmVjaXBpZW50XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBwdWJsaWNrZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHR2YXIgcGtleSA9IHB1YmxpY2tleXNbaV0uZ2V0RW5jcnlwdGlvbktleSgpO1xuXHRcdFx0aWYgKHBrZXkgPT0gbnVsbCkge1xuXHRcdFx0XHR1dGlsLnByaW50X2Vycm9yKFwibm8gZW5jcnlwdGlvbiBrZXkgZm91bmQhIEtleSBpcyBmb3Igc2lnbmluZyBvbmx5LlwiKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHRyZXN1bHQyICs9IG5ldyBvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRzZXNzaW9ua2V5KCkuXG5cdFx0XHRcdFx0d3JpdGVfcHViX2tleV9wYWNrZXQoXG5cdFx0XHRcdFx0XHRwa2V5LmdldEtleUlkKCksXG5cdFx0XHRcdFx0XHRwa2V5Lk1QSXMsXG5cdFx0XHRcdFx0XHRwa2V5LnB1YmxpY0tleUFsZ29yaXRobSxcblx0XHRcdFx0XHRcdG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcixcblx0XHRcdFx0XHRcdHNlc3Npb25rZXkpO1xuXHRcdH1cblx0XHRpZiAob3BlbnBncC5jb25maWcuY29uZmlnLmludGVncml0eV9wcm90ZWN0KSB7XG5cdFx0XHRyZXN1bHQyICs9IG5ldyBvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRpbnRlZ3JpdHlwcm90ZWN0ZWRkYXRhKCkud3JpdGVfcGFja2V0KG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlciwgc2Vzc2lvbmtleSwgcmVzdWx0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YSgpLndyaXRlX3BhY2tldChvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsIHNlc3Npb25rZXksIHJlc3VsdCk7XG5cdFx0fVxuXHRcdHJldHVybiBvcGVucGdwX2VuY29kaW5nX2FybW9yKDMscmVzdWx0MixudWxsLG51bGwpO1xuXHR9XG5cdFxuXHQvKipcblx0ICogY3JlYXRlcyBhIGJpbmFyeSBzdHJpbmcgcmVwcmVzZW50YXRpb24gYSBzaWduZWQgbWVzc2FnZS5cblx0ICogVGhlIG1lc3NhZ2Ugd2lsbCBiZSBzaWduZWQgd2l0aCB0aGUgc3BlY2lmaWVkIHByaXZhdGUga2V5LlxuXHQgKiBAcGFyYW0ge09iamVjdH0gcHJpdmF0ZWtleSB7b2JqOiBbb3BlbnBncF9tc2dfcHJpdmF0ZWtleV19XG5cdCAqIC0gdGhlIHByaXZhdGUga2V5IHRvIGJlIHVzZWQgdG8gc2lnbiB0aGUgbWVzc2FnZSBcblx0ICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2V0ZXh0IG1lc3NhZ2UgdGV4dCB0byBzaWduXG5cdCAqIEByZXR1cm4ge09iamVjdH0ge09iamVjdDogdGV4dCBbU3RyaW5nXX0sIG9wZW5wZ3A6IHtTdHJpbmd9IGEgYmluYXJ5XG5cdCAqICBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1lc3NhZ2Ugd2hpY2ggY2FuIGJlIE9wZW5QR1Bcblx0ICogICBhcm1vcmVkKG9wZW5wZ3ApIGFuZCBhIHRleHQgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1lc3NhZ2UgKHRleHQpLiBcblx0ICogVGhpcyBjYW4gYmUgZGlyZWN0bHkgdXNlZCB0byBPcGVuUEdQIGFybW9yIHRoZSBtZXNzYWdlXG5cdCAqL1xuXHRmdW5jdGlvbiB3cml0ZV9zaWduZWRfbWVzc2FnZShwcml2YXRla2V5LCBtZXNzYWdldGV4dCkge1xuXHRcdHZhciBzaWcgPSBuZXcgb3BlbnBncF9wYWNrZXRfc2lnbmF0dXJlKCkud3JpdGVfbWVzc2FnZV9zaWduYXR1cmUoMSwgbWVzc2FnZXRleHQucmVwbGFjZSgvXFxyXFxuL2csXCJcXG5cIikucmVwbGFjZSgvXFxuLyxcIlxcclxcblwiKSwgcHJpdmF0ZWtleSk7XG5cdFx0dmFyIHJlc3VsdCA9IHt0ZXh0OiBtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZyxcIlxcblwiKS5yZXBsYWNlKC9cXG4vLFwiXFxyXFxuXCIpLCBvcGVucGdwOiBzaWcub3BlbnBncCwgaGFzaDogc2lnLmhhc2h9O1xuXHRcdHJldHVybiBvcGVucGdwX2VuY29kaW5nX2FybW9yKDIscmVzdWx0LCBudWxsLCBudWxsKVxuXHR9XG5cdFxuXHQvKipcblx0ICogZ2VuZXJhdGVzIGEgbmV3IGtleSBwYWlyIGZvciBvcGVucGdwLiBCZXRhIHN0YWdlLiBDdXJyZW50bHkgb25seSBcblx0ICogc3VwcG9ydHMgUlNBIGtleXMsIGFuZCBubyBzdWJrZXlzLlxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGtleVR5cGUgdG8gaW5kaWNhdGUgd2hhdCB0eXBlIG9mIGtleSB0byBtYWtlLiBcblx0ICogUlNBIGlzIDEuIEZvbGxvd3MgYWxnb3JpdGhtcyBvdXRsaW5lZCBpbiBPcGVuUEdQLlxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IG51bUJpdHMgbnVtYmVyIG9mIGJpdHMgZm9yIHRoZSBrZXkgY3JlYXRpb24uIChzaG91bGQgXG5cdCAqIGJlIDEwMjQrLCBnZW5lcmFsbHkpXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB1c2VySWQgYXNzdW1lcyBhbHJlYWR5IGluIGZvcm0gb2YgXCJVc2VyIE5hbWUgXG5cdCAqIDx1c2VybmFtZUBlbWFpbC5jb20+XCJcblx0ICogQHBhcmFtIHtTdHJpbmd9IHBhc3NwaHJhc2UgVGhlIHBhc3NwaHJhc2UgdXNlZCB0byBlbmNyeXB0IHRoZSByZXN1bHRpbmcgcHJpdmF0ZSBrZXlcblx0ICogQHJldHVybiB7T2JqZWN0fSB7cHJpdmF0ZUtleTogW29wZW5wZ3BfbXNnX3ByaXZhdGVrZXldLCBcblx0ICogcHJpdmF0ZUtleUFybW9yZWQ6IFtzdHJpbmddLCBwdWJsaWNLZXlBcm1vcmVkOiBbc3RyaW5nXX1cblx0ICovXG5cdGZ1bmN0aW9uIGdlbmVyYXRlX2tleV9wYWlyKGtleVR5cGUsIG51bUJpdHMsIHVzZXJJZCwgcGFzc3BocmFzZSl7XG5cdFx0dmFyIHVzZXJJZFBhY2tldCA9IG5ldyBvcGVucGdwX3BhY2tldF91c2VyaWQoKTtcblx0XHR2YXIgdXNlcklkU3RyaW5nID0gdXNlcklkUGFja2V0LndyaXRlX3BhY2tldCh1c2VySWQpO1xuXHRcdFxuXHRcdHZhciBrZXlQYWlyID0gb3BlbnBncF9jcnlwdG9fZ2VuZXJhdGVLZXlQYWlyKGtleVR5cGUsbnVtQml0cywgcGFzc3BocmFzZSwgb3BlbnBncC5jb25maWcuY29uZmlnLnByZWZlcl9oYXNoX2FsZ29yaXRobSwgMyk7XG5cdFx0dmFyIHByaXZLZXlTdHJpbmcgPSBrZXlQYWlyLnByaXZhdGVLZXk7XG5cdFx0dmFyIHByaXZLZXlQYWNrZXQgPSBuZXcgb3BlbnBncF9wYWNrZXRfa2V5bWF0ZXJpYWwoKS5yZWFkX3ByaXZfa2V5KHByaXZLZXlTdHJpbmcuc3RyaW5nLDMscHJpdktleVN0cmluZy5zdHJpbmcubGVuZ3RoKTtcblx0XHRpZighcHJpdktleVBhY2tldC5kZWNyeXB0U2VjcmV0TVBJcyhwYXNzcGhyYXNlKSlcblx0XHQgICAgdXRpbC5wcmludF9lcnJvcignSXNzdWUgY3JlYXRpbmcga2V5LiBVbmFibGUgdG8gcmVhZCByZXN1bHRpbmcgcHJpdmF0ZSBrZXknKTtcblx0XHR2YXIgcHJpdktleSA9IG5ldyBvcGVucGdwX21zZ19wcml2YXRla2V5KCk7XG5cdFx0cHJpdktleS5wcml2YXRlS2V5UGFja2V0ID0gcHJpdktleVBhY2tldDtcblx0XHRwcml2S2V5LmdldFByZWZlcnJlZFNpZ25hdHVyZUhhc2hBbGdvcml0aG0gPSBmdW5jdGlvbigpe3JldHVybiBvcGVucGdwLmNvbmZpZy5jb25maWcucHJlZmVyX2hhc2hfYWxnb3JpdGhtfTsvL25lZWQgdG8gb3ZlcnJpZGUgdGhpcyB0byBzb2x2ZSBjYXRjaCAyMiB0byBnZW5lcmF0ZSBzaWduYXR1cmUuIDggaXMgdmFsdWUgZm9yIFNIQTI1NlxuXHRcdFxuXHRcdHZhciBwdWJsaWNLZXlTdHJpbmcgPSBwcml2S2V5LnByaXZhdGVLZXlQYWNrZXQucHVibGljS2V5LmRhdGE7XG5cdFx0dmFyIGhhc2hEYXRhID0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDk5KSsgU3RyaW5nLmZyb21DaGFyQ29kZSgoKHB1YmxpY0tleVN0cmluZy5sZW5ndGgpID4+IDgpICYgMHhGRikgXG5cdFx0XHQrIFN0cmluZy5mcm9tQ2hhckNvZGUoKHB1YmxpY0tleVN0cmluZy5sZW5ndGgpICYgMHhGRikgK3B1YmxpY0tleVN0cmluZytTdHJpbmcuZnJvbUNoYXJDb2RlKDB4QjQpICtcblx0XHRcdFN0cmluZy5mcm9tQ2hhckNvZGUoKHVzZXJJZC5sZW5ndGgpID4+IDI0KSArU3RyaW5nLmZyb21DaGFyQ29kZSgoKHVzZXJJZC5sZW5ndGgpID4+IDE2KSAmIDB4RkYpIFxuXHRcdFx0KyBTdHJpbmcuZnJvbUNoYXJDb2RlKCgodXNlcklkLmxlbmd0aCkgPj4gOCkgJiAweEZGKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoKHVzZXJJZC5sZW5ndGgpICYgMHhGRikgKyB1c2VySWRcblx0XHR2YXIgc2lnbmF0dXJlID0gbmV3IG9wZW5wZ3BfcGFja2V0X3NpZ25hdHVyZSgpO1xuXHRcdHNpZ25hdHVyZSA9IHNpZ25hdHVyZS53cml0ZV9tZXNzYWdlX3NpZ25hdHVyZSgxNixoYXNoRGF0YSwgcHJpdktleSk7XG5cdFx0dmFyIHB1YmxpY0FybW9yZWQgPSBvcGVucGdwX2VuY29kaW5nX2FybW9yKDQsIGtleVBhaXIucHVibGljS2V5LnN0cmluZyArIHVzZXJJZFN0cmluZyArIHNpZ25hdHVyZS5vcGVucGdwICk7XG5cblx0XHR2YXIgcHJpdkFybW9yZWQgPSBvcGVucGdwX2VuY29kaW5nX2FybW9yKDUscHJpdktleVN0cmluZy5zdHJpbmcrdXNlcklkU3RyaW5nK3NpZ25hdHVyZS5vcGVucGdwKTtcblx0XHRcblx0XHRyZXR1cm4ge3ByaXZhdGVLZXkgOiBwcml2S2V5LCBwcml2YXRlS2V5QXJtb3JlZDogcHJpdkFybW9yZWQsIHB1YmxpY0tleUFybW9yZWQ6IHB1YmxpY0FybW9yZWR9XG5cdH1cblx0XG5cdHRoaXMuZ2VuZXJhdGVfa2V5X3BhaXIgPSBnZW5lcmF0ZV9rZXlfcGFpcjtcblx0dGhpcy53cml0ZV9zaWduZWRfbWVzc2FnZSA9IHdyaXRlX3NpZ25lZF9tZXNzYWdlOyBcblx0dGhpcy53cml0ZV9zaWduZWRfYW5kX2VuY3J5cHRlZF9tZXNzYWdlID0gd3JpdGVfc2lnbmVkX2FuZF9lbmNyeXB0ZWRfbWVzc2FnZTtcblx0dGhpcy53cml0ZV9lbmNyeXB0ZWRfbWVzc2FnZSA9IHdyaXRlX2VuY3J5cHRlZF9tZXNzYWdlO1xuXHR0aGlzLnJlYWRfbWVzc2FnZSA9IHJlYWRfbWVzc2FnZTtcblx0dGhpcy5yZWFkX21lc3NhZ2VzX2RlYXJtb3JlZCA9IHJlYWRfbWVzc2FnZXNfZGVhcm1vcmVkO1xuXHR0aGlzLnJlYWRfcHVibGljS2V5ID0gcmVhZF9wdWJsaWNLZXk7XG5cdHRoaXMucmVhZF9wcml2YXRlS2V5ID0gcmVhZF9wcml2YXRlS2V5O1xuXHR0aGlzLmluaXQgPSBpbml0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBfb3BlbnBncCgpO1xuXG4iLCJcbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyk7XG5cbi8vIFRoaXMgaXMgcHJldHR5IHVnbHksIGJ1dCBicm93c2VyaWZ5IG5lZWRzIHRvIGhhdmUgdGhlIHJlcXVpcmVzIGV4cGxpY2l0bHkgd3JpdHRlbi5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRjb21wcmVzc2VkOiByZXF1aXJlKCcuL2NvbXByZXNzZWQuanMnKSxcblx0c3ltX2VuY3J5cHRlZF9pbnRlZ3JpdHlfcHJvdGVjdGVkOiByZXF1aXJlKCcuL3N5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZC5qcycpLFxuXHRwdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleTogcmVxdWlyZSgnLi9wdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleS5qcycpLFxuXHRzeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5OiByZXF1aXJlKCcuL3N5bV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkuanMnKSxcblx0bGl0ZXJhbDogcmVxdWlyZSgnLi9saXRlcmFsLmpzJyksXG5cdHB1YmxpY19rZXk6IHJlcXVpcmUoJy4vcHVibGljX2tleS5qcycpLFxuXHRzeW1tZXRyaWNhbGx5X2VuY3J5cHRlZDogcmVxdWlyZSgnLi9zeW1tZXRyaWNhbGx5X2VuY3J5cHRlZC5qcycpLFxuXHRtYXJrZXI6IHJlcXVpcmUoJy4vbWFya2VyLmpzJyksXG5cdHB1YmxpY19zdWJrZXk6IHJlcXVpcmUoJy4vcHVibGljX3N1YmtleS5qcycpLFxuXHR1c2VyX2F0dHJpYnV0ZTogcmVxdWlyZSgnLi91c2VyX2F0dHJpYnV0ZS5qcycpLFxuXHRvbmVfcGFzc19zaWduYXR1cmU6IHJlcXVpcmUoJy4vb25lX3Bhc3Nfc2lnbmF0dXJlLmpzJyksXG5cdHNlY3JldF9rZXk6IHJlcXVpcmUoJy4vc2VjcmV0X2tleS5qcycpLFxuXHR1c2VyaWQ6IHJlcXVpcmUoJy4vdXNlcmlkLmpzJyksXG5cdHNlY3JldF9zdWJrZXk6IHJlcXVpcmUoJy4vc2VjcmV0X3N1YmtleS5qcycpLFxuXHRzaWduYXR1cmU6IHJlcXVpcmUoJy4vc2lnbmF0dXJlLmpzJyksXG5cdHRydXN0OiByZXF1aXJlKCcuL3RydXN0LmpzJylcbn1cblxuZm9yKHZhciBpIGluIGVudW1zLnBhY2tldCkge1xuXHR2YXIgcGFja2V0Q2xhc3MgPSBtb2R1bGUuZXhwb3J0c1tpXTtcblxuXHRpZihwYWNrZXRDbGFzcyAhPSB1bmRlZmluZWQpXG5cdFx0cGFja2V0Q2xhc3MucHJvdG90eXBlLnRhZyA9IGVudW1zLnBhY2tldFtpXTtcbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG5cdEpYRyA9IHJlcXVpcmUoJy4uL2NvbXByZXNzaW9uL2p4Zy5qcycpLFxuXHRiYXNlNjQgPSByZXF1aXJlKCcuLi9lbmNvZGluZy9iYXNlNjQuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIENvbXByZXNzZWQgRGF0YSBQYWNrZXQgKFRhZyA4KVxuICogXG4gKiBSRkM0ODgwIDUuNjpcbiAqIFRoZSBDb21wcmVzc2VkIERhdGEgcGFja2V0IGNvbnRhaW5zIGNvbXByZXNzZWQgZGF0YS4gIFR5cGljYWxseSwgdGhpc1xuICogcGFja2V0IGlzIGZvdW5kIGFzIHRoZSBjb250ZW50cyBvZiBhbiBlbmNyeXB0ZWQgcGFja2V0LCBvciBmb2xsb3dpbmdcbiAqIGEgU2lnbmF0dXJlIG9yIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQsIGFuZCBjb250YWlucyBhIGxpdGVyYWwgZGF0YVxuICogcGFja2V0LlxuICovICAgXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9jb21wcmVzc2VkKCkge1xuXHQvKiogQHR5cGUge3BhY2tldGxpc3R9ICovXG5cdHRoaXMucGFja2V0cztcblx0LyoqIEB0eXBlIHtjb21wcmVzc2lvbn0gKi9cblx0dGhpcy5hbGdvcml0aG0gPSAndW5jb21wcmVzc2VkJztcblxuXHR0aGlzLmNvbXByZXNzZWQgPSBudWxsO1xuXG5cdFxuXHQvKipcblx0ICogUGFyc2luZyBmdW5jdGlvbiBmb3IgdGhlIHBhY2tldC5cblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2YgYSB0YWcgOCBwYWNrZXRcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBQb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuXHQgKiBAcGFyQU0ge2lOVEVHRVJ9IExFTiBsRU5HVEggT0YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBcblx0ICogaW5wdXQgYXQgcG9zaXRpb25cblx0ICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfY29tcHJlc3NlZH0gT2JqZWN0IHJlcHJlc2VudGF0aW9uXG5cdCAqL1xuXHR0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdC8vIE9uZSBvY3RldCB0aGF0IGdpdmVzIHRoZSBhbGdvcml0aG0gdXNlZCB0byBjb21wcmVzcyB0aGUgcGFja2V0LlxuXHRcdHRoaXMuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5jb21wcmVzc2lvbiwgYnl0ZXMuY2hhckNvZGVBdCgwKSk7XG5cblx0XHQvLyBDb21wcmVzc2VkIGRhdGEsIHdoaWNoIG1ha2VzIHVwIHRoZSByZW1haW5kZXIgb2YgdGhlIHBhY2tldC5cblx0XHR0aGlzLmNvbXByZXNzZWQgPSBieXRlcy5zdWJzdHIoMSk7XG5cblx0XHR0aGlzLmRlY29tcHJlc3MoKTtcblx0fVxuXG5cdFxuXHRcblx0dGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmKHRoaXMuY29tcHJlc3NlZCA9PSBudWxsKVxuXHRcdFx0dGhpcy5jb21wcmVzcygpO1xuXG5cdFx0cmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuY29tcHJlc3Npb24sIHRoaXMuYWxnb3JpdGhtKSkgXG5cdFx0XHQrIHRoaXMuY29tcHJlc3NlZDtcblx0fVxuXG5cblx0LyoqXG5cdCAqIERlY29tcHJlc3Npb24gbWV0aG9kIGZvciBkZWNvbXByZXNzaW5nIHRoZSBjb21wcmVzc2VkIGRhdGFcblx0ICogcmVhZCBieSByZWFkX3BhY2tldFxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSBkZWNvbXByZXNzZWQgZGF0YVxuXHQgKi9cblx0dGhpcy5kZWNvbXByZXNzID0gZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGRlY29tcHJlc3NlZDtcblxuXHRcdHN3aXRjaCAodGhpcy5hbGdvcml0aG0pIHtcblx0XHRjYXNlICd1bmNvbXByZXNzZWQnOlxuXHRcdFx0ZGVjb21wcmVzc2VkID0gdGhpcy5jb21wcmVzc2VkO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlICd6aXAnOlxuXHRcdFx0dmFyIGNvbXBEYXRhID0gdGhpcy5jb21wcmVzc2VkO1xuXG5cdFx0XHR2YXIgcmFkaXggPSBiYXNlNjQuZW5jb2RlKGNvbXBEYXRhKS5yZXBsYWNlKC9cXG4vZyxcIlwiKTtcblx0XHRcdC8vIG5vIGhlYWRlciBpbiB0aGlzIGNhc2UsIGRpcmVjdGx5IGNhbGwgZGVmbGF0ZVxuXHRcdFx0dmFyIGp4Z19vYmogPSBuZXcgSlhHLlV0aWwuVW56aXAoSlhHLlV0aWwuQmFzZTY0LmRlY29kZUFzQXJyYXkocmFkaXgpKTtcblxuXHRcdFx0ZGVjb21wcmVzc2VkID0gdW5lc2NhcGUoanhnX29iai5kZWZsYXRlKClbMF1bMF0pO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlICd6bGliJzpcblx0XHRcdC8vUkZDIDE5NTAuIEJpdHMgMC0zIENvbXByZXNzaW9uIE1ldGhvZFxuXHRcdFx0dmFyIGNvbXByZXNzaW9uTWV0aG9kID0gdGhpcy5jb21wcmVzc2VkLmNoYXJDb2RlQXQoMCkgJSAweDEwO1xuXG5cdFx0XHQvL0JpdHMgNC03IFJGQyAxOTUwIGFyZSBMWjc3IFdpbmRvdy4gR2VuZXJhbGx5IHRoaXMgdmFsdWUgaXMgNyA9PSAzMmsgd2luZG93IHNpemUuXG5cdFx0XHQvLyAybmQgQnl0ZSBpbiBSRkMgMTk1MCBpcyBmb3IgXCJGTEFHc1wiIEFsbG93cyBmb3IgYSBEaWN0aW9uYXJ5IFxuXHRcdFx0Ly8gKGhvdyBpcyB0aGlzIGRlZmluZWQpLiBCYXNpYyBjaGVja3N1bSwgYW5kIGNvbXByZXNzaW9uIGxldmVsLlxuXG5cdFx0XHRpZiAoY29tcHJlc3Npb25NZXRob2QgPT0gOCkgeyAvL0NNIDggaXMgZm9yIERFRkxBVEUsIFJGQyAxOTUxXG5cdFx0XHRcdC8vIHJlbW92ZSA0IGJ5dGVzIEFETEVSMzIgY2hlY2tzdW0gZnJvbSB0aGUgZW5kXG5cdFx0XHRcdHZhciBjb21wRGF0YSA9IHRoaXMuY29tcHJlc3NlZC5zdWJzdHJpbmcoMCwgdGhpcy5jb21wcmVzc2VkLmxlbmd0aCAtIDQpO1xuXHRcdFx0XHR2YXIgcmFkaXggPSBiYXNlNjQuZW5jb2RlKGNvbXBEYXRhKS5yZXBsYWNlKC9cXG4vZyxcIlwiKTtcblx0XHRcdFx0Ly9UT0RPIGNoZWNrIEFETEVSMzIgY2hlY2tzdW1cblx0XHRcdFx0ZGVjb21wcmVzc2VkID0gSlhHLmRlY29tcHJlc3MocmFkaXgpO1xuXHRcdFx0XHRicmVhaztcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSBaTElCIG9ubHkgc3VwcG9ydHMgXCIgK1xuXHRcdFx0XHRcdFwiREVGTEFURSBjb21wcmVzc2lvbiBtZXRob2QuXCIpO1xuXHRcdFx0fVxuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlICdiemlwMic6XG5cdFx0XHQvLyBUT0RPOiBuZWVkIHRvIGltcGxlbWVudCB0aGlzXG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0NvbXByZXNzaW9uIGFsZ29yaXRobSBCWmlwMiBbQloyXSBpcyBub3QgaW1wbGVtZW50ZWQuJyk7XG5cdFx0XHRicmVhaztcblxuXHRcdGRlZmF1bHQ6XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJDb21wcmVzc2lvbiBhbGdvcml0aG0gdW5rbm93biA6XCIgKyB0aGlzLmFsb2dyaXRobSk7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cblx0XHR0aGlzLnBhY2tldHMucmVhZChkZWNvbXByZXNzZWQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbXByZXNzIHRoZSBwYWNrZXQgZGF0YSAobWVtYmVyIGRlY29tcHJlc3NlZERhdGEpXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gdHlwZSBBbGdvcml0aG0gdG8gYmUgdXNlZCAvLyBTZWUgUkZDIDQ4ODAgOS4zXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIERhdGEgdG8gYmUgY29tcHJlc3NlZFxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSBjb21wcmVzc2VkIGRhdGEgc3RvcmVkIGluIGF0dHJpYnV0ZSBjb21wcmVzc2VkRGF0YVxuXHQgKi9cblx0dGhpcy5jb21wcmVzcyA9IGZ1bmN0aW9uKCkge1xuXHRcdHN3aXRjaCAodGhpcy5hbGdvcml0aG0pIHtcblxuXHRcdGNhc2UgJ3VuY29tcHJlc3NlZCc6IC8vIC0gVW5jb21wcmVzc2VkXG5cdFx0XHR0aGlzLmNvbXByZXNzZWQgPSB0aGlzLnBhY2tldHMud3JpdGUoKTtcblx0XHRcdGJyZWFrO1xuXG5cdFx0Y2FzZSAnemlwJzogLy8gLSBaSVAgW1JGQzE5NTFdXG5cdFx0XHR1dGlsLnByaW50X2Vycm9yKFwiQ29tcHJlc3Npb24gYWxnb3JpdGhtIFpJUCBbUkZDMTk1MV0gaXMgbm90IGltcGxlbWVudGVkLlwiKTtcblx0XHRcdGJyZWFrO1xuXG5cdFx0Y2FzZSAnemxpYic6IC8vIC0gWkxJQiBbUkZDMTk1MF1cblx0XHRcdC8vIFRPRE86IG5lZWQgdG8gaW1wbGVtZW50IHRoaXNcblx0XHRcdHV0aWwucHJpbnRfZXJyb3IoXCJDb21wcmVzc2lvbiBhbGdvcml0aG0gWkxJQiBbUkZDMTk1MF0gaXMgbm90IGltcGxlbWVudGVkLlwiKTtcblx0XHRcdGJyZWFrO1xuXG5cdFx0Y2FzZSAnYnppcDInOiAvLyAgLSBCWmlwMiBbQloyXVxuXHRcdFx0Ly8gVE9ETzogbmVlZCB0byBpbXBsZW1lbnQgdGhpc1xuXHRcdFx0dXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSBCWmlwMiBbQloyXSBpcyBub3QgaW1wbGVtZW50ZWQuXCIpO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRkZWZhdWx0OlxuXHRcdFx0dXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSB1bmtub3duIDpcIit0aGlzLnR5cGUpO1xuXHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9XG59O1xuIiwiXG52YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0bGlzdDogcmVxdWlyZSgnLi9wYWNrZXRsaXN0LmpzJyksXG59XG5cbnZhciBwYWNrZXRzID0gcmVxdWlyZSgnLi9hbGxfcGFja2V0cy5qcycpO1xuXG5mb3IodmFyIGkgaW4gcGFja2V0cylcblx0bW9kdWxlLmV4cG9ydHNbaV0gPSBwYWNrZXRzW2ldO1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG5cdGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIExpdGVyYWwgRGF0YSBQYWNrZXQgKFRhZyAxMSlcbiAqIFxuICogUkZDNDg4MCA1Ljk6IEEgTGl0ZXJhbCBEYXRhIHBhY2tldCBjb250YWlucyB0aGUgYm9keSBvZiBhIG1lc3NhZ2U7IGRhdGEgdGhhdFxuICogaXMgbm90IHRvIGJlIGZ1cnRoZXIgaW50ZXJwcmV0ZWQuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X2xpdGVyYWwoKSB7XG5cdHRoaXMuZm9ybWF0ID0gJ3V0ZjgnO1xuXHR0aGlzLmRhdGEgPSAnJztcblx0dGhpcy5kYXRlID0gbmV3IERhdGUoKTtcblxuXHRcblx0LyoqXG5cdCAqIFNldCB0aGUgcGFja2V0IGRhdGEgdG8gYSBqYXZhc2NyaXB0IG5hdGl2ZSBzdHJpbmcgb3IgYSBzcXVlbmNlIG9mIFxuXHQgKiBieXRlcy4gQ29udmVyc2lvbiB0byBhIHByb3BlciB1dGY4IGVuY29kaW5nIHRha2VzIHBsYWNlIHdoZW4gdGhlIFxuXHQgKiBwYWNrZXQgaXMgd3JpdHRlbi5cblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBBbnkgbmF0aXZlIGphdmFzY3JpcHQgc3RyaW5nXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9wYWNrZXRfbGl0ZXJhbGRhdGEuZm9ybWF0fSBmb3JtYXQgXG5cdCAqL1xuXHR0aGlzLnNldCA9IGZ1bmN0aW9uKHN0ciwgZm9ybWF0KSB7XG5cdFx0dGhpcy5mb3JtYXQgPSBmb3JtYXQ7XG5cdFx0dGhpcy5kYXRhID0gc3RyO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldCB0aGUgcGFja2V0IGRhdGEgdG8gdmFsdWUgcmVwcmVzZW50ZWQgYnkgdGhlIHByb3ZpZGVkIHN0cmluZ1xuXHQgKiBvZiBieXRlcyB0b2dldGhlciB3aXRoIHRoZSBhcHByb3ByaWF0ZSBjb252ZXJzaW9uIGZvcm1hdC5cblx0ICogQHBhcmFtIHtTdHJpbmd9IGJ5dGVzIFRoZSBzdHJpbmcgb2YgYnl0ZXNcblx0ICogQHBhcmFtIHtvcGVucGdwX3BhY2tldF9saXRlcmFsZGF0YS5mb3JtYXR9IGZvcm1hdFxuXHQgKi9cblx0dGhpcy5zZXRCeXRlcyA9IGZ1bmN0aW9uKGJ5dGVzLCBmb3JtYXQpIHtcblx0XHR0aGlzLmZvcm1hdCA9IGZvcm1hdDtcblxuXHRcdGlmKGZvcm1hdCA9PSAndXRmOCcpXG5cdFx0XHRieXRlcyA9IHV0aWwuZGVjb2RlX3V0ZjgoYnl0ZXMpO1xuXG5cdFx0dGhpcy5kYXRhID0gYnl0ZXM7XG5cdH1cblxuXHQvKipcblx0ICogR2V0IHRoZSBieXRlIHNlcXVlbmNlIHJlcHJlc2VudGluZyB0aGUgbGl0ZXJhbCBwYWNrZXQgZGF0YVxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBBIHNlcXVlbmNlIG9mIGJ5dGVzXG5cdCAqL1xuXHR0aGlzLmdldEJ5dGVzID0gZnVuY3Rpb24oKSB7XG5cdFx0aWYodGhpcy5mb3JtYXQgPT0gJ3V0ZjgnKVxuXHRcdFx0cmV0dXJuIHV0aWwuZW5jb2RlX3V0ZjgodGhpcy5kYXRhKTtcblx0XHRlbHNlXG5cdFx0XHRyZXR1cm4gdGhpcy5kYXRhO1xuXHR9XG5cdFxuXHRcblxuXHQvKipcblx0ICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBsaXRlcmFsIGRhdGEgcGFja2V0ICh0YWcgMTEpLlxuXHQgKiBcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2YgYSB0YWcgMTEgcGFja2V0XG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb25cblx0ICogICAgICAgICAgICBQb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlblxuXHQgKiAgICAgICAgICAgIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mXG5cdCAqICAgICAgICAgICAgaW5wdXQgYXQgcG9zaXRpb25cblx0ICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YX0gb2JqZWN0IHJlcHJlc2VudGF0aW9uXG5cdCAqL1xuXHR0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdC8vIC0gQSBvbmUtb2N0ZXQgZmllbGQgdGhhdCBkZXNjcmliZXMgaG93IHRoZSBkYXRhIGlzIGZvcm1hdHRlZC5cblxuXHRcdHZhciBmb3JtYXQgPSBlbnVtcy5yZWFkKGVudW1zLmxpdGVyYWwsIGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSk7XG5cblx0XHR2YXIgZmlsZW5hbWVfbGVuID0gYnl0ZXMuY2hhckNvZGVBdCgxKTtcblx0XHR0aGlzLmZpbGVuYW1lID0gdXRpbC5kZWNvZGVfdXRmOChieXRlcy5zdWJzdHIoMiwgZmlsZW5hbWVfbGVuKSk7XG5cblx0XHR0aGlzLmRhdGUgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cigyXG5cdFx0XHRcdCsgZmlsZW5hbWVfbGVuLCA0KSk7XG5cblx0XHR2YXIgZGF0YSA9IGJ5dGVzLnN1YnN0cmluZyg2ICsgZmlsZW5hbWVfbGVuKTtcblx0XG5cdFx0dGhpcy5zZXRCeXRlcyhkYXRhLCBmb3JtYXQpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhY2tldFxuXHQgKiBcblx0ICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgVGhlIGRhdGEgdG8gYmUgaW5zZXJ0ZWQgYXMgYm9keVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IHN0cmluZy1yZXByZXNlbnRhdGlvbiBvZiB0aGUgcGFja2V0XG5cdCAqL1xuXHR0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGZpbGVuYW1lID0gdXRpbC5lbmNvZGVfdXRmOChcIm1zZy50eHRcIik7XG5cblx0XHR2YXIgZGF0YSA9IHRoaXMuZ2V0Qnl0ZXMoKTtcblxuXHRcdHZhciByZXN1bHQgPSAnJztcblx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5saXRlcmFsLCB0aGlzLmZvcm1hdCkpO1xuXHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGZpbGVuYW1lLmxlbmd0aCk7XG5cdFx0cmVzdWx0ICs9IGZpbGVuYW1lO1xuXHRcdHJlc3VsdCArPSB1dGlsLndyaXRlRGF0ZSh0aGlzLmRhdGUpO1xuXHRcdHJlc3VsdCArPSBkYXRhO1xuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBzdHJhbmdlIFwiTWFya2VyIHBhY2tldFwiIChUYWcgMTApXG4gKiBcbiAqIFJGQzQ4ODAgNS44OiBBbiBleHBlcmltZW50YWwgdmVyc2lvbiBvZiBQR1AgdXNlZCB0aGlzIHBhY2tldCBhcyB0aGUgTGl0ZXJhbFxuICogcGFja2V0LCBidXQgbm8gcmVsZWFzZWQgdmVyc2lvbiBvZiBQR1AgZ2VuZXJhdGVkIExpdGVyYWwgcGFja2V0cyB3aXRoIHRoaXNcbiAqIHRhZy4gV2l0aCBQR1AgNS54LCB0aGlzIHBhY2tldCBoYXMgYmVlbiByZWFzc2lnbmVkIGFuZCBpcyByZXNlcnZlZCBmb3IgdXNlIGFzXG4gKiB0aGUgTWFya2VyIHBhY2tldC5cbiAqIFxuICogU3VjaCBhIHBhY2tldCBNVVNUIGJlIGlnbm9yZWQgd2hlbiByZWNlaXZlZC5cbiAqL1xuZnVuY3Rpb24gcGFja2V0X21hcmtlcigpIHtcblx0LyoqXG5cdCAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgbGl0ZXJhbCBkYXRhIHBhY2tldCAodGFnIDEwKS5cblx0ICogXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIGEgdGFnIDEwIHBhY2tldFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uXG5cdCAqICAgICAgICAgICAgUG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5cblx0ICogICAgICAgICAgICBMZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZlxuXHQgKiAgICAgICAgICAgIGlucHV0IGF0IHBvc2l0aW9uXG5cdCAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IE9iamVjdCByZXByZXNlbnRhdGlvblxuXHQgKi9cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0XHRpZiAoYnl0ZXNbMF0uY2hhckNvZGVBdCgpID09IDB4NTAgJiYgLy8gUFxuXHRcdFx0XHRieXRlc1sxXS5jaGFyQ29kZUF0KCkgPT0gMHg0NyAmJiAvLyBHXG5cdFx0XHRcdGJ5dGVzWzJdLmNoYXJDb2RlQXQoKSA9PSAweDUwKSAvLyBQXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHQvLyBtYXJrZXIgcGFja2V0IGRvZXMgbm90IGNvbnRhaW4gXCJQR1BcIlxuXHRcdHJldHVybiBmYWxzZTtcblx0fVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHBhY2tldF9tYXJrZXI7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuXHR1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRyZWFkU2ltcGxlTGVuZ3RoOiBmdW5jdGlvbihieXRlcykge1xuXHRcdHZhciBsZW4gPSAwLFxuXHRcdFx0b2Zmc2V0LFxuXHRcdFx0dHlwZSA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblxuXG5cdFx0aWYgKHR5cGUgPCAxOTIpIHtcblx0XHRcdGxlbiA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblx0XHRcdG9mZnNldCA9IDE7XG5cdFx0fSBlbHNlIGlmICh0eXBlIDwgMjU1KSB7XG5cdFx0XHRsZW4gPSAoKGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSAtIDE5MikgPDwgOCkgKyAoYnl0ZXNbMV0uY2hhckNvZGVBdCgpKSArIDE5Mjtcblx0XHRcdG9mZnNldCA9IDI7XG5cdFx0fSBlbHNlIGlmICh0eXBlID09IDI1NSkge1xuXHRcdFx0bGVuID0gdXRpbC5yZWFkTnVtYmVyKGJ5dGVzLnN1YnN0cigxLCA0KSk7XG5cdFx0XHRvZmZzZXQgPSA1O1xuXHRcdH1cblxuXHRcdHJldHVybiB7IGxlbjogbGVuLCBvZmZzZXQ6IG9mZnNldCB9O1xuXHR9LFxuXG5cdC8qKlxuXHQgKiBFbmNvZGVzIGEgZ2l2ZW4gaW50ZWdlciBvZiBsZW5ndGggdG8gdGhlIG9wZW5wZ3AgbGVuZ3RoIHNwZWNpZmllciB0byBhXG5cdCAqIHN0cmluZ1xuXHQgKiBcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5ndGggVGhlIGxlbmd0aCB0byBlbmNvZGVcblx0ICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgd2l0aCBvcGVucGdwIGxlbmd0aCByZXByZXNlbnRhdGlvblxuXHQgKi9cblx0d3JpdGVTaW1wbGVMZW5ndGg6IGZ1bmN0aW9uKGxlbmd0aCkge1xuXHRcdHZhciByZXN1bHQgPSBcIlwiO1xuXHRcdGlmIChsZW5ndGggPCAxOTIpIHtcblx0XHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGxlbmd0aCk7XG5cdFx0fSBlbHNlIGlmIChsZW5ndGggPiAxOTEgJiYgbGVuZ3RoIDwgODM4NCkge1xuXHRcdFx0Lypcblx0XHRcdCAqIGxldCBhID0gKHRvdGFsIGRhdGEgcGFja2V0IGxlbmd0aCkgLSAxOTIgbGV0IGJjID0gdHdvIG9jdGV0XG5cdFx0XHQgKiByZXByZXNlbnRhdGlvbiBvZiBhIGxldCBkID0gYiArIDE5MlxuXHRcdFx0ICovXG5cdFx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoKGxlbmd0aCAtIDE5MikgPj4gOCkgKyAxOTIpO1xuXHRcdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGxlbmd0aCAtIDE5MikgJiAweEZGKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMjU1KTtcblx0XHRcdHJlc3VsdCArPSB1dGlsLndyaXRlTnVtYmVyKGxlbmd0aCwgNCk7XG5cdFx0fVxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0LyoqXG5cdCAqIFdyaXRlcyBhIHBhY2tldCBoZWFkZXIgdmVyc2lvbiA0IHdpdGggdGhlIGdpdmVuIHRhZ190eXBlIGFuZCBsZW5ndGggdG8gYVxuXHQgKiBzdHJpbmdcblx0ICogXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gdGFnX3R5cGUgVGFnIHR5cGVcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5ndGggTGVuZ3RoIG9mIHRoZSBwYXlsb2FkXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gU3RyaW5nIG9mIHRoZSBoZWFkZXJcblx0ICovXG5cdHdyaXRlSGVhZGVyOiBmdW5jdGlvbih0YWdfdHlwZSwgbGVuZ3RoKSB7XG5cdFx0Lyogd2UncmUgb25seSBnZW5lcmF0aW5nIHY0IHBhY2tldCBoZWFkZXJzIGhlcmUgKi9cblx0XHR2YXIgcmVzdWx0ID0gXCJcIjtcblx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweEMwIHwgdGFnX3R5cGUpO1xuXHRcdHJlc3VsdCArPSB0aGlzLndyaXRlU2ltcGxlTGVuZ3RoKGxlbmd0aCk7XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fSxcblxuXHQvKipcblx0ICogV3JpdGVzIGEgcGFja2V0IGhlYWRlciBWZXJzaW9uIDMgd2l0aCB0aGUgZ2l2ZW4gdGFnX3R5cGUgYW5kIGxlbmd0aCB0byBhXG5cdCAqIHN0cmluZ1xuXHQgKiBcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSB0YWdfdHlwZSBUYWcgdHlwZVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBMZW5ndGggb2YgdGhlIHBheWxvYWRcblx0ICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgb2YgdGhlIGhlYWRlclxuXHQgKi9cblx0d3JpdGVPbGRIZWFkZXI6IGZ1bmN0aW9uKHRhZ190eXBlLCBsZW5ndGgpIHtcblx0XHR2YXIgcmVzdWx0ID0gXCJcIjtcblx0XHRpZiAobGVuZ3RoIDwgMjU2KSB7XG5cdFx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDgwIHwgKHRhZ190eXBlIDw8IDIpKTtcblx0XHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGxlbmd0aCk7XG5cdFx0fSBlbHNlIGlmIChsZW5ndGggPCA2NTUzNikge1xuXHRcdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHg4MCB8ICh0YWdfdHlwZSA8PCAyKSB8IDEpO1xuXHRcdFx0cmVzdWx0ICs9IHV0aWwud3JpdGVOdW1iZXIobGVuZ3RoLCAyKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHg4MCB8ICh0YWdfdHlwZSA8PCAyKSB8IDIpO1xuXHRcdFx0cmVzdWx0ICs9IHV0aWwud3JpdGVOdW1iZXIobGVuZ3RoLCA0KTtcblx0XHR9XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fSxcblxuXHQvKipcblx0ICogR2VuZXJpYyBzdGF0aWMgUGFja2V0IFBhcnNlciBmdW5jdGlvblxuXHQgKiBcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IElucHV0IHN0cmVhbSBhcyBzdHJpbmdcblx0ICogQHBhcmFtIHtpbnRlZ2VyfSBwb3NpdGlvbiBQb3NpdGlvbiB0byBzdGFydCBwYXJzaW5nXG5cdCAqIEBwYXJhbSB7aW50ZWdlcn0gbGVuIExlbmd0aCBvZiB0aGUgaW5wdXQgZnJvbSBwb3NpdGlvbiBvblxuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFJldHVybnMgYSBwYXJzZWQgb3BlbnBncF9wYWNrZXRcblx0ICovXG5cdHJlYWQ6IGZ1bmN0aW9uKGlucHV0LCBwb3NpdGlvbiwgbGVuKSB7XG5cdFx0Ly8gc29tZSBzYW5pdHkgY2hlY2tzXG5cdFx0aWYgKGlucHV0ID09IG51bGwgfHwgaW5wdXQubGVuZ3RoIDw9IHBvc2l0aW9uXG5cdFx0XHRcdHx8IGlucHV0LnN1YnN0cmluZyhwb3NpdGlvbikubGVuZ3RoIDwgMlxuXHRcdFx0XHR8fCAoaW5wdXRbcG9zaXRpb25dLmNoYXJDb2RlQXQoKSAmIDB4ODApID09IDApIHtcblx0XHRcdHV0aWxcblx0XHRcdFx0XHQucHJpbnRfZXJyb3IoXCJFcnJvciBkdXJpbmcgcGFyc2luZy4gVGhpcyBtZXNzYWdlIC8ga2V5IGlzIHByb2JhYmx5IG5vdCBjb250YWluaW5nIGEgdmFsaWQgT3BlblBHUCBmb3JtYXQuXCIpO1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHRcdHZhciBteXBvcyA9IHBvc2l0aW9uO1xuXHRcdHZhciB0YWcgPSAtMTtcblx0XHR2YXIgZm9ybWF0ID0gLTE7XG5cdFx0dmFyIHBhY2tldF9sZW5ndGg7XG5cblx0XHRmb3JtYXQgPSAwOyAvLyAwID0gb2xkIGZvcm1hdDsgMSA9IG5ldyBmb3JtYXRcblx0XHRpZiAoKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDQwKSAhPSAwKSB7XG5cdFx0XHRmb3JtYXQgPSAxO1xuXHRcdH1cblxuXHRcdHZhciBwYWNrZXRfbGVuZ3RoX3R5cGU7XG5cdFx0aWYgKGZvcm1hdCkge1xuXHRcdFx0Ly8gbmV3IGZvcm1hdCBoZWFkZXJcblx0XHRcdHRhZyA9IGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDNGOyAvLyBiaXQgNS0wXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIG9sZCBmb3JtYXQgaGVhZGVyXG5cdFx0XHR0YWcgPSAoaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSAmIDB4M0YpID4+IDI7IC8vIGJpdCA1LTJcblx0XHRcdHBhY2tldF9sZW5ndGhfdHlwZSA9IGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDAzOyAvLyBiaXQgMS0wXG5cdFx0fVxuXG5cdFx0Ly8gaGVhZGVyIG9jdGV0IHBhcnNpbmcgZG9uZVxuXHRcdG15cG9zKys7XG5cblx0XHQvLyBwYXJzZWQgbGVuZ3RoIGZyb20gbGVuZ3RoIGZpZWxkXG5cdFx0dmFyIGJvZHlkYXRhID0gbnVsbDtcblxuXHRcdC8vIHVzZWQgZm9yIHBhcnRpYWwgYm9keSBsZW5ndGhzXG5cdFx0dmFyIHJlYWxfcGFja2V0X2xlbmd0aCA9IC0xO1xuXHRcdGlmICghZm9ybWF0KSB7XG5cdFx0XHQvLyA0LjIuMS4gT2xkIEZvcm1hdCBQYWNrZXQgTGVuZ3Roc1xuXHRcdFx0c3dpdGNoIChwYWNrZXRfbGVuZ3RoX3R5cGUpIHtcblx0XHRcdGNhc2UgMDogLy8gVGhlIHBhY2tldCBoYXMgYSBvbmUtb2N0ZXQgbGVuZ3RoLiBUaGUgaGVhZGVyIGlzIDIgb2N0ZXRzXG5cdFx0XHRcdC8vIGxvbmcuXG5cdFx0XHRcdHBhY2tldF9sZW5ndGggPSBpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAxOiAvLyBUaGUgcGFja2V0IGhhcyBhIHR3by1vY3RldCBsZW5ndGguIFRoZSBoZWFkZXIgaXMgMyBvY3RldHNcblx0XHRcdFx0Ly8gbG9uZy5cblx0XHRcdFx0cGFja2V0X2xlbmd0aCA9IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgOClcblx0XHRcdFx0XHRcdHwgaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgMjogLy8gVGhlIHBhY2tldCBoYXMgYSBmb3VyLW9jdGV0IGxlbmd0aC4gVGhlIGhlYWRlciBpcyA1XG5cdFx0XHRcdC8vIG9jdGV0cyBsb25nLlxuXHRcdFx0XHRwYWNrZXRfbGVuZ3RoID0gKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCAyNClcblx0XHRcdFx0XHRcdHwgKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCAxNilcblx0XHRcdFx0XHRcdHwgKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCA4KVxuXHRcdFx0XHRcdFx0fCBpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0Ly8gMyAtIFRoZSBwYWNrZXQgaXMgb2YgaW5kZXRlcm1pbmF0ZSBsZW5ndGguIFRoZSBoZWFkZXIgaXMgMVxuXHRcdFx0XHQvLyBvY3RldCBsb25nLCBhbmQgdGhlIGltcGxlbWVudGF0aW9uIG11c3QgZGV0ZXJtaW5lIGhvdyBsb25nXG5cdFx0XHRcdC8vIHRoZSBwYWNrZXQgaXMuIElmIHRoZSBwYWNrZXQgaXMgaW4gYSBmaWxlLCB0aGlzIG1lYW5zIHRoYXRcblx0XHRcdFx0Ly8gdGhlIHBhY2tldCBleHRlbmRzIHVudGlsIHRoZSBlbmQgb2YgdGhlIGZpbGUuIEluIGdlbmVyYWwsIFxuXHRcdFx0XHQvLyBhbiBpbXBsZW1lbnRhdGlvbiBTSE9VTEQgTk9UIHVzZSBpbmRldGVybWluYXRlLWxlbmd0aCBcblx0XHRcdFx0Ly8gcGFja2V0cyBleGNlcHQgd2hlcmUgdGhlIGVuZCBvZiB0aGUgZGF0YSB3aWxsIGJlIGNsZWFyIFxuXHRcdFx0XHQvLyBmcm9tIHRoZSBjb250ZXh0LCBhbmQgZXZlbiB0aGVuIGl0IGlzIGJldHRlciB0byB1c2UgYSBcblx0XHRcdFx0Ly8gZGVmaW5pdGUgbGVuZ3RoLCBvciBhIG5ldyBmb3JtYXQgaGVhZGVyLiBUaGUgbmV3IGZvcm1hdCBcblx0XHRcdFx0Ly8gaGVhZGVycyBkZXNjcmliZWQgYmVsb3cgaGF2ZSBhIG1lY2hhbmlzbSBmb3IgcHJlY2lzZWx5XG5cdFx0XHRcdC8vIGVuY29kaW5nIGRhdGEgb2YgaW5kZXRlcm1pbmF0ZSBsZW5ndGguXG5cdFx0XHRcdHBhY2tldF9sZW5ndGggPSBsZW47XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0fSBlbHNlIC8vIDQuMi4yLiBOZXcgRm9ybWF0IFBhY2tldCBMZW5ndGhzXG5cdFx0e1xuXG5cdFx0XHQvLyA0LjIuMi4xLiBPbmUtT2N0ZXQgTGVuZ3Roc1xuXHRcdFx0aWYgKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgPCAxOTIpIHtcblx0XHRcdFx0cGFja2V0X2xlbmd0aCA9IGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKTtcblx0XHRcdFx0dXRpbC5wcmludF9kZWJ1ZyhcIjEgYnl0ZSBsZW5ndGg6XCIgKyBwYWNrZXRfbGVuZ3RoKTtcblx0XHRcdFx0Ly8gNC4yLjIuMi4gVHdvLU9jdGV0IExlbmd0aHNcblx0XHRcdH0gZWxzZSBpZiAoaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSA+PSAxOTJcblx0XHRcdFx0XHQmJiBpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpIDwgMjI0KSB7XG5cdFx0XHRcdHBhY2tldF9sZW5ndGggPSAoKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSAtIDE5MikgPDwgOClcblx0XHRcdFx0XHRcdCsgKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSkgKyAxOTI7XG5cdFx0XHRcdHV0aWwucHJpbnRfZGVidWcoXCIyIGJ5dGUgbGVuZ3RoOlwiICsgcGFja2V0X2xlbmd0aCk7XG5cdFx0XHRcdC8vIDQuMi4yLjQuIFBhcnRpYWwgQm9keSBMZW5ndGhzXG5cdFx0XHR9IGVsc2UgaWYgKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgPiAyMjNcblx0XHRcdFx0XHQmJiBpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpIDwgMjU1KSB7XG5cdFx0XHRcdHBhY2tldF9sZW5ndGggPSAxIDw8IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgJiAweDFGKTtcblx0XHRcdFx0dXRpbC5wcmludF9kZWJ1ZyhcIjQgYnl0ZSBsZW5ndGg6XCIgKyBwYWNrZXRfbGVuZ3RoKTtcblx0XHRcdFx0Ly8gRUVFSywgd2UncmUgcmVhZGluZyB0aGUgZnVsbCBkYXRhIGhlcmUuLi5cblx0XHRcdFx0dmFyIG15cG9zMiA9IG15cG9zICsgcGFja2V0X2xlbmd0aDtcblx0XHRcdFx0Ym9keWRhdGEgPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MsIG15cG9zICsgcGFja2V0X2xlbmd0aCk7XG5cdFx0XHRcdHdoaWxlICh0cnVlKSB7XG5cdFx0XHRcdFx0aWYgKGlucHV0W215cG9zMl0uY2hhckNvZGVBdCgpIDwgMTkyKSB7XG5cdFx0XHRcdFx0XHR2YXIgdG1wbGVuID0gaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKTtcblx0XHRcdFx0XHRcdHBhY2tldF9sZW5ndGggKz0gdG1wbGVuO1xuXHRcdFx0XHRcdFx0Ym9keWRhdGEgKz0gaW5wdXQuc3Vic3RyaW5nKG15cG9zMiwgbXlwb3MyICsgdG1wbGVuKTtcblx0XHRcdFx0XHRcdG15cG9zMiArPSB0bXBsZW47XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGlucHV0W215cG9zMl0uY2hhckNvZGVBdCgpID49IDE5MlxuXHRcdFx0XHRcdFx0XHQmJiBpbnB1dFtteXBvczJdLmNoYXJDb2RlQXQoKSA8IDIyNCkge1xuXHRcdFx0XHRcdFx0dmFyIHRtcGxlbiA9ICgoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSAtIDE5MikgPDwgOClcblx0XHRcdFx0XHRcdFx0XHQrIChpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpKSArIDE5Mjtcblx0XHRcdFx0XHRcdHBhY2tldF9sZW5ndGggKz0gdG1wbGVuO1xuXHRcdFx0XHRcdFx0Ym9keWRhdGEgKz0gaW5wdXQuc3Vic3RyaW5nKG15cG9zMiwgbXlwb3MyICsgdG1wbGVuKTtcblx0XHRcdFx0XHRcdG15cG9zMiArPSB0bXBsZW47XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9IGVsc2UgaWYgKGlucHV0W215cG9zMl0uY2hhckNvZGVBdCgpID4gMjIzXG5cdFx0XHRcdFx0XHRcdCYmIGlucHV0W215cG9zMl0uY2hhckNvZGVBdCgpIDwgMjU1KSB7XG5cdFx0XHRcdFx0XHR2YXIgdG1wbGVuID0gMSA8PCAoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSAmIDB4MUYpO1xuXHRcdFx0XHRcdFx0cGFja2V0X2xlbmd0aCArPSB0bXBsZW47XG5cdFx0XHRcdFx0XHRib2R5ZGF0YSArPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MyLCBteXBvczIgKyB0bXBsZW4pO1xuXHRcdFx0XHRcdFx0bXlwb3MyICs9IHRtcGxlbjtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0bXlwb3MyKys7XG5cdFx0XHRcdFx0XHR2YXIgdG1wbGVuID0gKGlucHV0W215cG9zMisrXS5jaGFyQ29kZUF0KCkgPDwgMjQpXG5cdFx0XHRcdFx0XHRcdFx0fCAoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSA8PCAxNilcblx0XHRcdFx0XHRcdFx0XHR8IChpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpIDw8IDgpXG5cdFx0XHRcdFx0XHRcdFx0fCBpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0XHRcdFx0Ym9keWRhdGEgKz0gaW5wdXQuc3Vic3RyaW5nKG15cG9zMiwgbXlwb3MyICsgdG1wbGVuKTtcblx0XHRcdFx0XHRcdHBhY2tldF9sZW5ndGggKz0gdG1wbGVuO1xuXHRcdFx0XHRcdFx0bXlwb3MyICs9IHRtcGxlbjtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZWFsX3BhY2tldF9sZW5ndGggPSBteXBvczI7XG5cdFx0XHRcdC8vIDQuMi4yLjMuIEZpdmUtT2N0ZXQgTGVuZ3Roc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0bXlwb3MrKztcblx0XHRcdFx0cGFja2V0X2xlbmd0aCA9IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgMjQpXG5cdFx0XHRcdFx0XHR8IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgMTYpXG5cdFx0XHRcdFx0XHR8IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgOClcblx0XHRcdFx0XHRcdHwgaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIGlmIHRoZXJlIHdhcydudCBhIHBhcnRpYWwgYm9keSBsZW5ndGg6IHVzZSB0aGUgc3BlY2lmaWVkXG5cdFx0Ly8gcGFja2V0X2xlbmd0aFxuXHRcdGlmIChyZWFsX3BhY2tldF9sZW5ndGggPT0gLTEpIHtcblx0XHRcdHJlYWxfcGFja2V0X2xlbmd0aCA9IHBhY2tldF9sZW5ndGg7XG5cdFx0fVxuXG5cdFx0aWYgKGJvZHlkYXRhID09IG51bGwpIHtcblx0XHRcdGJvZHlkYXRhID0gaW5wdXQuc3Vic3RyaW5nKG15cG9zLCBteXBvcyArIHJlYWxfcGFja2V0X2xlbmd0aCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHsgXG5cdFx0XHR0YWc6IHRhZyxcblx0XHRcdHBhY2tldDogYm9keWRhdGEsXG5cdFx0XHRvZmZzZXQ6IG15cG9zICsgcmVhbF9wYWNrZXRfbGVuZ3RoXG5cdFx0fTtcblx0fVxufVxuXG4iLCJcblxudmFyIHBhY2tldFBhcnNlciA9IHJlcXVpcmUoJy4vcGFja2V0LmpzJyksXG5cdHBhY2tldHMgPSByZXF1aXJlKCcuL2FsbF9wYWNrZXRzLmpzJyksXG5cdGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgVGhpcyBjbGFzcyByZXByZXNlbnRzIGEgbGlzdCBvZiBvcGVucGdwIHBhY2tldHMuXG4gKiBUYWtlIGNhcmUgd2hlbiBpdGVyYXRpbmcgb3ZlciBpdCAtIHRoZSBwYWNrZXRzIHRoZW1zZWx2ZXNcbiAqIGFyZSBzdG9yZWQgYXMgbnVtZXJpY2FsIGluZGljZXMuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0bGlzdCgpIHtcblx0LyoqIFRoZSBudW1iZXIgb2YgcGFja2V0cyBjb250YWluZWQgd2l0aGluIHRoZSBsaXN0LlxuXHQgKiBAcmVhZG9ubHlcblx0ICogQHR5cGUge0ludGVnZXJ9ICovXG5cdHRoaXMubGVuZ3RoID0gMDtcblxuXG5cblx0LyoqXG5cdCAqIFJlYWRzIGEgc3RyZWFtIG9mIGJpbmFyeSBkYXRhIGFuZCBpbnRlcnByZW50cyBpdCBhcyBhIGxpc3Qgb2YgcGFja2V0cy5cblx0ICogQHBhcmFtIHtvcGVucGdwX2J5dGVhcnJheX0gQW4gYXJyYXkgb2YgYnl0ZXMuXG5cdCAqL1xuXHR0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdHZhciBpID0gMDtcblxuXHRcdHdoaWxlKGkgPCBieXRlcy5sZW5ndGgpIHtcblx0XHRcdHZhciBwYXJzZWQgPSBwYWNrZXRQYXJzZXIucmVhZChieXRlcywgaSwgYnl0ZXMubGVuZ3RoIC0gaSk7XG5cdFx0XHRpID0gcGFyc2VkLm9mZnNldDtcblxuXHRcdFx0dmFyIHRhZyA9IGVudW1zLnJlYWQoZW51bXMucGFja2V0LCBwYXJzZWQudGFnKTtcblx0XHRcdHZhciBwYWNrZXQgPSBuZXcgcGFja2V0c1t0YWddKCk7XG5cblx0XHRcdHRoaXMucHVzaChwYWNrZXQpO1xuXG5cdFx0XHRwYWNrZXQucmVhZChwYXJzZWQucGFja2V0KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIGJpbmFyeSByZXByZXNlbnRhdGlvbiBvZiBvcGVucGdwIG9iamVjdHMgY29udGFpbmVkIHdpdGhpbiB0aGVcblx0ICogY2xhc3MgaW5zdGFuY2UuXG5cdCAqIEByZXR1cm5zIHtvcGVucGdwX2J5dGVhcnJheX0gQW4gYXJyYXkgb2YgYnl0ZXMgY29udGFpbmluZyB2YWxpZCBvcGVucGdwIHBhY2tldHMuXG5cdCAqL1xuXHR0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGJ5dGVzID0gJyc7XG5cblx0XHRmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0dmFyIHBhY2tldGJ5dGVzID0gdGhpc1tpXS53cml0ZSgpO1xuXHRcdFx0Ynl0ZXMgKz0gcGFja2V0UGFyc2VyLndyaXRlSGVhZGVyKHRoaXNbaV0udGFnLCBwYWNrZXRieXRlcy5sZW5ndGgpO1xuXHRcdFx0Ynl0ZXMgKz0gcGFja2V0Ynl0ZXM7XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiBieXRlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBBZGRzIGEgcGFja2V0IHRvIHRoZSBsaXN0LiBUaGlzIGlzIHRoZSBvbmx5IHN1cHBvcnRlZCBtZXRob2Qgb2YgZG9pbmcgc287XG5cdCAqIHdyaXRpbmcgdG8gcGFja2V0bGlzdFtpXSBkaXJlY3RseSB3aWxsIHJlc3VsdCBpbiBhbiBlcnJvci5cblx0ICovXG5cdHRoaXMucHVzaCA9IGZ1bmN0aW9uKHBhY2tldCkge1xuXHRcdHBhY2tldC5wYWNrZXRzID0gbmV3IHBhY2tldGxpc3QoKTtcblxuXHRcdHRoaXNbdGhpcy5sZW5ndGhdID0gcGFja2V0O1xuXHRcdHRoaXMubGVuZ3RoKys7XG5cdH1cblxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG5cdHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKSxcblx0ZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuXHRjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIEtleSBNYXRlcmlhbCBQYWNrZXQgKFRhZyA1LDYsNywxNClcbiAqICAgXG4gKiBSRkM0NDgwIDUuNTpcbiAqIEEga2V5IG1hdGVyaWFsIHBhY2tldCBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IGEgcHVibGljIG9yXG4gKiBwcml2YXRlIGtleS4gIFRoZXJlIGFyZSBmb3VyIHZhcmlhbnRzIG9mIHRoaXMgcGFja2V0IHR5cGUsIGFuZCB0d29cbiAqIG1ham9yIHZlcnNpb25zLiAgQ29uc2VxdWVudGx5LCB0aGlzIHNlY3Rpb24gaXMgY29tcGxleC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfcHVibGljX2tleSgpIHtcblx0LyoqIEtleSBjcmVhdGlvbiBkYXRlLlxuXHQgKiBAdHlwZSB7RGF0ZX0gKi9cblx0dGhpcy5jcmVhdGVkID0gbmV3IERhdGUoKTtcblx0LyoqIEEgbGlzdCBvZiBtdWx0aXByZWNpc2lvbiBpbnRlZ2Vyc1xuXHQgKiBAdHlwZSB7b3BlbnBncF90eXBlX21waX0gKi9cblx0dGhpcy5tcGkgPSBbXTtcblx0LyoqIFB1YmxpYyBrZXkgYWxnb3JpdGhtXG5cdCAqIEB0eXBlIHtvcGVucGdwLnB1YmxpY2tleX0gKi9cblx0dGhpcy5hbGdvcml0aG0gPSAncnNhX3NpZ24nO1xuXG5cblx0LyoqXG5cdCAqIEludGVybmFsIFBhcnNlciBmb3IgcHVibGljIGtleXMgYXMgc3BlY2lmaWVkIGluIFJGQyA0ODgwIHNlY3Rpb24gXG5cdCAqIDUuNS4yIFB1YmxpYy1LZXkgUGFja2V0IEZvcm1hdHNcblx0ICogY2FsbGVkIGJ5IHJlYWRfdGFnJmx0O251bSZndDtcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IElucHV0IHN0cmluZyB0byByZWFkIHRoZSBwYWNrZXQgZnJvbVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFN0YXJ0IHBvc2l0aW9uIGZvciB0aGUgcGFyc2VyXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHJlbWFpbmluZyBsZW5ndGggb2YgaW5wdXRcblx0ICogQHJldHVybiB7T2JqZWN0fSBUaGlzIG9iamVjdCB3aXRoIGF0dHJpYnV0ZXMgc2V0IGJ5IHRoZSBwYXJzZXJcblx0ICovICBcblx0dGhpcy5yZWFkUHVibGljS2V5ID0gdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0XHQvLyBBIG9uZS1vY3RldCB2ZXJzaW9uIG51bWJlciAoMyBvciA0KS5cblx0XHR2YXIgdmVyc2lvbiA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblxuXHRcdGlmICh2ZXJzaW9uID09IDQpIHtcblx0XHRcdC8vIC0gQSBmb3VyLW9jdGV0IG51bWJlciBkZW5vdGluZyB0aGUgdGltZSB0aGF0IHRoZSBrZXkgd2FzIGNyZWF0ZWQuXG5cdFx0XHR0aGlzLmNyZWF0ZWQgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cigxLCA0KSk7XG5cdFx0XHRcblx0XHRcdC8vIC0gQSBvbmUtb2N0ZXQgbnVtYmVyIGRlbm90aW5nIHRoZSBwdWJsaWMta2V5IGFsZ29yaXRobSBvZiB0aGlzIGtleS5cblx0XHRcdHRoaXMuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGJ5dGVzWzVdLmNoYXJDb2RlQXQoKSk7XG5cblx0XHRcdHZhciBtcGljb3VudCA9IGNyeXB0by5nZXRQdWJsaWNNcGlDb3VudCh0aGlzLmFsZ29yaXRobSk7XG5cdFx0XHR0aGlzLm1waSA9IFtdO1xuXG5cdFx0XHR2YXIgYm1waSA9IGJ5dGVzLnN1YnN0cig2KTtcblx0XHRcdHZhciBwID0gMDtcblxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IFxuXHRcdFx0XHRpIDwgbXBpY291bnQgJiYgcCA8IGJtcGkubGVuZ3RoOyBcblx0XHRcdFx0aSsrKSB7XG5cblx0XHRcdFx0dGhpcy5tcGlbaV0gPSBuZXcgdHlwZV9tcGkoKTtcblxuXHRcdFx0XHRwICs9IHRoaXMubXBpW2ldLnJlYWQoYm1waS5zdWJzdHIocCkpXG5cblx0XHRcdFx0aWYocCA+IGJtcGkubGVuZ3RoKVxuXHRcdFx0XHRcdHV0aWwucHJpbnRfZXJyb3IoXCJvcGVucGdwLnBhY2tldC5rZXltYXRlcmlhbC5qc1xcblwiXG5cdFx0XHRcdFx0XHQrJ2Vycm9yIHJlYWRpbmcgTVBJIEA6JytwKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHAgKyA2O1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ1ZlcnNpb24gJyArIHZlcnNpb24gKyAnIG9mIHRoZSBrZXkgcGFja2V0IGlzIHVuc3VwcG9ydGVkLicpO1xuXHRcdH1cblx0fVxuXG5cdC8qXG4gICAgICogU2FtZSBhcyB3cml0ZV9wcml2YXRlX2tleSwgYnV0IGhhcyBsZXNzIGluZm9ybWF0aW9uIGJlY2F1c2Ugb2YgXG5cdCAqIHB1YmxpYyBrZXkuXG4gICAgICogQHBhcmFtIHtJbnRlZ2VyfSBrZXlUeXBlIEZvbGxvd3MgdGhlIE9wZW5QR1AgYWxnb3JpdGhtIHN0YW5kYXJkLCBcblx0ICogSUUgMSBjb3JyZXNwb25kcyB0byBSU0EuXG4gICAgICogQHBhcmFtIHtSU0Eua2V5T2JqZWN0fSBrZXlcbiAgICAgKiBAcGFyYW0gdGltZVBhY2tldFxuICAgICAqIEByZXR1cm4ge09iamVjdH0ge2JvZHk6IFtzdHJpbmddT3BlblBHUCBwYWNrZXQgYm9keSBjb250ZW50cywgXG5cdCAqIGhlYWRlcjogW3N0cmluZ10gT3BlblBHUCBwYWNrZXQgaGVhZGVyLCBzdHJpbmc6IFtzdHJpbmddIGhlYWRlcitib2R5fVxuICAgICAqL1xuICAgIHRoaXMud3JpdGVQdWJsaWNLZXkgPSB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG5cdFx0Ly8gVmVyc2lvblxuXHRcdHZhciByZXN1bHQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDQpO1xuICAgICAgICByZXN1bHQgKz0gdXRpbC53cml0ZURhdGUodGhpcy5jcmVhdGVkKTtcblx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5wdWJsaWNLZXksIHRoaXMuYWxnb3JpdGhtKSk7XG5cblx0XHR2YXIgbXBpY291bnQgPSBjcnlwdG8uZ2V0UHVibGljTXBpQ291bnQodGhpcy5hbGdvcml0aG0pO1xuXG5cdFx0Zm9yKHZhciBpID0gMDsgaSA8IG1waWNvdW50OyBpKyspIHtcblx0XHRcdHJlc3VsdCArPSB0aGlzLm1waVtpXS53cml0ZSgpO1xuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHQvLyBXcml0ZSBhbiBvbGQgdmVyc2lvbiBwYWNrZXQgLSBpdCdzIHVzZWQgYnkgc29tZSBvZiB0aGUgaW50ZXJuYWwgcm91dGluZXMuXG5cdHRoaXMud3JpdGVPbGQgPSBmdW5jdGlvbigpIHtcblx0XHR2YXIgYnl0ZXMgPSB0aGlzLndyaXRlUHVibGljS2V5KCk7XG5cblx0XHRyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgweDk5KSArXG5cdFx0XHR1dGlsLndyaXRlTnVtYmVyKGJ5dGVzLmxlbmd0aCwgMikgK1xuXHRcdFx0Ynl0ZXM7XG5cdH1cblxuXHQvKipcblx0ICogQ2FsY3VsYXRlcyB0aGUga2V5IGlkIG9mIHRoZSBrZXkgXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gQSA4IGJ5dGUga2V5IGlkXG5cdCAqL1xuXHR0aGlzLmdldEtleUlkID0gZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZ2V0RmluZ2VycHJpbnQoKS5zdWJzdHIoMTIsIDgpO1xuXHR9XG5cdFxuXHQvKipcblx0ICogQ2FsY3VsYXRlcyB0aGUgZmluZ2VycHJpbnQgb2YgdGhlIGtleVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IEEgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGZpbmdlcnByaW50XG5cdCAqL1xuXHR0aGlzLmdldEZpbmdlcnByaW50ID0gZnVuY3Rpb24oKSB7XG5cdFx0dmFyIHRvSGFzaCA9IHRoaXMud3JpdGVPbGQoKTtcblx0XHRyZXR1cm4gY3J5cHRvLmhhc2guc2hhMSh0b0hhc2gsIHRvSGFzaC5sZW5ndGgpO1xuXHR9XG5cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB0eXBlX2tleWlkID0gcmVxdWlyZSgnLi4vdHlwZS9rZXlpZC5qcycpLFxuXHR1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuXHR0eXBlX21waSA9IHJlcXVpcmUoJy4uL3R5cGUvbXBpLmpzJyksXG5cdGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcblx0Y3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cdFxuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBQdWJsaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleSBQYWNrZXRzIChUYWcgMSlcbiAqIFxuICogUkZDNDg4MCA1LjE6IEEgUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgcGFja2V0IGhvbGRzIHRoZSBzZXNzaW9uIGtleVxuICogdXNlZCB0byBlbmNyeXB0IGEgbWVzc2FnZS4gWmVybyBvciBtb3JlIFB1YmxpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5XG4gKiBwYWNrZXRzIGFuZC9vciBTeW1tZXRyaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXRzIG1heSBwcmVjZWRlIGFcbiAqIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgUGFja2V0LCB3aGljaCBob2xkcyBhbiBlbmNyeXB0ZWQgbWVzc2FnZS4gVGhlXG4gKiBtZXNzYWdlIGlzIGVuY3J5cHRlZCB3aXRoIHRoZSBzZXNzaW9uIGtleSwgYW5kIHRoZSBzZXNzaW9uIGtleSBpcyBpdHNlbGZcbiAqIGVuY3J5cHRlZCBhbmQgc3RvcmVkIGluIHRoZSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgcGFja2V0KHMpLiBUaGVcbiAqIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgUGFja2V0IGlzIHByZWNlZGVkIGJ5IG9uZSBQdWJsaWMtS2V5IEVuY3J5cHRlZFxuICogU2Vzc2lvbiBLZXkgcGFja2V0IGZvciBlYWNoIE9wZW5QR1Aga2V5IHRvIHdoaWNoIHRoZSBtZXNzYWdlIGlzIGVuY3J5cHRlZC5cbiAqIFRoZSByZWNpcGllbnQgb2YgdGhlIG1lc3NhZ2UgZmluZHMgYSBzZXNzaW9uIGtleSB0aGF0IGlzIGVuY3J5cHRlZCB0byB0aGVpclxuICogcHVibGljIGtleSwgZGVjcnlwdHMgdGhlIHNlc3Npb24ga2V5LCBhbmQgdGhlbiB1c2VzIHRoZSBzZXNzaW9uIGtleSB0b1xuICogZGVjcnlwdCB0aGUgbWVzc2FnZS5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfcHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkoKSB7XG5cdHRoaXMudmVyc2lvbiA9IDM7XG5cblx0dGhpcy5wdWJsaWNLZXlJZCA9IG5ldyB0eXBlX2tleWlkKCk7XG5cdHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gJ3JzYV9lbmNyeXB0JztcblxuXHR0aGlzLnNlc3Npb25LZXkgPSBudWxsO1xuXHR0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0gPSAnYWVzMjU2JztcblxuXHQvKiogQHR5cGUge29wZW5wZ3BfdHlwZV9tcGlbXX0gKi9cblx0dGhpcy5lbmNyeXB0ZWQgPSBbXTtcblxuXHQvKipcblx0ICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBwdWJsaWNrZXkgZW5jcnlwdGVkIHNlc3Npb24ga2V5IHBhY2tldCAodGFnIDEpLlxuXHQgKiBcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2YgYSB0YWcgMSBwYWNrZXRcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBQb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBMZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZlxuXHQgKiAgICAgICAgICAgIGlucHV0IGF0IHBvc2l0aW9uXG5cdCAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IE9iamVjdCByZXByZXNlbnRhdGlvblxuXHQgKi9cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblxuXHRcdHRoaXMudmVyc2lvbiA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblx0XHR0aGlzLnB1YmxpY0tleUlkLnJlYWQoYnl0ZXMuc3Vic3RyKDEpKTtcblx0XHR0aGlzLnB1YmxpY0tleUFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMucHVibGljS2V5LCBieXRlc1s5XS5jaGFyQ29kZUF0KCkpO1xuXG5cdFx0dmFyIGkgPSAxMDtcblxuXHRcdHZhciBpbnRlZ2VyQ291bnQgPSAoZnVuY3Rpb24oYWxnbykge1xuXHRcdFx0c3dpdGNoIChhbGdvKSB7XG5cdFx0XHRjYXNlICdyc2FfZW5jcnlwdCc6XG5cdFx0XHRjYXNlICdyc2FfZW5jcnlwdF9zaWduJzpcblx0XHRcdFx0cmV0dXJuIDE7XG5cblx0XHRcdGNhc2UgJ2VsZ2FtYWwnOlxuXHRcdFx0XHRyZXR1cm4gMjtcblxuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBhbGdvcml0aG0uXCIpO1xuXHRcdFx0fVxuXHRcdH0pKHRoaXMucHVibGljS2V5QWxnb3JpdGhtKTtcblxuXHRcdHRoaXMuZW5jcnlwdGVkID0gW107XG5cblx0XHRmb3IodmFyIGogPSAwOyBqIDwgaW50ZWdlckNvdW50OyBqKyspIHtcblx0XHRcdHZhciBtcGkgPSBuZXcgdHlwZV9tcGkoKTtcblx0XHRcdGkgKz0gbXBpLnJlYWQoYnl0ZXMuc3Vic3RyKGkpKTtcblx0XHRcdHRoaXMuZW5jcnlwdGVkLnB1c2gobXBpKTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgdGFnIDEgcGFja2V0XG5cdCAqIFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gcHVibGljS2V5SWRcblx0ICogICAgICAgICAgICAgVGhlIHB1YmxpYyBrZXkgaWQgY29ycmVzcG9uZGluZyB0byBwdWJsaWNNUElzIGtleSBhcyBzdHJpbmdcblx0ICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IHB1YmxpY01QSXNcblx0ICogICAgICAgICAgICBNdWx0aXByZWNpc2lvbiBpbnRlZ2VyIG9iamVjdHMgZGVzY3JpYmluZyB0aGUgcHVibGljIGtleVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHB1YmFsZ29cblx0ICogICAgICAgICAgICBUaGUgY29ycmVzcG9uZGluZyBwdWJsaWMga2V5IGFsZ29yaXRobSAvLyBTZWUgUkZDNDg4MCA5LjFcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBzeW1tYWxnb1xuXHQgKiAgICAgICAgICAgIFRoZSBzeW1tZXRyaWMgY2lwaGVyIGFsZ29yaXRobSB1c2VkIHRvIGVuY3J5cHQgdGhlIGRhdGEgXG5cdCAqICAgICAgICAgICAgd2l0aGluIGFuIGVuY3J5cHRlZGRhdGFwYWNrZXQgb3IgZW5jcnlwdGVkaW50ZWdyaXR5LVxuXHQgKiAgICAgICAgICAgIHByb3RlY3RlZGRhdGFwYWNrZXQgXG5cdCAqICAgICAgICAgICAgZm9sbG93aW5nIHRoaXMgcGFja2V0IC8vU2VlIFJGQzQ4ODAgOS4yXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBzZXNzaW9ua2V5XG5cdCAqICAgICAgICAgICAgQSBzdHJpbmcgb2YgcmFuZG9tYnl0ZXMgcmVwcmVzZW50aW5nIHRoZSBzZXNzaW9uIGtleVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb25cblx0ICovXG5cdHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcblxuXHRcdHZhciByZXN1bHQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMudmVyc2lvbik7XG5cdFx0cmVzdWx0ICs9IHRoaXMucHVibGljS2V5SWQud3JpdGUoKTtcblx0XHRyZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShcblx0XHRcdGVudW1zLndyaXRlKGVudW1zLnB1YmxpY0tleSwgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0pKTtcblxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHRoaXMuZW5jcnlwdGVkLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRyZXN1bHQgKz0gdGhpcy5lbmNyeXB0ZWRbaV0ud3JpdGUoKVxuXHRcdH1cblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH1cblxuXHR0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihrZXkpIHtcblx0XHR2YXIgZGF0YSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG5cdFx0XHRlbnVtcy53cml0ZShlbnVtcy5zeW1tZXRyaWMsIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSkpO1xuXG5cdFx0ZGF0YSArPSB0aGlzLnNlc3Npb25LZXk7XG5cdFx0dmFyIGNoZWNrc3VtID0gdXRpbC5jYWxjX2NoZWNrc3VtKHRoaXMuc2Vzc2lvbktleSk7XG5cdFx0ZGF0YSArPSB1dGlsLndyaXRlTnVtYmVyKGNoZWNrc3VtLCAyKTtcblxuXHRcdHZhciBtcGkgPSBuZXcgdHlwZV9tcGkoKTtcblx0XHRtcGkuZnJvbUJ5dGVzKGNyeXB0by5wa2NzMS5lbWUuZW5jb2RlKFxuXHRcdFx0ZGF0YSxcblx0XHRcdGtleS5tcGlbMF0uYnl0ZUxlbmd0aCgpKSk7XG5cblx0XHR0aGlzLmVuY3J5cHRlZCA9IGNyeXB0by5wdWJsaWNLZXlFbmNyeXB0KFxuXHRcdFx0dGhpcy5wdWJsaWNLZXlBbGdvcml0aG0sIFxuXHRcdFx0a2V5Lm1waSxcblx0XHRcdG1waSk7XG5cdH1cblxuXHQvKipcblx0ICogRGVjcnlwdHMgdGhlIHNlc3Npb24ga2V5IChvbmx5IGZvciBwdWJsaWMga2V5IGVuY3J5cHRlZCBzZXNzaW9uIGtleVxuXHQgKiBwYWNrZXRzICh0YWcgMSlcblx0ICogXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9tc2dfbWVzc2FnZX0gbXNnXG5cdCAqICAgICAgICAgICAgVGhlIG1lc3NhZ2Ugb2JqZWN0ICh3aXRoIG1lbWJlciBlbmNyeXB0ZWREYXRhXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0ga2V5XG5cdCAqICAgICAgICAgICAgUHJpdmF0ZSBrZXkgd2l0aCBzZWNNUElzIHVubG9ja2VkXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHVuZW5jcnlwdGVkIHNlc3Npb24ga2V5XG5cdCAqL1xuXHR0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihrZXkpIHtcblx0XHR2YXIgcmVzdWx0ID0gY3J5cHRvLnB1YmxpY0tleURlY3J5cHQoXG5cdFx0XHRcdHRoaXMucHVibGljS2V5QWxnb3JpdGhtLFxuXHRcdFx0XHRrZXkubXBpLFxuXHRcdFx0XHR0aGlzLmVuY3J5cHRlZCkudG9CeXRlcygpO1xuXG5cdFx0dmFyIGNoZWNrc3VtID0gdXRpbC5yZWFkTnVtYmVyKHJlc3VsdC5zdWJzdHIocmVzdWx0Lmxlbmd0aCAtIDIpKTtcblxuXHRcdHZhciBkZWNvZGVkID0gY3J5cHRvLnBrY3MxLmVtZS5kZWNvZGUoXG5cdFx0XHRyZXN1bHQsXG5cdFx0XHRrZXkubXBpWzBdLmJ5dGVMZW5ndGgoKSk7XG5cblx0XHR2YXIga2V5ID0gZGVjb2RlZC5zdWJzdHJpbmcoMSwgZGVjb2RlZC5sZW5ndGggLSAyKTtcblxuXHRcdGlmKGNoZWNrc3VtICE9IHV0aWwuY2FsY19jaGVja3N1bShrZXkpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0NoZWNrc3VtIG1pc21hdGNoJyk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0dGhpcy5zZXNzaW9uS2V5ID0ga2V5O1xuXHRcdFx0dGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtID0gXG5cdFx0XHRcdGVudW1zLnJlYWQoZW51bXMuc3ltbWV0cmljLCBkZWNvZGVkLmNoYXJDb2RlQXQoMCkpO1xuXHRcdH1cblx0fVxufTtcblxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHB1YmxpY19rZXkgPSByZXF1aXJlKCcuL3B1YmxpY19rZXkuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwdWJsaWNfc3Via2V5KCkge1xuXHRwdWJsaWNfa2V5LmNhbGwodGhpcyk7XG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgcHVibGljS2V5ID0gcmVxdWlyZSgnLi9wdWJsaWNfa2V5LmpzJyksXG5cdGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcblx0dXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcblx0Y3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyksXG5cdHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKSxcblx0dHlwZV9zMmsgPSByZXF1aXJlKCcuLi90eXBlL3Myay5qcycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgS2V5IE1hdGVyaWFsIFBhY2tldCAoVGFnIDUsNiw3LDE0KVxuICogICBcbiAqIFJGQzQ0ODAgNS41OlxuICogQSBrZXkgbWF0ZXJpYWwgcGFja2V0IGNvbnRhaW5zIGFsbCB0aGUgaW5mb3JtYXRpb24gYWJvdXQgYSBwdWJsaWMgb3JcbiAqIHByaXZhdGUga2V5LiAgVGhlcmUgYXJlIGZvdXIgdmFyaWFudHMgb2YgdGhpcyBwYWNrZXQgdHlwZSwgYW5kIHR3b1xuICogbWFqb3IgdmVyc2lvbnMuICBDb25zZXF1ZW50bHksIHRoaXMgc2VjdGlvbiBpcyBjb21wbGV4LlxuICovXG5mdW5jdGlvbiBwYWNrZXRfc2VjcmV0X2tleSgpIHtcblx0cHVibGljS2V5LmNhbGwodGhpcyk7XG5cblx0dGhpcy5lbmNyeXB0ZWQgPSBudWxsO1xuXG5cblx0ZnVuY3Rpb24gZ2V0X2hhc2hfbGVuKGhhc2gpIHtcblx0XHRpZihoYXNoID09ICdzaGExJylcblx0XHRcdHJldHVybiAyMDtcblx0XHRlbHNlXG5cdFx0XHRyZXR1cm4gMjtcblx0fVxuXG5cdGZ1bmN0aW9uIGdldF9oYXNoX2ZuKGhhc2gpIHtcblx0XHRpZihoYXNoID09ICdzaGExJylcblx0XHRcdHJldHVybiBjcnlwdG8uaGFzaC5zaGExO1xuXHRcdGVsc2Vcblx0XHRcdHJldHVybiBmdW5jdGlvbihjKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHV0aWwud3JpdGVOdW1iZXIodXRpbC5jYWxjX2NoZWNrc3VtKGMpLCAyKTtcblx0XHRcdFx0fVxuXHR9XG5cblx0Ly8gSGVscGVyIGZ1bmN0aW9uXG5cdGZ1bmN0aW9uIHBhcnNlX2NsZWFydGV4dF9tcGkoaGFzaF9hbGdvcml0aG0sIGNsZWFydGV4dCwgYWxnb3JpdGhtKSB7XG5cdFx0dmFyIGhhc2hsZW4gPSBnZXRfaGFzaF9sZW4oaGFzaF9hbGdvcml0aG0pLFxuXHRcdFx0aGFzaGZuID0gZ2V0X2hhc2hfZm4oaGFzaF9hbGdvcml0aG0pO1xuXG5cdFx0dmFyIGhhc2h0ZXh0ID0gY2xlYXJ0ZXh0LnN1YnN0cihjbGVhcnRleHQubGVuZ3RoIC0gaGFzaGxlbik7XG5cdFx0Y2xlYXJ0ZXh0ID0gY2xlYXJ0ZXh0LnN1YnN0cigwLCBjbGVhcnRleHQubGVuZ3RoIC0gaGFzaGxlbik7XG5cblx0XHR2YXIgaGFzaCA9IGhhc2hmbihjbGVhcnRleHQpO1xuXG5cdFx0aWYoaGFzaCAhPSBoYXNodGV4dClcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIkhhc2ggbWlzbWF0Y2guXCIpO1xuXG5cdFx0dmFyIG1waXMgPSBjcnlwdG8uZ2V0UHJpdmF0ZU1waUNvdW50KGFsZ29yaXRobSk7XG5cblx0XHR2YXIgaiA9IDA7XG5cdFx0dmFyIG1waSA9IFtdO1xuXG5cdFx0Zm9yKHZhciBpID0gMDsgaSA8IG1waXMgJiYgaiA8IGNsZWFydGV4dC5sZW5ndGg7IGkrKykge1xuXHRcdFx0bXBpW2ldID0gbmV3IHR5cGVfbXBpKCk7XG5cdFx0XHRqICs9IG1waVtpXS5yZWFkKGNsZWFydGV4dC5zdWJzdHIoaikpO1xuXHRcdH1cblxuXHRcdHJldHVybiBtcGk7XG5cdH1cblxuXHRmdW5jdGlvbiB3cml0ZV9jbGVhcnRleHRfbXBpKGhhc2hfYWxnb3JpdGhtLCBhbGdvcml0aG0sIG1waSkge1xuXHRcdHZhciBieXRlcz0gJyc7XG5cdFx0dmFyIGRpc2NhcmQgPSBjcnlwdG8uZ2V0UHVibGljTXBpQ291bnQoYWxnb3JpdGhtKTtcblxuXHRcdGZvcih2YXIgaSA9IGRpc2NhcmQ7IGkgPCBtcGkubGVuZ3RoOyBpKyspIHtcblx0XHRcdGJ5dGVzICs9IG1waVtpXS53cml0ZSgpO1xuXHRcdH1cblxuXG5cdFx0Ynl0ZXMgKz0gZ2V0X2hhc2hfZm4oaGFzaF9hbGdvcml0aG0pKGJ5dGVzKTtcblx0XHRcblx0XHRyZXR1cm4gYnl0ZXM7XG5cdH1cblx0XHRcblxuXHQvLyA1LjUuMy4gIFNlY3JldC1LZXkgUGFja2V0IEZvcm1hdHNcblx0XG5cdC8qKlxuXHQgKiBJbnRlcm5hbCBwYXJzZXIgZm9yIHByaXZhdGUga2V5cyBhcyBzcGVjaWZpZWQgaW4gUkZDIDQ4ODAgc2VjdGlvbiA1LjUuM1xuXHQgKiBAcGFyYW0ge1N0cmluZ30gYnl0ZXMgSW5wdXQgc3RyaW5nIHRvIHJlYWQgdGhlIHBhY2tldCBmcm9tXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gU3RhcnQgcG9zaXRpb24gZm9yIHRoZSBwYXJzZXJcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBsZW4gTGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgcmVtYWluaW5nIGxlbmd0aCBvZiBieXRlc1xuXHQgKiBAcmV0dXJuIHtPYmplY3R9IFRoaXMgb2JqZWN0IHdpdGggYXR0cmlidXRlcyBzZXQgYnkgdGhlIHBhcnNlclxuXHQgKi9cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0ICAgIC8vIC0gQSBQdWJsaWMtS2V5IG9yIFB1YmxpYy1TdWJrZXkgcGFja2V0LCBhcyBkZXNjcmliZWQgYWJvdmUuXG5cdFx0dmFyIGxlbiA9IHRoaXMucmVhZFB1YmxpY0tleShieXRlcyk7XG5cblx0ICAgIGJ5dGVzID0gYnl0ZXMuc3Vic3RyKGxlbik7XG5cblx0XHRcblx0ICAgIC8vIC0gT25lIG9jdGV0IGluZGljYXRpbmcgc3RyaW5nLXRvLWtleSB1c2FnZSBjb252ZW50aW9ucy4gIFplcm9cblx0ICAgIC8vICAgaW5kaWNhdGVzIHRoYXQgdGhlIHNlY3JldC1rZXkgZGF0YSBpcyBub3QgZW5jcnlwdGVkLiAgMjU1IG9yIDI1NFxuXHQgICAgLy8gICBpbmRpY2F0ZXMgdGhhdCBhIHN0cmluZy10by1rZXkgc3BlY2lmaWVyIGlzIGJlaW5nIGdpdmVuLiAgQW55XG5cdCAgICAvLyAgIG90aGVyIHZhbHVlIGlzIGEgc3ltbWV0cmljLWtleSBlbmNyeXB0aW9uIGFsZ29yaXRobSBpZGVudGlmaWVyLlxuXHQgICAgdmFyIGlzRW5jcnlwdGVkID0gYnl0ZXNbMF0uY2hhckNvZGVBdCgpO1xuXG5cdFx0aWYoaXNFbmNyeXB0ZWQpIHtcblx0XHRcdHRoaXMuZW5jcnlwdGVkID0gYnl0ZXM7XG5cdFx0fSBlbHNlIHtcblx0XG5cdFx0XHQvLyAtIFBsYWluIG9yIGVuY3J5cHRlZCBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBjb21wcmlzaW5nIHRoZSBzZWNyZXRcblx0XHRcdC8vICAga2V5IGRhdGEuICBUaGVzZSBhbGdvcml0aG0tc3BlY2lmaWMgZmllbGRzIGFyZSBhcyBkZXNjcmliZWRcblx0XHRcdC8vICAgYmVsb3cuXG5cblx0XHRcdHRoaXMubXBpID0gdGhpcy5tcGkuY29uY2F0KHBhcnNlX2NsZWFydGV4dF9tcGkoJ21vZCcsIGJ5dGVzLnN1YnN0cigxKSxcblx0XHRcdFx0dGhpcy5hbGdvcml0aG0pKTtcblx0XHR9ICAgIFxuXG5cdH1cblx0XG5cdC8qXG4gICAgICogQ3JlYXRlcyBhbiBPcGVuUEdQIGtleSBwYWNrZXQgZm9yIHRoZSBnaXZlbiBrZXkuIG11Y2ggXG5cdCAqIFRPRE8gaW4gcmVnYXJkcyB0byBzMmssIHN1YmtleXMuXG4gICAgICogQHBhcmFtIHtJbnRlZ2VyfSBrZXlUeXBlIEZvbGxvd3MgdGhlIE9wZW5QR1AgYWxnb3JpdGhtIHN0YW5kYXJkLCBcblx0ICogSUUgMSBjb3JyZXNwb25kcyB0byBSU0EuXG4gICAgICogQHBhcmFtIHtSU0Eua2V5T2JqZWN0fSBrZXlcbiAgICAgKiBAcGFyYW0gcGFzc3BocmFzZVxuICAgICAqIEBwYXJhbSBzMmtIYXNoXG4gICAgICogQHBhcmFtIHN5bW1ldHJpY0VuY3J5cHRpb25BbGdvcml0aG1cbiAgICAgKiBAcGFyYW0gdGltZVBhY2tldFxuICAgICAqIEByZXR1cm4ge09iamVjdH0ge2JvZHk6IFtzdHJpbmddT3BlblBHUCBwYWNrZXQgYm9keSBjb250ZW50cywgXG5cdFx0aGVhZGVyOiBbc3RyaW5nXSBPcGVuUEdQIHBhY2tldCBoZWFkZXIsIHN0cmluZzogW3N0cmluZ10gaGVhZGVyK2JvZHl9XG4gICAgICovXG4gICAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBieXRlcyA9IHRoaXMud3JpdGVQdWJsaWNLZXkoKTtcblxuXHRcdGlmKCF0aGlzLmVuY3J5cHRlZCkge1xuXHRcdFx0Ynl0ZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcblx0XHRcdFxuXHRcdFx0Ynl0ZXMgKz0gd3JpdGVfY2xlYXJ0ZXh0X21waSgnbW9kJywgdGhpcy5hbGdvcml0aG0sIHRoaXMubXBpKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ynl0ZXMgKz0gdGhpcy5lbmNyeXB0ZWQ7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGJ5dGVzO1xuXHR9XG5cdFx0XHRcblxuXG5cblx0LyoqIEVuY3J5cHQgdGhlIHBheWxvYWQuIEJ5IGRlZmF1bHQsIHdlIHVzZSBhZXMyNTYgYW5kIGl0ZXJhdGVkLCBzYWx0ZWQgc3RyaW5nXG5cdCAqIHRvIGtleSBzcGVjaWZpZXJcblx0ICogQHBhcmFtIHtTdHJpbmd9IHBhc3NwaHJhc2Vcblx0ICovXG4gICAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24ocGFzc3BocmFzZSkge1xuXG5cdFx0dmFyIHMyayA9IG5ldyB0eXBlX3MyaygpLFxuXHRcdFx0c3ltbWV0cmljID0gJ2FlczI1NicsXG5cdFx0XHRjbGVhcnRleHQgPSB3cml0ZV9jbGVhcnRleHRfbXBpKCdzaGExJywgdGhpcy5hbGdvcml0aG0sIHRoaXMubXBpKSxcblx0XHRcdGtleSA9IHByb2R1Y2VFbmNyeXB0aW9uS2V5KHMyaywgcGFzc3BocmFzZSwgc3ltbWV0cmljKSxcblx0XHRcdGJsb2NrTGVuID0gY3J5cHRvLmNpcGhlcltzeW1tZXRyaWNdLmJsb2NrU2l6ZSxcblx0XHRcdGl2ID0gY3J5cHRvLnJhbmRvbS5nZXRSYW5kb21CeXRlcyhibG9ja0xlbik7XG5cblxuXHRcdHRoaXMuZW5jcnlwdGVkID0gJyc7XG5cdFx0dGhpcy5lbmNyeXB0ZWQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgyNTQpO1xuXHRcdHRoaXMuZW5jcnlwdGVkICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuc3ltbWV0cmljLCBzeW1tZXRyaWMpKTtcblx0XHR0aGlzLmVuY3J5cHRlZCArPSBzMmsud3JpdGUoKTtcblx0XHR0aGlzLmVuY3J5cHRlZCArPSBpdjtcblxuXG5cblx0XHR0aGlzLmVuY3J5cHRlZCArPSBjcnlwdG8uY2ZiLm5vcm1hbEVuY3J5cHQoc3ltbWV0cmljLCBrZXksIGNsZWFydGV4dCwgaXYpO1xuICAgIH1cblxuXHRmdW5jdGlvbiBwcm9kdWNlRW5jcnlwdGlvbktleShzMmssIHBhc3NwaHJhc2UsIGFsZ29yaXRobSkge1xuXHRcdHJldHVybiBzMmsucHJvZHVjZV9rZXkocGFzc3BocmFzZSxcblx0XHRcdGNyeXB0by5jaXBoZXJbYWxnb3JpdGhtXS5rZXlTaXplKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBEZWNyeXB0cyB0aGUgcHJpdmF0ZSBrZXkgTVBJcyB3aGljaCBhcmUgbmVlZGVkIHRvIHVzZSB0aGUga2V5LlxuXHQgKiBvcGVucGdwX3BhY2tldF9rZXltYXRlcmlhbC5oYXNVbmVuY3J5cHRlZFNlY3JldEtleURhdGEgc2hvdWxkIGJlIFxuXHQgKiBmYWxzZSBvdGhlcndpc2Vcblx0ICogYSBjYWxsIHRvIHRoaXMgZnVuY3Rpb24gaXMgbm90IG5lZWRlZFxuXHQgKiBcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0cl9wYXNzcGhyYXNlIFRoZSBwYXNzcGhyYXNlIGZvciB0aGlzIHByaXZhdGUga2V5IFxuXHQgKiBhcyBzdHJpbmdcblx0ICogQHJldHVybiB7Qm9vbGVhbn0gVHJ1ZSBpZiB0aGUgcGFzc3BocmFzZSB3YXMgY29ycmVjdDsgZmFsc2UgaWYgbm90XG5cdCAqL1xuXHR0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihwYXNzcGhyYXNlKSB7XG5cdFx0aWYgKCF0aGlzLmVuY3J5cHRlZClcblx0XHRcdHJldHVybjtcblxuXHRcdHZhciBpID0gMCxcblx0XHRcdHN5bW1ldHJpYyxcblx0XHRcdGtleTtcblxuXHRcdHZhciBzMmtfdXNhZ2UgPSB0aGlzLmVuY3J5cHRlZFtpKytdLmNoYXJDb2RlQXQoKTtcblxuXHQgICAgLy8gLSBbT3B0aW9uYWxdIElmIHN0cmluZy10by1rZXkgdXNhZ2Ugb2N0ZXQgd2FzIDI1NSBvciAyNTQsIGEgb25lLVxuXHQgICAgLy8gICBvY3RldCBzeW1tZXRyaWMgZW5jcnlwdGlvbiBhbGdvcml0aG0uXG5cdCAgICBpZiAoczJrX3VzYWdlID09IDI1NSB8fCBzMmtfdXNhZ2UgPT0gMjU0KSB7XG5cdCAgICBcdHN5bW1ldHJpYyA9IHRoaXMuZW5jcnlwdGVkW2krK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0c3ltbWV0cmljID0gZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsIHN5bW1ldHJpYyk7XG5cdCAgICAgXG5cdFx0XHQvLyAtIFtPcHRpb25hbF0gSWYgc3RyaW5nLXRvLWtleSB1c2FnZSBvY3RldCB3YXMgMjU1IG9yIDI1NCwgYVxuXHRcdFx0Ly8gICBzdHJpbmctdG8ta2V5IHNwZWNpZmllci4gIFRoZSBsZW5ndGggb2YgdGhlIHN0cmluZy10by1rZXlcblx0XHRcdC8vICAgc3BlY2lmaWVyIGlzIGltcGxpZWQgYnkgaXRzIHR5cGUsIGFzIGRlc2NyaWJlZCBhYm92ZS5cblx0ICAgIFx0dmFyIHMyayA9IG5ldyB0eXBlX3MyaygpO1xuXHQgICAgXHRpICs9IHMyay5yZWFkKHRoaXMuZW5jcnlwdGVkLnN1YnN0cihpKSk7XG5cblx0XHRcdGtleSA9IHByb2R1Y2VFbmNyeXB0aW9uS2V5KHMyaywgcGFzc3BocmFzZSwgc3ltbWV0cmljKTtcblx0ICAgIH0gZWxzZSB7XG5cdFx0XHRzeW1tZXRyaWMgPSBzMmtfdXNhZ2U7XG5cdFx0XHRzeW1tZXRyaWMgPSBlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgc3ltbWV0cmljKTtcblx0XHRcdGtleSA9IGNyeXB0by5oYXNoLm1kNShwYXNzcGhyYXNlKTtcblx0XHR9XG5cblx0ICAgIFxuXHQgICAgLy8gLSBbT3B0aW9uYWxdIElmIHNlY3JldCBkYXRhIGlzIGVuY3J5cHRlZCAoc3RyaW5nLXRvLWtleSB1c2FnZSBvY3RldFxuXHQgICAgLy8gICBub3QgemVybyksIGFuIEluaXRpYWwgVmVjdG9yIChJVikgb2YgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZVxuXHQgICAgLy8gICBjaXBoZXIncyBibG9jayBzaXplLlxuXHRcdHZhciBpdiA9IHRoaXMuZW5jcnlwdGVkLnN1YnN0cihpLCBcblx0XHRcdGNyeXB0by5jaXBoZXJbc3ltbWV0cmljXS5ibG9ja1NpemUpO1xuXG5cdFx0aSArPSBpdi5sZW5ndGg7XG5cblx0XHR2YXIgY2xlYXJ0ZXh0LFxuXHRcdFx0Y2lwaGVydGV4dCA9IHRoaXMuZW5jcnlwdGVkLnN1YnN0cihpKTtcblxuIFx0XHRjbGVhcnRleHQgPSBjcnlwdG8uY2ZiLm5vcm1hbERlY3J5cHQoc3ltbWV0cmljLCBrZXksIGNpcGhlcnRleHQsIGl2KTtcblxuXHRcdHZhciBoYXNoID0gczJrX3VzYWdlID09IDI1NCA/XG5cdFx0XHQnc2hhMScgOlxuXHRcdFx0J21vZCc7XG5cbiAgIFx0XG5cdFx0dGhpcy5tcGkgPSB0aGlzLm1waS5jb25jYXQocGFyc2VfY2xlYXJ0ZXh0X21waShoYXNoLCBjbGVhcnRleHQsXG5cdFx0XHR0aGlzLmFsZ29yaXRobSkpO1xuXHR9XG5cblx0dGhpcy5nZW5lcmF0ZSA9IGZ1bmN0aW9uKGJpdHMpIHtcblxuXHR9XG5cdFxufVxuXG5wYWNrZXRfc2VjcmV0X2tleS5wcm90b3R5cGUgPSBuZXcgcHVibGljS2V5O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHBhY2tldF9zZWNyZXRfa2V5O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHNlY3JldF9rZXkgPSByZXF1aXJlKCcuL3NlY3JldF9rZXkuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZWNyZXRfc3Via2V5KCkge1xuXHRzZWNyZXRfa2V5LmNhbGwodGhpcyk7XG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcblx0cGFja2V0ID0gcmVxdWlyZSgnLi9wYWNrZXQuanMnKSxcblx0ZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuXHRjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKSxcblx0dHlwZV9tcGkgPSByZXF1aXJlKCcuLi90eXBlL21waS5qcycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgU2lnbmF0dXJlIFBhY2tldCAoVGFnIDIpXG4gKiBcbiAqIFJGQzQ0ODAgNS4yOlxuICogQSBTaWduYXR1cmUgcGFja2V0IGRlc2NyaWJlcyBhIGJpbmRpbmcgYmV0d2VlbiBzb21lIHB1YmxpYyBrZXkgYW5kXG4gKiBzb21lIGRhdGEuICBUaGUgbW9zdCBjb21tb24gc2lnbmF0dXJlcyBhcmUgYSBzaWduYXR1cmUgb2YgYSBmaWxlIG9yIGFcbiAqIGJsb2NrIG9mIHRleHQsIGFuZCBhIHNpZ25hdHVyZSB0aGF0IGlzIGEgY2VydGlmaWNhdGlvbiBvZiBhIFVzZXIgSUQuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3NpZ25hdHVyZSgpIHtcblxuXHR0aGlzLnNpZ25hdHVyZVR5cGUgPSBudWxsO1xuXHR0aGlzLmhhc2hBbGdvcml0aG0gPSBudWxsO1xuXHR0aGlzLnB1YmxpY0tleUFsZ29yaXRobSA9IG51bGw7IFxuXG5cdHRoaXMuc2lnbmF0dXJlRGF0YSA9IG51bGw7XG5cdHRoaXMuc2lnbmVkSGFzaFZhbHVlID0gbnVsbDtcblx0dGhpcy5tcGkgPSBudWxsO1xuXG5cdHRoaXMuY3JlYXRlZCA9IG51bGw7XG5cdHRoaXMuc2lnbmF0dXJlRXhwaXJhdGlvblRpbWUgPSBudWxsO1xuXHR0aGlzLnNpZ25hdHVyZU5ldmVyRXhwaXJlcyA9IG51bGw7XG5cdHRoaXMuZXhwb3J0YWJsZSA9IG51bGw7XG5cdHRoaXMudHJ1c3RMZXZlbCA9IG51bGw7XG5cdHRoaXMudHJ1c3RBbW91bnQgPSBudWxsO1xuXHR0aGlzLnJlZ3VsYXJFeHByZXNzaW9uID0gbnVsbDtcblx0dGhpcy5yZXZvY2FibGUgPSBudWxsO1xuXHR0aGlzLmtleUV4cGlyYXRpb25UaW1lID0gbnVsbDtcblx0dGhpcy5rZXlOZXZlckV4cGlyZXMgPSBudWxsO1xuXHR0aGlzLnByZWZlcnJlZFN5bW1ldHJpY0FsZ29yaXRobXMgPSBudWxsO1xuXHR0aGlzLnJldm9jYXRpb25LZXlDbGFzcyA9IG51bGw7XG5cdHRoaXMucmV2b2NhdGlvbktleUFsZ29yaXRobSA9IG51bGw7XG5cdHRoaXMucmV2b2NhdGlvbktleUZpbmdlcnByaW50ID0gbnVsbDtcblx0dGhpcy5pc3N1ZXJLZXlJZCA9IG51bGw7XG5cdHRoaXMubm90YXRpb24gPSB7fTtcblx0dGhpcy5wcmVmZXJyZWRIYXNoQWxnb3JpdGhtcyA9IG51bGw7XG5cdHRoaXMucHJlZmVycmVkQ29tcHJlc3Npb25BbGdvcml0aG1zID0gbnVsbDtcblx0dGhpcy5rZXlTZXJ2ZXJQcmVmZXJlbmNlcyA9IG51bGw7XG5cdHRoaXMucHJlZmVycmVkS2V5U2VydmVyID0gbnVsbDtcblx0dGhpcy5pc1ByaW1hcnlVc2VySUQgPSBudWxsO1xuXHR0aGlzLnBvbGljeVVSSSA9IG51bGw7XG5cdHRoaXMua2V5RmxhZ3MgPSBudWxsO1xuXHR0aGlzLnNpZ25lcnNVc2VySWQgPSBudWxsO1xuXHR0aGlzLnJlYXNvbkZvclJldm9jYXRpb25GbGFnID0gbnVsbDtcblx0dGhpcy5yZWFzb25Gb3JSZXZvY2F0aW9uU3RyaW5nID0gbnVsbDtcblx0dGhpcy5zaWduYXR1cmVUYXJnZXRQdWJsaWNLZXlBbGdvcml0aG0gPSBudWxsO1xuXHR0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2hBbGdvcml0aG0gPSBudWxsO1xuXHR0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2ggPSBudWxsO1xuXHR0aGlzLmVtYmVkZGVkU2lnbmF0dXJlID0gbnVsbDtcblxuXHR0aGlzLnZlcmlmaWVkID0gZmFsc2U7XG5cdFxuXG5cdC8qKlxuXHQgKiBwYXJzaW5nIGZ1bmN0aW9uIGZvciBhIHNpZ25hdHVyZSBwYWNrZXQgKHRhZyAyKS5cblx0ICogQHBhcmFtIHtTdHJpbmd9IGJ5dGVzIHBheWxvYWQgb2YgYSB0YWcgMiBwYWNrZXRcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBwb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGJ5dGVzIHN0cmluZ1xuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBsZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBieXRlcyBhdCBwb3NpdGlvblxuXHQgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBvYmplY3QgcmVwcmVzZW50YXRpb25cblx0ICovXG5cdHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG5cdFx0dmFyIGkgPSAwO1xuXG5cdFx0dmFyIHZlcnNpb24gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcblx0XHQvLyBzd2l0Y2ggb24gdmVyc2lvbiAoMyBhbmQgNClcblx0XHRzd2l0Y2ggKHZlcnNpb24pIHtcblx0XHRjYXNlIDM6XG5cdFx0XHQvLyBPbmUtb2N0ZXQgbGVuZ3RoIG9mIGZvbGxvd2luZyBoYXNoZWQgbWF0ZXJpYWwuIE1VU1QgYmUgNS5cblx0XHRcdGlmIChieXRlc1tpKytdLmNoYXJDb2RlQXQoKSAhPSA1KVxuXHRcdFx0XHR1dGlsLnByaW50X2RlYnVnKFwib3BlbnBncC5wYWNrZXQuc2lnbmF0dXJlLmpzXFxuXCIrXG5cdFx0XHRcdFx0J2ludmFsaWQgT25lLW9jdGV0IGxlbmd0aCBvZiBmb2xsb3dpbmcgaGFzaGVkIG1hdGVyaWFsLicgK1xuXHRcdFx0XHRcdCdNVVNUIGJlIDUuIEA6JysoaS0xKSk7XG5cblx0XHRcdHZhciBzaWdwb3MgPSBpO1xuXHRcdFx0Ly8gT25lLW9jdGV0IHNpZ25hdHVyZSB0eXBlLlxuXHRcdFx0dGhpcy5zaWduYXR1cmVUeXBlID0gYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG5cblx0XHRcdC8vIEZvdXItb2N0ZXQgY3JlYXRpb24gdGltZS5cblx0XHRcdHRoaXMuY3JlYXRlZCA9IHV0aWwucmVhZERhdGUoYnl0ZXMuc3Vic3RyKGksIDQpKTtcblx0XHRcdGkgKz0gNDtcblx0XHRcdFxuXHRcdFx0Ly8gc3RvcmluZyBkYXRhIGFwcGVuZGVkIHRvIGRhdGEgd2hpY2ggZ2V0cyB2ZXJpZmllZFxuXHRcdFx0dGhpcy5zaWduYXR1cmVEYXRhID0gYnl0ZXMuc3Vic3RyaW5nKHBvc2l0aW9uLCBpKTtcblx0XHRcdFxuXHRcdFx0Ly8gRWlnaHQtb2N0ZXQgS2V5IElEIG9mIHNpZ25lci5cblx0XHRcdHRoaXMuaXNzdWVyS2V5SWQgPSBieXRlcy5zdWJzdHJpbmcoaSwgaSArOCk7XG5cdFx0XHRpICs9IDg7XG5cblx0XHRcdC8vIE9uZS1vY3RldCBwdWJsaWMta2V5IGFsZ29yaXRobS5cblx0XHRcdHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG5cblx0XHRcdC8vIE9uZS1vY3RldCBoYXNoIGFsZ29yaXRobS5cblx0XHRcdHRoaXMuaGFzaEFsZ29yaXRobSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuXHRcdGJyZWFrO1xuXHRcdGNhc2UgNDpcblx0XHRcdHRoaXMuc2lnbmF0dXJlVHlwZSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0dGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcblx0XHRcdHRoaXMuaGFzaEFsZ29yaXRobSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuXG5cblx0XHRcdGZ1bmN0aW9uIHN1YnBhY2tldHMoYnl0ZXMsIHNpZ25lZCkge1xuXHRcdFx0XHQvLyBUd28tb2N0ZXQgc2NhbGFyIG9jdGV0IGNvdW50IGZvciBmb2xsb3dpbmcgaGFzaGVkIHN1YnBhY2tldFxuXHRcdFx0XHQvLyBkYXRhLlxuXHRcdFx0XHR2YXIgc3VicGFja2V0X2xlbmd0aCA9IHV0aWwucmVhZE51bWJlcihcblx0XHRcdFx0XHRieXRlcy5zdWJzdHIoMCwgMikpO1xuXG5cdFx0XHRcdHZhciBpID0gMjtcblxuXHRcdFx0XHQvLyBIYXNoZWQgc3VicGFja2V0IGRhdGEgc2V0ICh6ZXJvIG9yIG1vcmUgc3VicGFja2V0cylcblx0XHRcdFx0dmFyIHN1YnBhY2tlZF9yZWFkID0gMDtcblx0XHRcdFx0d2hpbGUgKGkgPCAyICsgc3VicGFja2V0X2xlbmd0aCkge1xuXG5cdFx0XHRcdFx0dmFyIGxlbiA9IHBhY2tldC5yZWFkU2ltcGxlTGVuZ3RoKGJ5dGVzLnN1YnN0cihpKSk7XG5cdFx0XHRcdFx0aSArPSBsZW4ub2Zmc2V0O1xuXG5cdFx0XHRcdFx0Ly8gU2luY2UgaXQgaXMgdHJpdmlhbCB0byBhZGQgZGF0YSB0byB0aGUgdW5oYXNoZWQgcG9ydGlvbiBvZiBcblx0XHRcdFx0XHQvLyB0aGUgcGFja2V0IHdlIHNpbXBseSBpZ25vcmUgYWxsIHVuYXV0aGVudGljYXRlZCBkYXRhLlxuXHRcdFx0XHRcdGlmKHNpZ25lZClcblx0XHRcdFx0XHRcdHRoaXMucmVhZF9zdWJfcGFja2V0KGJ5dGVzLnN1YnN0cihpLCBsZW4ubGVuKSk7XG5cblx0XHRcdFx0XHRpICs9IGxlbi5sZW47XG5cdFx0XHRcdH1cblx0XHRcdFx0XG5cdFx0XHRcdHJldHVybiBpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpICs9IHN1YnBhY2tldHMuY2FsbCh0aGlzLCBieXRlcy5zdWJzdHIoaSksIHRydWUpO1xuXG5cdFx0XHQvLyBBIFY0IHNpZ25hdHVyZSBoYXNoZXMgdGhlIHBhY2tldCBib2R5XG5cdFx0XHQvLyBzdGFydGluZyBmcm9tIGl0cyBmaXJzdCBmaWVsZCwgdGhlIHZlcnNpb24gbnVtYmVyLCB0aHJvdWdoIHRoZSBlbmRcblx0XHRcdC8vIG9mIHRoZSBoYXNoZWQgc3VicGFja2V0IGRhdGEuICBUaHVzLCB0aGUgZmllbGRzIGhhc2hlZCBhcmUgdGhlXG5cdFx0XHQvLyBzaWduYXR1cmUgdmVyc2lvbiwgdGhlIHNpZ25hdHVyZSB0eXBlLCB0aGUgcHVibGljLWtleSBhbGdvcml0aG0sIHRoZVxuXHRcdFx0Ly8gaGFzaCBhbGdvcml0aG0sIHRoZSBoYXNoZWQgc3VicGFja2V0IGxlbmd0aCwgYW5kIHRoZSBoYXNoZWRcblx0XHRcdC8vIHN1YnBhY2tldCBib2R5LlxuXHRcdFx0dGhpcy5zaWduYXR1cmVEYXRhID0gYnl0ZXMuc3Vic3RyKDAsIGkpO1xuXG5cdFx0XHRpICs9IHN1YnBhY2tldHMuY2FsbCh0aGlzLCBieXRlcy5zdWJzdHIoaSksIGZhbHNlKTtcblxuXHRcdFx0YnJlYWs7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHRocm93IG5ldyBFcnJvcignVmVyc2lvbiAnICsgdmVyc2lvbiArICcgb2YgdGhlIHNpZ25hdHVyZSBpcyB1bnN1cHBvcnRlZC4nKTtcblx0XHRcdGJyZWFrO1xuXHRcdH1cblxuXHRcdC8vIFR3by1vY3RldCBmaWVsZCBob2xkaW5nIGxlZnQgMTYgYml0cyBvZiBzaWduZWQgaGFzaCB2YWx1ZS5cblx0XHR0aGlzLnNpZ25lZEhhc2hWYWx1ZSA9IGJ5dGVzLnN1YnN0cihpLCAyKTtcblx0XHRpICs9IDI7XG5cblx0XHR0aGlzLnNpZ25hdHVyZSA9IGJ5dGVzLnN1YnN0cihpKTtcblx0fVxuXG5cdHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5zaWduYXR1cmVEYXRhICsgXG5cdFx0XHR1dGlsLndyaXRlTnVtYmVyKDAsIDIpICsgLy8gTnVtYmVyIG9mIHVuc2lnbmVkIHN1YnBhY2tldHMuXG5cdFx0XHR0aGlzLnNpZ25lZEhhc2hWYWx1ZSArXG5cdFx0XHR0aGlzLnNpZ25hdHVyZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTaWducyBwcm92aWRlZCBkYXRhLiBUaGlzIG5lZWRzIHRvIGJlIGRvbmUgcHJpb3IgdG8gc2VyaWFsaXphdGlvbi5cblx0ICogQHBhcmFtIHtPYmplY3R9IGRhdGEgQ29udGFpbnMgcGFja2V0cyB0byBiZSBzaWduZWQuXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0gcHJpdmF0ZWtleSBwcml2YXRlIGtleSB1c2VkIHRvIHNpZ24gdGhlIG1lc3NhZ2UuIFxuXHQgKi9cblx0dGhpcy5zaWduID0gZnVuY3Rpb24oa2V5LCBkYXRhKSB7XG5cdFx0dmFyIHNpZ25hdHVyZVR5cGUgPSBlbnVtcy53cml0ZShlbnVtcy5zaWduYXR1cmUsIHRoaXMuc2lnbmF0dXJlVHlwZSksXG5cdFx0XHRwdWJsaWNLZXlBbGdvcml0aG0gPSBlbnVtcy53cml0ZShlbnVtcy5wdWJsaWNLZXksIHRoaXMucHVibGljS2V5QWxnb3JpdGhtKSxcblx0XHRcdGhhc2hBbGdvcml0aG0gPSBlbnVtcy53cml0ZShlbnVtcy5oYXNoLCB0aGlzLmhhc2hBbGdvcml0aG0pO1xuXG5cdFx0dmFyIHJlc3VsdCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoNCk7IFxuXHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHNpZ25hdHVyZVR5cGUpO1xuXHRcdHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHB1YmxpY0tleUFsZ29yaXRobSk7XG5cdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoaGFzaEFsZ29yaXRobSk7XG5cblxuXHRcdC8vIEFkZCBzdWJwYWNrZXRzIGhlcmVcblx0XHRyZXN1bHQgKz0gdXRpbC53cml0ZU51bWJlcigwLCAyKTtcblxuXG5cdFx0dGhpcy5zaWduYXR1cmVEYXRhID0gcmVzdWx0O1xuXG5cdFx0dmFyIHRyYWlsZXIgPSB0aGlzLmNhbGN1bGF0ZVRyYWlsZXIoKTtcblx0XHRcblx0XHR2YXIgdG9IYXNoID0gdGhpcy50b1NpZ24oc2lnbmF0dXJlVHlwZSwgZGF0YSkgKyBcblx0XHRcdHRoaXMuc2lnbmF0dXJlRGF0YSArIHRyYWlsZXI7XG5cblx0XHR2YXIgaGFzaCA9IGNyeXB0by5oYXNoLmRpZ2VzdChoYXNoQWxnb3JpdGhtLCB0b0hhc2gpO1xuXHRcdFxuXHRcdHRoaXMuc2lnbmVkSGFzaFZhbHVlID0gaGFzaC5zdWJzdHIoMCwgMik7XG5cblxuXHRcdHRoaXMuc2lnbmF0dXJlID0gY3J5cHRvLnNpZ25hdHVyZS5zaWduKGhhc2hBbGdvcml0aG0sIFxuXHRcdFx0cHVibGljS2V5QWxnb3JpdGhtLCBrZXkubXBpLCB0b0hhc2gpO1xuXHR9XG5cblx0LyoqXG5cdCAqIGNyZWF0ZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBzdWIgc2lnbmF0dXJlIHBhY2tldCAoU2VlIFJGQyA0ODgwIDUuMi4zLjEpXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gdHlwZSBzdWJwYWNrZXQgc2lnbmF0dXJlIHR5cGUuIFNpZ25hdHVyZSB0eXBlcyBhcyBkZXNjcmliZWQgXG5cdCAqIGluIFJGQzQ4ODAgU2VjdGlvbiA1LjIuMy4yXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIGRhdGEgdG8gYmUgaW5jbHVkZWRcblx0ICogQHJldHVybiB7U3RyaW5nfSBhIHN0cmluZy1yZXByZXNlbnRhdGlvbiBvZiBhIHN1YiBzaWduYXR1cmUgcGFja2V0IChTZWUgUkZDIDQ4ODAgNS4yLjMuMSlcblx0ICovXG5cdGZ1bmN0aW9uIHdyaXRlX3N1Yl9wYWNrZXQodHlwZSwgZGF0YSkge1xuXHRcdHZhciByZXN1bHQgPSBcIlwiO1xuXHRcdHJlc3VsdCArPSBwYWNrZXQud3JpdGVTaW1wbGVMZW5ndGgoZGF0YS5sZW5ndGgrMSk7XG5cdFx0cmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodHlwZSk7XG5cdFx0cmVzdWx0ICs9IGRhdGE7XG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fVxuXHRcblx0Ly8gVjQgc2lnbmF0dXJlIHN1YiBwYWNrZXRzXG5cdFxuXHR0aGlzLnJlYWRfc3ViX3BhY2tldCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG5cdFx0dmFyIG15cG9zID0gMDtcblxuXHRcdGZ1bmN0aW9uIHJlYWRfYXJyYXkocHJvcCwgYnl0ZXMpIHtcblx0XHRcdHRoaXNbcHJvcF0gPSBbXTtcblxuXHRcdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHR0aGlzW3Byb3BdLnB1c2goYnl0ZXNbaV0uY2hhckNvZGVBdCgpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0XG5cdFx0Ly8gVGhlIGxlZnR3b3N0IGJpdCBkZW5vdGVzIGEgXCJjcml0aWNhbFwiIHBhY2tldCwgYnV0IHdlIGlnbm9yZSBpdC5cblx0XHR2YXIgdHlwZSA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKSAmIDB4N0Y7XG5cblx0XHQvLyBzdWJwYWNrZXQgdHlwZVxuXHRcdHN3aXRjaCAodHlwZSkge1xuXHRcdGNhc2UgMjogLy8gU2lnbmF0dXJlIENyZWF0aW9uIFRpbWVcblx0XHRcdHRoaXMuY3JlYXRlZCA9IHV0aWwucmVhZERhdGUoYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDM6IC8vIFNpZ25hdHVyZSBFeHBpcmF0aW9uIFRpbWVcblx0XHRcdHZhciB0aW1lID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIobXlwb3MpKTtcblxuXHRcdFx0dGhpcy5zaWduYXR1cmVOZXZlckV4cGlyZXMgPSB0aW1lLmdldFRpbWUoKSA9PSAwO1xuXHRcdFx0dGhpcy5zaWduYXR1cmVFeHBpcmF0aW9uVGltZSA9IHRpbWU7XG5cdFx0XHRcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgNDogLy8gRXhwb3J0YWJsZSBDZXJ0aWZpY2F0aW9uXG5cdFx0XHR0aGlzLmV4cG9ydGFibGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgPT0gMTtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgNTogLy8gVHJ1c3QgU2lnbmF0dXJlXG5cdFx0XHR0aGlzLnRydXN0TGV2ZWwgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG5cdFx0XHR0aGlzLnRydXN0QW1vdW50ID0gYnl0ZXNbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSA2OiAvLyBSZWd1bGFyIEV4cHJlc3Npb25cblx0XHRcdHRoaXMucmVndWxhckV4cHJlc3Npb24gPSBieXRlcy5zdWJzdHIobXlwb3MpO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSA3OiAvLyBSZXZvY2FibGVcblx0XHRcdHRoaXMucmV2b2NhYmxlID0gYnl0ZXNbbXlwb3MrK10uY2hhckNvZGVBdCgpID09IDE7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDk6IC8vIEtleSBFeHBpcmF0aW9uIFRpbWVcblx0XHRcdHZhciB0aW1lID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIobXlwb3MpKTtcblxuXHRcdFx0dGhpcy5rZXlFeHBpcmF0aW9uVGltZSA9IHRpbWU7XG5cdFx0XHR0aGlzLmtleU5ldmVyRXhwaXJlcyA9IHRpbWUuZ2V0VGltZSgpID09IDA7XG5cblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgMTE6IC8vIFByZWZlcnJlZCBTeW1tZXRyaWMgQWxnb3JpdGhtc1xuXHRcdFx0dGhpcy5wcmVmZXJyZWRTeW1tZXRyaWNBbGdvcml0aG1zID0gW107XG5cblx0XHRcdHdoaWxlKG15cG9zICE9IGJ5dGVzLmxlbmd0aCkge1xuXHRcdFx0XHR0aGlzLnByZWZlcnJlZFN5bW1ldHJpY0FsZ29yaXRobXMucHVzaChieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkpO1xuXHRcdFx0fVxuXG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDEyOiAvLyBSZXZvY2F0aW9uIEtleVxuXHRcdFx0Ly8gKDEgb2N0ZXQgb2YgY2xhc3MsIDEgb2N0ZXQgb2YgcHVibGljLWtleSBhbGdvcml0aG0gSUQsIDIwXG5cdFx0XHQvLyBvY3RldHMgb2Zcblx0XHRcdC8vIGZpbmdlcnByaW50KVxuXHRcdFx0dGhpcy5yZXZvY2F0aW9uS2V5Q2xhc3MgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG5cdFx0XHR0aGlzLnJldm9jYXRpb25LZXlBbGdvcml0aG0gPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG5cdFx0XHR0aGlzLnJldm9jYXRpb25LZXlGaW5nZXJwcmludCA9IGJ5dGVzLnN1YnN0cihteXBvcywgMjApO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlIDE2OiAvLyBJc3N1ZXJcblx0XHRcdHRoaXMuaXNzdWVyS2V5SWQgPSBieXRlcy5zdWJzdHIobXlwb3MsIDgpO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlIDIwOiAvLyBOb3RhdGlvbiBEYXRhXG5cdFx0XHQvLyBXZSBkb24ndCBrbm93IGhvdyB0byBoYW5kbGUgYW55dGhpbmcgYnV0IGEgdGV4dCBmbGFnZ2VkIGRhdGEuXG5cdFx0XHRpZihieXRlc1tteXBvc10uY2hhckNvZGVBdCgpID09IDB4ODApIHtcblxuXHRcdFx0XHQvLyBXZSBleHRyYWN0IGtleS92YWx1ZSB0dXBsZSBmcm9tIHRoZSBieXRlIHN0cmVhbS5cblx0XHRcdFx0bXlwb3MgKz0gNDtcblx0XHRcdFx0dmFyIG0gPSB1dGlsLndyaXRlTnVtYmVyKGJ5dGVzLnN1YnN0cihteXBvcywgMikpO1xuXHRcdFx0XHRteXBvcyArPSAyXG5cdFx0XHRcdHZhciBuID0gdXRpbC53cml0ZU51bWJlcihieXRlcy5zdWJzdHIobXlwb3MsIDIpKTtcblx0XHRcdFx0bXlwb3MgKz0gMlxuXG5cdFx0XHRcdHZhciBuYW1lID0gYnl0ZXMuc3Vic3RyKG15cG9zLCBtKSxcblx0XHRcdFx0XHR2YWx1ZSA9IGJ5dGVzLnN1YnN0cihteXBvcyArIG0sIG4pO1xuXG5cdFx0XHRcdHRoaXMubm90YXRpb25bbmFtZV0gPSB2YWx1ZTtcblx0XHRcdH1cblx0XHRcdGVsc2UgdGhyb3cgbmV3IEVycm9yKFwiVW5zdXBwb3J0ZWQgbm90YXRpb24gZmxhZy5cIik7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDIxOiAvLyBQcmVmZXJyZWQgSGFzaCBBbGdvcml0aG1zXG5cdFx0XHRyZWFkX2FycmF5LmNhbGwodGhpcywgJ3ByZWZlcnJlZEhhc2hBbGdvcml0aG1zJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDIyOiAvLyBQcmVmZXJyZWQgQ29tcHJlc3Npb24gQWxnb3JpdGhtc1xuXHRcdFx0cmVhZF9hcnJheS5jYWxsKHRoaXMsICdwcmVmZXJyZWRDb21wcmVzc2lvbkFsZ29yaXRobXMgJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDIzOiAvLyBLZXkgU2VydmVyIFByZWZlcmVuY2VzXG5cdFx0XHRyZWFkX2FycmF5LmNhbGwodGhpcywgJ2tleVNlcnZlclByZWZlcmVuY2VzcycsIGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAyNDogLy8gUHJlZmVycmVkIEtleSBTZXJ2ZXJcblx0XHRcdHRoaXMucHJlZmVycmVkS2V5U2VydmVyID0gYnl0ZXMuc3Vic3RyKG15cG9zKTtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgMjU6IC8vIFByaW1hcnkgVXNlciBJRFxuXHRcdFx0dGhpcy5pc1ByaW1hcnlVc2VySUQgPSBieXRlc1tteXBvcysrXSAhPSAwO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAyNjogLy8gUG9saWN5IFVSSVxuXHRcdFx0dGhpcy5wb2xpY3lVUkkgPSBieXRlcy5zdWJzdHIobXlwb3MpO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAyNzogLy8gS2V5IEZsYWdzXG5cdFx0XHRyZWFkX2FycmF5LmNhbGwodGhpcywgJ2tleUZsYWdzJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDI4OiAvLyBTaWduZXIncyBVc2VyIElEXG5cdFx0XHR0aGlzLnNpZ25lcnNVc2VySWQgKz0gYnl0ZXMuc3Vic3RyKG15cG9zKTtcblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgMjk6IC8vIFJlYXNvbiBmb3IgUmV2b2NhdGlvblxuXHRcdFx0dGhpcy5yZWFzb25Gb3JSZXZvY2F0aW9uRmxhZyA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKTtcblx0XHRcdHRoaXMucmVhc29uRm9yUmV2b2NhdGlvblN0cmluZyA9IGJ5dGVzLnN1YnN0cihteXBvcyk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDMwOiAvLyBGZWF0dXJlc1xuXHRcdFx0cmVhZF9hcnJheS5jYWxsKHRoaXMsICdmZWF0dXJlcycsIGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAzMTogLy8gU2lnbmF0dXJlIFRhcmdldFxuXHRcdFx0Ly8gKDEgb2N0ZXQgcHVibGljLWtleSBhbGdvcml0aG0sIDEgb2N0ZXQgaGFzaCBhbGdvcml0aG0sIE4gb2N0ZXRzIGhhc2gpXG5cdFx0XHR0aGlzLnNpZ25hdHVyZVRhcmdldFB1YmxpY0tleUFsZ29yaXRobSA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKTtcblx0XHRcdHRoaXMuc2lnbmF0dXJlVGFyZ2V0SGFzaEFsZ29yaXRobSA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKTtcblxuXHRcdFx0dmFyIGxlbiA9IGNyeXB0by5nZXRIYXNoQnl0ZUxlbmd0aCh0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2hBbGdvcml0aG0pO1xuXG5cdFx0XHR0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2ggPSBieXRlcy5zdWJzdHIobXlwb3MsIGxlbik7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlIDMyOiAvLyBFbWJlZGRlZCBTaWduYXR1cmVcblx0XHRcdHRoaXMuZW1iZWRkZWRTaWduYXR1cmUgPSBuZXcgcGFja2V0X3NpZ25hdHVyZSgpO1xuXHRcdFx0dGhpcy5lbWJlZGRlZFNpZ25hdHVyZS5yZWFkKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXHRcdFx0YnJlYWs7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHV0aWwucHJpbnRfZXJyb3IoXCJvcGVucGdwLnBhY2tldC5zaWduYXR1cmUuanNcXG5cIitcblx0XHRcdFx0J3Vua25vd24gc2lnbmF0dXJlIHN1YnBhY2tldCB0eXBlICcrdHlwZStcIiBAOlwiK215cG9zK1xuXHRcdFx0XHRcIiBzdWJwbGVuOlwiK3N1YnBsZW4rXCIgbGVuOlwiK2xlbik7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH07XG5cblx0Ly8gUHJvZHVjZXMgZGF0YSB0byBwcm9kdWNlIHNpZ25hdHVyZSBvblxuXHR0aGlzLnRvU2lnbiA9IGZ1bmN0aW9uKHR5cGUsIGRhdGEpIHtcblx0XHR2YXIgdCA9IGVudW1zLnNpZ25hdHVyZVxuXG5cdFx0c3dpdGNoKHR5cGUpIHtcblx0XHRjYXNlIHQuYmluYXJ5OlxuXHRcdFx0cmV0dXJuIGRhdGEubGl0ZXJhbC5nZXRCeXRlcygpO1xuXG5cdFx0Y2FzZSB0LnRleHQ6XG5cdFx0XHRyZXR1cm4gdGhpcy50b1NpZ24odC5iaW5hcnksIGRhdGEpXG5cdFx0XHRcdC5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpXG5cdFx0XHRcdC5yZXBsYWNlKC9cXG4vZywgJ1xcclxcbicpO1xuXHRcdFx0XHRcblx0XHRjYXNlIHQuc3RhbmRhbG9uZTpcblx0XHRcdHJldHVybiAnJ1xuXG5cdFx0Y2FzZSB0LmNlcnRfZ2VuZXJpYzpcblx0XHRjYXNlIHQuY2VydF9wZXJzb25hOlxuXHRcdGNhc2UgdC5jZXJ0X2Nhc3VhbDpcblx0XHRjYXNlIHQuY2VydF9wb3NpdGl2ZTpcblx0XHRjYXNlIHQuY2VydF9yZXZvY2F0aW9uOlxuXHRcdHtcblx0XHRcdHZhciBwYWNrZXQsIHRhZztcblxuXHRcdFx0aWYoZGF0YS51c2VyaWQgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHRhZyA9IDB4QjQ7XG5cdFx0XHRcdHBhY2tldCA9IGRhdGEudXNlcmlkO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZihkYXRhLnVzZXJhdHRyaWJ1dGUgIT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdHRhZyA9IDB4RDFcblx0XHRcdFx0cGFja2V0ID0gZGF0YS51c2VyYXR0cmlidXRlO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB0aHJvdyBuZXcgRXJyb3IoJ0VpdGhlciBhIHVzZXJpZCBvciB1c2VyYXR0cmlidXRlIHBhY2tldCBuZWVkcyB0byBiZSAnICtcblx0XHRcdFx0J3N1cHBsaWVkIGZvciBjZXJ0aWZpY2F0aW9uLicpO1xuXG5cblx0XHRcdHZhciBieXRlcyA9IHBhY2tldC53cml0ZSgpO1xuXG5cdFx0XHRcblx0XHRcdHJldHVybiB0aGlzLnRvU2lnbih0LmtleSwgZGF0YSkgK1xuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKHRhZykgK1xuXHRcdFx0XHR1dGlsLndyaXRlTnVtYmVyKGJ5dGVzLmxlbmd0aCwgNCkgK1xuXHRcdFx0XHRieXRlcztcblx0XHR9XG5cdFx0Y2FzZSB0LnN1YmtleV9iaW5kaW5nOlxuXHRcdGNhc2UgdC5rZXlfYmluZGluZzpcblx0XHR7XG5cdFx0XHRyZXR1cm4gdGhpcy50b1NpZ24odC5rZXksIGRhdGEpICsgdGhpcy50b1NpZ24odC5rZXksIHsga2V5OiBkYXRhLmJpbmQgfSk7XG5cdFx0fVxuXHRcdGNhc2UgdC5rZXk6XG5cdFx0e1xuXHRcdFx0aWYoZGF0YS5rZXkgPT0gdW5kZWZpbmVkKVxuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0tleSBwYWNrZXQgaXMgcmVxdWlyZWQgZm9yIHRoaXMgc2lndGF0dXJlLicpO1xuXHRcdFx0XG5cdFx0XHRyZXR1cm4gZGF0YS5rZXkud3JpdGVPbGQoKTtcblx0XHR9XG5cdFx0Y2FzZSB0LmtleV9yZXZvY2F0aW9uOlxuXHRcdGNhc2UgdC5zdWJrZXlfcmV2b2NhdGlvbjpcblx0XHRcdHJldHVybiB0aGlzLnRvU2lnbih0LmtleSwgZGF0YSk7XG5cdFx0Y2FzZSB0LnRpbWVzdGFtcDpcblx0XHRcdHJldHVybiAnJztcblx0XHRjYXNlIHQudGhyaWRfcGFydHk6XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ05vdCBpbXBsZW1lbnRlZCcpO1xuXHRcdFx0YnJlYWs7XG5cdFx0ZGVmYXVsdDpcblx0XHRcdHRocm93IG5ldyBFcnJvcignVW5rbm93biBzaWduYXR1cmUgdHlwZS4nKVxuXHRcdH1cblx0fVxuXG5cdFxuXHR0aGlzLmNhbGN1bGF0ZVRyYWlsZXIgPSBmdW5jdGlvbigpIHtcblx0XHQvLyBjYWxjdWxhdGluZyB0aGUgdHJhaWxlclxuXHRcdHZhciB0cmFpbGVyID0gJyc7XG5cdFx0dHJhaWxlciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDQpOyAvLyBWZXJzaW9uXG5cdFx0dHJhaWxlciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4RkYpO1xuXHRcdHRyYWlsZXIgKz0gdXRpbC53cml0ZU51bWJlcih0aGlzLnNpZ25hdHVyZURhdGEubGVuZ3RoLCA0KTtcblx0XHRyZXR1cm4gdHJhaWxlclxuXHR9XG5cblxuXHQvKipcblx0ICogdmVyaWZ5cyB0aGUgc2lnbmF0dXJlIHBhY2tldC4gTm90ZTogbm90IHNpZ25hdHVyZSB0eXBlcyBhcmUgaW1wbGVtZW50ZWRcblx0ICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgZGF0YSB3aGljaCBvbiB0aGUgc2lnbmF0dXJlIGFwcGxpZXNcblx0ICogQHBhcmFtIHtvcGVucGdwX21zZ19wcml2YXRla2V5fSBrZXkgdGhlIHB1YmxpYyBrZXkgdG8gdmVyaWZ5IHRoZSBzaWduYXR1cmVcblx0ICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBtZXNzYWdlIGlzIHZlcmlmaWVkLCBlbHNlIGZhbHNlLlxuXHQgKi9cblx0dGhpcy52ZXJpZnkgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcblx0XHR2YXIgc2lnbmF0dXJlVHlwZSA9IGVudW1zLndyaXRlKGVudW1zLnNpZ25hdHVyZSwgdGhpcy5zaWduYXR1cmVUeXBlKSxcblx0XHRcdHB1YmxpY0tleUFsZ29yaXRobSA9IGVudW1zLndyaXRlKGVudW1zLnB1YmxpY0tleSwgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0pLFxuXHRcdFx0aGFzaEFsZ29yaXRobSA9IGVudW1zLndyaXRlKGVudW1zLmhhc2gsIHRoaXMuaGFzaEFsZ29yaXRobSk7XG5cblx0XHR2YXIgYnl0ZXMgPSB0aGlzLnRvU2lnbihzaWduYXR1cmVUeXBlLCBkYXRhKSxcblx0XHRcdHRyYWlsZXIgPSB0aGlzLmNhbGN1bGF0ZVRyYWlsZXIoKTtcblxuXG5cdFx0dmFyIG1waWNvdW50ID0gMDtcblx0XHQvLyBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBSU0Egc2lnbmF0dXJlczpcblx0XHQvLyBcdCAgICAtIG11bHRpcHJlY2lzaW9uIG51bWJlciAoTVBJKSBvZiBSU0Egc2lnbmF0dXJlIHZhbHVlIG0qKmQgbW9kIG4uXG5cdFx0aWYgKHB1YmxpY0tleUFsZ29yaXRobSA+IDAgJiYgcHVibGljS2V5QWxnb3JpdGhtIDwgNClcblx0XHRcdG1waWNvdW50ID0gMTtcblx0XHQvLyAgICBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBEU0Egc2lnbmF0dXJlczpcblx0XHQvLyAgICAgIC0gTVBJIG9mIERTQSB2YWx1ZSByLlxuXHRcdC8vICAgICAgLSBNUEkgb2YgRFNBIHZhbHVlIHMuXG5cdFx0ZWxzZSBpZiAocHVibGljS2V5QWxnb3JpdGhtID09IDE3KVxuXHRcdFx0bXBpY291bnQgPSAyO1xuXHRcdFxuXHRcdHZhciBtcGkgPSBbXSwgaSA9IDA7XG5cdFx0Zm9yICh2YXIgaiA9IDA7IGogPCBtcGljb3VudDsgaisrKSB7XG5cdFx0XHRtcGlbal0gPSBuZXcgdHlwZV9tcGkoKTtcblx0XHRcdGkgKz0gbXBpW2pdLnJlYWQodGhpcy5zaWduYXR1cmUuc3Vic3RyKGkpKTtcblx0XHR9XG5cblx0XHR0aGlzLnZlcmlmaWVkID0gY3J5cHRvLnNpZ25hdHVyZS52ZXJpZnkocHVibGljS2V5QWxnb3JpdGhtLCBcblx0XHRcdGhhc2hBbGdvcml0aG0sIG1waSwga2V5Lm1waSwgXG5cdFx0XHRieXRlcyArIHRoaXMuc2lnbmF0dXJlRGF0YSArIHRyYWlsZXIpO1xuXG5cdFx0cmV0dXJuIHRoaXMudmVyaWZpZWQ7XG5cdH1cbn1cblxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG5cdGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgU3ltLiBFbmNyeXB0ZWQgSW50ZWdyaXR5IFByb3RlY3RlZCBEYXRhIFxuICogUGFja2V0IChUYWcgMTgpXG4gKiBcbiAqIFJGQzQ4ODAgNS4xMzogVGhlIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIEludGVncml0eSBQcm90ZWN0ZWQgRGF0YSBwYWNrZXQgaXNcbiAqIGEgdmFyaWFudCBvZiB0aGUgU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBwYWNrZXQuIEl0IGlzIGEgbmV3IGZlYXR1cmVcbiAqIGNyZWF0ZWQgZm9yIE9wZW5QR1AgdGhhdCBhZGRyZXNzZXMgdGhlIHByb2JsZW0gb2YgZGV0ZWN0aW5nIGEgbW9kaWZpY2F0aW9uIHRvXG4gKiBlbmNyeXB0ZWQgZGF0YS4gSXQgaXMgdXNlZCBpbiBjb21iaW5hdGlvbiB3aXRoIGEgTW9kaWZpY2F0aW9uIERldGVjdGlvbiBDb2RlXG4gKiBwYWNrZXQuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfc3ltX2VuY3J5cHRlZF9pbnRlZ3JpdHlfcHJvdGVjdGVkKCkge1xuXHQvKiogVGhlIGVuY3J5cHRlZCBwYXlsb2FkLiAqL1xuXHR0aGlzLmVuY3J5cHRlZCA9IG51bGw7IC8vIHN0cmluZ1xuXHQvKiogQHR5cGUge0Jvb2xlYW59XG5cdCAqIElmIGFmdGVyIGRlY3J5cHRpbmcgdGhlIHBhY2tldCB0aGlzIGlzIHNldCB0byB0cnVlLFxuXHQgKiBhIG1vZGlmaWNhdGlvbiBoYXMgYmVlbiBkZXRlY3RlZCBhbmQgdGh1cyB0aGUgY29udGVudHNcblx0ICogc2hvdWxkIGJlIGRpc2NhcmRlZC5cblx0ICovXG5cdHRoaXMubW9kaWZpY2F0aW9uID0gZmFsc2U7XG5cdHRoaXMucGFja2V0cztcblxuXG5cdHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG5cdFx0Ly8gLSBBIG9uZS1vY3RldCB2ZXJzaW9uIG51bWJlci4gVGhlIG9ubHkgY3VycmVudGx5IGRlZmluZWQgdmFsdWUgaXNcblx0XHQvLyAxLlxuXHRcdHZhciB2ZXJzaW9uID0gYnl0ZXNbMF0uY2hhckNvZGVBdCgpO1xuXG5cdFx0aWYgKHZlcnNpb24gIT0gMSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhY2tldCB2ZXJzaW9uLicpO1xuXHRcdH1cblxuXHRcdC8vIC0gRW5jcnlwdGVkIGRhdGEsIHRoZSBvdXRwdXQgb2YgdGhlIHNlbGVjdGVkIHN5bW1ldHJpYy1rZXkgY2lwaGVyXG5cdFx0Ly8gICBvcGVyYXRpbmcgaW4gQ2lwaGVyIEZlZWRiYWNrIG1vZGUgd2l0aCBzaGlmdCBhbW91bnQgZXF1YWwgdG8gdGhlXG5cdFx0Ly8gICBibG9jayBzaXplIG9mIHRoZSBjaXBoZXIgKENGQi1uIHdoZXJlIG4gaXMgdGhlIGJsb2NrIHNpemUpLlxuXHRcdHRoaXMuZW5jcnlwdGVkID0gYnl0ZXMuc3Vic3RyKDEpO1xuXHR9XG5cblx0dGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFxuXHRcdHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKDEpIC8vIFZlcnNpb25cblx0XHRcdCsgdGhpcy5lbmNyeXB0ZWQ7XG5cdH1cblxuXHR0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihzZXNzaW9uS2V5QWxnb3JpdGhtLCBrZXkpIHtcblx0XHR2YXIgYnl0ZXMgPSB0aGlzLnBhY2tldHMud3JpdGUoKVxuXHRcdFxuXHRcdHZhciBwcmVmaXhyYW5kb20gPSBjcnlwdG8uZ2V0UHJlZml4UmFuZG9tKHNlc3Npb25LZXlBbGdvcml0aG0pO1xuXHRcdHZhciBwcmVmaXggPSBwcmVmaXhyYW5kb21cblx0XHRcdFx0KyBwcmVmaXhyYW5kb20uY2hhckF0KHByZWZpeHJhbmRvbS5sZW5ndGggLSAyKVxuXHRcdFx0XHQrIHByZWZpeHJhbmRvbS5jaGFyQXQocHJlZml4cmFuZG9tLmxlbmd0aCAtIDEpXG5cblx0XHR2YXIgdG9oYXNoID0gYnl0ZXM7XG5cblxuXHRcdC8vIE1vZGlmaWNhdGlvbiBkZXRlY3Rpb24gY29kZSBwYWNrZXQuXG5cdFx0dG9oYXNoICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhEMyk7XG5cdFx0dG9oYXNoICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHgxNCk7XG5cblxuXHRcdHRvaGFzaCArPSBjcnlwdG8uaGFzaC5zaGExKHByZWZpeCArIHRvaGFzaCk7XG5cblxuXHRcdHRoaXMuZW5jcnlwdGVkID0gY3J5cHRvLmNmYi5lbmNyeXB0KHByZWZpeHJhbmRvbSxcblx0XHRcdFx0c2Vzc2lvbktleUFsZ29yaXRobSwgdG9oYXNoLCBrZXksIGZhbHNlKS5zdWJzdHJpbmcoMCxcblx0XHRcdFx0cHJlZml4Lmxlbmd0aCArIHRvaGFzaC5sZW5ndGgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIERlY3J5cHRzIHRoZSBlbmNyeXB0ZWQgZGF0YSBjb250YWluZWQgaW4gdGhpcyBvYmplY3QgcmVhZF9wYWNrZXQgbXVzdFxuXHQgKiBoYXZlIGJlZW4gY2FsbGVkIGJlZm9yZVxuXHQgKiBcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBzZXNzaW9uS2V5QWxnb3JpdGhtXG5cdCAqICAgICAgICAgICAgVGhlIHNlbGVjdGVkIHN5bW1ldHJpYyBlbmNyeXB0aW9uIGFsZ29yaXRobSB0byBiZSB1c2VkXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBrZXkgVGhlIGtleSBvZiBjaXBoZXIgYmxvY2tzaXplIGxlbmd0aCB0byBiZSB1c2VkXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gVGhlIGRlY3J5cHRlZCBkYXRhIG9mIHRoaXMgcGFja2V0XG5cdCAqL1xuXHR0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihzZXNzaW9uS2V5QWxnb3JpdGhtLCBrZXkpIHtcblx0XHR2YXIgZGVjcnlwdGVkID0gY3J5cHRvLmNmYi5kZWNyeXB0KFxuXHRcdFx0XHRzZXNzaW9uS2V5QWxnb3JpdGhtLCBrZXksIHRoaXMuZW5jcnlwdGVkLCBmYWxzZSk7XG5cblxuXHRcdC8vIHRoZXJlIG11c3QgYmUgYSBtb2RpZmljYXRpb24gZGV0ZWN0aW9uIGNvZGUgcGFja2V0IGFzIHRoZVxuXHRcdC8vIGxhc3QgcGFja2V0IGFuZCBldmVyeXRoaW5nIGdldHMgaGFzaGVkIGV4Y2VwdCB0aGUgaGFzaCBpdHNlbGZcblx0XHR0aGlzLmhhc2ggPSBjcnlwdG8uaGFzaC5zaGExKFxuXHRcdFx0Y3J5cHRvLmNmYi5tZGMoc2Vzc2lvbktleUFsZ29yaXRobSwga2V5LCB0aGlzLmVuY3J5cHRlZClcblx0XHRcdCsgZGVjcnlwdGVkLnN1YnN0cmluZygwLCBkZWNyeXB0ZWQubGVuZ3RoIC0gMjApKTtcblxuXG5cdFx0dmFyIG1kYyA9IGRlY3J5cHRlZC5zdWJzdHIoZGVjcnlwdGVkLmxlbmd0aCAtIDIwLCAyMCk7XG5cblx0XHRpZih0aGlzLmhhc2ggIT0gbWRjKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01vZGlmaWNhdGlvbiBkZXRlY3RlZC4nKTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdFx0dGhpcy5wYWNrZXRzLnJlYWQoZGVjcnlwdGVkLnN1YnN0cigwLCBkZWNyeXB0ZWQubGVuZ3RoIC0gMjIpKTtcblx0fVxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB0eXBlX3MyayA9IHJlcXVpcmUoJy4uL3R5cGUvczJrLmpzJyksXG5cdGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcblx0Y3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIFB1YmxpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IFBhY2tldHMgKFRhZyAxKVxuICogXG4gKiBSRkM0ODgwIDUuMTogQSBQdWJsaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXQgaG9sZHMgdGhlIHNlc3Npb24ga2V5XG4gKiB1c2VkIHRvIGVuY3J5cHQgYSBtZXNzYWdlLiBaZXJvIG9yIG1vcmUgUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXlcbiAqIHBhY2tldHMgYW5kL29yIFN5bW1ldHJpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldHMgbWF5IHByZWNlZGUgYVxuICogU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQsIHdoaWNoIGhvbGRzIGFuIGVuY3J5cHRlZCBtZXNzYWdlLiBUaGVcbiAqIG1lc3NhZ2UgaXMgZW5jcnlwdGVkIHdpdGggdGhlIHNlc3Npb24ga2V5LCBhbmQgdGhlIHNlc3Npb24ga2V5IGlzIGl0c2VsZlxuICogZW5jcnlwdGVkIGFuZCBzdG9yZWQgaW4gdGhlIEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXQocykuIFRoZVxuICogU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQgaXMgcHJlY2VkZWQgYnkgb25lIFB1YmxpYy1LZXkgRW5jcnlwdGVkXG4gKiBTZXNzaW9uIEtleSBwYWNrZXQgZm9yIGVhY2ggT3BlblBHUCBrZXkgdG8gd2hpY2ggdGhlIG1lc3NhZ2UgaXMgZW5jcnlwdGVkLlxuICogVGhlIHJlY2lwaWVudCBvZiB0aGUgbWVzc2FnZSBmaW5kcyBhIHNlc3Npb24ga2V5IHRoYXQgaXMgZW5jcnlwdGVkIHRvIHRoZWlyXG4gKiBwdWJsaWMga2V5LCBkZWNyeXB0cyB0aGUgc2Vzc2lvbiBrZXksIGFuZCB0aGVuIHVzZXMgdGhlIHNlc3Npb24ga2V5IHRvXG4gKiBkZWNyeXB0IHRoZSBtZXNzYWdlLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9zeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5KCkge1xuXHR0aGlzLnRhZyA9IDM7XG5cdHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0gPSBudWxsO1xuXHR0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0gPSAnYWVzMjU2Jztcblx0dGhpcy5lbmNyeXB0ZWQgPSBudWxsO1xuXHR0aGlzLnMyayA9IG5ldyB0eXBlX3MyaygpO1xuXG5cdC8qKlxuXHQgKiBQYXJzaW5nIGZ1bmN0aW9uIGZvciBhIHN5bW1ldHJpYyBlbmNyeXB0ZWQgc2Vzc2lvbiBrZXkgcGFja2V0ICh0YWcgMykuXG5cdCAqIFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgUGF5bG9hZCBvZiBhIHRhZyAxIHBhY2tldFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgc3RyaW5nXG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuXG5cdCAqICAgICAgICAgICAgTGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2Zcblx0ICogICAgICAgICAgICBpbnB1dCBhdCBwb3NpdGlvblxuXHQgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBPYmplY3QgcmVwcmVzZW50YXRpb25cblx0ICovXG5cdHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG5cdFx0Ly8gQSBvbmUtb2N0ZXQgdmVyc2lvbiBudW1iZXIuIFRoZSBvbmx5IGN1cnJlbnRseSBkZWZpbmVkIHZlcnNpb24gaXMgNC5cblx0XHR0aGlzLnZlcnNpb24gPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG5cblx0XHQvLyBBIG9uZS1vY3RldCBudW1iZXIgZGVzY3JpYmluZyB0aGUgc3ltbWV0cmljIGFsZ29yaXRobSB1c2VkLlxuXHRcdHZhciBhbGdvID0gZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsIGJ5dGVzWzFdLmNoYXJDb2RlQXQoKSk7XG5cblx0XHQvLyBBIHN0cmluZy10by1rZXkgKFMySykgc3BlY2lmaWVyLCBsZW5ndGggYXMgZGVmaW5lZCBhYm92ZS5cblx0XHR2YXIgczJrbGVuZ3RoID0gdGhpcy5zMmsucmVhZChieXRlcy5zdWJzdHIoMikpO1xuXG5cdFx0Ly8gT3B0aW9uYWxseSwgdGhlIGVuY3J5cHRlZCBzZXNzaW9uIGtleSBpdHNlbGYsIHdoaWNoIGlzIGRlY3J5cHRlZFxuXHRcdC8vIHdpdGggdGhlIHN0cmluZy10by1rZXkgb2JqZWN0LlxuXHRcdHZhciBkb25lID0gczJrbGVuZ3RoICsgMjtcblxuXHRcdGlmKGRvbmUgPCBieXRlcy5sZW5ndGgpIHtcblx0XHRcdHRoaXMuZW5jcnlwdGVkID0gYnl0ZXMuc3Vic3RyKGRvbmUpO1xuXHRcdFx0dGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSA9IGFsZ29cblx0XHR9XG5cdFx0ZWxzZVxuXHRcdFx0dGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtID0gYWxnbztcblx0fVxuXG5cdHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcblx0XHR2YXIgYWxnbyA9IHRoaXMuZW5jcnlwdGVkID09IG51bGwgPyBcblx0XHRcdHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA6XG5cdFx0XHR0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtO1xuXG5cdFx0dmFyIGJ5dGVzID0gU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLnZlcnNpb24pICtcblx0XHRcdFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuc3ltbWV0cmljLCBhbGdvKSkgK1xuXHRcdFx0dGhpcy5zMmsud3JpdGUoKTtcblxuXHRcdGlmKHRoaXMuZW5jcnlwdGVkICE9IG51bGwpXG5cdFx0XHRieXRlcyArPSB0aGlzLmVuY3J5cHRlZDtcblx0XHRyZXR1cm4gYnl0ZXM7XG5cdH1cblxuXHQvKipcblx0ICogRGVjcnlwdHMgdGhlIHNlc3Npb24ga2V5IChvbmx5IGZvciBwdWJsaWMga2V5IGVuY3J5cHRlZCBzZXNzaW9uIGtleVxuXHQgKiBwYWNrZXRzICh0YWcgMSlcblx0ICogXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9tc2dfbWVzc2FnZX0gbXNnXG5cdCAqICAgICAgICAgICAgVGhlIG1lc3NhZ2Ugb2JqZWN0ICh3aXRoIG1lbWJlciBlbmNyeXB0ZWREYXRhXG5cdCAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0ga2V5XG5cdCAqICAgICAgICAgICAgUHJpdmF0ZSBrZXkgd2l0aCBzZWNNUElzIHVubG9ja2VkXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHVuZW5jcnlwdGVkIHNlc3Npb24ga2V5XG5cdCAqL1xuXHR0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihwYXNzcGhyYXNlKSB7XG5cdFx0dmFyIGFsZ28gPSB0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtICE9IG51bGwgP1xuXHRcdFx0dGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSA6XG5cdFx0XHR0aGlzLnNlc3Npb25LZXlBbGdvcml0aG07XG5cblxuXHRcdHZhciBsZW5ndGggPSBjcnlwdG8uY2lwaGVyW2FsZ29dLmtleVNpemU7XG5cdFx0dmFyIGtleSA9IHRoaXMuczJrLnByb2R1Y2Vfa2V5KHBhc3NwaHJhc2UsIGxlbmd0aCk7XG5cblx0XHRpZih0aGlzLmVuY3J5cHRlZCA9PSBudWxsKSB7XG5cdFx0XHR0aGlzLnNlc3Npb25LZXkgPSBrZXk7XG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0dmFyIGRlY3J5cHRlZCA9IGNyeXB0by5jZmIuZGVjcnlwdChcblx0XHRcdFx0dGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSwga2V5LCB0aGlzLmVuY3J5cHRlZCwgdHJ1ZSk7XG5cblx0XHRcdHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMuc3ltbWV0cmljLFxuXHRcdFx0XHRkZWNyeXB0ZWRbMF0ua2V5Q29kZUF0KCkpO1xuXG5cdFx0XHR0aGlzLnNlc3Npb25LZXkgPSBkZWNyeXB0ZWQuc3Vic3RyKDEpO1xuXHRcdH1cblx0fVxuXG5cdHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKHBhc3NwaHJhc2UpIHtcblx0XHR2YXIgbGVuZ3RoID0gY3J5cHRvLmdldEtleUxlbmd0aCh0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtKTtcblx0XHR2YXIga2V5ID0gdGhpcy5zMmsucHJvZHVjZV9rZXkocGFzc3BocmFzZSwgbGVuZ3RoKTtcblxuXHRcdHZhciBwcml2YXRlX2tleSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG5cdFx0XHRlbnVtcy53cml0ZShlbnVtcy5zeW1tZXRyaWMsIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSkpICtcblxuXHRcdFx0Y3J5cHRvLmdldFJhbmRvbUJ5dGVzKFxuXHRcdFx0XHRjcnlwdG8uZ2V0S2V5TGVuZ3RoKHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSkpO1xuXG5cdFx0dGhpcy5lbmNyeXB0ZWQgPSBjcnlwdG8uY2ZiLmVuY3J5cHQoXG5cdFx0XHRcdGNyeXB0by5nZXRQcmVmaXhSYW5kb20odGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSksIFxuXHRcdFx0XHR0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtLCBrZXksIHByaXZhdGVfa2V5LCB0cnVlKTtcblx0fVxufTtcblxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQgKFRhZyA5KVxuICogXG4gKiBSRkM0ODgwIDUuNzogVGhlIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgcGFja2V0IGNvbnRhaW5zIGRhdGEgZW5jcnlwdGVkXG4gKiB3aXRoIGEgc3ltbWV0cmljLWtleSBhbGdvcml0aG0uIFdoZW4gaXQgaGFzIGJlZW4gZGVjcnlwdGVkLCBpdCBjb250YWlucyBvdGhlclxuICogcGFja2V0cyAodXN1YWxseSBhIGxpdGVyYWwgZGF0YSBwYWNrZXQgb3IgY29tcHJlc3NlZCBkYXRhIHBhY2tldCwgYnV0IGluXG4gKiB0aGVvcnkgb3RoZXIgU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBwYWNrZXRzIG9yIHNlcXVlbmNlcyBvZiBwYWNrZXRzXG4gKiB0aGF0IGZvcm0gd2hvbGUgT3BlblBHUCBtZXNzYWdlcykuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQoKSB7XG5cdHRoaXMuZW5jcnlwdGVkID0gbnVsbDtcblx0LyoqIERlY3J5cHRlZCBwYWNrZXRzIGNvbnRhaW5lZCB3aXRoaW4uIFxuXHQgKiBAdHlwZSB7b3BlbnBncF9wYWNrZXRsaXN0fSAqL1xuXHR0aGlzLnBhY2tldHM7XG5cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0XHR0aGlzLmVuY3J5cHRlZCA9IGJ5dGVzO1xuXHR9XG5cblx0dGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVuY3J5cHRlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBTeW1tZXRyaWNhbGx5IGRlY3J5cHQgdGhlIHBhY2tldCBkYXRhXG5cdCAqIFxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHNlc3Npb25LZXlBbGdvcml0aG1cblx0ICogICAgICAgICAgICAgU3ltbWV0cmljIGtleSBhbGdvcml0aG0gdG8gdXNlIC8vIFNlZSBSRkM0ODgwIDkuMlxuXHQgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG5cdCAqICAgICAgICAgICAgIEtleSBhcyBzdHJpbmcgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBsZW5ndGggdG8gdGhlXG5cdCAqICAgICAgICAgICAgYWxnb3JpdGhtXG5cdCAqIEByZXR1cm4gVGhlIGRlY3J5cHRlZCBkYXRhO1xuXHQgKi9cblx0dGhpcy5kZWNyeXB0ID0gZnVuY3Rpb24oc2Vzc2lvbktleUFsZ29yaXRobSwga2V5KSB7XG5cdFx0dmFyIGRlY3J5cHRlZCA9IGNyeXB0by5jZmIuZGVjcnlwdChcblx0XHRcdFx0c2Vzc2lvbktleUFsZ29yaXRobSwga2V5LCB0aGlzLmVuY3J5cHRlZCwgdHJ1ZSk7XG5cblx0XHR0aGlzLnBhY2tldHMucmVhZChkZWNyeXB0ZWQpO1xuXHR9XG5cblx0dGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oYWxnbywga2V5KSB7XG5cdFx0dmFyIGRhdGEgPSB0aGlzLnBhY2tldHMud3JpdGUoKTtcblxuXHRcdHRoaXMuZW5jcnlwdGVkID0gY3J5cHRvLmNmYi5lbmNyeXB0KFxuXHRcdFx0XHRjcnlwdG8uZ2V0UHJlZml4UmFuZG9tKGFsZ28pLCBhbGdvLCBkYXRhLCBrZXksIHRydWUpO1xuXHR9XG59O1xuIiwiXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF90cnVzdCgpIHtcblxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbi8qKiBcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVXNlciBBdHRyaWJ1dGUgUGFja2V0IChUYWcgMTcpXG4gKiAgVGhlIFVzZXIgQXR0cmlidXRlIHBhY2tldCBpcyBhIHZhcmlhdGlvbiBvZiB0aGUgVXNlciBJRCBwYWNrZXQuICBJdFxuICogIGlzIGNhcGFibGUgb2Ygc3RvcmluZyBtb3JlIHR5cGVzIG9mIGRhdGEgdGhhbiB0aGUgVXNlciBJRCBwYWNrZXQsXG4gKiAgd2hpY2ggaXMgbGltaXRlZCB0byB0ZXh0LiAgTGlrZSB0aGUgVXNlciBJRCBwYWNrZXQsIGEgVXNlciBBdHRyaWJ1dGVcbiAqICBwYWNrZXQgbWF5IGJlIGNlcnRpZmllZCBieSB0aGUga2V5IG93bmVyIChcInNlbGYtc2lnbmVkXCIpIG9yIGFueSBvdGhlclxuICogIGtleSBvd25lciB3aG8gY2FyZXMgdG8gY2VydGlmeSBpdC4gIEV4Y2VwdCBhcyBub3RlZCwgYSBVc2VyIEF0dHJpYnV0ZVxuICogIHBhY2tldCBtYXkgYmUgdXNlZCBhbnl3aGVyZSB0aGF0IGEgVXNlciBJRCBwYWNrZXQgbWF5IGJlIHVzZWQuXG4gKlxuICogIFdoaWxlIFVzZXIgQXR0cmlidXRlIHBhY2tldHMgYXJlIG5vdCBhIHJlcXVpcmVkIHBhcnQgb2YgdGhlIE9wZW5QR1BcbiAqICBzdGFuZGFyZCwgaW1wbGVtZW50YXRpb25zIFNIT1VMRCBwcm92aWRlIGF0IGxlYXN0IGVub3VnaFxuICogIGNvbXBhdGliaWxpdHkgdG8gcHJvcGVybHkgaGFuZGxlIGEgY2VydGlmaWNhdGlvbiBzaWduYXR1cmUgb24gdGhlXG4gKiAgVXNlciBBdHRyaWJ1dGUgcGFja2V0LiAgQSBzaW1wbGUgd2F5IHRvIGRvIHRoaXMgaXMgYnkgdHJlYXRpbmcgdGhlXG4gKiAgVXNlciBBdHRyaWJ1dGUgcGFja2V0IGFzIGEgVXNlciBJRCBwYWNrZXQgd2l0aCBvcGFxdWUgY29udGVudHMsIGJ1dFxuICogIGFuIGltcGxlbWVudGF0aW9uIG1heSB1c2UgYW55IG1ldGhvZCBkZXNpcmVkLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF91c2VyX2F0dHJpYnV0ZSgpIHtcblx0dGhpcy50YWcgPSAxNztcblx0dGhpcy5hdHRyaWJ1dGVzID0gW107XG5cblx0LyoqXG5cdCAqIHBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgdXNlciBhdHRyaWJ1dGUgcGFja2V0ICh0YWcgMTcpLlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgcGF5bG9hZCBvZiBhIHRhZyAxNyBwYWNrZXRcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBwb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBsZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBpbnB1dCBhdCBwb3NpdGlvblxuXHQgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBvYmplY3QgcmVwcmVzZW50YXRpb25cblx0ICovXG5cdHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG5cdFx0dmFyIGkgPSAwO1xuXHRcdHdoaWxlKGkgPCBieXRlcy5sZW5ndGgpIHtcblx0XHRcdHZhciBsZW4gPSBvcGVucGdwX3BhY2tldC5yZWFkX3NpbXBsZV9sZW5ndGgoYnl0ZXMpO1xuXG5cdFx0XHRpICs9IGxlbi5vZmZzZXQ7XG5cdFx0XHR0aGlzLmF0dHJpYnV0ZXMucHVzaChieXRlcy5zdWJzdHIoaSwgbGVuLmxlbikpO1xuXHRcdFx0aSArPSBsZW4ubGVuO1xuXHRcdH1cblx0fVxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVXNlciBJRCBQYWNrZXQgKFRhZyAxMylcbiAqIEEgVXNlciBJRCBwYWNrZXQgY29uc2lzdHMgb2YgVVRGLTggdGV4dCB0aGF0IGlzIGludGVuZGVkIHRvIHJlcHJlc2VudFxuICogdGhlIG5hbWUgYW5kIGVtYWlsIGFkZHJlc3Mgb2YgdGhlIGtleSBob2xkZXIuICBCeSBjb252ZW50aW9uLCBpdFxuICogaW5jbHVkZXMgYW4gUkZDIDI4MjIgW1JGQzI4MjJdIG1haWwgbmFtZS1hZGRyLCBidXQgdGhlcmUgYXJlIG5vXG4gKiByZXN0cmljdGlvbnMgb24gaXRzIGNvbnRlbnQuICBUaGUgcGFja2V0IGxlbmd0aCBpbiB0aGUgaGVhZGVyXG4gKiBzcGVjaWZpZXMgdGhlIGxlbmd0aCBvZiB0aGUgVXNlciBJRC4gXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3VzZXJpZCgpIHtcblx0LyoqIEB0eXBlIHtTdHJpbmd9IEEgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIHVzZXIgaWQuIFVzdWFsbHkgaW4gdGhlIGZvcm1cblx0ICogSm9obiBEb2UgPGpvaG5AZXhhbXBsZS5jb20+IFxuXHQgKi9cblx0dGhpcy51c2VyaWQgPSAnJztcblx0XG5cdFxuXHQvKipcblx0ICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSB1c2VyIGlkIHBhY2tldCAodGFnIDEzKS5cblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IHBheWxvYWQgb2YgYSB0YWcgMTMgcGFja2V0XG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gcG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcblx0ICogQHBhcmFtIHtJbnRlZ2VyfSBsZW4gbGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2YgaW5wdXQgXG5cdCAqIGF0IHBvc2l0aW9uXG5cdCAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IG9iamVjdCByZXByZXNlbnRhdGlvblxuXHQgKi9cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0XHR0aGlzLnVzZXJpZCA9IHV0aWwuZGVjb2RlX3V0ZjgoYnl0ZXMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHVzZXIgaWQgcGFja2V0XG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB1c2VyX2lkIHRoZSB1c2VyIGlkIGFzIHN0cmluZyAoXCJKb2huIERvZSA8am9obi5kb2VAbWFpbC51c1wiKVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvblxuXHQgKi9cblx0dGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB1dGlsLmVuY29kZV91dGY4KHRoaXMudXNlcmlkKTtcblx0fVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdHlwZSBrZXkgaWQgKFJGQzQ4ODAgMy4zKVxuICogIEEgS2V5IElEIGlzIGFuIGVpZ2h0LW9jdGV0IHNjYWxhciB0aGF0IGlkZW50aWZpZXMgYSBrZXkuXG4gICBJbXBsZW1lbnRhdGlvbnMgU0hPVUxEIE5PVCBhc3N1bWUgdGhhdCBLZXkgSURzIGFyZSB1bmlxdWUuICBUaGVcbiAgIHNlY3Rpb24gXCJFbmhhbmNlZCBLZXkgRm9ybWF0c1wiIGJlbG93IGRlc2NyaWJlcyBob3cgS2V5IElEcyBhcmVcbiAgIGZvcm1lZC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBrZXlpZCgpIHtcblx0dmFyIGJ5dGVzID0gJyc7XG5cblx0Zm9yKHZhciBpID0gMDsgaSA8IDg7IGkrKylcblx0XHRieXRlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuXHQvKipcblx0ICogUGFyc2luZyBtZXRob2QgZm9yIGEga2V5IGlkXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBJbnB1dCB0byByZWFkIHRoZSBrZXkgaWQgZnJvbSBcblx0ICogQHBhcmFtIHtpbnRlZ2VyfSBwb3NpdGlvbiBQb3NpdGlvbiB3aGVyZSB0byBzdGFydCByZWFkaW5nIHRoZSBrZXkgXG5cdCAqIGlkIGZyb20gaW5wdXRcblx0ICogQHJldHVybiB7b3BlbnBncF90eXBlX2tleWlkfSBUaGlzIG9iamVjdFxuXHQgKi9cblx0dGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcblx0XHR0aGlzLmJ5dGVzID0gYnl0ZXMuc3Vic3RyKDAsIDgpO1xuXHR9XG5cblx0dGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmJ5dGVzO1xuXHR9XG59O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxuLy8gSGludDogV2UgaG9sZCBvdXIgTVBJcyBhcyBhbiBhcnJheSBvZiBvY3RldHMgaW4gYmlnIGVuZGlhbiBmb3JtYXQgcHJlY2VlZGluZyBhIHR3b1xuLy8gb2N0ZXQgc2NhbGFyOiBNUEk6IFthLGIsYyxkLGUsZl1cbi8vIC0gTVBJIHNpemU6IChhIDw8IDgpIHwgYiBcbi8vIC0gTVBJID0gYyB8IGQgPDwgOCB8IGUgPDwgKChNUEkubGVuZ3RoIC0yKSo4KSB8IGYgKChNUEkubGVuZ3RoIC0yKSo4KVxuXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4uL2NyeXB0by9wdWJsaWNfa2V5L2pzYm4uanMnKSxcblx0dXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2NJbXBsZW1lbnRhdGlvbiBvZiB0eXBlIE1QSSAoUkZDNDg4MCAzLjIpXG4gKiBNdWx0aXByZWNpc2lvbiBpbnRlZ2VycyAoYWxzbyBjYWxsZWQgTVBJcykgYXJlIHVuc2lnbmVkIGludGVnZXJzIHVzZWRcbiAqIHRvIGhvbGQgbGFyZ2UgaW50ZWdlcnMgc3VjaCBhcyB0aGUgb25lcyB1c2VkIGluIGNyeXB0b2dyYXBoaWNcbiAqIGNhbGN1bGF0aW9ucy5cbiAqIEFuIE1QSSBjb25zaXN0cyBvZiB0d28gcGllY2VzOiBhIHR3by1vY3RldCBzY2FsYXIgdGhhdCBpcyB0aGUgbGVuZ3RoXG4gKiBvZiB0aGUgTVBJIGluIGJpdHMgZm9sbG93ZWQgYnkgYSBzdHJpbmcgb2Ygb2N0ZXRzIHRoYXQgY29udGFpbiB0aGVcbiAqIGFjdHVhbCBpbnRlZ2VyLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1waSgpIHtcblx0LyoqIEFuIGltcGxlbWVudGF0aW9uIGRlcGVuZGVudCBpbnRlZ2VyICovXG5cdHRoaXMuZGF0YSA9IG51bGw7XG5cblx0LyoqXG5cdCAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgbXBpIChSRkMgNDg4MCAzLjIpLlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgUGF5bG9hZCBvZiBtcGkgZGF0YVxuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgXG5cdCAqIHN0cmluZ1xuXHQgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBMZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBcblx0ICogaW5wdXQgYXQgcG9zaXRpb25cblx0ICogQHJldHVybiB7b3BlbnBncF90eXBlX21waX0gT2JqZWN0IHJlcHJlc2VudGF0aW9uXG5cdCAqL1xuXHR0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdHZhciBiaXRzID0gKGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSA8PCA4KSB8IGJ5dGVzWzFdLmNoYXJDb2RlQXQoKTtcblx0XHRcblx0XHQvLyBBZGRpdGlvbmFsIHJ1bGVzOlxuXHRcdC8vXG5cdFx0Ly8gICAgVGhlIHNpemUgb2YgYW4gTVBJIGlzICgoTVBJLmxlbmd0aCArIDcpIC8gOCkgKyAyIG9jdGV0cy5cblx0XHQvL1xuXHRcdC8vICAgIFRoZSBsZW5ndGggZmllbGQgb2YgYW4gTVBJIGRlc2NyaWJlcyB0aGUgbGVuZ3RoIHN0YXJ0aW5nIGZyb20gaXRzXG5cdFx0Ly9cdCAgbW9zdCBzaWduaWZpY2FudCBub24temVybyBiaXQuICBUaHVzLCB0aGUgTVBJIFswMCAwMiAwMV0gaXMgbm90XG5cdFx0Ly8gICAgZm9ybWVkIGNvcnJlY3RseS4gIEl0IHNob3VsZCBiZSBbMDAgMDEgMDFdLlxuXG5cdFx0Ly8gVE9ETzogVmVyaWZpY2F0aW9uIG9mIHRoaXMgc2l6ZSBtZXRob2QhIFRoaXMgc2l6ZSBjYWxjdWxhdGlvbiBhc1xuXHRcdC8vIFx0XHQgc3BlY2lmaWVkIGFib3ZlIGlzIG5vdCBhcHBsaWNhYmxlIGluIEphdmFTY3JpcHRcblx0XHR2YXIgYnl0ZWxlbiA9IE1hdGguY2VpbChiaXRzIC8gOCk7XG5cdFx0XG5cdFx0dmFyIHJhdyA9IGJ5dGVzLnN1YnN0cigyLCBieXRlbGVuKTtcblx0XHR0aGlzLmZyb21CeXRlcyhyYXcpO1xuXG5cdFx0cmV0dXJuIDIgKyBieXRlbGVuO1xuXHR9XG5cblx0dGhpcy5mcm9tQnl0ZXMgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdHRoaXMuZGF0YSA9IG5ldyBCaWdJbnRlZ2VyKHV0aWwuaGV4c3RyZHVtcChieXRlcyksIDE2KTsgXG5cdH1cblxuXHR0aGlzLnRvQnl0ZXMgPSBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy53cml0ZSgpLnN1YnN0cigyKTtcblx0fVxuXG5cdHRoaXMuYnl0ZUxlbmd0aCA9IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnRvQnl0ZXMoKS5sZW5ndGg7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgdGhlIG1waSBvYmplY3QgdG8gYSBzdHJpbmcgYXMgc3BlY2lmaWVkIGluIFJGQzQ4ODAgMy4yXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gbXBpIEJ5dGUgcmVwcmVzZW50YXRpb25cblx0ICovXG5cdHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gdGhpcy5kYXRhLnRvTVBJKCk7XG5cdH1cblxuXHR0aGlzLnRvQmlnSW50ZWdlciA9IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmRhdGEuY2xvbmUoKTtcblx0fVxuXG5cdHRoaXMuZnJvbUJpZ0ludGVnZXIgPSBmdW5jdGlvbihibikge1xuXHRcdHRoaXMuZGF0YSA9IGJuLmNsb25lKCk7XG5cdH1cbn1cblxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcblx0dXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcblx0Y3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBTdHJpbmctdG8ta2V5IHNwZWNpZmllciAoUkZDNDg4MCAzLjcpXG4gKiBTdHJpbmctdG8ta2V5IChTMkspIHNwZWNpZmllcnMgYXJlIHVzZWQgdG8gY29udmVydCBwYXNzcGhyYXNlIHN0cmluZ3NcbiAgIGludG8gc3ltbWV0cmljLWtleSBlbmNyeXB0aW9uL2RlY3J5cHRpb24ga2V5cy4gIFRoZXkgYXJlIHVzZWQgaW4gdHdvXG4gICBwbGFjZXMsIGN1cnJlbnRseTogdG8gZW5jcnlwdCB0aGUgc2VjcmV0IHBhcnQgb2YgcHJpdmF0ZSBrZXlzIGluIHRoZVxuICAgcHJpdmF0ZSBrZXlyaW5nLCBhbmQgdG8gY29udmVydCBwYXNzcGhyYXNlcyB0byBlbmNyeXB0aW9uIGtleXMgZm9yXG4gICBzeW1tZXRyaWNhbGx5IGVuY3J5cHRlZCBtZXNzYWdlcy5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzMmsoKSB7XG5cdC8qKiBAdHlwZSB7b3BlbnBncC5oYXNofSAqL1xuXHR0aGlzLmFsZ29yaXRobSA9ICdzaGEyNTYnO1xuXHQvKiogQHR5cGUge29wZW5wZ3BfdHlwZV9zMmsudHlwZX0gKi9cblx0dGhpcy50eXBlID0gJ2l0ZXJhdGVkJztcblx0dGhpcy5jID0gOTY7XG5cdC8qKiBAdHlwZSB7b3BlbnBncF9ieXRlYXJyYXl9IFxuXHQgKiBFaWdodCBieXRlcyBvZiBzYWx0LiAqL1xuXHR0aGlzLnNhbHQgPSBjcnlwdG8ucmFuZG9tLmdldFJhbmRvbUJ5dGVzKDgpO1xuXG5cblx0Ly8gRXhwb25lbiBiaWFzLCBkZWZpbmVkIGluIFJGQzQ4ODBcblx0dmFyIGV4cGJpYXMgPSA2O1xuXG5cdHRoaXMuZ2V0X2NvdW50ID0gZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuICgxNiArICh0aGlzLmMgJiAxNSkpIDw8ICgodGhpcy5jID4+IDQpICsgZXhwYmlhcyk7XG5cdH1cblxuXHQvKipcblx0ICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBzdHJpbmctdG8ta2V5IHNwZWNpZmllciAoUkZDIDQ4ODAgMy43KS5cblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2Ygc3RyaW5nLXRvLWtleSBzcGVjaWZpZXJcblx0ICogQHJldHVybiB7SW50ZWdlcn0gQWN0dWFsIGxlbmd0aCBvZiB0aGUgb2JqZWN0XG5cdCAqL1xuXHR0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdHZhciBpID0gMDtcblx0XHR0aGlzLnR5cGUgPSBlbnVtcy5yZWFkKGVudW1zLnMyaywgYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCkpO1xuXHRcdHRoaXMuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5oYXNoLCBieXRlc1tpKytdLmNoYXJDb2RlQXQoKSk7XG5cblx0XHRzd2l0Y2ggKHRoaXMudHlwZSkge1xuXHRcdGNhc2UgJ3NpbXBsZSc6XG5cdFx0XHRicmVhaztcblxuXHRcdGNhc2UgJ3NhbHRlZCc6XG5cdFx0XHR0aGlzLnNhbHQgPSBieXRlcy5zdWJzdHIoaSwgOCk7XG5cdFx0XHRpICs9IDg7XG5cdFx0XHRicmVhaztcblxuXHRcdGNhc2UgJ2l0ZXJhdGVkJzpcblx0XHRcdHRoaXMuc2FsdCA9IGJ5dGVzLnN1YnN0cihpLCA4KTtcblx0XHRcdGkgKz0gODtcblxuXHRcdFx0Ly8gT2N0ZXQgMTA6IGNvdW50LCBhIG9uZS1vY3RldCwgY29kZWQgdmFsdWVcblx0XHRcdHRoaXMuYyA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuXHRcdFx0YnJlYWs7XG5cblx0XHRjYXNlICdnbnUnOlxuXHRcdFx0aWYoYnl0ZXMuc3Vic3RyKGksIDMpID09IFwiR05VXCIpIHtcblx0XHRcdFx0aSArPSAzOyAvLyBHTlVcblx0XHRcdFx0dmFyIGdudUV4dFR5cGUgPSAxMDAwICsgYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG5cdFx0XHRcdGlmKGdudUV4dFR5cGUgPT0gMTAwMSkge1xuXHRcdFx0XHRcdHRoaXMudHlwZSA9IGdudUV4dFR5cGU7XG5cdFx0XHRcdFx0Ly8gR251UEcgZXh0ZW5zaW9uIG1vZGUgMTAwMSAtLSBkb24ndCB3cml0ZSBzZWNyZXQga2V5IGF0IGFsbFxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvcihcIlVua25vd24gczJrIGdudSBwcm90ZWN0aW9uIG1vZGUuXCIpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHMyayB0eXBlLlwiKTtcblx0XHRcdH1cblx0XHRcdGJyZWFrO1xuXG5cdFx0ZGVmYXVsdDpcblx0XHRcdHRocm93IG5ldyBFcnJvcihcIlVua25vd24gczJrIHR5cGUuXCIpO1xuXHRcdFx0YnJlYWs7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGk7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogd3JpdGVzIGFuIHMyayBoYXNoIGJhc2VkIG9uIHRoZSBpbnB1dHMuXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gUHJvZHVjZWQga2V5IG9mIGhhc2hBbGdvcml0aG0gaGFzaCBsZW5ndGhcblx0ICovXG5cdHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcblx0XHR2YXIgYnl0ZXMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLnMyaywgdGhpcy50eXBlKSk7XG5cdFx0Ynl0ZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5oYXNoLCB0aGlzLmFsZ29yaXRobSkpO1xuXG5cdFx0c3dpdGNoKHRoaXMudHlwZSkge1xuXHRcdFx0Y2FzZSAnc2ltcGxlJzpcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdzYWx0ZWQnOlxuXHRcdFx0XHRieXRlcyArPSB0aGlzLnNhbHQ7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAnaXRlcmF0ZWQnOlxuXHRcdFx0XHRieXRlcyArPSB0aGlzLnNhbHQ7XG5cdFx0XHRcdGJ5dGVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy5jKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fTtcblxuXHRcdHJldHVybiBieXRlcztcblx0fVxuXG5cdC8qKlxuXHQgKiBQcm9kdWNlcyBhIGtleSB1c2luZyB0aGUgc3BlY2lmaWVkIHBhc3NwaHJhc2UgYW5kIHRoZSBkZWZpbmVkIFxuXHQgKiBoYXNoQWxnb3JpdGhtIFxuXHQgKiBAcGFyYW0ge1N0cmluZ30gcGFzc3BocmFzZSBQYXNzcGhyYXNlIGNvbnRhaW5pbmcgdXNlciBpbnB1dFxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IFByb2R1Y2VkIGtleSB3aXRoIGEgbGVuZ3RoIGNvcnJlc3BvbmRpbmcgdG8gXG5cdCAqIGhhc2hBbGdvcml0aG0gaGFzaCBsZW5ndGhcblx0ICovXG5cdHRoaXMucHJvZHVjZV9rZXkgPSBmdW5jdGlvbihwYXNzcGhyYXNlLCBudW1CeXRlcykge1xuXHRcdHBhc3NwaHJhc2UgPSB1dGlsLmVuY29kZV91dGY4KHBhc3NwaHJhc2UpO1xuXG5cdFx0ZnVuY3Rpb24gcm91bmQocHJlZml4LCBzMmspIHtcblx0XHRcdHZhciBhbGdvcml0aG0gPSBlbnVtcy53cml0ZShlbnVtcy5oYXNoLCBzMmsuYWxnb3JpdGhtKTtcblxuXHRcdFx0c3dpdGNoKHMyay50eXBlKSB7XG5cdFx0XHRcdGNhc2UgJ3NpbXBsZSc6XG5cdFx0XHRcdFx0cmV0dXJuIGNyeXB0by5oYXNoLmRpZ2VzdChhbGdvcml0aG0sIHByZWZpeCArIHBhc3NwaHJhc2UpO1xuXG5cdFx0XHRcdGNhc2UgJ3NhbHRlZCc6XG5cdFx0XHRcdFx0cmV0dXJuIGNyeXB0by5oYXNoLmRpZ2VzdChhbGdvcml0aG0sIFxuXHRcdFx0XHRcdFx0cHJlZml4ICsgczJrLnNhbHQgKyBwYXNzcGhyYXNlKTtcblxuXHRcdFx0XHRjYXNlICdpdGVyYXRlZCc6XG5cdFx0XHRcdFx0dmFyIGlzcCA9IFtdLFxuXHRcdFx0XHRcdFx0Y291bnQgPSBzMmsuZ2V0X2NvdW50KCk7XG5cdFx0XHRcdFx0XHRkYXRhID0gczJrLnNhbHQgKyBwYXNzcGhyYXNlO1xuXG5cdFx0XHRcdFx0d2hpbGUgKGlzcC5sZW5ndGggKiBkYXRhLmxlbmd0aCA8IGNvdW50KVxuXHRcdFx0XHRcdFx0aXNwLnB1c2goZGF0YSk7XG5cblx0XHRcdFx0XHRpc3AgPSBpc3Auam9pbignJyk7XHRcdFx0XG5cblx0XHRcdFx0XHRpZiAoaXNwLmxlbmd0aCA+IGNvdW50KVxuXHRcdFx0XHRcdFx0aXNwID0gaXNwLnN1YnN0cigwLCBjb3VudCk7XG5cblx0XHRcdFx0XHRyZXR1cm4gY3J5cHRvLmhhc2guZGlnZXN0KGFsZ29yaXRobSwgcHJlZml4ICsgaXNwKTtcblx0XHRcdH07XG5cdFx0fVxuXHRcdFxuXHRcdHZhciByZXN1bHQgPSAnJyxcblx0XHRcdHByZWZpeCA9ICcnO1xuXG5cdFx0d2hpbGUocmVzdWx0Lmxlbmd0aCA8PSBudW1CeXRlcykge1xuXHRcdFx0cmVzdWx0ICs9IHJvdW5kKHByZWZpeCwgdGhpcyk7XG5cdFx0XHRwcmVmaXggKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gcmVzdWx0LnN1YnN0cigwLCBudW1CeXRlcyk7XG5cdH1cbn1cblxuXG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgVXRpbCA9IGZ1bmN0aW9uKCkge1xuXG5cblxuXHR0aGlzLnJlYWROdW1iZXIgPSBmdW5jdGlvbiAoYnl0ZXMpIHtcblx0XHR2YXIgbiA9IDA7XG5cblx0XHRmb3IodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIHtcblx0XHRcdG4gPDw9IDg7XG5cdFx0XHRuICs9IGJ5dGVzW2ldLmNoYXJDb2RlQXQoKVxuXHRcdH1cblxuXHRcdHJldHVybiBuO1xuXHR9XG5cblx0dGhpcy53cml0ZU51bWJlciA9IGZ1bmN0aW9uKG4sIGJ5dGVzKSB7XG5cdFx0dmFyIGIgPSAnJztcblx0XHRmb3IodmFyIGkgPSAwOyBpIDwgYnl0ZXM7IGkrKykge1xuXHRcdFx0YiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChuID4+ICg4ICogKGJ5dGVzLSBpIC0gMSkpKSAmIDB4RkYpO1xuXHRcdH1cblxuXHRcdHJldHVybiBiO1xuXHR9XG5cblxuXG5cdHRoaXMucmVhZERhdGUgPSBmdW5jdGlvbihieXRlcykge1xuXHRcdHZhciBuID0gdGhpcy5yZWFkTnVtYmVyKGJ5dGVzKTtcblx0XHR2YXIgZCA9IG5ldyBEYXRlKCk7XG5cdFx0ZC5zZXRUaW1lKG4gKiAxMDAwKTtcblx0XHRyZXR1cm4gZDtcblx0fVxuXG5cdHRoaXMud3JpdGVEYXRlID0gZnVuY3Rpb24odGltZSkge1xuXHRcdHZhciBudW1lcmljID0gTWF0aC5yb3VuZCh0aW1lLmdldFRpbWUoKSAvIDEwMDApO1xuXG5cdFx0cmV0dXJuIHRoaXMud3JpdGVOdW1iZXIobnVtZXJpYywgNCk7XG5cdH1cblxuICAgIHRoaXMuZW1haWxSZWdFeCA9IC9bYS16MC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKD86XFwuW2EtejAtOSEjJCUmJyorLz0/Xl9ge3x9fi1dKykqQCg/OlthLXowLTldKD86W2EtejAtOS1dKlthLXowLTldKT9cXC4pK1thLXowLTldKD86W2EtejAtOS1dKlthLXowLTldKT8vO1xuXHRcblx0dGhpcy5kZWJ1ZyA9IGZhbHNlO1xuXG5cdHRoaXMuaGV4ZHVtcCA9IGZ1bmN0aW9uKHN0cikge1xuXHQgICAgdmFyIHI9W107XG5cdCAgICB2YXIgZT1zdHIubGVuZ3RoO1xuXHQgICAgdmFyIGM9MDtcblx0ICAgIHZhciBoO1xuXHQgICAgdmFyIGkgPSAwO1xuXHQgICAgd2hpbGUoYzxlKXtcblx0ICAgICAgICBoPXN0ci5jaGFyQ29kZUF0KGMrKykudG9TdHJpbmcoMTYpO1xuXHQgICAgICAgIHdoaWxlKGgubGVuZ3RoPDIpIGg9XCIwXCIraDtcblx0ICAgICAgICByLnB1c2goXCIgXCIraCk7XG5cdCAgICAgICAgaSsrO1xuXHQgICAgICAgIGlmIChpICUgMzIgPT0gMClcblx0ICAgICAgICBcdHIucHVzaChcIlxcbiAgICAgICAgICAgXCIpO1xuXHQgICAgfVxuXHQgICAgcmV0dXJuIHIuam9pbignJyk7XG5cdH07XG5cdFxuXHQvKipcblx0ICogQ3JlYXRlIGhleHN0cmluZyBmcm9tIGEgYmluYXJ5XG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIGNvbnZlcnRcblx0ICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgY29udGFpbmluZyB0aGUgaGV4YWRlY2ltYWwgdmFsdWVzXG5cdCAqL1xuXHR0aGlzLmhleHN0cmR1bXAgPSBmdW5jdGlvbihzdHIpIHtcblx0XHRpZiAoc3RyID09IG51bGwpXG5cdFx0XHRyZXR1cm4gXCJcIjtcblx0ICAgIHZhciByPVtdO1xuXHQgICAgdmFyIGU9c3RyLmxlbmd0aDtcblx0ICAgIHZhciBjPTA7XG5cdCAgICB2YXIgaDtcblx0ICAgIHdoaWxlKGM8ZSl7XG5cdCAgICAgICAgaD1zdHJbYysrXS5jaGFyQ29kZUF0KCkudG9TdHJpbmcoMTYpO1xuXHQgICAgICAgIHdoaWxlKGgubGVuZ3RoPDIpIGg9XCIwXCIraDtcblx0ICAgICAgICByLnB1c2goXCJcIitoKTtcblx0ICAgIH1cblx0ICAgIHJldHVybiByLmpvaW4oJycpO1xuXHR9O1xuXHRcblx0LyoqXG5cdCAqIENyZWF0ZSBiaW5hcnkgc3RyaW5nIGZyb20gYSBoZXggZW5jb2RlZCBzdHJpbmdcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBIZXggc3RyaW5nIHRvIGNvbnZlcnRcblx0ICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgY29udGFpbmluZyB0aGUgYmluYXJ5IHZhbHVlc1xuXHQgKi9cblx0dGhpcy5oZXgyYmluID0gZnVuY3Rpb24oaGV4KSB7XG5cdCAgICB2YXIgc3RyID0gJyc7XG5cdCAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhleC5sZW5ndGg7IGkgKz0gMilcblx0ICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShwYXJzZUludChoZXguc3Vic3RyKGksIDIpLCAxNikpO1xuXHQgICAgcmV0dXJuIHN0cjtcblx0fTtcblx0XG5cdC8qKlxuXHQgKiBDcmVhdGluZyBhIGhleCBzdHJpbmcgZnJvbSBhbiBiaW5hcnkgYXJyYXkgb2YgaW50ZWdlcnMgKDAuLjI1NSlcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBBcnJheSBvZiBieXRlcyB0byBjb252ZXJ0XG5cdCAqIEByZXR1cm4ge1N0cmluZ30gSGV4YWRlY2ltYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIGFycmF5XG5cdCAqL1xuXHR0aGlzLmhleGlkdW1wID0gZnVuY3Rpb24oc3RyKSB7XG5cdCAgICB2YXIgcj1bXTtcblx0ICAgIHZhciBlPXN0ci5sZW5ndGg7XG5cdCAgICB2YXIgYz0wO1xuXHQgICAgdmFyIGg7XG5cdCAgICB3aGlsZShjPGUpe1xuXHQgICAgICAgIGg9c3RyW2MrK10udG9TdHJpbmcoMTYpO1xuXHQgICAgICAgIHdoaWxlKGgubGVuZ3RoPDIpIGg9XCIwXCIraDtcblx0ICAgICAgICByLnB1c2goXCJcIitoKTtcblx0ICAgIH1cblx0ICAgIHJldHVybiByLmpvaW4oJycpO1xuXHR9O1xuXG5cblx0LyoqXG5cdCAqIENvbnZlcnQgYSBuYXRpdmUgamF2YXNjcmlwdCBzdHJpbmcgdG8gYSBzdHJpbmcgb2YgdXRmOCBieXRlc1xuXHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFRoZSBzdHJpbmcgdG8gY29udmVydFxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IEEgdmFsaWQgc3F1ZW5jZSBvZiB1dGY4IGJ5dGVzXG5cdCAqL1xuXHR0aGlzLmVuY29kZV91dGY4ID0gZnVuY3Rpb24oc3RyKSB7XG5cdFx0cmV0dXJuIHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudChzdHIpKTtcblx0fTtcblxuXHQvKipcblx0ICogQ29udmVydCBhIHN0cmluZyBvZiB1dGY4IGJ5dGVzIHRvIGEgbmF0aXZlIGphdmFzY3JpcHQgc3RyaW5nXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB1dGY4IEEgdmFsaWQgc3F1ZW5jZSBvZiB1dGY4IGJ5dGVzXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gQSBuYXRpdmUgamF2YXNjcmlwdCBzdHJpbmdcblx0ICovXG5cdHRoaXMuZGVjb2RlX3V0ZjggPSBmdW5jdGlvbih1dGY4KSB7XG5cdFx0cmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUodXRmOCkpO1xuXHR9O1xuXG5cdHZhciBzdHIyYmluID0gZnVuY3Rpb24oc3RyLCByZXN1bHQpIHtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuXHRcdFx0cmVzdWx0W2ldID0gc3RyLmNoYXJDb2RlQXQoaSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdDtcblx0fTtcblx0XG5cdHZhciBiaW4yc3RyID0gZnVuY3Rpb24oYmluKSB7XG5cdFx0dmFyIHJlc3VsdCA9IFtdO1xuXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBiaW4ubGVuZ3RoOyBpKyspIHtcblx0XHRcdHJlc3VsdC5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYmluW2ldKSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJlc3VsdC5qb2luKCcnKTtcblx0fTtcblxuXHQvKipcblx0ICogQ29udmVydCBhIHN0cmluZyB0byBhbiBhcnJheSBvZiBpbnRlZ2VycygwLjI1NSlcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gY29udmVydFxuXHQgKiBAcmV0dXJuIHtJbnRlZ2VyW119IEFuIGFycmF5IG9mIChiaW5hcnkpIGludGVnZXJzXG5cdCAqL1xuXHR0aGlzLnN0cjJiaW4gPSBmdW5jdGlvbihzdHIpIHsgXG5cdFx0cmV0dXJuIHN0cjJiaW4oc3RyLCBuZXcgQXJyYXkoc3RyLmxlbmd0aCkpO1xuXHR9O1xuXHRcblx0XG5cdC8qKlxuXHQgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGludGVnZXJzKDAuMjU1KSB0byBhIHN0cmluZyBcblx0ICogQHBhcmFtIHtJbnRlZ2VyW119IGJpbiBBbiBhcnJheSBvZiAoYmluYXJ5KSBpbnRlZ2VycyB0byBjb252ZXJ0XG5cdCAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgYXJyYXlcblx0ICovXG5cdHRoaXMuYmluMnN0ciA9IGJpbjJzdHI7XG5cdFxuXHQvKipcblx0ICogQ29udmVydCBhIHN0cmluZyB0byBhIFVpbnQ4QXJyYXlcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gY29udmVydFxuXHQgKiBAcmV0dXJuIHtVaW50OEFycmF5fSBUaGUgYXJyYXkgb2YgKGJpbmFyeSkgaW50ZWdlcnNcblx0ICovXG5cdHRoaXMuc3RyMlVpbnQ4QXJyYXkgPSBmdW5jdGlvbihzdHIpIHsgXG5cdFx0cmV0dXJuIHN0cjJiaW4oc3RyLCBuZXcgVWludDhBcnJheShuZXcgQXJyYXlCdWZmZXIoc3RyLmxlbmd0aCkpKTsgXG5cdH07XG5cdFxuXHQvKipcblx0ICogQ29udmVydCBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmcuIFRoaXMgY3VycmVudGx5IGZ1bmN0aW9ucyBcblx0ICogdGhlIHNhbWUgYXMgYmluMnN0ci4gXG5cdCAqIEBwYXJhbSB7VWludDhBcnJheX0gYmluIEFuIGFycmF5IG9mIChiaW5hcnkpIGludGVnZXJzIHRvIGNvbnZlcnRcblx0ICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGFycmF5XG5cdCAqL1xuXHR0aGlzLlVpbnQ4QXJyYXkyc3RyID0gYmluMnN0cjtcblx0XG5cdC8qKlxuXHQgKiBDYWxjdWxhdGVzIGEgMTZiaXQgc3VtIG9mIGEgc3RyaW5nIGJ5IGFkZGluZyBlYWNoIGNoYXJhY3RlciBcblx0ICogY29kZXMgbW9kdWx1cyA2NTUzNVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdGV4dCBTdHJpbmcgdG8gY3JlYXRlIGEgc3VtIG9mXG5cdCAqIEByZXR1cm4ge0ludGVnZXJ9IEFuIGludGVnZXIgY29udGFpbmluZyB0aGUgc3VtIG9mIGFsbCBjaGFyYWN0ZXIgXG5cdCAqIGNvZGVzICUgNjU1MzVcblx0ICovXG5cdHRoaXMuY2FsY19jaGVja3N1bSA9IGZ1bmN0aW9uKHRleHQpIHtcblx0XHR2YXIgY2hlY2tzdW0gPSB7ICBzOiAwLCBhZGQ6IGZ1bmN0aW9uIChzYWRkKSB7IHRoaXMucyA9ICh0aGlzLnMgKyBzYWRkKSAlIDY1NTM2OyB9fTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcblx0XHRcdGNoZWNrc3VtLmFkZCh0ZXh0LmNoYXJDb2RlQXQoaSkpO1xuXHRcdH1cblx0XHRyZXR1cm4gY2hlY2tzdW0ucztcblx0fTtcblx0XG5cdC8qKlxuXHQgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYSBkZWJ1ZyBtZXNzYWdlLiBEZWJ1ZyBcblx0ICogbWVzc2FnZXMgYXJlIG9ubHkgcHJpbnRlZCBpZlxuXHQgKiBvcGVucGdwLmNvbmZpZy5kZWJ1ZyBpcyBzZXQgdG8gdHJ1ZS4gVGhlIGNhbGxpbmdcblx0ICogSmF2YXNjcmlwdCBjb250ZXh0IE1VU1QgZGVmaW5lXG5cdCAqIGEgXCJzaG93TWVzc2FnZXModGV4dClcIiBmdW5jdGlvbi4gTGluZSBmZWVkcyAoJ1xcbicpXG5cdCAqIGFyZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBIVE1MIGxpbmUgZmVlZHMgJzxici8+J1xuXHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyBvZiB0aGUgZGVidWcgbWVzc2FnZVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IEFuIEhUTUwgdHQgZW50aXR5IGNvbnRhaW5pbmcgYSBwYXJhZ3JhcGggd2l0aCBhIFxuXHQgKiBzdHlsZSBhdHRyaWJ1dGUgd2hlcmUgdGhlIGRlYnVnIG1lc3NhZ2UgaXMgSFRNTGVuY29kZWQgaW4uIFxuXHQgKi9cblx0dGhpcy5wcmludF9kZWJ1ZyA9IGZ1bmN0aW9uKHN0cikge1xuXHRcdGlmICh0aGlzLmRlYnVnKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhzdHIpO1xuXHRcdH1cblx0fTtcblx0XG5cdC8qKlxuXHQgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYSBkZWJ1ZyBtZXNzYWdlLiBEZWJ1ZyBcblx0ICogbWVzc2FnZXMgYXJlIG9ubHkgcHJpbnRlZCBpZlxuXHQgKiBvcGVucGdwLmNvbmZpZy5kZWJ1ZyBpcyBzZXQgdG8gdHJ1ZS4gVGhlIGNhbGxpbmdcblx0ICogSmF2YXNjcmlwdCBjb250ZXh0IE1VU1QgZGVmaW5lXG5cdCAqIGEgXCJzaG93TWVzc2FnZXModGV4dClcIiBmdW5jdGlvbi4gTGluZSBmZWVkcyAoJ1xcbicpXG5cdCAqIGFyZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBIVE1MIGxpbmUgZmVlZHMgJzxici8+J1xuXHQgKiBEaWZmZXJlbnQgdGhhbiBwcmludF9kZWJ1ZyBiZWNhdXNlIHdpbGwgY2FsbCBoZXhzdHJkdW1wIGlmZiBuZWNlc3NhcnkuXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIG9mIHRoZSBkZWJ1ZyBtZXNzYWdlXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gQW4gSFRNTCB0dCBlbnRpdHkgY29udGFpbmluZyBhIHBhcmFncmFwaCB3aXRoIGEgXG5cdCAqIHN0eWxlIGF0dHJpYnV0ZSB3aGVyZSB0aGUgZGVidWcgbWVzc2FnZSBpcyBIVE1MZW5jb2RlZCBpbi4gXG5cdCAqL1xuXHR0aGlzLnByaW50X2RlYnVnX2hleHN0cl9kdW1wID0gZnVuY3Rpb24oc3RyLHN0clRvSGV4KSB7XG5cdFx0aWYgKHRoaXMuZGVidWcpIHtcblx0XHRcdHN0ciA9IHN0ciArIHRoaXMuaGV4c3RyZHVtcChzdHJUb0hleCk7XG5cdFx0XHRjb25zb2xlLmxvZyhzdHIpO1xuXHRcdH1cblx0fTtcblx0XG5cdC8qKlxuXHQgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYW4gZXJyb3IgbWVzc2FnZS4gXG5cdCAqIFRoZSBjYWxsaW5nIEphdmFzY3JpcHQgY29udGV4dCBNVVNUIGRlZmluZVxuXHQgKiBhIFwic2hvd01lc3NhZ2VzKHRleHQpXCIgZnVuY3Rpb24uIExpbmUgZmVlZHMgKCdcXG4nKVxuXHQgKiBhcmUgYXV0b21hdGljYWxseSBjb252ZXJ0ZWQgdG8gSFRNTCBsaW5lIGZlZWRzICc8YnIvPidcblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgb2YgdGhlIGVycm9yIG1lc3NhZ2Vcblx0ICogQHJldHVybiB7U3RyaW5nfSBBIEhUTUwgcGFyYWdyYXBoIGVudGl0eSB3aXRoIGEgc3R5bGUgYXR0cmlidXRlIFxuXHQgKiBjb250YWluaW5nIHRoZSBIVE1MIGVuY29kZWQgZXJyb3IgbWVzc2FnZVxuXHQgKi9cblx0dGhpcy5wcmludF9lcnJvciA9IGZ1bmN0aW9uKHN0cikge1xuXHRcdGlmKHRoaXMuZGVidWcpXG5cdFx0XHR0aHJvdyBzdHI7XG5cdFx0Y29uc29sZS5sb2coc3RyKTtcblx0fTtcblx0XG5cdC8qKlxuXHQgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYW4gaW5mbyBtZXNzYWdlLiBcblx0ICogVGhlIGNhbGxpbmcgSmF2YXNjcmlwdCBjb250ZXh0IE1VU1QgZGVmaW5lXG5cdCAqIGEgXCJzaG93TWVzc2FnZXModGV4dClcIiBmdW5jdGlvbi4gTGluZSBmZWVkcyAoJ1xcbicpXG5cdCAqIGFyZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBIVE1MIGxpbmUgZmVlZHMgJzxici8+Jy5cblx0ICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgb2YgdGhlIGluZm8gbWVzc2FnZVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IEEgSFRNTCBwYXJhZ3JhcGggZW50aXR5IHdpdGggYSBzdHlsZSBhdHRyaWJ1dGUgXG5cdCAqIGNvbnRhaW5pbmcgdGhlIEhUTUwgZW5jb2RlZCBpbmZvIG1lc3NhZ2Vcblx0ICovXG5cdHRoaXMucHJpbnRfaW5mbyA9IGZ1bmN0aW9uKHN0cikge1xuXHRcdGlmKHRoaXMuZGVidWcpXG5cdFx0XHRjb25zb2xlLmxvZyhzdHIpO1xuXHR9O1xuXHRcblx0dGhpcy5wcmludF93YXJuaW5nID0gZnVuY3Rpb24oc3RyKSB7XG5cdFx0Y29uc29sZS5sb2coc3RyKTtcblx0fTtcblx0XG5cdHRoaXMuZ2V0TGVmdE5CaXRzID0gZnVuY3Rpb24gKHN0cmluZywgYml0Y291bnQpIHtcblx0XHR2YXIgcmVzdCA9IGJpdGNvdW50ICUgODtcblx0XHRpZiAocmVzdCA9PSAwKVxuXHRcdFx0cmV0dXJuIHN0cmluZy5zdWJzdHJpbmcoMCwgYml0Y291bnQgLyA4KTtcblx0XHR2YXIgYnl0ZXMgPSAoYml0Y291bnQgLSByZXN0KSAvIDggKzE7XG5cdFx0dmFyIHJlc3VsdCA9IHN0cmluZy5zdWJzdHJpbmcoMCwgYnl0ZXMpO1xuXHRcdHJldHVybiB0aGlzLnNoaWZ0UmlnaHQocmVzdWx0LCA4LXJlc3QpOyAvLyArU3RyaW5nLmZyb21DaGFyQ29kZShzdHJpbmcuY2hhckNvZGVBdChieXRlcyAtMSkgPDwgKDgtcmVzdCkgJiAweEZGKTtcblx0fTtcblxuXHQvKipcblx0ICogU2hpZnRpbmcgYSBzdHJpbmcgdG8gbiBiaXRzIHJpZ2h0XG5cdCAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSBUaGUgc3RyaW5nIHRvIHNoaWZ0XG5cdCAqIEBwYXJhbSB7SW50ZWdlcn0gYml0Y291bnQgQW1vdW50IG9mIGJpdHMgdG8gc2hpZnQgKE1VU1QgYmUgc21hbGxlciBcblx0ICogdGhhbiA5KVxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IFJlc3VsdGluZyBzdHJpbmcuIFxuXHQgKi9cblx0dGhpcy5zaGlmdFJpZ2h0ID0gZnVuY3Rpb24odmFsdWUsIGJpdGNvdW50KSB7XG5cdFx0dmFyIHRlbXAgPSB1dGlsLnN0cjJiaW4odmFsdWUpO1xuICAgICAgICBpZiAoYml0Y291bnQgJSA4ICE9IDApIHtcbiAgICAgICAgXHRmb3IgKHZhciBpID0gdGVtcC5sZW5ndGgtMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgXHRcdHRlbXBbaV0gPj49IGJpdGNvdW50ICUgODtcbiAgICAgICAgXHRcdGlmIChpID4gMClcbiAgICAgICAgXHRcdFx0dGVtcFtpXSB8PSAodGVtcFtpIC0gMV0gPDwgKDggLSAoYml0Y291bnQgJSA4KSkpICYgMHhGRjtcbiAgICAgICAgXHR9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgIFx0cmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1dGlsLmJpbjJzdHIodGVtcCk7XG5cdH07XG5cdFxuXHQvKipcblx0ICogUmV0dXJuIHRoZSBhbGdvcml0aG0gdHlwZSBhcyBzdHJpbmdcblx0ICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBtZXNzYWdlIHR5cGVcblx0ICovXG5cdHRoaXMuZ2V0X2hhc2hBbGdvcml0aG1TdHJpbmcgPSBmdW5jdGlvbihhbGdvKSB7XG5cdFx0c3dpdGNoKGFsZ28pIHtcblx0XHRjYXNlIDE6XG5cdFx0XHRyZXR1cm4gXCJNRDVcIjtcblx0XHRjYXNlIDI6XG5cdFx0XHRyZXR1cm4gXCJTSEExXCI7XG5cdFx0Y2FzZSAzOlxuXHRcdFx0cmV0dXJuIFwiUklQRU1EMTYwXCI7XG5cdFx0Y2FzZSA4OlxuXHRcdFx0cmV0dXJuIFwiU0hBMjU2XCI7XG5cdFx0Y2FzZSA5OlxuXHRcdFx0cmV0dXJuIFwiU0hBMzg0XCI7XG5cdFx0Y2FzZSAxMDpcblx0XHRcdHJldHVybiBcIlNIQTUxMlwiO1xuXHRcdGNhc2UgMTE6XG5cdFx0XHRyZXR1cm4gXCJTSEEyMjRcIjtcblx0XHR9XG5cdFx0cmV0dXJuIFwidW5rbm93blwiO1xuXHR9O1xufTtcblxuLyoqXG4gKiBhbiBpbnN0YW5jZSB0aGF0IHNob3VsZCBiZSB1c2VkLiBcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBuZXcgVXRpbCgpO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJBRVMgUmlqbmRhZWwgY2lwaGVyIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBlY2JfdGJsLnR4dFwiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKTtcbiAgdmFyIHV0aWwgPSBvcGVucGdwLnV0aWw7XG5cbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSgpO1xuXG4gIGZ1bmN0aW9uIHRlc3RfYWVzKGlucHV0LCBrZXksIG91dHB1dCkge1xuICAgIHZhciBhZXMgPSBuZXcgb3BlbnBncC5jaXBoZXIuYWVzMTI4KHV0aWwuYmluMnN0cihrZXkpKTtcblxuICAgIHZhciByZXN1bHQgPSB1dGlsLmJpbjJzdHIoYWVzLmVuY3J5cHQoaW5wdXQpKTtcblxuICAgIHJldHVybiB1dGlsLmhleHN0cmR1bXAocmVzdWx0KSA9PSB1dGlsLmhleHN0cmR1bXAodXRpbC5iaW4yc3RyKG91dHB1dCkpO1xuICB9O1xuXG4gIHZhciB0ZXN0dmVjdG9yczEyOCA9IFtbWzB4MDAsMHgwMSwweDAyLDB4MDMsMHgwNSwweDA2LDB4MDcsMHgwOCwweDBBLDB4MEIsMHgwQywweDBELDB4MEYsMHgxMCwweDExLDB4MTJdLFsweDUwLDB4NjgsMHgxMiwweEE0LDB4NUYsMHgwOCwweEM4LDB4ODksMHhCOSwweDdGLDB4NTksMHg4MCwweDAzLDB4OEIsMHg4MywweDU5XSxbMHhEOCwweEY1LDB4MzIsMHg1MywweDgyLDB4ODksMHhFRiwweDdELDB4MDYsMHhCNSwweDA2LDB4QTQsMHhGRCwweDVCLDB4RTksMHhDOV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDE0LDB4MTUsMHgxNiwweDE3LDB4MTksMHgxQSwweDFCLDB4MUMsMHgxRSwweDFGLDB4MjAsMHgyMSwweDIzLDB4MjQsMHgyNSwweDI2XSxbMHg1QywweDZELDB4NzEsMHhDQSwweDMwLDB4REUsMHg4QiwweDhCLDB4MDAsMHg1NCwweDk5LDB4ODQsMHhEMiwweEVDLDB4N0QsMHg0Ql0sWzB4NTksMHhBQiwweDMwLDB4RjQsMHhENCwweEVFLDB4NkUsMHg0RiwweEY5LDB4OTAsMHg3RSwweEY2LDB4NUIsMHgxRiwweEI2LDB4OENdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgyOCwweDI5LDB4MkEsMHgyQiwweDJELDB4MkUsMHgyRiwweDMwLDB4MzIsMHgzMywweDM0LDB4MzUsMHgzNywweDM4LDB4MzksMHgzQV0sWzB4NTMsMHhGMywweEY0LDB4QzYsMHg0RiwweDg2LDB4MTYsMHhFNCwweEU3LDB4QzUsMHg2MSwweDk5LDB4RjQsMHg4RiwweDIxLDB4RjZdLFsweEJGLDB4MUUsMHhEMiwweEZDLDB4QjIsMHhBRiwweDNGLDB4RDQsMHgxNCwweDQzLDB4QjUsMHg2RCwweDg1LDB4MDIsMHg1QywweEIxXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4M0MsMHgzRCwweDNFLDB4M0YsMHg0MSwweDQyLDB4NDMsMHg0NCwweDQ2LDB4NDcsMHg0OCwweDQ5LDB4NEIsMHg0QywweDRELDB4NEVdLFsweEExLDB4RUIsMHg2NSwweEEzLDB4NDgsMHg3MSwweDY1LDB4RkIsMHgwRiwweDFDLDB4MjcsMHhGRiwweDk5LDB4NTksMHhGNywweDAzXSxbMHg3MywweDE2LDB4NjMsMHgyRCwweDVDLDB4MzIsMHgyMywweDNFLDB4REMsMHhCMCwweDc4LDB4MDUsMHg2MCwweEVBLDB4RTgsMHhCMl1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDUwLDB4NTEsMHg1MiwweDUzLDB4NTUsMHg1NiwweDU3LDB4NTgsMHg1QSwweDVCLDB4NUMsMHg1RCwweDVGLDB4NjAsMHg2MSwweDYyXSxbMHgzNSwweDUzLDB4RUMsMHhGMCwweEIxLDB4NzMsMHg5NSwweDU4LDB4QjAsMHg4RSwweDM1LDB4MEEsMHg5OCwweEEzLDB4OUIsMHhGQV0sWzB4NDAsMHg4QywweDA3LDB4M0UsMHgzRSwweDI1LDB4MzgsMHgwNywweDJCLDB4NzIsMHg2MiwweDVFLDB4NjgsMHhCOCwweDM2LDB4NEJdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg2NCwweDY1LDB4NjYsMHg2NywweDY5LDB4NkEsMHg2QiwweDZDLDB4NkUsMHg2RiwweDcwLDB4NzEsMHg3MywweDc0LDB4NzUsMHg3Nl0sWzB4NjcsMHg0MiwweDk5LDB4NjksMHg0OSwweDBCLDB4OTcsMHgxMSwweEFFLDB4MkIsMHgwMSwweERDLDB4NDksMHg3QSwweEZELDB4RThdLFsweEUxLDB4RjksMHg0RCwweEZBLDB4NzcsMHg2NSwweDk3LDB4QkUsMHhBQywweEEyLDB4NjIsMHhGMiwweEY2LDB4MzYsMHg2RiwweEVBXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NzgsMHg3OSwweDdBLDB4N0IsMHg3RCwweDdFLDB4N0YsMHg4MCwweDgyLDB4ODMsMHg4NCwweDg1LDB4ODcsMHg4OCwweDg5LDB4OEFdLFsweDkzLDB4MzgsMHg1QywweDFGLDB4MkEsMHhFQywweDhCLDB4RUQsMHgxOSwweDJGLDB4NUEsMHg4RSwweDE2LDB4MUQsMHhENSwweDA4XSxbMHhGMiwweDlFLDB4OTgsMHg2QywweDZBLDB4MUMsMHgyNywweEQ3LDB4QjIsMHg5RiwweEZELDB4N0UsMHhFOSwweDJCLDB4NzUsMHhGMV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDhDLDB4OEQsMHg4RSwweDhGLDB4OTEsMHg5MiwweDkzLDB4OTQsMHg5NiwweDk3LDB4OTgsMHg5OSwweDlCLDB4OUMsMHg5RCwweDlFXSxbMHhCNSwweEJGLDB4OTQsMHg2QiwweEUxLDB4OUIsMHhFQiwweDhELDB4QjMsMHg5OCwweDNCLDB4NUYsMHg0QywweDZFLDB4OEQsMHhEQl0sWzB4MTMsMHgxQywweDg4LDB4NkEsMHg1NywweEY4LDB4QzIsMHhFNywweDEzLDB4QUIsMHhBNiwweDk1LDB4NUUsMHgyQiwweDU1LDB4QjVdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhBMCwweEExLDB4QTIsMHhBMywweEE1LDB4QTYsMHhBNywweEE4LDB4QUEsMHhBQiwweEFDLDB4QUQsMHhBRiwweEIwLDB4QjEsMHhCMl0sWzB4NDEsMHgzMiwweDFFLDB4RTEsMHgwRSwweDIxLDB4QkQsMHg5MCwweDcyLDB4MjcsMHhDNCwweDQ1LDB4MEYsMHhGNCwweDIzLDB4MjRdLFsweEQyLDB4QUIsMHg3NiwweDYyLDB4REYsMHg5QiwweDhDLDB4NzQsMHgwMiwweDEwLDB4RTUsMHhFRSwweEI2LDB4MUMsMHgxOSwweDlEXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4QjQsMHhCNSwweEI2LDB4QjcsMHhCOSwweEJBLDB4QkIsMHhCQywweEJFLDB4QkYsMHhDMCwweEMxLDB4QzMsMHhDNCwweEM1LDB4QzZdLFsweDAwLDB4QTgsMHgyRiwweDU5LDB4QzksMHgxQywweDg0LDB4ODYsMHhEMSwweDJDLDB4MEEsMHg4MCwweDEyLDB4NEYsMHg2MCwweDg5XSxbMHgxNCwweEMxLDB4MDUsMHg1NCwweEIyLDB4ODUsMHg5QywweDQ4LDB4NEMsMHhBQiwweDU4LDB4NjksMHhCQiwweEU3LDB4QzQsMHg3MF1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEM4LDB4QzksMHhDQSwweENCLDB4Q0QsMHhDRSwweENGLDB4RDAsMHhEMiwweEQzLDB4RDQsMHhENSwweEQ3LDB4RDgsMHhEOSwweERBXSxbMHg3QywweEUwLDB4RkQsMHgwNywweDY3LDB4NTQsMHg2OSwweDFCLDB4NEIsMHhCRCwweDlGLDB4QUYsMHg4QSwweDEzLDB4NzIsMHhGRV0sWzB4REIsMHg0RCwweDQ5LDB4OEYsMHgwQSwweDQ5LDB4Q0YsMHg1NSwweDQ0LDB4NUQsMHg1MCwweDJDLDB4MUYsMHg5QSwweEIzLDB4QjVdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhEQywweERELDB4REUsMHhERiwweEUxLDB4RTIsMHhFMywweEU0LDB4RTYsMHhFNywweEU4LDB4RTksMHhFQiwweEVDLDB4RUQsMHhFRV0sWzB4MjMsMHg2MCwweDVBLDB4ODIsMHg0MywweEQwLDB4NzcsMHg2NCwweDU0LDB4MUIsMHhDNSwweEFELDB4MzUsMHg1QiwweDMxLDB4MjldLFsweDZELDB4OTYsMHhGRSwweEY3LDB4RDYsMHg2NSwweDkwLDB4QTcsMHg3QSwweDc3LDB4QkIsMHgyMCwweDU2LDB4NjYsMHg3RiwweDdGXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4RjAsMHhGMSwweEYyLDB4RjMsMHhGNSwweEY2LDB4RjcsMHhGOCwweEZBLDB4RkIsMHhGQywweEZELDB4RkUsMHgwMSwweDAwLDB4MDJdLFsweDEyLDB4QTgsMHhDRiwweEEyLDB4M0UsMHhBNywweDY0LDB4RkQsMHg4NywweDYyLDB4MzIsMHhCNCwweEU4LDB4NDIsMHhCQywweDQ0XSxbMHgzMSwweDZGLDB4QjYsMHg4RSwweERCLDB4QTcsMHgzNiwweEM1LDB4M0UsMHg3OCwweDQ3LDB4N0IsMHhGOSwweDEzLDB4NzIsMHg1Q11dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDA0LDB4MDUsMHgwNiwweDA3LDB4MDksMHgwQSwweDBCLDB4MEMsMHgwRSwweDBGLDB4MTAsMHgxMSwweDEzLDB4MTQsMHgxNSwweDE2XSxbMHhCQywweEFGLDB4MzIsMHg0MSwweDVFLDB4ODMsMHgwOCwweEIzLDB4NzIsMHgzRSwweDVGLDB4REQsMHg4NSwweDNDLDB4Q0MsMHg4MF0sWzB4NjksMHgzNiwweEYyLDB4QjksMHgzQSwweEY4LDB4MzksMHg3RiwweEQzLDB4QTcsMHg3MSwweEZDLDB4MDEsMHgxQywweDhDLDB4MzddXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgyQywweDJELDB4MkUsMHgyRiwweDMxLDB4MzIsMHgzMywweDM0LDB4MzYsMHgzNywweDM4LDB4MzksMHgzQiwweDNDLDB4M0QsMHgzRV0sWzB4ODksMHhBRiwweEFFLDB4NjgsMHg1RCwweDgwLDB4MUEsMHhENywweDQ3LDB4QUMsMHhFOSwweDFGLDB4QzQsMHg5QSwweERELDB4RTBdLFsweEYzLDB4RjksMHgyRiwweDdBLDB4OUMsMHg1OSwweDE3LDB4OUMsMHgxRiwweENDLDB4MkMsMHgyQiwweEEwLDB4QjAsMHg4MiwweENEXV1dO1xuICBcbiAgdmFyIHRlc3R2ZWN0b3JzMTkyID0gW1tbMHgwMCwweDAxLDB4MDIsMHgwMywweDA1LDB4MDYsMHgwNywweDA4LDB4MEEsMHgwQiwweDBDLDB4MEQsMHgwRiwweDEwLDB4MTEsMHgxMiwweDE0LDB4MTUsMHgxNiwweDE3LDB4MTksMHgxQSwweDFCLDB4MUNdLFsweDJELDB4MzMsMHhFRSwweEYyLDB4QzAsMHg0MywweDBBLDB4OEEsMHg5RSwweEJGLDB4NDUsMHhFOCwweDA5LDB4QzQsMHgwQiwweEI2XSxbMHhERiwweEY0LDB4OTQsMHg1RSwweDAzLDB4MzYsMHhERiwweDRDLDB4MUMsMHg1NiwweEJDLDB4NzAsMHgwRSwweEZGLDB4ODMsMHg3Rl1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDFFLDB4MUYsMHgyMCwweDIxLDB4MjMsMHgyNCwweDI1LDB4MjYsMHgyOCwweDI5LDB4MkEsMHgyQiwweDJELDB4MkUsMHgyRiwweDMwLDB4MzIsMHgzMywweDM0LDB4MzUsMHgzNywweDM4LDB4MzksMHgzQV0sWzB4NkEsMHhBMywweDc1LDB4RDEsMHhGQSwweDE1LDB4NUEsMHg2MSwweEZCLDB4NzIsMHgzNSwweDNFLDB4MEEsMHg1QSwweDg3LDB4NTZdLFsweEI2LDB4RkQsMHhERSwweEY0LDB4NzUsMHgyNywweDY1LDB4RTMsMHg0NywweEQ1LDB4RDIsMHhEQywweDE5LDB4NkQsMHgxMiwweDUyXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4M0MsMHgzRCwweDNFLDB4M0YsMHg0MSwweDQyLDB4NDMsMHg0NCwweDQ2LDB4NDcsMHg0OCwweDQ5LDB4NEIsMHg0QywweDRELDB4NEUsMHg1MCwweDUxLDB4NTIsMHg1MywweDU1LDB4NTYsMHg1NywweDU4XSxbMHhCQywweDM3LDB4MzYsMHg1MSwweDhCLDB4OTQsMHg5MCwweERDLDB4QjgsMHhFRCwweDYwLDB4RUIsMHgyNiwweDc1LDB4OEUsMHhENF0sWzB4RDIsMHgzNiwweDg0LDB4RTMsMHhEOSwweDYzLDB4QjMsMHhBRiwweENGLDB4MUEsMHgxMSwweDRBLDB4Q0EsMHg5MCwweENCLDB4RDZdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg1QSwweDVCLDB4NUMsMHg1RCwweDVGLDB4NjAsMHg2MSwweDYyLDB4NjQsMHg2NSwweDY2LDB4NjcsMHg2OSwweDZBLDB4NkIsMHg2QywweDZFLDB4NkYsMHg3MCwweDcxLDB4NzMsMHg3NCwweDc1LDB4NzZdLFsweEFBLDB4MjEsMHg0NCwweDAyLDB4QjQsMHg2QywweEZGLDB4QjksMHhGNywweDYxLDB4RUMsMHgxMSwweDI2LDB4M0EsMHgzMSwweDFFXSxbMHgzQSwweDdBLDB4QzAsMHgyNywweDc1LDB4M0UsMHgyQSwweDE4LDB4QzIsMHhDRSwweEFCLDB4OUUsMHgxNywweEMxLDB4MUYsMHhEMF1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDc4LDB4NzksMHg3QSwweDdCLDB4N0QsMHg3RSwweDdGLDB4ODAsMHg4MiwweDgzLDB4ODQsMHg4NSwweDg3LDB4ODgsMHg4OSwweDhBLDB4OEMsMHg4RCwweDhFLDB4OEYsMHg5MSwweDkyLDB4OTMsMHg5NF0sWzB4MDIsMHhBRSwweEE4LDB4NkUsMHg1NywweDJFLDB4RUEsMHhCNiwweDZCLDB4MkMsMHgzQSwweEY1LDB4RTksMHhBNCwweDZGLDB4RDZdLFsweDhGLDB4NjcsMHg4NiwweEJELDB4MDAsMHg3NSwweDI4LDB4QkEsMHgyNiwweDYwLDB4M0MsMHgxNiwweDAxLDB4Q0QsMHhEMCwweEQ4XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4OTYsMHg5NywweDk4LDB4OTksMHg5QiwweDlDLDB4OUQsMHg5RSwweEEwLDB4QTEsMHhBMiwweEEzLDB4QTUsMHhBNiwweEE3LDB4QTgsMHhBQSwweEFCLDB4QUMsMHhBRCwweEFGLDB4QjAsMHhCMSwweEIyXSxbMHhFMiwweEFFLDB4RjYsMHhBQywweEMzLDB4M0IsMHg5NiwweDVDLDB4NEYsMHhBMSwweEY5LDB4MUMsMHg3NSwweEZGLDB4NkYsMHgzNl0sWzB4RDEsMHg3RCwweDA3LDB4M0IsMHgwMSwweEU3LDB4MTUsMHgwMiwweEUyLDB4OEIsMHg0NywweEFCLDB4NTUsMHgxMSwweDY4LDB4QjNdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhCNCwweEI1LDB4QjYsMHhCNywweEI5LDB4QkEsMHhCQiwweEJDLDB4QkUsMHhCRiwweEMwLDB4QzEsMHhDMywweEM0LDB4QzUsMHhDNiwweEM4LDB4QzksMHhDQSwweENCLDB4Q0QsMHhDRSwweENGLDB4RDBdLFsweDA2LDB4NTksMHhERiwweDQ2LDB4NDIsMHg3MSwweDYyLDB4QjksMHg0MywweDQ4LDB4NjUsMHhERCwweDk0LDB4OTksMHhGOSwweDFEXSxbMHhBNCwweDY5LDB4REEsMHg1MSwweDcxLDB4MTksMHhGQSwweEI5LDB4NTgsMHg3NiwweEY0LDB4MUQsMHgwNiwweEQ0LDB4MEYsMHhGQV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEQyLDB4RDMsMHhENCwweEQ1LDB4RDcsMHhEOCwweEQ5LDB4REEsMHhEQywweERELDB4REUsMHhERiwweEUxLDB4RTIsMHhFMywweEU0LDB4RTYsMHhFNywweEU4LDB4RTksMHhFQiwweEVDLDB4RUQsMHhFRV0sWzB4NDksMHhBNCwweDQyLDB4MzksMHhDNywweDQ4LDB4RkUsMHhCNCwweDU2LDB4RjUsMHg5QywweDI3LDB4NkEsMHg1NiwweDU4LDB4REZdLFsweDYwLDB4OTEsMHhBQSwweDNCLDB4NjksMHg1QywweDExLDB4RjUsMHhDMCwweEI2LDB4QUQsMHgyNiwweEQzLDB4RDgsMHg2MiwweEZGXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4RjAsMHhGMSwweEYyLDB4RjMsMHhGNSwweEY2LDB4RjcsMHhGOCwweEZBLDB4RkIsMHhGQywweEZELDB4RkUsMHgwMSwweDAwLDB4MDIsMHgwNCwweDA1LDB4MDYsMHgwNywweDA5LDB4MEEsMHgwQiwweDBDXSxbMHg2NiwweDIwLDB4OEYsMHg2RSwweDlELDB4MDQsMHg1MiwweDVCLDB4REUsMHhEQiwweDI3LDB4MzMsMHhCNiwweEE2LDB4QkUsMHgzN10sWzB4NzAsMHhGOSwweEU2LDB4N0YsMHg5RiwweDhELDB4RjEsMHgyOSwweDQxLDB4MzEsMHg2NiwweDJELDB4QzYsMHhFNiwweDkzLDB4NjRdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgwRSwweDBGLDB4MTAsMHgxMSwweDEzLDB4MTQsMHgxNSwweDE2LDB4MTgsMHgxOSwweDFBLDB4MUIsMHgxRCwweDFFLDB4MUYsMHgyMCwweDIyLDB4MjMsMHgyNCwweDI1LDB4MjcsMHgyOCwweDI5LDB4MkFdLFsweDMzLDB4OTMsMHhGOCwweERGLDB4QzcsMHgyOSwweEM5LDB4N0YsMHg1NCwweDgwLDB4QjksMHg1MCwweEJDLDB4OTYsMHg2NiwweEIwXSxbMHhEMSwweDU0LDB4REMsMHhBRiwweEFELDB4OEIsMHgyMCwweDdGLDB4QTUsMHhDQiwweEM5LDB4NUUsMHg5OSwweDk2LDB4QjUsMHg1OV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDJDLDB4MkQsMHgyRSwweDJGLDB4MzEsMHgzMiwweDMzLDB4MzQsMHgzNiwweDM3LDB4MzgsMHgzOSwweDNCLDB4M0MsMHgzRCwweDNFLDB4NDAsMHg0MSwweDQyLDB4NDMsMHg0NSwweDQ2LDB4NDcsMHg0OF0sWzB4NjAsMHg2OCwweDM0LDB4QzgsMHhDRSwweDA2LDB4M0YsMHgzMiwweDM0LDB4Q0YsMHgxMSwweDQ1LDB4MzIsMHg1RCwweEJELDB4NzFdLFsweDQ5LDB4MzQsMHhENSwweDQxLDB4RTgsMHhCNCwweDZGLDB4QTMsMHgzOSwweEM4LDB4MDUsMHhBNywweEFFLDB4QjksMHhFNSwweERBXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NEEsMHg0QiwweDRDLDB4NEQsMHg0RiwweDUwLDB4NTEsMHg1MiwweDU0LDB4NTUsMHg1NiwweDU3LDB4NTksMHg1QSwweDVCLDB4NUMsMHg1RSwweDVGLDB4NjAsMHg2MSwweDYzLDB4NjQsMHg2NSwweDY2XSxbMHhGRSwweEMxLDB4QzAsMHg0RiwweDUyLDB4OUIsMHhCRCwweDE3LDB4RDgsMHhDRSwweENGLDB4Q0MsMHg0NywweDE4LDB4QjEsMHg3Rl0sWzB4NjIsMHg1NiwweDRDLDB4NzMsMHg4RiwweDNFLDB4RkUsMHgxOCwweDZFLDB4MUEsMHgxMiwweDdBLDB4MEMsMHg0RCwweDNDLDB4NjFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg2OCwweDY5LDB4NkEsMHg2QiwweDZELDB4NkUsMHg2RiwweDcwLDB4NzIsMHg3MywweDc0LDB4NzUsMHg3NywweDc4LDB4NzksMHg3QSwweDdDLDB4N0QsMHg3RSwweDdGLDB4ODEsMHg4MiwweDgzLDB4ODRdLFsweDMyLDB4REYsMHg5OSwweEI0LDB4MzEsMHhFRCwweDVELDB4QzUsMHhBQywweEY4LDB4Q0EsMHhGNiwweERDLDB4NkMsMHhFNCwweDc1XSxbMHgwNywweDgwLDB4NUEsMHhBMCwweDQzLDB4OTgsMHg2RSwweEIyLDB4MzYsMHg5MywweEUyLDB4M0IsMHhFRiwweDhGLDB4MzQsMHgzOF1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDg2LDB4ODcsMHg4OCwweDg5LDB4OEIsMHg4QywweDhELDB4OEUsMHg5MCwweDkxLDB4OTIsMHg5MywweDk1LDB4OTYsMHg5NywweDk4LDB4OUEsMHg5QiwweDlDLDB4OUQsMHg5RiwweEEwLDB4QTEsMHhBMl0sWzB4N0YsMHhEQywweDJCLDB4NzQsMHg2RiwweDNGLDB4NjYsMHg1MiwweDk2LDB4OTQsMHgzQiwweDgzLDB4NzEsMHgwRCwweDFGLDB4ODJdLFsweERGLDB4MEIsMHg0OSwweDMxLDB4MDMsMHg4QiwweEFELDB4RTgsMHg0OCwweERFLDB4RTMsMHhCNCwweEI4LDB4NUEsMHhBNCwweDRCXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4QTQsMHhBNSwweEE2LDB4QTcsMHhBOSwweEFBLDB4QUIsMHhBQywweEFFLDB4QUYsMHhCMCwweEIxLDB4QjMsMHhCNCwweEI1LDB4QjYsMHhCOCwweEI5LDB4QkEsMHhCQiwweEJELDB4QkUsMHhCRiwweEMwXSxbMHg4RiwweEJBLDB4MTUsMHgxMCwweEEzLDB4QzUsMHhCOCwweDdFLDB4MkUsMHhBQSwweDNGLDB4N0EsMHg5MSwweDQ1LDB4NUMsMHhBMl0sWzB4NTksMHgyRCwweDVGLDB4REUsMHhENywweDY1LDB4ODIsMHhFNCwweDE0LDB4M0MsMHg2NSwweDA5LDB4OTMsMHgwOSwweDQ3LDB4N0NdXV07XG4gIFxuICB2YXIgdGVzdHZlY3RvcnMyNTYgPSBbW1sweDAwLDB4MDEsMHgwMiwweDAzLDB4MDUsMHgwNiwweDA3LDB4MDgsMHgwQSwweDBCLDB4MEMsMHgwRCwweDBGLDB4MTAsMHgxMSwweDEyLDB4MTQsMHgxNSwweDE2LDB4MTcsMHgxOSwweDFBLDB4MUIsMHgxQywweDFFLDB4MUYsMHgyMCwweDIxLDB4MjMsMHgyNCwweDI1LDB4MjZdLFsweDgzLDB4NEUsMHhBRCwweEZDLDB4Q0EsMHhDNywweEUxLDB4QjMsMHgwNiwweDY0LDB4QjEsMHhBQiwweEE0LDB4NDgsMHgxNSwweEFCXSxbMHgxOSwweDQ2LDB4REEsMHhCRiwweDZBLDB4MDMsMHhBMiwweEEyLDB4QzMsMHhEMCwweEIwLDB4NTAsMHg4MCwweEFFLDB4RDYsMHhGQ11dLFxuICAgICAgICAgICAgICBbWzB4MjgsMHgyOSwweDJBLDB4MkIsMHgyRCwweDJFLDB4MkYsMHgzMCwweDMyLDB4MzMsMHgzNCwweDM1LDB4MzcsMHgzOCwweDM5LDB4M0EsMHgzQywweDNELDB4M0UsMHgzRiwweDQxLDB4NDIsMHg0MywweDQ0LDB4NDYsMHg0NywweDQ4LDB4NDksMHg0QiwweDRDLDB4NEQsMHg0RV0sWzB4RDksMHhEQywweDRELDB4QkEsMHgzMCwweDIxLDB4QjAsMHg1RCwweDY3LDB4QzAsMHg1MSwweDhGLDB4NzIsMHhCNiwweDJCLDB4RjFdLFsweDVFLDB4RDMsMHgwMSwweEQ3LDB4NDcsMHhEMywweENDLDB4NzEsMHg1NCwweDQ1LDB4RUIsMHhERSwweEM2LDB4MkYsMHgyRiwweEI0XV0sXG4gICAgICAgICAgICAgIFtbMHg1MCwweDUxLDB4NTIsMHg1MywweDU1LDB4NTYsMHg1NywweDU4LDB4NUEsMHg1QiwweDVDLDB4NUQsMHg1RiwweDYwLDB4NjEsMHg2MiwweDY0LDB4NjUsMHg2NiwweDY3LDB4NjksMHg2QSwweDZCLDB4NkMsMHg2RSwweDZGLDB4NzAsMHg3MSwweDczLDB4NzQsMHg3NSwweDc2XSxbMHhBMiwweDkxLDB4RDgsMHg2MywweDAxLDB4QTQsMHhBNywweDM5LDB4RjcsMHgzOSwweDIxLDB4NzMsMHhBQSwweDNDLDB4NjAsMHg0Q10sWzB4NjUsMHg4NSwweEM4LDB4RjQsMHgzRCwweDEzLDB4QTYsMHhCRSwweEFCLDB4NjQsMHgxOSwweEZDLDB4NTksMHgzNSwweEI5LDB4RDBdXSxcbiAgICAgICAgICAgICAgW1sweDc4LDB4NzksMHg3QSwweDdCLDB4N0QsMHg3RSwweDdGLDB4ODAsMHg4MiwweDgzLDB4ODQsMHg4NSwweDg3LDB4ODgsMHg4OSwweDhBLDB4OEMsMHg4RCwweDhFLDB4OEYsMHg5MSwweDkyLDB4OTMsMHg5NCwweDk2LDB4OTcsMHg5OCwweDk5LDB4OUIsMHg5QywweDlELDB4OUVdLFsweDQyLDB4NjQsMHhCMiwweDY5LDB4NjQsMHg5OCwweERFLDB4NEQsMHhGNywweDk3LDB4ODgsMHhBOSwweEY4LDB4M0UsMHg5MywweDkwXSxbMHgyQSwweDVCLDB4NTYsMHhBNSwweDk2LDB4NjgsMHgwRiwweENDLDB4MEUsMHgwNSwweEY1LDB4RTAsMHhGMSwweDUxLDB4RUMsMHhBRV1dLFxuICAgICAgICAgICAgICBbWzB4QTAsMHhBMSwweEEyLDB4QTMsMHhBNSwweEE2LDB4QTcsMHhBOCwweEFBLDB4QUIsMHhBQywweEFELDB4QUYsMHhCMCwweEIxLDB4QjIsMHhCNCwweEI1LDB4QjYsMHhCNywweEI5LDB4QkEsMHhCQiwweEJDLDB4QkUsMHhCRiwweEMwLDB4QzEsMHhDMywweEM0LDB4QzUsMHhDNl0sWzB4RUUsMHg5OSwweDMyLDB4QjMsMHg3MiwweDE4LDB4MDQsMHhENSwweEE4LDB4M0UsMHhGNSwweDk0LDB4OTIsMHg0NSwweEI2LDB4RjZdLFsweEY1LDB4RDYsMHhGRiwweDQxLDB4NEYsMHhEMiwweEM2LDB4MTgsMHgxNCwweDk0LDB4RDIsMHgwQywweDM3LDB4RjIsMHhCOCwweEM0XV0sXG4gICAgICAgICAgICAgIFtbMHhDOCwweEM5LDB4Q0EsMHhDQiwweENELDB4Q0UsMHhDRiwweEQwLDB4RDIsMHhEMywweEQ0LDB4RDUsMHhENywweEQ4LDB4RDksMHhEQSwweERDLDB4REQsMHhERSwweERGLDB4RTEsMHhFMiwweEUzLDB4RTQsMHhFNiwweEU3LDB4RTgsMHhFOSwweEVCLDB4RUMsMHhFRCwweEVFXSxbMHhFNiwweDI0LDB4OEYsMHg1NSwweEM1LDB4RkQsMHhDQiwweENBLDB4OUMsMHhCQiwweEIwLDB4MUMsMHg4OCwweEEyLDB4RUEsMHg3N10sWzB4ODUsMHgzOSwweDlDLDB4MDEsMHhGNSwweDlGLDB4RkYsMHhCNSwweDIwLDB4NEYsMHgxOSwweEY4LDB4NDgsMHgyRiwweDAwLDB4QjhdXSxcbiAgICAgICAgICAgICAgW1sweEYwLDB4RjEsMHhGMiwweEYzLDB4RjUsMHhGNiwweEY3LDB4RjgsMHhGQSwweEZCLDB4RkMsMHhGRCwweEZFLDB4MDEsMHgwMCwweDAyLDB4MDQsMHgwNSwweDA2LDB4MDcsMHgwOSwweDBBLDB4MEIsMHgwQywweDBFLDB4MEYsMHgxMCwweDExLDB4MTMsMHgxNCwweDE1LDB4MTZdLFsweEI4LDB4MzUsMHg4RSwweDQxLDB4QjksMHhERiwweEY2LDB4NUYsMHhENCwweDYxLDB4RDUsMHg1QSwweDk5LDB4MjYsMHg2MiwweDQ3XSxbMHg5MiwweDA5LDB4N0IsMHg0QywweDg4LDB4QTAsMHg0MSwweERELDB4RjksMHg4MSwweDQ0LDB4QkMsMHg4RCwweDIyLDB4RTgsMHhFN11dLFxuICAgICAgICAgICAgICBbWzB4MTgsMHgxOSwweDFBLDB4MUIsMHgxRCwweDFFLDB4MUYsMHgyMCwweDIyLDB4MjMsMHgyNCwweDI1LDB4MjcsMHgyOCwweDI5LDB4MkEsMHgyQywweDJELDB4MkUsMHgyRiwweDMxLDB4MzIsMHgzMywweDM0LDB4MzYsMHgzNywweDM4LDB4MzksMHgzQiwweDNDLDB4M0QsMHgzRV0sWzB4RjAsMHhFMiwweEQ3LDB4MjIsMHg2MCwweEFGLDB4NTgsMHhFMiwweDFFLDB4MDEsMHg1QSwweEIzLDB4QTQsMHhDMCwweEQ5LDB4MDZdLFsweDg5LDB4QkQsMHg1QiwweDczLDB4QjMsMHg1NiwweEFCLDB4NDEsMHgyQSwweEVGLDB4OUYsMHg3NiwweENFLDB4QTIsMHhENiwweDVDXV0sXG4gICAgICAgICAgICAgIFtbMHg0MCwweDQxLDB4NDIsMHg0MywweDQ1LDB4NDYsMHg0NywweDQ4LDB4NEEsMHg0QiwweDRDLDB4NEQsMHg0RiwweDUwLDB4NTEsMHg1MiwweDU0LDB4NTUsMHg1NiwweDU3LDB4NTksMHg1QSwweDVCLDB4NUMsMHg1RSwweDVGLDB4NjAsMHg2MSwweDYzLDB4NjQsMHg2NSwweDY2XSxbMHg0NywweDVCLDB4OEIsMHg4MiwweDNDLDB4RTgsMHg4OSwweDNELDB4QjMsMHhDNCwweDRBLDB4OUYsMHgyQSwweDM3LDB4OUYsMHhGN10sWzB4MjUsMHgzNiwweDk2LDB4OTAsMHg5MywweEM1LDB4NUYsMHhGOSwweDQ1LDB4NDYsMHg5MiwweEYyLDB4RkEsMHhDMiwweEY1LDB4MzBdXSxcbiAgICAgICAgICAgICAgW1sweDY4LDB4NjksMHg2QSwweDZCLDB4NkQsMHg2RSwweDZGLDB4NzAsMHg3MiwweDczLDB4NzQsMHg3NSwweDc3LDB4NzgsMHg3OSwweDdBLDB4N0MsMHg3RCwweDdFLDB4N0YsMHg4MSwweDgyLDB4ODMsMHg4NCwweDg2LDB4ODcsMHg4OCwweDg5LDB4OEIsMHg4QywweDhELDB4OEVdLFsweDY4LDB4OEYsMHg1MiwweDgxLDB4OTQsMHg1OCwweDEyLDB4ODYsMHgyRiwweDVGLDB4MzAsMHg3NiwweENGLDB4ODAsMHg0MSwweDJGXSxbMHgwNywweEZDLDB4NzYsMHhBOCwweDcyLDB4ODQsMHgzRiwweDNGLDB4NkUsMHgwMCwweDgxLDB4RUUsMHg5MywweDk2LDB4RDYsMHgzN11dLFxuICAgICAgICAgICAgICBbWzB4OTAsMHg5MSwweDkyLDB4OTMsMHg5NSwweDk2LDB4OTcsMHg5OCwweDlBLDB4OUIsMHg5QywweDlELDB4OUYsMHhBMCwweEExLDB4QTIsMHhBNCwweEE1LDB4QTYsMHhBNywweEE5LDB4QUEsMHhBQiwweEFDLDB4QUUsMHhBRiwweEIwLDB4QjEsMHhCMywweEI0LDB4QjUsMHhCNl0sWzB4MDgsMHhEMSwweEQyLDB4QkMsMHg3NSwweDBBLDB4RjUsMHg1MywweDM2LDB4NUQsMHgzNSwweEU3LDB4NUEsMHhGQSwweENFLDB4QUFdLFsweEUzLDB4OEIsMHhBOCwweEVDLDB4MkEsMHhBNywweDQxLDB4MzUsMHg4RCwweENDLDB4OTMsMHhFOCwweEYxLDB4NDEsMHhDNCwweDkxXV0sXG4gICAgICAgICAgICAgIFtbMHhCOCwweEI5LDB4QkEsMHhCQiwweEJELDB4QkUsMHhCRiwweEMwLDB4QzIsMHhDMywweEM0LDB4QzUsMHhDNywweEM4LDB4QzksMHhDQSwweENDLDB4Q0QsMHhDRSwweENGLDB4RDEsMHhEMiwweEQzLDB4RDQsMHhENiwweEQ3LDB4RDgsMHhEOSwweERCLDB4REMsMHhERCwweERFXSxbMHg4NywweDA3LDB4MTIsMHgxRiwweDQ3LDB4Q0MsMHgzRSwweEZDLDB4RUMsMHhBNSwweEY5LDB4QTgsMHg0NywweDQ5LDB4NTAsMHhBMV0sWzB4RDAsMHgyOCwweEVFLDB4MjMsMHhFNCwweEE4LDB4OTAsMHg3NSwweEQwLDB4QjAsMHgzRSwweDg2LDB4OEQsMHg3RCwweDNBLDB4NDJdXSxcbiAgICAgICAgICAgICAgW1sweEUwLDB4RTEsMHhFMiwweEUzLDB4RTUsMHhFNiwweEU3LDB4RTgsMHhFQSwweEVCLDB4RUMsMHhFRCwweEVGLDB4RjAsMHhGMSwweEYyLDB4RjQsMHhGNSwweEY2LDB4RjcsMHhGOSwweEZBLDB4RkIsMHhGQywweEZFLDB4RkUsMHgwMSwweDAxLDB4MDMsMHgwNCwweDA1LDB4MDZdLFsweEU1LDB4MUEsMHhBMCwweEIxLDB4MzUsMHhEQiwweEE1LDB4NjYsMHg5MywweDlDLDB4M0IsMHg2MywweDU5LDB4QTksMHg4MCwweEM1XSxbMHg4QywweEQ5LDB4NDIsMHgzRCwweEZDLDB4NDUsMHg5RSwweDU0LDB4NzEsMHg1NSwweEM1LDB4RDEsMHhENSwweDIyLDB4RTUsMHg0MF1dLFxuICAgICAgICAgICAgICBbWzB4MDgsMHgwOSwweDBBLDB4MEIsMHgwRCwweDBFLDB4MEYsMHgxMCwweDEyLDB4MTMsMHgxNCwweDE1LDB4MTcsMHgxOCwweDE5LDB4MUEsMHgxQywweDFELDB4MUUsMHgxRiwweDIxLDB4MjIsMHgyMywweDI0LDB4MjYsMHgyNywweDI4LDB4MjksMHgyQiwweDJDLDB4MkQsMHgyRV0sWzB4MDYsMHg5QSwweDAwLDB4N0YsMHhDNywweDZBLDB4NDUsMHg5RiwweDk4LDB4QkEsMHhGOSwweDE3LDB4RkUsMHhERiwweDk1LDB4MjFdLFsweDA4LDB4MEUsMHg5NSwweDE3LDB4RUIsMHgxNiwweDc3LDB4NzEsMHg5QSwweENGLDB4NzIsMHg4MCwweDg2LDB4MDQsMHgwQSwweEUzXV0sXG4gICAgICAgICAgICAgIFtbMHgzMCwweDMxLDB4MzIsMHgzMywweDM1LDB4MzYsMHgzNywweDM4LDB4M0EsMHgzQiwweDNDLDB4M0QsMHgzRiwweDQwLDB4NDEsMHg0MiwweDQ0LDB4NDUsMHg0NiwweDQ3LDB4NDksMHg0QSwweDRCLDB4NEMsMHg0RSwweDRGLDB4NTAsMHg1MSwweDUzLDB4NTQsMHg1NSwweDU2XSxbMHg3MiwweDYxLDB4NjUsMHhDMSwweDcyLDB4M0YsMHhCQywweEY2LDB4QzAsMHgyNiwweEQ3LDB4RDAsMHgwQiwweDA5LDB4MTAsMHgyN10sWzB4N0MsMHgxNywweDAwLDB4MjEsMHgxQSwweDM5LDB4OTEsMHhGQywweDBFLDB4Q0QsMHhFRCwweDBBLDB4QjMsMHhFNSwweDc2LDB4QjBdXV07XG5cbiAgdmFyIHJlcyA9IHRydWU7XG4gIHZhciBqID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXN0dmVjdG9yczEyOC5sZW5ndGg7IGkrKykge1xuICAgIHZhciByZXMyID0gdGVzdF9hZXModGVzdHZlY3RvcnMxMjhbaV1bMV0sdGVzdHZlY3RvcnMxMjhbaV1bMF0sdGVzdHZlY3RvcnMxMjhbaV1bMl0pO1xuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyAxMjggYml0IGtleSB2ZWN0b3Igd2l0aCBibG9jayBcIitcbiAgICAgICAgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczEyOFtpXVsxXSkrXG4gICAgICAgIFwiIGFuZCBrZXkgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczEyOFtpXVswXSkrXG4gICAgICAgIFwiIHNob3VsZCBiZSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMTI4W2ldWzJdKSxcbiAgICAgICAgZmFsc2UpO1xuICAgICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiMTI4IGJpdCBrZXkgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZC5cIix0cnVlKVxuICAgIGorKztcbiAgfVxuICBcbiAgcmVzID0gdHJ1ZTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXN0dmVjdG9yczE5Mi5sZW5ndGg7IGkrKykge1xuICAgIHZhciByZXMyID0gdGVzdF9hZXModGVzdHZlY3RvcnMxOTJbaV1bMV0sdGVzdHZlY3RvcnMxOTJbaV1bMF0sdGVzdHZlY3RvcnMxOTJbaV1bMl0pO1xuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyAxOTIgYml0IGtleSB2ZWN0b3Igd2l0aCBibG9jayBcIitcbiAgICAgICAgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczE5MltpXVsxXSkrXG4gICAgICAgIFwiIGFuZCBrZXkgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczE5MltpXVswXSkrXG4gICAgICAgIFwiIHNob3VsZCBiZSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMTkyW2ldWzJdKSxcbiAgICAgICAgZmFsc2UpO1xuICAgICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiMTkyIGJpdCBrZXkgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZC5cIix0cnVlKVxuICAgIGorKztcbiAgfVxuXG4gIHJlcyA9IHRydWU7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMyNTYubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcmVzMiA9IHRlc3RfYWVzKHRlc3R2ZWN0b3JzMjU2W2ldWzFdLHRlc3R2ZWN0b3JzMjU2W2ldWzBdLHRlc3R2ZWN0b3JzMjU2W2ldWzJdKTtcbiAgICByZXMgJj0gcmVzMjtcbiAgICBpZiAoIXJlczIpIHtcbiAgICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgMjU2IGJpdCBrZXkgdmVjdG9yIHdpdGggYmxvY2sgXCIrXG4gICAgICAgIHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMyNTZbaV1bMV0pK1xuICAgICAgICBcIiBhbmQga2V5IFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMyNTZbaV1bMF0pK1xuICAgICAgICBcIiBzaG91bGQgYmUgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczI1NltpXVsyXSksXG4gICAgICAgIGZhbHNlKTtcbiAgICAgIGorKztcbiAgICB9XG4gIH1cbiAgaWYgKHJlcykge1xuICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIjI1NiBiaXQga2V5IHRlc3QgdmVjdG9ycyBjb21wbGV0ZWQuXCIsIHRydWUpXG4gICAgaisrO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJCbG93ZmlzaCBjaXBoZXIgdGVzdCB3aXRoIHRlc3QgdmVjdG9ycyBmcm9tIGh0dHA6Ly93d3cuc2NobmVpZXIuY29tL2NvZGUvdmVjdG9ycy50eHRcIiwgZnVuY3Rpb24oKSB7XG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG4gICAgdXRpbCA9IG9wZW5wZ3AudXRpbCxcbiAgICBCRmVuY3J5cHQgPSBvcGVucGdwLmNpcGhlci5ibG93ZmlzaDtcblxuICB2YXIgcmVzdWx0ID0gW107XG4gIGZ1bmN0aW9uIHRlc3RfYmYoaW5wdXQsIGtleSwgb3V0cHV0KSB7XG4gICAgdmFyIGJsb3dmaXNoID0gbmV3IG9wZW5wZ3AuY2lwaGVyLmJsb3dmaXNoKHV0aWwuYmluMnN0cihrZXkpKTtcbiAgICB2YXIgcmVzdWx0ID0gdXRpbC5iaW4yc3RyKGJsb3dmaXNoLmVuY3J5cHQoaW5wdXQpKTtcblxuICAgIHJldHVybiAodXRpbC5oZXhzdHJkdW1wKHJlc3VsdCkgPT0gdXRpbC5oZXhzdHJkdW1wKHV0aWwuYmluMnN0cihvdXRwdXQpKSk7XG4gIH1cbiAgdmFyIHRlc3R2ZWN0b3JzID0gW1tbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHg0RSwweEY5LDB4OTcsMHg0NSwweDYxLDB4OTgsMHhERCwweDc4XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4NTEsMHg4NiwweDZGLDB4RDUsMHhCOCwweDVFLDB4Q0IsMHg4QV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDMwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDEwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDFdLFsweDdELDB4ODUsMHg2RiwweDlBLDB4NjEsMHgzMCwweDYzLDB4RjJdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExXSxbMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExXSxbMHgyNCwweDY2LDB4REQsMHg4NywweDhCLDB4OTYsMHgzQywweDlEXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMV0sWzB4NjEsMHhGOSwweEMzLDB4ODAsMHgyMiwweDgxLDB4QjAsMHg5Nl1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTFdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDdELDB4MEMsMHhDNiwweDMwLDB4QUYsMHhEQSwweDFFLDB4QzddXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHg0RSwweEY5LDB4OTcsMHg0NSwweDYxLDB4OTgsMHhERCwweDc4XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkUsMHhEQywweEJBLDB4OTgsMHg3NiwweDU0LDB4MzIsMHgxMF0sWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4MEEsMHhDRSwweEFCLDB4MEYsMHhDNiwweEEwLDB4QTIsMHg4RF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDdDLDB4QTEsMHgxMCwweDQ1LDB4NEEsMHgxQSwweDZFLDB4NTddLFsweDAxLDB4QTEsMHhENiwweEQwLDB4MzksMHg3NywweDY3LDB4NDJdLFsweDU5LDB4QzYsMHg4MiwweDQ1LDB4RUIsMHgwNSwweDI4LDB4MkJdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMSwweDMxLDB4RDksMHg2MSwweDlELDB4QzEsMHgzNywweDZFXSxbMHg1QywweEQ1LDB4NEMsMHhBOCwweDNELDB4RUYsMHg1NywweERBXSxbMHhCMSwweEI4LDB4Q0MsMHgwQiwweDI1LDB4MEYsMHgwOSwweEEwXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDcsMHhBMSwweDEzLDB4M0UsMHg0QSwweDBCLDB4MjYsMHg4Nl0sWzB4MDIsMHg0OCwweEQ0LDB4MzgsMHgwNiwweEY2LDB4NzEsMHg3Ml0sWzB4MTcsMHgzMCwweEU1LDB4NzcsMHg4QiwweEVBLDB4MUQsMHhBNF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDM4LDB4NDksMHg2NywweDRDLDB4MjYsMHgwMiwweDMxLDB4OUVdLFsweDUxLDB4NDUsMHg0QiwweDU4LDB4MkQsMHhERiwweDQ0LDB4MEFdLFsweEEyLDB4NUUsMHg3OCwweDU2LDB4Q0YsMHgyNiwweDUxLDB4RUJdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwNCwweEI5LDB4MTUsMHhCQSwweDQzLDB4RkUsMHhCNSwweEI2XSxbMHg0MiwweEZELDB4NDQsMHgzMCwweDU5LDB4NTcsMHg3RiwweEEyXSxbMHgzNSwweDM4LDB4ODIsMHhCMSwweDA5LDB4Q0UsMHg4RiwweDFBXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgxMywweEI5LDB4NzAsMHhGRCwweDM0LDB4RjIsMHhDRV0sWzB4MDUsMHg5QiwweDVFLDB4MDgsMHg1MSwweENGLDB4MTQsMHgzQV0sWzB4NDgsMHhGNCwweEQwLDB4ODgsMHg0QywweDM3LDB4OTksMHgxOF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4NzAsMHhGMSwweDc1LDB4NDYsMHg4RiwweEI1LDB4RTZdLFsweDA3LDB4NTYsMHhEOCwweEUwLDB4NzcsMHg0NywweDYxLDB4RDJdLFsweDQzLDB4MjEsMHg5MywweEI3LDB4ODksMHg1MSwweEZDLDB4OThdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg0MywweDI5LDB4N0YsMHhBRCwweDM4LDB4RTMsMHg3MywweEZFXSxbMHg3NiwweDI1LDB4MTQsMHhCOCwweDI5LDB4QkYsMHg0OCwweDZBXSxbMHgxMywweEYwLDB4NDEsMHg1NCwweEQ2LDB4OUQsMHgxQSwweEU1XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDcsMHhBNywweDEzLDB4NzAsMHg0NSwweERBLDB4MkEsMHgxNl0sWzB4M0IsMHhERCwweDExLDB4OTAsMHg0OSwweDM3LDB4MjgsMHgwMl0sWzB4MkUsMHhFRCwweERBLDB4OTMsMHhGRiwweEQzLDB4OUMsMHg3OV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDA0LDB4NjgsMHg5MSwweDA0LDB4QzIsMHhGRCwweDNCLDB4MkZdLFsweDI2LDB4OTUsMHg1RiwweDY4LDB4MzUsMHhBRiwweDYwLDB4OUFdLFsweEQ4LDB4ODcsMHhFMCwweDM5LDB4M0MsMHgyRCwweEE2LDB4RTNdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgzNywweEQwLDB4NkIsMHhCNSwweDE2LDB4Q0IsMHg3NSwweDQ2XSxbMHgxNiwweDRELDB4NUUsMHg0MCwweDRGLDB4MjcsMHg1MiwweDMyXSxbMHg1RiwweDk5LDB4RDAsMHg0RiwweDVCLDB4MTYsMHgzOSwweDY5XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MUYsMHgwOCwweDI2LDB4MEQsMHgxQSwweEMyLDB4NDYsMHg1RV0sWzB4NkIsMHgwNSwweDZFLDB4MTgsMHg3NSwweDlGLDB4NUMsMHhDQV0sWzB4NEEsMHgwNSwweDdBLDB4M0IsMHgyNCwweEQzLDB4OTcsMHg3Ql1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDU4LDB4NDAsMHgyMywweDY0LDB4MUEsMHhCQSwweDYxLDB4NzZdLFsweDAwLDB4NEIsMHhENiwweEVGLDB4MDksMHgxNywweDYwLDB4NjJdLFsweDQ1LDB4MjAsMHgzMSwweEMxLDB4RTQsMHhGQSwweERBLDB4OEVdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMiwweDU4LDB4MTYsMHgxNiwweDQ2LDB4MjksMHhCMCwweDA3XSxbMHg0OCwweDBELDB4MzksMHgwMCwweDZFLDB4RTcsMHg2MiwweEYyXSxbMHg3NSwweDU1LDB4QUUsMHgzOSwweEY1LDB4OUIsMHg4NywweEJEXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4NDksMHg3OSwweDNFLDB4QkMsMHg3OSwweEIzLDB4MjUsMHg4Rl0sWzB4NDMsMHg3NSwweDQwLDB4QzgsMHg2OSwweDhGLDB4M0MsMHhGQV0sWzB4NTMsMHhDNSwweDVGLDB4OUMsMHhCNCwweDlGLDB4QzAsMHgxOV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDRGLDB4QjAsMHg1RSwweDE1LDB4MTUsMHhBQiwweDczLDB4QTddLFsweDA3LDB4MkQsMHg0MywweEEwLDB4NzcsMHgwNywweDUyLDB4OTJdLFsweDdBLDB4OEUsMHg3QiwweEZBLDB4OTMsMHg3RSwweDg5LDB4QTNdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg0OSwweEU5LDB4NUQsMHg2RCwweDRDLDB4QTIsMHgyOSwweEJGXSxbMHgwMiwweEZFLDB4NTUsMHg3NywweDgxLDB4MTcsMHhGMSwweDJBXSxbMHhDRiwweDlDLDB4NUQsMHg3QSwweDQ5LDB4ODYsMHhBRCwweEI1XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHg4MywweDEwLDB4REMsMHg0MCwweDlCLDB4MjYsMHhENl0sWzB4MUQsMHg5RCwweDVDLDB4NTAsMHgxOCwweEY3LDB4MjgsMHhDMl0sWzB4RDEsMHhBQiwweEIyLDB4OTAsMHg2NSwweDhCLDB4QzcsMHg3OF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDFDLDB4NTgsMHg3RiwweDFDLDB4MTMsMHg5MiwweDRGLDB4RUZdLFsweDMwLDB4NTUsMHgzMiwweDI4LDB4NkQsMHg2RiwweDI5LDB4NUFdLFsweDU1LDB4Q0IsMHgzNywweDc0LDB4RDEsMHgzRSwweEYyLDB4MDFdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMSwweDAxLDB4MDEsMHgwMSwweDAxLDB4MDEsMHgwMSwweDAxXSxbMHgwMSwweDIzLDB4NDUsMHg2NywweDg5LDB4QUIsMHhDRCwweEVGXSxbMHhGQSwweDM0LDB4RUMsMHg0OCwweDQ3LDB4QjIsMHg2OCwweEIyXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MUYsMHgxRiwweDFGLDB4MUYsMHgwRSwweDBFLDB4MEUsMHgwRV0sWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4QTcsMHg5MCwweDc5LDB4NTEsMHgwOCwweEVBLDB4M0MsMHhBRV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweEUwLDB4RkUsMHhFMCwweEZFLDB4RjEsMHhGRSwweEYxLDB4RkVdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweEMzLDB4OUUsMHgwNywweDJELDB4OUYsMHhBQywweDYzLDB4MURdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGXSxbMHgwMSwweDQ5LDB4MzMsMHhFMCwweENELDB4QUYsMHhGNiwweEU0XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RjIsMHgxRSwweDlBLDB4NzcsMHhCNywweDFDLDB4NDksMHhCQ11dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDI0LDB4NTksMHg0NiwweDg4LDB4NTcsMHg1NCwweDM2LDB4OUFdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHhGRSwweERDLDB4QkEsMHg5OCwweDc2LDB4NTQsMHgzMiwweDEwXSxbMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGXSxbMHg2QiwweDVDLDB4NUEsMHg5QywweDVELDB4OUUsMHgwQSwweDVBXV1dO1xuXG4gIHZhciByZXMgPSB0cnVlO1xuICB2YXIgaiA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcmVzMiA9IHRlc3RfYmYodGVzdHZlY3RvcnNbaV1bMV0sdGVzdHZlY3RvcnNbaV1bMF0sdGVzdHZlY3RvcnNbaV1bMl0pO1xuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3IgXCIraStcIiB3aXRoIGJsb2NrIFwiK1xuICAgICAgICB1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzBdKStcbiAgICAgICAgXCIgYW5kIGtleSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzFdKStcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMl0pLCBmYWxzZSk7XG4gICAgICBqKys7XG4gICAgfVxuICB9XG4gIGlmIChyZXMpIHtcbiAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCIzNCB0ZXN0IHZlY3RvcnMgY29tcGxldGVkIFwiLCB0cnVlKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIkNBU1QtMTI4IGNpcGhlciB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gUkZDMjE0NFwiLCBmdW5jdGlvbigpIHtcblx0dmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcblx0XHR1dGlsID0gb3BlbnBncC51dGlsO1xuXG5cdHZhciByZXN1bHQgPSBbXTtcblx0ZnVuY3Rpb24gdGVzdF9jYXN0KGlucHV0LCBrZXksIG91dHB1dCkge1xuXHRcdHZhciBjYXN0NSA9IG5ldyBvcGVucGdwLmNpcGhlci5jYXN0NSh1dGlsLmJpbjJzdHIoa2V5KSk7XG5cdFx0dmFyIHJlc3VsdCA9IHV0aWwuYmluMnN0cihjYXN0NS5lbmNyeXB0KGlucHV0KSk7XG5cblx0XHRyZXR1cm4gdXRpbC5oZXhzdHJkdW1wKHJlc3VsdCkgPT0gdXRpbC5oZXhzdHJkdW1wKHV0aWwuYmluMnN0cihvdXRwdXQpKTtcblx0fVxuXHRcblx0dmFyIHRlc3R2ZWN0b3JzID0gW1tbMHgwMSwweDIzLDB4NDUsMHg2NywweDEyLDB4MzQsMHg1NiwweDc4LDB4MjMsMHg0NSwweDY3LDB4ODksMHgzNCwweDU2LDB4NzgsMHg5QV0sWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4MjMsMHg4QiwweDRGLDB4RTUsMHg4NCwweDdFLDB4NDQsMHhCMl1dXTtcblxuXHRmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzLmxlbmd0aDsgaSsrKSB7XG5cdFx0cmVzdWx0W2ldID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3Igd2l0aCBibG9jayBcIitcblx0XHRcdFx0dXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVswXSkrXG5cdFx0XHRcdFwiIGFuZCBrZXkgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVsxXSkrXG5cdFx0XHRcdFwiIHNob3VsZCBiZSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzJdKSxcblx0XHRcdHRlc3RfY2FzdCh0ZXN0dmVjdG9yc1tpXVsxXSx0ZXN0dmVjdG9yc1tpXVswXSx0ZXN0dmVjdG9yc1tpXVsyXSkpO1xuXHR9XG5cdHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vLi4vdW5pdC5qcycpO1xuXG4vL1RPRE8gU0MgOC8yMDEzIC0tIFRoaXMgdGVzdCBpcyBmYWlsaW5nIHRoZSBmaXJzdCB0ZXN0IGJlY2F1c2Ugb2YgdHJ1bmNhdGluZyB0aGUgbGFzdCAweDAwLCBhbGwgb3RoZXIgdGVzdHMgYXJlIHBhc3NpbmcuIFNob3VsZCBpbnZlc3RpZ2F0ZS5cbnVuaXQucmVnaXN0ZXIoXCJUcmlwbGVERVMgKEVERSkgY2lwaGVyIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBodHRwOi8vY3NyYy5uaXN0Lmdvdi9wdWJsaWNhdGlvbnMvbmlzdHB1YnMvODAwLTIwLzgwMC0yMC5wZGZcIiwgZnVuY3Rpb24oKSB7XG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG4gICAgdXRpbCA9IG9wZW5wZ3AudXRpbDtcblxuICB2YXIgcmVzdWx0ID0gW107XG4gIHZhciBrZXkgPSB1dGlsLmJpbjJzdHIoWzEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxXSk7XG4gIHZhciB0ZXN0dmVjdG9ycyA9IFtbWzB4ODAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4OTUsMHhGOCwweEE1LDB4RTUsMHhERCwweDMxLDB4RDksMHgwMF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDQwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweERELDB4N0YsMHgxMiwweDFDLDB4QTUsMHgwMSwweDU2LDB4MTldXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgyMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgyRSwweDg2LDB4NTMsMHgxMCwweDRGLDB4MzgsMHgzNCwweEVBXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MTAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NEIsMHhEMywweDg4LDB4RkYsMHg2QywweEQ4LDB4MUQsMHg0Rl1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDA4LDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDIwLDB4QjksMHhFNywweDY3LDB4QjIsMHhGQiwweDE0LDB4NTZdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwNCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHg1NSwweDU3LDB4OTMsMHg4MCwweEQ3LDB4NzEsMHgzOCwweEVGXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDIsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NkMsMHhDNSwweERFLDB4RkEsMHhBRiwweDA0LDB4NTEsMHgyRl1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDBELDB4OUYsMHgyNywweDlCLDB4QTUsMHhEOCwweDcyLDB4NjBdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDgwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHhEOSwweDAzLDB4MUIsMHgwMiwweDcxLDB4QkQsMHg1QSwweDBBXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHg0MCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NDIsMHg0MiwweDUwLDB4QjMsMHg3QywweDNELDB4RDksMHg1MV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MjAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEI4LDB4MDYsMHgxQiwweDdFLDB4Q0QsMHg5QSwweDIxLDB4RTVdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDEwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHhGMSwweDVELDB4MEYsMHgyOCwweDZCLDB4NjUsMHhCRCwweDI4XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwOCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4QUQsMHhEMCwweENDLDB4OEQsMHg2RSwweDVELDB4RUIsMHhBMV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDQsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEU2LDB4RDUsMHhGOCwweDI3LDB4NTIsMHhBRCwweDYzLDB4RDFdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAyLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHhFQywweEJGLDB4RTMsMHhCRCwweDNGLDB4NTksMHgxQSwweDVFXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMSwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RjMsMHg1NiwweDgzLDB4NDMsMHg3OSwweEQxLDB4NjUsMHhDRF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHg4MCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDJCLDB4OUYsMHg5OCwweDJGLDB4MjAsMHgwMywweDdGLDB4QTldXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAwLDB4NDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHg4OCwweDlELDB4RTAsMHg2OCwweEExLDB4NkYsMHgwQiwweEU2XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDIwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RTEsMHg5RSwweDI3LDB4NUQsMHg4NCwweDZBLDB4MTIsMHg5OF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgxMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDMyLDB4OUEsMHg4RSwweEQ1LDB4MjMsMHhENywweDFBLDB4RUNdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAwLDB4MDgsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHhFNywweEZDLDB4RTIsMHgyNSwweDU3LDB4RDIsMHgzQywweDk3XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDA0LDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MTIsMHhBOSwweEY1LDB4ODEsMHg3RiwweEYyLDB4RDYsMHg1RF1dXTtcblxuICB2YXIgcmVzID0gdHJ1ZTtcbiAgdmFyIGogPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGRlcyA9IG5ldyBvcGVucGdwLmNpcGhlci5kZXMoa2V5KTtcblxuICAgIHZhciBlbmNyID0gdXRpbC5iaW4yc3RyKGRlcy5lbmNyeXB0KHRlc3R2ZWN0b3JzW2ldWzBdLCBrZXkpKTtcbiAgICB2YXIgcmVzMiA9IGVuY3IgPT0gdXRpbC5iaW4yc3RyKHRlc3R2ZWN0b3JzW2ldWzFdKTtcblxuICAgIHJlcyAmPSByZXMyO1xuXG4gICAgaWYgKCFyZXMyKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3Igd2l0aCBibG9jayBcIiArXG4gICAgICAgIHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMF0pICtcbiAgICAgICAgXCIgYW5kIGtleSBcIiArIHV0aWwuaGV4c3RyZHVtcChrZXkpICtcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiICsgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVsxXSkgKyBcIiAhPSBcIiArXG4gICAgICAgIHV0aWwuaGV4aWR1bXAoZW5jciksXG4gICAgICBmYWxzZSk7XG4gICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiQWxsIDNERVMgRURFIHRlc3QgdmVjdG9ycyBjb21wbGV0ZWRcIiwgdHJ1ZSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJUd29maXNoIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBodHRwOi8vd3d3LnNjaG5laWVyLmNvbS9jb2RlL2VjYl9pdmFsLnR4dFwiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcbiAgICB1dGlsID0gb3BlbnBncC51dGlsO1xuXG4gIGZ1bmN0aW9uIFRGZW5jcnlwdChibG9jaywga2V5KSB7XG4gICAgdmFyIHRmID0gbmV3IG9wZW5wZ3AuY2lwaGVyLnR3b2Zpc2goa2V5KTtcblxuICAgIHJldHVybiB0Zi5lbmNyeXB0KGJsb2NrKTtcbiAgfVxuXG5cbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIgc3RhcnQgPSBbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXTtcbiAgdmFyIHN0YXJ0X3Nob3J0ID0gWzAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdO1xuICB2YXIgdGVzdHZlY3RvcnMgPSBbWzB4NTcsMHhGRiwweDczLDB4OUQsMHg0RCwweEM5LDB4MkMsMHgxQiwweEQ3LDB4RkMsMHgwMSwweDcwLDB4MEMsMHhDOCwweDIxLDB4NkZdLFxuICAgICAgICAgICAgWzB4RDQsMHgzQiwweEI3LDB4NTUsMHg2RSwweEEzLDB4MkUsMHg0NiwweEYyLDB4QTIsMHg4MiwweEI3LDB4RDQsMHg1QiwweDRFLDB4MERdLFxuICAgICAgICAgICAgWzB4OTAsMHhBRiwweEU5LDB4MUIsMHhCMiwweDg4LDB4NTQsMHg0RiwweDJDLDB4MzIsMHhEQywweDIzLDB4OUIsMHgyNiwweDM1LDB4RTZdLFxuICAgICAgICAgICAgWzB4NkMsMHhCNCwweDU2LDB4MUMsMHg0MCwweEJGLDB4MEEsMHg5NywweDA1LDB4OTMsMHgxQywweEI2LDB4RDQsMHgwOCwweEU3LDB4RkFdLFxuICAgICAgICAgICAgWzB4MzAsMHg1OSwweEQ2LDB4RDYsMHgxNywweDUzLDB4QjksMHg1OCwweEQ5LDB4MkYsMHg0NywweDgxLDB4QzgsMHg2NCwweDBFLDB4NThdLFxuICAgICAgICAgICAgWzB4RTYsMHg5NCwweDY1LDB4NzcsMHgwNSwweDA1LDB4RDcsMHhGOCwweDBFLDB4RjYsMHg4QywweEEzLDB4OEEsMHhCMywweEEzLDB4RDZdLFxuICAgICAgICAgICAgWzB4NUEsMHhCNiwweDdBLDB4NUYsMHg4NSwweDM5LDB4QTQsMHhBNSwweEZELDB4OUYsMHgwMywweDczLDB4QkEsMHg0NiwweDM0LDB4NjZdLFxuICAgICAgICAgICAgWzB4REMsMHgwOSwweDZCLDB4Q0QsMHg5OSwweEZDLDB4NzIsMHhGNywweDk5LDB4MzYsMHhENCwweEM3LDB4NDgsMHhFNywweDVBLDB4RjddLFxuICAgICAgICAgICAgWzB4QzUsMHhBMywweEU3LDB4Q0UsMHhFMCwweEYxLDB4QjcsMHgyNiwweDA1LDB4MjgsMHhBNiwweDhGLDB4QjQsMHhFQSwweDA1LDB4RjJdLFxuICAgICAgICAgICAgWzB4NDMsMHhENSwweENFLDB4QzMsMHgyNywweEIyLDB4NEEsMHhCOSwweDBBLDB4RDMsMHg0QSwweDc5LDB4RDAsMHg0NiwweDkxLDB4NTFdXTtcbiAgdGVzdHZlY3RvcnNbNDddID0gIFsweDQzLDB4MTAsMHg1OCwweEY0LDB4REIsMHhDNywweEY3LDB4MzQsMHhEQSwweDRGLDB4MDIsMHhGMCwweDRDLDB4QzQsMHhGNCwweDU5XTtcbiAgdGVzdHZlY3RvcnNbNDhdID0gIFsweDM3LDB4RkUsMHgyNiwweEZGLDB4MUMsMHhGNiwweDYxLDB4NzUsMHhGNSwweERELDB4RjQsMHhDMywweDNCLDB4OTcsMHhBMiwweDA1XTtcbiAgdmFyIHJlcyA9IHRydWU7XG4gIHZhciBqID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OTsgaSsrKSB7XG4gICAgdmFyIHJlczIgPSBmYWxzZTtcbiAgICB2YXIgYmxrLCBrZXksIGN0O1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICBibGsgPSBzdGFydF9zaG9ydDtcbiAgICAgIGtleSA9IHV0aWwuYmluMnN0cihzdGFydCk7XG4gICAgICBjdCA9IHRlc3R2ZWN0b3JzWzBdO1xuICAgICAgcmVzMiA9ICh1dGlsLmJpbjJzdHIoVEZlbmNyeXB0KGJsayxrZXkpKSA9PSB1dGlsLmJpbjJzdHIoY3QpKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IDEpIHtcbiAgICAgIGJsayA9IHRlc3R2ZWN0b3JzWzBdO1xuICAgICAga2V5ID0gdXRpbC5iaW4yc3RyKHN0YXJ0KTtcbiAgICAgIGN0ID0gdGVzdHZlY3RvcnNbMV07XG4gICAgICByZXMyID0gKHV0aWwuYmluMnN0cihURmVuY3J5cHQoYmxrLGtleSkpID09IHV0aWwuYmluMnN0cihjdCkpO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gMikge1xuICAgICAgYmxrID0gdGVzdHZlY3RvcnNbaS0xXTtcbiAgICAgIGtleSA9IHV0aWwuYmluMnN0cih0ZXN0dmVjdG9yc1tpLTJdLmNvbmNhdChzdGFydF9zaG9ydCkpO1xuICAgICAgY3QgPSB0ZXN0dmVjdG9yc1tpXTtcbiAgICAgIHJlczIgPSAodXRpbC5iaW4yc3RyKFRGZW5jcnlwdChibGssa2V5KSkgPT0gdXRpbC5iaW4yc3RyKGN0KSk7XG4gICAgfSBlbHNlIGlmIChpIDwgMTAgfHwgaSA+IDQ2KSB7XG4gICAgICBibGsgPSB0ZXN0dmVjdG9yc1tpLTFdO1xuICAgICAga2V5ID0gdXRpbC5iaW4yc3RyKHRlc3R2ZWN0b3JzW2ktMl0uY29uY2F0KHRlc3R2ZWN0b3JzW2ktM10pKTtcbiAgICAgIGN0ID0gdGVzdHZlY3RvcnNbaV07XG4gICAgICByZXMyID0gKHV0aWwuYmluMnN0cihURmVuY3J5cHQoYmxrLGtleSkpID09IHV0aWwuYmluMnN0cihjdCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0ZXN0dmVjdG9yc1tpXSA9IFRGZW5jcnlwdCh0ZXN0dmVjdG9yc1tpLTFdLHV0aWwuYmluMnN0cih0ZXN0dmVjdG9yc1tpLTJdLmNvbmNhdCh0ZXN0dmVjdG9yc1tpLTNdKSkpO1xuICAgICAgcmVzMiA9IHRydWU7XG4gICAgfVxuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3Igd2l0aCBibG9jayBcIit1dGlsLmhleGlkdW1wKGJsaykrXCIgd2l0aCBrZXkgXCIrIHV0aWwuaGV4c3RyZHVtcChrZXkpICtcIiBzaG91bGQgYmUgXCIrdXRpbC5oZXhpZHVtcChjdCkrXCIgYnV0IGlzIFwiK3V0aWwuaGV4aWR1bXAoVEZlbmNyeXB0KGJsayxrZXkpKSwgZmFsc2UpO1xuICAgICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiNDkgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZFwiLCB0cnVlKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIk1ENSB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gUkZDIDEzMjFcIiwgZnVuY3Rpb24oKSB7XG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG5cdFx0dXRpbCA9IG9wZW5wZ3AudXRpbCxcblx0XHRNRDUgPSBvcGVucGdwLmhhc2gubWQ1O1xuXG5cdHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblx0cmVzdWx0WzBdID0gbmV3IHVuaXQucmVzdWx0KFwiTUQ1IChcXFwiXFxcIikgPSBkNDFkOGNkOThmMDBiMjA0ZTk4MDA5OThlY2Y4NDI3ZVwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKE1ENShcIlwiKSkgPT0gXCJkNDFkOGNkOThmMDBiMjA0ZTk4MDA5OThlY2Y4NDI3ZVwiKTtcblx0cmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiTUQ1IChcXFwiYVxcXCIpID0gMGNjMTc1YjljMGYxYjZhODMxYzM5OWUyNjk3NzI2NjFcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChNRDUgKFwiYWJjXCIpKSA9PSBcIjkwMDE1MDk4M2NkMjRmYjBkNjk2M2Y3ZDI4ZTE3ZjcyXCIpO1xuXHRyZXN1bHRbMl0gPSBuZXcgdW5pdC5yZXN1bHQoXCJNRDUgKFxcXCJtZXNzYWdlIGRpZ2VzdFxcXCIpID0gZjk2YjY5N2Q3Y2I3OTM4ZDUyNWEyZjMxYWFmMTYxZDBcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChNRDUgKFwibWVzc2FnZSBkaWdlc3RcIikpID09IFwiZjk2YjY5N2Q3Y2I3OTM4ZDUyNWEyZjMxYWFmMTYxZDBcIik7XG5cdHJlc3VsdFszXSA9IG5ldyB1bml0LnJlc3VsdChcIk1ENSAoXFxcImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XFxcIikgPSBjM2ZjZDNkNzYxOTJlNDAwN2RmYjQ5NmNjYTY3ZTEzYlwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKE1ENSAoXCJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elwiKSkgPT0gXCJjM2ZjZDNkNzYxOTJlNDAwN2RmYjQ5NmNjYTY3ZTEzYlwiKTtcblx0cmVzdWx0WzRdID0gbmV3IHVuaXQucmVzdWx0KFwiTUQ1IChcXFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODlcXFwiKSA9IGQxNzRhYjk4ZDI3N2Q5ZjVhNTYxMWMyYzlmNDE5ZDlmXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoTUQ1IChcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5XCIpKSA9PSBcImQxNzRhYjk4ZDI3N2Q5ZjVhNTYxMWMyYzlmNDE5ZDlmXCIpO1xuXHRyZXN1bHRbNV0gPSBuZXcgdW5pdC5yZXN1bHQoXCJNRDUgKFxcXCIxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MFxcXCIpID0gNTdlZGY0YTIyYmUzYzk1NWFjNDlkYTJlMjEwN2I2N2FcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChNRDUgKFwiMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTBcIikpID09IFwiNTdlZGY0YTIyYmUzYzk1NWFjNDlkYTJlMjEwN2I2N2FcIik7XG5cdHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vLi4vdW5pdC5qcycpO1xuXG51bml0LnJlZ2lzdGVyKFwiUklQRS1NRCAxNjAgYml0cyB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gaHR0cDovL2hvbWVzLmVzYXQua3VsZXV2ZW4uYmUvfmJvc3NlbGFlL3JpcGVtZDE2MC5odG1sXCIsIGZ1bmN0aW9uKCkge1xuXG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG5cdFx0dXRpbCA9IG9wZW5wZ3AudXRpbCxcblx0XHRSTURzdHJpbmcgPSBvcGVucGdwLmhhc2gucmlwZW1kO1xuXG5cdHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblx0cmVzdWx0WzBdID0gbmV3IHVuaXQucmVzdWx0KFwiUk1Ec3RyaW5nIChcXFwiXFxcIikgPSA5YzExODVhNWM1ZTlmYzU0NjEyODA4OTc3ZWU4ZjU0OGIyMjU4ZDMxXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoUk1Ec3RyaW5nKFwiXCIpKSA9PSBcIjljMTE4NWE1YzVlOWZjNTQ2MTI4MDg5NzdlZThmNTQ4YjIyNThkMzFcIik7XG5cdHJlc3VsdFsxXSA9IG5ldyB1bml0LnJlc3VsdChcIlJNRHN0cmluZyAoXFxcImFcXFwiKSA9IDBiZGM5ZDJkMjU2YjNlZTlkYWFlMzQ3YmU2ZjRkYzgzNWE0NjdmZmVcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChSTURzdHJpbmcoXCJhXCIpKSA9PSBcIjBiZGM5ZDJkMjU2YjNlZTlkYWFlMzQ3YmU2ZjRkYzgzNWE0NjdmZmVcIik7XG5cdHJlc3VsdFsyXSA9IG5ldyB1bml0LnJlc3VsdChcIlJNRHN0cmluZyAoXFxcImFiY1xcXCIpID0gOGViMjA4ZjdlMDVkOTg3YTliMDQ0YThlOThjNmIwODdmMTVhMGJmY1wiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKFJNRHN0cmluZyhcImFiY1wiKSkgPT0gXCI4ZWIyMDhmN2UwNWQ5ODdhOWIwNDRhOGU5OGM2YjA4N2YxNWEwYmZjXCIpO1xuXHRyZXN1bHRbM10gPSBuZXcgdW5pdC5yZXN1bHQoXCJSTURzdHJpbmcgKFxcXCJtZXNzYWdlIGRpZ2VzdFxcXCIpID0gNWQwNjg5ZWY0OWQyZmFlNTcyYjg4MWIxMjNhODVmZmEyMTU5NWYzNlwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKFJNRHN0cmluZyhcIm1lc3NhZ2UgZGlnZXN0XCIpKSA9PSBcIjVkMDY4OWVmNDlkMmZhZTU3MmI4ODFiMTIzYTg1ZmZhMjE1OTVmMzZcIik7XG5cdHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vLi4vdW5pdC5qcycpO1xuXG5cbnVuaXQucmVnaXN0ZXIoXCJTSEEqIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBOSVNUIEZJUFMgMTgwLTJcIiwgZnVuY3Rpb24oKSB7XG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG5cdFx0dXRpbCA9IG9wZW5wZ3AudXRpbCxcblx0XHRoYXNoID0gb3BlbnBncC5oYXNoO1xuXG5cdHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblx0XG5cdHJlc3VsdFswXSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTEgLSBhOTk5M2UzNjQ3MDY4MTZhYmEzZTI1NzE3ODUwYzI2YzljZDBkODlkID0gaGFzaC5zaGExKFxcXCJhYmNcXFwiKSBcIixcblx0XHRcdFwiYTk5OTNlMzY0NzA2ODE2YWJhM2UyNTcxNzg1MGMyNmM5Y2QwZDg5ZFwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTEoXCJhYmNcIikpKTtcblx0cmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMSAtIDg0OTgzZTQ0MWMzYmQyNmViYWFlNGFhMWY5NTEyOWU1ZTU0NjcwZjEgPSBoYXNoLnNoYTEoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjg0OTgzZTQ0MWMzYmQyNmViYWFlNGFhMWY5NTEyOWU1ZTU0NjcwZjFcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGExKFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcIikpKTtcblx0cmVzdWx0WzJdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMjI0IC0gMjMwOTdkMjIzNDA1ZDgyMjg2NDJhNDc3YmRhMjU1YjMyYWFkYmNlNGJkYTBiM2Y3ZTM2YzlkYTcgPSBoYXNoLnNoYTIyNChcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcIjIzMDk3ZDIyMzQwNWQ4MjI4NjQyYTQ3N2JkYTI1NWIzMmFhZGJjZTRiZGEwYjNmN2UzNmM5ZGE3XCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhMjI0KFwiYWJjXCIpKSk7XG5cdHJlc3VsdFszXSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTIyNCAtIDc1Mzg4YjE2NTEyNzc2Y2M1ZGJhNWRhMWZkODkwMTUwYjBjNjQ1NWNiNGY1OGIxOTUyNTIyNTI1ID0gaGFzaC5zaGEyMjQoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjc1Mzg4YjE2NTEyNzc2Y2M1ZGJhNWRhMWZkODkwMTUwYjBjNjQ1NWNiNGY1OGIxOTUyNTIyNTI1XCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhMjI0KFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcIikpKTtcblx0cmVzdWx0WzRdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMjU2IC0gYmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljYjQxMGZmNjFmMjAwMTVhZCA9IGhhc2guc2hhMjU2KFxcXCJhYmNcXFwiKSBcIixcblx0XHRcdFwiYmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljYjQxMGZmNjFmMjAwMTVhZFwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTI1NihcImFiY1wiKSkpO1xuXHRyZXN1bHRbNV0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEyNTYgLSAyNDhkNmE2MWQyMDYzOGI4ZTVjMDI2OTMwYzNlNjAzOWEzM2NlNDU5NjRmZjIxNjdmNmVjZWRkNDE5ZGIwNmMxID0gaGFzaC5zaGEyNTYoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjI0OGQ2YTYxZDIwNjM4YjhlNWMwMjY5MzBjM2U2MDM5YTMzY2U0NTk2NGZmMjE2N2Y2ZWNlZGQ0MTlkYjA2YzFcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGEyNTYoXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVwiKSkpO1xuXHRyZXN1bHRbNl0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEzODQgLSBjYjAwNzUzZjQ1YTM1ZThiYjVhMDNkNjk5YWM2NTAwNzI3MmMzMmFiMGVkZWQxNjMxYThiNjA1YTQzZmY1YmVkODA4NjA3MmJhMWU3Y2MyMzU4YmFlY2ExMzRjODI1YTcgPSBoYXNoLnNoYTM4NChcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcImNiMDA3NTNmNDVhMzVlOGJiNWEwM2Q2OTlhYzY1MDA3MjcyYzMyYWIwZWRlZDE2MzFhOGI2MDVhNDNmZjViZWQ4MDg2MDcyYmExZTdjYzIzNThiYWVjYTEzNGM4MjVhN1wiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTM4NChcImFiY1wiKSkpO1xuXHRyZXN1bHRbN10gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEzODQgLSAzMzkxZmRkZGZjOGRjNzM5MzcwN2E2NWIxYjQ3MDkzOTdjZjhiMWQxNjJhZjA1YWJmZThmNDUwZGU1ZjM2YmM2YjA0NTVhODUyMGJjNGU2ZjVmZTk1YjFmZTNjODQ1MmIgPSBzdHIzODQoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjMzOTFmZGRkZmM4ZGM3MzkzNzA3YTY1YjFiNDcwOTM5N2NmOGIxZDE2MmFmMDVhYmZlOGY0NTBkZTVmMzZiYzZiMDQ1NWE4NTIwYmM0ZTZmNWZlOTViMWZlM2M4NDUyYlwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTM4NChcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXCIpKSk7XHRcdFx0XHRcdFxuXHRyZXN1bHRbOF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEE1MTIgLSBkZGFmMzVhMTkzNjE3YWJhY2M0MTczNDlhZTIwNDEzMTEyZTZmYTRlODlhOTdlYTIwYTllZWVlNjRiNTVkMzlhMjE5Mjk5MmEyNzRmYzFhODM2YmEzYzIzYTNmZWViYmQ0NTRkNDQyMzY0M2NlODBlMmE5YWM5NGZhNTRjYTQ5ZiA9IGhhc2guc2hhNTEyKFxcXCJhYmNcXFwiKSBcIixcblx0XHRcdFwiZGRhZjM1YTE5MzYxN2FiYWNjNDE3MzQ5YWUyMDQxMzExMmU2ZmE0ZTg5YTk3ZWEyMGE5ZWVlZTY0YjU1ZDM5YTIxOTI5OTJhMjc0ZmMxYTgzNmJhM2MyM2EzZmVlYmJkNDU0ZDQ0MjM2NDNjZTgwZTJhOWFjOTRmYTU0Y2E0OWZcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGE1MTIoXCJhYmNcIikpKTtcblx0cmVzdWx0WzldID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBNTEyIC0gMjA0YThmYzZkZGE4MmYwYTBjZWQ3YmViOGUwOGE0MTY1N2MxNmVmNDY4YjIyOGE4Mjc5YmUzMzFhNzAzYzMzNTk2ZmQxNWMxM2IxYjA3ZjlhYTFkM2JlYTU3Nzg5Y2EwMzFhZDg1YzdhNzFkZDcwMzU0ZWM2MzEyMzhjYTM0NDUgPSBoYXNoLnNoYTUxMihcXFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcXFwiKSBcIixcblx0XHRcdFwiMjA0YThmYzZkZGE4MmYwYTBjZWQ3YmViOGUwOGE0MTY1N2MxNmVmNDY4YjIyOGE4Mjc5YmUzMzFhNzAzYzMzNTk2ZmQxNWMxM2IxYjA3ZjlhYTFkM2JlYTU3Nzg5Y2EwMzFhZDg1YzdhNzFkZDcwMzU0ZWM2MzEyMzhjYTM0NDVcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGE1MTIoXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVwiKSkpO1x0XHRcdFx0XHRcblx0cmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJGdW5jdGlvbmFsIHRlc3Rpbmcgb2Ygb3BlbnBncF9jcnlwdG9fKiBtZXRob2RzXCIsIGZ1bmN0aW9uKCkge1xuXHR2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLycpO1xuICB2YXIgdXRpbCA9IG9wZW5wZ3AudXRpbDtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIgUlNBcHViTVBJc3RycyA9IFtcbiAgICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDA4LDB4MDAsMHhhYywweDE1LDB4YjMsMHhkNiwweGQyLDB4MGYsMHhmMCwweDdhLDB4ZGQsMHgyMSwweGI3LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YmYsMHg2MSwweGZhLDB4Y2EsMHg5MywweDg2LDB4YzgsMHg1NSwweDVhLDB4NGIsMHhhNiwweGE0LDB4MWEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg2MCwweGEyLDB4M2EsMHgzNywweDA2LDB4MDgsMHhkOCwweDE1LDB4OGUsMHg4NSwweDQ1LDB4YWEsMHhiNyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDFkLDB4N2IsMHgwYiwweDczLDB4OTQsMHg1NSwweDBjLDB4NWMsMHhlYywweGMwLDB4MjIsMHg0YiwweGExLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NjQsMHgyMCwweDdkLDB4NGQsMHhhOCwweDk2LDB4MWEsMHg2NCwweDM4LDB4OTMsMHhjZCwweGVjLDB4NzMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg1ZCwweGY5LDB4ODksMHg4OCwweDI0LDB4M2QsMHg0OCwweGZmLDB4M2IsMHg4NywweDYyLDB4ZDAsMHg4NCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGVhLDB4ZmYsMHgzOSwweGI1LDB4MjcsMHg3MCwweGVhLDB4NGEsMHhiMiwweDJlLDB4OWQsMHhmMSwweDdjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MjMsMHhlYywweGY0LDB4NWUsMHhlYSwweDYxLDB4M2QsMHhlNSwweGQ4LDB4MGQsMHhmOSwweDU5LDB4NmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgyOCwweDAwLDB4ZWIsMHhjYiwweGM5LDB4NTUsMHgwMCwweDcyLDB4MzAsMHgxZiwweDY1LDB4OWQsMHhkNixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDE3LDB4NTgsMHg1ZiwweGE2LDB4NGEsMHhhMCwweGRkLDB4ZTEsMHg3NiwweGYyLDB4ZWYsMHgyMSwweDlmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ODQsMHhmYywweGFhLDB4NWIsMHg1MiwweDZlLDB4YzEsMHhhMiwweGI5LDB4YmQsMHhiOSwweGY0LDB4OWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0OSwweDkyLDB4ZjIsMHhhZiwweDU3LDB4ODYsMHhmMiwweGVmLDB4NzAsMHhiZiwweDUxLDB4NDAsMHhmZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGJmLDB4NTYsMHg1MSwweGU4LDB4MmMsMHhhMiwweDRmLDB4ZjgsMHhhNCwweGQ3LDB4MzYsMHgxOCwweDg1LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4Y2UsMHgwOSwweDBkLDB4YmMsMHg4ZCwweDY1LDB4NWUsMHg4YSwweDFkLDB4OTgsMHhiMCwweDRkLDB4OWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhjMSwweGNmLDB4ODIsMHhlMSwweGI3LDB4NDMsMHg1ZCwweDVhLDB4NzIsMHhjZCwweDU1LDB4ZDIsMHhmZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGIxLDB4YjQsMHg3OCwweGJmLDB4YTEsMHg3ZCwweGFjLDB4ZDksMHgxYiwweGM0LDB4ZmEsMHgzOSwweDM0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4OTIsMHgwOSwweGY5LDB4MDgsMHgyYSwweDZiLDB4OWQsMHgxNCwweDU2LDB4MTIsMHg0YywweGU5LDB4YTYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgyOSwweGMxLDB4ZjMsMHhhOSwweDBiLDB4ZmMsMHgzMSwweDc1LDB4NTgsMHg3NCwweDJhLDB4ODgsMHhhZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGVlLDB4YzksMHhhNCwweGNkLDB4MTUsMHhkYywweDFiLDB4OGQsMHg2NCwweGMxLDB4MzYsMHgxNywweGM0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4OGQsMHg1ZSwweDk5LDB4N2EsMHg1YiwweDlmLDB4MzksMHhkMCwweDAwLDB4NmUsMHhmOV0pLFxuICAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDAsMHgxMSwweDAxLDB4MDAsMHgwMV0pXTtcbiAgdmFyIFJTQXNlY01QSXN0cnMgPSBbXG4gICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwNywweGZlLDB4MjMsMHhmZiwweGNlLDB4NDUsMHg2YywweDYwLDB4NjUsMHg0MCwweDZlLDB4YWUsMHgzNSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDEwLDB4NTYsMHg2MCwweGVlLDB4YWIsMHhmYSwweDEwLDB4NDIsMHhiYSwweGM3LDB4MDQsMHhhZiwweDYzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4Y2QsMHgzZiwweDYyLDB4Y2EsMHg0YiwweGZhLDB4ZTEsMHhhOSwweDcwLDB4Y2QsMHgzNCwweDhiLDB4YzgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwZSwweGU0LDB4YzQsMHhiYSwweDgzLDB4MTcsMHg1ZiwweGE0LDB4YjgsMHhlYSwweDYwLDB4YzIsMHg0ZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDlhLDB4ZjIsMHhhOSwweDAzLDB4ZWIsMHhmNiwweGFhLDB4YzIsMHhiOCwweDhiLDB4NDMsMHgxMiwweGU5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZjcsMHg4OCwweGQyLDB4NWEsMHhhNiwweGFhLDB4MjMsMHg3MSwweDMxLDB4NzQsMHhkYiwweDE5LDB4MjAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxNSwweDQxLDB4MWIsMHg0MywweDY4LDB4NjIsMHhkOCwweGMwLDB4OTMsMHg5MSwweGU4LDB4ZmMsMHhiMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGE5LDB4OWEsMHg1MiwweDZjLDB4ZTAsMHhiZiwweDQzLDB4MDEsMHhhOCwweDM3LDB4MTQsMHgyOCwweGJmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MGIsMHgxNSwweDU2LDB4M2UsMHhhNSwweDc5LDB4YTAsMHhjNCwweDQyLDB4ODgsMHhlZSwweGViLDB4MWIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhmNCwweDdhLDB4NGEsMHg1OCwweDMxLDB4NTgsMHg4MSwweGQyLDB4M2UsMHhkZSwweDA3LDB4NjQsMHg5MixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGYwLDB4NjAsMHhkMywweDlhLDB4MjksMHhjYSwweGM2LDB4NjcsMHg3NSwweDA3LDB4Y2EsMHg5MiwweDM5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NTYsMHhmNiwweDExLDB4ODQsMHhiYSwweDZkLDB4NGIsMHhlNiwweDZmLDB4NjYsMHhjMiwweDE3LDB4ZWIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0NiwweDY5LDB4MWMsMHhiYiwweGRmLDB4YzAsMHgzOCwweDAwLDB4ZDYsMHgwMSwweGU2LDB4NzAsMHg5ZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDRiLDB4OWIsMHg3MCwweGVkLDB4NWMsMHhiOCwweGNmLDB4ZTgsMHg2OCwweDcxLDB4YmUsMHgyNCwweDZkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YjEsMHhhMywweDEzLDB4Y2MsMHhmMSwweGJjLDB4NjcsMHhkYywweGUwLDB4NjksMHgwOSwweDgyLDB4M2MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgzYiwweDBmLDB4MTQsMHg5OCwweDQ4LDB4MzAsMHhiMiwweDcwLDB4YzYsMHg5ZSwweGZhLDB4NDYsMHg4ZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGYxLDB4YzAsMHg2NSwweDhlLDB4YzYsMHhhZSwweGRjLDB4NDcsMHg5MSwweDEzLDB4MWUsMHhkNiwweDRhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZjIsMHhhZCwweGRhLDB4YzIsMHhjNywweDM5LDB4NzgsMHg5OSwweGRlLDB4NTcsMHgxNCwweDQ1LDB4N2YsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgzMiwweDM4LDB4YTMsMHg0NCwweDBmLDB4ZTcsMHgzOSwweDRjLDB4NmYsMHgwZiwweDMyLDB4N2UsMHhmMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDVjLDB4ODQsMHg5NywweGRkLDB4YTAsMHgwYywweDg3LDB4NjYsMHg3ZCwweDc1LDB4NzldKSxcbiAgICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDA0LDB4MDAsMHhjMiwweGJjLDB4NzEsMHhmNywweDQxLDB4NGEsMHgwOSwweDY2LDB4NzAsMHgwMiwweDY4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4OGIsMHhlYiwweGUyLDB4MzQsMHhkMSwweDEyLDB4ODMsMHg5MywweDc1LDB4ZTksMHg3MSwweDMyLDB4ZTIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhlZCwweDE4LDB4NmYsMHg4ZSwweDNhLDB4ZmYsMHgyMiwweDcwLDB4MjgsMHgwMSwweGJmLDB4NGEsMHgzOSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDQxLDB4YmIsMHgzYywweDRhLDB4YmMsMHhiOCwweDEzLDB4ZmMsMHgxNCwweGY2LDB4NzEsMHhhMSwweDQ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MWMsMHgwMiwweGExLDB4NzMsMHg4MSwweGNjLDB4YTAsMHgzNSwweDAyLDB4M2UsMHg5NywweGI1LDB4YzQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg5NCwweDMzLDB4ZjEsMHhkMSwweGRmLDB4MTQsMHgzZiwweGZiLDB4OGYsMHhiOSwweDc1LDB4NzAsMHhkYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDc0LDB4M2YsMHgwNywweDM1LDB4OGYsMHg1MywweGFhLDB4YjIsMHhkNiwweDg4LDB4NTEsMHg3MSwweDRlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MDEsMHgyNCwweGVjLDB4N2QsMHhjYSwweGY2LDB4YTIsMHhiMywweGJiLDB4YWQsMHgyZSwweDYwLDB4ZmIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxYywweGVlLDB4NDksMHhkMCwweDRlLDB4NWMsMHhlMywweDFmLDB4ODgsMHg0OCwweGU0LDB4NjgsMHgxNCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDNkLDB4NzEsMHhiYSwweGQ3LDB4NGQsMHgzNSwweDEwLDB4ODYsMHgzNywweDYyLDB4ZTAsMHhhNSwweDBiXSksXG4gICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwNCwweDAwLDB4ZTIsMHgzOCwweGY5LDB4YzgsMHgzYywweGQxLDB4Y2YsMHg2MiwweDkzLDB4YzMsMHg3NyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDc2LDB4OTcsMHg0NCwweGU4LDB4YzgsMHhjYSwweDkzLDB4OWEsMHhlZiwweGYwLDB4NjMsMHg3NiwweDI1LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4M2IsMHgxYywweDQ2LDB4ZmYsMHg5MCwweDEzLDB4OTEsMHgxNSwweDk3LDB4N2UsMHg4OCwweDk1LDB4ZDQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg3ZiwweDJmLDB4NTIsMHg2ZSwweDBkLDB4NTUsMHg1NSwweDJlLDB4ZjEsMHg1OCwweDVjLDB4N2UsMHg1NixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGQ0LDB4NDgsMHhhYSwweGRiLDB4OGMsMHg0NCwweDRkLDB4ODQsMHg2OSwweDMzLDB4ODcsMHgwNywweGIyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4N2UsMHhmNSwweGEwLDB4NjAsMHhmYiwweDczLDB4NTksMHg0NiwweDI5LDB4Y2IsMHgxZSwweDNmLDB4N2MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgyZiwweGE2LDB4NTMsMHhlMywweDhjLDB4ZWYsMHhkNSwweGViLDB4YmIsMHhjOCwweDlhLDB4OGUsMHg2NixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDRhLDB4NDcsMHgyZiwweGUxLDB4YmEsMHg1ZSwweDMyLDB4ZDQsMHg1MiwweDA0LDB4ODgsMHg5ZCwweDYzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4M2UsMHhiYSwweDcxLDB4MmQsMHhmNywweDYxLDB4ZDUsMHhmYywweDI2LDB4YmYsMHhkOCwweDYwLDB4OTIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg3YiwweDk0LDB4ZjgsMHg2ZiwweDNkLDB4OTcsMHgwYiwweDBjLDB4NTIsMHg4YywweGIzLDB4YjYsMHg4Yl0pLFxuICAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDQsMHgwMCwweGI3LDB4YzUsMHg0ZCwweDZlLDB4MmYsMHhkZCwweGVmLDB4ZWMsMHgwNywweDcwLDB4YTIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg3YywweDFjLDB4OWQsMHg4ZSwweDY2LDB4NjAsMHg3YywweDYxLDB4MWUsMHg0NSwweGU5LDB4ZGMsMHg4MixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDJmLDB4YzUsMHg3ZSwweDFhLDB4YzYsMHhkMCwweDkyLDB4YzUsMHgyMiwweDliLDB4OWEsMHhmYiwweDczLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4OTUsMHg5OSwweGYyLDB4N2MsMHhkYiwweDJhLDB4OTMsMHg3YiwweDVhLDB4MjksMHg3MywweDI0LDB4MTYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0MSwweDQ5LDB4YjUsMHhmMiwweDVmLDB4YmUsMHhlNywweDY0LDB4NGQsMHhkYSwweDUyLDB4OWUsMHhjMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDQxLDB4NDAsMHg1ZSwweDAzLDB4OTIsMHg4ZCwweDM5LDB4OTUsMHgxZiwweDY4LDB4OWYsMHgwMCwweDJlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MGMsMHg2ZiwweGNmLDB4ZDksMHg2ZCwweDY4LDB4ZjcsMHgwMCwweDRmLDB4MGUsMHhjOCwweDBiLDB4ZmEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg1MSwweGUwLDB4MjIsMHhmMCwweGZmLDB4YTcsMHg0MiwweGQ0LDB4ZGUsMHgwYiwweDQ3LDB4OGYsMHgyYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGY1LDB4NGQsMHgwNCwweDMyLDB4OTEsMHg4OSwweDRiLDB4MGUsMHgwNSwweDhkLDB4NzAsMHhmOSwweGJiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZTcsMHhkNiwweDc2LDB4ZWEsMHgwZSwweDFhLDB4OTAsMHgzMCwweGY1LDB4OTgsMHgwMSwweGM1LDB4NzNdKV07XG4gIFxuICB2YXIgRFNBcHViTVBJc3RycyA9IFtcbiAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDgsMHgwMCwweGE4LDB4ODUsMHg1YywweDI4LDB4MDUsMHg5NCwweDAzLDB4YmUsMHgwNywweDZjLDB4MTMsMHgzZSwweDY1LFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhmYiwweGI1LDB4ZTEsMHg5OSwweDdjLDB4ZmEsMHg4NCwweGUzLDB4YWMsMHg0NywweGE1LDB4YzQsMHg0NiwweGQ4LDB4NWYsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDQ0LDB4ZTksMHhjMSwweDZiLDB4NjksMHhmNywweDEwLDB4NzYsMHg0OSwweGE3LDB4MjUsMHg4NSwweGY0LDB4MWIsMHhlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4YzYsMHg2MCwweGM0LDB4NWIsMHhhYSwweGQ0LDB4ODcsMHhkNiwweDhmLDB4OTIsMHg1NiwweDdkLDB4NTUsMHgzZiwweDQ1LFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhhZSwweDEyLDB4NzMsMHhkYSwweDI5LDB4OGMsMHhiYSwweDMyLDB4Y2MsMHhkNywweGE0LDB4ZDAsMHgyNCwweGIwLDB4N2MsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGQ4LDB4MGMsMHgzYSwweDkxLDB4NmYsMHg5OCwweDQwLDB4OWMsMHg5YSwweGE4LDB4Y2MsMHgyOCwweDI3LDB4OTUsMHgwYixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4ZTEsMHg1YiwweGI5LDB4M2IsMHgxYywweDFjLDB4ZDIsMHhlYywweGFiLDB4MDcsMHgyNSwweDhkLDB4N2EsMHgyYSwweDJiLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHgxNiwweDE0LDB4ZTgsMHhkYSwweDcxLDB4ZDIsMHhhYiwweGJhLDB4ODUsMHgxNCwweDBkLDB4YzUsMHhlMCwweDg4LDB4ZWIsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGE1LDB4ZTIsMHhkNSwweDQ4LDB4M2QsMHg3NCwweDBjLDB4NDEsMHhlYiwweGZkLDB4YjYsMHg0ZSwweGY5LDB4MmMsMHg4MixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MTcsMHhkZCwweDY0LDB4MWUsMHgxOSwweDM5LDB4YTMsMHg3ZiwweGY5LDB4MDAsMHhjZCwweDliLDB4ZGEsMHgyZSwweGJkLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHg3MSwweDEyLDB4ZGYsMHgwZCwweDdjLDB4MGEsMHg2YiwweDJkLDB4MjEsMHgzYiwweDljLDB4NjYsMHg5MywweDRhLDB4MWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDkwLDB4NzksMHhkMywweDVhLDB4NWIsMHhlNSwweGI5LDB4OTQsMHgxYiwweGU2LDB4NDcsMHg5OSwweDA2LDB4OTgsMHhkOCxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MmEsMHhlNSwweGUyLDB4YTYsMHg5NSwweDZhLDB4MDcsMHhjOCwweGFjLDB4N2MsMHhlOSwweGZjLDB4YTIsMHg2YSwweDE2LFxuICAgICAgICAgICAgICAgICAgICAgICAgMHgyYywweDk0LDB4OTgsMHhiZCwweDkxLDB4MGEsMHg3YywweDdjLDB4MmMsMHhiOSwweDdlLDB4YTIsMHg1MSwweDhiLDB4NDUsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDFkLDB4NDYsMHgzNCwweGE4LDB4NTIsMHgyYiwweGRkLDB4ZDksMHhhOCwweGJjLDB4NDYsMHg3OCwweDY2LDB4ZTEsMHg3MixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MTEsMHhmMSwweGNiLDB4MWEsMHhiNiwweDRlLDB4MDUsMHg1NCwweGY3LDB4ZTksMHhiZSwweDRjLDB4MjUsMHg1OSwweDA4LFxuICAgICAgICAgICAgICAgICAgICAgICAgMHg5ZiwweGY4LDB4ZWEsMHgyNSwweDk3LDB4MzMsMHhkNiwweGM5LDB4MGYsMHg1OSwweDBlLDB4ZmQsMHg5ZiwweGRjLDB4ZTIsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGMwLDB4Y2YsMHgyZl0pLFxuICAgICAgdXRpbC5iaW4yc3RyKFsweDAxLDB4MDAsMHhlMSwweDcyLDB4MmMsMHhkMCwweGJiLDB4MWEsMHg0ZiwweGI2LDB4YjYsMHg5NSwweDc3LDB4NzEsMHgyZSxcbiAgICAgICAgICAgICAgICAgICAgMHgwMSwweDQ4LDB4M2UsMHgzNSwweDU0LDB4NjQsMHgyYiwweGVkLDB4NDAsMHg1ZiwweDY1LDB4MGMsMHg1NywweDI4LDB4NWYsXG4gICAgICAgICAgICAgICAgICAgIDB4ZmQsMHhmZCwweGZmLDB4ZDddKSxcbiAgICAgIHV0aWwuYmluMnN0cihbMHgwNywweGZmLDB4NWQsMHg5ZiwweGM0LDB4YjUsMHg2MywweDI1LDB4OWQsMHg3MiwweDg4LDB4ZTUsMHg1MywweDQ2LDB4OTgsXG4gICAgICAgICAgICAgICAgICAgIDB4ZTMsMHhlOSwweDYyLDB4Y2IsMHgwYywweGExLDB4YjcsMHg3NSwweDlmLDB4MTgsMHg0MSwweDk0LDB4MzIsMHgyOCwweDI5LFxuICAgICAgICAgICAgICAgICAgICAweDZkLDB4NjksMHhlMCwweDNmLDB4N2QsMHg3YiwweDJiLDB4MDYsMHg1YSwweDMzLDB4NWMsMHhkNCwweDM2LDB4MzEsMHgwOSxcbiAgICAgICAgICAgICAgICAgICAgMHg1NCwweDg1LDB4OWQsMHhiOCwweDIwLDB4ZmUsMHhkYSwweGZjLDB4Y2QsMHgxZiwweGIxLDB4MmMsMHgxNSwweDA4LDB4OWQsXG4gICAgICAgICAgICAgICAgICAgIDB4MzIsMHg1MywweDJmLDB4YzEsMHg0MiwweDIyLDB4NjksMHhmZiwweDY3LDB4MmUsMHgzOSwweDk3LDB4NTAsMHg2NiwweDM5LFxuICAgICAgICAgICAgICAgICAgICAweGRhLDB4Y2YsMHhmZCwweDY0LDB4NmYsMHg5MSwweDA1LDB4NjQsMHgzNywweGM1LDB4MDcsMHgyNCwweGFhLDB4NDAsMHhhMCxcbiAgICAgICAgICAgICAgICAgICAgMHg3NSwweDgyLDB4MWQsMHg5NywweDk2LDB4MTIsMHhmMSwweGJkLDB4OWUsMHgwOSwweDI2LDB4M2MsMHg5NywweDVkLDB4NTcsXG4gICAgICAgICAgICAgICAgICAgIDB4YjgsMHg1YywweDdkLDB4ODksMHgwMywweDgyLDB4Y2QsMHg0MCwweGU1LDB4MDMsMHhlNiwweDRhLDB4ZmIsMHhiYywweGQyLFxuICAgICAgICAgICAgICAgICAgICAweGVmLDB4N2EsMHg4OSwweDAyLDB4MDgsMHhjOCwweDUyLDB4ZmEsMHg5NywweDc0LDB4NjYsMHgzMiwweGFlLDB4YTYsMHg1MixcbiAgICAgICAgICAgICAgICAgICAgMHg0YiwweGVmLDB4NWYsMHhjZSwweDkxLDB4MjMsMHgzZiwweGFiLDB4OWQsMHg2MiwweDIxLDB4ZWYsMHg0OCwweDZkLDB4MDcsXG4gICAgICAgICAgICAgICAgICAgIDB4NWEsMHhiYSwweGRmLDB4MDAsMHg5MSwweDU0LDB4ZWEsMHg1YywweGZhLDB4NGIsMHgxNiwweDI4LDB4MWEsMHhjZSwweDQ4LFxuICAgICAgICAgICAgICAgICAgICAweGI3LDB4NWMsMHg1MCwweGE1LDB4NTksMHhhNCwweGI0LDB4YWYsMHgxZiwweGViLDB4OGQsMHg1OCwweDNmLDB4MGEsMHhhNSxcbiAgICAgICAgICAgICAgICAgICAgMHg5NywweDJiLDB4NTEsMHg1NiwweGU4LDB4ODgsMHhmNiwweDA3LDB4YmMsMHhkZiwweGZhLDB4MmIsMHg3YiwweDg4LDB4ZTAsXG4gICAgICAgICAgICAgICAgICAgIDB4NDYsMHhjOCwweDdhLDB4M2UsMHhkOCwweDgwLDB4ZGIsMHg0ZCwweDg3LDB4NjEsMHg0ZiwweDY0LDB4Y2QsMHhlYiwweGU4LFxuICAgICAgICAgICAgICAgICAgICAweDBkLDB4ODYsMHgxNiwweGNjLDB4ZGQsMHg2YywweDc2LDB4NjYsMHhjMSwweDczLDB4YjcsMHgwOCwweDk4LDB4ODksMHgyZixcbiAgICAgICAgICAgICAgICAgICAgMHg2NywweDY5LDB4ZDEsMHhmYywweDk3LDB4NGQsMHhhMiwweGNlLDB4YWQsMHhiYiwweDZmLDB4YWIsMHhhNSwweGQ2LDB4MTgsXG4gICAgICAgICAgICAgICAgICAgIDB4YjMsMHgxYSwweDk2LDB4MDIsMHhiYywweDMxLDB4NDIsMHhhMiwweGFkLDB4NzcsMHhlOCwweGUyLDB4NGMsMHg5OSwweGY5LFxuICAgICAgICAgICAgICAgICAgICAweGRkLDB4YmUsMHhjZF0pLFxuICAgICAgdXRpbC5iaW4yc3RyKFsweDA3LDB4ZmYsMHg1ZCwweGZlLDB4OWMsMHg5OCwweGVmLDB4M2EsMHhhNiwweDQ5LDB4ZjAsMHgxMCwweDY3LDB4NzksMHgyYSxcbiAgICAgICAgICAgICAgICAgICAgMHg5ZCwweDc5LDB4NDMsMHgwNiwweGE0LDB4YTgsMHg2YiwweDFhLDB4NmQsMHgxZiwweDc3LDB4NmUsMHgwMCwweDMxLDB4YjksXG4gICAgICAgICAgICAgICAgICAgIDB4ZWQsMHhjOSwweDY2LDB4ZmYsMHhmMSwweDIxLDB4MzIsMHhmYSwweDYyLDB4NDMsMHhjZCwweDk3LDB4ZDMsMHgzZCwweGFmLFxuICAgICAgICAgICAgICAgICAgICAweGI0LDB4MjksMHgyOSwweDI2LDB4NGUsMHgxYywweGEwLDB4YWQsMHgxYywweDA3LDB4MjgsMHgzZiwweGU1LDB4NDMsMHgxMCxcbiAgICAgICAgICAgICAgICAgICAgMHhiYSwweGI0LDB4MDgsMHhlMCwweGRjLDB4YTIsMHhjMywweDViLDB4MWYsMHhiZCwweDk0LDB4YzcsMHg0MywweGU1LDB4ZjIsXG4gICAgICAgICAgICAgICAgICAgIDB4MTcsMHgzMCwweDU0LDB4N2YsMHgxNCwweGJlLDB4ZjQsMHhiZCwweDkxLDB4M2IsMHhlNCwweDM2LDB4YTQsMHg1MCwweDViLFxuICAgICAgICAgICAgICAgICAgICAweDM3LDB4ODksMHg1ZSwweGNjLDB4YzcsMHg3NCwweDU0LDB4MzIsMHgyMCwweDA5LDB4NjMsMHg5OCwweGI3LDB4ZDksMHhhZixcbiAgICAgICAgICAgICAgICAgICAgMHg3ZiwweGIwLDB4NmMsMHgyNywweDQzLDB4ZmUsMHg1MiwweGU2LDB4MWEsMHg4OCwweDU5LDB4MjUsMHhmYywweGViLDB4NDMsXG4gICAgICAgICAgICAgICAgICAgIDB4NTAsMHhjNywweDY1LDB4NDMsMHhjMSwweDg2LDB4NzMsMHg1OCwweDUzLDB4M2EsMHhjZiwweDdhLDB4YTMsMHgxZCwweDU2LFxuICAgICAgICAgICAgICAgICAgICAweGM4LDB4NGEsMHg4MCwweDcwLDB4YjcsMHhiZiwweGYyLDB4YTMsMHhlYywweGU4LDB4NzcsMHgwNSwweDMzLDB4MDksMHg5ZCxcbiAgICAgICAgICAgICAgICAgICAgMHhhYSwweGNhLDB4YTAsMHhlMSwweDY0LDB4NjQsMHg2ZiwweDc2LDB4OTksMHg0MSwweDc1LDB4NzgsMHg5MCwweGY2LDB4ZTcsXG4gICAgICAgICAgICAgICAgICAgIDB4MjMsMHhlNiwweGVjLDB4NTAsMHhlNSwweDk5LDB4YTgsMHgzZSwweDFhLDB4NGIsMHhjOSwweDg4LDB4NTgsMHg2NiwweGFlLFxuICAgICAgICAgICAgICAgICAgICAweDFhLDB4NTMsMHg1ZSwweGU0LDB4YjcsMHg4NiwweGNmLDB4YTYsMHhlNSwweGFkLDB4YjQsMHg4MCwweGEwLDB4ZjEsMHgwZCxcbiAgICAgICAgICAgICAgICAgICAgMHg5NiwweGI4LDB4NDEsMHhkMCwweDA3LDB4OWEsMHgyMSwweDhkLDB4NTAsMHg3ZiwweDRmLDB4NzMsMHgxMywweGEyLDB4ZTIsXG4gICAgICAgICAgICAgICAgICAgIDB4MDIsMHgwNywweGMzLDB4YTMsMHgwZiwweDA5LDB4MTgsMHg3ZiwweGY3LDB4NmIsMHg5MCwweDcwLDB4YzAsMHhmOSwweDBjLFxuICAgICAgICAgICAgICAgICAgICAweDY3LDB4OGQsMHg5ZCwweDE0LDB4YjYsMHg5ZCwweDMyLDB4ODIsMHhkMCwweGI1LDB4YzYsMHg1NywweGYwLDB4OTEsMHhkOSxcbiAgICAgICAgICAgICAgICAgICAgMHhjMywweDI2LDB4YWUsMHg5ZiwweGE5LDB4NjcsMHg0OSwweDk2LDB4NWMsMHgwNywweDNlLDB4NDcsMHg1YywweGVkLDB4NjAsXG4gICAgICAgICAgICAgICAgICAgIDB4MDcsMHhhYywweDZhXSldO1xuICB2YXIgRFNBc2VjTVBJc3RycyA9IFt1dGlsLmJpbjJzdHIoWzB4MDEsMHgwMCwweDliLDB4NTgsMHhhOCwweGY0LDB4MDQsMHhiMSwweGQ1LDB4MTQsMHgwOSwweGUxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhlMSwweGExLDB4OGEsMHgwYiwweGEzLDB4YzMsMHhhMywweDY2LDB4YWEsMHgyNywweDk5LDB4NTAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAweDFjLDB4NGQsMHhiYSwweDI0LDB4ZWUsMHhkZiwweGRmLDB4YjgsMHg4ZSwweDhlXSldO1xuICAgICAgICAgICAgXG4gIHZhciBFbGdhbWFscHViTVBJc3RycyA9IFxuICAgICAgICAgIFt1dGlsLmJpbjJzdHIoWzB4MDgsMHgwMCwweGVhLDB4Y2MsMHhiZSwweGUyLDB4ZTQsMHg1YSwweDUxLDB4MTgsMHg5MywweGExLDB4MTIsMHgyZixcbiAgICAgICAgICAgICAgICAgICAgIDB4MDAsMHg5OSwweDQyLDB4ZDgsMHg1YywweDFjLDB4MmYsMHhiNiwweDNjLDB4ZDksMHg5NCwweDYxLDB4YjQsMHg1NSxcbiAgICAgICAgICAgICAgICAgICAgIDB4OGQsMHg0ZSwweDczLDB4ZTYsMHg2OSwweGJjLDB4MWQsMHgzMywweGUzLDB4MmQsMHg5MSwweDIzLDB4NjksMHg5NSxcbiAgICAgICAgICAgICAgICAgICAgIDB4OTgsMHhkNywweDE4LDB4NWEsMHhhZiwweGE3LDB4OTMsMHhjNiwweDA1LDB4OTMsMHgzYSwweGM3LDB4ZWEsMHhkMCxcbiAgICAgICAgICAgICAgICAgICAgIDB4YjEsMHhhOSwweGM3LDB4YWIsMHg0MSwweDg5LDB4YzgsMHgzOCwweDk5LDB4ZGMsMHgxYSwweDU3LDB4MzUsMHgxYSxcbiAgICAgICAgICAgICAgICAgICAgIDB4MjcsMHg2MiwweDQwLDB4NzEsMHg5ZiwweDM2LDB4MWMsMHg2ZCwweDE4LDB4MWMsMHg5MywweGY3LDB4YmEsMHgzNSxcbiAgICAgICAgICAgICAgICAgICAgIDB4MDYsMHhlZCwweDMwLDB4YjgsMHhkOSwweDhhLDB4N2MsMHgwMywweGFmLDB4YmEsMHg0MCwweDFmLDB4NjIsMHhmMSxcbiAgICAgICAgICAgICAgICAgICAgIDB4NmQsMHg4NywweDJjLDB4YTYsMHgyZSwweDQ2LDB4YjAsMHhhYSwweGJjLDB4YmMsMHg5MywweGZhLDB4OWIsMHg0NyxcbiAgICAgICAgICAgICAgICAgICAgIDB4M2YsMHg3MCwweDFmLDB4MmEsMHhjMiwweDY2LDB4OWMsMHg3YywweDY5LDB4ZTAsMHgyYiwweDA1LDB4ZWUsMHhiNyxcbiAgICAgICAgICAgICAgICAgICAgIDB4YTcsMHg3ZiwweGYzLDB4MjEsMHg0OCwweDg1LDB4YzIsMHg5NSwweDVmLDB4NmYsMHgxZSwweGIzLDB4OWIsMHg5NyxcbiAgICAgICAgICAgICAgICAgICAgIDB4ZjgsMHgxNCwweGMzLDB4ZmYsMHg0ZCwweDk3LDB4MjUsMHgyOSwweDk0LDB4NDEsMHg0YiwweDkwLDB4ZDgsMHhiYSxcbiAgICAgICAgICAgICAgICAgICAgIDB4NzEsMHg0NSwweDRiLDB4MWUsMHgyZiwweGNhLDB4ODIsMHg1ZiwweDU2LDB4NzcsMHhlOSwweGQzLDB4ODgsMHg1ZCxcbiAgICAgICAgICAgICAgICAgICAgIDB4OGIsMHhlYywweDkyLDB4OGIsMHg4YSwweDIzLDB4ODgsMHgwNSwweGY4LDB4MmMsMHhhOCwweGYxLDB4NzAsMHg3NixcbiAgICAgICAgICAgICAgICAgICAgIDB4ZTcsMHhiZiwweDc1LDB4YTgsMHgzMSwweDE0LDB4OGUsMHg3NiwweGM4LDB4MDEsMHhhNiwweDI1LDB4MjcsMHg0OSxcbiAgICAgICAgICAgICAgICAgICAgIDB4YWYsMHhkYywweGY0LDB4ZjYsMHhmNCwweGNlLDB4OTAsMHg4NCwweDE1LDB4MmIsMHg0ZCwweGIzLDB4Y2MsMHg3NyxcbiAgICAgICAgICAgICAgICAgICAgIDB4ZGIsMHg2NSwweDcxLDB4NzUsMHhkMywweDAwLDB4MWQsMHgyMiwweGM1LDB4NDIsMHgyZiwweDUxLDB4ZmEsMHg3YixcbiAgICAgICAgICAgICAgICAgICAgIDB4ZWIsMHg2ZSwweDAzLDB4ZDksMHg0MSwweGRkLDB4MmQsMHgxYSwweGRkLDB4MDcsMHg3NCwweDhiLDB4YjcsMHhhMixcbiAgICAgICAgICAgICAgICAgICAgIDB4ZmEsMHhiMiwweDU5LDB4MGUsMHgwZSwweDk0LDB4N2MsMHgwMCwweGFkLDB4OTUsMHgyMywweDQyLDB4OTEsMHgxOCxcbiAgICAgICAgICAgICAgICAgICAgIDB4NGMsMHg5NywweGYxLDB4MjcsMHg2MiwweDc3XSksXG4gICAgICAgdXRpbC5iaW4yc3RyKFsweDAwLDB4MDMsMHgwNV0pLFxuICAgICAgIHV0aWwuYmluMnN0cihbMHgwNywweGZmLDB4NTcsMHgxOSwweDc2LDB4ZmMsMHgwOSwweDZhLDB4N2EsMHhmNywweGJhLDB4YjIsMHg0MiwweGJmLFxuICAgICAgICAgICAgICAgICAgICAgMHhjZCwweDJiLDB4YzEsMHgxYSwweDc5LDB4MjUsMHg4YywweGFkLDB4ZjQsMHgzYSwweDBhLDB4N2EsMHg5YiwweDRjLFxuICAgICAgICAgICAgICAgICAgICAgMHg0NiwweDNjLDB4ZTAsMHg0ZiwweGNjLDB4NmUsMHhlNSwweDdhLDB4MzMsMHgzYSwweDRlLDB4ODAsMHhjYiwweGQzLFxuICAgICAgICAgICAgICAgICAgICAgMHg2MiwweGQ3LDB4OGYsMHhlMiwweGM4LDB4YjAsMHhkMCwweGNiLDB4NDksMHhjOSwweDllLDB4MmQsMHg5NywweDE2LFxuICAgICAgICAgICAgICAgICAgICAgMHgzYSwweDdkLDB4YjEsMHhlMSwweGQzLDB4ZDksMHhkNywweDNmLDB4MjAsMHg2MCwweGUzLDB4M2UsMHg3NywweGVhLFxuICAgICAgICAgICAgICAgICAgICAgMHgwYywweGU0LDB4N2IsMHhmMCwweDM5LDB4MWEsMHgwZCwweGQ5LDB4OGYsMHg3MywweGQyLDB4NTEsMHhiOCwweDBjLFxuICAgICAgICAgICAgICAgICAgICAgMHgwZSwweDE1LDB4MWUsMHhhZCwweDdjLDB4ZDgsMHg5ZCwweDc0LDB4NmUsMHhhMiwweDE3LDB4NmIsMHg1OCwweDE0LFxuICAgICAgICAgICAgICAgICAgICAgMHgyYiwweGI3LDB4YWQsMHg4YSwweGQ3LDB4NjYsMHhjMCwweGRmLDB4ZWEsMHgyZCwweGZjLDB4YzQsMHg2ZSwweDY4LFxuICAgICAgICAgICAgICAgICAgICAgMHhiNiwweDRjLDB4OWEsMHgxNiwweGE0LDB4M2QsMHhjMiwweDI2LDB4MGMsMHhiNywweGQ0LDB4MTMsMHg3YiwweDIyLFxuICAgICAgICAgICAgICAgICAgICAgMHhmZCwweDg0LDB4ZDcsMHgwZiwweGRjLDB4NDIsMHg3NSwweDA1LDB4ODUsMHgyOSwweDAwLDB4MzEsMHgxZCwweGVjLFxuICAgICAgICAgICAgICAgICAgICAgMHg0ZSwweDIyLDB4OGIsMHhmNiwweDM3LDB4ODMsMHg0NSwweGU1LDB4YjMsMHgzMSwweDYxLDB4MmMsMHgwMiwweGExLFxuICAgICAgICAgICAgICAgICAgICAgMHhjNiwweDlkLDB4ZWEsMHhiYSwweDNkLDB4OGEsMHhhYiwweDBmLDB4NjEsMHg1ZSwweDE0LDB4NjQsMHg2OSwweDFlLFxuICAgICAgICAgICAgICAgICAgICAgMHhhMCwweDE1LDB4NDgsMHg4NiwweGU1LDB4MTEsMHgwNiwweGU4LDB4ZGUsMHgzNCwweGM3LDB4YTcsMHgzZCwweDM1LFxuICAgICAgICAgICAgICAgICAgICAgMHhkMSwweDc2LDB4YzIsMHhiZSwweDAxLDB4ODIsMHg2MSwweDhkLDB4ZTcsMHg3ZSwweDI4LDB4MWQsMHg0ZSwweDhjLFxuICAgICAgICAgICAgICAgICAgICAgMHhiOSwweGU4LDB4N2UsMHhhNCwweDVmLDB4YTYsMHgzYSwweDllLDB4NWQsMHhhYywweGYzLDB4NjAsMHgyMiwweDE0LFxuICAgICAgICAgICAgICAgICAgICAgMHhkNSwweGQ1LDB4YmUsMHgxZiwweGYwLDB4MTksMHhlNiwweDgxLDB4ZmQsMHg1ZCwweGUxLDB4ZjgsMHg3NiwweDVmLFxuICAgICAgICAgICAgICAgICAgICAgMHhlMywweGRhLDB4YmEsMHgxOSwweGYzLDB4Y2IsMHgxMCwweGEwLDB4NmIsMHhkMCwweDJkLDB4YmUsMHg0MCwweDQyLFxuICAgICAgICAgICAgICAgICAgICAgMHg3YiwweDliLDB4MTUsMHhhNCwweDJkLDB4ZWMsMHhjZiwweDA5LDB4ZDYsMHhlMywweDkyLDB4YzMsMHg4ZCwweDY1LFxuICAgICAgICAgICAgICAgICAgICAgMHg2YiwweDYwLDB4OTcsMHhkYSwweDZiLDB4Y2FdKV07XG5cbiAgdmFyIEVsZ2FtYWxzZWNNUElzdHJzID0gW1xuICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwMSwweDUyLDB4MDIsMHg4MCwweDg3LDB4ZjYsMHhlNCwweDQ5LDB4ZDcsMHgyZSwweDNlLDB4ZmUsMHg2MCwweGI5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhhMywweDJhLDB4ZjAsMHg2NywweDU4LDB4ZTksMHhmNiwweDQ3LDB4ODMsMHhkZSwweDdlLDB4ZmIsMHhiYiwweGJkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhkZiwweDQ4LDB4MTIsMHgxYiwweDA2LDB4N2QsMHgxMywweGJjLDB4M2IsMHg0OSwweGY5LDB4ODYsMHhkNCwweDUzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhlZCwweDJkLDB4NjhdKV07XG5cbiAgdmFyIFJTQXB1Yk1QSXMgPSBbXTtcbiAgdmFyIGk7XG4gIGZvciAoaSA9IDA7IGkgPCAyOyBpKyspIHtcbiAgICBSU0FwdWJNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgUlNBcHViTVBJc1tpXS5yZWFkKFJTQXB1Yk1QSXN0cnNbaV0sMCxSU0FwdWJNUElzdHJzW2ldLmxlbmd0aCk7XG4gIH1cblxuICB2YXIgUlNBc2VjTVBJcyA9IFtdO1xuICBmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgUlNBc2VjTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIFJTQXNlY01QSXNbaV0ucmVhZChSU0FzZWNNUElzdHJzW2ldLDAsUlNBc2VjTVBJc3Ryc1tpXS5sZW5ndGgpO1xuICB9XG4gICAgXG4gIHZhciBEU0FzZWNNUElzID0gW107XG4gIGZvciAoaSA9IDA7IGkgPCAxOyBpKyspIHtcbiAgICBEU0FzZWNNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRFNBc2VjTVBJc1tpXS5yZWFkKERTQXNlY01QSXN0cnNbaV0sMCxEU0FzZWNNUElzdHJzW2ldLmxlbmd0aCk7XG4gIH1cbiAgICBcbiAgdmFyIERTQXB1Yk1QSXMgPSBbXTtcbiAgZm9yIChpID0gMDsgaSA8IDQ7IGkrKykge1xuICAgIERTQXB1Yk1QSXNbaV0gPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgICBEU0FwdWJNUElzW2ldLnJlYWQoRFNBcHViTVBJc3Ryc1tpXSwwLERTQXB1Yk1QSXN0cnNbaV0ubGVuZ3RoKTtcbiAgfVxuICB2YXIgRWxnYW1hbHNlY01QSXMgPSBbXTtcbiAgZm9yIChpID0gMDsgaSA8IDE7IGkrKykge1xuICAgIEVsZ2FtYWxzZWNNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRWxnYW1hbHNlY01QSXNbaV0ucmVhZChFbGdhbWFsc2VjTVBJc3Ryc1tpXSwwLEVsZ2FtYWxzZWNNUElzdHJzW2ldLmxlbmd0aCk7XG4gIH1cbiAgICBcbiAgdmFyIEVsZ2FtYWxwdWJNUElzID0gW107XG4gIGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICBFbGdhbWFscHViTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIEVsZ2FtYWxwdWJNUElzW2ldLnJlYWQoRWxnYW1hbHB1Yk1QSXN0cnNbaV0sMCxFbGdhbWFscHViTVBJc3Ryc1tpXS5sZW5ndGgpO1xuICB9XG5cbiAgLy9PcmlnaW5hbGx5IHdlIHBhc3NlZCBwdWJsaWMgYW5kIHNlY3JldCBNUEkgc2VwYXJhdGVseSwgbm93IHRoZXkgYXJlIGpvaW5lZC4gSXMgdGhpcyB3aGF0IHdlIHdhbnQgdG8gZG8gbG9uZyB0ZXJtP1xuICBkZWJ1Z2dlcjtcbiAgLy8gUlNBXG4gIHZhciBSU0FzaWduZWREYXRhID0gb3BlbnBncC5zaWduYXR1cmUuc2lnbigyLCAxLCBSU0FwdWJNUElzLmNvbmNhdChSU0FzZWNNUElzKSwgXCJmb29iYXJcIik7XG4gIHZhciBSU0FzaWduZWREYXRhTVBJID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gIFJTQXNpZ25lZERhdGFNUEkucmVhZChSU0FzaWduZWREYXRhLCAwLCBSU0FzaWduZWREYXRhLmxlbmd0aCk7XG4gIHJlc3VsdFswXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgUlNBIFNpZ24gYW5kIFZlcmlmeVwiLFxuICAgICAgb3BlbnBncC5zaWduYXR1cmUudmVyaWZ5KDEsIDIsIFtSU0FzaWduZWREYXRhTVBJXSwgUlNBcHViTVBJcywgXCJmb29iYXJcIikpO1xuXG4gIC8vIERTQSBcbiAgdmFyIERTQXNpZ25lZERhdGEgPSBvcGVucGdwLnNpZ25hdHVyZS5zaWduKDIsIDE3LCBEU0FwdWJNUElzLmNvbmNhdChEU0FzZWNNUElzKSwgXCJmb29iYXJcIik7XG4gIFxuICB2YXIgRFNBbXNnTVBJcyA9IFtdO1xuICAgIERTQW1zZ01QSXNbMF0gPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgICBEU0Ftc2dNUElzWzFdID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRFNBbXNnTVBJc1swXS5yZWFkKERTQXNpZ25lZERhdGEsIDAsIERTQXNpZ25lZERhdGEubGVuZ3RoKTtcbiAgICBEU0Ftc2dNUElzWzFdLnJlYWQoRFNBc2lnbmVkRGF0YSwgRFNBbXNnTVBJc1swXS5wYWNrZXRMZW5ndGgsIERTQXNpZ25lZERhdGEubGVuZ3RoKTtcbiAgcmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBEU0EgU2lnbiBhbmQgVmVyaWZ5XCIsXG4gICAgICBvcGVucGdwLnNpZ25hdHVyZS52ZXJpZnkoMTcsIDIsIERTQW1zZ01QSXMsIERTQXB1Yk1QSXMsIFwiZm9vYmFyXCIpKTtcbiAgXG4gIHZhciBzeW1tQWxnbyA9IDk7IC8vIEFFUzI1NlxuICB2YXIgc3ltbUtleSA9IG9wZW5wZ3AuZ2VuZXJhdGVTZXNzaW9uS2V5KHN5bW1BbGdvKTtcbiAgdmFyIHN5bW1lbmNEYXRhT0NGQiA9IG9wZW5wZ3AuY2ZiLmVuY3J5cHQob3BlbnBncC5nZXRQcmVmaXhSYW5kb20oc3ltbUFsZ28pLHN5bW1BbGdvLCBzeW1tS2V5LCBcImZvb2JhclwiLHRydWUpO1xuICB2YXIgc3ltbWVuY0RhdGFDRkIgID0gb3BlbnBncC5jZmIuZW5jcnlwdChvcGVucGdwLmdldFByZWZpeFJhbmRvbShzeW1tQWxnbyksc3ltbUFsZ28sIHN5bW1LZXksIFwiZm9vYmFyXCIsZmFsc2UpO1xuICBcbiAgcmVzdWx0WzJdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBzeW1tZXRyaWMgZW5jcnlwdCBhbmQgZGVjcnlwdCB3aXRoIE9wZW5QR1AgQ0ZCIHJlc3luY1wiLFxuICAgICAgb3BlbnBncC5jZmIuZGVjcnlwdChzeW1tQWxnbyxzeW1tS2V5LHN5bW1lbmNEYXRhT0NGQix0cnVlKSA9PSBcImZvb2JhclwiKTtcbiAgcmVzdWx0WzNdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBzeW1tZXRyaWMgZW5jcnlwdCBhbmQgZGVjcnlwdCB3aXRob3V0IE9wZW5QR1AgQ0ZCIHJlc3luYyAodXNlZCBpbiBtb2RpZmljYXRpb24gZGV0ZWN0aW9uIGNvZGUgXFxcIk1EQ1xcXCIgcGFja2V0cylcIixcbiAgICAgIG9wZW5wZ3AuY2ZiLmRlY3J5cHQoc3ltbUFsZ28sc3ltbUtleSxzeW1tZW5jRGF0YUNGQixmYWxzZSkgPT0gXCJmb29iYXJcIik7XG5cbiAgdmFyIFJTQUVuY3J5cHRlZERhdGEgPSBvcGVucGdwLmNmYi5lbmNyeXB0KDEsIFJTQXB1Yk1QSXMsIG5ldyBvcGVucGdwLm1waSgpLmNyZWF0ZShvcGVucGdwX2VuY29kaW5nX2VtZV9wa2NzMV9lbmNvZGUoc3ltbUtleSwgUlNBcHViTVBJc1swXS5tcGlCeXRlTGVuZ3RoKSkpO1xuICB2YXIgUlNBRW5jcnlwdGVkRGF0YU1QSSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICBSU0FFbmNyeXB0ZWREYXRhTVBJLnJlYWQoUlNBRW5jcnlwdGVkRGF0YSwgMCxSU0FFbmNyeXB0ZWREYXRhLmxlbmd0aCk7XG5cbiAgcmVzdWx0WzRdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBhc3ltbWV0cmljIGVuY3J5cHQgYW5kIGRlY3J5cHQgdXNpbmcgUlNBIHdpdGggZW1lX3BrY3MxIHBhZGRpbmdcIixcbiAgICAgIG9wZW5wZ3BfZW5jb2RpbmdfZW1lX3BrY3MxX2RlY29kZShvcGVucGdwLmNmYi5kZWNyeXB0KDEsIFJTQXB1Yk1QSXMuY29uY2F0KFJTQXNlY01QSXMpLCBbUlNBRW5jcnlwdGVkRGF0YU1QSV0pLnRvTVBJKCkuc3Vic3RyaW5nKDIpLCBSU0FwdWJNUElzWzBdLm1waUJ5dGVMZW5ndGgpID09IHN5bW1LZXkpO1xuXG4gIHZhciBFbGdhbWFsRW5jcnlwdGVkRGF0YSA9IG9wZW5wZ3AuY2ZiLmVuY3J5cHQoMTYsIEVsZ2FtYWxwdWJNUElzLCBuZXcgb3BlbnBncC5tcGkoKS5jcmVhdGUob3BlbnBncF9lbmNvZGluZ19lbWVfcGtjczFfZW5jb2RlKHN5bW1LZXksIEVsZ2FtYWxwdWJNUElzWzBdLm1waUJ5dGVMZW5ndGgpKSk7XG4gIHZhciBFbGdhbWFsRW5jcnlwdGVkRGF0YU1QSXMgPSBbXTtcbiAgRWxnYW1hbEVuY3J5cHRlZERhdGFNUElzWzBdID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gIEVsZ2FtYWxFbmNyeXB0ZWREYXRhTVBJc1swXS5yZWFkKEVsZ2FtYWxFbmNyeXB0ZWREYXRhWzBdLCAwLCBFbGdhbWFsRW5jcnlwdGVkRGF0YVswXS5sZW5ndGgpO1xuICBFbGdhbWFsRW5jcnlwdGVkRGF0YU1QSXNbMV0gPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgRWxnYW1hbEVuY3J5cHRlZERhdGFNUElzWzFdLnJlYWQoRWxnYW1hbEVuY3J5cHRlZERhdGFbMV0sIDAsIEVsZ2FtYWxFbmNyeXB0ZWREYXRhWzFdLmxlbmd0aCk7XG5cbiAgcmVzdWx0WzVdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBhc3ltbWV0cmljIGVuY3J5cHQgYW5kIGRlY3J5cHQgdXNpbmcgRWxnYW1hbCB3aXRoIGVtZV9wa2NzMSBwYWRkaW5nXCIsXG4gICAgICBvcGVucGdwX2VuY29kaW5nX2VtZV9wa2NzMV9kZWNvZGUob3BlbnBncC5jZmIuZGVjcnlwdCgxNiwgRWxnYW1hbHB1Yk1QSXMuY29uY2F0KEVsZ2FtYWxzZWNNUElzKSwgRWxnYW1hbEVuY3J5cHRlZERhdGFNUElzKS50b01QSSgpLnN1YnN0cmluZygyKSwgRWxnYW1hbHB1Yk1QSXNbMF0ubXBpQnl0ZUxlbmd0aCkgPT0gc3ltbUtleSk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwiXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vdW5pdC5qcycpO1xuXG5yZXF1aXJlKCcuL2NyeXB0by9oYXNoL3NoYS5qcycpO1xucmVxdWlyZSgnLi9jcnlwdG8vaGFzaC9tZDUuanMnKTtcbnJlcXVpcmUoJy4vY3J5cHRvL2hhc2gvcmlwZW1kLmpzJyk7XG5cbnJlcXVpcmUoJy4vY3J5cHRvL2NpcGhlci9hZXMuanMnKTtcbnJlcXVpcmUoJy4vY3J5cHRvL2NpcGhlci9ibG93ZmlzaC5qcycpO1xucmVxdWlyZSgnLi9jcnlwdG8vY2lwaGVyL2Nhc3Q1LmpzJyk7XG5yZXF1aXJlKCcuL2NyeXB0by9jaXBoZXIvZGVzLmpzJyk7XG5yZXF1aXJlKCcuL2NyeXB0by9jaXBoZXIvdHdvZmlzaC5qcycpO1xuXG5yZXF1aXJlKCcuL2NyeXB0by9vcGVucGdwLmNyeXB0by5qcycpO1xuIiwidmFyIHByb2Nlc3M9cmVxdWlyZShcIl9fYnJvd3NlcmlmeV9wcm9jZXNzXCIpO1xubW9kdWxlLmV4cG9ydHMgPSB7XG5cdHRlc3RzOiBbXSxcblx0cmVnaXN0ZXI6IGZ1bmN0aW9uKHN0cl90aXRsZSwgZnVuY19ydW50ZXN0KSB7XG5cdFx0dGhpcy50ZXN0cy5wdXNoKHsgdGl0bGU6IHN0cl90aXRsZSwgcnVuOiBmdW5jX3J1bnRlc3QgfSk7XG5cdH0sXG5cdFxuXHRydW46IGZ1bmN0aW9uKCkge1xuXHRcdHZhciB0ZXN0ID0gdGhpcy50ZXN0cy5zaGlmdCgpO1xuXG5cdFx0dmFyIHJlc3VsdCA9IHtcblx0XHRcdHRpdGxlOiB0ZXN0LnRpdGxlXG5cdFx0fTtcblxuXG5cdFx0cmVzdWx0LnRlc3RzID0gdGVzdC5ydW4oKTtcblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0cnVuX2FsbDogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIHBhc3NlZCA9IHRydWU7XG5cblx0XHR3aGlsZSh0aGlzLnRlc3RzLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciByZXN1bHQgPSB0aGlzLnJ1bigpO1xuXG5cdFx0XHRjb25zb2xlLmxvZygnVGVzdDogJyArIHJlc3VsdC50aXRsZSk7XG5cblx0XHRcdGZvcih2YXIgaSBpbiByZXN1bHQudGVzdHMpIHtcblxuXHRcdFx0XHR2YXIgcmVzID0gcmVzdWx0LnRlc3RzW2ldLnJlc3VsdCA/XG5cdFx0XHRcdFx0J1NVQ0NFU1MnIDogJ0ZBSUxFRCc7XG5cblx0XHRcdFx0Y29uc29sZS5sb2cocmVzdWx0LnRlc3RzW2ldLmRlc2NyaXB0aW9uICsgJyAnICsgcmVzKTtcblxuXHRcdFx0XHRwYXNzZWQgPSBwYXNzZWQgJiYgcmVzdWx0LnRlc3RzW2ldLnJlc3VsdDtcblx0XHRcdH1cdFx0XHRcdFxuXHRcdH1cblxuXHRcdGlmKCFwYXNzZWQpIHByb2Nlc3MuZXhpdCgxKTtcblx0fSxcblx0XHRcblx0cmVzdWx0OiBmdW5jdGlvbihzdHJfZGVzY3JpcHRpb24sIGJvb2xlYW5fcmVzdWx0KSB7XG5cdFx0dGhpcy5kZXNjcmlwdGlvbiA9IHN0cl9kZXNjcmlwdGlvbjtcblx0XHR0aGlzLnJlc3VsdCA9IGJvb2xlYW5fcmVzdWx0O1xuXHR9XG59XG5cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbnByb2Nlc3MubmV4dFRpY2sgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBjYW5TZXRJbW1lZGlhdGUgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5zZXRJbW1lZGlhdGU7XG4gICAgdmFyIGNhblBvc3QgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5wb3N0TWVzc2FnZSAmJiB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lclxuICAgIDtcblxuICAgIGlmIChjYW5TZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmKSB7IHJldHVybiB3aW5kb3cuc2V0SW1tZWRpYXRlKGYpIH07XG4gICAgfVxuXG4gICAgaWYgKGNhblBvc3QpIHtcbiAgICAgICAgdmFyIHF1ZXVlID0gW107XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICBpZiAoZXYuc291cmNlID09PSB3aW5kb3cgJiYgZXYuZGF0YSA9PT0gJ3Byb2Nlc3MtdGljaycpIHtcbiAgICAgICAgICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAocXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZm4gPSBxdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICBmbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgICAgICBxdWV1ZS5wdXNoKGZuKTtcbiAgICAgICAgICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgncHJvY2Vzcy10aWNrJywgJyonKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgc2V0VGltZW91dChmbiwgMCk7XG4gICAgfTtcbn0pKCk7XG5cbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn1cblxuLy8gVE9ETyhzaHR5bG1hbilcbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuIl19
;