fork-openpgpjs/test/test-bundle.js
2013-11-18 10:07:18 +01:00

14433 lines
1.3 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){
// 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');
};
},{}],2:[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;
},{}],3:[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');
/**
*
* This object contains configuration values and implements
* storing and retrieving configuration them from HTML5 local storage.
*
* This object can be accessed after calling openpgp.init()
* using openpgp.config
* Stored config parameters can be accessed using
* openpgp.config.config
* @class
* @classdesc Implementation of the GPG4Browsers config object
*/
var config = function() {
/**
* @property {Integer} prefer_hash_algorithm
* @property {Integer} encryption_cipher
* @property {Integer} compression
* @property {Boolean} show_version
* @property {Boolean} show_comment
* @property {Boolean} integrity_protect
* @property {String} keyserver
*/
this.prefer_hash_algorithm = enums.hash.sha256;
this.encryption_cipher = enums.symmetric.aes256;
this.compression = enums.compression.zip;
this.show_version = true;
this.show_comment = true;
this.integrity_protect = true;
this.keyserver = "keyserver.linux.it"; // "pgp.mit.edu:11371"
this.versionstring = "OpenPGP.js VERSION";
this.commentstring = "http://openpgpjs.org";
/**
* If enabled, debug messages will be printed
*/
this.debug = false;
};
module.exports = new config();
},{"../enums.js":27}],4:[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":56,"./cipher":9}],5:[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":56}],6:[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":56}],7:[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":56}],8:[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
//only add padding if encrypting - note that you need to use the same padding option for both encrypt and decrypt
if (encrypt) {
message = des_addPadding(message, padding);
len = message.length;
}
//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;
//only remove padding if decrypting - note that you need to use the same padding option for both encrypt and decrypt
if (!encrypt) {
result = des_removePadding(result, padding);
}
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
function des_addPadding(message, padding) {
var padLength = 8 - (message.length % 8);
if ((padding == 2) && (padLength < 8)) { //pad the message with spaces
message += " ".substr(0, padLength);
} else if (padding == 1) { //PKCS7 padding
message += String.fromCharCode(padLength, padLength, padLength, padLength, padLength, padLength, padLength,
padLength).substr(0, padLength);
} else if (!padding && (padLength < 8)) { //pad the message out with null bytes
message += "\0\0\0\0\0\0\0\0".substr(0, padLength);
}
return message;
}
function des_removePadding(message, padding) {
if (padding == 2) { // space padded
message = message.replace(/ *$/g, "");
} else if (padding == 1) { // PKCS7
var padCount = message.charCodeAt(message.length - 1);
message = message.substr(0, message.length - padCount);
} else if (!padding) { // null padding
message = message.replace(/\0*$/g, "");
}
return message;
}
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));
}
}
Des.keySize = Des.prototype.keySize = 24;
Des.blockSize = Des.prototype.blockSize = 8;
// This is "original" DES - Des is actually Triple DES.
// This is only exported so we can unit test.
function OriginalDes(key) {
this.key = key;
this.encrypt = function(block, padding) {
var keys = des_createKeys(this.key);
return util.str2bin(des(keys, util.bin2str(block), true, 0, null, padding));
}
this.decrypt = function(block, padding) {
var keys = des_createKeys(this.key);
return util.str2bin(des(keys, util.bin2str(block), false, 0, null, padding));
}
}
module.exports = {
des: Des,
originalDes: OriginalDes
}
},{"../../util":56}],9:[function(require,module,exports){
var desModule = require('./des.js');
module.exports = {
des: desModule['des'],
originalDes: desModule['originalDes'],
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":5,"./blowfish.js":6,"./cast5.js":7,"./des.js":8,"./twofish.js":10}],10:[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":56}],11:[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'),
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.');
}
},
generateMpi: function(algo, bits) {
var result = (function() {
switch (algo) {
case 'rsa_encrypt':
case 'rsa_encrypt_sign':
case 'rsa_sign':
//remember "publicKey" refers to the crypto/public_key dir
var rsa = new publicKey.rsa();
var keyObject = rsa.generate(bits, "10001");
var output = [];
output.push(keyObject.n);
output.push(keyObject.ee);
output.push(keyObject.d);
output.push(keyObject.p);
output.push(keyObject.q);
output.push(keyObject.u);
return output;
default:
throw new Error('Unsupported algorithm for key generation.');
}
})();
return result.map(function(bn) {
var mpi = new type_mpi();
mpi.fromBigInteger(bn);
return mpi;
});
},
/**
* 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(cipher[algo].keySize);
},
};
},{"../type/mpi.js":54,"./cipher":9,"./public_key":20,"./random.js":23}],12:[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":13,"./ripe-md.js":14,"./sha.js":15}],13:[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":56}],14:[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;
},{}],15:[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");
}
}
},{}],16:[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":4,"./cipher":9,"./crypto.js":11,"./hash":12,"./pkcs1.js":17,"./public_key":20,"./random.js":23,"./signature.js":24}],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
/**
* 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":56,"./crypto.js":11,"./hash":12,"./public_key/jsbn.js":21,"./random.js":23}],18:[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'),
random = require('../random.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 = random.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":56,"../hash":12,"../random.js":23,"./jsbn.js":21}],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'),
random = require('../random.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 = random.getRandomBigIntegerInRange(two, pMinus2);
k = k.mod(pMinus2).add(BigInteger.ONE);
var c = [];
c[0] = g.modPow(k, p);
c[1] = y.modPow(k, p).multiply(m).mod(p);
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":56,"../random.js":23,"./jsbn.js":21}],20:[function(require,module,exports){
module.exports = {
rsa: require('./rsa.js'),
elgamal: require('./elgamal.js'),
dsa: require('./dsa.js')
}
},{"./dsa.js":18,"./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();
var j, bases = [];
for (var i = 0; i < t; ++i) {
//Pick bases at random, instead of starting at 2
for (;;) {
j = lowprimes[Math.floor(Math.random() * lowprimes.length)];
if (bases.indexOf(j) == -1) break;
}
bases.push(j);
a.fromInt(j);
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":56,"./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":56,"../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
var type_mpi = require('../type/mpi.js');
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;
},
/**
* 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 = this.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":54}],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":12,"./pkcs1.js":17,"./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');
var enums = require('../enums.js');
var config = require('../config');
/**
* 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 enums.armor.multipart_section;
} 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 enums.armor.multipart_last;
} 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 enums.armor.signed;
} else
// BEGIN PGP MESSAGE
// Used for signed, encrypted, or compressed files.
if (splittedtext[1].match(/BEGIN PGP MESSAGE/)) {
return enums.armor.message;
} else
// BEGIN PGP PUBLIC KEY BLOCK
// Used for armoring public keys.
if (splittedtext[1].match(/BEGIN PGP PUBLIC KEY BLOCK/)) {
return enums.armor.public_key;
} else
// BEGIN PGP PRIVATE KEY BLOCK
// Used for armoring private keys.
if (splittedtext[1].match(/BEGIN PGP PRIVATE KEY BLOCK/)) {
return enums.armor.private_key;
}
}
/**
* 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 (config.show_version) {
result += "Version: " + config.versionstring + '\r\n';
}
if (config.show_comment) {
result += "Comment: " + 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 enums.armor.multipart_section:
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 enums.armor.mutlipart_last:
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 enums.armor.signed:
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 enums.armor.message:
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 enums.armor.public_key:
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 enums.armor.private_key:
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
};
},{"../config":3,"../enums.js":27,"./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){
var enums = {
/** 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
},
signatureSubpacket: {
signature_creation_time: 2,
signature_expiration_time: 3,
exportable_certification: 4,
trust_signature: 5,
regular_expression: 6,
revocable: 7,
reserved: 8,
key_expiration_time: 9,
placeholder_backwards_compatibility: 10,
preferred_symmetric_algorithms: 11,
revocation_key: 12,
issuer: 16,
notification_data: 20,
preferred_hash_algorithms: 21,
preferred_compression_algorithms: 22,
key_server_preferences: 23,
preferred_key_server: 24,
primary_user_id: 25,
policy_uri: 26,
key_flags: 27,
signers_user_id: 28,
reason_for_revocation: 29,
features: 30,
signature_target: 31,
embedded_signature: 32
},
armor: {
multipart_section: 0,
multipart_last: 1,
signed: 2,
message: 3,
public_key: 4,
private_key: 5
},
// 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.');
}
}
module.exports = enums;
},{}],28:[function(require,module,exports){
module.exports = require('./openpgp.js');
module.exports.key = require('./key.js');
module.exports.message = require('./message.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');
module.exports.enums = require('./enums.js');
module.exports.config = require('./config');
module.exports.crypto = require('./crypto');
},{"./config":3,"./crypto":16,"./encoding/armor.js":25,"./enums.js":27,"./key.js":29,"./message.js":31,"./openpgp.js":32,"./packet":35,"./type/keyid.js":53,"./type/mpi.js":54,"./type/s2k.js":55,"./util":56}],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
var packet = require('./packet');
var enums = require('./enums.js');
var armor = require('./encoding/armor.js');
var config = require('./config');
/**
* @class
* @classdesc Class that represents an OpenPGP key. Must contain a master key.
* @param {packetlist} packetlist [description]
* Can contain additional subkeys, signatures,
* user ids, user attributes.
*/
function key(packetlist) {
this.packets = packetlist || new packet.list();
this.passphrase = null;
/**
* Returns the primary key packet (secret or public)
* @returns {packet_secret_key|packet_public_key|null}
*/
this.getKeyPacket = function() {
for (var i = 0; i < this.packets.length; i++) {
if (this.packets[i].tag == enums.packet.public_key ||
this.packets[i].tag == enums.packet.secret_key) {
return this.packets[i];
}
}
return null;
}
/**
* Returns all the private and public subkey packets
* @returns {[public_subkey|secret_subkey]}
*/
this.getSubkeyPackets = function() {
var subkeys = [];
for (var i = 0; i < this.packets.length; i++) {
if (this.packets[i].tag == enums.packet.public_subkey ||
this.packets[i].tag == enums.packet.secret_subkey) {
subkeys.push(this.packets[i]);
}
}
return subkeys;
}
/**
* Returns all the private and public key and subkey packets
* @returns {[public_subkey|secret_subkey|packet_secret_key|packet_public_key]}
*/
this.getAllKeyPackets = function() {
return [this.getKeyPacket()].concat(this.getSubkeyPackets());
}
/**
* Returns key IDs of all key packets
* @returns {[keyid]}
*/
this.getKeyIds = function() {
var keyIds = [];
var keys = this.getAllKeyPackets();
for (var i = 0; i < keys.length; i++) {
keyIds.push(keys[i].getKeyId());
}
return keyIds;
}
/**
* Returns first key packet for given array of key IDs
* @param {[keyid]} keyIds
* @return {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null}
*/
this.getKeyPacket = function(keyIds) {
var keys = this.getAllKeyPackets();
for (var i = 0; i < keys.length; i++) {
var keyId = keys[i].getKeyId();
for (var j = 0; j < keyIds.length; j++) {
if (keyId.equals(keyIds[j])) {
//TODO return only verified keys
return keys[i];
}
}
}
return null;
}
/**
* Returns first private key packet for given array of key IDs
* @param {[keyid]} keyIds
* @param {Boolean} decrypted decrypt private key packet
* @return {secret_subkey|packet_secret_key|null}
*/
this.getPrivateKeyPacket = function(keyIds, decrypted) {
var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey);
for (var i = 0; i < keys.length; i++) {
var keyId = keys[i].getKeyId();
for (var j = 0; j < keyIds.length; j++) {
if (keyId.equals(keyIds[j])) {
//TODO return only verified keys
if (decrypted) {
if (!this.passphrase) throw new Error('No passphrase to decrypt key.');
keys[i].decrypt(this.passphrase);
}
return keys[i];
}
}
}
return null;
}
/**
* Returns true if this is a public key
* @return {Boolean}
*/
this.isPublic = function() {
var publicKeyPackets = this.packets.filterByTag(enums.packet.public_key);
return publicKeyPackets.length ? true : false;
}
/**
* Returns true if this is a private key
* @return {Boolean}
*/
this.isPrivate = function() {
var privateKeyPackets = this.packets.filterByTag(enums.packet.private_key);
return privateKeyPackets.length ? true : false;
}
/**
* Returns first key packet that is available for signing
* @return {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null}
*/
this.getSigningKeyPacket = function() {
var signing = [ enums.publicKey.rsa_encrypt_sign, enums.publicKey.rsa_sign, enums.publicKey.dsa];
signing = signing.map(function(s) {
return enums.read(enums.publicKey, s);
});
var keys = this.getAllKeyPackets();
for (var i = 0; i < keys.length; i++) {
if (signing.indexOf(keys[i].algorithm) !== -1) {
return keys[i];
}
}
return null;
}
/**
* Returns preferred signature hash algorithm of this key
* @return {String}
*/
function getPreferredSignatureHashAlgorithm() {
//TODO implement: https://tools.ietf.org/html/rfc4880#section-5.2.3.8
//separate private key preference from digest preferences
return config.prefer_hash_algorithm;
}
/**
* Returns the first valid encryption key packet for this key
* @returns {public_subkey|secret_subkey|packet_secret_key|packet_public_key|null} key packet or null if no encryption key has been found
*/
this.getEncryptionKeyPacket = function() {
// V4: by convention subkeys are prefered for encryption service
// V3: keys MUST NOT have subkeys
var isValidEncryptionKey = function(key) {
//TODO evaluate key flags: http://tools.ietf.org/html/rfc4880#section-5.2.3.21
return key.algorithm != enums.read(enums.publicKey, enums.publicKey.dsa) && key.algorithm != enums.read(enums.publicKey,
enums.publicKey.rsa_sign);
//TODO verify key
//&& keys.verifyKey()
};
var subkeys = this.getSubkeyPackets();
for (var j = 0; j < subkeys.length; j++) {
if (isValidEncryptionKey(subkeys[j])) {
return subkeys[j];
}
}
// if no valid subkey for encryption, use primary key
var primaryKey = this.getKeyPacket();
if (isValidEncryptionKey(primaryKey)) {
return primaryKey;
}
return null;
}
/**
* Decrypts all secret key and subkey packets
* @param {String} passphrase
* @return {undefined}
*/
this.decrypt = function(passphrase) {
//TODO return value
var keys = this.getAllKeyPackets();
for (var i in keys) {
if (keys[i].tag == enums.packet.secret_subkey ||
keys[i].tag == enums.packet.secret_key) {
if (!passphrase && !this.passphrase) throw new Error('No passphrase to decrypt key.');
keys[i].decrypt(passphrase || this.passphrase);
}
}
}
/**
* Unlocks the key with passphrase, decryption of secret keys deferred. This allows to decrypt the required private key packets on demand
* @param {String} passphrase
* @return {undefined}
*/
this.unlock = function(passphrase) {
this.passphrase = passphrase;
}
// TODO
this.verify = function() {
}
// TODO
this.revoke = function() {
}
}
/**
* reads an OpenPGP armored text and returns a key object
* @param {String} armoredText text to be parsed
* @return {key} new key object
*/
key.readArmored = function(armoredText) {
//TODO how do we want to handle bad text? Exception throwing
//TODO don't accept non-key armored texts
var input = armor.decode(armoredText).openpgp;
var packetlist = new packet.list();
packetlist.read(input);
var newKey = new key(packetlist);
return newKey;
}
module.exports = key;
},{"./config":3,"./encoding/armor.js":25,"./enums.js":27,"./packet":35}],30:[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 packet = require('./packet');
var enums = require('./enums.js');
var armor = require('./encoding/armor.js');
/**
* @class
* @classdesc The class that deals with storage of the keyring. Currently the only option is to use HTML5 local storage.
*/
var keyring = function() {
this.armoredPacketlists = [];
this.parsedPacketlists = [];
/**
* Initialization routine for the keyring. This method reads the
* keyring from HTML5 local storage and initializes this instance.
* This method is called by openpgp.init().
*/
function init() {
var armoredPacketlists = JSON.parse(window.localStorage.getItem("armoredPacketlists"));
if (armoredPacketlists === null || armoredPacketlists.length === 0) {
armoredPacketlists = [];
}
this.armoredPacketlists = armoredPacketlists;
var packetlist;
for (var i = 0; i < armoredPacketlists.length; i++) {
packetlist = new packet.list();
packetlist.read(armoredPacketlists[i]);
this.parsedPacketlists.push(packetlist);
}
}
this.init = init;
/**
* Saves the current state of the keyring to HTML5 local storage.
* The privateKeys array and publicKeys array gets Stringified using JSON
*/
function store() {
window.localStorage.setItem("armoredPacketlists", JSON.stringify(this.armoredPacketlists));
}
this.store = store;
function emailPacketCheck(packet, email) {
var emailMatch = false;
var packetEmail;
email = email.toLowerCase();
if (packet.tag == enums.packet.userid) {
packetEmail = packet.userid;
//we need to get just the email from the userid packet
packetEmail = packetEmail.split('<')[1].split('<')[0].trim.toLowerCase();
if (packetEmail == email) {
emailMatch = true;
}
}
return emailMatch;
}
function idPacketCheck(packet, id) {
if (packet.getKeyId && packet.getKeyId().write() == id) {
return true;
}
return false;
}
function helperCheckIdentityAndPacketMatch(identityFunction, identityInput, packetType, packetlist) {
var packet;
for (var l = 0; l < packetlist.length; l++) {
packet = packetlist[l];
identityMatch = identityFunction(packet, identityInput);
if (!packetType) {
packetMatch = true;
} else if (packet.tag == packetType) {
packetMatch = true;
}
if (packetMatch && identityMatch) {
return true;
}
}
return false;
}
function checkForIdentityAndPacketMatch(identityFunction, identityInput, packetType) {
var results = [];
var packetlist;
var identityMatch;
var packetMatch;
for (var p = 0; p < this.parsedPacketlists.length; p++) {
identityMatch = false;
packetMatch = false;
packetlist = this.parsedPacketlists[p];
if (helperCheckIdentityAndPacketMatch(identityFunction, identityInput, packetType, packetlist)) {
results.push(packetlist);
}
}
return results;
}
this.checkForIdentityAndPacketMatch = checkForIdentityAndPacketMatch;
/**
* searches all public keys in the keyring matching the address or address part of the user ids
* @param {String} email_address
* @return {openpgp_msg_publickey[]} The public keys associated with provided email address.
*/
function getPublicKeyForAddress(email) {
return checkForIdentityAndPacketMatch(emailPacketCheck, email, enums.packet.public_key);
}
this.getPublicKeyForAddress = getPublicKeyForAddress;
/**
* Searches the keyring for a private key containing the specified email address
* @param {String} email_address email address to search for
* @return {openpgp_msg_privatekey[]} private keys found
*/
function getPrivateKeyForAddress(email_address) {
return checkForIdentityAndPacketMatch(emailPacketCheck, email, enums.packet.secret_key);
}
this.getPrivateKeyForAddress = getPrivateKeyForAddress;
/**
* Searches the keyring for public keys having the specified key id
* @param {String} keyId provided as string of hex number (lowercase)
* @return {openpgp_msg_privatekey[]} public keys found
*/
function getPacketlistsForKeyId(keyId) {
return this.checkForIdentityAndPacketMatch(idPacketCheck, keyId);
}
this.getPacketlistsForKeyId = getPacketlistsForKeyId;
/**
* Imports a packet list (public or private key block) from an ascii armored message
* @param {String} armored message to read the packets/key from
*/
function importPacketlist(armored) {
this.armoredPacketlists.push(armored);
var dearmored = armor.decode(armored.replace(/\r/g, '')).openpgp;
packetlist = new packet.list();
packetlist.read(dearmored);
this.parsedPacketlists.push(packetlist);
return true;
}
this.importPacketlist = importPacketlist;
/**
* TODO
* returns the openpgp_msg_privatekey representation of the public key at public key ring index
* @param {Integer} index the index of the public key within the publicKeys array
* @return {openpgp_msg_privatekey} the public key object
*/
function exportPublicKey(index) {
return this.publicKey[index];
}
this.exportPublicKey = exportPublicKey;
/**
* TODO
* Removes a public key from the public key keyring at the specified index
* @param {Integer} index the index of the public key within the publicKeys array
* @return {openpgp_msg_privatekey} The public key object which has been removed
*/
function removePublicKey(index) {
var removed = this.publicKeys.splice(index, 1);
this.store();
return removed;
}
this.removePublicKey = removePublicKey;
};
module.exports = new keyring();
},{"./encoding/armor.js":25,"./enums.js":27,"./packet":35}],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 packet = require('./packet');
var enums = require('./enums.js');
var armor = require('./encoding/armor.js');
var config = require('./config');
var crypto = require('./crypto');
/**
* @class
* @classdesc A generic message containing one or more literal packets.
*/
function message(packetlist) {
this.packets = packetlist || new packet.list();
/**
* Returns the key IDs of the public keys to which the session key is encrypted
* @return {[keyId]} array of keyid objects
*/
this.getEncryptionKeyIds = function() {
var keyIds = [];
var pkESKeyPacketlist = this.packets.filterByTag(enums.packet.public_key_encrypted_session_key);
pkESKeyPacketlist.forEach(function(packet) {
keyIds.push(packet.publicKeyId);
});
return keyIds;
}
/**
* Decrypt the message
* @param {key} privateKey unlocked private key for which the message is encrypted (corresponding to the session key)
* @return {[message]} new message with decrypted content
*/
this.decrypt = function(privateKey) {
var encryptionKeyIds = this.getEncryptionKeyIds();
if (!encryptionKeyIds.length) {
// nothing to decrypt return unmodified message
return this;
}
var privateKeyPacket = privateKey.getPrivateKeyPacket(encryptionKeyIds, true);
var pkESKeyPacketlist = this.packets.filterByTag(enums.packet.public_key_encrypted_session_key);
var pkESKeyPacket;
for (var i = 0; i < pkESKeyPacketlist.length; i++) {
if (pkESKeyPacketlist[i].publicKeyId.equals(privateKeyPacket.getKeyId())) {
pkESKeyPacket = pkESKeyPacketlist[i];
pkESKeyPacket.decrypt(privateKeyPacket);
break;
}
}
if (pkESKeyPacket) {
var symEncryptedPacketlist = this.packets.filterByTag(enums.packet.symmetrically_encrypted, enums.packet.sym_encrypted_integrity_protected);
if (symEncryptedPacketlist.length !== 0) {
var symEncryptedPacket = symEncryptedPacketlist[0];
symEncryptedPacket.decrypt(pkESKeyPacket.sessionKeyAlgorithm, pkESKeyPacket.sessionKey);
return new message(symEncryptedPacket.packets);
}
}
}
/**
* Get literal data that is the body of the message
* @return {String|null} literal body of the message as string
*/
this.getLiteral = function() {
var literal = this.packets.findPacket(enums.packet.literal);
return literal && literal.data || null;
}
/**
* Encrypt the message
* @param {[key]} keys array of keys, used to encrypt the message
* @return {[message]} new message with encrypted content
*/
this.encrypt = function(keys) {
var packetlist = new packet.list();
//TODO get preferred algo from signature
var sessionKey = crypto.generateSessionKey(enums.read(enums.symmetric, config.encryption_cipher));
keys.forEach(function(key) {
var encryptionKeyPacket = key.getEncryptionKeyPacket();
if (encryptionKeyPacket) {
var pkESKeyPacket = new packet.public_key_encrypted_session_key();
pkESKeyPacket.publicKeyId = encryptionKeyPacket.getKeyId();
pkESKeyPacket.publicKeyAlgorithm = encryptionKeyPacket.algorithm;
pkESKeyPacket.sessionKey = sessionKey;
//TODO get preferred algo from signature
pkESKeyPacket.sessionKeyAlgorithm = enums.read(enums.symmetric, config.encryption_cipher);
pkESKeyPacket.encrypt(encryptionKeyPacket);
packetlist.push(pkESKeyPacket);
}
});
var symEncryptedPacket;
if (config.integrity_protect) {
symEncryptedPacket = new packet.sym_encrypted_integrity_protected();
} else {
symEncryptedPacket = new packet.symmetrically_encrypted();
}
symEncryptedPacket.packets = this.packets;
//TODO get preferred algo from signature
symEncryptedPacket.encrypt(enums.read(enums.symmetric, config.encryption_cipher), sessionKey);
packetlist.push(symEncryptedPacket);
return new message(packetlist);
}
/**
* Decrypts a message and generates user interface message out of the found.
* MDC will be verified as well as message signatures
* @param {openpgp_msg_privatekey} private_key the private the message is encrypted with (corresponding to the session key)
* @param {openpgp_packet_encryptedsessionkey} sessionkey the session key to be used to decrypt the message
* @param {openpgp_msg_publickey} pubkey Array of public keys to check signature against. If not provided, checks local keystore.
* @return {String} plaintext of the message or null on error
*/
function decryptAndVerifySignature(private_key, sessionkey, pubkey) {
if (private_key == null || sessionkey == null || sessionkey == "")
return null;
var decrypted = sessionkey.decrypt(this, private_key.keymaterial);
if (decrypted == null)
return null;
var packet;
var position = 0;
var len = decrypted.length;
var validSignatures = new Array();
util.print_debug_hexstr_dump("openpgp.msg.messge decrypt:\n", decrypted);
var messages = openpgp.read_messages_dearmored({
text: decrypted,
openpgp: decrypted
});
for (var m in messages) {
if (messages[m].data) {
this.text = messages[m].data;
}
if (messages[m].signature) {
validSignatures.push(messages[m].verifySignature(pubkey));
}
}
return {
text: this.text,
validSignatures: validSignatures
};
}
/**
* Verifies a message signature. This function can be called after read_message if the message was signed only.
* @param {openpgp_msg_publickey} pubkey Array of public keys to check signature against. If not provided, checks local keystore.
* @return {boolean} true if the signature was correct; otherwise false
*/
function verifySignature(pubkey) {
var result = false;
if (this.signature.tagType == 2) {
if (!pubkey || pubkey.length == 0) {
var pubkey;
if (this.signature.version == 4) {
pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.issuerKeyId);
} else if (this.signature.version == 3) {
pubkey = openpgp.keyring.getPublicKeysForKeyId(this.signature.keyId);
} else {
util.print_error("unknown signature type on message!");
return false;
}
}
if (pubkey.length == 0)
util.print_warning("Unable to verify signature of issuer: " + util.hexstrdump(this.signature.issuerKeyId) +
". Public key not found in keyring.");
else {
for (var i = 0; i < pubkey.length; i++) {
var tohash = this.text.replace(/\r\n/g, "\n").replace(/\n/g, "\r\n");
if (this.signature.verify(tohash, pubkey[i])) {
util.print_info("Found Good Signature from " + pubkey[i].obj.userIds[0].text + " (0x" + util.hexstrdump(
pubkey[i].obj.getKeyId()).substring(8) + ")");
result = true;
} else {
util.print_error("Signature verification failed: Bad Signature from " + pubkey[i].obj.userIds[0].text +
" (0x" + util.hexstrdump(pubkey[0].obj.getKeyId()).substring(8) + ")");
}
}
}
}
return result;
}
}
/**
* reads an OpenPGP armored message and returns a message object
* @param {String} armoredText text to be parsed
* @return {message} new message object
*/
message.readArmored = function(armoredText) {
//TODO how do we want to handle bad text? Exception throwing
//TODO don't accept non-message armored texts
var input = armor.decode(armoredText).openpgp;
var packetlist = new packet.list();
packetlist.read(input);
var newMessage = new message(packetlist);
return newMessage;
}
/**
* creates new message object from text
* @param {String} text
* @return {message} new message object
*/
message.fromText = function(text) {
var literalDataPacket = new packet.literal();
// text will be converted to UTF8
literalDataPacket.set(text);
var literalDataPacketlist = new packet.list();
literalDataPacketlist.push(literalDataPacket);
var newMessage = new message(literalDataPacketlist);
return newMessage;
}
module.exports = message;
},{"./config":3,"./crypto":16,"./encoding/armor.js":25,"./enums.js":27,"./packet":35}],32:[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.
*/
var armor = require('./encoding/armor.js');
var packet = require('./packet');
var util = require('./util');
var enums = require('./enums.js');
var config = require('./config');
var message = require('./message.js');
/**
* 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() {
/**
* encrypts message with keys
* @param {[key]} keys array of keys, used to encrypt the message
* @param {String} text message as native JavaScript string
* @return {String} encrypted ASCII armored message
*/
function encryptMessage(keys, text) {
var msg = message.fromText(text);
msg = msg.encrypt(keys);
var armored = armor.encode(enums.armor.message, msg.packets.write());
return armored;
}
function encryptAndSignMessage(publicKeys, privateKey, message) {
}
/**
* decrypts message
* @param {key} privateKey unlocked private key
* @param {message} message the message object with the encrypted data
* @return {String|null} decrypted message as as native JavaScript string
* or null if no literal data found
*/
function decryptMessage(privateKey, message) {
message = message.decrypt(privateKey);
return message.getLiteral();
}
function decryptAndVerifyMessage(privateKey, publicKeys, messagePacketlist) {
}
function verifyMessage(publicKeys, messagePacketlist) {
}
function signMessage(privateKey, messagePacketlist) {
}
/**
* TODO: update this doc
* 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 generateKeyPair(keyType, numBits, userId, passphrase) {
var packetlist = new packet.list();
var secretKeyPacket = new packet.secret_key();
secretKeyPacket.algorithm = enums.read(enums.publicKey, keyType);
secretKeyPacket.generate(numBits);
secretKeyPacket.encrypt(passphrase);
var userIdPacket = new packet.userid();
userIdPacket.read(userId);
var dataToSign = {};
dataToSign.userid = userIdPacket;
dataToSign.key = secretKeyPacket;
var signaturePacket = new packet.signature();
signaturePacket.issuerKeyId = secretKeyPacket.getKeyId().write();
signaturePacket.signatureType = enums.signature.cert_generic;
signaturePacket.publicKeyAlgorithm = keyType;
//TODO we should load preferred hash from config, or as input to this function
signaturePacket.hashAlgorithm = enums.hash.sha256;
signaturePacket.sign(secretKeyPacket, dataToSign);
var secretSubkeyPacket = new packet.secret_subkey();
secretSubkeyPacket.algorithm = enums.read(enums.publicKey, keyType);
secretSubkeyPacket.generate(numBits);
secretSubkeyPacket.encrypt(passphrase);
dataToSign = {};
dataToSign.key = secretKeyPacket;
dataToSign.bind = secretSubkeyPacket;
var subkeySignaturePacket = new packet.signature();
subkeySignaturePacket.issuerKeyId = secretSubkeyPacket.getKeyId().write();
subkeySignaturePacket.signatureType = enums.signature.subkey_binding;
subkeySignaturePacket.publicKeyAlgorithm = keyType;
//TODO we should load preferred hash from config, or as input to this function
subkeySignaturePacket.hashAlgorithm = enums.hash.sha256;
subkeySignaturePacket.sign(secretSubkeyPacket, dataToSign);
packetlist.push(secretKeyPacket);
packetlist.push(userIdPacket);
packetlist.push(signaturePacket);
packetlist.push(secretSubkeyPacket);
packetlist.push(subkeySignaturePacket);
var armored = armor.encode(enums.armor.private_key, packetlist.write());
return armored;
}
/**
* 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 i;
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 (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 (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 armor.encode(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 armor.encode(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 armor.encode(2, result, null, null);
}
this.generateKeyPair = generateKeyPair;
this.write_signed_message = write_signed_message;
this.write_signed_and_encrypted_message = write_signed_and_encrypted_message;
this.encryptMessage = encryptMessage;
this.decryptMessage = decryptMessage;
}
module.exports = new _openpgp();
},{"./config":3,"./encoding/armor.js":25,"./enums.js":27,"./message.js":31,"./packet":35,"./util":56}],33:[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":34,"./literal.js":36,"./marker.js":37,"./one_pass_signature.js":38,"./public_key.js":41,"./public_key_encrypted_session_key.js":42,"./public_subkey.js":43,"./secret_key.js":44,"./secret_subkey.js":45,"./signature.js":46,"./sym_encrypted_integrity_protected.js":47,"./sym_encrypted_session_key.js":48,"./symmetrically_encrypted.js":49,"./trust.js":50,"./user_attribute.js":51,"./userid.js":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
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":2,"../encoding/base64.js":26,"../enums.js":27}],35:[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":33,"./packetlist.js":40}],36:[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'; // default format for literal data packets
this.data = ''; // literal data representation as native JavaScript string or bytes
this.date = new Date();
/**
* Set the packet data to a javascript native string or a squence of
* bytes. Conversion to the provided format takes place when the
* packet is written.
* @param {String} str Any native javascript string
* @param {'utf8|'binary'|'text'} format The format the packet data will be written to,
* defaults to 'utf8'
*/
this.set = function(str, format) {
this.format = format || this.format;
this.data = str;
}
/**
* Set the packet data to value represented by the provided string of bytes.
* @param {String} bytes The string of bytes
* @param {'utf8|'binary'|'text'} format The format of the string of bytes
*/
this.setBytes = function(bytes, format) {
this.format = format;
switch (format) {
case 'utf8':
bytes = util.decode_utf8(bytes);
bytes = bytes.replace(/\r\n/g, '\n');
break;
case 'text':
bytes = bytes.replace(/\r\n/g, '\n');
break;
}
this.data = bytes;
}
/**
* Get the byte sequence representing the literal packet data
* @returns {String} A sequence of bytes
*/
this.getBytes = function() {
var bytes = this.data;
switch (this.format) {
case 'utf8':
bytes = bytes.replace(/\n/g, '\r\n');
bytes = util.encode_utf8(bytes);
break;
case 'text':
bytes = bytes.replace(/\n/g, '\r\n');
break;
}
return bytes;
}
/**
* 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":56}],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
/**
* @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;
},{}],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
/**
* @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().write();
if (nested)
result += String.fromCharCode(0);
else
result += String.fromCharCode(1);
return result;
}
};
},{"../enums.js":27,"../type/keyid.js":53}],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 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":56}],40:[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++;
}
/**
* Creates a new packetList with all packets that pass the test implemented by the provided function.
*/
this.filter = function(callback) {
var filtered = new packetlist();
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
filtered.push(this[i]);
}
}
return filtered;
}
/**
* Creates a new packetList with all packets from the given types
*/
this.filterByTag = function() {
var args = Array.prototype.slice.call(arguments);
var filtered = new packetlist();
var that = this;
for (var i = 0; i < this.length; i++) {
if (args.some(function(packetType) {return that[i].tag == packetType})) {
filtered.push(this[i]);
}
}
return filtered;
}
/**
* Executes the provided callback once for each element
*/
this.forEach = function(callback) {
for (var i = 0; i < this.length; i++) {
callback(this[i]);
}
}
/**
* Traverses packet tree and returns first matching packet
* @param {enums.packet} type The packet type
* @return {[type]}
*/
this.findPacket = function(type) {
var packetlist = this.filterByTag(type);
if (packetlist.length) {
return packetlist[0];
} else {
var found = null;
for (var i = 0; i < this.length; i++) {
if (this[i].packets.length) {
found = this[i].packets.findPacket(type);
if (found) return found;
}
}
}
return null;
}
}
},{"../enums.js":27,"./all_packets.js":33,"./packet.js":39}],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 util = require('../util'),
type_mpi = require('../type/mpi.js'),
type_keyid = require('../type/keyid.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() {
var keyid = new type_keyid();
keyid.read(this.getFingerprint().substr(12, 8));
return keyid;
}
/**
* 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":16,"../enums.js":27,"../type/keyid.js":53,"../type/mpi.js":54,"../util":56}],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 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":16,"../enums.js":27,"../type/keyid.js":53,"../type/mpi.js":54,"../util":56}],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 public_key = require('./public_key.js');
module.exports = function public_subkey() {
public_key.call(this);
}
},{"./public_key.js":41}],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 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);
// encrypted secret-key data
this.encrypted = null;
// indicator if secret-key data is available in decrypted form
this.isDecrypted = false;
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));
this.isDecrypted = true;
}
};
/*
* 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.isDecrypted)
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.isDecrypted = true;
};
this.generate = function(bits, passphrase) {
this.mpi = crypto.generateMpi(this.algorithm, bits);
this.isDecrypted = true;
};
}
packet_secret_key.prototype = new publicKey;
module.exports = packet_secret_key;
},{"../crypto":16,"../enums.js":27,"../type/mpi.js":54,"../type/s2k.js":55,"../util":56,"./public_key.js":41}],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 secret_key = require('./secret_key.js');
module.exports = function secret_subkey() {
secret_key.call(this);
}
},{"./secret_key.js":44}],46:[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);
//Calculate subpackets
var creationTimeSubpacket = write_sub_packet(enums.signatureSubpacket.signature_creation_time,
util.writeDate(new Date()));
var issuerSubpacket = write_sub_packet(enums.signatureSubpacket.issuer, key.getKeyId().write());
// Add subpackets here
result += util.writeNumber(creationTimeSubpacket.length + issuerSubpacket.length, 2);
result += creationTimeSubpacket + issuerSubpacket;
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.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":16,"../enums.js":27,"../type/mpi.js":54,"../util":56,"./packet.js":39}],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
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":16,"../util":56}],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 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":16,"../enums.js":27,"../type/s2k.js":55}],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
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":16}],50:[function(require,module,exports){
module.exports = function packet_trust() {
};
},{}],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
/**
* @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;
}
}
};
},{}],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 = 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":56}],53:[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 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.
*/
function keyid() {
// initialize keyid with 0x0000000000000000
var strArray = [];
var zero = String.fromCharCode(0);
for (var i = 0; i < 8; i++) {
strArray[i] = zero;
}
this.bytes = strArray.join('');
/**
* 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;
}
this.toHex = function() {
return util.hexstrdump(this.bytes);
}
this.equals = function(keyid) {
return this.bytes == keyid.bytes;
}
}
keyid.mapToHex = function(keyid) {
return keyid.toHex();
}
module.exports = keyid;
},{"../util":56}],54:[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":56}],55:[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":16,"../enums.js":27,"../util":56}],56:[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-zA-Z0-9_.-]+@([a-zA-Z0-9-]+\.)+[a-zA-Z0-9]{2,6}$/;
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) {
try {
return decodeURIComponent(escape(utf8));
} catch (e) {
return 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();
},{}],57:[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.crypto.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":70}],58:[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.crypto.cipher.blowfish;
var result = [];
function test_bf(input, key, output) {
var blowfish = new openpgp.crypto.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":70}],59:[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.crypto.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":70}],60:[function(require,module,exports){
var unit = require('../../unit.js');
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]],
[[0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00],[0xA4,0x84,0xC3,0xAD,0x38,0xDC,0x9C,0x19]],
[[0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00],[0xFB,0xE0,0x0A,0x8A,0x1E,0xF8,0xAD,0x72]],
[[0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00],[0x75,0x0D,0x07,0x94,0x07,0x52,0x13,0x63]],
[[0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00],[0x64,0xFE,0xED,0x9C,0x72,0x4C,0x2F,0xAF]],
[[0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00],[0xF0,0x2B,0x26,0x3B,0x32,0x8E,0x2B,0x60]],
[[0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00],[0x9D,0x64,0x55,0x5A,0x9A,0x10,0xB8,0x52]],
[[0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00],[0xD1,0x06,0xFF,0x0B,0xED,0x52,0x55,0xD7]],
[[0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00],[0xE1,0x65,0x2C,0x6B,0x13,0x8C,0x64,0xA5]],
[[0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00],[0xE4,0x28,0x58,0x11,0x86,0xEC,0x8F,0x46]],
[[0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00],[0xAE,0xB5,0xF5,0xED,0xE2,0x2D,0x1A,0x36]],
[[0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00],[0xE9,0x43,0xD7,0x56,0x8A,0xEC,0x0C,0x5C]],
[[0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00],[0xDF,0x98,0xC8,0x27,0x6F,0x54,0xB0,0x4B]],
[[0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00],[0xB1,0x60,0xE4,0x68,0x0F,0x6C,0x69,0x6F]],
[[0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00],[0xFA,0x07,0x52,0xB0,0x7D,0x9C,0x4A,0xB8]],
[[0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00],[0xCA,0x3A,0x2B,0x03,0x6D,0xBC,0x85,0x02]],
[[0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00],[0x5E,0x09,0x05,0x51,0x7B,0xB5,0x9B,0xCF]],
[[0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00],[0x81,0x4E,0xEB,0x3B,0x91,0xD9,0x07,0x26]],
[[0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00],[0x4D,0x49,0xDB,0x15,0x32,0x91,0x9C,0x9F]],
[[0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00],[0x25,0xEB,0x5F,0xC3,0xF8,0xCF,0x06,0x21]],
[[0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00],[0xAB,0x6A,0x20,0xC0,0x62,0x0D,0x1C,0x6F]],
[[0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00],[0x79,0xE9,0x0D,0xBC,0x98,0xF9,0x2C,0xCA]],
[[0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00],[0x86,0x6E,0xCE,0xDD,0x80,0x72,0xBB,0x0E]],
[[0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00],[0x8B,0x54,0x53,0x6F,0x2F,0x3E,0x64,0xA8]],
[[0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00],[0xEA,0x51,0xD3,0x97,0x55,0x95,0xB8,0x6B]],
[[0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00],[0xCA,0xFF,0xC6,0xAC,0x45,0x42,0xDE,0x31]],
[[0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00],[0x8D,0xD4,0x5A,0x2D,0xDF,0x90,0x79,0x6C]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00],[0x10,0x29,0xD5,0x5E,0x88,0x0E,0xC2,0xD0]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00],[0x5D,0x86,0xCB,0x23,0x63,0x9D,0xBE,0xA9]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00],[0x1D,0x1C,0xA8,0x53,0xAE,0x7C,0x0C,0x5F]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00],[0xCE,0x33,0x23,0x29,0x24,0x8F,0x32,0x28]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00],[0x84,0x05,0xD1,0xAB,0xE2,0x4F,0xB9,0x42]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00],[0xE6,0x43,0xD7,0x80,0x90,0xCA,0x42,0x07]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00],[0x48,0x22,0x1B,0x99,0x37,0x74,0x8A,0x23]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00],[0xDD,0x7C,0x0B,0xBD,0x61,0xFA,0xFD,0x54]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80],[0x2F,0xBC,0x29,0x1A,0x57,0x0D,0xB5,0xC4]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40],[0xE0,0x7C,0x30,0xD7,0xE4,0xE2,0x6E,0x12]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20],[0x09,0x53,0xE2,0x25,0x8E,0x8E,0x90,0xA1]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10],[0x5B,0x71,0x1B,0xC4,0xCE,0xEB,0xF2,0xEE]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08],[0xCC,0x08,0x3F,0x1E,0x6D,0x9E,0x85,0xF6]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04],[0xD2,0xFD,0x88,0x67,0xD5,0x0D,0x2D,0xFE]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02],[0x06,0xE7,0xEA,0x22,0xCE,0x92,0x70,0x8F]],
[[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01],[0x16,0x6B,0x40,0xB4,0x4A,0xBA,0x4B,0xD6]]];
var res = true;
var j = 0;
for (var i = 0; i < testvectors.length; i++) {
var des = new openpgp.crypto.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;
});
unit.register("DES encrypt/decrypt padding tests", function () {
var openpgp = require('../../../'),
util = openpgp.util;
var result = [];
var key = util.bin2str([0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]);
var testvectors = new Array();
testvectors[0] = [[[0x01], [0x24, 0xC7, 0x4A, 0x9A, 0x79, 0x75, 0x4B, 0xC7]],
[[0x02, 0x03], [0xA7, 0x7A, 0x9A, 0x59, 0x8A, 0x86, 0x85, 0xC5]],
[[0x03, 0x04, 0x05], [0x01, 0xCF, 0xEB, 0x6A, 0x74, 0x60, 0xF5, 0x02]],
[[0x04, 0x05, 0x06, 0x07], [0xA8, 0xF0, 0x3D, 0x59, 0xBA, 0x6B, 0x0E, 0x76]],
[[0x05, 0x06, 0x07, 0x08, 0x09], [0x86, 0x40, 0x33, 0x61, 0x3F, 0x55, 0x73, 0x49]],
[[0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], [0x13, 0x21, 0x3E, 0x0E, 0xCE, 0x2C, 0x94, 0x01]],
[[0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D], [0x30, 0x49, 0x97, 0xC1, 0xDA, 0xD5, 0x59, 0xA5]],
[[0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F], [0x83, 0x25, 0x79, 0x06, 0x54, 0xA4, 0x44, 0xD9]]];
testvectors[1] = [[[0x01], [0xF2, 0xAB, 0x1C, 0x9E, 0x70, 0x7D, 0xCC, 0x92]],
[[0x02, 0x03], [0x6B, 0x4C, 0x67, 0x24, 0x9F, 0xB7, 0x4D, 0xAC]],
[[0x03, 0x04, 0x05], [0x68, 0x95, 0xAB, 0xA8, 0xEA, 0x53, 0x13, 0x23]],
[[0x04, 0x05, 0x06, 0x07], [0xC8, 0xDE, 0x60, 0x8F, 0xF6, 0x09, 0x90, 0xB5]],
[[0x05, 0x06, 0x07, 0x08, 0x09], [0x19, 0x13, 0x50, 0x20, 0x70, 0x40, 0x2E, 0x09]],
[[0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], [0xA8, 0x23, 0x40, 0xC6, 0x17, 0xA6, 0x31, 0x4A]],
[[0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D], [0x36, 0x62, 0xF2, 0x99, 0x68, 0xD4, 0xBF, 0x7C]],
[[0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F], [0x83, 0x25, 0x79, 0x06, 0x54, 0xA4, 0x44, 0xD9, 0x08, 0x6F, 0x9A, 0x1D, 0x74, 0xC9, 0x4D, 0x4E]]];
testvectors[2] = [[[0x01], [0x83, 0x68, 0xE4, 0x9C, 0x84, 0xCC, 0xCB, 0xF0]],
[[0x02, 0x03], [0xBB, 0xA8, 0x0B, 0x66, 0x1B, 0x62, 0xC4, 0xC8]],
[[0x03, 0x04, 0x05], [0x9A, 0xD7, 0x5A, 0x24, 0xFD, 0x3F, 0xBF, 0x22]],
[[0x04, 0x05, 0x06, 0x07], [0x14, 0x4E, 0x68, 0x6D, 0x2E, 0xC1, 0xB7, 0x52]],
[[0x05, 0x06, 0x07, 0x08, 0x09], [0x12, 0x0A, 0x51, 0x08, 0xF9, 0xA3, 0x03, 0x74]],
[[0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], [0xB2, 0x07, 0xD1, 0x05, 0xF6, 0x67, 0xAF, 0xBA]],
[[0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D], [0xCA, 0x59, 0x61, 0x3A, 0x83, 0x23, 0x26, 0xDD]],
[[0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F], [0x83, 0x25, 0x79, 0x06, 0x54, 0xA4, 0x44, 0xD9]]];
var des = new openpgp.crypto.cipher.originalDes(key);
var res = true;
var j = 0;
for (var padding = 0; padding < 3; padding++) {
var thisVectorSet = testvectors[padding];
for (var i = 0; i < thisVectorSet.length; i++) {
var encrypted = des.encrypt(thisVectorSet[i][0], padding);
var decrypted = des.decrypt(encrypted, padding);
var res2 = (util.bin2str(encrypted) == util.bin2str(thisVectorSet[i][1]));
var res3 = (util.bin2str(decrypted) == util.bin2str(thisVectorSet[i][0]));
res &= res2;
res &= res3;
if (!res2 || !res3) {
result[j] = new unit.result(
"Testing vector with block [" +
util.hexidump(thisVectorSet[i][0]) +
"] and key [" + util.hexstrdump(key) +
"] and padding [" + padding +
"] should be " + util.hexidump(thisVectorSet[i][1]) + " - Actually [ENC:" + util.hexidump(encrypted) + ", DEC:" + util.hexidump(decrypted) + "]",
false);
j++;
}
}
}
if (res) {
result[j] = new unit.result("All DES test vectors completed", true);
}
return result;
});
},{"../../../":28,"../../unit.js":70}],61:[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.crypto.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":70}],62:[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.crypto.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":70}],63:[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.crypto.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":70}],64:[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.crypto.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":70}],65:[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]);
}
var RSAsecMPIs = [];
for (i = 0; i < 4; i++) {
RSAsecMPIs[i] = new openpgp.mpi();
RSAsecMPIs[i].read(RSAsecMPIstrs[i]);
}
var DSAsecMPIs = [];
for (i = 0; i < 1; i++) {
DSAsecMPIs[i] = new openpgp.mpi();
DSAsecMPIs[i].read(DSAsecMPIstrs[i]);
}
var DSApubMPIs = [];
for (i = 0; i < 4; i++) {
DSApubMPIs[i] = new openpgp.mpi();
DSApubMPIs[i].read(DSApubMPIstrs[i]);
}
var ElgamalsecMPIs = [];
for (i = 0; i < 1; i++) {
ElgamalsecMPIs[i] = new openpgp.mpi();
ElgamalsecMPIs[i].read(ElgamalsecMPIstrs[i]);
}
var ElgamalpubMPIs = [];
for (i = 0; i < 3; i++) {
ElgamalpubMPIs[i] = new openpgp.mpi();
ElgamalpubMPIs[i].read(ElgamalpubMPIstrs[i]);
}
//Originally we passed public and secret MPI separately, now they are joined. Is this what we want to do long term?
// RSA
var RSAsignedData = openpgp.crypto.signature.sign(2, 1, RSApubMPIs.concat(RSAsecMPIs), "foobar");
var RSAsignedDataMPI = new openpgp.mpi();
RSAsignedDataMPI.read(RSAsignedData);
result[0] = new unit.result("Testing RSA Sign and Verify",
openpgp.crypto.signature.verify(1, 2, [RSAsignedDataMPI], RSApubMPIs, "foobar"));
// DSA
var DSAsignedData = openpgp.crypto.signature.sign(2, 17, DSApubMPIs.concat(DSAsecMPIs), "foobar");
var DSAmsgMPIs = [];
DSAmsgMPIs[0] = new openpgp.mpi();
DSAmsgMPIs[1] = new openpgp.mpi();
DSAmsgMPIs[0].read(DSAsignedData.substring(0,34));
DSAmsgMPIs[1].read(DSAsignedData.substring(34,68));
result[1] = new unit.result("Testing DSA Sign and Verify",
openpgp.crypto.signature.verify(17, 2, DSAmsgMPIs, DSApubMPIs, "foobar"));
var symmAlgo = "aes256"; // AES256
var symmKey = openpgp.crypto.generateSessionKey(symmAlgo);
var symmencDataOCFB = openpgp.crypto.cfb.encrypt(openpgp.crypto.getPrefixRandom(symmAlgo), symmAlgo, "foobarfoobar1234567890", symmKey, true);
var symmencDataCFB = openpgp.crypto.cfb.encrypt(openpgp.crypto.getPrefixRandom(symmAlgo), symmAlgo, "foobarfoobar1234567890", symmKey, false);
result[2] = new unit.result("Testing symmetric encrypt and decrypt with OpenPGP CFB resync",
openpgp.crypto.cfb.decrypt(symmAlgo,symmKey,symmencDataOCFB,true) == "foobarfoobar1234567890");
result[3] = new unit.result("Testing symmetric encrypt and decrypt without OpenPGP CFB resync (used in modification detection code \"MDC\" packets)",
openpgp.crypto.cfb.decrypt(symmAlgo,symmKey,symmencDataCFB,false) == "foobarfoobar1234567890");
var RSAUnencryptedData = new openpgp.mpi();
RSAUnencryptedData.fromBytes(openpgp.crypto.pkcs1.eme.encode(symmKey, RSApubMPIs[0].byteLength()));
var RSAEncryptedData = openpgp.crypto.publicKeyEncrypt("rsa_encrypt_sign", RSApubMPIs, RSAUnencryptedData);
result[4] = new unit.result("Testing asymmetric encrypt and decrypt using RSA with eme_pkcs1 padding",
openpgp.crypto.pkcs1.eme.decode(openpgp.crypto.publicKeyDecrypt("rsa_encrypt_sign", RSApubMPIs.concat(RSAsecMPIs), RSAEncryptedData).write().substring(2), RSApubMPIs[0].byteLength()) == symmKey);
var ElgamalUnencryptedData = new openpgp.mpi();
ElgamalUnencryptedData.fromBytes(openpgp.crypto.pkcs1.eme.encode(symmKey, ElgamalpubMPIs[0].byteLength()));
var ElgamalEncryptedData = openpgp.crypto.publicKeyEncrypt("elgamal", ElgamalpubMPIs, ElgamalUnencryptedData);
result[5] = new unit.result("Testing asymmetric encrypt and decrypt using Elgamal with eme_pkcs1 padding",
openpgp.crypto.pkcs1.eme.decode(openpgp.crypto.publicKeyDecrypt("elgamal", ElgamalpubMPIs.concat(ElgamalsecMPIs), ElgamalEncryptedData).write().substring(2), ElgamalpubMPIs[0].byteLength()) == symmKey);
return result;
});
},{"../../":28,"../unit.js":70}],66:[function(require,module,exports){
var unit = require('../unit.js');
unit.register("Testing of binary signature checking", function() {
var openpgp = require('../../');
var keyring = require('../../src/keyring.js');
var result = [];
var priv_key = openpgp.key.readArmored([
'-----BEGIN PGP PRIVATE KEY BLOCK-----',
'Version: GnuPG v1.4.11 (GNU/Linux)',
'',
'lQHhBFERnrMRBADmM0hIfkI3yosjgbWo9v0Lnr3CCE+8KsMszgVS+hBu0XfGraKm',
'ivcA2aaJimHqVYOP7gEnwFAxHBBpeTJcu5wzCFyJwEYqVeS3nnaIhBPplSF14Duf',
'i6bB9RV7KxVAg6aunmM2tAutqC+a0y2rDaf7jkJoZ9gWJe2zI+vraD6fiwCgxvHo',
'3IgULB9RqIqpLoMgXfcjC+cD/1jeJlKRm+n71ryYwT/ECKsspFz7S36z6q3XyS8Q',
'QfrsUz2p1fbFicvJwIOJ8B20J/N2/nit4P0gBUTUxv3QEa7XCM/56/xrGkyBzscW',
'AzBoy/AK9K7GN6z13RozuAS60F1xO7MQc6Yi2VU3eASDQEKiyL/Ubf/s/rkZ+sGj',
'yJizBACtwCbQzA+z9XBZNUat5NPgcZz5Qeh1nwF9Nxnr6pyBv7tkrLh/3gxRGHqG',
'063dMbUk8pmUcJzBUyRsNiIPDoEUsLjY5zmZZmp/waAhpREsnK29WLCbqLdpUors',
'c1JJBsObkA1IM8TZY8YUmvsMEvBLCCanuKpclZZXqeRAeOHJ0v4DAwK8WfuTe5B+',
'M2BOOeZbN8BpfiA1l//fMMHLRS3UvbLBv4P1+4SyvhyYTR7M76Q0xPc03MFOWHL+',
'S9VumbQWVGVzdDIgPHRlc3QyQHRlc3QuY29tPohiBBMRAgAiBQJREZ6zAhsDBgsJ',
'CAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRARJ5QDyxae+MXNAKCzWSDR3tMrTrDb',
'TAri73N1Xb3j1ACfSl9y+SAah2q7GvmiR1+6+/ekqJGdAVgEURGesxAEANlpMZjW',
'33jMxlKHDdyRFXtKOq8RreXhq00plorHbgz9zFEWm4VF53+E/KGnmHGyY5Cy8TKy',
'ZjaueZZ9XuG0huZg5If68irFfNZtxdA26jv8//PdZ0Uj+X6J3RVa2peMLDDswTYL',
'OL1ZO1fxdtDD40fdAiIZ1QyjwEG0APtz41EfAAMFBAC5/dtgBBPtHe8UjDBaUe4n',
'NzHuUBBp6XE+H7eqHNFCuZAJ7yqJLGVHNIaQR419cNy08/OO/+YUQ7rg78LxjFiv',
'CH7IzhfU+6yvELSbgRMicY6EnAP2GT+b1+MtFNa3lBGtBHcJla52c2rTAHthYZWk',
'fT5R5DnJuQ2cJHBMS9HWyP4DAwK8WfuTe5B+M2C7a/YJSUv6SexdGCaiaTcAm6g/',
'PvA6hw/FLzIEP67QcQSSTmhftQIwnddt4S4MyJJH3U4fJaFfYQ1zCniYJohJBBgR',
'AgAJBQJREZ6zAhsMAAoJEBEnlAPLFp74QbMAn3V4857xwnO9/+vzIVnL93W3k0/8',
'AKC8omYPPomN1E/UJFfXdLDIMi5LoA==',
'=LSrW',
'-----END PGP PRIVATE KEY BLOCK-----'
].join("\n")).packets;
var pub_key = openpgp.key.readArmored(
[ '-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: GnuPG v1.4.11 (GNU/Linux)',
'',
'mQGiBFERlw4RBAD6Bmcf2w1dtUmtCLkdxeqZLArk3vYoQAjdibxA3gXVyur7fsWb',
'ro0jVbBHqOCtC6jDxE2l52NP9+tTlWeVMaqqNvUE47LSaPq2DGI8Wx1Rj6bF3mTs',
'obYEwhGbGh/MhJnME9AHODarvk8AZbzo0+k1EwrBWF6dTUBPfqO7rGU2ewCg80WV',
'x5pt3evj8rRK3jQ8SMKTNRsD/1PhTdxdZTdXARAFzcW1VaaruWW0Rr1+XHKKwDCz',
'i7HE76SO9qjnQfZCZG75CdQxI0h8GFeN3zsDqmhob2iSz2aJ1krtjM+iZ1FBFd57',
'OqCV6wmk5IT0RBN12ZzMS19YvzN/ONXHrmTZlKExd9Mh9RKLeVNw+bf6JsKQEzcY',
'JzFkBACX9X+hDYchO/2hiTwx4iOO9Fhsuh7eIWumB3gt+aUpm1jrSbas/QLTymmk',
'uZuQVXI4NtnlvzlNgWv4L5s5RU5WqNGG7WSaKNdcrvJZRC2dgbUJt04J5CKrWp6R',
'aIYal/81Ut1778lU01PEt563TcQnUBlnjU5OR25KhfSeN5CZY7QUVGVzdCA8dGVz',
'dEB0ZXN0LmNvbT6IYgQTEQIAIgUCURGXDgIbAwYLCQgHAwIGFQgCCQoLBBYCAwEC',
'HgECF4AACgkQikDlZK/UvLSspgCfcNaOpTg1W2ucR1JwBbBGvaERfuMAnRgt3/rs',
'EplqEakMckCtikEnpxYe',
'=b2Ln',
'-----END PGP PUBLIC KEY BLOCK-----'
].join("\n")).packets;
var msg = openpgp.message.readArmored([
'-----BEGIN PGP MESSAGE-----',
'Version: GnuPG v1.4.11 (GNU/Linux)',
'',
'hQEOA1N4OCSSjECBEAP/diDJCQn4e88193PgqhbfAkohk9RQ0v0MPnXpJbCRTHKO',
'8r9nxiAr/TQv4ZOingXdAp2JZEoE9pXxZ3r1UWew04czxmgJ8FP1ztZYWVFAWFVi',
'Tj930TBD7L1fY/MD4fK6xjEG7z5GT8k4tn4mLm/PpWMbarIglfMopTy1M/py2cID',
'/2Sj7Ikh3UFiG+zm4sViYc5roNbMy8ixeoKixxi99Mx8INa2cxNfqbabjblFyc0Z',
'BwmbIc+ZiY2meRNI5y/tk0gRD7hT84IXGGl6/mH00bsX/kkWdKGeTvz8s5G8RDHa',
'Za4HgLbXItkX/QarvRS9kvkD01ujHfj+1ZvgmOBttNfP0p8BQLIICqvg1eYD9aPB',
'+GtOZ2F3+k5VyBL5yIn/s65SBjNO8Fqs3aL0x+p7s1cfUzx8J8a8nWpqq/qIQIqg',
'ZJH6MZRKuQwscwH6NWgsSVwcnVCAXnYOpbHxFQ+j7RbF/+uiuqU+DFH/Rd5pik8b',
'0Dqnp0yfefrkjQ0nuvubgB6Rv89mHpnvuJfFJRInpg4lrHwLvRwdpN2HDozFHcKK',
'aOU=',
'=4iGt',
'-----END PGP MESSAGE-----'
].join("\n")).packets;
//TODO need both?
priv_key[0].decrypt("abcd");
priv_key[3].decrypt("abcd");
msg[0].decrypt(priv_key[3]);
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
msg[1].packets[2].verify(pub_key[0], msg[1].packets[1]);
result[0] = new unit.result("Testing signature checking on CAST5-enciphered message",
msg[1].packets[2].verified === true);
// exercises the GnuPG s2k type 1001 extension:
// the secrets on the primary key have been stripped.
var priv_key_gnupg_ext = openpgp.key.readArmored([
'-----BEGIN PGP PRIVATE KEY BLOCK-----',
'Version: GnuPG v1.4.11 (GNU/Linux)',
'',
'lQGqBFERnrMRBADmM0hIfkI3yosjgbWo9v0Lnr3CCE+8KsMszgVS+hBu0XfGraKm',
'ivcA2aaJimHqVYOP7gEnwFAxHBBpeTJcu5wzCFyJwEYqVeS3nnaIhBPplSF14Duf',
'i6bB9RV7KxVAg6aunmM2tAutqC+a0y2rDaf7jkJoZ9gWJe2zI+vraD6fiwCgxvHo',
'3IgULB9RqIqpLoMgXfcjC+cD/1jeJlKRm+n71ryYwT/ECKsspFz7S36z6q3XyS8Q',
'QfrsUz2p1fbFicvJwIOJ8B20J/N2/nit4P0gBUTUxv3QEa7XCM/56/xrGkyBzscW',
'AzBoy/AK9K7GN6z13RozuAS60F1xO7MQc6Yi2VU3eASDQEKiyL/Ubf/s/rkZ+sGj',
'yJizBACtwCbQzA+z9XBZNUat5NPgcZz5Qeh1nwF9Nxnr6pyBv7tkrLh/3gxRGHqG',
'063dMbUk8pmUcJzBUyRsNiIPDoEUsLjY5zmZZmp/waAhpREsnK29WLCbqLdpUors',
'c1JJBsObkA1IM8TZY8YUmvsMEvBLCCanuKpclZZXqeRAeOHJ0v4DZQJHTlUBtBZU',
'ZXN0MiA8dGVzdDJAdGVzdC5jb20+iGIEExECACIFAlERnrMCGwMGCwkIBwMCBhUI',
'AgkKCwQWAgMBAh4BAheAAAoJEBEnlAPLFp74xc0AoLNZINHe0ytOsNtMCuLvc3Vd',
'vePUAJ9KX3L5IBqHarsa+aJHX7r796SokZ0BWARREZ6zEAQA2WkxmNbfeMzGUocN',
'3JEVe0o6rxGt5eGrTSmWisduDP3MURabhUXnf4T8oaeYcbJjkLLxMrJmNq55ln1e',
'4bSG5mDkh/ryKsV81m3F0DbqO/z/891nRSP5fondFVral4wsMOzBNgs4vVk7V/F2',
'0MPjR90CIhnVDKPAQbQA+3PjUR8AAwUEALn922AEE+0d7xSMMFpR7ic3Me5QEGnp',
'cT4ft6oc0UK5kAnvKoksZUc0hpBHjX1w3LTz847/5hRDuuDvwvGMWK8IfsjOF9T7',
'rK8QtJuBEyJxjoScA/YZP5vX4y0U1reUEa0EdwmVrnZzatMAe2FhlaR9PlHkOcm5',
'DZwkcExL0dbI/gMDArxZ+5N7kH4zYLtr9glJS/pJ7F0YJqJpNwCbqD8+8DqHD8Uv',
'MgQ/rtBxBJJOaF+1AjCd123hLgzIkkfdTh8loV9hDXMKeJgmiEkEGBECAAkFAlER',
'nrMCGwwACgkQESeUA8sWnvhBswCfdXjznvHCc73/6/MhWcv3dbeTT/wAoLyiZg8+',
'iY3UT9QkV9d0sMgyLkug',
'=GQsY',
'-----END PGP PRIVATE KEY BLOCK-----',
].join("\n")).packets;
priv_key_gnupg_ext[3].decrypt("abcd");
msg[0].decrypt(priv_key_gnupg_ext[3]);
msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey);
msg[1].packets[2].verify(pub_key[0], msg[1].packets[1]);
result[1] = new unit.result("Testing GnuPG stripped-key extensions",
msg[1].packets[2].verified === true);
// Exercises the ability of openpgp_keyring.getPublicKeysForKeyId to return subkeys
keyring.init();
keyring.importPacketlist([
'-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: GnuPG v1.4.11 (GNU/Linux)',
'',
'mQGiBFERvI4RBAD0M/HGglCtVNXPF72ehT8riAXrl0rSec4RJC61Bh+UAOhxn5+U',
'fDgos5p1SpIzYmn+M87JoSSVLAjfakFk0gHgR9I3bu7SIwq3Bikk1Vw3gO+yDSO6',
'TKpLUFGYDiBSSE1MGdxBadWLE1hlRf5B2x62gnGmjSpSVbly33PFkoDmrwCg9rAp',
'RmncnF9GhWjOLFkEoQw9Yx8EAOsxvq8Ig5Z1gk+ZKfDZeftpHRe3FdrRtbnhxvYY',
'7z+w9uz1EpoZUwDR5G4X3hTwJQ7lXmIOskg/+eRMLEAqEY7b/7tW6RaUJ2d6Ehsi',
'dOS89fIxElwjAOnVOM5S24f0FDQTTto7QBOoxcNTfkEJCHXSlpoOUmGAP85fXh3l',
'yPTGBACJfKc76Un3UWC1sWIRDxYiyh3ZpZyNEskoV6ESW8jEI1RnMnv5TrfGJH5K',
'E8jWX7TTnoFyPJtBTjlucAtkQaS4Bb7dg1LLja17zAqKNGOJK2b9fb2Z+lnTjPiY',
'i7DPH1XHnfaEexjlh/U7mYa5RrwIphRxNi8gCuxv874ZMmhEn7QWVGVzdDMgPHRl',
'c3QzQHRlc3QuY29tPohiBBMRAgAiBQJREbyOAhsDBgsJCAcDAgYVCAIJCgsEFgID',
'AQIeAQIXgAAKCRC0u8O0Moa2JYxyAJ9Oi2UlcUT0VJNgwjyl/VF9Xcjf9gCeJPvy',
'g/fp4EAU8MJIaN2yMI8pLFS5AaIEURG8nhEEAKVgeNDuYDPufLuJ0GrJV/CbXEjj',
'aEPA0iTUqV0nTCPdAfQ/nmE3gh5UlNMr/zSHJ+c4FQhYdLrzRGDOSzV+mfPHH3t+',
'YVx+wat0BYwABpHAtsIuLIVo2RQqYZYH85tatwBkm71HHT3jmlEAvr6NFH38+v3s',
'3w4Wl0/sdHyaeiSXAKCxJ4X1eOdN7L1rrbJozQ/gDCFuVQP/dcV6Ksss8Aw443jG',
'AYBLHWh6o4GhAY6/h1kijF0xD+uc+tNmTQnQi1tEOoTeIZMXnSRwtk8XEuJkkbAP',
'+uyvMgyV3wrk9zkaTAin7nrjAERxezFOdBEOtnB1CovJxtMn+RRxaMEGpC4GnETy',
'N5+6FkLuLcNXiCQP75ajzOAN1aID/juNjUNpBbNpfqBV7j1K+Kn0n9HYTyQl9ghy',
'026+/4c8ag2HV+bg3BD7c2VTVu9xBODHsfu0q8Ql/QB9W8tmYugU6DeXMHaeWPUH',
'ph98guM9kF2yHIiRBvAd5i7wOjwn+I/Ir6nBR2yxJ3p31CDUnUlbjTPYg7mtQvHW',
'EY2Cp4SWiJEEGBECAAkFAlERvJ4CGwIAUgkQtLvDtDKGtiVHIAQZEQIABgUCURG8',
'ngAKCRAMiMeR296Y2SjyAJ9V3wRJJ2Szazqal4khWGfLu5R6/wCfQQIRD24yVdz8',
'2a+2eCrwyALT2GAihACfS0nWM3a0gtITqngpJsRws+Ep+eIAn15qD2itutxNb8NI',
'bR2gBB5QmVJ3',
'=pGA6',
'-----END PGP PUBLIC KEY BLOCK-----'
].join("\n"));
var msg2 = openpgp.message.readArmored([
'-----BEGIN PGP MESSAGE-----',
'Version: GnuPG v1.4.11 (GNU/Linux)',
'',
'kA0DAAIRDIjHkdvemNkBrB1iB2Zvby50eHRREbz3VEVTVCBEQVRBIDEyMzQ1NohG',
'BAARAgAGBQJREbz3AAoJEAyIx5Hb3pjZ2TcAn32LpDEuHe9QrSRlyvSuREKNOFwz',
'AJ9zh4zsK4GIPuEu81YPNmHsju7DYg==',
'=WaSx',
'-----END PGP MESSAGE-----'
].join("\n")).packets;
var packetlists = keyring.getPacketlistsForKeyId(msg2[0].signingKeyId.write());
var pubKey = packetlists[0];
msg2[2].verify(pubKey[3], msg2[1]);
result[2] = new unit.result("Testing keyring public subkey support",
packetlists !== null &&
packetlists.length == 1 &&
msg2[2].verified);
return result;
});
},{"../../":28,"../../src/keyring.js":30,"../unit.js":70}],67:[function(require,module,exports){
var unit = require('../unit.js');
unit.register("Key generation/encryption/decryption", function() {
var openpgp = require('../../');
var result = [];
var testHelper = function(passphrase, userid, message) {
var key = openpgp.generateKeyPair(openpgp.enums.publicKey.rsa_encrypt_sign, 512,
userid, message, passphrase);
var info = '\npassphrase: ' + passphrase + '\n'
+ 'userid: ' + userid + '\n'
+ 'message: ' + message;
var privKey = openpgp.key.readArmored(key);
var encrypted = openpgp.encryptMessage([privKey], message);
var msg = openpgp.message.readArmored(encrypted);
privKey.unlock(passphrase);
try {
var decrypted = openpgp.decryptMessage(privKey, msg);
return new unit.result(message + ' == ' + decrypted + info, message == decrypted);
} catch (e) {
return new unit.result("Exception on decrypt of private key packet!" + info, false);
}
};
result.push(testHelper('password', 'Test McTestington <test@example.com>', 'hello world'));
result.push(testHelper('●●●●', '♔♔♔♔ <test@example.com>', 'łäóć'));
return result;
});
unit.register("Encryption/decryption", function() {
var openpgp = require('../../');
var result = [];
var pub_key =
['-----BEGIN PGP PUBLIC KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
'Type: RSA/RSA',
'',
'mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+',
'fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5',
'GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0',
'JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS',
'YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6',
'AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki',
'Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf',
'9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa',
'JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag',
'Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr',
'woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb',
'LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA',
'SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP',
'GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2',
'bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X',
'W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD',
'AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY',
'hz3tYjKhoFTKEIq3y3Pp',
'=h/aX',
'-----END PGP PUBLIC KEY BLOCK-----'].join('\n');
var priv_key =
['-----BEGIN PGP PRIVATE KEY BLOCK-----',
'Version: GnuPG v2.0.19 (GNU/Linux)',
'Type: RSA/RSA',
'Pwd: hello world',
'',
'lQH+BFJhL04BBADclrUEDDsm0PSZbQ6pml9FpzTyXiyCyDN+rMOsy9J300Oc10kt',
'/nyBej9vZSRcaW5VpNNj0iA+c1/w2FPf84zNsTzvDmuMaNHFUzky4/vkYuZra//3',
'+Ri7CF8RawSYQ/4IRbC9zqdBlzniyfQOW7Dp/LYe8eibnDSrmkQem0G0jwARAQAB',
'/gMDAu7L//czBpE40p1ZqO8K3k7UejemjsQqc7kOqnlDYd1Z6/3NEA/UM30Siipr',
'KjdIFY5+hp0hcs6EiiNq0PDfm/W2j+7HfrZ5kpeQVxDek4irezYZrl7JS2xezaLv',
'k0Fv/6fxasnFtjOM6Qbstu67s5Gpl9y06ZxbP3VpT62+Xeibn/swWrfiJjuGEEhM',
'bgnsMpHtzAz/L8y6KSzViG/05hBaqrvk3/GeEA6nE+o0+0a6r0LYLTemmq6FbaA1',
'PHo+x7k7oFcBFUUeSzgx78GckuPwqr2mNfeF+IuSRnrlpZl3kcbHASPAOfEkyMXS',
'sWGE7grCAjbyQyM3OEXTSyqnehvGS/1RdB6kDDxGwgE/QFbwNyEh6K4eaaAThW2j',
'IEEI0WEnRkPi9fXyxhFsCLSI1XhqTaq7iDNqJTxE+AX2b9ZuZXAxI3Tc/7++vEyL',
'3p18N/MB2kt1Wb1azmXWL2EKlT1BZ5yDaJuBQ8BhphM3tCRUZXN0IE1jVGVzdGlu',
'Z3RvbiA8dGVzdEBleGFtcGxlLmNvbT6IuQQTAQIAIwUCUmEvTgIbLwcLCQgHAwIB',
'BhUIAgkKCwQWAgMBAh4BAheAAAoJEEpjYTpNbkCUMAwD+gIK08qpEZSVas9qW+Ok',
'32wzNkwxe6PQgZwcyBqMQYZUcKagC8+89pMQQ5sKUGvpIgat42Tf1KLGPcvG4cDA',
'JZ6w2PYz9YHQqPh9LA+PAnV8m25TcGmKcKgvFUqQ3U53X/Y9sBP8HooRqfwwHcv9',
'pMgQmojmNbI4VHydRqIBePawnQH+BFJhL04BBADpH8+0EVolpPiOrXTKoBKTiyrB',
'UyxzodyJ8zmVJ3HMTEU/vidpQwzISwoc/ndDFMXQauq6xqBCD9m2BPQI3UdQzXnb',
'LsAI52nWCIqOkzM5NAKWoKhyXK9Y4UH4v9LAYQgl/stIISvCgG4mJ8lzzEBWvRdf',
'Qm2Ghb64/3V5NDdemwARAQAB/gMDAu7L//czBpE40iPcpLzL7GwBbWFhSWgSLy53',
'Md99Kxw3cApWCok2E8R9/4VS0490xKZIa5y2I/K8thVhqk96Z8Kbt7MRMC1WLHgC',
'qJvkeQCI6PrFM0PUIPLHAQtDJYKtaLXxYuexcAdKzZj3FHdtLNWCooK6n3vJlL1c',
'WjZcHJ1PH7USlj1jup4XfxsbziuysRUSyXkjn92GZLm+64vCIiwhqAYoizF2NHHG',
'hRTN4gQzxrxgkeVchl+ag7DkQUDANIIVI+A63JeLJgWJiH1fbYlwESByHW+zBFNt',
'qStjfIOhjrfNIc3RvsggbDdWQLcbxmLZj4sB0ydPSgRKoaUdRHJY0S4vp9ouKOtl',
'2au/P1BP3bhD0fDXl91oeheYth+MSmsJFDg/vZJzCJhFaQ9dp+2EnjN5auNCNbaI',
'beFJRHFf9cha8p3hh+AK54NRCT++B2MXYf+TPwqX88jYMBv8kk8vYUgo8128r1zQ',
'EzjviQE9BBgBAgAJBQJSYS9OAhsuAKgJEEpjYTpNbkCUnSAEGQECAAYFAlJhL04A',
'CgkQ4IT3RGwgLJe6ogQA2aaJEIBIXtgrs+8WSJ4k3DN4rRXcXaUZf667pjdD9nF2',
'3BzjFH6Z78JIGaxRHJdM7b05aE8YuzM8f3NIlT0F0OLq/TI2muYU9f/U2DQBuf+w',
'KTB62+PELVgi9MsXC1Qv/u/o1LZtmmxTFFOD35xKsxZZI2OJj2pQpqObW27M8Nlc',
'BQQAw2YA3fFc38qPK+PY4rZyTRdbvjyyX+1zeqIo8wn7QCQwXs+OGaH2fGoT35AI',
'SXuqKcWqoEuO7OBSEFThCXBfUYMC01OrqKEswPm/V3zZkLu01q12UMwZach28QwK',
'/YZly4ioND2tdazj17u2rU2dwtiHPe1iMqGgVMoQirfLc+k=',
'=lw5e',
'-----END PGP PRIVATE KEY BLOCK-----'].join('\n');
var plaintext = 'short message\nnext line\n한국어/조선말';
var key = openpgp.key.readArmored(pub_key);
var encrypted = openpgp.encryptMessage([key], plaintext);
var message = openpgp.message.readArmored(encrypted);
var privKey = openpgp.key.readArmored(priv_key);
privKey.unlock('hello world');
var decrypted = openpgp.decryptMessage(privKey, message);
result[0] = new unit.result('Encrypt plain text and afterwards decrypt leads to same result', plaintext == decrypted);
return result;
});
},{"../../":28,"../unit.js":70}],"test-bundle.js":[function(require,module,exports){
module.exports=require('QjPZ1q');
},{}],"QjPZ1q":[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');
require('./crypto/openpgp.sigcheck.js');
require('./general/openpgp.basic.js');
},{"./crypto/cipher/aes.js":57,"./crypto/cipher/blowfish.js":58,"./crypto/cipher/cast5.js":59,"./crypto/cipher/des.js":60,"./crypto/cipher/twofish.js":61,"./crypto/hash/md5.js":62,"./crypto/hash/ripemd.js":63,"./crypto/hash/sha.js":64,"./crypto/openpgp.crypto.js":65,"./crypto/openpgp.sigcheck.js":66,"./general/openpgp.basic.js":67,"./unit.js":70}],70:[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":1}]},{},[])
//@ sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9pbnNlcnQtbW9kdWxlLWdsb2JhbHMvbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NvbXByZXNzaW9uL2p4Zy5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NvbmZpZy9jb25maWcuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vY2ZiLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2NpcGhlci9hZXMuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vY2lwaGVyL2Jsb3dmaXNoLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2NpcGhlci9jYXN0NS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9jaXBoZXIvZGVzLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2NpcGhlci9pbmRleC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9jaXBoZXIvdHdvZmlzaC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9jcnlwdG8uanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vaGFzaC9pbmRleC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9oYXNoL21kNS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9oYXNoL3JpcGUtbWQuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vaGFzaC9zaGEuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vaW5kZXguanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcGtjczEuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcHVibGljX2tleS9kc2EuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcHVibGljX2tleS9lbGdhbWFsLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL3B1YmxpY19rZXkvaW5kZXguanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcHVibGljX2tleS9qc2JuLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL3B1YmxpY19rZXkvcnNhLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL3JhbmRvbS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9zaWduYXR1cmUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9lbmNvZGluZy9hcm1vci5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2VuY29kaW5nL2Jhc2U2NC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2VudW1zLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvaW5kZXguanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9rZXkuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9rZXlyaW5nLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvbWVzc2FnZS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL29wZW5wZ3AuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvYWxsX3BhY2tldHMuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvY29tcHJlc3NlZC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9pbmRleC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9saXRlcmFsLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L21hcmtlci5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9vbmVfcGFzc19zaWduYXR1cmUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvcGFja2V0LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L3BhY2tldGxpc3QuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvcHVibGljX2tleS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9wdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9wdWJsaWNfc3Via2V5LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L3NlY3JldF9rZXkuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvc2VjcmV0X3N1YmtleS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9zaWduYXR1cmUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvc3ltX2VuY3J5cHRlZF9pbnRlZ3JpdHlfcHJvdGVjdGVkLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L3N5bV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvdHJ1c3QuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvdXNlcl9hdHRyaWJ1dGUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvdXNlcmlkLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvdHlwZS9rZXlpZC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3R5cGUvbXBpLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvdHlwZS9zMmsuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy91dGlsL3V0aWwuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL2NpcGhlci9hZXMuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL2NpcGhlci9ibG93ZmlzaC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9jcnlwdG8vY2lwaGVyL2Nhc3Q1LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L2NyeXB0by9jaXBoZXIvZGVzLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L2NyeXB0by9jaXBoZXIvdHdvZmlzaC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9jcnlwdG8vaGFzaC9tZDUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL2hhc2gvcmlwZW1kLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L2NyeXB0by9oYXNoL3NoYS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9jcnlwdG8vb3BlbnBncC5jcnlwdG8uanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL29wZW5wZ3Auc2lnY2hlY2suanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvZ2VuZXJhbC9vcGVucGdwLmJhc2ljLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L3Rlc3QtYWxsLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L3VuaXQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdHZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDclpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNWxDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDenFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcE9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRUE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDaElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcblxudmFyIHByb2Nlc3MgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG5wcm9jZXNzLm5leHRUaWNrID0gKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgY2FuU2V0SW1tZWRpYXRlID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcbiAgICAmJiB3aW5kb3cuc2V0SW1tZWRpYXRlO1xuICAgIHZhciBjYW5Qb3N0ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdcbiAgICAmJiB3aW5kb3cucG9zdE1lc3NhZ2UgJiYgd2luZG93LmFkZEV2ZW50TGlzdGVuZXJcbiAgICA7XG5cbiAgICBpZiAoY2FuU2V0SW1tZWRpYXRlKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoZikgeyByZXR1cm4gd2luZG93LnNldEltbWVkaWF0ZShmKSB9O1xuICAgIH1cblxuICAgIGlmIChjYW5Qb3N0KSB7XG4gICAgICAgIHZhciBxdWV1ZSA9IFtdO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIGZ1bmN0aW9uIChldikge1xuICAgICAgICAgICAgaWYgKGV2LnNvdXJjZSA9PT0gd2luZG93ICYmIGV2LmRhdGEgPT09ICdwcm9jZXNzLXRpY2snKSB7XG4gICAgICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZuID0gcXVldWUuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICAgICAgcXVldWUucHVzaChmbik7XG4gICAgICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ3Byb2Nlc3MtdGljaycsICcqJyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgIH07XG59KSgpO1xuXG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcblxucHJvY2Vzcy5iaW5kaW5nID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkJyk7XG59XG5cbi8vIFRPRE8oc2h0eWxtYW4pXG5wcm9jZXNzLmN3ZCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuICcvJyB9O1xucHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcbiIsIkpYRyA9IHtcbiAgZXhpc3RzOiAoZnVuY3Rpb24odW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHYpIHtcbiAgICAgIHJldHVybiAhKHYgPT09IHVuZGVmaW5lZCB8fCB2ID09PSBudWxsKTtcbiAgICB9XG4gIH0pKClcbn07XG5KWEcuZGVjb21wcmVzcyA9IGZ1bmN0aW9uKHN0cikge1xuICByZXR1cm4gdW5lc2NhcGUoKG5ldyBKWEcuVXRpbC5VbnppcChKWEcuVXRpbC5CYXNlNjQuZGVjb2RlQXNBcnJheShzdHIpKSkudW56aXAoKVswXVswXSk7XG59O1xuLypcbiAgICBDb3B5cmlnaHQgMjAwOC0yMDEyXG4gICAgICAgIE1hdHRoaWFzIEVobWFubixcbiAgICAgICAgTWljaGFlbCBHZXJoYWV1c2VyLFxuICAgICAgICBDYXJzdGVuIE1pbGxlcixcbiAgICAgICAgQmlhbmNhIFZhbGVudGluLFxuICAgICAgICBBbGZyZWQgV2Fzc2VybWFubixcbiAgICAgICAgUGV0ZXIgV2lsZmFocnRcblxuICAgIFRoaXMgZmlsZSBpcyBwYXJ0IG9mIEpTWEdyYXBoLlxuICAgIFxuICAgIER1YWwgbGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlIFZlcnNpb24gMi4wLCBvciBMR1BMIFZlcnNpb24gMyBsaWNlbnNlcy5cblxuICAgIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICAgIGFsb25nIHdpdGggSlNYQ29tcHJlc3Nvci4gIElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi5cbiAgICBcbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBBcGFjaGUgTGljZW5zZSBhbG9uZyB3aXRoIEpTWENvbXByZXNzb3IuICBcbiAgICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzLz4uXG5cbiovXG5cbi8qKlxuICogQGNsYXNzIFV0aWwgY2xhc3NcbiAqIEBjbGFzc2Rlc2MgVXRpbGl0aWVzIGZvciB1bmNvbXByZXNzaW5nIGFuZCBiYXNlNjQgZGVjb2RpbmdcbiAqIENsYXNzIGZvciBndW56aXBwaW5nLCB1bnppcHBpbmcgYW5kIGJhc2U2NCBkZWNvZGluZyBvZiBmaWxlcy5cbiAqIEl0IGlzIHVzZWQgZm9yIHJlYWRpbmcgR0VPTkV4VCwgR2VvZ2VicmEgYW5kIEludGVyZ2VvIGZpbGVzLlxuICpcbiAqIE9ubHkgSHVmZm1hbiBjb2RlcyBhcmUgZGVjb2RlZCBpbiBndW56aXAuXG4gKiBUaGUgY29kZSBpcyBiYXNlZCBvbiB0aGUgc291cmNlIGNvZGUgZm9yIGd1bnppcC5jIGJ5IFBhc2kgT2phbGEgXG4gKiB7QGxpbmsgaHR0cDovL3d3dy5jcy50dXQuZmkvfmFsYmVydC9EZXYvZ3VuemlwL2d1bnppcC5jfVxuICoge0BsaW5rIGh0dHA6Ly93d3cuY3MudHV0LmZpL35hbGJlcnR9XG4gKi9cbkpYRy5VdGlsID0ge307XG5cbi8qKlxuICogVW56aXAgemlwIGZpbGVzXG4gKi9cbkpYRy5VdGlsLlVuemlwID0gZnVuY3Rpb24oYmFycmF5KSB7XG4gIHZhciBvdXRwdXRBcnIgPSBbXSxcbiAgICBvdXRwdXQgPSBcIlwiLFxuICAgIGRlYnVnID0gZmFsc2UsXG4gICAgZ3BmbGFncyxcbiAgICBmaWxlcyA9IDAsXG4gICAgdW56aXBwZWQgPSBbXSxcbiAgICBjcmMsXG4gICAgYnVmMzJrID0gbmV3IEFycmF5KDMyNzY4KSxcbiAgICBiSWR4ID0gMCxcbiAgICBtb2RlWklQID0gZmFsc2UsXG5cbiAgICBDUkMsIFNJWkUsXG5cbiAgICBiaXRSZXZlcnNlID0gW1xuICAgICAgICAweDAwLCAweDgwLCAweDQwLCAweGMwLCAweDIwLCAweGEwLCAweDYwLCAweGUwLFxuICAgICAgICAweDEwLCAweDkwLCAweDUwLCAweGQwLCAweDMwLCAweGIwLCAweDcwLCAweGYwLFxuICAgICAgICAweDA4LCAweDg4LCAweDQ4LCAweGM4LCAweDI4LCAweGE4LCAweDY4LCAweGU4LFxuICAgICAgICAweDE4LCAweDk4LCAweDU4LCAweGQ4LCAweDM4LCAweGI4LCAweDc4LCAweGY4LFxuICAgICAgICAweDA0LCAweDg0LCAweDQ0LCAweGM0LCAweDI0LCAweGE0LCAweDY0LCAweGU0LFxuICAgICAgICAweDE0LCAweDk0LCAweDU0LCAweGQ0LCAweDM0LCAweGI0LCAweDc0LCAweGY0LFxuICAgICAgICAweDBjLCAweDhjLCAweDRjLCAweGNjLCAweDJjLCAweGFjLCAweDZjLCAweGVjLFxuICAgICAgICAweDFjLCAweDljLCAweDVjLCAweGRjLCAweDNjLCAweGJjLCAweDdjLCAweGZjLFxuICAgICAgICAweDAyLCAweDgyLCAweDQyLCAweGMyLCAweDIyLCAweGEyLCAweDYyLCAweGUyLFxuICAgICAgICAweDEyLCAweDkyLCAweDUyLCAweGQyLCAweDMyLCAweGIyLCAweDcyLCAweGYyLFxuICAgICAgICAweDBhLCAweDhhLCAweDRhLCAweGNhLCAweDJhLCAweGFhLCAweDZhLCAweGVhLFxuICAgICAgICAweDFhLCAweDlhLCAweDVhLCAweGRhLCAweDNhLCAweGJhLCAweDdhLCAweGZhLFxuICAgICAgICAweDA2LCAweDg2LCAweDQ2LCAweGM2LCAweDI2LCAweGE2LCAweDY2LCAweGU2LFxuICAgICAgICAweDE2LCAweDk2LCAweDU2LCAweGQ2LCAweDM2LCAweGI2LCAweDc2LCAweGY2LFxuICAgICAgICAweDBlLCAweDhlLCAweDRlLCAweGNlLCAweDJlLCAweGFlLCAweDZlLCAweGVlLFxuICAgICAgICAweDFlLCAweDllLCAweDVlLCAweGRlLCAweDNlLCAweGJlLCAweDdlLCAweGZlLFxuICAgICAgICAweDAxLCAweDgxLCAweDQxLCAweGMxLCAweDIxLCAweGExLCAweDYxLCAweGUxLFxuICAgICAgICAweDExLCAweDkxLCAweDUxLCAweGQxLCAweDMxLCAweGIxLCAweDcxLCAweGYxLFxuICAgICAgICAweDA5LCAweDg5LCAweDQ5LCAweGM5LCAweDI5LCAweGE5LCAweDY5LCAweGU5LFxuICAgICAgICAweDE5LCAweDk5LCAweDU5LCAweGQ5LCAweDM5LCAweGI5LCAweDc5LCAweGY5LFxuICAgICAgICAweDA1LCAweDg1LCAweDQ1LCAweGM1LCAweDI1LCAweGE1LCAweDY1LCAweGU1LFxuICAgICAgICAweDE1LCAweDk1LCAweDU1LCAweGQ1LCAweDM1LCAweGI1LCAweDc1LCAweGY1LFxuICAgICAgICAweDBkLCAweDhkLCAweDRkLCAweGNkLCAweDJkLCAweGFkLCAweDZkLCAweGVkLFxuICAgICAgICAweDFkLCAweDlkLCAweDVkLCAweGRkLCAweDNkLCAweGJkLCAweDdkLCAweGZkLFxuICAgICAgICAweDAzLCAweDgzLCAweDQzLCAweGMzLCAweDIzLCAweGEzLCAweDYzLCAweGUzLFxuICAgICAgICAweDEzLCAweDkzLCAweDUzLCAweGQzLCAweDMzLCAweGIzLCAweDczLCAweGYzLFxuICAgICAgICAweDBiLCAweDhiLCAweDRiLCAweGNiLCAweDJiLCAweGFiLCAweDZiLCAweGViLFxuICAgICAgICAweDFiLCAweDliLCAweDViLCAweGRiLCAweDNiLCAweGJiLCAweDdiLCAweGZiLFxuICAgICAgICAweDA3LCAweDg3LCAweDQ3LCAweGM3LCAweDI3LCAweGE3LCAweDY3LCAweGU3LFxuICAgICAgICAweDE3LCAweDk3LCAweDU3LCAweGQ3LCAweDM3LCAweGI3LCAweDc3LCAweGY3LFxuICAgICAgICAweDBmLCAweDhmLCAweDRmLCAweGNmLCAweDJmLCAweGFmLCAweDZmLCAweGVmLFxuICAgICAgICAweDFmLCAweDlmLCAweDVmLCAweGRmLCAweDNmLCAweGJmLCAweDdmLCAweGZmXG4gICAgXSxcblxuICAgIGNwbGVucyA9IFtcbiAgICAgICAgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMywgMTUsIDE3LCAxOSwgMjMsIDI3LCAzMSxcbiAgICAgICAgMzUsIDQzLCA1MSwgNTksIDY3LCA4MywgOTksIDExNSwgMTMxLCAxNjMsIDE5NSwgMjI3LCAyNTgsIDAsIDBcbiAgICBdLFxuXG4gICAgY3BsZXh0ID0gW1xuICAgICAgICAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAxLCAxLCAxLCAxLCAyLCAyLCAyLCAyLFxuICAgICAgICAzLCAzLCAzLCAzLCA0LCA0LCA0LCA0LCA1LCA1LCA1LCA1LCAwLCA5OSwgOTlcbiAgICBdLFxuICAgIC8qIDk5PT1pbnZhbGlkICovXG5cbiAgICBjcGRpc3QgPSBbXG4gICAgICAgIDB4MDAwMSwgMHgwMDAyLCAweDAwMDMsIDB4MDAwNCwgMHgwMDA1LCAweDAwMDcsIDB4MDAwOSwgMHgwMDBkLFxuICAgICAgICAweDAwMTEsIDB4MDAxOSwgMHgwMDIxLCAweDAwMzEsIDB4MDA0MSwgMHgwMDYxLCAweDAwODEsIDB4MDBjMSxcbiAgICAgICAgMHgwMTAxLCAweDAxODEsIDB4MDIwMSwgMHgwMzAxLCAweDA0MDEsIDB4MDYwMSwgMHgwODAxLCAweDBjMDEsXG4gICAgICAgIDB4MTAwMSwgMHgxODAxLCAweDIwMDEsIDB4MzAwMSwgMHg0MDAxLCAweDYwMDFcbiAgICBdLFxuXG4gICAgY3BkZXh0ID0gW1xuICAgICAgICAwLCAwLCAwLCAwLCAxLCAxLCAyLCAyLFxuICAgICAgICAzLCAzLCA0LCA0LCA1LCA1LCA2LCA2LFxuICAgICAgICA3LCA3LCA4LCA4LCA5LCA5LCAxMCwgMTAsXG4gICAgICAgIDExLCAxMSwgMTIsIDEyLCAxMywgMTNcbiAgICBdLFxuXG4gICAgYm9yZGVyID0gWzE2LCAxNywgMTgsIDAsIDgsIDcsIDksIDYsIDEwLCA1LCAxMSwgNCwgMTIsIDMsIDEzLCAyLCAxNCwgMSwgMTVdLFxuXG4gICAgYkEgPSBiYXJyYXksXG5cbiAgICBieXRlcG9zID0gMCxcbiAgICBiaXRwb3MgPSAwLFxuICAgIGJiID0gMSxcbiAgICBiaXRzID0gMCxcblxuICAgIE5BTUVNQVggPSAyNTYsXG5cbiAgICBuYW1lQnVmID0gW10sXG5cbiAgICBmaWxlb3V0O1xuXG4gIGZ1bmN0aW9uIHJlYWRCeXRlKCkge1xuICAgIGJpdHMgKz0gODtcbiAgICBpZiAoYnl0ZXBvcyA8IGJBLmxlbmd0aCkge1xuICAgICAgLy9pZiAoZGVidWcpXG4gICAgICAvLyAgICBkb2N1bWVudC53cml0ZShieXRlcG9zK1wiOiBcIitiQVtieXRlcG9zXStcIjxicj5cIik7XG4gICAgICByZXR1cm4gYkFbYnl0ZXBvcysrXTtcbiAgICB9IGVsc2VcbiAgICAgIHJldHVybiAtMTtcbiAgfTtcblxuICBmdW5jdGlvbiBieXRlQWxpZ24oKSB7XG4gICAgYmIgPSAxO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHJlYWRCaXQoKSB7XG4gICAgdmFyIGNhcnJ5O1xuICAgIGJpdHMrKztcbiAgICBjYXJyeSA9IChiYiAmIDEpO1xuICAgIGJiID4+PSAxO1xuICAgIGlmIChiYiA9PSAwKSB7XG4gICAgICBiYiA9IHJlYWRCeXRlKCk7XG4gICAgICBjYXJyeSA9IChiYiAmIDEpO1xuICAgICAgYmIgPSAoYmIgPj4gMSkgfCAweDgwO1xuICAgIH1cbiAgICByZXR1cm4gY2Fycnk7XG4gIH07XG5cbiAgZnVuY3Rpb24gcmVhZEJpdHMoYSkge1xuICAgIHZhciByZXMgPSAwLFxuICAgICAgaSA9IGE7XG5cbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICByZXMgPSAocmVzIDw8IDEpIHwgcmVhZEJpdCgpO1xuICAgIH1cbiAgICBpZiAoYSkge1xuICAgICAgcmVzID0gYml0UmV2ZXJzZVtyZXNdID4+ICg4IC0gYSk7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH07XG5cbiAgZnVuY3Rpb24gZmx1c2hCdWZmZXIoKSB7XG4gICAgLy9kb2N1bWVudC53cml0ZSgnRkxVU0hCVUZGRVI6JytidWYzMmspO1xuICAgIGJJZHggPSAwO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGFkZEJ1ZmZlcihhKSB7XG4gICAgU0laRSsrO1xuICAgIC8vQ1JDPXVwZGNyYyhhLGNyYyk7XG4gICAgYnVmMzJrW2JJZHgrK10gPSBhO1xuICAgIG91dHB1dEFyci5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYSkpO1xuICAgIC8vb3V0cHV0Kz1TdHJpbmcuZnJvbUNoYXJDb2RlKGEpO1xuICAgIGlmIChiSWR4ID09IDB4ODAwMCkge1xuICAgICAgLy9kb2N1bWVudC53cml0ZSgnQUREQlVGRkVSOicrYnVmMzJrKTtcbiAgICAgIGJJZHggPSAwO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBIdWZOb2RlKCkge1xuICAgIHRoaXMuYjAgPSAwO1xuICAgIHRoaXMuYjEgPSAwO1xuICAgIHRoaXMuanVtcCA9IG51bGw7XG4gICAgdGhpcy5qdW1wcG9zID0gLTE7XG4gIH07XG5cbiAgdmFyIExJVEVSQUxTID0gMjg4O1xuXG4gIHZhciBsaXRlcmFsVHJlZSA9IG5ldyBBcnJheShMSVRFUkFMUyk7XG4gIHZhciBkaXN0YW5jZVRyZWUgPSBuZXcgQXJyYXkoMzIpO1xuICB2YXIgdHJlZXBvcyA9IDA7XG4gIHZhciBQbGFjZXMgPSBudWxsO1xuICB2YXIgUGxhY2VzMiA9IG51bGw7XG5cbiAgdmFyIGltcERpc3RhbmNlVHJlZSA9IG5ldyBBcnJheSg2NCk7XG4gIHZhciBpbXBMZW5ndGhUcmVlID0gbmV3IEFycmF5KDY0KTtcblxuICB2YXIgbGVuID0gMDtcbiAgdmFyIGZwb3MgPSBuZXcgQXJyYXkoMTcpO1xuICBmcG9zWzBdID0gMDtcbiAgdmFyIGZsZW5zO1xuICB2YXIgZm1heDtcblxuICBmdW5jdGlvbiBJc1BhdCgpIHtcbiAgICB3aGlsZSAoMSkge1xuICAgICAgaWYgKGZwb3NbbGVuXSA+PSBmbWF4KVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgICBpZiAoZmxlbnNbZnBvc1tsZW5dXSA9PSBsZW4pXG4gICAgICAgIHJldHVybiBmcG9zW2xlbl0rKztcbiAgICAgIGZwb3NbbGVuXSsrO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBSZWMoKSB7XG4gICAgdmFyIGN1cnBsYWNlID0gUGxhY2VzW3RyZWVwb3NdO1xuICAgIHZhciB0bXA7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+bGVuOlwiICsgbGVuICsgXCIgdHJlZXBvczpcIiArIHRyZWVwb3MpO1xuICAgIGlmIChsZW4gPT0gMTcpIHsgLy93YXIgMTdcbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgdHJlZXBvcysrO1xuICAgIGxlbisrO1xuXG4gICAgdG1wID0gSXNQYXQoKTtcbiAgICBpZiAoZGVidWcpXG4gICAgICBkb2N1bWVudC53cml0ZShcIjxicj5Jc1BhdCBcIiArIHRtcCk7XG4gICAgaWYgKHRtcCA+PSAwKSB7XG4gICAgICBjdXJwbGFjZS5iMCA9IHRtcDsgLyogbGVhZiBjZWxsIGZvciAwLWJpdCAqL1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBkb2N1bWVudC53cml0ZShcIjxicj5iMCBcIiArIGN1cnBsYWNlLmIwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLyogTm90IGEgTGVhZiBjZWxsICovXG4gICAgICBjdXJwbGFjZS5iMCA9IDB4ODAwMDtcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+YjAgXCIgKyBjdXJwbGFjZS5iMCk7XG4gICAgICBpZiAoUmVjKCkpXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgdG1wID0gSXNQYXQoKTtcbiAgICBpZiAodG1wID49IDApIHtcbiAgICAgIGN1cnBsYWNlLmIxID0gdG1wOyAvKiBsZWFmIGNlbGwgZm9yIDEtYml0ICovXG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPmIxIFwiICsgY3VycGxhY2UuYjEpO1xuICAgICAgY3VycGxhY2UuanVtcCA9IG51bGw7IC8qIEp1c3QgZm9yIHRoZSBkaXNwbGF5IHJvdXRpbmUgKi9cbiAgICB9IGVsc2Uge1xuICAgICAgLyogTm90IGEgTGVhZiBjZWxsICovXG4gICAgICBjdXJwbGFjZS5iMSA9IDB4ODAwMDtcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+YjEgXCIgKyBjdXJwbGFjZS5iMSk7XG4gICAgICBjdXJwbGFjZS5qdW1wID0gUGxhY2VzW3RyZWVwb3NdO1xuICAgICAgY3VycGxhY2UuanVtcHBvcyA9IHRyZWVwb3M7XG4gICAgICBpZiAoUmVjKCkpXG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgbGVuLS07XG4gICAgcmV0dXJuIDA7XG4gIH07XG5cbiAgZnVuY3Rpb24gQ3JlYXRlVHJlZShjdXJyZW50VHJlZSwgbnVtdmFsLCBsZW5ndGhzLCBzaG93KSB7XG4gICAgdmFyIGk7XG4gICAgLyogQ3JlYXRlIHRoZSBIdWZmbWFuIGRlY29kZSB0cmVlL3RhYmxlICovXG4gICAgLy9kb2N1bWVudC53cml0ZShcIjxicj5jcmVhdGV0cmVlPGJyPlwiKTtcbiAgICBpZiAoZGVidWcpXG4gICAgICBkb2N1bWVudC53cml0ZShcImN1cnJlbnRUcmVlIFwiICsgY3VycmVudFRyZWUgKyBcIiBudW12YWwgXCIgKyBudW12YWwgKyBcIiBsZW5ndGhzIFwiICsgbGVuZ3RocyArIFwiIHNob3cgXCIgKyBzaG93KTtcbiAgICBQbGFjZXMgPSBjdXJyZW50VHJlZTtcbiAgICB0cmVlcG9zID0gMDtcbiAgICBmbGVucyA9IGxlbmd0aHM7XG4gICAgZm1heCA9IG51bXZhbDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTc7IGkrKylcbiAgICAgIGZwb3NbaV0gPSAwO1xuICAgIGxlbiA9IDA7XG4gICAgaWYgKFJlYygpKSB7XG4gICAgICAvL2ZwcmludGYoc3RkZXJyLCBcImludmFsaWQgaHVmZm1hbiB0cmVlXFxuXCIpO1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChcImludmFsaWQgaHVmZm1hbiB0cmVlXFxuXCIpO1xuICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIGRvY3VtZW50LndyaXRlKCc8YnI+VHJlZTogJyArIFBsYWNlcy5sZW5ndGgpO1xuICAgICAgZm9yICh2YXIgYSA9IDA7IGEgPCAzMjsgYSsrKSB7XG4gICAgICAgIGRvY3VtZW50LndyaXRlKFwiUGxhY2VzW1wiICsgYSArIFwiXS5iMD1cIiArIFBsYWNlc1thXS5iMCArIFwiPGJyPlwiKTtcbiAgICAgICAgZG9jdW1lbnQud3JpdGUoXCJQbGFjZXNbXCIgKyBhICsgXCJdLmIxPVwiICsgUGxhY2VzW2FdLmIxICsgXCI8YnI+XCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qaWYoc2hvdykge1xuICAgICAgICAgICAgdmFyIHRtcDtcbiAgICAgICAgICAgIGZvcih0bXA9Y3VycmVudFRyZWU7dG1wPFBsYWNlczt0bXArKykge1xuICAgICAgICAgICAgICAgIGZwcmludGYoc3Rkb3V0LCBcIjB4JTAzeCAgMHglMDN4ICgweCUwNHgpXCIsdG1wLWN1cnJlbnRUcmVlLCB0bXAtPmp1bXA/dG1wLT5qdW1wLWN1cnJlbnRUcmVlOjAsKHRtcC0+anVtcD90bXAtPmp1bXAtY3VycmVudFRyZWU6MCkqNisweGNmMCk7XG4gICAgICAgICAgICAgICAgaWYoISh0bXAuYjAgJiAweDgwMDApKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vZnByaW50ZihzdGRvdXQsIFwiICAweCUwM3ggKCVjKVwiLCB0bXAtPmIwLCh0bXAtPmIwPDI1NiAmJiBpc3ByaW50KHRtcC0+YjApKT90bXAtPmIwOifvv70nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYoISh0bXAuYjEgJiAweDgwMDApKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKCh0bXAuYjAgJiAweDgwMDApKVxuICAgICAgICAgICAgICAgICAgICAgICAgZnByaW50ZihzdGRvdXQsIFwiICAgICAgICAgICBcIik7XG4gICAgICAgICAgICAgICAgICAgIGZwcmludGYoc3Rkb3V0LCBcIiAgMHglMDN4ICglYylcIiwgdG1wLT5iMSwodG1wLT5iMTwyNTYgJiYgaXNwcmludCh0bXAtPmIxKSk/dG1wLT5iMTon77+9Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZwcmludGYoc3Rkb3V0LCBcIlxcblwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSovXG4gICAgcmV0dXJuIDA7XG4gIH07XG5cbiAgZnVuY3Rpb24gRGVjb2RlVmFsdWUoY3VycmVudFRyZWUpIHtcbiAgICB2YXIgbGVuLCBpLFxuICAgICAgeHRyZWVwb3MgPSAwLFxuICAgICAgWCA9IGN1cnJlbnRUcmVlW3h0cmVlcG9zXSxcbiAgICAgIGI7XG5cbiAgICAvKiBkZWNvZGUgb25lIHN5bWJvbCBvZiB0aGUgZGF0YSAqL1xuICAgIHdoaWxlICgxKSB7XG4gICAgICBiID0gcmVhZEJpdCgpO1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBkb2N1bWVudC53cml0ZShcImI9XCIgKyBiKTtcbiAgICAgIGlmIChiKSB7XG4gICAgICAgIGlmICghKFguYjEgJiAweDgwMDApKSB7XG4gICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgZG9jdW1lbnQud3JpdGUoXCJyZXQxXCIpO1xuICAgICAgICAgIHJldHVybiBYLmIxOyAvKiBJZiBsZWFmIG5vZGUsIHJldHVybiBkYXRhICovXG4gICAgICAgIH1cbiAgICAgICAgWCA9IFguanVtcDtcbiAgICAgICAgbGVuID0gY3VycmVudFRyZWUubGVuZ3RoO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICBpZiAoY3VycmVudFRyZWVbaV0gPT09IFgpIHtcbiAgICAgICAgICAgIHh0cmVlcG9zID0gaTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvL3h0cmVlcG9zKys7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIShYLmIwICYgMHg4MDAwKSkge1xuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwicmV0MlwiKTtcbiAgICAgICAgICByZXR1cm4gWC5iMDsgLyogSWYgbGVhZiBub2RlLCByZXR1cm4gZGF0YSAqL1xuICAgICAgICB9XG4gICAgICAgIC8vWCsrOyAvLz8/Pz8/Pz8/Pz8/Pz8/Pz8/P1xuICAgICAgICB4dHJlZXBvcysrO1xuICAgICAgICBYID0gY3VycmVudFRyZWVbeHRyZWVwb3NdO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoZGVidWcpXG4gICAgICBkb2N1bWVudC53cml0ZShcInJldDNcIik7XG4gICAgcmV0dXJuIC0xO1xuICB9O1xuXG4gIGZ1bmN0aW9uIERlZmxhdGVMb29wKCkge1xuICAgIHZhciBsYXN0LCBjLCB0eXBlLCBpLCBsZW47XG5cbiAgICBkbyB7XG4gICAgICAvKmlmKChsYXN0ID0gcmVhZEJpdCgpKSl7XG4gICAgICAgICAgICBmcHJpbnRmKGVycmZwLCBcIkxhc3QgQmxvY2s6IFwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZwcmludGYoZXJyZnAsIFwiTm90IExhc3QgQmxvY2s6IFwiKTtcbiAgICAgICAgfSovXG4gICAgICBsYXN0ID0gcmVhZEJpdCgpO1xuICAgICAgdHlwZSA9IHJlYWRCaXRzKDIpO1xuICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBhbGVydChcIlN0b3JlZFxcblwiKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGFsZXJ0KFwiRml4ZWQgSHVmZm1hbiBjb2Rlc1xcblwiKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGFsZXJ0KFwiRHluYW1pYyBIdWZmbWFuIGNvZGVzXFxuXCIpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgYWxlcnQoXCJSZXNlcnZlZCBibG9jayB0eXBlISFcXG5cIik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgYWxlcnQoXCJVbmV4cGVjdGVkIHZhbHVlICVkIVxcblwiLCB0eXBlKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGUgPT0gMCkge1xuICAgICAgICB2YXIgYmxvY2tMZW4sIGNTdW07XG5cbiAgICAgICAgLy8gU3RvcmVkIFxuICAgICAgICBieXRlQWxpZ24oKTtcbiAgICAgICAgYmxvY2tMZW4gPSByZWFkQnl0ZSgpO1xuICAgICAgICBibG9ja0xlbiB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcblxuICAgICAgICBjU3VtID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgY1N1bSB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcblxuICAgICAgICBpZiAoKChibG9ja0xlbiBeIH5jU3VtKSAmIDB4ZmZmZikpIHtcbiAgICAgICAgICBkb2N1bWVudC53cml0ZShcIkJsb2NrTGVuIGNoZWNrc3VtIG1pc21hdGNoXFxuXCIpO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChibG9ja0xlbi0tKSB7XG4gICAgICAgICAgYyA9IHJlYWRCeXRlKCk7XG4gICAgICAgICAgYWRkQnVmZmVyKGMpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT0gMSkge1xuICAgICAgICB2YXIgajtcblxuICAgICAgICAvKiBGaXhlZCBIdWZmbWFuIHRhYmxlcyAtLSBmaXhlZCBkZWNvZGUgcm91dGluZSAqL1xuICAgICAgICB3aGlsZSAoMSkge1xuICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgMjU2ICAgIDAwMDAwMDAgICAgICAgIDBcbiAgICAgICAgICAgICAgICA6ICAgOiAgICAgOlxuICAgICAgICAgICAgICAgIDI3OSAgICAwMDEwMTExICAgICAgICAyM1xuICAgICAgICAgICAgICAgIDAgICAwMDExMDAwMCAgICA0OFxuICAgICAgICAgICAgICAgIDogICAgOiAgICAgIDpcbiAgICAgICAgICAgICAgICAxNDMgICAgMTAxMTExMTEgICAgMTkxXG4gICAgICAgICAgICAgICAgMjgwIDExMDAwMDAwICAgIDE5MlxuICAgICAgICAgICAgICAgIDogICAgOiAgICAgIDpcbiAgICAgICAgICAgICAgICAyODcgMTEwMDAxMTEgICAgMTk5XG4gICAgICAgICAgICAgICAgMTQ0ICAgIDExMDAxMDAwMCAgICA0MDBcbiAgICAgICAgICAgICAgICA6ICAgIDogICAgICAgOlxuICAgICAgICAgICAgICAgIDI1NSAgICAxMTExMTExMTEgICAgNTExXG4gICAgXG4gICAgICAgICAgICAgICAgTm90ZSB0aGUgYml0IG9yZGVyIVxuICAgICAgICAgICAgICAgICovXG5cbiAgICAgICAgICBqID0gKGJpdFJldmVyc2VbcmVhZEJpdHMoNyldID4+IDEpO1xuICAgICAgICAgIGlmIChqID4gMjMpIHtcbiAgICAgICAgICAgIGogPSAoaiA8PCAxKSB8IHJlYWRCaXQoKTsgLyogNDguLjI1NSAqL1xuXG4gICAgICAgICAgICBpZiAoaiA+IDE5OSkgeyAvKiAyMDAuLjI1NSAqL1xuICAgICAgICAgICAgICBqIC09IDEyODsgLyogIDcyLi4xMjcgKi9cbiAgICAgICAgICAgICAgaiA9IChqIDw8IDEpIHwgcmVhZEJpdCgpOyAvKiAxNDQuLjI1NSA8PCAqL1xuICAgICAgICAgICAgfSBlbHNlIHsgLyogIDQ4Li4xOTkgKi9cbiAgICAgICAgICAgICAgaiAtPSA0ODsgLyogICAwLi4xNTEgKi9cbiAgICAgICAgICAgICAgaWYgKGogPiAxNDMpIHtcbiAgICAgICAgICAgICAgICBqID0gaiArIDEzNjsgLyogMjgwLi4yODcgPDwgKi9cbiAgICAgICAgICAgICAgICAvKiAgIDAuLjE0MyA8PCAqL1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHsgLyogICAwLi4yMyAqL1xuICAgICAgICAgICAgaiArPSAyNTY7IC8qIDI1Ni4uMjc5IDw8ICovXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChqIDwgMjU2KSB7XG4gICAgICAgICAgICBhZGRCdWZmZXIoaik7XG4gICAgICAgICAgICAvL2RvY3VtZW50LndyaXRlKFwib3V0OlwiK1N0cmluZy5mcm9tQ2hhckNvZGUoaikpO1xuICAgICAgICAgICAgLypmcHJpbnRmKGVycmZwLCBcIkAlZCAlMDJ4XFxuXCIsIFNJWkUsIGopOyovXG4gICAgICAgICAgfSBlbHNlIGlmIChqID09IDI1Nikge1xuICAgICAgICAgICAgLyogRU9GICovXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGxlbiwgZGlzdDtcblxuICAgICAgICAgICAgaiAtPSAyNTYgKyAxOyAvKiBieXRlcyArIEVPRiAqL1xuICAgICAgICAgICAgbGVuID0gcmVhZEJpdHMoY3BsZXh0W2pdKSArIGNwbGVuc1tqXTtcblxuICAgICAgICAgICAgaiA9IGJpdFJldmVyc2VbcmVhZEJpdHMoNSldID4+IDM7XG4gICAgICAgICAgICBpZiAoY3BkZXh0W2pdID4gOCkge1xuICAgICAgICAgICAgICBkaXN0ID0gcmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgIGRpc3QgfD0gKHJlYWRCaXRzKGNwZGV4dFtqXSAtIDgpIDw8IDgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZGlzdCA9IHJlYWRCaXRzKGNwZGV4dFtqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXN0ICs9IGNwZGlzdFtqXTtcblxuICAgICAgICAgICAgLypmcHJpbnRmKGVycmZwLCBcIkAlZCAobCUwMngsZCUwNHgpXFxuXCIsIFNJWkUsIGxlbiwgZGlzdCk7Ki9cbiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW47IGorKykge1xuICAgICAgICAgICAgICB2YXIgYyA9IGJ1ZjMya1soYklkeCAtIGRpc3QpICYgMHg3ZmZmXTtcbiAgICAgICAgICAgICAgYWRkQnVmZmVyKGMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSAvLyB3aGlsZVxuICAgICAgfSBlbHNlIGlmICh0eXBlID09IDIpIHtcbiAgICAgICAgdmFyIGosIG4sIGxpdGVyYWxDb2RlcywgZGlzdENvZGVzLCBsZW5Db2RlcztcbiAgICAgICAgdmFyIGxsID0gbmV3IEFycmF5KDI4OCArIDMyKTsgLy8gXCJzdGF0aWNcIiBqdXN0IHRvIHByZXNlcnZlIHN0YWNrXG5cbiAgICAgICAgLy8gRHluYW1pYyBIdWZmbWFuIHRhYmxlcyBcblxuICAgICAgICBsaXRlcmFsQ29kZXMgPSAyNTcgKyByZWFkQml0cyg1KTtcbiAgICAgICAgZGlzdENvZGVzID0gMSArIHJlYWRCaXRzKDUpO1xuICAgICAgICBsZW5Db2RlcyA9IDQgKyByZWFkQml0cyg0KTtcbiAgICAgICAgLy9kb2N1bWVudC53cml0ZShcIjxicj5wYXJhbTogXCIrbGl0ZXJhbENvZGVzK1wiIFwiK2Rpc3RDb2RlcytcIiBcIitsZW5Db2RlcytcIjxicj5cIik7XG4gICAgICAgIGZvciAoaiA9IDA7IGogPCAxOTsgaisrKSB7XG4gICAgICAgICAgbGxbal0gPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2V0IHRoZSBkZWNvZGUgdHJlZSBjb2RlIGxlbmd0aHNcblxuICAgICAgICAvL2RvY3VtZW50LndyaXRlKFwiPGJyPlwiKTtcbiAgICAgICAgZm9yIChqID0gMDsgaiA8IGxlbkNvZGVzOyBqKyspIHtcbiAgICAgICAgICBsbFtib3JkZXJbal1dID0gcmVhZEJpdHMoMyk7XG4gICAgICAgICAgLy9kb2N1bWVudC53cml0ZShsbFtib3JkZXJbal1dK1wiIFwiKTtcbiAgICAgICAgfVxuICAgICAgICAvL2ZwcmludGYoZXJyZnAsIFwiXFxuXCIpO1xuICAgICAgICAvL2RvY3VtZW50LndyaXRlKCc8YnI+bGw6JytsbCk7XG4gICAgICAgIGxlbiA9IGRpc3RhbmNlVHJlZS5sZW5ndGg7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgICAgICBkaXN0YW5jZVRyZWVbaV0gPSBuZXcgSHVmTm9kZSgpO1xuICAgICAgICBpZiAoQ3JlYXRlVHJlZShkaXN0YW5jZVRyZWUsIDE5LCBsbCwgMCkpIHtcbiAgICAgICAgICBmbHVzaEJ1ZmZlcigpO1xuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZWJ1Zykge1xuICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPmRpc3RhbmNlVHJlZVwiKTtcbiAgICAgICAgICBmb3IgKHZhciBhID0gMDsgYSA8IGRpc3RhbmNlVHJlZS5sZW5ndGg7IGErKykge1xuICAgICAgICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+XCIgKyBkaXN0YW5jZVRyZWVbYV0uYjAgKyBcIiBcIiArIGRpc3RhbmNlVHJlZVthXS5iMSArIFwiIFwiICsgZGlzdGFuY2VUcmVlW2FdLmp1bXAgKyBcIiBcIiArXG4gICAgICAgICAgICAgIGRpc3RhbmNlVHJlZVthXS5qdW1wcG9zKTtcbiAgICAgICAgICAgIC8qaWYgKGRpc3RhbmNlVHJlZVthXS5qdW1wcG9zIT0tMSlcbiAgICAgICAgICAgICAgICAgICAgXHRkb2N1bWVudC53cml0ZShcIiBcIitkaXN0YW5jZVRyZWVbYV0uanVtcC5iMCtcIiBcIitkaXN0YW5jZVRyZWVbYV0uanVtcC5iMSk7XG4gICAgICAgICAgICAgICAgXHQqL1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvL2RvY3VtZW50LndyaXRlKCc8QlI+dHJlZSBjcmVhdGVkJyk7XG5cbiAgICAgICAgLy9yZWFkIGluIGxpdGVyYWwgYW5kIGRpc3RhbmNlIGNvZGUgbGVuZ3Roc1xuICAgICAgICBuID0gbGl0ZXJhbENvZGVzICsgZGlzdENvZGVzO1xuICAgICAgICBpID0gMDtcbiAgICAgICAgdmFyIHogPSAtMTtcbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPm49XCIgKyBuICsgXCIgYml0czogXCIgKyBiaXRzICsgXCI8YnI+XCIpO1xuICAgICAgICB3aGlsZSAoaSA8IG4pIHtcbiAgICAgICAgICB6Kys7XG4gICAgICAgICAgaiA9IERlY29kZVZhbHVlKGRpc3RhbmNlVHJlZSk7XG4gICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+XCIgKyB6ICsgXCIgaTpcIiArIGkgKyBcIiBkZWNvZGU6IFwiICsgaiArIFwiICAgIGJpdHMgXCIgKyBiaXRzICsgXCI8YnI+XCIpO1xuICAgICAgICAgIGlmIChqIDwgMTYpIHsgLy8gbGVuZ3RoIG9mIGNvZGUgaW4gYml0cyAoMC4uMTUpXG4gICAgICAgICAgICBsbFtpKytdID0gajtcbiAgICAgICAgICB9IGVsc2UgaWYgKGogPT0gMTYpIHsgLy8gcmVwZWF0IGxhc3QgbGVuZ3RoIDMgdG8gNiB0aW1lcyBcbiAgICAgICAgICAgIHZhciBsO1xuICAgICAgICAgICAgaiA9IDMgKyByZWFkQml0cygyKTtcbiAgICAgICAgICAgIGlmIChpICsgaiA+IG4pIHtcbiAgICAgICAgICAgICAgZmx1c2hCdWZmZXIoKTtcbiAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsID0gaSA/IGxsW2kgLSAxXSA6IDA7XG4gICAgICAgICAgICB3aGlsZSAoai0tKSB7XG4gICAgICAgICAgICAgIGxsW2krK10gPSBsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoaiA9PSAxNykgeyAvLyAzIHRvIDEwIHplcm8gbGVuZ3RoIGNvZGVzXG4gICAgICAgICAgICAgIGogPSAzICsgcmVhZEJpdHMoMyk7XG4gICAgICAgICAgICB9IGVsc2UgeyAvLyBqID09IDE4OiAxMSB0byAxMzggemVybyBsZW5ndGggY29kZXMgXG4gICAgICAgICAgICAgIGogPSAxMSArIHJlYWRCaXRzKDcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGkgKyBqID4gbikge1xuICAgICAgICAgICAgICBmbHVzaEJ1ZmZlcigpO1xuICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlIChqLS0pIHtcbiAgICAgICAgICAgICAgbGxbaSsrXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qZm9yKGo9MDsgajxsaXRlcmFsQ29kZXMrZGlzdENvZGVzOyBqKyspIHtcbiAgICAgICAgICAgICAgICAvL2ZwcmludGYoZXJyZnAsIFwiJWQgXCIsIGxsW2pdKTtcbiAgICAgICAgICAgICAgICBpZiAoKGomNyk9PTcpXG4gICAgICAgICAgICAgICAgICAgIGZwcmludGYoZXJyZnAsIFwiXFxuXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnByaW50ZihlcnJmcCwgXCJcXG5cIik7Ki9cbiAgICAgICAgLy8gQ2FuIG92ZXJ3cml0ZSB0cmVlIGRlY29kZSB0cmVlIGFzIGl0IGlzIG5vdCB1c2VkIGFueW1vcmVcbiAgICAgICAgbGVuID0gbGl0ZXJhbFRyZWUubGVuZ3RoO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICAgICAgbGl0ZXJhbFRyZWVbaV0gPSBuZXcgSHVmTm9kZSgpO1xuICAgICAgICBpZiAoQ3JlYXRlVHJlZShsaXRlcmFsVHJlZSwgbGl0ZXJhbENvZGVzLCBsbCwgMCkpIHtcbiAgICAgICAgICBmbHVzaEJ1ZmZlcigpO1xuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG4gICAgICAgIGxlbiA9IGxpdGVyYWxUcmVlLmxlbmd0aDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKVxuICAgICAgICAgIGRpc3RhbmNlVHJlZVtpXSA9IG5ldyBIdWZOb2RlKCk7XG4gICAgICAgIHZhciBsbDIgPSBuZXcgQXJyYXkoKTtcbiAgICAgICAgZm9yIChpID0gbGl0ZXJhbENvZGVzOyBpIDwgbGwubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBsbDJbaSAtIGxpdGVyYWxDb2Rlc10gPSBsbFtpXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoQ3JlYXRlVHJlZShkaXN0YW5jZVRyZWUsIGRpc3RDb2RlcywgbGwyLCAwKSkge1xuICAgICAgICAgIGZsdXNoQnVmZmVyKCk7XG4gICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPmxpdGVyYWxUcmVlXCIpO1xuICAgICAgICBvdXRlcjogd2hpbGUgKDEpIHtcbiAgICAgICAgICBqID0gRGVjb2RlVmFsdWUobGl0ZXJhbFRyZWUpO1xuICAgICAgICAgIGlmIChqID49IDI1NikgeyAvLyBJbiBDNjQ6IGlmIGNhcnJ5IHNldFxuICAgICAgICAgICAgdmFyIGxlbiwgZGlzdDtcbiAgICAgICAgICAgIGogLT0gMjU2O1xuICAgICAgICAgICAgaWYgKGogPT0gMCkge1xuICAgICAgICAgICAgICAvLyBFT0ZcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBqLS07XG4gICAgICAgICAgICBsZW4gPSByZWFkQml0cyhjcGxleHRbal0pICsgY3BsZW5zW2pdO1xuXG4gICAgICAgICAgICBqID0gRGVjb2RlVmFsdWUoZGlzdGFuY2VUcmVlKTtcbiAgICAgICAgICAgIGlmIChjcGRleHRbal0gPiA4KSB7XG4gICAgICAgICAgICAgIGRpc3QgPSByZWFkQml0cyg4KTtcbiAgICAgICAgICAgICAgZGlzdCB8PSAocmVhZEJpdHMoY3BkZXh0W2pdIC0gOCkgPDwgOCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBkaXN0ID0gcmVhZEJpdHMoY3BkZXh0W2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRpc3QgKz0gY3BkaXN0W2pdO1xuICAgICAgICAgICAgd2hpbGUgKGxlbi0tKSB7XG4gICAgICAgICAgICAgIGlmIChiSWR4IC0gZGlzdCA8IDApIHtcbiAgICAgICAgICAgICAgICBicmVhayBvdXRlcjtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB2YXIgYyA9IGJ1ZjMya1soYklkeCAtIGRpc3QpICYgMHg3ZmZmXTtcbiAgICAgICAgICAgICAgYWRkQnVmZmVyKGMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhZGRCdWZmZXIoaik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSB3aGlsZSAoIWxhc3QpO1xuICAgIGZsdXNoQnVmZmVyKCk7XG5cbiAgICBieXRlQWxpZ24oKTtcbiAgICByZXR1cm4gMDtcbiAgfTtcblxuICBKWEcuVXRpbC5VbnppcC5wcm90b3R5cGUudW56aXBGaWxlID0gZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBpO1xuICAgIHRoaXMudW56aXAoKTtcbiAgICAvL2FsZXJ0KHVuemlwcGVkWzBdWzFdKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdW56aXBwZWQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICh1bnppcHBlZFtpXVsxXSA9PSBuYW1lKSB7XG4gICAgICAgIHJldHVybiB1bnppcHBlZFtpXVswXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgfTtcblxuICBKWEcuVXRpbC5VbnppcC5wcm90b3R5cGUuZGVmbGF0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIG91dHB1dEFyciA9IFtdO1xuICAgIHZhciB0bXAgPSBbXTtcbiAgICBtb2RlWklQID0gZmFsc2U7XG4gICAgRGVmbGF0ZUxvb3AoKTtcbiAgICBpZiAoZGVidWcpXG4gICAgICBhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuICAgIHVuemlwcGVkW2ZpbGVzXSA9IG5ldyBBcnJheSgyKTtcbiAgICB1bnppcHBlZFtmaWxlc11bMF0gPSBvdXRwdXRBcnIuam9pbignJyk7XG4gICAgdW56aXBwZWRbZmlsZXNdWzFdID0gXCJERUZMQVRFXCI7XG4gICAgZmlsZXMrKztcbiAgICByZXR1cm4gdW56aXBwZWQ7XG4gIH1cblxuICBKWEcuVXRpbC5VbnppcC5wcm90b3R5cGUudW56aXAgPSBmdW5jdGlvbigpIHtcbiAgICAvL2NvbnZlcnRUb0J5dGVBcnJheShpbnB1dCk7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgYWxlcnQoYkEpO1xuICAgIC8qZm9yIChpPTA7aTxiQS5sZW5ndGgqODtpKyspe1xuXHRcdGRvY3VtZW50LndyaXRlKHJlYWRCaXQoKSk7XG5cdFx0aWYgKChpKzEpJTg9PTApXG5cdFx0XHRkb2N1bWVudC53cml0ZShcIiBcIik7XG5cdH0qL1xuICAgIC8qZm9yIChpPTA7aTxiQS5sZW5ndGg7aSsrKXtcblx0XHRkb2N1bWVudC53cml0ZShyZWFkQnl0ZSgpK1wiIFwiKTtcblx0XHRpZiAoKGkrMSklOD09MClcblx0XHRcdGRvY3VtZW50LndyaXRlKFwiIFwiKTtcblx0fVxuXHRmb3IgKGk9MDtpPGJBLmxlbmd0aDtpKyspe1xuXHRcdGRvY3VtZW50LndyaXRlKGJBW2ldK1wiIFwiKTtcblx0XHRpZiAoKGkrMSklMTY9PTApXG5cdFx0XHRkb2N1bWVudC53cml0ZShcIjxicj5cIik7XG5cdH1cdFxuXHQqL1xuICAgIC8vYWxlcnQoYkEpO1xuICAgIG5leHRGaWxlKCk7XG4gICAgcmV0dXJuIHVuemlwcGVkO1xuICB9O1xuXG4gIGZ1bmN0aW9uIG5leHRGaWxlKCkge1xuICAgIGlmIChkZWJ1ZylcbiAgICAgIGFsZXJ0KFwiTkVYVEZJTEVcIik7XG4gICAgb3V0cHV0QXJyID0gW107XG4gICAgdmFyIHRtcCA9IFtdO1xuICAgIG1vZGVaSVAgPSBmYWxzZTtcbiAgICB0bXBbMF0gPSByZWFkQnl0ZSgpO1xuICAgIHRtcFsxXSA9IHJlYWRCeXRlKCk7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgYWxlcnQoXCJ0eXBlOiBcIiArIHRtcFswXSArIFwiIFwiICsgdG1wWzFdKTtcbiAgICBpZiAodG1wWzBdID09IHBhcnNlSW50KFwiNzhcIiwgMTYpICYmIHRtcFsxXSA9PSBwYXJzZUludChcImRhXCIsIDE2KSkgeyAvL0daSVBcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgYWxlcnQoXCJHRU9ORXhULUdaSVBcIik7XG4gICAgICBEZWZsYXRlTG9vcCgpO1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdID0gbmV3IEFycmF5KDIpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdWzBdID0gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdWzFdID0gXCJnZW9uZXh0Lmd4dFwiO1xuICAgICAgZmlsZXMrKztcbiAgICB9XG4gICAgaWYgKHRtcFswXSA9PSBwYXJzZUludChcIjc4XCIsIDE2KSAmJiB0bXBbMV0gPT0gcGFyc2VJbnQoXCI5Y1wiLCAxNikpIHsgLy9aTElCXG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KFwiWkxJQlwiKTtcbiAgICAgIERlZmxhdGVMb29wKCk7XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KG91dHB1dEFyci5qb2luKCcnKSk7XG4gICAgICB1bnppcHBlZFtmaWxlc10gPSBuZXcgQXJyYXkoMik7XG4gICAgICB1bnppcHBlZFtmaWxlc11bMF0gPSBvdXRwdXRBcnIuam9pbignJyk7XG4gICAgICB1bnppcHBlZFtmaWxlc11bMV0gPSBcIlpMSUJcIjtcbiAgICAgIGZpbGVzKys7XG4gICAgfVxuICAgIGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCIxZlwiLCAxNikgJiYgdG1wWzFdID09IHBhcnNlSW50KFwiOGJcIiwgMTYpKSB7IC8vR1pJUFxuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChcIkdaSVBcIik7XG4gICAgICAvL0RlZmxhdGVMb29wKCk7XG4gICAgICBza2lwZGlyKCk7XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KG91dHB1dEFyci5qb2luKCcnKSk7XG4gICAgICB1bnppcHBlZFtmaWxlc10gPSBuZXcgQXJyYXkoMik7XG4gICAgICB1bnppcHBlZFtmaWxlc11bMF0gPSBvdXRwdXRBcnIuam9pbignJyk7XG4gICAgICB1bnppcHBlZFtmaWxlc11bMV0gPSBcImZpbGVcIjtcbiAgICAgIGZpbGVzKys7XG4gICAgfVxuICAgIGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI1MFwiLCAxNikgJiYgdG1wWzFdID09IHBhcnNlSW50KFwiNGJcIiwgMTYpKSB7IC8vWklQXG4gICAgICBtb2RlWklQID0gdHJ1ZTtcbiAgICAgIHRtcFsyXSA9IHJlYWRCeXRlKCk7XG4gICAgICB0bXBbM10gPSByZWFkQnl0ZSgpO1xuICAgICAgaWYgKHRtcFsyXSA9PSBwYXJzZUludChcIjNcIiwgMTYpICYmIHRtcFszXSA9PSBwYXJzZUludChcIjRcIiwgMTYpKSB7XG4gICAgICAgIC8vTU9ERV9aSVBcbiAgICAgICAgdG1wWzBdID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgdG1wWzFdID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgIGFsZXJ0KFwiWklQLVZlcnNpb246IFwiICsgdG1wWzFdICsgXCIgXCIgKyB0bXBbMF0gLyAxMCArIFwiLlwiICsgdG1wWzBdICUgMTApO1xuXG4gICAgICAgIGdwZmxhZ3MgPSByZWFkQnl0ZSgpO1xuICAgICAgICBncGZsYWdzIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgYWxlcnQoXCJncGZsYWdzOiBcIiArIGdwZmxhZ3MpO1xuXG4gICAgICAgIHZhciBtZXRob2QgPSByZWFkQnl0ZSgpO1xuICAgICAgICBtZXRob2QgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICBhbGVydChcIm1ldGhvZDogXCIgKyBtZXRob2QpO1xuXG4gICAgICAgIHJlYWRCeXRlKCk7XG4gICAgICAgIHJlYWRCeXRlKCk7XG4gICAgICAgIHJlYWRCeXRlKCk7XG4gICAgICAgIHJlYWRCeXRlKCk7XG5cbiAgICAgICAgdmFyIGNyYyA9IHJlYWRCeXRlKCk7XG4gICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICAgICAgY3JjIHw9IChyZWFkQnl0ZSgpIDw8IDE2KTtcbiAgICAgICAgY3JjIHw9IChyZWFkQnl0ZSgpIDw8IDI0KTtcblxuICAgICAgICB2YXIgY29tcFNpemUgPSByZWFkQnl0ZSgpO1xuICAgICAgICBjb21wU2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICAgICAgY29tcFNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMTYpO1xuICAgICAgICBjb21wU2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG5cbiAgICAgICAgdmFyIHNpemUgPSByZWFkQnl0ZSgpO1xuICAgICAgICBzaXplIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuICAgICAgICBzaXplIHw9IChyZWFkQnl0ZSgpIDw8IDE2KTtcbiAgICAgICAgc2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG5cbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgIGFsZXJ0KFwibG9jYWwgQ1JDOiBcIiArIGNyYyArIFwiXFxubG9jYWwgU2l6ZTogXCIgKyBzaXplICsgXCJcXG5sb2NhbCBDb21wU2l6ZTogXCIgKyBjb21wU2l6ZSk7XG5cbiAgICAgICAgdmFyIGZpbGVsZW4gPSByZWFkQnl0ZSgpO1xuICAgICAgICBmaWxlbGVuIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuXG4gICAgICAgIHZhciBleHRyYWxlbiA9IHJlYWRCeXRlKCk7XG4gICAgICAgIGV4dHJhbGVuIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuXG4gICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICBhbGVydChcImZpbGVsZW4gXCIgKyBmaWxlbGVuKTtcbiAgICAgICAgaSA9IDA7XG4gICAgICAgIG5hbWVCdWYgPSBbXTtcbiAgICAgICAgd2hpbGUgKGZpbGVsZW4tLSkge1xuICAgICAgICAgIHZhciBjID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgICBpZiAoYyA9PSBcIi9cIiB8IGMgPT0gXCI6XCIpIHtcbiAgICAgICAgICAgIGkgPSAwO1xuICAgICAgICAgIH0gZWxzZSBpZiAoaSA8IE5BTUVNQVggLSAxKVxuICAgICAgICAgICAgbmFtZUJ1ZltpKytdID0gU3RyaW5nLmZyb21DaGFyQ29kZShjKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgYWxlcnQoXCJuYW1lQnVmOiBcIiArIG5hbWVCdWYpO1xuXG4gICAgICAgIC8vbmFtZUJ1ZltpXSA9IFwiXFwwXCI7XG4gICAgICAgIGlmICghZmlsZW91dClcbiAgICAgICAgICBmaWxlb3V0ID0gbmFtZUJ1ZjtcblxuICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgIHdoaWxlIChpIDwgZXh0cmFsZW4pIHtcbiAgICAgICAgICBjID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgICBpKys7XG4gICAgICAgIH1cblxuICAgICAgICBDUkMgPSAweGZmZmZmZmZmO1xuICAgICAgICBTSVpFID0gMDtcblxuICAgICAgICBpZiAoc2l6ZSA9IDAgJiYgZmlsZU91dC5jaGFyQXQoZmlsZW91dC5sZW5ndGggLSAxKSA9PSBcIi9cIikge1xuICAgICAgICAgIC8vc2tpcGRpclxuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGFsZXJ0KFwic2tpcGRpclwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWV0aG9kID09IDgpIHtcbiAgICAgICAgICBEZWZsYXRlTG9vcCgpO1xuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGFsZXJ0KG91dHB1dEFyci5qb2luKCcnKSk7XG4gICAgICAgICAgdW56aXBwZWRbZmlsZXNdID0gbmV3IEFycmF5KDIpO1xuICAgICAgICAgIHVuemlwcGVkW2ZpbGVzXVswXSA9IG91dHB1dEFyci5qb2luKCcnKTtcbiAgICAgICAgICB1bnppcHBlZFtmaWxlc11bMV0gPSBuYW1lQnVmLmpvaW4oJycpO1xuICAgICAgICAgIGZpbGVzKys7XG4gICAgICAgICAgLy9yZXR1cm4gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgICAgICB9XG4gICAgICAgIHNraXBkaXIoKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gc2tpcGRpcigpIHtcbiAgICB2YXIgY3JjLFxuICAgICAgdG1wID0gW10sXG4gICAgICBjb21wU2l6ZSwgc2l6ZSwgb3MsIGksIGM7XG5cbiAgICBpZiAoKGdwZmxhZ3MgJiA4KSkge1xuICAgICAgdG1wWzBdID0gcmVhZEJ5dGUoKTtcbiAgICAgIHRtcFsxXSA9IHJlYWRCeXRlKCk7XG4gICAgICB0bXBbMl0gPSByZWFkQnl0ZSgpO1xuICAgICAgdG1wWzNdID0gcmVhZEJ5dGUoKTtcblxuICAgICAgaWYgKHRtcFswXSA9PSBwYXJzZUludChcIjUwXCIsIDE2KSAmJlxuICAgICAgICB0bXBbMV0gPT0gcGFyc2VJbnQoXCI0YlwiLCAxNikgJiZcbiAgICAgICAgdG1wWzJdID09IHBhcnNlSW50KFwiMDdcIiwgMTYpICYmXG4gICAgICAgIHRtcFszXSA9PSBwYXJzZUludChcIjA4XCIsIDE2KSkge1xuICAgICAgICBjcmMgPSByZWFkQnl0ZSgpO1xuICAgICAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCAxNik7XG4gICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcmMgPSB0bXBbMF0gfCAodG1wWzFdIDw8IDgpIHwgKHRtcFsyXSA8PCAxNikgfCAodG1wWzNdIDw8IDI0KTtcbiAgICAgIH1cblxuICAgICAgY29tcFNpemUgPSByZWFkQnl0ZSgpO1xuICAgICAgY29tcFNpemUgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgICBjb21wU2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCAxNik7XG4gICAgICBjb21wU2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG5cbiAgICAgIHNpemUgPSByZWFkQnl0ZSgpO1xuICAgICAgc2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICAgIHNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMTYpO1xuICAgICAgc2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG5cbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgYWxlcnQoXCJDUkM6XCIpO1xuICAgIH1cblxuICAgIGlmIChtb2RlWklQKVxuICAgICAgbmV4dEZpbGUoKTtcblxuICAgIHRtcFswXSA9IHJlYWRCeXRlKCk7XG4gICAgaWYgKHRtcFswXSAhPSA4KSB7XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KFwiVW5rbm93biBjb21wcmVzc2lvbiBtZXRob2QhXCIpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgZ3BmbGFncyA9IHJlYWRCeXRlKCk7XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBpZiAoKGdwZmxhZ3MgJiB+KHBhcnNlSW50KFwiMWZcIiwgMTYpKSkpXG4gICAgICAgIGFsZXJ0KFwiVW5rbm93biBmbGFncyBzZXQhXCIpO1xuICAgIH1cblxuICAgIHJlYWRCeXRlKCk7XG4gICAgcmVhZEJ5dGUoKTtcbiAgICByZWFkQnl0ZSgpO1xuICAgIHJlYWRCeXRlKCk7XG5cbiAgICByZWFkQnl0ZSgpO1xuICAgIG9zID0gcmVhZEJ5dGUoKTtcblxuICAgIGlmICgoZ3BmbGFncyAmIDQpKSB7XG4gICAgICB0bXBbMF0gPSByZWFkQnl0ZSgpO1xuICAgICAgdG1wWzJdID0gcmVhZEJ5dGUoKTtcbiAgICAgIGxlbiA9IHRtcFswXSArIDI1NiAqIHRtcFsxXTtcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgYWxlcnQoXCJFeHRyYSBmaWVsZCBzaXplOiBcIiArIGxlbik7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICAgIHJlYWRCeXRlKCk7XG4gICAgfVxuXG4gICAgaWYgKChncGZsYWdzICYgOCkpIHtcbiAgICAgIGkgPSAwO1xuICAgICAgbmFtZUJ1ZiA9IFtdO1xuICAgICAgd2hpbGUgKGMgPSByZWFkQnl0ZSgpKSB7XG4gICAgICAgIGlmIChjID09IFwiN1wiIHx8IGMgPT0gXCI6XCIpXG4gICAgICAgICAgaSA9IDA7XG4gICAgICAgIGlmIChpIDwgTkFNRU1BWCAtIDEpXG4gICAgICAgICAgbmFtZUJ1ZltpKytdID0gYztcbiAgICAgIH1cbiAgICAgIC8vbmFtZUJ1ZltpXSA9IFwiXFwwXCI7XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KFwib3JpZ2luYWwgZmlsZSBuYW1lOiBcIiArIG5hbWVCdWYpO1xuICAgIH1cblxuICAgIGlmICgoZ3BmbGFncyAmIDE2KSkge1xuICAgICAgd2hpbGUgKGMgPSByZWFkQnl0ZSgpKSB7XG4gICAgICAgIC8vRklMRSBDT01NRU5UXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKChncGZsYWdzICYgMikpIHtcbiAgICAgIHJlYWRCeXRlKCk7XG4gICAgICByZWFkQnl0ZSgpO1xuICAgIH1cblxuICAgIERlZmxhdGVMb29wKCk7XG5cbiAgICBjcmMgPSByZWFkQnl0ZSgpO1xuICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgMTYpO1xuICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG5cbiAgICBzaXplID0gcmVhZEJ5dGUoKTtcbiAgICBzaXplIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuICAgIHNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMTYpO1xuICAgIHNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuXG4gICAgaWYgKG1vZGVaSVApXG4gICAgICBuZXh0RmlsZSgpO1xuXG4gIH07XG5cbn07XG5cbi8qKlxuICogIEJhc2U2NCBlbmNvZGluZyAvIGRlY29kaW5nXG4gKiAge0BsaW5rIGh0dHA6Ly93d3cud2VidG9vbGtpdC5pbmZvL31cbiAqL1xuSlhHLlV0aWwuQmFzZTY0ID0ge1xuXG4gIC8vIHByaXZhdGUgcHJvcGVydHlcbiAgX2tleVN0cjogXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvPVwiLFxuXG4gIC8vIHB1YmxpYyBtZXRob2QgZm9yIGVuY29kaW5nXG4gIGVuY29kZTogZnVuY3Rpb24oaW5wdXQpIHtcbiAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICBjaHIxLCBjaHIyLCBjaHIzLCBlbmMxLCBlbmMyLCBlbmMzLCBlbmM0LFxuICAgICAgaSA9IDA7XG5cbiAgICBpbnB1dCA9IEpYRy5VdGlsLkJhc2U2NC5fdXRmOF9lbmNvZGUoaW5wdXQpO1xuXG4gICAgd2hpbGUgKGkgPCBpbnB1dC5sZW5ndGgpIHtcblxuICAgICAgY2hyMSA9IGlucHV0LmNoYXJDb2RlQXQoaSsrKTtcbiAgICAgIGNocjIgPSBpbnB1dC5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICBjaHIzID0gaW5wdXQuY2hhckNvZGVBdChpKyspO1xuXG4gICAgICBlbmMxID0gY2hyMSA+PiAyO1xuICAgICAgZW5jMiA9ICgoY2hyMSAmIDMpIDw8IDQpIHwgKGNocjIgPj4gNCk7XG4gICAgICBlbmMzID0gKChjaHIyICYgMTUpIDw8IDIpIHwgKGNocjMgPj4gNik7XG4gICAgICBlbmM0ID0gY2hyMyAmIDYzO1xuXG4gICAgICBpZiAoaXNOYU4oY2hyMikpIHtcbiAgICAgICAgZW5jMyA9IGVuYzQgPSA2NDtcbiAgICAgIH0gZWxzZSBpZiAoaXNOYU4oY2hyMykpIHtcbiAgICAgICAgZW5jNCA9IDY0O1xuICAgICAgfVxuXG4gICAgICBvdXRwdXQucHVzaChbdGhpcy5fa2V5U3RyLmNoYXJBdChlbmMxKSxcbiAgICAgICAgICB0aGlzLl9rZXlTdHIuY2hhckF0KGVuYzIpLFxuICAgICAgICAgIHRoaXMuX2tleVN0ci5jaGFyQXQoZW5jMyksXG4gICAgICAgICAgdGhpcy5fa2V5U3RyLmNoYXJBdChlbmM0KVxuICAgICAgXS5qb2luKCcnKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dC5qb2luKCcnKTtcbiAgfSxcblxuICAvLyBwdWJsaWMgbWV0aG9kIGZvciBkZWNvZGluZ1xuICBkZWNvZGU6IGZ1bmN0aW9uKGlucHV0LCB1dGY4KSB7XG4gICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgY2hyMSwgY2hyMiwgY2hyMyxcbiAgICAgIGVuYzEsIGVuYzIsIGVuYzMsIGVuYzQsXG4gICAgICBpID0gMDtcblxuICAgIGlucHV0ID0gaW5wdXQucmVwbGFjZSgvW15BLVphLXowLTlcXCtcXC9cXD1dL2csIFwiXCIpO1xuXG4gICAgd2hpbGUgKGkgPCBpbnB1dC5sZW5ndGgpIHtcblxuICAgICAgZW5jMSA9IHRoaXMuX2tleVN0ci5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcbiAgICAgIGVuYzIgPSB0aGlzLl9rZXlTdHIuaW5kZXhPZihpbnB1dC5jaGFyQXQoaSsrKSk7XG4gICAgICBlbmMzID0gdGhpcy5fa2V5U3RyLmluZGV4T2YoaW5wdXQuY2hhckF0KGkrKykpO1xuICAgICAgZW5jNCA9IHRoaXMuX2tleVN0ci5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcblxuICAgICAgY2hyMSA9IChlbmMxIDw8IDIpIHwgKGVuYzIgPj4gNCk7XG4gICAgICBjaHIyID0gKChlbmMyICYgMTUpIDw8IDQpIHwgKGVuYzMgPj4gMik7XG4gICAgICBjaHIzID0gKChlbmMzICYgMykgPDwgNikgfCBlbmM0O1xuXG4gICAgICBvdXRwdXQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNocjEpKTtcblxuICAgICAgaWYgKGVuYzMgIT0gNjQpIHtcbiAgICAgICAgb3V0cHV0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaHIyKSk7XG4gICAgICB9XG4gICAgICBpZiAoZW5jNCAhPSA2NCkge1xuICAgICAgICBvdXRwdXQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNocjMpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBvdXRwdXQgPSBvdXRwdXQuam9pbignJyk7XG5cbiAgICBpZiAodXRmOCkge1xuICAgICAgb3V0cHV0ID0gSlhHLlV0aWwuQmFzZTY0Ll91dGY4X2RlY29kZShvdXRwdXQpO1xuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0O1xuXG4gIH0sXG5cbiAgLy8gcHJpdmF0ZSBtZXRob2QgZm9yIFVURi04IGVuY29kaW5nXG4gIF91dGY4X2VuY29kZTogZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgc3RyaW5nID0gc3RyaW5nLnJlcGxhY2UoL1xcclxcbi9nLCBcIlxcblwiKTtcbiAgICB2YXIgdXRmdGV4dCA9IFwiXCI7XG5cbiAgICBmb3IgKHZhciBuID0gMDsgbiA8IHN0cmluZy5sZW5ndGg7IG4rKykge1xuXG4gICAgICB2YXIgYyA9IHN0cmluZy5jaGFyQ29kZUF0KG4pO1xuXG4gICAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYyk7XG4gICAgICB9IGVsc2UgaWYgKChjID4gMTI3KSAmJiAoYyA8IDIwNDgpKSB7XG4gICAgICAgIHV0ZnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoYyA+PiA2KSB8IDE5Mik7XG4gICAgICAgIHV0ZnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoYyAmIDYzKSB8IDEyOCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgPj4gMTIpIHwgMjI0KTtcbiAgICAgICAgdXRmdGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgoYyA+PiA2KSAmIDYzKSB8IDEyOCk7XG4gICAgICAgIHV0ZnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoYyAmIDYzKSB8IDEyOCk7XG4gICAgICB9XG5cbiAgICB9XG5cbiAgICByZXR1cm4gdXRmdGV4dDtcbiAgfSxcblxuICAvLyBwcml2YXRlIG1ldGhvZCBmb3IgVVRGLTggZGVjb2RpbmdcbiAgX3V0ZjhfZGVjb2RlOiBmdW5jdGlvbih1dGZ0ZXh0KSB7XG4gICAgdmFyIHN0cmluZyA9IFtdLFxuICAgICAgaSA9IDAsXG4gICAgICBjID0gMCxcbiAgICAgIGMyID0gMCxcbiAgICAgIGMzID0gMDtcblxuICAgIHdoaWxlIChpIDwgdXRmdGV4dC5sZW5ndGgpIHtcbiAgICAgIGMgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgICBzdHJpbmcucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGMpKTtcbiAgICAgICAgaSsrO1xuICAgICAgfSBlbHNlIGlmICgoYyA+IDE5MSkgJiYgKGMgPCAyMjQpKSB7XG4gICAgICAgIGMyID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkgKyAxKTtcbiAgICAgICAgc3RyaW5nLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMgJiAzMSkgPDwgNikgfCAoYzIgJiA2MykpKTtcbiAgICAgICAgaSArPSAyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYzIgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgICBjMyA9IHV0ZnRleHQuY2hhckNvZGVBdChpICsgMik7XG4gICAgICAgIHN0cmluZy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoKChjICYgMTUpIDw8IDEyKSB8ICgoYzIgJiA2MykgPDwgNikgfCAoYzMgJiA2MykpKTtcbiAgICAgICAgaSArPSAzO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3RyaW5nLmpvaW4oJycpO1xuICB9LFxuXG4gIF9kZXN0cmlwOiBmdW5jdGlvbihzdHJpcHBlZCwgd3JhcCkge1xuICAgIHZhciBsaW5lcyA9IFtdLFxuICAgICAgbGluZW5vLCBpLFxuICAgICAgZGVzdHJpcHBlZCA9IFtdO1xuXG4gICAgaWYgKHdyYXAgPT0gbnVsbClcbiAgICAgIHdyYXAgPSA3NjtcblxuICAgIHN0cmlwcGVkLnJlcGxhY2UoLyAvZywgXCJcIik7XG4gICAgbGluZW5vID0gc3RyaXBwZWQubGVuZ3RoIC8gd3JhcDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGluZW5vOyBpKyspXG4gICAgICBsaW5lc1tpXSA9IHN0cmlwcGVkLnN1YnN0cihpICogd3JhcCwgd3JhcCk7XG4gICAgaWYgKGxpbmVubyAhPSBzdHJpcHBlZC5sZW5ndGggLyB3cmFwKVxuICAgICAgbGluZXNbbGluZXMubGVuZ3RoXSA9IHN0cmlwcGVkLnN1YnN0cihsaW5lbm8gKiB3cmFwLCBzdHJpcHBlZC5sZW5ndGggLSAobGluZW5vICogd3JhcCkpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKVxuICAgICAgZGVzdHJpcHBlZC5wdXNoKGxpbmVzW2ldKTtcbiAgICByZXR1cm4gZGVzdHJpcHBlZC5qb2luKCdcXG4nKTtcbiAgfSxcblxuICBkZWNvZGVBc0FycmF5OiBmdW5jdGlvbihpbnB1dCkge1xuICAgIHZhciBkZWMgPSB0aGlzLmRlY29kZShpbnB1dCksXG4gICAgICBhciA9IFtdLFxuICAgICAgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgZGVjLmxlbmd0aDsgaSsrKSB7XG4gICAgICBhcltpXSA9IGRlYy5jaGFyQ29kZUF0KGkpO1xuICAgIH1cbiAgICByZXR1cm4gYXI7XG4gIH0sXG5cbiAgZGVjb2RlR0VPTkV4VDogZnVuY3Rpb24oaW5wdXQpIHtcbiAgICByZXR1cm4gZGVjb2RlQXNBcnJheShkZXN0cmlwKGlucHV0KSwgZmFsc2UpO1xuICB9XG59O1xuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbkpYRy5VdGlsLmFzY2lpQ2hhckNvZGVBdCA9IGZ1bmN0aW9uKHN0ciwgaSkge1xuICB2YXIgYyA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICBpZiAoYyA+IDI1NSkge1xuICAgIHN3aXRjaCAoYykge1xuICAgICAgY2FzZSA4MzY0OlxuICAgICAgICBjID0gMTI4O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIxODpcbiAgICAgICAgYyA9IDEzMDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDQwMjpcbiAgICAgICAgYyA9IDEzMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMjI6XG4gICAgICAgIGMgPSAxMzI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjMwOlxuICAgICAgICBjID0gMTMzO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIyNDpcbiAgICAgICAgYyA9IDEzNDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMjU6XG4gICAgICAgIGMgPSAxMzU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA3MTA6XG4gICAgICAgIGMgPSAxMzY7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjQwOlxuICAgICAgICBjID0gMTM3O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzUyOlxuICAgICAgICBjID0gMTM4O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODI0OTpcbiAgICAgICAgYyA9IDEzOTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDMzODpcbiAgICAgICAgYyA9IDE0MDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM4MTpcbiAgICAgICAgYyA9IDE0MjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMTY6XG4gICAgICAgIGMgPSAxNDU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjE3OlxuICAgICAgICBjID0gMTQ2O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIyMDpcbiAgICAgICAgYyA9IDE0NztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMjE6XG4gICAgICAgIGMgPSAxNDg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjI2OlxuICAgICAgICBjID0gMTQ5O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIxMTpcbiAgICAgICAgYyA9IDE1MDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMTI6XG4gICAgICAgIGMgPSAxNTE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA3MzI6XG4gICAgICAgIGMgPSAxNTI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4NDgyOlxuICAgICAgICBjID0gMTUzO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzUzOlxuICAgICAgICBjID0gMTU0O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODI1MDpcbiAgICAgICAgYyA9IDE1NTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDMzOTpcbiAgICAgICAgYyA9IDE1NjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM4MjpcbiAgICAgICAgYyA9IDE1ODtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM3NjpcbiAgICAgICAgYyA9IDE1OTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGM7XG59O1xuXG4vKipcbiAqIERlY29kaW5nIHN0cmluZyBpbnRvIHV0Zi04XG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyaW5nIHRvIGRlY29kZVxuICogQHJldHVybiB7U3RyaW5nfSB1dGY4IGRlY29kZWQgc3RyaW5nXG4gKi9cbkpYRy5VdGlsLnV0ZjhEZWNvZGUgPSBmdW5jdGlvbih1dGZ0ZXh0KSB7XG4gIHZhciBzdHJpbmcgPSBbXTtcbiAgdmFyIGkgPSAwO1xuICB2YXIgYyA9IDAsXG4gICAgYzEgPSAwLFxuICAgIGMyID0gMCxcbiAgICBjMztcbiAgaWYgKCFKWEcuZXhpc3RzKHV0ZnRleHQpKSByZXR1cm4gJyc7XG5cbiAgd2hpbGUgKGkgPCB1dGZ0ZXh0Lmxlbmd0aCkge1xuICAgIGMgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSk7XG5cbiAgICBpZiAoYyA8IDEyOCkge1xuICAgICAgc3RyaW5nLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjKSk7XG4gICAgICBpKys7XG4gICAgfSBlbHNlIGlmICgoYyA+IDE5MSkgJiYgKGMgPCAyMjQpKSB7XG4gICAgICBjMiA9IHV0ZnRleHQuY2hhckNvZGVBdChpICsgMSk7XG4gICAgICBzdHJpbmcucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKCgoYyAmIDMxKSA8PCA2KSB8IChjMiAmIDYzKSkpO1xuICAgICAgaSArPSAyO1xuICAgIH0gZWxzZSB7XG4gICAgICBjMiA9IHV0ZnRleHQuY2hhckNvZGVBdChpICsgMSk7XG4gICAgICBjMyA9IHV0ZnRleHQuY2hhckNvZGVBdChpICsgMik7XG4gICAgICBzdHJpbmcucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKCgoYyAmIDE1KSA8PCAxMikgfCAoKGMyICYgNjMpIDw8IDYpIHwgKGMzICYgNjMpKSk7XG4gICAgICBpICs9IDM7XG4gICAgfVxuICB9O1xuICByZXR1cm4gc3RyaW5nLmpvaW4oJycpO1xufTtcblxuLyoqXG4gKiBHZW5lcmF0ZSBhIHJhbmRvbSB1dWlkLlxuICogaHR0cDovL3d3dy5icm9vZmEuY29tXG4gKiBtYWlsdG86cm9iZXJ0QGJyb29mYS5jb21cbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAgUm9iZXJ0IEtpZWZmZXJcbiAqIER1YWwgbGljZW5zZWQgdW5kZXIgdGhlIE1JVCBhbmQgR1BMIGxpY2Vuc2VzLlxuICpcbiAqIEVYQU1QTEVTOlxuICogICA+Pj4gTWF0aC51dWlkKClcbiAqICAgXCI5MjMyOUQzOS02RjVDLTQ1MjAtQUJGQy1BQUI2NDU0NEUxNzJcIlxuICovXG5KWEcuVXRpbC5nZW5VVUlEID0gZnVuY3Rpb24oKSB7XG4gIC8vIFByaXZhdGUgYXJyYXkgb2YgY2hhcnMgdG8gdXNlXG4gIHZhciBjaGFycyA9ICcwMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eicuc3BsaXQoJycpLFxuICAgIHV1aWQgPSBuZXcgQXJyYXkoMzYpLFxuICAgIHJuZCA9IDAsXG4gICAgcjtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IDM2OyBpKyspIHtcbiAgICBpZiAoaSA9PSA4IHx8IGkgPT0gMTMgfHwgaSA9PSAxOCB8fCBpID09IDIzKSB7XG4gICAgICB1dWlkW2ldID0gJy0nO1xuICAgIH0gZWxzZSBpZiAoaSA9PSAxNCkge1xuICAgICAgdXVpZFtpXSA9ICc0JztcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHJuZCA8PSAweDAyKSBybmQgPSAweDIwMDAwMDAgKyAoTWF0aC5yYW5kb20oKSAqIDB4MTAwMDAwMCkgfCAwO1xuICAgICAgciA9IHJuZCAmIDB4ZjtcbiAgICAgIHJuZCA9IHJuZCA+PiA0O1xuICAgICAgdXVpZFtpXSA9IGNoYXJzWyhpID09IDE5KSA/IChyICYgMHgzKSB8IDB4OCA6IHJdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB1dWlkLmpvaW4oJycpO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IEpYRztcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy9cbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vL1xuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vL1xuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyk7XG5cbi8qKlxuICpcbiAqIFRoaXMgb2JqZWN0IGNvbnRhaW5zIGNvbmZpZ3VyYXRpb24gdmFsdWVzIGFuZCBpbXBsZW1lbnRzXG4gKiBzdG9yaW5nIGFuZCByZXRyaWV2aW5nIGNvbmZpZ3VyYXRpb24gdGhlbSBmcm9tIEhUTUw1IGxvY2FsIHN0b3JhZ2UuXG4gKlxuICogVGhpcyBvYmplY3QgY2FuIGJlIGFjY2Vzc2VkIGFmdGVyIGNhbGxpbmcgb3BlbnBncC5pbml0KClcbiAqIHVzaW5nIG9wZW5wZ3AuY29uZmlnXG4gKiBTdG9yZWQgY29uZmlnIHBhcmFtZXRlcnMgY2FuIGJlIGFjY2Vzc2VkIHVzaW5nXG4gKiBvcGVucGdwLmNvbmZpZy5jb25maWdcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgR1BHNEJyb3dzZXJzIGNvbmZpZyBvYmplY3RcbiAqL1xudmFyIGNvbmZpZyA9IGZ1bmN0aW9uKCkge1xuICAvKipcbiAgICogQHByb3BlcnR5IHtJbnRlZ2VyfSBwcmVmZXJfaGFzaF9hbGdvcml0aG1cbiAgICogQHByb3BlcnR5IHtJbnRlZ2VyfSBlbmNyeXB0aW9uX2NpcGhlclxuICAgKiBAcHJvcGVydHkge0ludGVnZXJ9IGNvbXByZXNzaW9uXG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gc2hvd192ZXJzaW9uXG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gc2hvd19jb21tZW50XG4gICAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gaW50ZWdyaXR5X3Byb3RlY3RcbiAgICogQHByb3BlcnR5IHtTdHJpbmd9IGtleXNlcnZlclxuICAgKi9cbiAgdGhpcy5wcmVmZXJfaGFzaF9hbGdvcml0aG0gPSBlbnVtcy5oYXNoLnNoYTI1NjtcbiAgdGhpcy5lbmNyeXB0aW9uX2NpcGhlciA9IGVudW1zLnN5bW1ldHJpYy5hZXMyNTY7XG4gIHRoaXMuY29tcHJlc3Npb24gPSBlbnVtcy5jb21wcmVzc2lvbi56aXA7XG4gIHRoaXMuc2hvd192ZXJzaW9uID0gdHJ1ZTtcbiAgdGhpcy5zaG93X2NvbW1lbnQgPSB0cnVlO1xuICB0aGlzLmludGVncml0eV9wcm90ZWN0ID0gdHJ1ZTtcbiAgdGhpcy5rZXlzZXJ2ZXIgPSBcImtleXNlcnZlci5saW51eC5pdFwiOyAvLyBcInBncC5taXQuZWR1OjExMzcxXCJcblxuICB0aGlzLnZlcnNpb25zdHJpbmcgPSBcIk9wZW5QR1AuanMgVkVSU0lPTlwiO1xuICB0aGlzLmNvbW1lbnRzdHJpbmcgPSBcImh0dHA6Ly9vcGVucGdwanMub3JnXCI7XG5cbiAgLyoqXG4gICAqIElmIGVuYWJsZWQsIGRlYnVnIG1lc3NhZ2VzIHdpbGwgYmUgcHJpbnRlZFxuICAgKi9cbiAgdGhpcy5kZWJ1ZyA9IGZhbHNlO1xuXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBjb25maWcoKTtcbiIsIi8vIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSCBcblxuLy8gbW9kaWZpZWQgdmVyc2lvbiBvZiBodHRwOi8vd3d3LmhhbmV3aW4ubmV0L2VuY3J5cHQvUEdkZWNvZGUuanM6XG5cbi8qIE9wZW5QR1AgZW5jcnlwdGlvbiB1c2luZyBSU0EvQUVTXG4gKiBDb3B5cmlnaHQgMjAwNS0yMDA2IEhlcmJlcnQgSGFuZXdpbmtlbCwgd3d3LmhhbmVXSU4uZGVcbiAqIHZlcnNpb24gMi4wLCBjaGVjayB3d3cuaGFuZVdJTi5kZSBmb3IgdGhlIGxhdGVzdCB2ZXJzaW9uXG5cbiAqIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgYXMtaXMsIHdpdGhvdXQgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LiAgXG4gKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlIG9yIHNlbGwgdGhpcyBzb2Z0d2FyZSwgd2l0aCBvclxuICogd2l0aG91dCBmZWUsIGZvciBhbnkgcHVycG9zZSBhbmQgYnkgYW55IGluZGl2aWR1YWwgb3Igb3JnYW5pemF0aW9uLCBpcyBoZXJlYnlcbiAqIGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGFyYWdyYXBoIGFwcGVhciBcbiAqIGluIGFsbCBjb3BpZXMuIERpc3RyaWJ1dGlvbiBhcyBhIHBhcnQgb2YgYW4gYXBwbGljYXRpb24gb3IgYmluYXJ5IG11c3RcbiAqIGluY2x1ZGUgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyXG4gKiBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgYXBwbGljYXRpb24gb3IgZGlzdHJpYnV0aW9uLlxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICBjaXBoZXIgPSByZXF1aXJlKCcuL2NpcGhlcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblxuICAvKipcbiAgICogQW4gYXJyYXkgb2YgYnl0ZXMsIHRoYXQgaXMgaW50ZWdlcnMgd2l0aCB2YWx1ZXMgZnJvbSAwIHRvIDI1NVxuICAgKiBAdHlwZWRlZiB7KEFycmF5fFVpbnQ4QXJyYXkpfSBvcGVucGdwX2J5dGVfYXJyYXlcbiAgICovXG5cbiAgLyoqXG4gICAqIEJsb2NrIGNpcGhlciBmdW5jdGlvblxuICAgKiBAY2FsbGJhY2sgb3BlbnBncF9jaXBoZXJfYmxvY2tfZm5cbiAgICogQHBhcmFtIHtvcGVucGdwX2J5dGVfYXJyYXl9IGJsb2NrIEEgYmxvY2sgdG8gcGVyZm9ybSBvcGVyYXRpb25zIG9uXG4gICAqIEBwYXJhbSB7b3BlbnBncF9ieXRlX2FycmF5fSBrZXkgdG8gdXNlIGluIGVuY3J5cHRpb24vZGVjcnlwdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX2J5dGVfYXJyYXl9IEVuY3J5cHRlZC9kZWNyeXB0ZWQgYmxvY2tcbiAgICovXG5cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBlbmNyeXB0cyBhIGdpdmVuIHdpdGggdGhlIHNwZWNpZmllZCBwcmVmaXhyYW5kb20gXG4gICAqIHVzaW5nIHRoZSBzcGVjaWZpZWQgYmxvY2tjaXBoZXIgdG8gZW5jcnlwdCBhIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByZWZpeHJhbmRvbSByYW5kb20gYnl0ZXMgb2YgYmxvY2tfc2l6ZSBsZW5ndGggcHJvdmlkZWQgXG4gICAqICBhcyBhIHN0cmluZyB0byBiZSB1c2VkIGluIHByZWZpeGluZyB0aGUgZGF0YVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfY2lwaGVyX2Jsb2NrX2ZufSBibG9ja2NpcGhlcmZuIHRoZSBhbGdvcml0aG0gZW5jcnlwdCBmdW5jdGlvbiB0byBlbmNyeXB0XG4gICAqICBkYXRhIGluIG9uZSBibG9ja19zaXplIGVuY3J5cHRpb24uIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGJsb2NrX3NpemUgdGhlIGJsb2NrIHNpemUgaW4gYnl0ZXMgb2YgdGhlIGFsZ29yaXRobSB1c2VkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwbGFpbnRleHQgZGF0YSB0byBiZSBlbmNyeXB0ZWQgcHJvdmlkZWQgYXMgYSBzdHJpbmdcbiAgICogQHBhcmFtIHtvcGVucGdwX2J5dGVfYXJyYXl9IGtleSBrZXkgdG8gYmUgdXNlZCB0byBlbmNyeXB0IHRoZSBkYXRhLiBUaGlzIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSBcbiAgICogIGJsb2NrY2lwaGVyZm5cbiAgICogQHBhcmFtIHtCb29sZWFufSByZXN5bmMgYSBib29sZWFuIHZhbHVlIHNwZWNpZnlpbmcgaWYgYSByZXN5bmMgb2YgdGhlIFxuICAgKiAgSVYgc2hvdWxkIGJlIHVzZWQgb3Igbm90LiBUaGUgZW5jcnlwdGVkZGF0YXBhY2tldCB1c2VzIHRoZSBcbiAgICogIFwib2xkXCIgc3R5bGUgd2l0aCBhIHJlc3luYy4gRW5jcnlwdGlvbiB3aXRoaW4gYW4gXG4gICAqICBlbmNyeXB0ZWRpbnRlZ3JpdHlwcm90ZWN0ZWRkYXRhIHBhY2tldCBpcyBub3QgcmVzeW5jaW5nIHRoZSBJVi5cbiAgICogQHJldHVybiB7U3RyaW5nfSBhIHN0cmluZyB3aXRoIHRoZSBlbmNyeXB0ZWQgZGF0YVxuICAgKi9cbiAgZW5jcnlwdDogZnVuY3Rpb24ocHJlZml4cmFuZG9tLCBjaXBoZXJmbiwgcGxhaW50ZXh0LCBrZXksIHJlc3luYykge1xuICAgIGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcbiAgICB2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuICAgIHZhciBGUiA9IG5ldyBBcnJheShibG9ja19zaXplKTtcbiAgICB2YXIgRlJFID0gbmV3IEFycmF5KGJsb2NrX3NpemUpO1xuXG4gICAgcHJlZml4cmFuZG9tID0gcHJlZml4cmFuZG9tICsgcHJlZml4cmFuZG9tLmNoYXJBdChibG9ja19zaXplIC0gMikgKyBwcmVmaXhyYW5kb20uY2hhckF0KGJsb2NrX3NpemUgLSAxKTtcbiAgICB1dGlsLnByaW50X2RlYnVnKFwicHJlZml4cmFuZG9tOlwiICsgdXRpbC5oZXhzdHJkdW1wKHByZWZpeHJhbmRvbSkpO1xuICAgIHZhciBjaXBoZXJ0ZXh0ID0gXCJcIjtcbiAgICAvLyAxLiAgVGhlIGZlZWRiYWNrIHJlZ2lzdGVyIChGUikgaXMgc2V0IHRvIHRoZSBJViwgd2hpY2ggaXMgYWxsIHplcm9zLlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBGUltpXSA9IDA7XG5cbiAgICAvLyAyLiAgRlIgaXMgZW5jcnlwdGVkIHRvIHByb2R1Y2UgRlJFIChGUiBFbmNyeXB0ZWQpLiAgVGhpcyBpcyB0aGVcbiAgICAvLyAgICAgZW5jcnlwdGlvbiBvZiBhbiBhbGwtemVybyB2YWx1ZS5cbiAgICBGUkUgPSBjaXBoZXJmbi5lbmNyeXB0KEZSKTtcbiAgICAvLyAzLiAgRlJFIGlzIHhvcmVkIHdpdGggdGhlIGZpcnN0IEJTIG9jdGV0cyBvZiByYW5kb20gZGF0YSBwcmVmaXhlZCB0b1xuICAgIC8vICAgICB0aGUgcGxhaW50ZXh0IHRvIHByb2R1Y2UgQ1sxXSB0aHJvdWdoIENbQlNdLCB0aGUgZmlyc3QgQlMgb2N0ZXRzXG4gICAgLy8gICAgIG9mIGNpcGhlcnRleHQuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIGNpcGhlcnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwcmVmaXhyYW5kb20uY2hhckNvZGVBdChpKSk7XG5cbiAgICAvLyA0LiAgRlIgaXMgbG9hZGVkIHdpdGggQ1sxXSB0aHJvdWdoIENbQlNdLlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBGUltpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcblxuICAgIC8vIDUuICBGUiBpcyBlbmNyeXB0ZWQgdG8gcHJvZHVjZSBGUkUsIHRoZSBlbmNyeXB0aW9uIG9mIHRoZSBmaXJzdCBCU1xuICAgIC8vIFx0ICAgb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG4gICAgRlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG5cbiAgICAvLyA2LiAgVGhlIGxlZnQgdHdvIG9jdGV0cyBvZiBGUkUgZ2V0IHhvcmVkIHdpdGggdGhlIG5leHQgdHdvIG9jdGV0cyBvZlxuICAgIC8vICAgICBkYXRhIHRoYXQgd2VyZSBwcmVmaXhlZCB0byB0aGUgcGxhaW50ZXh0LiAgVGhpcyBwcm9kdWNlcyBDW0JTKzFdXG4gICAgLy8gICAgIGFuZCBDW0JTKzJdLCB0aGUgbmV4dCB0d28gb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG4gICAgY2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVswXSBeIHByZWZpeHJhbmRvbS5jaGFyQ29kZUF0KGJsb2NrX3NpemUpKTtcbiAgICBjaXBoZXJ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFWzFdIF4gcHJlZml4cmFuZG9tLmNoYXJDb2RlQXQoYmxvY2tfc2l6ZSArIDEpKTtcblxuICAgIGlmIChyZXN5bmMpIHtcbiAgICAgIC8vIDcuICAoVGhlIHJlc3luYyBzdGVwKSBGUiBpcyBsb2FkZWQgd2l0aCBDMy1DMTAuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgRlJbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSArIDIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgRlJbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSk7XG4gICAgfVxuICAgIC8vIDguICBGUiBpcyBlbmNyeXB0ZWQgdG8gcHJvZHVjZSBGUkUuXG4gICAgRlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUiwga2V5KTtcblxuICAgIGlmIChyZXN5bmMpIHtcbiAgICAgIC8vIDkuICBGUkUgaXMgeG9yZWQgd2l0aCB0aGUgZmlyc3QgOCBvY3RldHMgb2YgdGhlIGdpdmVuIHBsYWludGV4dCwgbm93XG4gICAgICAvL1x0ICAgdGhhdCB3ZSBoYXZlIGZpbmlzaGVkIGVuY3J5cHRpbmcgdGhlIDEwIG9jdGV0cyBvZiBwcmVmaXhlZCBkYXRhLlxuICAgICAgLy8gXHQgICBUaGlzIHByb2R1Y2VzIEMxMS1DMTgsIHRoZSBuZXh0IDggb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKylcbiAgICAgICAgY2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVtpXSBeIHBsYWludGV4dC5jaGFyQ29kZUF0KGkpKTtcbiAgICAgIGZvciAobiA9IGJsb2NrX3NpemUgKyAyOyBuIDwgcGxhaW50ZXh0Lmxlbmd0aDsgbiArPSBibG9ja19zaXplKSB7XG4gICAgICAgIC8vIDEwLiBGUiBpcyBsb2FkZWQgd2l0aCBDMTEtQzE4XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBGUltpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChuICsgaSk7XG5cbiAgICAgICAgLy8gMTEuIEZSIGlzIGVuY3J5cHRlZCB0byBwcm9kdWNlIEZSRS5cbiAgICAgICAgRlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG5cbiAgICAgICAgLy8gMTIuIEZSRSBpcyB4b3JlZCB3aXRoIHRoZSBuZXh0IDggb2N0ZXRzIG9mIHBsYWludGV4dCwgdG8gcHJvZHVjZSB0aGVcbiAgICAgICAgLy8gbmV4dCA4IG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LiAgVGhlc2UgYXJlIGxvYWRlZCBpbnRvIEZSIGFuZCB0aGVcbiAgICAgICAgLy8gcHJvY2VzcyBpcyByZXBlYXRlZCB1bnRpbCB0aGUgcGxhaW50ZXh0IGlzIHVzZWQgdXAuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBjaXBoZXJ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFW2ldIF4gcGxhaW50ZXh0LmNoYXJDb2RlQXQoKG4gLSAyKSArXG4gICAgICAgICAgICBpKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHBsYWludGV4dCA9IFwiICBcIiArIHBsYWludGV4dDtcbiAgICAgIC8vIDkuICBGUkUgaXMgeG9yZWQgd2l0aCB0aGUgZmlyc3QgOCBvY3RldHMgb2YgdGhlIGdpdmVuIHBsYWludGV4dCwgbm93XG4gICAgICAvL1x0ICAgdGhhdCB3ZSBoYXZlIGZpbmlzaGVkIGVuY3J5cHRpbmcgdGhlIDEwIG9jdGV0cyBvZiBwcmVmaXhlZCBkYXRhLlxuICAgICAgLy8gXHQgICBUaGlzIHByb2R1Y2VzIEMxMS1DMTgsIHRoZSBuZXh0IDggb2N0ZXRzIG9mIGNpcGhlcnRleHQuXG4gICAgICBmb3IgKHZhciBpID0gMjsgaSA8IGJsb2NrX3NpemU7IGkrKykgY2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVtpXSBeIHBsYWludGV4dC5jaGFyQ29kZUF0KGkpKTtcbiAgICAgIHZhciB0ZW1wQ2lwaGVydGV4dCA9IGNpcGhlcnRleHQuc3Vic3RyaW5nKDAsIDIgKiBibG9ja19zaXplKS5zcGxpdCgnJyk7XG4gICAgICB2YXIgdGVtcENpcGhlcnRleHRTdHJpbmcgPSBjaXBoZXJ0ZXh0LnN1YnN0cmluZyhibG9ja19zaXplKTtcbiAgICAgIGZvciAobiA9IGJsb2NrX3NpemU7IG4gPCBwbGFpbnRleHQubGVuZ3RoOyBuICs9IGJsb2NrX3NpemUpIHtcbiAgICAgICAgLy8gMTAuIEZSIGlzIGxvYWRlZCB3aXRoIEMxMS1DMThcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gdGVtcENpcGhlcnRleHRTdHJpbmcuY2hhckNvZGVBdChpKTtcbiAgICAgICAgdGVtcENpcGhlcnRleHRTdHJpbmcgPSAnJztcblxuICAgICAgICAvLyAxMS4gRlIgaXMgZW5jcnlwdGVkIHRvIHByb2R1Y2UgRlJFLlxuICAgICAgICBGUkUgPSBjaXBoZXJmbi5lbmNyeXB0KEZSKTtcblxuICAgICAgICAvLyAxMi4gRlJFIGlzIHhvcmVkIHdpdGggdGhlIG5leHQgOCBvY3RldHMgb2YgcGxhaW50ZXh0LCB0byBwcm9kdWNlIHRoZVxuICAgICAgICAvLyAgICAgbmV4dCA4IG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LiAgVGhlc2UgYXJlIGxvYWRlZCBpbnRvIEZSIGFuZCB0aGVcbiAgICAgICAgLy8gICAgIHByb2Nlc3MgaXMgcmVwZWF0ZWQgdW50aWwgdGhlIHBsYWludGV4dCBpcyB1c2VkIHVwLlxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykge1xuICAgICAgICAgIHRlbXBDaXBoZXJ0ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwbGFpbnRleHQuY2hhckNvZGVBdChuICsgaSkpKTtcbiAgICAgICAgICB0ZW1wQ2lwaGVydGV4dFN0cmluZyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVtpXSBeIHBsYWludGV4dC5jaGFyQ29kZUF0KG4gKyBpKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNpcGhlcnRleHQgPSB0ZW1wQ2lwaGVydGV4dC5qb2luKCcnKTtcblxuICAgIH1cblxuICAgIGNpcGhlcnRleHQgPSBjaXBoZXJ0ZXh0LnN1YnN0cmluZygwLCBwbGFpbnRleHQubGVuZ3RoICsgMiArIGJsb2NrX3NpemUpO1xuXG4gICAgcmV0dXJuIGNpcGhlcnRleHQ7XG4gIH0sXG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIHRoZSBwcmVmaXhlZCBkYXRhIGZvciB0aGUgTW9kaWZpY2F0aW9uIERldGVjdGlvbiBDb2RlIChNREMpIGNvbXB1dGF0aW9uXG4gICAqIEBwYXJhbSB7b3BlbnBncF9ibG9ja19jaXBoZXJfZm59IGNpcGhlcmZuLmVuY3J5cHQgQ2lwaGVyIGZ1bmN0aW9uIHRvIHVzZVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGJsb2NrX3NpemUgQmxvY2tzaXplIG9mIHRoZSBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtvcGVucGdwX2J5dGVfYXJyYXl9IGtleSBUaGUga2V5IGZvciBlbmNyeXB0aW9uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBjaXBoZXJ0ZXh0IFRoZSBlbmNyeXB0ZWQgZGF0YVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IHBsYWludGV4dCBEYXRhIG9mIEQoY2lwaGVydGV4dCkgd2l0aCBibG9ja3NpemUgbGVuZ3RoICsyXG4gICAqL1xuICBtZGM6IGZ1bmN0aW9uKGNpcGhlcmZuLCBrZXksIGNpcGhlcnRleHQpIHtcbiAgICBjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG4gICAgdmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cbiAgICB2YXIgaWJsb2NrID0gbmV3IEFycmF5KGJsb2NrX3NpemUpO1xuICAgIHZhciBhYmxvY2sgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG4gICAgdmFyIGk7XG5cblxuICAgIC8vIGluaXRpYWxpc2F0aW9uIHZlY3RvclxuICAgIGZvciAoaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIGlibG9ja1tpXSA9IDA7XG5cbiAgICBpYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGlibG9jayk7XG4gICAgZm9yIChpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykge1xuICAgICAgYWJsb2NrW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWJsb2NrW2ldIF49IGFibG9ja1tpXTtcbiAgICB9XG5cbiAgICBhYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGFibG9jayk7XG5cbiAgICByZXR1cm4gdXRpbC5iaW4yc3RyKGlibG9jaykgK1xuICAgICAgU3RyaW5nLmZyb21DaGFyQ29kZShhYmxvY2tbMF0gXiBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoYmxvY2tfc2l6ZSkpICtcbiAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUoYWJsb2NrWzFdIF4gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGJsb2NrX3NpemUgKyAxKSk7XG4gIH0sXG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGRlY3J5cHRzIGEgZ2l2ZW4gcGxhaW50ZXh0IHVzaW5nIHRoZSBzcGVjaWZpZWRcbiAgICogYmxvY2tjaXBoZXIgdG8gZGVjcnlwdCBhIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtvcGVucGdwX2NpcGhlcl9ibG9ja19mbn0gYmxvY2tjaXBoZXJmbiBUaGUgYWxnb3JpdGhtIF9lbmNyeXB0XyBmdW5jdGlvbiB0byBlbmNyeXB0XG4gICAqICBkYXRhIGluIG9uZSBibG9ja19zaXplIGVuY3J5cHRpb24uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gYmxvY2tfc2l6ZSB0aGUgYmxvY2sgc2l6ZSBpbiBieXRlcyBvZiB0aGUgYWxnb3JpdGhtIHVzZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBsYWludGV4dCBjaXBoZXJ0ZXh0IHRvIGJlIGRlY3J5cHRlZCBwcm92aWRlZCBhcyBhIHN0cmluZ1xuICAgKiBAcGFyYW0ge29wZW5wZ3BfYnl0ZV9hcnJheX0ga2V5IGtleSB0byBiZSB1c2VkIHRvIGRlY3J5cHQgdGhlIGNpcGhlcnRleHQuIFRoaXMgd2lsbCBiZSBwYXNzZWQgdG8gdGhlIFxuICAgKiAgYmxvY2tjaXBoZXJmblxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHJlc3luYyBhIGJvb2xlYW4gdmFsdWUgc3BlY2lmeWluZyBpZiBhIHJlc3luYyBvZiB0aGUgXG4gICAqICBJViBzaG91bGQgYmUgdXNlZCBvciBub3QuIFRoZSBlbmNyeXB0ZWRkYXRhcGFja2V0IHVzZXMgdGhlIFxuICAgKiAgXCJvbGRcIiBzdHlsZSB3aXRoIGEgcmVzeW5jLiBEZWNyeXB0aW9uIHdpdGhpbiBhbiBcbiAgICogIGVuY3J5cHRlZGludGVncml0eXByb3RlY3RlZGRhdGEgcGFja2V0IGlzIG5vdCByZXN5bmNpbmcgdGhlIElWLlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGEgc3RyaW5nIHdpdGggdGhlIHBsYWludGV4dCBkYXRhXG4gICAqL1xuXG4gIGRlY3J5cHQ6IGZ1bmN0aW9uKGNpcGhlcmZuLCBrZXksIGNpcGhlcnRleHQsIHJlc3luYykge1xuICAgIGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcbiAgICB2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuICAgIHZhciBpYmxvY2sgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG4gICAgdmFyIGFibG9jayA9IG5ldyBBcnJheShibG9ja19zaXplKTtcbiAgICB2YXIgaSwgbiA9ICcnO1xuICAgIHZhciB0ZXh0ID0gW107XG5cbiAgICAvLyBpbml0aWFsaXNhdGlvbiB2ZWN0b3JcbiAgICBmb3IgKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSAwO1xuXG4gICAgaWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChpYmxvY2ssIGtleSk7XG4gICAgZm9yIChpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykge1xuICAgICAgYWJsb2NrW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWJsb2NrW2ldIF49IGFibG9ja1tpXTtcbiAgICB9XG5cbiAgICBhYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGFibG9jaywga2V5KTtcblxuICAgIC8vIHRlc3QgY2hlY2sgb2N0ZXRzXG4gICAgaWYgKGlibG9ja1tibG9ja19zaXplIC0gMl0gIT0gKGFibG9ja1swXSBeIGNpcGhlcnRleHQuY2hhckNvZGVBdChibG9ja19zaXplKSkgfHwgaWJsb2NrW2Jsb2NrX3NpemUgLSAxXSAhPSAoYWJsb2NrW1xuICAgICAgMV0gXiBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoYmxvY2tfc2l6ZSArIDEpKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGRhdGEuJyk7XG4gICAgfVxuXG4gICAgLyogIFJGQzQ4ODA6IFRhZyAxOCBhbmQgUmVzeW5jOlxuXHRcdCAqICBbLi4uXSBVbmxpa2UgdGhlIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgUGFja2V0LCBub1xuXHRcdCAqICBzcGVjaWFsIENGQiByZXN5bmNocm9uaXphdGlvbiBpcyBkb25lIGFmdGVyIGVuY3J5cHRpbmcgdGhpcyBwcmVmaXhcblx0XHQgKiAgZGF0YS4gIFNlZSBcIk9wZW5QR1AgQ0ZCIE1vZGVcIiBiZWxvdyBmb3IgbW9yZSBkZXRhaWxzLlxuXG5cdFx0ICovXG5cbiAgICBpZiAocmVzeW5jKSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSArIDIpO1xuICAgICAgZm9yIChuID0gYmxvY2tfc2l6ZSArIDI7IG4gPCBjaXBoZXJ0ZXh0Lmxlbmd0aDsgbiArPSBibG9ja19zaXplKSB7XG4gICAgICAgIGFibG9jayA9IGNpcGhlcmZuLmVuY3J5cHQoaWJsb2NrKTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZSAmJiBpICsgbiA8IGNpcGhlcnRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQobiArIGkpO1xuICAgICAgICAgIHRleHQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGFibG9ja1tpXSBeIGlibG9ja1tpXSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIGlibG9ja1tpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgIGZvciAobiA9IGJsb2NrX3NpemU7IG4gPCBjaXBoZXJ0ZXh0Lmxlbmd0aDsgbiArPSBibG9ja19zaXplKSB7XG4gICAgICAgIGFibG9jayA9IGNpcGhlcmZuLmVuY3J5cHQoaWJsb2NrKTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGJsb2NrX3NpemUgJiYgaSArIG4gPCBjaXBoZXJ0ZXh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWJsb2NrW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KG4gKyBpKTtcbiAgICAgICAgICB0ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhYmxvY2tbaV0gXiBpYmxvY2tbaV0pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBuID0gcmVzeW5jID8gMCA6IDI7XG5cbiAgICB0ZXh0ID0gdGV4dC5qb2luKCcnKTtcblxuICAgIHRleHQgPSB0ZXh0LnN1YnN0cmluZyhuLCBjaXBoZXJ0ZXh0Lmxlbmd0aCAtIGJsb2NrX3NpemUgLSAyICsgbik7XG5cblxuICAgIHJldHVybiB0ZXh0O1xuICB9LFxuXG5cbiAgbm9ybWFsRW5jcnlwdDogZnVuY3Rpb24oY2lwaGVyZm4sIGtleSwgcGxhaW50ZXh0LCBpdikge1xuICAgIGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcbiAgICB2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuICAgIHZhciBibG9ja2kgPSBcIlwiO1xuICAgIHZhciBibG9ja2MgPSBcIlwiO1xuICAgIHZhciBwb3MgPSAwO1xuICAgIHZhciBjeXBoZXJ0ZXh0ID0gW107XG4gICAgdmFyIHRlbXBCbG9jayA9IFtdO1xuICAgIGJsb2NrYyA9IGl2LnN1YnN0cmluZygwLCBibG9ja19zaXplKTtcbiAgICB3aGlsZSAocGxhaW50ZXh0Lmxlbmd0aCA+IGJsb2NrX3NpemUgKiBwb3MpIHtcbiAgICAgIHZhciBlbmNibG9jayA9IGNpcGhlcmZuLmVuY3J5cHQodXRpbC5zdHIyYmluKGJsb2NrYykpO1xuICAgICAgYmxvY2tpID0gcGxhaW50ZXh0LnN1YnN0cmluZygocG9zICogYmxvY2tfc2l6ZSksIChwb3MgKiBibG9ja19zaXplKSArIGJsb2NrX3NpemUpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja2kubGVuZ3RoOyBpKyspXG4gICAgICAgIHRlbXBCbG9jay5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYmxvY2tpLmNoYXJDb2RlQXQoaSkgXiBlbmNibG9ja1tpXSkpO1xuICAgICAgYmxvY2tjID0gdGVtcEJsb2NrLmpvaW4oJycpO1xuICAgICAgdGVtcEJsb2NrID0gW107XG4gICAgICBjeXBoZXJ0ZXh0LnB1c2goYmxvY2tjKTtcbiAgICAgIHBvcysrO1xuICAgIH1cbiAgICByZXR1cm4gY3lwaGVydGV4dC5qb2luKCcnKTtcbiAgfSxcblxuICBub3JtYWxEZWNyeXB0OiBmdW5jdGlvbihjaXBoZXJmbiwga2V5LCBjaXBoZXJ0ZXh0LCBpdikge1xuICAgIGNpcGhlcmZuID0gbmV3IGNpcGhlcltjaXBoZXJmbl0oa2V5KTtcbiAgICB2YXIgYmxvY2tfc2l6ZSA9IGNpcGhlcmZuLmJsb2NrU2l6ZTtcblxuICAgIHZhciBibG9ja3AgPSBcIlwiO1xuICAgIHZhciBwb3MgPSAwO1xuICAgIHZhciBwbGFpbnRleHQgPSBbXTtcbiAgICB2YXIgb2Zmc2V0ID0gMDtcbiAgICBpZiAoaXYgPT0gbnVsbClcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBibG9ja3AgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcbiAgICBlbHNlXG4gICAgICBibG9ja3AgPSBpdi5zdWJzdHJpbmcoMCwgYmxvY2tfc2l6ZSk7XG4gICAgd2hpbGUgKGNpcGhlcnRleHQubGVuZ3RoID4gKGJsb2NrX3NpemUgKiBwb3MpKSB7XG4gICAgICB2YXIgZGVjYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KHV0aWwuc3RyMmJpbihibG9ja3ApKTtcbiAgICAgIGJsb2NrcCA9IGNpcGhlcnRleHQuc3Vic3RyaW5nKChwb3MgKiAoYmxvY2tfc2l6ZSkpICsgb2Zmc2V0LCAocG9zICogKGJsb2NrX3NpemUpKSArIChibG9ja19zaXplKSArIG9mZnNldCk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrcC5sZW5ndGg7IGkrKykge1xuICAgICAgICBwbGFpbnRleHQucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGJsb2NrcC5jaGFyQ29kZUF0KGkpIF4gZGVjYmxvY2tbaV0pKTtcbiAgICAgIH1cbiAgICAgIHBvcysrO1xuICAgIH1cblxuICAgIHJldHVybiBwbGFpbnRleHQuam9pbignJyk7XG4gIH1cbn1cbiIsIi8qIFJpam5kYWVsIChBRVMpIEVuY3J5cHRpb25cbiAqIENvcHlyaWdodCAyMDA1IEhlcmJlcnQgSGFuZXdpbmtlbCwgd3d3LmhhbmVXSU4uZGVcbiAqIHZlcnNpb24gMS4xLCBjaGVjayB3d3cuaGFuZVdJTi5kZSBmb3IgdGhlIGxhdGVzdCB2ZXJzaW9uXG5cbiAqIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgYXMtaXMsIHdpdGhvdXQgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LiAgXG4gKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlIG9yIHNlbGwgdGhpcyBzb2Z0d2FyZSwgd2l0aCBvclxuICogd2l0aG91dCBmZWUsIGZvciBhbnkgcHVycG9zZSBhbmQgYnkgYW55IGluZGl2aWR1YWwgb3Igb3JnYW5pemF0aW9uLCBpcyBoZXJlYnlcbiAqIGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGFyYWdyYXBoIGFwcGVhciBcbiAqIGluIGFsbCBjb3BpZXMuIERpc3RyaWJ1dGlvbiBhcyBhIHBhcnQgb2YgYW4gYXBwbGljYXRpb24gb3IgYmluYXJ5IG11c3RcbiAqIGluY2x1ZGUgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyXG4gKiBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgYXBwbGljYXRpb24gb3IgZGlzdHJpYnV0aW9uLlxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG4vLyBUaGUgcm91bmQgY29uc3RhbnRzIHVzZWQgaW4gc3Via2V5IGV4cGFuc2lvblxudmFyIFJjb24gPSBbXG4gICAgMHgwMSwgMHgwMiwgMHgwNCwgMHgwOCwgMHgxMCwgMHgyMCwgMHg0MCwgMHg4MCwgMHgxYiwgMHgzNiwgMHg2YywgMHhkOCxcbiAgICAweGFiLCAweDRkLCAweDlhLCAweDJmLCAweDVlLCAweGJjLCAweDYzLCAweGM2LCAweDk3LCAweDM1LCAweDZhLCAweGQ0LFxuICAgIDB4YjMsIDB4N2QsIDB4ZmEsIDB4ZWYsIDB4YzUsIDB4OTFcbl07XG5cbi8vIFByZWNvbXB1dGVkIGxvb2t1cCB0YWJsZSBmb3IgdGhlIFNCb3hcbnZhciBTID0gW1xuICAgIDk5LCAxMjQsIDExOSwgMTIzLCAyNDIsIDEwNywgMTExLCAxOTcsIDQ4LCAxLCAxMDMsIDQzLCAyNTQsIDIxNSwgMTcxLFxuICAgIDExOCwgMjAyLCAxMzAsIDIwMSwgMTI1LCAyNTAsIDg5LCA3MSwgMjQwLCAxNzMsIDIxMiwgMTYyLCAxNzUsIDE1NiwgMTY0LFxuICAgIDExNCwgMTkyLCAxODMsIDI1MywgMTQ3LCAzOCwgNTQsIDYzLCAyNDcsIDIwNCwgNTIsIDE2NSwgMjI5LCAyNDEsIDExMyxcbiAgICAyMTYsIDQ5LCAyMSwgNCwgMTk5LCAzNSwgMTk1LCAyNCwgMTUwLCA1LCAxNTQsIDcsIDE4LCAxMjgsIDIyNixcbiAgICAyMzUsIDM5LCAxNzgsIDExNywgOSwgMTMxLCA0NCwgMjYsIDI3LCAxMTAsIDkwLCAxNjAsIDgyLCA1OSwgMjE0LFxuICAgIDE3OSwgNDEsIDIyNywgNDcsIDEzMiwgODMsIDIwOSwgMCwgMjM3LCAzMiwgMjUyLCAxNzcsIDkxLCAxMDYsIDIwMyxcbiAgICAxOTAsIDU3LCA3NCwgNzYsIDg4LCAyMDcsIDIwOCwgMjM5LCAxNzAsIDI1MSwgNjcsIDc3LCA1MSwgMTMzLCA2OSxcbiAgICAyNDksIDIsIDEyNywgODAsIDYwLCAxNTksIDE2OCwgODEsIDE2MywgNjQsIDE0MywgMTQ2LCAxNTcsIDU2LCAyNDUsXG4gICAgMTg4LCAxODIsIDIxOCwgMzMsIDE2LCAyNTUsIDI0MywgMjEwLCAyMDUsIDEyLCAxOSwgMjM2LCA5NSwgMTUxLCA2OCxcbiAgICAyMywgMTk2LCAxNjcsIDEyNiwgNjEsIDEwMCwgOTMsIDI1LCAxMTUsIDk2LCAxMjksIDc5LCAyMjAsIDM0LCA0MixcbiAgICAxNDQsIDEzNiwgNzAsIDIzOCwgMTg0LCAyMCwgMjIyLCA5NCwgMTEsIDIxOSwgMjI0LCA1MCwgNTgsIDEwLCA3MyxcbiAgICA2LCAzNiwgOTIsIDE5NCwgMjExLCAxNzIsIDk4LCAxNDUsIDE0OSwgMjI4LCAxMjEsIDIzMSwgMjAwLCA1NSwgMTA5LFxuICAgIDE0MSwgMjEzLCA3OCwgMTY5LCAxMDgsIDg2LCAyNDQsIDIzNCwgMTAxLCAxMjIsIDE3NCwgOCwgMTg2LCAxMjAsIDM3LFxuICAgIDQ2LCAyOCwgMTY2LCAxODAsIDE5OCwgMjMyLCAyMjEsIDExNiwgMzEsIDc1LCAxODksIDEzOSwgMTM4LCAxMTIsIDYyLFxuICAgIDE4MSwgMTAyLCA3MiwgMywgMjQ2LCAxNCwgOTcsIDUzLCA4NywgMTg1LCAxMzQsIDE5MywgMjksIDE1OCwgMjI1LFxuICAgIDI0OCwgMTUyLCAxNywgMTA1LCAyMTcsIDE0MiwgMTQ4LCAxNTUsIDMwLCAxMzUsIDIzMywgMjA2LCA4NSwgNDAsIDIyMyxcbiAgICAxNDAsIDE2MSwgMTM3LCAxMywgMTkxLCAyMzAsIDY2LCAxMDQsIDY1LCAxNTMsIDQ1LCAxNSwgMTc2LCA4NCwgMTg3LFxuICAgIDIyXG5dO1xuXG52YXIgVDEgPSBbXG4gICAgMHhhNTYzNjNjNiwgMHg4NDdjN2NmOCwgMHg5OTc3NzdlZSwgMHg4ZDdiN2JmNixcbiAgICAweDBkZjJmMmZmLCAweGJkNmI2YmQ2LCAweGIxNmY2ZmRlLCAweDU0YzVjNTkxLFxuICAgIDB4NTAzMDMwNjAsIDB4MDMwMTAxMDIsIDB4YTk2NzY3Y2UsIDB4N2QyYjJiNTYsXG4gICAgMHgxOWZlZmVlNywgMHg2MmQ3ZDdiNSwgMHhlNmFiYWI0ZCwgMHg5YTc2NzZlYyxcbiAgICAweDQ1Y2FjYThmLCAweDlkODI4MjFmLCAweDQwYzljOTg5LCAweDg3N2Q3ZGZhLFxuICAgIDB4MTVmYWZhZWYsIDB4ZWI1OTU5YjIsIDB4Yzk0NzQ3OGUsIDB4MGJmMGYwZmIsXG4gICAgMHhlY2FkYWQ0MSwgMHg2N2Q0ZDRiMywgMHhmZGEyYTI1ZiwgMHhlYWFmYWY0NSxcbiAgICAweGJmOWM5YzIzLCAweGY3YTRhNDUzLCAweDk2NzI3MmU0LCAweDViYzBjMDliLFxuICAgIDB4YzJiN2I3NzUsIDB4MWNmZGZkZTEsIDB4YWU5MzkzM2QsIDB4NmEyNjI2NGMsXG4gICAgMHg1YTM2MzY2YywgMHg0MTNmM2Y3ZSwgMHgwMmY3ZjdmNSwgMHg0ZmNjY2M4MyxcbiAgICAweDVjMzQzNDY4LCAweGY0YTVhNTUxLCAweDM0ZTVlNWQxLCAweDA4ZjFmMWY5LFxuICAgIDB4OTM3MTcxZTIsIDB4NzNkOGQ4YWIsIDB4NTMzMTMxNjIsIDB4M2YxNTE1MmEsXG4gICAgMHgwYzA0MDQwOCwgMHg1MmM3Yzc5NSwgMHg2NTIzMjM0NiwgMHg1ZWMzYzM5ZCxcbiAgICAweDI4MTgxODMwLCAweGExOTY5NjM3LCAweDBmMDUwNTBhLCAweGI1OWE5YTJmLFxuICAgIDB4MDkwNzA3MGUsIDB4MzYxMjEyMjQsIDB4OWI4MDgwMWIsIDB4M2RlMmUyZGYsXG4gICAgMHgyNmViZWJjZCwgMHg2OTI3Mjc0ZSwgMHhjZGIyYjI3ZiwgMHg5Zjc1NzVlYSxcbiAgICAweDFiMDkwOTEyLCAweDllODM4MzFkLCAweDc0MmMyYzU4LCAweDJlMWExYTM0LFxuICAgIDB4MmQxYjFiMzYsIDB4YjI2ZTZlZGMsIDB4ZWU1YTVhYjQsIDB4ZmJhMGEwNWIsXG4gICAgMHhmNjUyNTJhNCwgMHg0ZDNiM2I3NiwgMHg2MWQ2ZDZiNywgMHhjZWIzYjM3ZCxcbiAgICAweDdiMjkyOTUyLCAweDNlZTNlM2RkLCAweDcxMmYyZjVlLCAweDk3ODQ4NDEzLFxuICAgIDB4ZjU1MzUzYTYsIDB4NjhkMWQxYjksIDB4MDAwMDAwMDAsIDB4MmNlZGVkYzEsXG4gICAgMHg2MDIwMjA0MCwgMHgxZmZjZmNlMywgMHhjOGIxYjE3OSwgMHhlZDViNWJiNixcbiAgICAweGJlNmE2YWQ0LCAweDQ2Y2JjYjhkLCAweGQ5YmViZTY3LCAweDRiMzkzOTcyLFxuICAgIDB4ZGU0YTRhOTQsIDB4ZDQ0YzRjOTgsIDB4ZTg1ODU4YjAsIDB4NGFjZmNmODUsXG4gICAgMHg2YmQwZDBiYiwgMHgyYWVmZWZjNSwgMHhlNWFhYWE0ZiwgMHgxNmZiZmJlZCxcbiAgICAweGM1NDM0Mzg2LCAweGQ3NGQ0ZDlhLCAweDU1MzMzMzY2LCAweDk0ODU4NTExLFxuICAgIDB4Y2Y0NTQ1OGEsIDB4MTBmOWY5ZTksIDB4MDYwMjAyMDQsIDB4ODE3ZjdmZmUsXG4gICAgMHhmMDUwNTBhMCwgMHg0NDNjM2M3OCwgMHhiYTlmOWYyNSwgMHhlM2E4YTg0YixcbiAgICAweGYzNTE1MWEyLCAweGZlYTNhMzVkLCAweGMwNDA0MDgwLCAweDhhOGY4ZjA1LFxuICAgIDB4YWQ5MjkyM2YsIDB4YmM5ZDlkMjEsIDB4NDgzODM4NzAsIDB4MDRmNWY1ZjEsXG4gICAgMHhkZmJjYmM2MywgMHhjMWI2YjY3NywgMHg3NWRhZGFhZiwgMHg2MzIxMjE0MixcbiAgICAweDMwMTAxMDIwLCAweDFhZmZmZmU1LCAweDBlZjNmM2ZkLCAweDZkZDJkMmJmLFxuICAgIDB4NGNjZGNkODEsIDB4MTQwYzBjMTgsIDB4MzUxMzEzMjYsIDB4MmZlY2VjYzMsXG4gICAgMHhlMTVmNWZiZSwgMHhhMjk3OTczNSwgMHhjYzQ0NDQ4OCwgMHgzOTE3MTcyZSxcbiAgICAweDU3YzRjNDkzLCAweGYyYTdhNzU1LCAweDgyN2U3ZWZjLCAweDQ3M2QzZDdhLFxuICAgIDB4YWM2NDY0YzgsIDB4ZTc1ZDVkYmEsIDB4MmIxOTE5MzIsIDB4OTU3MzczZTYsXG4gICAgMHhhMDYwNjBjMCwgMHg5ODgxODExOSwgMHhkMTRmNGY5ZSwgMHg3ZmRjZGNhMyxcbiAgICAweDY2MjIyMjQ0LCAweDdlMmEyYTU0LCAweGFiOTA5MDNiLCAweDgzODg4ODBiLFxuICAgIDB4Y2E0NjQ2OGMsIDB4MjllZWVlYzcsIDB4ZDNiOGI4NmIsIDB4M2MxNDE0MjgsXG4gICAgMHg3OWRlZGVhNywgMHhlMjVlNWViYywgMHgxZDBiMGIxNiwgMHg3NmRiZGJhZCxcbiAgICAweDNiZTBlMGRiLCAweDU2MzIzMjY0LCAweDRlM2EzYTc0LCAweDFlMGEwYTE0LFxuICAgIDB4ZGI0OTQ5OTIsIDB4MGEwNjA2MGMsIDB4NmMyNDI0NDgsIDB4ZTQ1YzVjYjgsXG4gICAgMHg1ZGMyYzI5ZiwgMHg2ZWQzZDNiZCwgMHhlZmFjYWM0MywgMHhhNjYyNjJjNCxcbiAgICAweGE4OTE5MTM5LCAweGE0OTU5NTMxLCAweDM3ZTRlNGQzLCAweDhiNzk3OWYyLFxuICAgIDB4MzJlN2U3ZDUsIDB4NDNjOGM4OGIsIDB4NTkzNzM3NmUsIDB4Yjc2ZDZkZGEsXG4gICAgMHg4YzhkOGQwMSwgMHg2NGQ1ZDViMSwgMHhkMjRlNGU5YywgMHhlMGE5YTk0OSxcbiAgICAweGI0NmM2Y2Q4LCAweGZhNTY1NmFjLCAweDA3ZjRmNGYzLCAweDI1ZWFlYWNmLFxuICAgIDB4YWY2NTY1Y2EsIDB4OGU3YTdhZjQsIDB4ZTlhZWFlNDcsIDB4MTgwODA4MTAsXG4gICAgMHhkNWJhYmE2ZiwgMHg4ODc4NzhmMCwgMHg2ZjI1MjU0YSwgMHg3MjJlMmU1YyxcbiAgICAweDI0MWMxYzM4LCAweGYxYTZhNjU3LCAweGM3YjRiNDczLCAweDUxYzZjNjk3LFxuICAgIDB4MjNlOGU4Y2IsIDB4N2NkZGRkYTEsIDB4OWM3NDc0ZTgsIDB4MjExZjFmM2UsXG4gICAgMHhkZDRiNGI5NiwgMHhkY2JkYmQ2MSwgMHg4NjhiOGIwZCwgMHg4NThhOGEwZixcbiAgICAweDkwNzA3MGUwLCAweDQyM2UzZTdjLCAweGM0YjViNTcxLCAweGFhNjY2NmNjLFxuICAgIDB4ZDg0ODQ4OTAsIDB4MDUwMzAzMDYsIDB4MDFmNmY2ZjcsIDB4MTIwZTBlMWMsXG4gICAgMHhhMzYxNjFjMiwgMHg1ZjM1MzU2YSwgMHhmOTU3NTdhZSwgMHhkMGI5Yjk2OSxcbiAgICAweDkxODY4NjE3LCAweDU4YzFjMTk5LCAweDI3MWQxZDNhLCAweGI5OWU5ZTI3LFxuICAgIDB4MzhlMWUxZDksIDB4MTNmOGY4ZWIsIDB4YjM5ODk4MmIsIDB4MzMxMTExMjIsXG4gICAgMHhiYjY5NjlkMiwgMHg3MGQ5ZDlhOSwgMHg4OThlOGUwNywgMHhhNzk0OTQzMyxcbiAgICAweGI2OWI5YjJkLCAweDIyMWUxZTNjLCAweDkyODc4NzE1LCAweDIwZTllOWM5LFxuICAgIDB4NDljZWNlODcsIDB4ZmY1NTU1YWEsIDB4NzgyODI4NTAsIDB4N2FkZmRmYTUsXG4gICAgMHg4ZjhjOGMwMywgMHhmOGExYTE1OSwgMHg4MDg5ODkwOSwgMHgxNzBkMGQxYSxcbiAgICAweGRhYmZiZjY1LCAweDMxZTZlNmQ3LCAweGM2NDI0Mjg0LCAweGI4Njg2OGQwLFxuICAgIDB4YzM0MTQxODIsIDB4YjA5OTk5MjksIDB4NzcyZDJkNWEsIDB4MTEwZjBmMWUsXG4gICAgMHhjYmIwYjA3YiwgMHhmYzU0NTRhOCwgMHhkNmJiYmI2ZCwgMHgzYTE2MTYyY1xuXTtcblxudmFyIFQyID0gW1xuICAgIDB4NjM2M2M2YTUsIDB4N2M3Y2Y4ODQsIDB4Nzc3N2VlOTksIDB4N2I3YmY2OGQsXG4gICAgMHhmMmYyZmYwZCwgMHg2YjZiZDZiZCwgMHg2ZjZmZGViMSwgMHhjNWM1OTE1NCxcbiAgICAweDMwMzA2MDUwLCAweDAxMDEwMjAzLCAweDY3NjdjZWE5LCAweDJiMmI1NjdkLFxuICAgIDB4ZmVmZWU3MTksIDB4ZDdkN2I1NjIsIDB4YWJhYjRkZTYsIDB4NzY3NmVjOWEsXG4gICAgMHhjYWNhOGY0NSwgMHg4MjgyMWY5ZCwgMHhjOWM5ODk0MCwgMHg3ZDdkZmE4NyxcbiAgICAweGZhZmFlZjE1LCAweDU5NTliMmViLCAweDQ3NDc4ZWM5LCAweGYwZjBmYjBiLFxuICAgIDB4YWRhZDQxZWMsIDB4ZDRkNGIzNjcsIDB4YTJhMjVmZmQsIDB4YWZhZjQ1ZWEsXG4gICAgMHg5YzljMjNiZiwgMHhhNGE0NTNmNywgMHg3MjcyZTQ5NiwgMHhjMGMwOWI1YixcbiAgICAweGI3Yjc3NWMyLCAweGZkZmRlMTFjLCAweDkzOTMzZGFlLCAweDI2MjY0YzZhLFxuICAgIDB4MzYzNjZjNWEsIDB4M2YzZjdlNDEsIDB4ZjdmN2Y1MDIsIDB4Y2NjYzgzNGYsXG4gICAgMHgzNDM0Njg1YywgMHhhNWE1NTFmNCwgMHhlNWU1ZDEzNCwgMHhmMWYxZjkwOCxcbiAgICAweDcxNzFlMjkzLCAweGQ4ZDhhYjczLCAweDMxMzE2MjUzLCAweDE1MTUyYTNmLFxuICAgIDB4MDQwNDA4MGMsIDB4YzdjNzk1NTIsIDB4MjMyMzQ2NjUsIDB4YzNjMzlkNWUsXG4gICAgMHgxODE4MzAyOCwgMHg5Njk2MzdhMSwgMHgwNTA1MGEwZiwgMHg5YTlhMmZiNSxcbiAgICAweDA3MDcwZTA5LCAweDEyMTIyNDM2LCAweDgwODAxYjliLCAweGUyZTJkZjNkLFxuICAgIDB4ZWJlYmNkMjYsIDB4MjcyNzRlNjksIDB4YjJiMjdmY2QsIDB4NzU3NWVhOWYsXG4gICAgMHgwOTA5MTIxYiwgMHg4MzgzMWQ5ZSwgMHgyYzJjNTg3NCwgMHgxYTFhMzQyZSxcbiAgICAweDFiMWIzNjJkLCAweDZlNmVkY2IyLCAweDVhNWFiNGVlLCAweGEwYTA1YmZiLFxuICAgIDB4NTI1MmE0ZjYsIDB4M2IzYjc2NGQsIDB4ZDZkNmI3NjEsIDB4YjNiMzdkY2UsXG4gICAgMHgyOTI5NTI3YiwgMHhlM2UzZGQzZSwgMHgyZjJmNWU3MSwgMHg4NDg0MTM5NyxcbiAgICAweDUzNTNhNmY1LCAweGQxZDFiOTY4LCAweDAwMDAwMDAwLCAweGVkZWRjMTJjLFxuICAgIDB4MjAyMDQwNjAsIDB4ZmNmY2UzMWYsIDB4YjFiMTc5YzgsIDB4NWI1YmI2ZWQsXG4gICAgMHg2YTZhZDRiZSwgMHhjYmNiOGQ0NiwgMHhiZWJlNjdkOSwgMHgzOTM5NzI0YixcbiAgICAweDRhNGE5NGRlLCAweDRjNGM5OGQ0LCAweDU4NThiMGU4LCAweGNmY2Y4NTRhLFxuICAgIDB4ZDBkMGJiNmIsIDB4ZWZlZmM1MmEsIDB4YWFhYTRmZTUsIDB4ZmJmYmVkMTYsXG4gICAgMHg0MzQzODZjNSwgMHg0ZDRkOWFkNywgMHgzMzMzNjY1NSwgMHg4NTg1MTE5NCxcbiAgICAweDQ1NDU4YWNmLCAweGY5ZjllOTEwLCAweDAyMDIwNDA2LCAweDdmN2ZmZTgxLFxuICAgIDB4NTA1MGEwZjAsIDB4M2MzYzc4NDQsIDB4OWY5ZjI1YmEsIDB4YThhODRiZTMsXG4gICAgMHg1MTUxYTJmMywgMHhhM2EzNWRmZSwgMHg0MDQwODBjMCwgMHg4ZjhmMDU4YSxcbiAgICAweDkyOTIzZmFkLCAweDlkOWQyMWJjLCAweDM4Mzg3MDQ4LCAweGY1ZjVmMTA0LFxuICAgIDB4YmNiYzYzZGYsIDB4YjZiNjc3YzEsIDB4ZGFkYWFmNzUsIDB4MjEyMTQyNjMsXG4gICAgMHgxMDEwMjAzMCwgMHhmZmZmZTUxYSwgMHhmM2YzZmQwZSwgMHhkMmQyYmY2ZCxcbiAgICAweGNkY2Q4MTRjLCAweDBjMGMxODE0LCAweDEzMTMyNjM1LCAweGVjZWNjMzJmLFxuICAgIDB4NWY1ZmJlZTEsIDB4OTc5NzM1YTIsIDB4NDQ0NDg4Y2MsIDB4MTcxNzJlMzksXG4gICAgMHhjNGM0OTM1NywgMHhhN2E3NTVmMiwgMHg3ZTdlZmM4MiwgMHgzZDNkN2E0NyxcbiAgICAweDY0NjRjOGFjLCAweDVkNWRiYWU3LCAweDE5MTkzMjJiLCAweDczNzNlNjk1LFxuICAgIDB4NjA2MGMwYTAsIDB4ODE4MTE5OTgsIDB4NGY0ZjllZDEsIDB4ZGNkY2EzN2YsXG4gICAgMHgyMjIyNDQ2NiwgMHgyYTJhNTQ3ZSwgMHg5MDkwM2JhYiwgMHg4ODg4MGI4MyxcbiAgICAweDQ2NDY4Y2NhLCAweGVlZWVjNzI5LCAweGI4Yjg2YmQzLCAweDE0MTQyODNjLFxuICAgIDB4ZGVkZWE3NzksIDB4NWU1ZWJjZTIsIDB4MGIwYjE2MWQsIDB4ZGJkYmFkNzYsXG4gICAgMHhlMGUwZGIzYiwgMHgzMjMyNjQ1NiwgMHgzYTNhNzQ0ZSwgMHgwYTBhMTQxZSxcbiAgICAweDQ5NDk5MmRiLCAweDA2MDYwYzBhLCAweDI0MjQ0ODZjLCAweDVjNWNiOGU0LFxuICAgIDB4YzJjMjlmNWQsIDB4ZDNkM2JkNmUsIDB4YWNhYzQzZWYsIDB4NjI2MmM0YTYsXG4gICAgMHg5MTkxMzlhOCwgMHg5NTk1MzFhNCwgMHhlNGU0ZDMzNywgMHg3OTc5ZjI4YixcbiAgICAweGU3ZTdkNTMyLCAweGM4Yzg4YjQzLCAweDM3Mzc2ZTU5LCAweDZkNmRkYWI3LFxuICAgIDB4OGQ4ZDAxOGMsIDB4ZDVkNWIxNjQsIDB4NGU0ZTljZDIsIDB4YTlhOTQ5ZTAsXG4gICAgMHg2YzZjZDhiNCwgMHg1NjU2YWNmYSwgMHhmNGY0ZjMwNywgMHhlYWVhY2YyNSxcbiAgICAweDY1NjVjYWFmLCAweDdhN2FmNDhlLCAweGFlYWU0N2U5LCAweDA4MDgxMDE4LFxuICAgIDB4YmFiYTZmZDUsIDB4Nzg3OGYwODgsIDB4MjUyNTRhNmYsIDB4MmUyZTVjNzIsXG4gICAgMHgxYzFjMzgyNCwgMHhhNmE2NTdmMSwgMHhiNGI0NzNjNywgMHhjNmM2OTc1MSxcbiAgICAweGU4ZThjYjIzLCAweGRkZGRhMTdjLCAweDc0NzRlODljLCAweDFmMWYzZTIxLFxuICAgIDB4NGI0Yjk2ZGQsIDB4YmRiZDYxZGMsIDB4OGI4YjBkODYsIDB4OGE4YTBmODUsXG4gICAgMHg3MDcwZTA5MCwgMHgzZTNlN2M0MiwgMHhiNWI1NzFjNCwgMHg2NjY2Y2NhYSxcbiAgICAweDQ4NDg5MGQ4LCAweDAzMDMwNjA1LCAweGY2ZjZmNzAxLCAweDBlMGUxYzEyLFxuICAgIDB4NjE2MWMyYTMsIDB4MzUzNTZhNWYsIDB4NTc1N2FlZjksIDB4YjliOTY5ZDAsXG4gICAgMHg4Njg2MTc5MSwgMHhjMWMxOTk1OCwgMHgxZDFkM2EyNywgMHg5ZTllMjdiOSxcbiAgICAweGUxZTFkOTM4LCAweGY4ZjhlYjEzLCAweDk4OTgyYmIzLCAweDExMTEyMjMzLFxuICAgIDB4Njk2OWQyYmIsIDB4ZDlkOWE5NzAsIDB4OGU4ZTA3ODksIDB4OTQ5NDMzYTcsXG4gICAgMHg5YjliMmRiNiwgMHgxZTFlM2MyMiwgMHg4Nzg3MTU5MiwgMHhlOWU5YzkyMCxcbiAgICAweGNlY2U4NzQ5LCAweDU1NTVhYWZmLCAweDI4Mjg1MDc4LCAweGRmZGZhNTdhLFxuICAgIDB4OGM4YzAzOGYsIDB4YTFhMTU5ZjgsIDB4ODk4OTA5ODAsIDB4MGQwZDFhMTcsXG4gICAgMHhiZmJmNjVkYSwgMHhlNmU2ZDczMSwgMHg0MjQyODRjNiwgMHg2ODY4ZDBiOCxcbiAgICAweDQxNDE4MmMzLCAweDk5OTkyOWIwLCAweDJkMmQ1YTc3LCAweDBmMGYxZTExLFxuICAgIDB4YjBiMDdiY2IsIDB4NTQ1NGE4ZmMsIDB4YmJiYjZkZDYsIDB4MTYxNjJjM2Fcbl07XG5cbnZhciBUMyA9IFtcbiAgICAweDYzYzZhNTYzLCAweDdjZjg4NDdjLCAweDc3ZWU5OTc3LCAweDdiZjY4ZDdiLFxuICAgIDB4ZjJmZjBkZjIsIDB4NmJkNmJkNmIsIDB4NmZkZWIxNmYsIDB4YzU5MTU0YzUsXG4gICAgMHgzMDYwNTAzMCwgMHgwMTAyMDMwMSwgMHg2N2NlYTk2NywgMHgyYjU2N2QyYixcbiAgICAweGZlZTcxOWZlLCAweGQ3YjU2MmQ3LCAweGFiNGRlNmFiLCAweDc2ZWM5YTc2LFxuICAgIDB4Y2E4ZjQ1Y2EsIDB4ODIxZjlkODIsIDB4Yzk4OTQwYzksIDB4N2RmYTg3N2QsXG4gICAgMHhmYWVmMTVmYSwgMHg1OWIyZWI1OSwgMHg0NzhlYzk0NywgMHhmMGZiMGJmMCxcbiAgICAweGFkNDFlY2FkLCAweGQ0YjM2N2Q0LCAweGEyNWZmZGEyLCAweGFmNDVlYWFmLFxuICAgIDB4OWMyM2JmOWMsIDB4YTQ1M2Y3YTQsIDB4NzJlNDk2NzIsIDB4YzA5YjViYzAsXG4gICAgMHhiNzc1YzJiNywgMHhmZGUxMWNmZCwgMHg5MzNkYWU5MywgMHgyNjRjNmEyNixcbiAgICAweDM2NmM1YTM2LCAweDNmN2U0MTNmLCAweGY3ZjUwMmY3LCAweGNjODM0ZmNjLFxuICAgIDB4MzQ2ODVjMzQsIDB4YTU1MWY0YTUsIDB4ZTVkMTM0ZTUsIDB4ZjFmOTA4ZjEsXG4gICAgMHg3MWUyOTM3MSwgMHhkOGFiNzNkOCwgMHgzMTYyNTMzMSwgMHgxNTJhM2YxNSxcbiAgICAweDA0MDgwYzA0LCAweGM3OTU1MmM3LCAweDIzNDY2NTIzLCAweGMzOWQ1ZWMzLFxuICAgIDB4MTgzMDI4MTgsIDB4OTYzN2ExOTYsIDB4MDUwYTBmMDUsIDB4OWEyZmI1OWEsXG4gICAgMHgwNzBlMDkwNywgMHgxMjI0MzYxMiwgMHg4MDFiOWI4MCwgMHhlMmRmM2RlMixcbiAgICAweGViY2QyNmViLCAweDI3NGU2OTI3LCAweGIyN2ZjZGIyLCAweDc1ZWE5Zjc1LFxuICAgIDB4MDkxMjFiMDksIDB4ODMxZDllODMsIDB4MmM1ODc0MmMsIDB4MWEzNDJlMWEsXG4gICAgMHgxYjM2MmQxYiwgMHg2ZWRjYjI2ZSwgMHg1YWI0ZWU1YSwgMHhhMDViZmJhMCxcbiAgICAweDUyYTRmNjUyLCAweDNiNzY0ZDNiLCAweGQ2Yjc2MWQ2LCAweGIzN2RjZWIzLFxuICAgIDB4Mjk1MjdiMjksIDB4ZTNkZDNlZTMsIDB4MmY1ZTcxMmYsIDB4ODQxMzk3ODQsXG4gICAgMHg1M2E2ZjU1MywgMHhkMWI5NjhkMSwgMHgwMDAwMDAwMCwgMHhlZGMxMmNlZCxcbiAgICAweDIwNDA2MDIwLCAweGZjZTMxZmZjLCAweGIxNzljOGIxLCAweDViYjZlZDViLFxuICAgIDB4NmFkNGJlNmEsIDB4Y2I4ZDQ2Y2IsIDB4YmU2N2Q5YmUsIDB4Mzk3MjRiMzksXG4gICAgMHg0YTk0ZGU0YSwgMHg0Yzk4ZDQ0YywgMHg1OGIwZTg1OCwgMHhjZjg1NGFjZixcbiAgICAweGQwYmI2YmQwLCAweGVmYzUyYWVmLCAweGFhNGZlNWFhLCAweGZiZWQxNmZiLFxuICAgIDB4NDM4NmM1NDMsIDB4NGQ5YWQ3NGQsIDB4MzM2NjU1MzMsIDB4ODUxMTk0ODUsXG4gICAgMHg0NThhY2Y0NSwgMHhmOWU5MTBmOSwgMHgwMjA0MDYwMiwgMHg3ZmZlODE3ZixcbiAgICAweDUwYTBmMDUwLCAweDNjNzg0NDNjLCAweDlmMjViYTlmLCAweGE4NGJlM2E4LFxuICAgIDB4NTFhMmYzNTEsIDB4YTM1ZGZlYTMsIDB4NDA4MGMwNDAsIDB4OGYwNThhOGYsXG4gICAgMHg5MjNmYWQ5MiwgMHg5ZDIxYmM5ZCwgMHgzODcwNDgzOCwgMHhmNWYxMDRmNSxcbiAgICAweGJjNjNkZmJjLCAweGI2NzdjMWI2LCAweGRhYWY3NWRhLCAweDIxNDI2MzIxLFxuICAgIDB4MTAyMDMwMTAsIDB4ZmZlNTFhZmYsIDB4ZjNmZDBlZjMsIDB4ZDJiZjZkZDIsXG4gICAgMHhjZDgxNGNjZCwgMHgwYzE4MTQwYywgMHgxMzI2MzUxMywgMHhlY2MzMmZlYyxcbiAgICAweDVmYmVlMTVmLCAweDk3MzVhMjk3LCAweDQ0ODhjYzQ0LCAweDE3MmUzOTE3LFxuICAgIDB4YzQ5MzU3YzQsIDB4YTc1NWYyYTcsIDB4N2VmYzgyN2UsIDB4M2Q3YTQ3M2QsXG4gICAgMHg2NGM4YWM2NCwgMHg1ZGJhZTc1ZCwgMHgxOTMyMmIxOSwgMHg3M2U2OTU3MyxcbiAgICAweDYwYzBhMDYwLCAweDgxMTk5ODgxLCAweDRmOWVkMTRmLCAweGRjYTM3ZmRjLFxuICAgIDB4MjI0NDY2MjIsIDB4MmE1NDdlMmEsIDB4OTAzYmFiOTAsIDB4ODgwYjgzODgsXG4gICAgMHg0NjhjY2E0NiwgMHhlZWM3MjllZSwgMHhiODZiZDNiOCwgMHgxNDI4M2MxNCxcbiAgICAweGRlYTc3OWRlLCAweDVlYmNlMjVlLCAweDBiMTYxZDBiLCAweGRiYWQ3NmRiLFxuICAgIDB4ZTBkYjNiZTAsIDB4MzI2NDU2MzIsIDB4M2E3NDRlM2EsIDB4MGExNDFlMGEsXG4gICAgMHg0OTkyZGI0OSwgMHgwNjBjMGEwNiwgMHgyNDQ4NmMyNCwgMHg1Y2I4ZTQ1YyxcbiAgICAweGMyOWY1ZGMyLCAweGQzYmQ2ZWQzLCAweGFjNDNlZmFjLCAweDYyYzRhNjYyLFxuICAgIDB4OTEzOWE4OTEsIDB4OTUzMWE0OTUsIDB4ZTRkMzM3ZTQsIDB4NzlmMjhiNzksXG4gICAgMHhlN2Q1MzJlNywgMHhjODhiNDNjOCwgMHgzNzZlNTkzNywgMHg2ZGRhYjc2ZCxcbiAgICAweDhkMDE4YzhkLCAweGQ1YjE2NGQ1LCAweDRlOWNkMjRlLCAweGE5NDllMGE5LFxuICAgIDB4NmNkOGI0NmMsIDB4NTZhY2ZhNTYsIDB4ZjRmMzA3ZjQsIDB4ZWFjZjI1ZWEsXG4gICAgMHg2NWNhYWY2NSwgMHg3YWY0OGU3YSwgMHhhZTQ3ZTlhZSwgMHgwODEwMTgwOCxcbiAgICAweGJhNmZkNWJhLCAweDc4ZjA4ODc4LCAweDI1NGE2ZjI1LCAweDJlNWM3MjJlLFxuICAgIDB4MWMzODI0MWMsIDB4YTY1N2YxYTYsIDB4YjQ3M2M3YjQsIDB4YzY5NzUxYzYsXG4gICAgMHhlOGNiMjNlOCwgMHhkZGExN2NkZCwgMHg3NGU4OWM3NCwgMHgxZjNlMjExZixcbiAgICAweDRiOTZkZDRiLCAweGJkNjFkY2JkLCAweDhiMGQ4NjhiLCAweDhhMGY4NThhLFxuICAgIDB4NzBlMDkwNzAsIDB4M2U3YzQyM2UsIDB4YjU3MWM0YjUsIDB4NjZjY2FhNjYsXG4gICAgMHg0ODkwZDg0OCwgMHgwMzA2MDUwMywgMHhmNmY3MDFmNiwgMHgwZTFjMTIwZSxcbiAgICAweDYxYzJhMzYxLCAweDM1NmE1ZjM1LCAweDU3YWVmOTU3LCAweGI5NjlkMGI5LFxuICAgIDB4ODYxNzkxODYsIDB4YzE5OTU4YzEsIDB4MWQzYTI3MWQsIDB4OWUyN2I5OWUsXG4gICAgMHhlMWQ5MzhlMSwgMHhmOGViMTNmOCwgMHg5ODJiYjM5OCwgMHgxMTIyMzMxMSxcbiAgICAweDY5ZDJiYjY5LCAweGQ5YTk3MGQ5LCAweDhlMDc4OThlLCAweDk0MzNhNzk0LFxuICAgIDB4OWIyZGI2OWIsIDB4MWUzYzIyMWUsIDB4ODcxNTkyODcsIDB4ZTljOTIwZTksXG4gICAgMHhjZTg3NDljZSwgMHg1NWFhZmY1NSwgMHgyODUwNzgyOCwgMHhkZmE1N2FkZixcbiAgICAweDhjMDM4ZjhjLCAweGExNTlmOGExLCAweDg5MDk4MDg5LCAweDBkMWExNzBkLFxuICAgIDB4YmY2NWRhYmYsIDB4ZTZkNzMxZTYsIDB4NDI4NGM2NDIsIDB4NjhkMGI4NjgsXG4gICAgMHg0MTgyYzM0MSwgMHg5OTI5YjA5OSwgMHgyZDVhNzcyZCwgMHgwZjFlMTEwZixcbiAgICAweGIwN2JjYmIwLCAweDU0YThmYzU0LCAweGJiNmRkNmJiLCAweDE2MmMzYTE2XG5dO1xuXG52YXIgVDQgPSBbXG4gICAgMHhjNmE1NjM2MywgMHhmODg0N2M3YywgMHhlZTk5Nzc3NywgMHhmNjhkN2I3YixcbiAgICAweGZmMGRmMmYyLCAweGQ2YmQ2YjZiLCAweGRlYjE2ZjZmLCAweDkxNTRjNWM1LFxuICAgIDB4NjA1MDMwMzAsIDB4MDIwMzAxMDEsIDB4Y2VhOTY3NjcsIDB4NTY3ZDJiMmIsXG4gICAgMHhlNzE5ZmVmZSwgMHhiNTYyZDdkNywgMHg0ZGU2YWJhYiwgMHhlYzlhNzY3NixcbiAgICAweDhmNDVjYWNhLCAweDFmOWQ4MjgyLCAweDg5NDBjOWM5LCAweGZhODc3ZDdkLFxuICAgIDB4ZWYxNWZhZmEsIDB4YjJlYjU5NTksIDB4OGVjOTQ3NDcsIDB4ZmIwYmYwZjAsXG4gICAgMHg0MWVjYWRhZCwgMHhiMzY3ZDRkNCwgMHg1ZmZkYTJhMiwgMHg0NWVhYWZhZixcbiAgICAweDIzYmY5YzljLCAweDUzZjdhNGE0LCAweGU0OTY3MjcyLCAweDliNWJjMGMwLFxuICAgIDB4NzVjMmI3YjcsIDB4ZTExY2ZkZmQsIDB4M2RhZTkzOTMsIDB4NGM2YTI2MjYsXG4gICAgMHg2YzVhMzYzNiwgMHg3ZTQxM2YzZiwgMHhmNTAyZjdmNywgMHg4MzRmY2NjYyxcbiAgICAweDY4NWMzNDM0LCAweDUxZjRhNWE1LCAweGQxMzRlNWU1LCAweGY5MDhmMWYxLFxuICAgIDB4ZTI5MzcxNzEsIDB4YWI3M2Q4ZDgsIDB4NjI1MzMxMzEsIDB4MmEzZjE1MTUsXG4gICAgMHgwODBjMDQwNCwgMHg5NTUyYzdjNywgMHg0NjY1MjMyMywgMHg5ZDVlYzNjMyxcbiAgICAweDMwMjgxODE4LCAweDM3YTE5Njk2LCAweDBhMGYwNTA1LCAweDJmYjU5YTlhLFxuICAgIDB4MGUwOTA3MDcsIDB4MjQzNjEyMTIsIDB4MWI5YjgwODAsIDB4ZGYzZGUyZTIsXG4gICAgMHhjZDI2ZWJlYiwgMHg0ZTY5MjcyNywgMHg3ZmNkYjJiMiwgMHhlYTlmNzU3NSxcbiAgICAweDEyMWIwOTA5LCAweDFkOWU4MzgzLCAweDU4NzQyYzJjLCAweDM0MmUxYTFhLFxuICAgIDB4MzYyZDFiMWIsIDB4ZGNiMjZlNmUsIDB4YjRlZTVhNWEsIDB4NWJmYmEwYTAsXG4gICAgMHhhNGY2NTI1MiwgMHg3NjRkM2IzYiwgMHhiNzYxZDZkNiwgMHg3ZGNlYjNiMyxcbiAgICAweDUyN2IyOTI5LCAweGRkM2VlM2UzLCAweDVlNzEyZjJmLCAweDEzOTc4NDg0LFxuICAgIDB4YTZmNTUzNTMsIDB4Yjk2OGQxZDEsIDB4MDAwMDAwMDAsIDB4YzEyY2VkZWQsXG4gICAgMHg0MDYwMjAyMCwgMHhlMzFmZmNmYywgMHg3OWM4YjFiMSwgMHhiNmVkNWI1YixcbiAgICAweGQ0YmU2YTZhLCAweDhkNDZjYmNiLCAweDY3ZDliZWJlLCAweDcyNGIzOTM5LFxuICAgIDB4OTRkZTRhNGEsIDB4OThkNDRjNGMsIDB4YjBlODU4NTgsIDB4ODU0YWNmY2YsXG4gICAgMHhiYjZiZDBkMCwgMHhjNTJhZWZlZiwgMHg0ZmU1YWFhYSwgMHhlZDE2ZmJmYixcbiAgICAweDg2YzU0MzQzLCAweDlhZDc0ZDRkLCAweDY2NTUzMzMzLCAweDExOTQ4NTg1LFxuICAgIDB4OGFjZjQ1NDUsIDB4ZTkxMGY5ZjksIDB4MDQwNjAyMDIsIDB4ZmU4MTdmN2YsXG4gICAgMHhhMGYwNTA1MCwgMHg3ODQ0M2MzYywgMHgyNWJhOWY5ZiwgMHg0YmUzYThhOCxcbiAgICAweGEyZjM1MTUxLCAweDVkZmVhM2EzLCAweDgwYzA0MDQwLCAweDA1OGE4ZjhmLFxuICAgIDB4M2ZhZDkyOTIsIDB4MjFiYzlkOWQsIDB4NzA0ODM4MzgsIDB4ZjEwNGY1ZjUsXG4gICAgMHg2M2RmYmNiYywgMHg3N2MxYjZiNiwgMHhhZjc1ZGFkYSwgMHg0MjYzMjEyMSxcbiAgICAweDIwMzAxMDEwLCAweGU1MWFmZmZmLCAweGZkMGVmM2YzLCAweGJmNmRkMmQyLFxuICAgIDB4ODE0Y2NkY2QsIDB4MTgxNDBjMGMsIDB4MjYzNTEzMTMsIDB4YzMyZmVjZWMsXG4gICAgMHhiZWUxNWY1ZiwgMHgzNWEyOTc5NywgMHg4OGNjNDQ0NCwgMHgyZTM5MTcxNyxcbiAgICAweDkzNTdjNGM0LCAweDU1ZjJhN2E3LCAweGZjODI3ZTdlLCAweDdhNDczZDNkLFxuICAgIDB4YzhhYzY0NjQsIDB4YmFlNzVkNWQsIDB4MzIyYjE5MTksIDB4ZTY5NTczNzMsXG4gICAgMHhjMGEwNjA2MCwgMHgxOTk4ODE4MSwgMHg5ZWQxNGY0ZiwgMHhhMzdmZGNkYyxcbiAgICAweDQ0NjYyMjIyLCAweDU0N2UyYTJhLCAweDNiYWI5MDkwLCAweDBiODM4ODg4LFxuICAgIDB4OGNjYTQ2NDYsIDB4YzcyOWVlZWUsIDB4NmJkM2I4YjgsIDB4MjgzYzE0MTQsXG4gICAgMHhhNzc5ZGVkZSwgMHhiY2UyNWU1ZSwgMHgxNjFkMGIwYiwgMHhhZDc2ZGJkYixcbiAgICAweGRiM2JlMGUwLCAweDY0NTYzMjMyLCAweDc0NGUzYTNhLCAweDE0MWUwYTBhLFxuICAgIDB4OTJkYjQ5NDksIDB4MGMwYTA2MDYsIDB4NDg2YzI0MjQsIDB4YjhlNDVjNWMsXG4gICAgMHg5ZjVkYzJjMiwgMHhiZDZlZDNkMywgMHg0M2VmYWNhYywgMHhjNGE2NjI2MixcbiAgICAweDM5YTg5MTkxLCAweDMxYTQ5NTk1LCAweGQzMzdlNGU0LCAweGYyOGI3OTc5LFxuICAgIDB4ZDUzMmU3ZTcsIDB4OGI0M2M4YzgsIDB4NmU1OTM3MzcsIDB4ZGFiNzZkNmQsXG4gICAgMHgwMThjOGQ4ZCwgMHhiMTY0ZDVkNSwgMHg5Y2QyNGU0ZSwgMHg0OWUwYTlhOSxcbiAgICAweGQ4YjQ2YzZjLCAweGFjZmE1NjU2LCAweGYzMDdmNGY0LCAweGNmMjVlYWVhLFxuICAgIDB4Y2FhZjY1NjUsIDB4ZjQ4ZTdhN2EsIDB4NDdlOWFlYWUsIDB4MTAxODA4MDgsXG4gICAgMHg2ZmQ1YmFiYSwgMHhmMDg4Nzg3OCwgMHg0YTZmMjUyNSwgMHg1YzcyMmUyZSxcbiAgICAweDM4MjQxYzFjLCAweDU3ZjFhNmE2LCAweDczYzdiNGI0LCAweDk3NTFjNmM2LFxuICAgIDB4Y2IyM2U4ZTgsIDB4YTE3Y2RkZGQsIDB4ZTg5Yzc0NzQsIDB4M2UyMTFmMWYsXG4gICAgMHg5NmRkNGI0YiwgMHg2MWRjYmRiZCwgMHgwZDg2OGI4YiwgMHgwZjg1OGE4YSxcbiAgICAweGUwOTA3MDcwLCAweDdjNDIzZTNlLCAweDcxYzRiNWI1LCAweGNjYWE2NjY2LFxuICAgIDB4OTBkODQ4NDgsIDB4MDYwNTAzMDMsIDB4ZjcwMWY2ZjYsIDB4MWMxMjBlMGUsXG4gICAgMHhjMmEzNjE2MSwgMHg2YTVmMzUzNSwgMHhhZWY5NTc1NywgMHg2OWQwYjliOSxcbiAgICAweDE3OTE4Njg2LCAweDk5NThjMWMxLCAweDNhMjcxZDFkLCAweDI3Yjk5ZTllLFxuICAgIDB4ZDkzOGUxZTEsIDB4ZWIxM2Y4ZjgsIDB4MmJiMzk4OTgsIDB4MjIzMzExMTEsXG4gICAgMHhkMmJiNjk2OSwgMHhhOTcwZDlkOSwgMHgwNzg5OGU4ZSwgMHgzM2E3OTQ5NCxcbiAgICAweDJkYjY5YjliLCAweDNjMjIxZTFlLCAweDE1OTI4Nzg3LCAweGM5MjBlOWU5LFxuICAgIDB4ODc0OWNlY2UsIDB4YWFmZjU1NTUsIDB4NTA3ODI4MjgsIDB4YTU3YWRmZGYsXG4gICAgMHgwMzhmOGM4YywgMHg1OWY4YTFhMSwgMHgwOTgwODk4OSwgMHgxYTE3MGQwZCxcbiAgICAweDY1ZGFiZmJmLCAweGQ3MzFlNmU2LCAweDg0YzY0MjQyLCAweGQwYjg2ODY4LFxuICAgIDB4ODJjMzQxNDEsIDB4MjliMDk5OTksIDB4NWE3NzJkMmQsIDB4MWUxMTBmMGYsXG4gICAgMHg3YmNiYjBiMCwgMHhhOGZjNTQ1NCwgMHg2ZGQ2YmJiYiwgMHgyYzNhMTYxNlxuXTtcblxuZnVuY3Rpb24gQjAoeCkge1xuICByZXR1cm4gKHggJiAyNTUpO1xufVxuXG5mdW5jdGlvbiBCMSh4KSB7XG4gIHJldHVybiAoKHggPj4gOCkgJiAyNTUpO1xufVxuXG5mdW5jdGlvbiBCMih4KSB7XG4gIHJldHVybiAoKHggPj4gMTYpICYgMjU1KTtcbn1cblxuZnVuY3Rpb24gQjMoeCkge1xuICByZXR1cm4gKCh4ID4+IDI0KSAmIDI1NSk7XG59XG5cbmZ1bmN0aW9uIEYxKHgwLCB4MSwgeDIsIHgzKSB7XG4gIHJldHVybiBCMShUMVt4MCAmIDI1NV0pIHwgKEIxKFQxWyh4MSA+PiA4KSAmIDI1NV0pIDw8IDgpIHwgKEIxKFQxWyh4MiA+PiAxNikgJiAyNTVdKSA8PCAxNikgfCAoQjEoVDFbeDMgPj4+IDI0XSkgPDxcbiAgICAyNCk7XG59XG5cbmZ1bmN0aW9uIHBhY2tCeXRlcyhvY3RldHMpIHtcbiAgdmFyIGksIGo7XG4gIHZhciBsZW4gPSBvY3RldHMubGVuZ3RoO1xuICB2YXIgYiA9IG5ldyBBcnJheShsZW4gLyA0KTtcblxuICBpZiAoIW9jdGV0cyB8fCBsZW4gJSA0KSByZXR1cm47XG5cbiAgZm9yIChpID0gMCwgaiA9IDA7IGogPCBsZW47IGogKz0gNClcbiAgICBiW2krK10gPSBvY3RldHNbal0gfCAob2N0ZXRzW2ogKyAxXSA8PCA4KSB8IChvY3RldHNbaiArIDJdIDw8IDE2KSB8IChvY3RldHNbaiArIDNdIDw8IDI0KTtcblxuICByZXR1cm4gYjtcbn1cblxuZnVuY3Rpb24gdW5wYWNrQnl0ZXMocGFja2VkKSB7XG4gIHZhciBqO1xuICB2YXIgaSA9IDAsXG4gICAgbCA9IHBhY2tlZC5sZW5ndGg7XG4gIHZhciByID0gbmV3IEFycmF5KGwgKiA0KTtcblxuICBmb3IgKGogPSAwOyBqIDwgbDsgaisrKSB7XG4gICAgcltpKytdID0gQjAocGFja2VkW2pdKTtcbiAgICByW2krK10gPSBCMShwYWNrZWRbal0pO1xuICAgIHJbaSsrXSA9IEIyKHBhY2tlZFtqXSk7XG4gICAgcltpKytdID0gQjMocGFja2VkW2pdKTtcbiAgfVxuICByZXR1cm4gcjtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbnZhciBtYXhrYyA9IDg7XG52YXIgbWF4cmsgPSAxNDtcblxuZnVuY3Rpb24ga2V5RXhwYW5zaW9uKGtleSkge1xuICB2YXIga2MsIGksIGosIHIsIHQ7XG4gIHZhciByb3VuZHM7XG4gIHZhciBrZXlTY2hlZCA9IG5ldyBBcnJheShtYXhyayArIDEpO1xuICB2YXIga2V5bGVuID0ga2V5Lmxlbmd0aDtcbiAgdmFyIGsgPSBuZXcgQXJyYXkobWF4a2MpO1xuICB2YXIgdGsgPSBuZXcgQXJyYXkobWF4a2MpO1xuICB2YXIgcmNvbnBvaW50ZXIgPSAwO1xuXG4gIGlmIChrZXlsZW4gPT0gMTYpIHtcbiAgICByb3VuZHMgPSAxMDtcbiAgICBrYyA9IDQ7XG4gIH0gZWxzZSBpZiAoa2V5bGVuID09IDI0KSB7XG4gICAgcm91bmRzID0gMTI7XG4gICAga2MgPSA2O1xuICB9IGVsc2UgaWYgKGtleWxlbiA9PSAzMikge1xuICAgIHJvdW5kcyA9IDE0O1xuICAgIGtjID0gODtcbiAgfSBlbHNlIHtcbiAgICB1dGlsLnByaW50X2Vycm9yKCdhZXMuanM6IEludmFsaWQga2V5LWxlbmd0aCBmb3IgQUVTIGtleTonICsga2V5bGVuKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBmb3IgKGkgPSAwOyBpIDwgbWF4cmsgKyAxOyBpKyspIGtleVNjaGVkW2ldID0gbmV3IEFycmF5KDQpO1xuXG4gIGZvciAoaSA9IDAsIGogPSAwOyBqIDwga2V5bGVuOyBqKyssIGkgKz0gNClcbiAgICBrW2pdID0ga2V5LmNoYXJDb2RlQXQoaSkgfCAoa2V5LmNoYXJDb2RlQXQoaSArIDEpIDw8IDgpIHwgKGtleS5jaGFyQ29kZUF0KGkgKyAyKSA8PCAxNikgfCAoa2V5LmNoYXJDb2RlQXQoaSArIDMpIDw8XG4gICAgICAyNCk7XG5cbiAgZm9yIChqID0ga2MgLSAxOyBqID49IDA7IGotLSkgdGtbal0gPSBrW2pdO1xuXG4gIHIgPSAwO1xuICB0ID0gMDtcbiAgZm9yIChqID0gMDtcbiAgKGogPCBrYykgJiYgKHIgPCByb3VuZHMgKyAxKTspIHtcbiAgICBmb3IgKDtcbiAgICAoaiA8IGtjKSAmJiAodCA8IDQpOyBqKyssIHQrKykge1xuICAgICAga2V5U2NoZWRbcl1bdF0gPSB0a1tqXTtcbiAgICB9XG4gICAgaWYgKHQgPT0gNCkge1xuICAgICAgcisrO1xuICAgICAgdCA9IDA7XG4gICAgfVxuICB9XG5cbiAgd2hpbGUgKHIgPCByb3VuZHMgKyAxKSB7XG4gICAgdmFyIHRlbXAgPSB0a1trYyAtIDFdO1xuXG4gICAgdGtbMF0gXj0gU1tCMSh0ZW1wKV0gfCAoU1tCMih0ZW1wKV0gPDwgOCkgfCAoU1tCMyh0ZW1wKV0gPDwgMTYpIHwgKFNbQjAodGVtcCldIDw8IDI0KTtcbiAgICB0a1swXSBePSBSY29uW3Jjb25wb2ludGVyKytdO1xuXG4gICAgaWYgKGtjICE9IDgpIHtcbiAgICAgIGZvciAoaiA9IDE7IGogPCBrYzsgaisrKSB0a1tqXSBePSB0a1tqIC0gMV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAoaiA9IDE7IGogPCBrYyAvIDI7IGorKykgdGtbal0gXj0gdGtbaiAtIDFdO1xuXG4gICAgICB0ZW1wID0gdGtba2MgLyAyIC0gMV07XG4gICAgICB0a1trYyAvIDJdIF49IFNbQjAodGVtcCldIHwgKFNbQjEodGVtcCldIDw8IDgpIHwgKFNbQjIodGVtcCldIDw8IDE2KSB8IChTW0IzKHRlbXApXSA8PCAyNCk7XG5cbiAgICAgIGZvciAoaiA9IGtjIC8gMiArIDE7IGogPCBrYzsgaisrKSB0a1tqXSBePSB0a1tqIC0gMV07XG4gICAgfVxuXG4gICAgZm9yIChqID0gMDtcbiAgICAoaiA8IGtjKSAmJiAociA8IHJvdW5kcyArIDEpOykge1xuICAgICAgZm9yICg7XG4gICAgICAoaiA8IGtjKSAmJiAodCA8IDQpOyBqKyssIHQrKykge1xuICAgICAgICBrZXlTY2hlZFtyXVt0XSA9IHRrW2pdO1xuICAgICAgfVxuICAgICAgaWYgKHQgPT0gNCkge1xuICAgICAgICByKys7XG4gICAgICAgIHQgPSAwO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICB0aGlzLnJvdW5kcyA9IHJvdW5kcztcbiAgdGhpcy5yayA9IGtleVNjaGVkO1xuICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gQUVTZW5jcnlwdChibG9jaywgY3R4KSB7XG4gIHZhciByO1xuICB2YXIgdDAsIHQxLCB0MiwgdDM7XG5cbiAgdmFyIGIgPSBwYWNrQnl0ZXMoYmxvY2spO1xuICB2YXIgcm91bmRzID0gY3R4LnJvdW5kcztcbiAgdmFyIGIwID0gYlswXTtcbiAgdmFyIGIxID0gYlsxXTtcbiAgdmFyIGIyID0gYlsyXTtcbiAgdmFyIGIzID0gYlszXTtcblxuICBmb3IgKHIgPSAwOyByIDwgcm91bmRzIC0gMTsgcisrKSB7XG4gICAgdDAgPSBiMCBeIGN0eC5ya1tyXVswXTtcbiAgICB0MSA9IGIxIF4gY3R4LnJrW3JdWzFdO1xuICAgIHQyID0gYjIgXiBjdHgucmtbcl1bMl07XG4gICAgdDMgPSBiMyBeIGN0eC5ya1tyXVszXTtcblxuICAgIGIwID0gVDFbdDAgJiAyNTVdIF4gVDJbKHQxID4+IDgpICYgMjU1XSBeIFQzWyh0MiA+PiAxNikgJiAyNTVdIF4gVDRbdDMgPj4+IDI0XTtcbiAgICBiMSA9IFQxW3QxICYgMjU1XSBeIFQyWyh0MiA+PiA4KSAmIDI1NV0gXiBUM1sodDMgPj4gMTYpICYgMjU1XSBeIFQ0W3QwID4+PiAyNF07XG4gICAgYjIgPSBUMVt0MiAmIDI1NV0gXiBUMlsodDMgPj4gOCkgJiAyNTVdIF4gVDNbKHQwID4+IDE2KSAmIDI1NV0gXiBUNFt0MSA+Pj4gMjRdO1xuICAgIGIzID0gVDFbdDMgJiAyNTVdIF4gVDJbKHQwID4+IDgpICYgMjU1XSBeIFQzWyh0MSA+PiAxNikgJiAyNTVdIF4gVDRbdDIgPj4+IDI0XTtcbiAgfVxuXG4gIC8vIGxhc3Qgcm91bmQgaXMgc3BlY2lhbFxuICByID0gcm91bmRzIC0gMTtcblxuICB0MCA9IGIwIF4gY3R4LnJrW3JdWzBdO1xuICB0MSA9IGIxIF4gY3R4LnJrW3JdWzFdO1xuICB0MiA9IGIyIF4gY3R4LnJrW3JdWzJdO1xuICB0MyA9IGIzIF4gY3R4LnJrW3JdWzNdO1xuXG4gIGJbMF0gPSBGMSh0MCwgdDEsIHQyLCB0MykgXiBjdHgucmtbcm91bmRzXVswXTtcbiAgYlsxXSA9IEYxKHQxLCB0MiwgdDMsIHQwKSBeIGN0eC5ya1tyb3VuZHNdWzFdO1xuICBiWzJdID0gRjEodDIsIHQzLCB0MCwgdDEpIF4gY3R4LnJrW3JvdW5kc11bMl07XG4gIGJbM10gPSBGMSh0MywgdDAsIHQxLCB0MikgXiBjdHgucmtbcm91bmRzXVszXTtcblxuICByZXR1cm4gdW5wYWNrQnl0ZXMoYik7XG59XG5cbmZ1bmN0aW9uIG1ha2VDbGFzcyhsZW5ndGgpIHtcblxuICB2YXIgYyA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHRoaXMua2V5ID0ga2V5RXhwYW5zaW9uKGtleSk7XG5cbiAgICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihibG9jaykge1xuICAgICAgcmV0dXJuIEFFU2VuY3J5cHQoYmxvY2ssIHRoaXMua2V5KTtcbiAgICB9XG4gIH1cblxuICBjLmJsb2NrU2l6ZSA9IGMucHJvdG90eXBlLmJsb2NrU2l6ZSA9IDE2O1xuICBjLmtleVNpemUgPSBjLnByb3RvdHlwZS5rZXlTaXplID0gbGVuZ3RoIC8gODtcblxuICByZXR1cm4gYztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7fVxuXG52YXIgdHlwZXMgPSBbMTI4LCAxOTIsIDI1Nl07XG5cbmZvciAodmFyIGkgaW4gdHlwZXMpIHtcbiAgbW9kdWxlLmV4cG9ydHNbdHlwZXNbaV1dID0gbWFrZUNsYXNzKHR5cGVzW2ldKTtcbn1cbiIsIi8qIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSCBcbiAqIFxuICogT3JpZ2luYWxseSB3cml0dGVuIGJ5IG5rbGVpbiBzb2Z0d2FyZSAobmtsZWluLmNvbSlcbiAqL1xuXG4vKiBcbiAqIEphdmFzY3JpcHQgaW1wbGVtZW50YXRpb24gYmFzZWQgb24gQnJ1Y2UgU2NobmVpZXIncyByZWZlcmVuY2UgaW1wbGVtZW50YXRpb24uXG4gKlxuICpcbiAqIFRoZSBjb25zdHJ1Y3RvciBkb2Vzbid0IGRvIG11Y2ggb2YgYW55dGhpbmcuICBJdCdzIGp1c3QgaGVyZVxuICogc28gd2UgY2FuIHN0YXJ0IGRlZmluaW5nIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMgYW5kIHN1Y2guXG4gKi9cbmZ1bmN0aW9uIEJsb3dmaXNoKCkge307XG5cbi8qXG4gKiBEZWNsYXJlIHRoZSBibG9jayBzaXplIHNvIHRoYXQgcHJvdG9jb2xzIGtub3cgd2hhdCBzaXplXG4gKiBJbml0aWFsaXphdGlvbiBWZWN0b3IgKElWKSB0aGV5IHdpbGwgbmVlZC5cbiAqL1xuQmxvd2Zpc2gucHJvdG90eXBlLkJMT0NLU0laRSA9IDg7XG5cbi8qXG4gKiBUaGVzZSBhcmUgdGhlIGRlZmF1bHQgU0JPWEVTLlxuICovXG5CbG93ZmlzaC5wcm90b3R5cGUuU0JPWEVTID0gW1xuICBbXG4gICAgICAweGQxMzEwYmE2LCAweDk4ZGZiNWFjLCAweDJmZmQ3MmRiLCAweGQwMWFkZmI3LCAweGI4ZTFhZmVkLCAweDZhMjY3ZTk2LFxuICAgICAgMHhiYTdjOTA0NSwgMHhmMTJjN2Y5OSwgMHgyNGExOTk0NywgMHhiMzkxNmNmNywgMHgwODAxZjJlMiwgMHg4NThlZmMxNixcbiAgICAgIDB4NjM2OTIwZDgsIDB4NzE1NzRlNjksIDB4YTQ1OGZlYTMsIDB4ZjQ5MzNkN2UsIDB4MGQ5NTc0OGYsIDB4NzI4ZWI2NTgsXG4gICAgICAweDcxOGJjZDU4LCAweDgyMTU0YWVlLCAweDdiNTRhNDFkLCAweGMyNWE1OWI1LCAweDljMzBkNTM5LCAweDJhZjI2MDEzLFxuICAgICAgMHhjNWQxYjAyMywgMHgyODYwODVmMCwgMHhjYTQxNzkxOCwgMHhiOGRiMzhlZiwgMHg4ZTc5ZGNiMCwgMHg2MDNhMTgwZSxcbiAgICAgIDB4NmM5ZTBlOGIsIDB4YjAxZThhM2UsIDB4ZDcxNTc3YzEsIDB4YmQzMTRiMjcsIDB4NzhhZjJmZGEsIDB4NTU2MDVjNjAsXG4gICAgICAweGU2NTUyNWYzLCAweGFhNTVhYjk0LCAweDU3NDg5ODYyLCAweDYzZTgxNDQwLCAweDU1Y2EzOTZhLCAweDJhYWIxMGI2LFxuICAgICAgMHhiNGNjNWMzNCwgMHgxMTQxZThjZSwgMHhhMTU0ODZhZiwgMHg3YzcyZTk5MywgMHhiM2VlMTQxMSwgMHg2MzZmYmMyYSxcbiAgICAgIDB4MmJhOWM1NWQsIDB4NzQxODMxZjYsIDB4Y2U1YzNlMTYsIDB4OWI4NzkzMWUsIDB4YWZkNmJhMzMsIDB4NmMyNGNmNWMsXG4gICAgICAweDdhMzI1MzgxLCAweDI4OTU4Njc3LCAweDNiOGY0ODk4LCAweDZiNGJiOWFmLCAweGM0YmZlODFiLCAweDY2MjgyMTkzLFxuICAgICAgMHg2MWQ4MDljYywgMHhmYjIxYTk5MSwgMHg0ODdjYWM2MCwgMHg1ZGVjODAzMiwgMHhlZjg0NWQ1ZCwgMHhlOTg1NzViMSxcbiAgICAgIDB4ZGMyNjIzMDIsIDB4ZWI2NTFiODgsIDB4MjM4OTNlODEsIDB4ZDM5NmFjYzUsIDB4MGY2ZDZmZjMsIDB4ODNmNDQyMzksXG4gICAgICAweDJlMGI0NDgyLCAweGE0ODQyMDA0LCAweDY5YzhmMDRhLCAweDllMWY5YjVlLCAweDIxYzY2ODQyLCAweGY2ZTk2YzlhLFxuICAgICAgMHg2NzBjOWM2MSwgMHhhYmQzODhmMCwgMHg2YTUxYTBkMiwgMHhkODU0MmY2OCwgMHg5NjBmYTcyOCwgMHhhYjUxMzNhMyxcbiAgICAgIDB4NmVlZjBiNmMsIDB4MTM3YTNiZTQsIDB4YmEzYmYwNTAsIDB4N2VmYjJhOTgsIDB4YTFmMTY1MWQsIDB4MzlhZjAxNzYsXG4gICAgICAweDY2Y2E1OTNlLCAweDgyNDMwZTg4LCAweDhjZWU4NjE5LCAweDQ1NmY5ZmI0LCAweDdkODRhNWMzLCAweDNiOGI1ZWJlLFxuICAgICAgMHhlMDZmNzVkOCwgMHg4NWMxMjA3MywgMHg0MDFhNDQ5ZiwgMHg1NmMxNmFhNiwgMHg0ZWQzYWE2MiwgMHgzNjNmNzcwNixcbiAgICAgIDB4MWJmZWRmNzIsIDB4NDI5YjAyM2QsIDB4MzdkMGQ3MjQsIDB4ZDAwYTEyNDgsIDB4ZGIwZmVhZDMsIDB4NDlmMWMwOWIsXG4gICAgICAweDA3NTM3MmM5LCAweDgwOTkxYjdiLCAweDI1ZDQ3OWQ4LCAweGY2ZThkZWY3LCAweGUzZmU1MDFhLCAweGI2Nzk0YzNiLFxuICAgICAgMHg5NzZjZTBiZCwgMHgwNGMwMDZiYSwgMHhjMWE5NGZiNiwgMHg0MDlmNjBjNCwgMHg1ZTVjOWVjMiwgMHgxOTZhMjQ2MyxcbiAgICAgIDB4NjhmYjZmYWYsIDB4M2U2YzUzYjUsIDB4MTMzOWIyZWIsIDB4M2I1MmVjNmYsIDB4NmRmYzUxMWYsIDB4OWIzMDk1MmMsXG4gICAgICAweGNjODE0NTQ0LCAweGFmNWViZDA5LCAweGJlZTNkMDA0LCAweGRlMzM0YWZkLCAweDY2MGYyODA3LCAweDE5MmU0YmIzLFxuICAgICAgMHhjMGNiYTg1NywgMHg0NWM4NzQwZiwgMHhkMjBiNWYzOSwgMHhiOWQzZmJkYiwgMHg1NTc5YzBiZCwgMHgxYTYwMzIwYSxcbiAgICAgIDB4ZDZhMTAwYzYsIDB4NDAyYzcyNzksIDB4Njc5ZjI1ZmUsIDB4ZmIxZmEzY2MsIDB4OGVhNWU5ZjgsIDB4ZGIzMjIyZjgsXG4gICAgICAweDNjNzUxNmRmLCAweGZkNjE2YjE1LCAweDJmNTAxZWM4LCAweGFkMDU1MmFiLCAweDMyM2RiNWZhLCAweGZkMjM4NzYwLFxuICAgICAgMHg1MzMxN2I0OCwgMHgzZTAwZGY4MiwgMHg5ZTVjNTdiYiwgMHhjYTZmOGNhMCwgMHgxYTg3NTYyZSwgMHhkZjE3NjlkYixcbiAgICAgIDB4ZDU0MmE4ZjYsIDB4Mjg3ZWZmYzMsIDB4YWM2NzMyYzYsIDB4OGM0ZjU1NzMsIDB4Njk1YjI3YjAsIDB4YmJjYTU4YzgsXG4gICAgICAweGUxZmZhMzVkLCAweGI4ZjAxMWEwLCAweDEwZmEzZDk4LCAweGZkMjE4M2I4LCAweDRhZmNiNTZjLCAweDJkZDFkMzViLFxuICAgICAgMHg5YTUzZTQ3OSwgMHhiNmY4NDU2NSwgMHhkMjhlNDliYywgMHg0YmZiOTc5MCwgMHhlMWRkZjJkYSwgMHhhNGNiN2UzMyxcbiAgICAgIDB4NjJmYjEzNDEsIDB4Y2VlNGM2ZTgsIDB4ZWYyMGNhZGEsIDB4MzY3NzRjMDEsIDB4ZDA3ZTllZmUsIDB4MmJmMTFmYjQsXG4gICAgICAweDk1ZGJkYTRkLCAweGFlOTA5MTk4LCAweGVhYWQ4ZTcxLCAweDZiOTNkNWEwLCAweGQwOGVkMWQwLCAweGFmYzcyNWUwLFxuICAgICAgMHg4ZTNjNWIyZiwgMHg4ZTc1OTRiNywgMHg4ZmY2ZTJmYiwgMHhmMjEyMmI2NCwgMHg4ODg4YjgxMiwgMHg5MDBkZjAxYyxcbiAgICAgIDB4NGZhZDVlYTAsIDB4Njg4ZmMzMWMsIDB4ZDFjZmYxOTEsIDB4YjNhOGMxYWQsIDB4MmYyZjIyMTgsIDB4YmUwZTE3NzcsXG4gICAgICAweGVhNzUyZGZlLCAweDhiMDIxZmExLCAweGU1YTBjYzBmLCAweGI1NmY3NGU4LCAweDE4YWNmM2Q2LCAweGNlODllMjk5LFxuICAgICAgMHhiNGE4NGZlMCwgMHhmZDEzZTBiNywgMHg3Y2M0M2I4MSwgMHhkMmFkYThkOSwgMHgxNjVmYTI2NiwgMHg4MDk1NzcwNSxcbiAgICAgIDB4OTNjYzczMTQsIDB4MjExYTE0NzcsIDB4ZTZhZDIwNjUsIDB4NzdiNWZhODYsIDB4Yzc1NDQyZjUsIDB4ZmI5ZDM1Y2YsXG4gICAgICAweGViY2RhZjBjLCAweDdiM2U4OWEwLCAweGQ2NDExYmQzLCAweGFlMWU3ZTQ5LCAweDAwMjUwZTJkLCAweDIwNzFiMzVlLFxuICAgICAgMHgyMjY4MDBiYiwgMHg1N2I4ZTBhZiwgMHgyNDY0MzY5YiwgMHhmMDA5YjkxZSwgMHg1NTYzOTExZCwgMHg1OWRmYTZhYSxcbiAgICAgIDB4NzhjMTQzODksIDB4ZDk1YTUzN2YsIDB4MjA3ZDViYTIsIDB4MDJlNWI5YzUsIDB4ODMyNjAzNzYsIDB4NjI5NWNmYTksXG4gICAgICAweDExYzgxOTY4LCAweDRlNzM0YTQxLCAweGIzNDcyZGNhLCAweDdiMTRhOTRhLCAweDFiNTEwMDUyLCAweDlhNTMyOTE1LFxuICAgICAgMHhkNjBmNTczZiwgMHhiYzliYzZlNCwgMHgyYjYwYTQ3NiwgMHg4MWU2NzQwMCwgMHgwOGJhNmZiNSwgMHg1NzFiZTkxZixcbiAgICAgIDB4ZjI5NmVjNmIsIDB4MmEwZGQ5MTUsIDB4YjY2MzY1MjEsIDB4ZTdiOWY5YjYsIDB4ZmYzNDA1MmUsIDB4YzU4NTU2NjQsXG4gICAgICAweDUzYjAyZDVkLCAweGE5OWY4ZmExLCAweDA4YmE0Nzk5LCAweDZlODUwNzZhXG4gIF0sXG4gIFtcbiAgICAgIDB4NGI3YTcwZTksIDB4YjViMzI5NDQsIDB4ZGI3NTA5MmUsIDB4YzQxOTI2MjMsIDB4YWQ2ZWE2YjAsIDB4NDlhN2RmN2QsXG4gICAgICAweDljZWU2MGI4LCAweDhmZWRiMjY2LCAweGVjYWE4YzcxLCAweDY5OWExN2ZmLCAweDU2NjQ1MjZjLCAweGMyYjE5ZWUxLFxuICAgICAgMHgxOTM2MDJhNSwgMHg3NTA5NGMyOSwgMHhhMDU5MTM0MCwgMHhlNDE4M2EzZSwgMHgzZjU0OTg5YSwgMHg1YjQyOWQ2NSxcbiAgICAgIDB4NmI4ZmU0ZDYsIDB4OTlmNzNmZDYsIDB4YTFkMjljMDcsIDB4ZWZlODMwZjUsIDB4NGQyZDM4ZTYsIDB4ZjAyNTVkYzEsXG4gICAgICAweDRjZGQyMDg2LCAweDg0NzBlYjI2LCAweDYzODJlOWM2LCAweDAyMWVjYzVlLCAweDA5Njg2YjNmLCAweDNlYmFlZmM5LFxuICAgICAgMHgzYzk3MTgxNCwgMHg2YjZhNzBhMSwgMHg2ODdmMzU4NCwgMHg1MmEwZTI4NiwgMHhiNzljNTMwNSwgMHhhYTUwMDczNyxcbiAgICAgIDB4M2UwNzg0MWMsIDB4N2ZkZWFlNWMsIDB4OGU3ZDQ0ZWMsIDB4NTcxNmYyYjgsIDB4YjAzYWRhMzcsIDB4ZjA1MDBjMGQsXG4gICAgICAweGYwMWMxZjA0LCAweDAyMDBiM2ZmLCAweGFlMGNmNTFhLCAweDNjYjU3NGIyLCAweDI1ODM3YTU4LCAweGRjMDkyMWJkLFxuICAgICAgMHhkMTkxMTNmOSwgMHg3Y2E5MmZmNiwgMHg5NDMyNDc3MywgMHgyMmY1NDcwMSwgMHgzYWU1ZTU4MSwgMHgzN2MyZGFkYyxcbiAgICAgIDB4YzhiNTc2MzQsIDB4OWFmM2RkYTcsIDB4YTk0NDYxNDYsIDB4MGZkMDAzMGUsIDB4ZWNjOGM3M2UsIDB4YTQ3NTFlNDEsXG4gICAgICAweGUyMzhjZDk5LCAweDNiZWEwZTJmLCAweDMyODBiYmExLCAweDE4M2ViMzMxLCAweDRlNTQ4YjM4LCAweDRmNmRiOTA4LFxuICAgICAgMHg2ZjQyMGQwMywgMHhmNjBhMDRiZiwgMHgyY2I4MTI5MCwgMHgyNDk3N2M3OSwgMHg1Njc5YjA3MiwgMHhiY2FmODlhZixcbiAgICAgIDB4ZGU5YTc3MWYsIDB4ZDk5MzA4MTAsIDB4YjM4YmFlMTIsIDB4ZGNjZjNmMmUsIDB4NTUxMjcyMWYsIDB4MmU2YjcxMjQsXG4gICAgICAweDUwMWFkZGU2LCAweDlmODRjZDg3LCAweDdhNTg0NzE4LCAweDc0MDhkYTE3LCAweGJjOWY5YWJjLCAweGU5NGI3ZDhjLFxuICAgICAgMHhlYzdhZWMzYSwgMHhkYjg1MWRmYSwgMHg2MzA5NDM2NiwgMHhjNDY0YzNkMiwgMHhlZjFjMTg0NywgMHgzMjE1ZDkwOCxcbiAgICAgIDB4ZGQ0MzNiMzcsIDB4MjRjMmJhMTYsIDB4MTJhMTRkNDMsIDB4MmE2NWM0NTEsIDB4NTA5NDAwMDIsIDB4MTMzYWU0ZGQsXG4gICAgICAweDcxZGZmODllLCAweDEwMzE0ZTU1LCAweDgxYWM3N2Q2LCAweDVmMTExOTliLCAweDA0MzU1NmYxLCAweGQ3YTNjNzZiLFxuICAgICAgMHgzYzExMTgzYiwgMHg1OTI0YTUwOSwgMHhmMjhmZTZlZCwgMHg5N2YxZmJmYSwgMHg5ZWJhYmYyYywgMHgxZTE1M2M2ZSxcbiAgICAgIDB4ODZlMzQ1NzAsIDB4ZWFlOTZmYjEsIDB4ODYwZTVlMGEsIDB4NWEzZTJhYjMsIDB4NzcxZmU3MWMsIDB4NGUzZDA2ZmEsXG4gICAgICAweDI5NjVkY2I5LCAweDk5ZTcxZDBmLCAweDgwM2U4OWQ2LCAweDUyNjZjODI1LCAweDJlNGNjOTc4LCAweDljMTBiMzZhLFxuICAgICAgMHhjNjE1MGViYSwgMHg5NGUyZWE3OCwgMHhhNWZjM2M1MywgMHgxZTBhMmRmNCwgMHhmMmY3NGVhNywgMHgzNjFkMmIzZCxcbiAgICAgIDB4MTkzOTI2MGYsIDB4MTljMjc5NjAsIDB4NTIyM2E3MDgsIDB4ZjcxMzEyYjYsIDB4ZWJhZGZlNmUsIDB4ZWFjMzFmNjYsXG4gICAgICAweGUzYmM0NTk1LCAweGE2N2JjODgzLCAweGIxN2YzN2QxLCAweDAxOGNmZjI4LCAweGMzMzJkZGVmLCAweGJlNmM1YWE1LFxuICAgICAgMHg2NTU4MjE4NSwgMHg2OGFiOTgwMiwgMHhlZWNlYTUwZiwgMHhkYjJmOTUzYiwgMHgyYWVmN2RhZCwgMHg1YjZlMmY4NCxcbiAgICAgIDB4MTUyMWI2MjgsIDB4MjkwNzYxNzAsIDB4ZWNkZDQ3NzUsIDB4NjE5ZjE1MTAsIDB4MTNjY2E4MzAsIDB4ZWI2MWJkOTYsXG4gICAgICAweDAzMzRmZTFlLCAweGFhMDM2M2NmLCAweGI1NzM1YzkwLCAweDRjNzBhMjM5LCAweGQ1OWU5ZTBiLCAweGNiYWFkZTE0LFxuICAgICAgMHhlZWNjODZiYywgMHg2MDYyMmNhNywgMHg5Y2FiNWNhYiwgMHhiMmYzODQ2ZSwgMHg2NDhiMWVhZiwgMHgxOWJkZjBjYSxcbiAgICAgIDB4YTAyMzY5YjksIDB4NjU1YWJiNTAsIDB4NDA2ODVhMzIsIDB4M2MyYWI0YjMsIDB4MzE5ZWU5ZDUsIDB4YzAyMWI4ZjcsXG4gICAgICAweDliNTQwYjE5LCAweDg3NWZhMDk5LCAweDk1Zjc5OTdlLCAweDYyM2Q3ZGE4LCAweGY4Mzc4ODlhLCAweDk3ZTMyZDc3LFxuICAgICAgMHgxMWVkOTM1ZiwgMHgxNjY4MTI4MSwgMHgwZTM1ODgyOSwgMHhjN2U2MWZkNiwgMHg5NmRlZGZhMSwgMHg3ODU4YmE5OSxcbiAgICAgIDB4NTdmNTg0YTUsIDB4MWIyMjcyNjMsIDB4OWI4M2MzZmYsIDB4MWFjMjQ2OTYsIDB4Y2RiMzBhZWIsIDB4NTMyZTMwNTQsXG4gICAgICAweDhmZDk0OGU0LCAweDZkYmMzMTI4LCAweDU4ZWJmMmVmLCAweDM0YzZmZmVhLCAweGZlMjhlZDYxLCAweGVlN2MzYzczLFxuICAgICAgMHg1ZDRhMTRkOSwgMHhlODY0YjdlMywgMHg0MjEwNWQxNCwgMHgyMDNlMTNlMCwgMHg0NWVlZTJiNiwgMHhhM2FhYWJlYSxcbiAgICAgIDB4ZGI2YzRmMTUsIDB4ZmFjYjRmZDAsIDB4Yzc0MmY0NDIsIDB4ZWY2YWJiYjUsIDB4NjU0ZjNiMWQsIDB4NDFjZDIxMDUsXG4gICAgICAweGQ4MWU3OTllLCAweDg2ODU0ZGM3LCAweGU0NGI0NzZhLCAweDNkODE2MjUwLCAweGNmNjJhMWYyLCAweDViOGQyNjQ2LFxuICAgICAgMHhmYzg4ODNhMCwgMHhjMWM3YjZhMywgMHg3ZjE1MjRjMywgMHg2OWNiNzQ5MiwgMHg0Nzg0OGEwYiwgMHg1NjkyYjI4NSxcbiAgICAgIDB4MDk1YmJmMDAsIDB4YWQxOTQ4OWQsIDB4MTQ2MmIxNzQsIDB4MjM4MjBlMDAsIDB4NTg0MjhkMmEsIDB4MGM1NWY1ZWEsXG4gICAgICAweDFkYWRmNDNlLCAweDIzM2Y3MDYxLCAweDMzNzJmMDkyLCAweDhkOTM3ZTQxLCAweGQ2NWZlY2YxLCAweDZjMjIzYmRiLFxuICAgICAgMHg3Y2RlMzc1OSwgMHhjYmVlNzQ2MCwgMHg0MDg1ZjJhNywgMHhjZTc3MzI2ZSwgMHhhNjA3ODA4NCwgMHgxOWY4NTA5ZSxcbiAgICAgIDB4ZThlZmQ4NTUsIDB4NjFkOTk3MzUsIDB4YTk2OWE3YWEsIDB4YzUwYzA2YzIsIDB4NWEwNGFiZmMsIDB4ODAwYmNhZGMsXG4gICAgICAweDllNDQ3YTJlLCAweGMzNDUzNDg0LCAweGZkZDU2NzA1LCAweDBlMWU5ZWM5LCAweGRiNzNkYmQzLCAweDEwNTU4OGNkLFxuICAgICAgMHg2NzVmZGE3OSwgMHhlMzY3NDM0MCwgMHhjNWM0MzQ2NSwgMHg3MTNlMzhkOCwgMHgzZDI4Zjg5ZSwgMHhmMTZkZmYyMCxcbiAgICAgIDB4MTUzZTIxZTcsIDB4OGZiMDNkNGEsIDB4ZTZlMzlmMmIsIDB4ZGI4M2FkZjdcbiAgXSxcbiAgW1xuICAgICAgMHhlOTNkNWE2OCwgMHg5NDgxNDBmNywgMHhmNjRjMjYxYywgMHg5NDY5MjkzNCwgMHg0MTE1MjBmNywgMHg3NjAyZDRmNyxcbiAgICAgIDB4YmNmNDZiMmUsIDB4ZDRhMjAwNjgsIDB4ZDQwODI0NzEsIDB4MzMyMGY0NmEsIDB4NDNiN2Q0YjcsIDB4NTAwMDYxYWYsXG4gICAgICAweDFlMzlmNjJlLCAweDk3MjQ0NTQ2LCAweDE0MjE0Zjc0LCAweGJmOGI4ODQwLCAweDRkOTVmYzFkLCAweDk2YjU5MWFmLFxuICAgICAgMHg3MGY0ZGRkMywgMHg2NmEwMmY0NSwgMHhiZmJjMDllYywgMHgwM2JkOTc4NSwgMHg3ZmFjNmRkMCwgMHgzMWNiODUwNCxcbiAgICAgIDB4OTZlYjI3YjMsIDB4NTVmZDM5NDEsIDB4ZGEyNTQ3ZTYsIDB4YWJjYTBhOWEsIDB4Mjg1MDc4MjUsIDB4NTMwNDI5ZjQsXG4gICAgICAweDBhMmM4NmRhLCAweGU5YjY2ZGZiLCAweDY4ZGMxNDYyLCAweGQ3NDg2OTAwLCAweDY4MGVjMGE0LCAweDI3YTE4ZGVlLFxuICAgICAgMHg0ZjNmZmVhMiwgMHhlODg3YWQ4YywgMHhiNThjZTAwNiwgMHg3YWY0ZDZiNiwgMHhhYWNlMWU3YywgMHhkMzM3NWZlYyxcbiAgICAgIDB4Y2U3OGEzOTksIDB4NDA2YjJhNDIsIDB4MjBmZTllMzUsIDB4ZDlmMzg1YjksIDB4ZWUzOWQ3YWIsIDB4M2IxMjRlOGIsXG4gICAgICAweDFkYzlmYWY3LCAweDRiNmQxODU2LCAweDI2YTM2NjMxLCAweGVhZTM5N2IyLCAweDNhNmVmYTc0LCAweGRkNWI0MzMyLFxuICAgICAgMHg2ODQxZTdmNywgMHhjYTc4MjBmYiwgMHhmYjBhZjU0ZSwgMHhkOGZlYjM5NywgMHg0NTQwNTZhYywgMHhiYTQ4OTUyNyxcbiAgICAgIDB4NTU1MzNhM2EsIDB4MjA4MzhkODcsIDB4ZmU2YmE5YjcsIDB4ZDA5Njk1NGIsIDB4NTVhODY3YmMsIDB4YTExNTlhNTgsXG4gICAgICAweGNjYTkyOTYzLCAweDk5ZTFkYjMzLCAweGE2MmE0YTU2LCAweDNmMzEyNWY5LCAweDVlZjQ3ZTFjLCAweDkwMjkzMTdjLFxuICAgICAgMHhmZGY4ZTgwMiwgMHgwNDI3MmY3MCwgMHg4MGJiMTU1YywgMHgwNTI4MmNlMywgMHg5NWMxMTU0OCwgMHhlNGM2NmQyMixcbiAgICAgIDB4NDhjMTEzM2YsIDB4YzcwZjg2ZGMsIDB4MDdmOWM5ZWUsIDB4NDEwNDFmMGYsIDB4NDA0Nzc5YTQsIDB4NWQ4ODZlMTcsXG4gICAgICAweDMyNWY1MWViLCAweGQ1OWJjMGQxLCAweGYyYmNjMThmLCAweDQxMTEzNTY0LCAweDI1N2I3ODM0LCAweDYwMmE5YzYwLFxuICAgICAgMHhkZmY4ZThhMywgMHgxZjYzNmMxYiwgMHgwZTEyYjRjMiwgMHgwMmUxMzI5ZSwgMHhhZjY2NGZkMSwgMHhjYWQxODExNSxcbiAgICAgIDB4NmIyMzk1ZTAsIDB4MzMzZTkyZTEsIDB4M2IyNDBiNjIsIDB4ZWViZWI5MjIsIDB4ODViMmEyMGUsIDB4ZTZiYTBkOTksXG4gICAgICAweGRlNzIwYzhjLCAweDJkYTJmNzI4LCAweGQwMTI3ODQ1LCAweDk1Yjc5NGZkLCAweDY0N2QwODYyLCAweGU3Y2NmNWYwLFxuICAgICAgMHg1NDQ5YTM2ZiwgMHg4NzdkNDhmYSwgMHhjMzlkZmQyNywgMHhmMzNlOGQxZSwgMHgwYTQ3NjM0MSwgMHg5OTJlZmY3NCxcbiAgICAgIDB4M2E2ZjZlYWIsIDB4ZjRmOGZkMzcsIDB4YTgxMmRjNjAsIDB4YTFlYmRkZjgsIDB4OTkxYmUxNGMsIDB4ZGI2ZTZiMGQsXG4gICAgICAweGM2N2I1NTEwLCAweDZkNjcyYzM3LCAweDI3NjVkNDNiLCAweGRjZDBlODA0LCAweGYxMjkwZGM3LCAweGNjMDBmZmEzLFxuICAgICAgMHhiNTM5MGY5MiwgMHg2OTBmZWQwYiwgMHg2NjdiOWZmYiwgMHhjZWRiN2Q5YywgMHhhMDkxY2YwYiwgMHhkOTE1NWVhMyxcbiAgICAgIDB4YmIxMzJmODgsIDB4NTE1YmFkMjQsIDB4N2I5NDc5YmYsIDB4NzYzYmQ2ZWIsIDB4MzczOTJlYjMsIDB4Y2MxMTU5NzksXG4gICAgICAweDgwMjZlMjk3LCAweGY0MmUzMTJkLCAweDY4NDJhZGE3LCAweGM2NmEyYjNiLCAweDEyNzU0Y2NjLCAweDc4MmVmMTFjLFxuICAgICAgMHg2YTEyNDIzNywgMHhiNzkyNTFlNywgMHgwNmExYmJlNiwgMHg0YmZiNjM1MCwgMHgxYTZiMTAxOCwgMHgxMWNhZWRmYSxcbiAgICAgIDB4M2QyNWJkZDgsIDB4ZTJlMWMzYzksIDB4NDQ0MjE2NTksIDB4MGExMjEzODYsIDB4ZDkwY2VjNmUsIDB4ZDVhYmVhMmEsXG4gICAgICAweDY0YWY2NzRlLCAweGRhODZhODVmLCAweGJlYmZlOTg4LCAweDY0ZTRjM2ZlLCAweDlkYmM4MDU3LCAweGYwZjdjMDg2LFxuICAgICAgMHg2MDc4N2JmOCwgMHg2MDAzNjA0ZCwgMHhkMWZkODM0NiwgMHhmNjM4MWZiMCwgMHg3NzQ1YWUwNCwgMHhkNzM2ZmNjYyxcbiAgICAgIDB4ODM0MjZiMzMsIDB4ZjAxZWFiNzEsIDB4YjA4MDQxODcsIDB4M2MwMDVlNWYsIDB4NzdhMDU3YmUsIDB4YmRlOGFlMjQsXG4gICAgICAweDU1NDY0Mjk5LCAweGJmNTgyZTYxLCAweDRlNThmNDhmLCAweGYyZGRmZGEyLCAweGY0NzRlZjM4LCAweDg3ODliZGMyLFxuICAgICAgMHg1MzY2ZjljMywgMHhjOGIzOGU3NCwgMHhiNDc1ZjI1NSwgMHg0NmZjZDliOSwgMHg3YWViMjY2MSwgMHg4YjFkZGY4NCxcbiAgICAgIDB4ODQ2YTBlNzksIDB4OTE1Zjk1ZTIsIDB4NDY2ZTU5OGUsIDB4MjBiNDU3NzAsIDB4OGNkNTU1OTEsIDB4YzkwMmRlNGMsXG4gICAgICAweGI5MGJhY2UxLCAweGJiODIwNWQwLCAweDExYTg2MjQ4LCAweDc1NzRhOTllLCAweGI3N2YxOWI2LCAweGUwYTlkYzA5LFxuICAgICAgMHg2NjJkMDlhMSwgMHhjNDMyNDYzMywgMHhlODVhMWYwMiwgMHgwOWYwYmU4YywgMHg0YTk5YTAyNSwgMHgxZDZlZmUxMCxcbiAgICAgIDB4MWFiOTNkMWQsIDB4MGJhNWE0ZGYsIDB4YTE4NmYyMGYsIDB4Mjg2OGYxNjksIDB4ZGNiN2RhODMsIDB4NTczOTA2ZmUsXG4gICAgICAweGExZTJjZTliLCAweDRmY2Q3ZjUyLCAweDUwMTE1ZTAxLCAweGE3MDY4M2ZhLCAweGEwMDJiNWM0LCAweDBkZTZkMDI3LFxuICAgICAgMHg5YWY4OGMyNywgMHg3NzNmODY0MSwgMHhjMzYwNGMwNiwgMHg2MWE4MDZiNSwgMHhmMDE3N2EyOCwgMHhjMGY1ODZlMCxcbiAgICAgIDB4MDA2MDU4YWEsIDB4MzBkYzdkNjIsIDB4MTFlNjllZDcsIDB4MjMzOGVhNjMsIDB4NTNjMmRkOTQsIDB4YzJjMjE2MzQsXG4gICAgICAweGJiY2JlZTU2LCAweDkwYmNiNmRlLCAweGViZmM3ZGExLCAweGNlNTkxZDc2LCAweDZmMDVlNDA5LCAweDRiN2MwMTg4LFxuICAgICAgMHgzOTcyMGEzZCwgMHg3YzkyN2MyNCwgMHg4NmUzNzI1ZiwgMHg3MjRkOWRiOSwgMHgxYWMxNWJiNCwgMHhkMzllYjhmYyxcbiAgICAgIDB4ZWQ1NDU1NzgsIDB4MDhmY2E1YjUsIDB4ZDgzZDdjZDMsIDB4NGRhZDBmYzQsIDB4MWU1MGVmNWUsIDB4YjE2MWU2ZjgsXG4gICAgICAweGEyODUxNGQ5LCAweDZjNTExMzNjLCAweDZmZDVjN2U3LCAweDU2ZTE0ZWM0LCAweDM2MmFiZmNlLCAweGRkYzZjODM3LFxuICAgICAgMHhkNzlhMzIzNCwgMHg5MjYzODIxMiwgMHg2NzBlZmE4ZSwgMHg0MDYwMDBlMFxuICBdLFxuICBbXG4gICAgICAweDNhMzljZTM3LCAweGQzZmFmNWNmLCAweGFiYzI3NzM3LCAweDVhYzUyZDFiLCAweDVjYjA2NzllLCAweDRmYTMzNzQyLFxuICAgICAgMHhkMzgyMjc0MCwgMHg5OWJjOWJiZSwgMHhkNTExOGU5ZCwgMHhiZjBmNzMxNSwgMHhkNjJkMWM3ZSwgMHhjNzAwYzQ3YixcbiAgICAgIDB4Yjc4YzFiNmIsIDB4MjFhMTkwNDUsIDB4YjI2ZWIxYmUsIDB4NmEzNjZlYjQsIDB4NTc0OGFiMmYsIDB4YmM5NDZlNzksXG4gICAgICAweGM2YTM3NmQyLCAweDY1NDljMmM4LCAweDUzMGZmOGVlLCAweDQ2OGRkZTdkLCAweGQ1NzMwYTFkLCAweDRjZDA0ZGM2LFxuICAgICAgMHgyOTM5YmJkYiwgMHhhOWJhNDY1MCwgMHhhYzk1MjZlOCwgMHhiZTVlZTMwNCwgMHhhMWZhZDVmMCwgMHg2YTJkNTE5YSxcbiAgICAgIDB4NjNlZjhjZTIsIDB4OWE4NmVlMjIsIDB4YzA4OWMyYjgsIDB4NDMyNDJlZjYsIDB4YTUxZTAzYWEsIDB4OWNmMmQwYTQsXG4gICAgICAweDgzYzA2MWJhLCAweDliZTk2YTRkLCAweDhmZTUxNTUwLCAweGJhNjQ1YmQ2LCAweDI4MjZhMmY5LCAweGE3M2EzYWUxLFxuICAgICAgMHg0YmE5OTU4NiwgMHhlZjU1NjJlOSwgMHhjNzJmZWZkMywgMHhmNzUyZjdkYSwgMHgzZjA0NmY2OSwgMHg3N2ZhMGE1OSxcbiAgICAgIDB4ODBlNGE5MTUsIDB4ODdiMDg2MDEsIDB4OWIwOWU2YWQsIDB4M2IzZWU1OTMsIDB4ZTk5MGZkNWEsIDB4OWUzNGQ3OTcsXG4gICAgICAweDJjZjBiN2Q5LCAweDAyMmI4YjUxLCAweDk2ZDVhYzNhLCAweDAxN2RhNjdkLCAweGQxY2YzZWQ2LCAweDdjN2QyZDI4LFxuICAgICAgMHgxZjlmMjVjZiwgMHhhZGYyYjg5YiwgMHg1YWQ2YjQ3MiwgMHg1YTg4ZjU0YywgMHhlMDI5YWM3MSwgMHhlMDE5YTVlNixcbiAgICAgIDB4NDdiMGFjZmQsIDB4ZWQ5M2ZhOWIsIDB4ZThkM2M0OGQsIDB4MjgzYjU3Y2MsIDB4ZjhkNTY2MjksIDB4NzkxMzJlMjgsXG4gICAgICAweDc4NWYwMTkxLCAweGVkNzU2MDU1LCAweGY3OTYwZTQ0LCAweGUzZDM1ZThjLCAweDE1MDU2ZGQ0LCAweDg4ZjQ2ZGJhLFxuICAgICAgMHgwM2ExNjEyNSwgMHgwNTY0ZjBiZCwgMHhjM2ViOWUxNSwgMHgzYzkwNTdhMiwgMHg5NzI3MWFlYywgMHhhOTNhMDcyYSxcbiAgICAgIDB4MWIzZjZkOWIsIDB4MWU2MzIxZjUsIDB4ZjU5YzY2ZmIsIDB4MjZkY2YzMTksIDB4NzUzM2Q5MjgsIDB4YjE1NWZkZjUsXG4gICAgICAweDAzNTYzNDgyLCAweDhhYmEzY2JiLCAweDI4NTE3NzExLCAweGMyMGFkOWY4LCAweGFiY2M1MTY3LCAweGNjYWQ5MjVmLFxuICAgICAgMHg0ZGU4MTc1MSwgMHgzODMwZGM4ZSwgMHgzNzlkNTg2MiwgMHg5MzIwZjk5MSwgMHhlYTdhOTBjMiwgMHhmYjNlN2JjZSxcbiAgICAgIDB4NTEyMWNlNjQsIDB4Nzc0ZmJlMzIsIDB4YThiNmUzN2UsIDB4YzMyOTNkNDYsIDB4NDhkZTUzNjksIDB4NjQxM2U2ODAsXG4gICAgICAweGEyYWUwODEwLCAweGRkNmRiMjI0LCAweDY5ODUyZGZkLCAweDA5MDcyMTY2LCAweGIzOWE0NjBhLCAweDY0NDVjMGRkLFxuICAgICAgMHg1ODZjZGVjZiwgMHgxYzIwYzhhZSwgMHg1YmJlZjdkZCwgMHgxYjU4OGQ0MCwgMHhjY2QyMDE3ZiwgMHg2YmI0ZTNiYixcbiAgICAgIDB4ZGRhMjZhN2UsIDB4M2E1OWZmNDUsIDB4M2UzNTBhNDQsIDB4YmNiNGNkZDUsIDB4NzJlYWNlYTgsIDB4ZmE2NDg0YmIsXG4gICAgICAweDhkNjYxMmFlLCAweGJmM2M2ZjQ3LCAweGQyOWJlNDYzLCAweDU0MmY1ZDllLCAweGFlYzI3NzFiLCAweGY2NGU2MzcwLFxuICAgICAgMHg3NDBlMGQ4ZCwgMHhlNzViMTM1NywgMHhmODcyMTY3MSwgMHhhZjUzN2Q1ZCwgMHg0MDQwY2IwOCwgMHg0ZWI0ZTJjYyxcbiAgICAgIDB4MzRkMjQ2NmEsIDB4MDExNWFmODQsIDB4ZTFiMDA0MjgsIDB4OTU5ODNhMWQsIDB4MDZiODlmYjQsIDB4Y2U2ZWEwNDgsXG4gICAgICAweDZmM2YzYjgyLCAweDM1MjBhYjgyLCAweDAxMWExZDRiLCAweDI3NzIyN2Y4LCAweDYxMTU2MGIxLCAweGU3OTMzZmRjLFxuICAgICAgMHhiYjNhNzkyYiwgMHgzNDQ1MjViZCwgMHhhMDg4MzllMSwgMHg1MWNlNzk0YiwgMHgyZjMyYzliNywgMHhhMDFmYmFjOSxcbiAgICAgIDB4ZTAxY2M4N2UsIDB4YmNjN2QxZjYsIDB4Y2YwMTExYzMsIDB4YTFlOGFhYzcsIDB4MWE5MDg3NDksIDB4ZDQ0ZmJkOWEsXG4gICAgICAweGQwZGFkZWNiLCAweGQ1MGFkYTM4LCAweDAzMzljMzJhLCAweGM2OTEzNjY3LCAweDhkZjkzMTdjLCAweGUwYjEyYjRmLFxuICAgICAgMHhmNzllNTliNywgMHg0M2Y1YmIzYSwgMHhmMmQ1MTlmZiwgMHgyN2Q5NDU5YywgMHhiZjk3MjIyYywgMHgxNWU2ZmMyYSxcbiAgICAgIDB4MGY5MWZjNzEsIDB4OWI5NDE1MjUsIDB4ZmFlNTkzNjEsIDB4Y2ViNjljZWIsIDB4YzJhODY0NTksIDB4MTJiYWE4ZDEsXG4gICAgICAweGI2YzEwNzVlLCAweGUzMDU2YTBjLCAweDEwZDI1MDY1LCAweGNiMDNhNDQyLCAweGUwZWM2ZTBlLCAweDE2OThkYjNiLFxuICAgICAgMHg0Yzk4YTBiZSwgMHgzMjc4ZTk2NCwgMHg5ZjFmOTUzMiwgMHhlMGQzOTJkZiwgMHhkM2EwMzQyYiwgMHg4OTcxZjIxZSxcbiAgICAgIDB4MWIwYTc0NDEsIDB4NGJhMzM0OGMsIDB4YzViZTcxMjAsIDB4YzM3NjMyZDgsIDB4ZGYzNTlmOGQsIDB4OWI5OTJmMmUsXG4gICAgICAweGU2MGI2ZjQ3LCAweDBmZTNmMTFkLCAweGU1NGNkYTU0LCAweDFlZGFkODkxLCAweGNlNjI3OWNmLCAweGNkM2U3ZTZmLFxuICAgICAgMHgxNjE4YjE2NiwgMHhmZDJjMWQwNSwgMHg4NDhmZDJjNSwgMHhmNmZiMjI5OSwgMHhmNTIzZjM1NywgMHhhNjMyNzYyMyxcbiAgICAgIDB4OTNhODM1MzEsIDB4NTZjY2NkMDIsIDB4YWNmMDgxNjIsIDB4NWE3NWViYjUsIDB4NmUxNjM2OTcsIDB4ODhkMjczY2MsXG4gICAgICAweGRlOTY2MjkyLCAweDgxYjk0OWQwLCAweDRjNTA5MDFiLCAweDcxYzY1NjE0LCAweGU2YzZjN2JkLCAweDMyN2ExNDBhLFxuICAgICAgMHg0NWUxZDAwNiwgMHhjM2YyN2I5YSwgMHhjOWFhNTNmZCwgMHg2MmE4MGYwMCwgMHhiYjI1YmZlMiwgMHgzNWJkZDJmNixcbiAgICAgIDB4NzExMjY5MDUsIDB4YjIwNDAyMjIsIDB4YjZjYmNmN2MsIDB4Y2Q3NjljMmIsIDB4NTMxMTNlYzAsIDB4MTY0MGUzZDMsXG4gICAgICAweDM4YWJiZDYwLCAweDI1NDdhZGYwLCAweGJhMzgyMDljLCAweGY3NDZjZTc2LCAweDc3YWZhMWM1LCAweDIwNzU2MDYwLFxuICAgICAgMHg4NWNiZmU0ZSwgMHg4YWU4OGRkOCwgMHg3YWFhZjliMCwgMHg0Y2Y5YWE3ZSwgMHgxOTQ4YzI1YywgMHgwMmZiOGE4YyxcbiAgICAgIDB4MDFjMzZhZTQsIDB4ZDZlYmUxZjksIDB4OTBkNGY4NjksIDB4YTY1Y2RlYTAsIDB4M2YwOTI1MmQsIDB4YzIwOGU2OWYsXG4gICAgICAweGI3NGU2MTMyLCAweGNlNzdlMjViLCAweDU3OGZkZmUzLCAweDNhYzM3MmU2XG4gIF1cbl07XG5cbi8vKlxuLy8qIFRoaXMgaXMgdGhlIGRlZmF1bHQgUEFSUkFZXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5QQVJSQVkgPSBbXG4gICAgMHgyNDNmNmE4OCwgMHg4NWEzMDhkMywgMHgxMzE5OGEyZSwgMHgwMzcwNzM0NCwgMHhhNDA5MzgyMiwgMHgyOTlmMzFkMCxcbiAgICAweDA4MmVmYTk4LCAweGVjNGU2Yzg5LCAweDQ1MjgyMWU2LCAweDM4ZDAxMzc3LCAweGJlNTQ2NmNmLCAweDM0ZTkwYzZjLFxuICAgIDB4YzBhYzI5YjcsIDB4Yzk3YzUwZGQsIDB4M2Y4NGQ1YjUsIDB4YjU0NzA5MTcsIDB4OTIxNmQ1ZDksIDB4ODk3OWZiMWJcbl07XG5cbi8vKlxuLy8qIFRoaXMgaXMgdGhlIG51bWJlciBvZiByb3VuZHMgdGhlIGNpcGhlciB3aWxsIGdvXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5OTiA9IDE2O1xuXG4vLypcbi8vKiBUaGlzIGZ1bmN0aW9uIGlzIG5lZWRlZCB0byBnZXQgcmlkIG9mIHByb2JsZW1zXG4vLyogd2l0aCB0aGUgaGlnaC1iaXQgZ2V0dGluZyBzZXQuICBJZiB3ZSBkb24ndCBkb1xuLy8qIHRoaXMsIHRoZW4gc29tZXRpbWVzICggYWEgJiAweDAwRkZGRkZGRkYgKSBpcyBub3Rcbi8vKiBlcXVhbCB0byAoIGJiICYgMHgwMEZGRkZGRkZGICkgZXZlbiB3aGVuIHRoZXlcbi8vKiBhZ3JlZSBiaXQtZm9yLWJpdCBmb3IgdGhlIGZpcnN0IDMyIGJpdHMuXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5fY2xlYW4gPSBmdW5jdGlvbih4eCkge1xuICBpZiAoeHggPCAwKSB7XG4gICAgdmFyIHl5ID0geHggJiAweDdGRkZGRkZGO1xuICAgIHh4ID0geXkgKyAweDgwMDAwMDAwO1xuICB9XG4gIHJldHVybiB4eDtcbn07XG5cbi8vKlxuLy8qIFRoaXMgaXMgdGhlIG1peGluZyBmdW5jdGlvbiB0aGF0IHVzZXMgdGhlIHNib3hlc1xuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuX0YgPSBmdW5jdGlvbih4eCkge1xuICB2YXIgYWE7XG4gIHZhciBiYjtcbiAgdmFyIGNjO1xuICB2YXIgZGQ7XG4gIHZhciB5eTtcblxuICBkZCA9IHh4ICYgMHgwMEZGO1xuICB4eCA+Pj49IDg7XG4gIGNjID0geHggJiAweDAwRkY7XG4gIHh4ID4+Pj0gODtcbiAgYmIgPSB4eCAmIDB4MDBGRjtcbiAgeHggPj4+PSA4O1xuICBhYSA9IHh4ICYgMHgwMEZGO1xuXG4gIHl5ID0gdGhpcy5zYm94ZXNbMF1bYWFdICsgdGhpcy5zYm94ZXNbMV1bYmJdO1xuICB5eSA9IHl5IF4gdGhpcy5zYm94ZXNbMl1bY2NdO1xuICB5eSA9IHl5ICsgdGhpcy5zYm94ZXNbM11bZGRdO1xuXG4gIHJldHVybiB5eTtcbn07XG5cbi8vKlxuLy8qIFRoaXMgbWV0aG9kIHRha2VzIGFuIGFycmF5IHdpdGggdHdvIHZhbHVlcywgbGVmdCBhbmQgcmlnaHRcbi8vKiBhbmQgZG9lcyBOTiByb3VuZHMgb2YgQmxvd2Zpc2ggb24gdGhlbS5cbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLl9lbmNyeXB0X2Jsb2NrID0gZnVuY3Rpb24odmFscykge1xuICB2YXIgZGF0YUwgPSB2YWxzWzBdO1xuICB2YXIgZGF0YVIgPSB2YWxzWzFdO1xuXG4gIHZhciBpaTtcblxuICBmb3IgKGlpID0gMDsgaWkgPCB0aGlzLk5OOyArK2lpKSB7XG4gICAgZGF0YUwgPSBkYXRhTCBeIHRoaXMucGFycmF5W2lpXTtcbiAgICBkYXRhUiA9IHRoaXMuX0YoZGF0YUwpIF4gZGF0YVI7XG5cbiAgICB2YXIgdG1wID0gZGF0YUw7XG4gICAgZGF0YUwgPSBkYXRhUjtcbiAgICBkYXRhUiA9IHRtcDtcbiAgfVxuXG4gIGRhdGFMID0gZGF0YUwgXiB0aGlzLnBhcnJheVt0aGlzLk5OICsgMF07XG4gIGRhdGFSID0gZGF0YVIgXiB0aGlzLnBhcnJheVt0aGlzLk5OICsgMV07XG5cbiAgdmFsc1swXSA9IHRoaXMuX2NsZWFuKGRhdGFSKTtcbiAgdmFsc1sxXSA9IHRoaXMuX2NsZWFuKGRhdGFMKTtcbn07XG5cbi8vKlxuLy8qIFRoaXMgbWV0aG9kIHRha2VzIGEgdmVjdG9yIG9mIG51bWJlcnMgYW5kIHR1cm5zIHRoZW1cbi8vKiBpbnRvIGxvbmcgd29yZHMgc28gdGhhdCB0aGV5IGNhbiBiZSBwcm9jZXNzZWQgYnkgdGhlXG4vLyogcmVhbCBhbGdvcml0aG0uXG4vLypcbi8vKiBNYXliZSBJIHNob3VsZCBtYWtlIHRoZSByZWFsIGFsZ29yaXRobSBhYm92ZSB0YWtlIGEgdmVjdG9yXG4vLyogaW5zdGVhZC4gIFRoYXQgd2lsbCBpbnZvbHZlIG1vcmUgbG9vcGluZywgYnV0IGl0IHdvbid0IHJlcXVpcmVcbi8vKiB0aGUgRigpIG1ldGhvZCB0byBkZWNvbnN0cnVjdCB0aGUgdmVjdG9yLlxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuZW5jcnlwdF9ibG9jayA9IGZ1bmN0aW9uKHZlY3Rvcikge1xuICB2YXIgaWk7XG4gIHZhciB2YWxzID0gWzAsIDBdO1xuICB2YXIgb2ZmID0gdGhpcy5CTE9DS1NJWkUgLyAyO1xuICBmb3IgKGlpID0gMDsgaWkgPCB0aGlzLkJMT0NLU0laRSAvIDI7ICsraWkpIHtcbiAgICB2YWxzWzBdID0gKHZhbHNbMF0gPDwgOCkgfCAodmVjdG9yW2lpICsgMF0gJiAweDAwRkYpO1xuICAgIHZhbHNbMV0gPSAodmFsc1sxXSA8PCA4KSB8ICh2ZWN0b3JbaWkgKyBvZmZdICYgMHgwMEZGKTtcbiAgfVxuXG4gIHRoaXMuX2VuY3J5cHRfYmxvY2sodmFscyk7XG5cbiAgdmFyIHJldCA9IFtdO1xuICBmb3IgKGlpID0gMDsgaWkgPCB0aGlzLkJMT0NLU0laRSAvIDI7ICsraWkpIHtcbiAgICByZXRbaWkgKyAwXSA9ICh2YWxzWzBdID4+PiAoMjQgLSA4ICogKGlpKSkgJiAweDAwRkYpO1xuICAgIHJldFtpaSArIG9mZl0gPSAodmFsc1sxXSA+Pj4gKDI0IC0gOCAqIChpaSkpICYgMHgwMEZGKTtcbiAgICAvLyB2YWxzWyAwIF0gPSAoIHZhbHNbIDAgXSA+Pj4gOCApO1xuICAgIC8vIHZhbHNbIDEgXSA9ICggdmFsc1sgMSBdID4+PiA4ICk7XG4gIH1cblxuICByZXR1cm4gcmV0O1xufTtcblxuLy8qXG4vLyogVGhpcyBtZXRob2QgdGFrZXMgYW4gYXJyYXkgd2l0aCB0d28gdmFsdWVzLCBsZWZ0IGFuZCByaWdodFxuLy8qIGFuZCB1bmRvZXMgTk4gcm91bmRzIG9mIEJsb3dmaXNoIG9uIHRoZW0uXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5fZGVjcnlwdF9ibG9jayA9IGZ1bmN0aW9uKHZhbHMpIHtcbiAgdmFyIGRhdGFMID0gdmFsc1swXTtcbiAgdmFyIGRhdGFSID0gdmFsc1sxXTtcblxuICB2YXIgaWk7XG5cbiAgZm9yIChpaSA9IHRoaXMuTk4gKyAxOyBpaSA+IDE7IC0taWkpIHtcbiAgICBkYXRhTCA9IGRhdGFMIF4gdGhpcy5wYXJyYXlbaWldO1xuICAgIGRhdGFSID0gdGhpcy5fRihkYXRhTCkgXiBkYXRhUjtcblxuICAgIHZhciB0bXAgPSBkYXRhTDtcbiAgICBkYXRhTCA9IGRhdGFSO1xuICAgIGRhdGFSID0gdG1wO1xuICB9XG5cbiAgZGF0YUwgPSBkYXRhTCBeIHRoaXMucGFycmF5WzFdO1xuICBkYXRhUiA9IGRhdGFSIF4gdGhpcy5wYXJyYXlbMF07XG5cbiAgdmFsc1swXSA9IHRoaXMuX2NsZWFuKGRhdGFSKTtcbiAgdmFsc1sxXSA9IHRoaXMuX2NsZWFuKGRhdGFMKTtcbn07XG5cbi8vKlxuLy8qIFRoaXMgbWV0aG9kIHRha2VzIGEga2V5IGFycmF5IGFuZCBpbml0aWFsaXplcyB0aGVcbi8vKiBzYm94ZXMgYW5kIHBhcnJheSBmb3IgdGhpcyBlbmNyeXB0aW9uLlxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uKGtleSkge1xuICB2YXIgaWk7XG4gIHZhciBqaiA9IDA7XG5cbiAgdGhpcy5wYXJyYXkgPSBbXTtcbiAgZm9yIChpaSA9IDA7IGlpIDwgdGhpcy5OTiArIDI7ICsraWkpIHtcbiAgICB2YXIgZGF0YSA9IDB4MDAwMDAwMDA7XG4gICAgdmFyIGtrO1xuICAgIGZvciAoa2sgPSAwOyBrayA8IDQ7ICsra2spIHtcbiAgICAgIGRhdGEgPSAoZGF0YSA8PCA4KSB8IChrZXlbampdICYgMHgwMEZGKTtcbiAgICAgIGlmICgrK2pqID49IGtleS5sZW5ndGgpIHtcbiAgICAgICAgamogPSAwO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLnBhcnJheVtpaV0gPSB0aGlzLlBBUlJBWVtpaV0gXiBkYXRhO1xuICB9XG5cbiAgdGhpcy5zYm94ZXMgPSBbXTtcbiAgZm9yIChpaSA9IDA7IGlpIDwgNDsgKytpaSkge1xuICAgIHRoaXMuc2JveGVzW2lpXSA9IFtdO1xuICAgIGZvciAoamogPSAwOyBqaiA8IDI1NjsgKytqaikge1xuICAgICAgdGhpcy5zYm94ZXNbaWldW2pqXSA9IHRoaXMuU0JPWEVTW2lpXVtqal07XG4gICAgfVxuICB9XG5cbiAgdmFyIHZhbHMgPSBbMHgwMDAwMDAwMCwgMHgwMDAwMDAwMF07XG5cbiAgZm9yIChpaSA9IDA7IGlpIDwgdGhpcy5OTiArIDI7IGlpICs9IDIpIHtcbiAgICB0aGlzLl9lbmNyeXB0X2Jsb2NrKHZhbHMpO1xuICAgIHRoaXMucGFycmF5W2lpICsgMF0gPSB2YWxzWzBdO1xuICAgIHRoaXMucGFycmF5W2lpICsgMV0gPSB2YWxzWzFdO1xuICB9XG5cbiAgZm9yIChpaSA9IDA7IGlpIDwgNDsgKytpaSkge1xuICAgIGZvciAoamogPSAwOyBqaiA8IDI1NjsgamogKz0gMikge1xuICAgICAgdGhpcy5fZW5jcnlwdF9ibG9jayh2YWxzKTtcbiAgICAgIHRoaXMuc2JveGVzW2lpXVtqaiArIDBdID0gdmFsc1swXTtcbiAgICAgIHRoaXMuc2JveGVzW2lpXVtqaiArIDFdID0gdmFsc1sxXTtcbiAgICB9XG4gIH1cbn07XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG4vLyBhZGRlZCBieSBSZWN1cml0eSBMYWJzXG5cbmZ1bmN0aW9uIEJGZW5jcnlwdChibG9jaywga2V5KSB7XG4gIHZhciBiZiA9IG5ldyBCbG93ZmlzaCgpO1xuICBiZi5pbml0KHV0aWwuc3RyMmJpbihrZXkpKTtcbiAgcmV0dXJuIGJmLmVuY3J5cHRfYmxvY2soYmxvY2spO1xufVxuXG5mdW5jdGlvbiBCRihrZXkpIHtcbiAgdGhpcy5iZiA9IG5ldyBCbG93ZmlzaCgpO1xuICB0aGlzLmJmLmluaXQodXRpbC5zdHIyYmluKGtleSkpO1xuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGJsb2NrKSB7XG4gICAgcmV0dXJuIHRoaXMuYmYuZW5jcnlwdF9ibG9jayhibG9jayk7XG4gIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IEJGO1xubW9kdWxlLmV4cG9ydHMua2V5U2l6ZSA9IEJGLnByb3RvdHlwZS5rZXlTaXplID0gMTY7XG5tb2R1bGUuZXhwb3J0cy5ibG9ja1NpemUgPSBCRi5wcm90b3R5cGUuYmxvY2tTaXplID0gMTY7XG4iLCIvLyBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhIEJTRC1zdHlsZVxuLy8gbGljZW5zZSB0aGF0IGNhbiBiZSBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlLlxuXG4vLyBDb3B5cmlnaHQgMjAxMCBwamFjb2JzQHhlZWtyLmNvbSAuIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG5cbi8vIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSFxuXG4vLyBmaXhlZC9tb2RpZmllZCBieSBIZXJiZXJ0IEhhbmV3aW5rZWwsIHd3dy5oYW5lV0lOLmRlXG4vLyBjaGVjayB3d3cuaGFuZVdJTi5kZSBmb3IgdGhlIGxhdGVzdCB2ZXJzaW9uXG5cbi8vIGNhc3Q1LmpzIGlzIGEgSmF2YXNjcmlwdCBpbXBsZW1lbnRhdGlvbiBvZiBDQVNULTEyOCwgYXMgZGVmaW5lZCBpbiBSRkMgMjE0NC5cbi8vIENBU1QtMTI4IGlzIGEgY29tbW9uIE9wZW5QR1AgY2lwaGVyLlxuXG5cbi8vIENBU1Q1IGNvbnN0cnVjdG9yXG5cblxuXG5mdW5jdGlvbiBvcGVucGdwX3N5bWVuY19jYXN0NSgpIHtcbiAgdGhpcy5CbG9ja1NpemUgPSA4O1xuICB0aGlzLktleVNpemUgPSAxNjtcblxuICB0aGlzLnNldEtleSA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHRoaXMubWFza2luZyA9IG5ldyBBcnJheSgxNik7XG4gICAgdGhpcy5yb3RhdGUgPSBuZXcgQXJyYXkoMTYpO1xuXG4gICAgdGhpcy5yZXNldCgpO1xuXG4gICAgaWYgKGtleS5sZW5ndGggPT0gdGhpcy5LZXlTaXplKSB7XG4gICAgICB0aGlzLmtleVNjaGVkdWxlKGtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHV0aWwucHJpbnRfZXJyb3IoJ2Nhc3Q1LmpzOiBDQVNULTEyODoga2V5cyBtdXN0IGJlIDE2IGJ5dGVzJyk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIHRoaXMucmVzZXQgPSBmdW5jdGlvbigpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgIHRoaXMubWFza2luZ1tpXSA9IDA7XG4gICAgICB0aGlzLnJvdGF0ZVtpXSA9IDA7XG4gICAgfVxuICB9O1xuXG4gIHRoaXMuZ2V0QmxvY2tTaXplID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIEJsb2NrU2l6ZTtcbiAgfTtcblxuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihzcmMpIHtcbiAgICB2YXIgZHN0ID0gbmV3IEFycmF5KHNyYy5sZW5ndGgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzcmMubGVuZ3RoOyBpICs9IDgpIHtcbiAgICAgIHZhciBsID0gc3JjW2ldIDw8IDI0IHwgc3JjW2kgKyAxXSA8PCAxNiB8IHNyY1tpICsgMl0gPDwgOCB8IHNyY1tpICsgM107XG4gICAgICB2YXIgciA9IHNyY1tpICsgNF0gPDwgMjQgfCBzcmNbaSArIDVdIDw8IDE2IHwgc3JjW2kgKyA2XSA8PCA4IHwgc3JjW2kgKyA3XTtcbiAgICAgIHZhciB0O1xuXG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzBdLCB0aGlzLnJvdGF0ZVswXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbMV0sIHRoaXMucm90YXRlWzFdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1syXSwgdGhpcy5yb3RhdGVbMl0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzNdLCB0aGlzLnJvdGF0ZVszXSk7XG4gICAgICBsID0gdDtcblxuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1s0XSwgdGhpcy5yb3RhdGVbNF0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzVdLCB0aGlzLnJvdGF0ZVs1XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbNl0sIHRoaXMucm90YXRlWzZdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1s3XSwgdGhpcy5yb3RhdGVbN10pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMyhyLCB0aGlzLm1hc2tpbmdbOF0sIHRoaXMucm90YXRlWzhdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1s5XSwgdGhpcy5yb3RhdGVbOV0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjIociwgdGhpcy5tYXNraW5nWzEwXSwgdGhpcy5yb3RhdGVbMTBdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1sxMV0sIHRoaXMucm90YXRlWzExXSk7XG4gICAgICBsID0gdDtcblxuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1sxMl0sIHRoaXMucm90YXRlWzEyXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbMTNdLCB0aGlzLnJvdGF0ZVsxM10pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzE0XSwgdGhpcy5yb3RhdGVbMTRdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1sxNV0sIHRoaXMucm90YXRlWzE1XSk7XG4gICAgICBsID0gdDtcblxuICAgICAgZHN0W2ldID0gKHIgPj4+IDI0KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgMV0gPSAociA+Pj4gMTYpICYgMjU1O1xuICAgICAgZHN0W2kgKyAyXSA9IChyID4+PiA4KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgM10gPSByICYgMjU1O1xuICAgICAgZHN0W2kgKyA0XSA9IChsID4+PiAyNCkgJiAyNTU7XG4gICAgICBkc3RbaSArIDVdID0gKGwgPj4+IDE2KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgNl0gPSAobCA+Pj4gOCkgJiAyNTU7XG4gICAgICBkc3RbaSArIDddID0gbCAmIDI1NTtcbiAgICB9XG5cbiAgICByZXR1cm4gZHN0O1xuICB9O1xuXG4gIHRoaXMuZGVjcnlwdCA9IGZ1bmN0aW9uKHNyYykge1xuICAgIHZhciBkc3QgPSBuZXcgQXJyYXkoc3JjLmxlbmd0aCk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNyYy5sZW5ndGg7IGkgKz0gOCkge1xuICAgICAgdmFyIGwgPSBzcmNbaV0gPDwgMjQgfCBzcmNbaSArIDFdIDw8IDE2IHwgc3JjW2kgKyAyXSA8PCA4IHwgc3JjW2kgKyAzXTtcbiAgICAgIHZhciByID0gc3JjW2kgKyA0XSA8PCAyNCB8IHNyY1tpICsgNV0gPDwgMTYgfCBzcmNbaSArIDZdIDw8IDggfCBzcmNbaSArIDddO1xuICAgICAgdmFyIHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbMTVdLCB0aGlzLnJvdGF0ZVsxNV0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzE0XSwgdGhpcy5yb3RhdGVbMTRdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1sxM10sIHRoaXMucm90YXRlWzEzXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbMTJdLCB0aGlzLnJvdGF0ZVsxMl0pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMyhyLCB0aGlzLm1hc2tpbmdbMTFdLCB0aGlzLnJvdGF0ZVsxMV0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjIociwgdGhpcy5tYXNraW5nWzEwXSwgdGhpcy5yb3RhdGVbMTBdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1s5XSwgdGhpcy5yb3RhdGVbOV0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzhdLCB0aGlzLnJvdGF0ZVs4XSk7XG4gICAgICBsID0gdDtcblxuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1s3XSwgdGhpcy5yb3RhdGVbN10pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzZdLCB0aGlzLnJvdGF0ZVs2XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMyhyLCB0aGlzLm1hc2tpbmdbNV0sIHRoaXMucm90YXRlWzVdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1s0XSwgdGhpcy5yb3RhdGVbNF0pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbM10sIHRoaXMucm90YXRlWzNdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1syXSwgdGhpcy5yb3RhdGVbMl0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjIociwgdGhpcy5tYXNraW5nWzFdLCB0aGlzLnJvdGF0ZVsxXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbMF0sIHRoaXMucm90YXRlWzBdKTtcbiAgICAgIGwgPSB0O1xuXG4gICAgICBkc3RbaV0gPSAociA+Pj4gMjQpICYgMjU1O1xuICAgICAgZHN0W2kgKyAxXSA9IChyID4+PiAxNikgJiAyNTU7XG4gICAgICBkc3RbaSArIDJdID0gKHIgPj4+IDgpICYgMjU1O1xuICAgICAgZHN0W2kgKyAzXSA9IHIgJiAyNTU7XG4gICAgICBkc3RbaSArIDRdID0gKGwgPj4+IDI0KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgNV0gPSAobCA+PiAxNikgJiAyNTU7XG4gICAgICBkc3RbaSArIDZdID0gKGwgPj4gOCkgJiAyNTU7XG4gICAgICBkc3RbaSArIDddID0gbCAmIDI1NTtcbiAgICB9XG5cbiAgICByZXR1cm4gZHN0O1xuICB9O1xuICB2YXIgc2NoZWR1bGVBID0gbmV3IEFycmF5KDQpO1xuXG4gIHNjaGVkdWxlQVswXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVBWzBdWzBdID0gbmV3IEFycmF5KDQsIDAsIDB4ZCwgMHhmLCAweGMsIDB4ZSwgMHg4KTtcbiAgc2NoZWR1bGVBWzBdWzFdID0gbmV3IEFycmF5KDUsIDIsIDE2ICsgMCwgMTYgKyAyLCAxNiArIDEsIDE2ICsgMywgMHhhKTtcbiAgc2NoZWR1bGVBWzBdWzJdID0gbmV3IEFycmF5KDYsIDMsIDE2ICsgNywgMTYgKyA2LCAxNiArIDUsIDE2ICsgNCwgOSk7XG4gIHNjaGVkdWxlQVswXVszXSA9IG5ldyBBcnJheSg3LCAxLCAxNiArIDB4YSwgMTYgKyA5LCAxNiArIDB4YiwgMTYgKyA4LCAweGIpO1xuXG4gIHNjaGVkdWxlQVsxXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVBWzFdWzBdID0gbmV3IEFycmF5KDAsIDYsIDE2ICsgNSwgMTYgKyA3LCAxNiArIDQsIDE2ICsgNiwgMTYgKyAwKTtcbiAgc2NoZWR1bGVBWzFdWzFdID0gbmV3IEFycmF5KDEsIDQsIDAsIDIsIDEsIDMsIDE2ICsgMik7XG4gIHNjaGVkdWxlQVsxXVsyXSA9IG5ldyBBcnJheSgyLCA1LCA3LCA2LCA1LCA0LCAxNiArIDEpO1xuICBzY2hlZHVsZUFbMV1bM10gPSBuZXcgQXJyYXkoMywgNywgMHhhLCA5LCAweGIsIDgsIDE2ICsgMyk7XG5cbiAgc2NoZWR1bGVBWzJdID0gbmV3IEFycmF5KDQpO1xuICBzY2hlZHVsZUFbMl1bMF0gPSBuZXcgQXJyYXkoNCwgMCwgMHhkLCAweGYsIDB4YywgMHhlLCA4KTtcbiAgc2NoZWR1bGVBWzJdWzFdID0gbmV3IEFycmF5KDUsIDIsIDE2ICsgMCwgMTYgKyAyLCAxNiArIDEsIDE2ICsgMywgMHhhKTtcbiAgc2NoZWR1bGVBWzJdWzJdID0gbmV3IEFycmF5KDYsIDMsIDE2ICsgNywgMTYgKyA2LCAxNiArIDUsIDE2ICsgNCwgOSk7XG4gIHNjaGVkdWxlQVsyXVszXSA9IG5ldyBBcnJheSg3LCAxLCAxNiArIDB4YSwgMTYgKyA5LCAxNiArIDB4YiwgMTYgKyA4LCAweGIpO1xuXG5cbiAgc2NoZWR1bGVBWzNdID0gbmV3IEFycmF5KDQpO1xuICBzY2hlZHVsZUFbM11bMF0gPSBuZXcgQXJyYXkoMCwgNiwgMTYgKyA1LCAxNiArIDcsIDE2ICsgNCwgMTYgKyA2LCAxNiArIDApO1xuICBzY2hlZHVsZUFbM11bMV0gPSBuZXcgQXJyYXkoMSwgNCwgMCwgMiwgMSwgMywgMTYgKyAyKTtcbiAgc2NoZWR1bGVBWzNdWzJdID0gbmV3IEFycmF5KDIsIDUsIDcsIDYsIDUsIDQsIDE2ICsgMSk7XG4gIHNjaGVkdWxlQVszXVszXSA9IG5ldyBBcnJheSgzLCA3LCAweGEsIDksIDB4YiwgOCwgMTYgKyAzKTtcblxuICB2YXIgc2NoZWR1bGVCID0gbmV3IEFycmF5KDQpO1xuXG4gIHNjaGVkdWxlQlswXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVCWzBdWzBdID0gbmV3IEFycmF5KDE2ICsgOCwgMTYgKyA5LCAxNiArIDcsIDE2ICsgNiwgMTYgKyAyKTtcbiAgc2NoZWR1bGVCWzBdWzFdID0gbmV3IEFycmF5KDE2ICsgMHhhLCAxNiArIDB4YiwgMTYgKyA1LCAxNiArIDQsIDE2ICsgNik7XG4gIHNjaGVkdWxlQlswXVsyXSA9IG5ldyBBcnJheSgxNiArIDB4YywgMTYgKyAweGQsIDE2ICsgMywgMTYgKyAyLCAxNiArIDkpO1xuICBzY2hlZHVsZUJbMF1bM10gPSBuZXcgQXJyYXkoMTYgKyAweGUsIDE2ICsgMHhmLCAxNiArIDEsIDE2ICsgMCwgMTYgKyAweGMpO1xuXG4gIHNjaGVkdWxlQlsxXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVCWzFdWzBdID0gbmV3IEFycmF5KDMsIDIsIDB4YywgMHhkLCA4KTtcbiAgc2NoZWR1bGVCWzFdWzFdID0gbmV3IEFycmF5KDEsIDAsIDB4ZSwgMHhmLCAweGQpO1xuICBzY2hlZHVsZUJbMV1bMl0gPSBuZXcgQXJyYXkoNywgNiwgOCwgOSwgMyk7XG4gIHNjaGVkdWxlQlsxXVszXSA9IG5ldyBBcnJheSg1LCA0LCAweGEsIDB4YiwgNyk7XG5cblxuICBzY2hlZHVsZUJbMl0gPSBuZXcgQXJyYXkoNCk7XG4gIHNjaGVkdWxlQlsyXVswXSA9IG5ldyBBcnJheSgxNiArIDMsIDE2ICsgMiwgMTYgKyAweGMsIDE2ICsgMHhkLCAxNiArIDkpO1xuICBzY2hlZHVsZUJbMl1bMV0gPSBuZXcgQXJyYXkoMTYgKyAxLCAxNiArIDAsIDE2ICsgMHhlLCAxNiArIDB4ZiwgMTYgKyAweGMpO1xuICBzY2hlZHVsZUJbMl1bMl0gPSBuZXcgQXJyYXkoMTYgKyA3LCAxNiArIDYsIDE2ICsgOCwgMTYgKyA5LCAxNiArIDIpO1xuICBzY2hlZHVsZUJbMl1bM10gPSBuZXcgQXJyYXkoMTYgKyA1LCAxNiArIDQsIDE2ICsgMHhhLCAxNiArIDB4YiwgMTYgKyA2KTtcblxuXG4gIHNjaGVkdWxlQlszXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVCWzNdWzBdID0gbmV3IEFycmF5KDgsIDksIDcsIDYsIDMpO1xuICBzY2hlZHVsZUJbM11bMV0gPSBuZXcgQXJyYXkoMHhhLCAweGIsIDUsIDQsIDcpO1xuICBzY2hlZHVsZUJbM11bMl0gPSBuZXcgQXJyYXkoMHhjLCAweGQsIDMsIDIsIDgpO1xuICBzY2hlZHVsZUJbM11bM10gPSBuZXcgQXJyYXkoMHhlLCAweGYsIDEsIDAsIDB4ZCk7XG5cbiAgLy8gY2hhbmdlZCAnaW4nIHRvICdpbm4nIChpbiBqYXZhc2NyaXB0ICdpbicgaXMgYSByZXNlcnZlZCB3b3JkKVxuICB0aGlzLmtleVNjaGVkdWxlID0gZnVuY3Rpb24oaW5uKSB7XG4gICAgdmFyIHQgPSBuZXcgQXJyYXkoOCk7XG4gICAgdmFyIGsgPSBuZXcgQXJyYXkoMzIpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgIHZhciBqID0gaSAqIDQ7XG4gICAgICB0W2ldID0gaW5uW2pdIDw8IDI0IHwgaW5uW2ogKyAxXSA8PCAxNiB8IGlubltqICsgMl0gPDwgOCB8IGlubltqICsgM107XG4gICAgfVxuXG4gICAgdmFyIHggPSBbNiwgNywgNCwgNV07XG4gICAgdmFyIGtpID0gMDtcblxuICAgIGZvciAodmFyIGhhbGYgPSAwOyBoYWxmIDwgMjsgaGFsZisrKSB7XG4gICAgICBmb3IgKHZhciByb3VuZCA9IDA7IHJvdW5kIDwgNDsgcm91bmQrKykge1xuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDQ7IGorKykge1xuICAgICAgICAgIHZhciBhID0gc2NoZWR1bGVBW3JvdW5kXVtqXTtcbiAgICAgICAgICB2YXIgdyA9IHRbYVsxXV07XG5cbiAgICAgICAgICB3IF49IHNCb3hbNF1bKHRbYVsyXSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYVsyXSAmIDMpKSkgJiAweGZmXTtcbiAgICAgICAgICB3IF49IHNCb3hbNV1bKHRbYVszXSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYVszXSAmIDMpKSkgJiAweGZmXTtcbiAgICAgICAgICB3IF49IHNCb3hbNl1bKHRbYVs0XSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYVs0XSAmIDMpKSkgJiAweGZmXTtcbiAgICAgICAgICB3IF49IHNCb3hbN11bKHRbYVs1XSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYVs1XSAmIDMpKSkgJiAweGZmXTtcbiAgICAgICAgICB3IF49IHNCb3hbeFtqXV1bKHRbYVs2XSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYVs2XSAmIDMpKSkgJiAweGZmXTtcbiAgICAgICAgICB0W2FbMF1dID0gdztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgNDsgaisrKSB7XG4gICAgICAgICAgdmFyIGIgPSBzY2hlZHVsZUJbcm91bmRdW2pdO1xuICAgICAgICAgIHZhciB3ID0gc0JveFs0XVsodFtiWzBdID4+PiAyXSA+Pj4gKDI0IC0gOCAqIChiWzBdICYgMykpKSAmIDB4ZmZdO1xuXG4gICAgICAgICAgdyBePSBzQm94WzVdWyh0W2JbMV0gPj4+IDJdID4+PiAoMjQgLSA4ICogKGJbMV0gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94WzZdWyh0W2JbMl0gPj4+IDJdID4+PiAoMjQgLSA4ICogKGJbMl0gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94WzddWyh0W2JbM10gPj4+IDJdID4+PiAoMjQgLSA4ICogKGJbM10gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94WzQgKyBqXVsodFtiWzRdID4+PiAyXSA+Pj4gKDI0IC0gOCAqIChiWzRdICYgMykpKSAmIDB4ZmZdO1xuICAgICAgICAgIGtba2ldID0gdztcbiAgICAgICAgICBraSsrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICB0aGlzLm1hc2tpbmdbaV0gPSBrW2ldO1xuICAgICAgdGhpcy5yb3RhdGVbaV0gPSBrWzE2ICsgaV0gJiAweDFmO1xuICAgIH1cbiAgfTtcblxuICAvLyBUaGVzZSBhcmUgdGhlIHRocmVlICdmJyBmdW5jdGlvbnMuIFNlZSBSRkMgMjE0NCwgc2VjdGlvbiAyLjIuXG5cbiAgZnVuY3Rpb24gZjEoZCwgbSwgcikge1xuICAgIHZhciB0ID0gbSArIGQ7XG4gICAgdmFyIEkgPSAodCA8PCByKSB8ICh0ID4+PiAoMzIgLSByKSk7XG4gICAgcmV0dXJuICgoc0JveFswXVtJID4+PiAyNF0gXiBzQm94WzFdWyhJID4+PiAxNikgJiAyNTVdKSAtIHNCb3hbMl1bKEkgPj4+IDgpICYgMjU1XSkgKyBzQm94WzNdW0kgJiAyNTVdO1xuICB9XG5cbiAgZnVuY3Rpb24gZjIoZCwgbSwgcikge1xuICAgIHZhciB0ID0gbSBeIGQ7XG4gICAgdmFyIEkgPSAodCA8PCByKSB8ICh0ID4+PiAoMzIgLSByKSk7XG4gICAgcmV0dXJuICgoc0JveFswXVtJID4+PiAyNF0gLSBzQm94WzFdWyhJID4+PiAxNikgJiAyNTVdKSArIHNCb3hbMl1bKEkgPj4+IDgpICYgMjU1XSkgXiBzQm94WzNdW0kgJiAyNTVdO1xuICB9XG5cbiAgZnVuY3Rpb24gZjMoZCwgbSwgcikge1xuICAgIHZhciB0ID0gbSAtIGQ7XG4gICAgdmFyIEkgPSAodCA8PCByKSB8ICh0ID4+PiAoMzIgLSByKSk7XG4gICAgcmV0dXJuICgoc0JveFswXVtJID4+PiAyNF0gKyBzQm94WzFdWyhJID4+PiAxNikgJiAyNTVdKSBeIHNCb3hbMl1bKEkgPj4+IDgpICYgMjU1XSkgLSBzQm94WzNdW0kgJiAyNTVdO1xuICB9XG5cbiAgdmFyIHNCb3ggPSBuZXcgQXJyYXkoOCk7XG4gIHNCb3hbMF0gPSBuZXcgQXJyYXkoXG4gICAgMHgzMGZiNDBkNCwgMHg5ZmEwZmYwYiwgMHg2YmVjY2QyZiwgMHgzZjI1OGM3YSwgMHgxZTIxM2YyZiwgMHg5YzAwNGRkMywgMHg2MDAzZTU0MCwgMHhjZjlmYzk0OSxcbiAgICAweGJmZDRhZjI3LCAweDg4YmJiZGI1LCAweGUyMDM0MDkwLCAweDk4ZDA5Njc1LCAweDZlNjNhMGUwLCAweDE1YzM2MWQyLCAweGMyZTc2NjFkLCAweDIyZDRmZjhlLFxuICAgIDB4Mjg2ODNiNmYsIDB4YzA3ZmQwNTksIDB4ZmYyMzc5YzgsIDB4Nzc1ZjUwZTIsIDB4NDNjMzQwZDMsIDB4ZGYyZjg2NTYsIDB4ODg3Y2E0MWEsIDB4YTJkMmJkMmQsXG4gICAgMHhhMWM5ZTBkNiwgMHgzNDZjNDgxOSwgMHg2MWI3NmQ4NywgMHgyMjU0MGYyZiwgMHgyYWJlMzJlMSwgMHhhYTU0MTY2YiwgMHgyMjU2OGUzYSwgMHhhMmQzNDFkMCxcbiAgICAweDY2ZGI0MGM4LCAweGE3ODQzOTJmLCAweDAwNGRmZjJmLCAweDJkYjlkMmRlLCAweDk3OTQzZmFjLCAweDRhOTdjMWQ4LCAweDUyNzY0NGI3LCAweGI1ZjQzN2E3LFxuICAgIDB4YjgyY2JhZWYsIDB4ZDc1MWQxNTksIDB4NmZmN2YwZWQsIDB4NWEwOTdhMWYsIDB4ODI3YjY4ZDAsIDB4OTBlY2Y1MmUsIDB4MjJiMGMwNTQsIDB4YmM4ZTU5MzUsXG4gICAgMHg0YjZkMmY3ZiwgMHg1MGJiNjRhMiwgMHhkMjY2NDkxMCwgMHhiZWU1ODEyZCwgMHhiNzMzMjI5MCwgMHhlOTNiMTU5ZiwgMHhiNDhlZTQxMSwgMHg0YmZmMzQ1ZCxcbiAgICAweGZkNDVjMjQwLCAweGFkMzE5NzNmLCAweGM0ZjZkMDJlLCAweDU1ZmM4MTY1LCAweGQ1YjFjYWFkLCAweGExYWMyZGFlLCAweGEyZDRiNzZkLCAweGMxOWIwYzUwLFxuICAgIDB4ODgyMjQwZjIsIDB4MGM2ZTRmMzgsIDB4YTRlNGJmZDcsIDB4NGY1YmEyNzIsIDB4NTY0YzFkMmYsIDB4YzU5YzUzMTksIDB4Yjk0OWUzNTQsIDB4YjA0NjY5ZmUsXG4gICAgMHhiMWI2YWI4YSwgMHhjNzEzNThkZCwgMHg2Mzg1YzU0NSwgMHgxMTBmOTM1ZCwgMHg1NzUzOGFkNSwgMHg2YTM5MDQ5MywgMHhlNjNkMzdlMCwgMHgyYTU0ZjZiMyxcbiAgICAweDNhNzg3ZDVmLCAweDYyNzZhMGI1LCAweDE5YTZmY2RmLCAweDdhNDIyMDZhLCAweDI5ZjlkNGQ1LCAweGY2MWIxODkxLCAweGJiNzIyNzVlLCAweGFhNTA4MTY3LFxuICAgIDB4Mzg5MDEwOTEsIDB4YzZiNTA1ZWIsIDB4ODRjN2NiOGMsIDB4MmFkNzVhMGYsIDB4ODc0YTE0MjcsIDB4YTJkMTkzNmIsIDB4MmFkMjg2YWYsIDB4YWE1NmQyOTEsXG4gICAgMHhkNzg5NDM2MCwgMHg0MjVjNzUwZCwgMHg5M2IzOWUyNiwgMHgxODcxODRjOSwgMHg2YzAwYjMyZCwgMHg3M2UyYmIxNCwgMHhhMGJlYmMzYywgMHg1NDYyMzc3OSxcbiAgICAweDY0NDU5ZWFiLCAweDNmMzI4YjgyLCAweDc3MThjZjgyLCAweDU5YTJjZWE2LCAweDA0ZWUwMDJlLCAweDg5ZmU3OGU2LCAweDNmYWIwOTUwLCAweDMyNWZmNmMyLFxuICAgIDB4ODEzODNmMDUsIDB4Njk2M2M1YzgsIDB4NzZjYjVhZDYsIDB4ZDQ5OTc0YzksIDB4Y2ExODBkY2YsIDB4MzgwNzgyZDUsIDB4YzdmYTVjZjYsIDB4OGFjMzE1MTEsXG4gICAgMHgzNWU3OWUxMywgMHg0N2RhOTFkMCwgMHhmNDBmOTA4NiwgMHhhN2UyNDE5ZSwgMHgzMTM2NjI0MSwgMHgwNTFlZjQ5NSwgMHhhYTU3M2IwNCwgMHg0YTgwNWQ4ZCxcbiAgICAweDU0ODMwMGQwLCAweDAwMzIyYTNjLCAweGJmNjRjZGRmLCAweGJhNTdhNjhlLCAweDc1YzYzNzJiLCAweDUwYWZkMzQxLCAweGE3YzEzMjc1LCAweDkxNWEwYmY1LFxuICAgIDB4NmI1NGJmYWIsIDB4MmIwYjE0MjYsIDB4YWI0Y2M5ZDcsIDB4NDQ5Y2NkODIsIDB4ZjdmYmYyNjUsIDB4YWI4NWM1ZjMsIDB4MWI1NWRiOTQsIDB4YWFkNGUzMjQsXG4gICAgMHhjZmE0YmQzZiwgMHgyZGVhYTNlMiwgMHg5ZTIwNGQwMiwgMHhjOGJkMjVhYywgMHhlYWRmNTViMywgMHhkNWJkOWU5OCwgMHhlMzEyMzFiMiwgMHgyYWQ1YWQ2YyxcbiAgICAweDk1NDMyOWRlLCAweGFkYmU0NTI4LCAweGQ4NzEwZjY5LCAweGFhNTFjOTBmLCAweGFhNzg2YmY2LCAweDIyNTEzZjFlLCAweGFhNTFhNzliLCAweDJhZDM0NGNjLFxuICAgIDB4N2I1YTQxZjAsIDB4ZDM3Y2ZiYWQsIDB4MWIwNjk1MDUsIDB4NDFlY2U0OTEsIDB4YjRjMzMyZTYsIDB4MDMyMjY4ZDQsIDB4Yzk2MDBhY2MsIDB4Y2UzODdlNmQsXG4gICAgMHhiZjZiYjE2YywgMHg2YTcwZmI3OCwgMHgwZDAzZDljOSwgMHhkNGRmMzlkZSwgMHhlMDEwNjNkYSwgMHg0NzM2ZjQ2NCwgMHg1YWQzMjhkOCwgMHhiMzQ3Y2M5NixcbiAgICAweDc1YmIwZmMzLCAweDk4NTExYmZiLCAweDRmZmJjYzM1LCAweGI1OGJjZjZhLCAweGUxMWYwYWJjLCAweGJmYzVmZTRhLCAweGE3MGFlYzEwLCAweGFjMzk1NzBhLFxuICAgIDB4M2YwNDQ0MmYsIDB4NjE4OGIxNTMsIDB4ZTAzOTdhMmUsIDB4NTcyN2NiNzksIDB4OWNlYjQxOGYsIDB4MWNhY2Q2OGQsIDB4MmFkMzdjOTYsIDB4MDE3NWNiOWQsXG4gICAgMHhjNjlkZmYwOSwgMHhjNzViNjVmMCwgMHhkOWRiNDBkOCwgMHhlYzBlNzc3OSwgMHg0NzQ0ZWFkNCwgMHhiMTFjMzI3NCwgMHhkZDI0Y2I5ZSwgMHg3ZTFjNTRiZCxcbiAgICAweGYwMTE0NGY5LCAweGQyMjQwZWIxLCAweDk2NzViM2ZkLCAweGEzYWMzNzU1LCAweGQ0N2MyN2FmLCAweDUxYzg1ZjRkLCAweDU2OTA3NTk2LCAweGE1YmIxNWU2LFxuICAgIDB4NTgwMzA0ZjAsIDB4Y2EwNDJjZjEsIDB4MDExYTM3ZWEsIDB4OGRiZmFhZGIsIDB4MzViYTNlNGEsIDB4MzUyNmZmYTAsIDB4YzM3YjRkMDksIDB4YmMzMDZlZDksXG4gICAgMHg5OGE1MjY2NiwgMHg1NjQ4ZjcyNSwgMHhmZjVlNTY5ZCwgMHgwY2VkNjNkMCwgMHg3YzYzYjJjZiwgMHg3MDBiNDVlMSwgMHhkNWVhNTBmMSwgMHg4NWE5Mjg3MixcbiAgICAweGFmMWZiZGE3LCAweGQ0MjM0ODcwLCAweGE3ODcwYmYzLCAweDJkM2I0ZDc5LCAweDQyZTA0MTk4LCAweDBjZDBlZGU3LCAweDI2NDcwZGI4LCAweGY4ODE4MTRjLFxuICAgIDB4NDc0ZDZhZDcsIDB4N2MwYzVlNWMsIDB4ZDEyMzE5NTksIDB4MzgxYjcyOTgsIDB4ZjVkMmY0ZGIsIDB4YWI4Mzg2NTMsIDB4NmUyZjFlMjMsIDB4ODM3MTljOWUsXG4gICAgMHhiZDkxZTA0NiwgMHg5YTU2NDU2ZSwgMHhkYzM5MjAwYywgMHgyMGM4YzU3MSwgMHg5NjJiZGExYywgMHhlMWU2OTZmZiwgMHhiMTQxYWIwOCwgMHg3Y2NhODliOSxcbiAgICAweDFhNjllNzgzLCAweDAyY2M0ODQzLCAweGEyZjdjNTc5LCAweDQyOWVmNDdkLCAweDQyN2IxNjljLCAweDVhYzlmMDQ5LCAweGRkOGYwZjAwLCAweDVjODE2NWJmKTtcblxuICBzQm94WzFdID0gbmV3IEFycmF5KFxuICAgIDB4MWYyMDEwOTQsIDB4ZWYwYmE3NWIsIDB4NjllM2NmN2UsIDB4MzkzZjQzODAsIDB4ZmU2MWNmN2EsIDB4ZWVjNTIwN2EsIDB4NTU4ODljOTQsIDB4NzJmYzA2NTEsXG4gICAgMHhhZGE3ZWY3OSwgMHg0ZTFkNzIzNSwgMHhkNTVhNjNjZSwgMHhkZTA0MzZiYSwgMHg5OWM0MzBlZiwgMHg1ZjBjMDc5NCwgMHgxOGRjZGI3ZCwgMHhhMWQ2ZWZmMyxcbiAgICAweGEwYjUyZjdiLCAweDU5ZTgzNjA1LCAweGVlMTViMDk0LCAweGU5ZmZkOTA5LCAweGRjNDQwMDg2LCAweGVmOTQ0NDU5LCAweGJhODNjY2IzLCAweGUwYzNjZGZiLFxuICAgIDB4ZDFkYTQxODEsIDB4M2IwOTJhYjEsIDB4Zjk5N2YxYzEsIDB4YTVlNmNmN2IsIDB4MDE0MjBkZGIsIDB4ZTRlN2VmNWIsIDB4MjVhMWZmNDEsIDB4ZTE4MGY4MDYsXG4gICAgMHgxZmM0MTA4MCwgMHgxNzliZWU3YSwgMHhkMzdhYzZhOSwgMHhmZTU4MzBhNCwgMHg5OGRlOGI3ZiwgMHg3N2U4M2Y0ZSwgMHg3OTkyOTI2OSwgMHgyNGZhOWY3YixcbiAgICAweGUxMTNjODViLCAweGFjYzQwMDgzLCAweGQ3NTAzNTI1LCAweGY3ZWE2MTVmLCAweDYyMTQzMTU0LCAweDBkNTU0YjYzLCAweDVkNjgxMTIxLCAweGM4NjZjMzU5LFxuICAgIDB4M2Q2M2NmNzMsIDB4Y2VlMjM0YzAsIDB4ZDRkODdlODcsIDB4NWM2NzJiMjEsIDB4MDcxZjYxODEsIDB4MzlmNzYyN2YsIDB4MzYxZTMwODQsIDB4ZTRlYjU3M2IsXG4gICAgMHg2MDJmNjRhNCwgMHhkNjNhY2Q5YywgMHgxYmJjNDYzNSwgMHg5ZTgxMDMyZCwgMHgyNzAxZjUwYywgMHg5OTg0N2FiNCwgMHhhMGUzZGY3OSwgMHhiYTZjZjM4YyxcbiAgICAweDEwODQzMDk0LCAweDI1MzdhOTVlLCAweGY0NmY2ZmZlLCAweGExZmYzYjFmLCAweDIwOGNmYjZhLCAweDhmNDU4Yzc0LCAweGQ5ZTBhMjI3LCAweDRlYzczYTM0LFxuICAgIDB4ZmM4ODRmNjksIDB4M2U0ZGU4ZGYsIDB4ZWYwZTAwODgsIDB4MzU1OTY0OGQsIDB4OGE0NTM4OGMsIDB4MWQ4MDQzNjYsIDB4NzIxZDliZmQsIDB4YTU4Njg0YmIsXG4gICAgMHhlODI1NjMzMywgMHg4NDRlODIxMiwgMHgxMjhkODA5OCwgMHhmZWQzM2ZiNCwgMHhjZTI4MGFlMSwgMHgyN2UxOWJhNSwgMHhkNWE2YzI1MiwgMHhlNDk3NTRiZCxcbiAgICAweGM1ZDY1NWRkLCAweGViNjY3MDY0LCAweDc3ODQwYjRkLCAweGExYjZhODAxLCAweDg0ZGIyNmE5LCAweGUwYjU2NzE0LCAweDIxZjA0M2I3LCAweGU1ZDA1ODYwLFxuICAgIDB4NTRmMDMwODQsIDB4MDY2ZmY0NzIsIDB4YTMxYWExNTMsIDB4ZGFkYzQ3NTUsIDB4YjU2MjVkYmYsIDB4Njg1NjFiZTYsIDB4ODNjYTZiOTQsIDB4MmQ2ZWQyM2IsXG4gICAgMHhlY2NmMDFkYiwgMHhhNmQzZDBiYSwgMHhiNjgwM2Q1YywgMHhhZjc3YTcwOSwgMHgzM2I0YTM0YywgMHgzOTdiYzhkNiwgMHg1ZWUyMmI5NSwgMHg1ZjBlNTMwNCxcbiAgICAweDgxZWQ2ZjYxLCAweDIwZTc0MzY0LCAweGI0NWUxMzc4LCAweGRlMTg2MzliLCAweDg4MWNhMTIyLCAweGI5NjcyNmQxLCAweDgwNDlhN2U4LCAweDIyYjdkYTdiLFxuICAgIDB4NWU1NTJkMjUsIDB4NTI3MmQyMzcsIDB4NzlkMjk1MWMsIDB4YzYwZDg5NGMsIDB4NDg4Y2I0MDIsIDB4MWJhNGZlNWIsIDB4YTRiMDlmNmIsIDB4MWNhODE1Y2YsXG4gICAgMHhhMjBjMzAwNSwgMHg4ODcxZGY2MywgMHhiOWRlMmZjYiwgMHgwY2M2YzllOSwgMHgwYmVlZmY1MywgMHhlMzIxNDUxNywgMHhiNDU0MjgzNSwgMHg5ZjYzMjkzYyxcbiAgICAweGVlNDFlNzI5LCAweDZlMWQyZDdjLCAweDUwMDQ1Mjg2LCAweDFlNjY4NWYzLCAweGYzMzQwMWM2LCAweDMwYTIyYzk1LCAweDMxYTcwODUwLCAweDYwOTMwZjEzLFxuICAgIDB4NzNmOTg0MTcsIDB4YTEyNjk4NTksIDB4ZWM2NDVjNDQsIDB4NTJjODc3YTksIDB4Y2RmZjMzYTYsIDB4YTAyYjE3NDEsIDB4N2NiYWQ5YTIsIDB4MjE4MDAzNmYsXG4gICAgMHg1MGQ5OWMwOCwgMHhjYjNmNDg2MSwgMHhjMjZiZDc2NSwgMHg2NGEzZjZhYiwgMHg4MDM0MjY3NiwgMHgyNWE3NWU3YiwgMHhlNGU2ZDFmYywgMHgyMGM3MTBlNixcbiAgICAweGNkZjBiNjgwLCAweDE3ODQ0ZDNiLCAweDMxZWVmODRkLCAweDdlMDgyNGU0LCAweDJjY2I0OWViLCAweDg0NmEzYmFlLCAweDhmZjc3ODg4LCAweGVlNWQ2MGY2LFxuICAgIDB4N2FmNzU2NzMsIDB4MmZkZDVjZGIsIDB4YTExNjMxYzEsIDB4MzBmNjZmNDMsIDB4YjNmYWVjNTQsIDB4MTU3ZmQ3ZmEsIDB4ZWY4NTc5Y2MsIDB4ZDE1MmRlNTgsXG4gICAgMHhkYjJmZmQ1ZSwgMHg4ZjMyY2UxOSwgMHgzMDZhZjk3YSwgMHgwMmYwM2VmOCwgMHg5OTMxOWFkNSwgMHhjMjQyZmEwZiwgMHhhN2UzZWJiMCwgMHhjNjhlNDkwNixcbiAgICAweGI4ZGEyMzBjLCAweDgwODIzMDI4LCAweGRjZGVmM2M4LCAweGQzNWZiMTcxLCAweDA4OGExYmM4LCAweGJlYzBjNTYwLCAweDYxYTNjOWU4LCAweGJjYThmNTRkLFxuICAgIDB4YzcyZmVmZmEsIDB4MjI4MjJlOTksIDB4ODJjNTcwYjQsIDB4ZDhkOTRlODksIDB4OGIxYzM0YmMsIDB4MzAxZTE2ZTYsIDB4MjczYmU5NzksIDB4YjBmZmVhYTYsXG4gICAgMHg2MWQ5YjhjNiwgMHgwMGIyNDg2OSwgMHhiN2ZmY2UzZiwgMHgwOGRjMjgzYiwgMHg0M2RhZjY1YSwgMHhmN2UxOTc5OCwgMHg3NjE5YjcyZiwgMHg4ZjFjOWJhNCxcbiAgICAweGRjODYzN2EwLCAweDE2YTdkM2IxLCAweDlmYzM5M2I3LCAweGE3MTM2ZWViLCAweGM2YmNjNjNlLCAweDFhNTEzNzQyLCAweGVmNjgyOGJjLCAweDUyMDM2NWQ2LFxuICAgIDB4MmQ2YTc3YWIsIDB4MzUyN2VkNGIsIDB4ODIxZmQyMTYsIDB4MDk1YzZlMmUsIDB4ZGI5MmYyZmIsIDB4NWVlYTI5Y2IsIDB4MTQ1ODkyZjUsIDB4OTE1ODRmN2YsXG4gICAgMHg1NDgzNjk3YiwgMHgyNjY3YThjYywgMHg4NTE5NjA0OCwgMHg4YzRiYWNlYSwgMHg4MzM4NjBkNCwgMHgwZDIzZTBmOSwgMHg2YzM4N2U4YSwgMHgwYWU2ZDI0OSxcbiAgICAweGIyODQ2MDBjLCAweGQ4MzU3MzFkLCAweGRjYjFjNjQ3LCAweGFjNGM1NmVhLCAweDNlYmQ4MWIzLCAweDIzMGVhYmIwLCAweDY0MzhiYzg3LCAweGYwYjViMWZhLFxuICAgIDB4OGY1ZWEyYjMsIDB4ZmMxODQ2NDIsIDB4MGEwMzZiN2EsIDB4NGZiMDg5YmQsIDB4NjQ5ZGE1ODksIDB4YTM0NTQxNWUsIDB4NWMwMzgzMjMsIDB4M2U1ZDNiYjksXG4gICAgMHg0M2Q3OTU3MiwgMHg3ZTZkZDA3YywgMHgwNmRmZGYxZSwgMHg2YzZjYzRlZiwgMHg3MTYwYTUzOSwgMHg3M2JmYmU3MCwgMHg4Mzg3NzYwNSwgMHg0NTIzZWNmMSk7XG5cbiAgc0JveFsyXSA9IG5ldyBBcnJheShcbiAgICAweDhkZWZjMjQwLCAweDI1ZmE1ZDlmLCAweGViOTAzZGJmLCAweGU4MTBjOTA3LCAweDQ3NjA3ZmZmLCAweDM2OWZlNDRiLCAweDhjMWZjNjQ0LCAweGFlY2VjYTkwLFxuICAgIDB4YmViMWY5YmYsIDB4ZWVmYmNhZWEsIDB4ZThjZjE5NTAsIDB4NTFkZjA3YWUsIDB4OTIwZTg4MDYsIDB4ZjBhZDA1NDgsIDB4ZTEzYzhkODMsIDB4OTI3MDEwZDUsXG4gICAgMHgxMTEwN2Q5ZiwgMHgwNzY0N2RiOSwgMHhiMmUzZTRkNCwgMHgzZDRmMjg1ZSwgMHhiOWFmYTgyMCwgMHhmYWRlODJlMCwgMHhhMDY3MjY4YiwgMHg4MjcyNzkyZSxcbiAgICAweDU1M2ZiMmMwLCAweDQ4OWFlMjJiLCAweGQ0ZWY5Nzk0LCAweDEyNWUzZmJjLCAweDIxZmZmY2VlLCAweDgyNWIxYmZkLCAweDkyNTVjNWVkLCAweDEyNTdhMjQwLFxuICAgIDB4NGUxYTgzMDIsIDB4YmFlMDdmZmYsIDB4NTI4MjQ2ZTcsIDB4OGU1NzE0MGUsIDB4MzM3M2Y3YmYsIDB4OGM5ZjgxODgsIDB4YTZmYzRlZTgsIDB4Yzk4MmI1YTUsXG4gICAgMHhhOGMwMWRiNywgMHg1NzlmYzI2NCwgMHg2NzA5NGYzMSwgMHhmMmJkM2Y1ZiwgMHg0MGZmZjdjMSwgMHgxZmI3OGRmYywgMHg4ZTZiZDJjMSwgMHg0MzdiZTU5YixcbiAgICAweDk5YjAzZGJmLCAweGI1ZGJjNjRiLCAweDYzOGRjMGU2LCAweDU1ODE5ZDk5LCAweGExOTdjODFjLCAweDRhMDEyZDZlLCAweGM1ODg0YTI4LCAweGNjYzM2ZjcxLFxuICAgIDB4Yjg0M2MyMTMsIDB4NmMwNzQzZjEsIDB4ODMwOTg5M2MsIDB4MGZlZGRkNWYsIDB4MmY3ZmU4NTAsIDB4ZDdjMDdmN2UsIDB4MDI1MDdmYmYsIDB4NWFmYjlhMDQsXG4gICAgMHhhNzQ3ZDJkMCwgMHgxNjUxMTkyZSwgMHhhZjcwYmYzZSwgMHg1OGMzMTM4MCwgMHg1Zjk4MzAyZSwgMHg3MjdjYzNjNCwgMHgwYTBmYjQwMiwgMHgwZjdmZWY4MixcbiAgICAweDhjOTZmZGFkLCAweDVkMmMyYWFlLCAweDhlZTk5YTQ5LCAweDUwZGE4OGI4LCAweDg0MjdmNGEwLCAweDFlYWM1NzkwLCAweDc5NmZiNDQ5LCAweDgyNTJkYzE1LFxuICAgIDB4ZWZiZDdkOWIsIDB4YTY3MjU5N2QsIDB4YWRhODQwZDgsIDB4NDVmNTQ1MDQsIDB4ZmE1ZDc0MDMsIDB4ZTgzZWMzMDUsIDB4NGY5MTc1MWEsIDB4OTI1NjY5YzIsXG4gICAgMHgyM2VmZTk0MSwgMHhhOTAzZjEyZSwgMHg2MDI3MGRmMiwgMHgwMjc2ZTRiNiwgMHg5NGZkNjU3NCwgMHg5Mjc5ODViMiwgMHg4Mjc2ZGJjYiwgMHgwMjc3ODE3NixcbiAgICAweGY4YWY5MThkLCAweDRlNDhmNzllLCAweDhmNjE2ZGRmLCAweGUyOWQ4NDBlLCAweDg0MmY3ZDgzLCAweDM0MGNlNWM4LCAweDk2YmJiNjgyLCAweDkzYjRiMTQ4LFxuICAgIDB4ZWYzMDNjYWIsIDB4OTg0ZmFmMjgsIDB4Nzc5ZmFmOWIsIDB4OTJkYzU2MGQsIDB4MjI0ZDFlMjAsIDB4ODQzN2FhODgsIDB4N2QyOWRjOTYsIDB4Mjc1NmQzZGMsXG4gICAgMHg4YjkwN2NlZSwgMHhiNTFmZDI0MCwgMHhlN2MwN2NlMywgMHhlNTY2YjRhMSwgMHhjM2U5NjE1ZSwgMHgzY2Y4MjA5ZCwgMHg2MDk0ZDFlMywgMHhjZDljYTM0MSxcbiAgICAweDVjNzY0NjBlLCAweDAwZWE5ODNiLCAweGQ0ZDY3ODgxLCAweGZkNDc1NzJjLCAweGY3NmNlZGQ5LCAweGJkYTgyMjljLCAweDEyN2RhZGFhLCAweDQzOGEwNzRlLFxuICAgIDB4MWY5N2MwOTAsIDB4MDgxYmRiOGEsIDB4OTNhMDdlYmUsIDB4YjkzOGNhMTUsIDB4OTdiMDNjZmYsIDB4M2RjMmMwZjgsIDB4OGQxYWIyZWMsIDB4NjQzODBlNTEsXG4gICAgMHg2OGNjN2JmYiwgMHhkOTBmMjc4OCwgMHgxMjQ5MDE4MSwgMHg1ZGU1ZmZkNCwgMHhkZDdlZjg2YSwgMHg3NmEyZTIxNCwgMHhiOWE0MDM2OCwgMHg5MjVkOTU4ZixcbiAgICAweDRiMzlmZmZhLCAweGJhMzlhZWU5LCAweGE0ZmZkMzBiLCAweGZhZjc5MzNiLCAweDZkNDk4NjIzLCAweDE5M2NiY2ZhLCAweDI3NjI3NTQ1LCAweDgyNWNmNDdhLFxuICAgIDB4NjFiZDhiYTAsIDB4ZDExZTQyZDEsIDB4Y2VhZDA0ZjQsIDB4MTI3ZWEzOTIsIDB4MTA0MjhkYjcsIDB4ODI3MmE5NzIsIDB4OTI3MGM0YTgsIDB4MTI3ZGU1MGIsXG4gICAgMHgyODViYTFjOCwgMHgzYzYyZjQ0ZiwgMHgzNWMwZWFhNSwgMHhlODA1ZDIzMSwgMHg0Mjg5MjlmYiwgMHhiNGZjZGY4MiwgMHg0ZmI2NmE1MywgMHgwZTdkYzE1YixcbiAgICAweDFmMDgxZmFiLCAweDEwODYxOGFlLCAweGZjZmQwODZkLCAweGY5ZmYyODg5LCAweDY5NGJjYzExLCAweDIzNmE1Y2FlLCAweDEyZGVjYTRkLCAweDJjM2Y4Y2M1LFxuICAgIDB4ZDJkMDJkZmUsIDB4ZjhlZjU4OTYsIDB4ZTRjZjUyZGEsIDB4OTUxNTViNjcsIDB4NDk0YTQ4OGMsIDB4YjliNmE4MGMsIDB4NWM4ZjgyYmMsIDB4ODlkMzZiNDUsXG4gICAgMHgzYTYwOTQzNywgMHhlYzAwYzlhOSwgMHg0NDcxNTI1MywgMHgwYTg3NGI0OSwgMHhkNzczYmM0MCwgMHg3YzM0NjcxYywgMHgwMjcxN2VmNiwgMHg0ZmViNTUzNixcbiAgICAweGEyZDAyZmZmLCAweGQyYmY2MGM0LCAweGQ0M2YwM2MwLCAweDUwYjRlZjZkLCAweDA3NDc4Y2QxLCAweDAwNmUxODg4LCAweGEyZTUzZjU1LCAweGI5ZTZkNGJjLFxuICAgIDB4YTIwNDgwMTYsIDB4OTc1NzM4MzMsIDB4ZDcyMDdkNjcsIDB4ZGUwZjhmM2QsIDB4NzJmODdiMzMsIDB4YWJjYzRmMzMsIDB4NzY4OGM1NWQsIDB4N2IwMGE2YjAsXG4gICAgMHg5NDdiMDAwMSwgMHg1NzAwNzVkMiwgMHhmOWJiODhmOCwgMHg4OTQyMDE5ZSwgMHg0MjY0YTVmZiwgMHg4NTYzMDJlMCwgMHg3MmRiZDkyYiwgMHhlZTk3MWI2OSxcbiAgICAweDZlYTIyZmRlLCAweDVmMDhhZTJiLCAweGFmN2E2MTZkLCAweGU1Yzk4NzY3LCAweGNmMWZlYmQyLCAweDYxZWZjOGMyLCAweGYxYWMyNTcxLCAweGNjODIzOWMyLFxuICAgIDB4NjcyMTRjYjgsIDB4YjFlNTgzZDEsIDB4YjdkYzNlNjIsIDB4N2YxMGJkY2UsIDB4ZjkwYTVjMzgsIDB4MGZmMDQ0M2QsIDB4NjA2ZTZkYzYsIDB4NjA1NDNhNDksXG4gICAgMHg1NzI3YzE0OCwgMHgyYmU5OGExZCwgMHg4YWI0MTczOCwgMHgyMGUxYmUyNCwgMHhhZjk2ZGEwZiwgMHg2ODQ1ODQyNSwgMHg5OTgzM2JlNSwgMHg2MDBkNDU3ZCxcbiAgICAweDI4MmY5MzUwLCAweDgzMzRiMzYyLCAweGQ5MWQxMTIwLCAweDJiNmQ4ZGEwLCAweDY0MmIxZTMxLCAweDljMzA1YTAwLCAweDUyYmNlNjg4LCAweDFiMDM1ODhhLFxuICAgIDB4ZjdiYWVmZDUsIDB4NDE0MmVkOWMsIDB4YTQzMTVjMTEsIDB4ODMzMjNlYzUsIDB4ZGZlZjQ2MzYsIDB4YTEzM2M1MDEsIDB4ZTlkMzUzMWMsIDB4ZWUzNTM3ODMpO1xuXG4gIHNCb3hbM10gPSBuZXcgQXJyYXkoXG4gICAgMHg5ZGIzMDQyMCwgMHgxZmI2ZTlkZSwgMHhhN2JlN2JlZiwgMHhkMjczYTI5OCwgMHg0YTRmN2JkYiwgMHg2NGFkOGM1NywgMHg4NTUxMDQ0MywgMHhmYTAyMGVkMSxcbiAgICAweDdlMjg3YWZmLCAweGU2MGZiNjYzLCAweDA5NWYzNWExLCAweDc5ZWJmMTIwLCAweGZkMDU5ZDQzLCAweDY0OTdiN2IxLCAweGYzNjQxZjYzLCAweDI0MWU0YWRmLFxuICAgIDB4MjgxNDdmNWYsIDB4NGZhMmI4Y2QsIDB4Yzk0MzAwNDAsIDB4MGNjMzIyMjAsIDB4ZmRkMzBiMzAsIDB4YzBhNTM3NGYsIDB4MWQyZDAwZDksIDB4MjQxNDdiMTUsXG4gICAgMHhlZTRkMTExYSwgMHgwZmNhNTE2NywgMHg3MWZmOTA0YywgMHgyZDE5NWZmZSwgMHgxYTA1NjQ1ZiwgMHgwYzEzZmVmZSwgMHgwODFiMDhjYSwgMHgwNTE3MDEyMSxcbiAgICAweDgwNTMwMTAwLCAweGU4M2U1ZWZlLCAweGFjOWFmNGY4LCAweDdmZTcyNzAxLCAweGQyYjhlZTVmLCAweDA2ZGY0MjYxLCAweGJiOWU5YjhhLCAweDcyOTNlYTI1LFxuICAgIDB4Y2U4NGZmZGYsIDB4ZjU3MTg4MDEsIDB4M2RkNjRiMDQsIDB4YTI2ZjI2M2IsIDB4N2VkNDg0MDAsIDB4NTQ3ZWViZTYsIDB4NDQ2ZDRjYTAsIDB4NmNmM2Q2ZjUsXG4gICAgMHgyNjQ5YWJkZiwgMHhhZWEwYzdmNSwgMHgzNjMzOGNjMSwgMHg1MDNmN2U5MywgMHhkMzc3MjA2MSwgMHgxMWI2MzhlMSwgMHg3MjUwMGUwMywgMHhmODBlYjJiYixcbiAgICAweGFiZTA1MDJlLCAweGVjOGQ3N2RlLCAweDU3OTcxZTgxLCAweGUxNGY2NzQ2LCAweGM5MzM1NDAwLCAweDY5MjAzMThmLCAweDA4MWRiYjk5LCAweGZmYzMwNGE1LFxuICAgIDB4NGQzNTE4MDUsIDB4N2YzZDVjZTMsIDB4YTZjODY2YzYsIDB4NWQ1YmNjYTksIDB4ZGFlYzZmZWEsIDB4OWY5MjZmOTEsIDB4OWY0NjIyMmYsIDB4Mzk5MTQ2N2QsXG4gICAgMHhhNWJmNmQ4ZSwgMHgxMTQzYzQ0ZiwgMHg0Mzk1ODMwMiwgMHhkMDIxNGVlYiwgMHgwMjIwODNiOCwgMHgzZmI2MTgwYywgMHgxOGY4OTMxZSwgMHgyODE2NThlNixcbiAgICAweDI2NDg2ZTNlLCAweDhiZDc4YTcwLCAweDc0NzdlNGMxLCAweGI1MDZlMDdjLCAweGYzMmQwYTI1LCAweDc5MDk4YjAyLCAweGU0ZWFiYjgxLCAweDI4MTIzYjIzLFxuICAgIDB4NjlkZWFkMzgsIDB4MTU3NGNhMTYsIDB4ZGY4NzFiNjIsIDB4MjExYzQwYjcsIDB4YTUxYTllZjksIDB4MDAxNDM3N2IsIDB4MDQxZThhYzgsIDB4MDkxMTQwMDMsXG4gICAgMHhiZDU5ZTRkMiwgMHhlM2QxNTZkNSwgMHg0ZmU4NzZkNSwgMHgyZjkxYTM0MCwgMHg1NTdiZThkZSwgMHgwMGVhZTRhNywgMHgwY2U1YzJlYywgMHg0ZGI0YmJhNixcbiAgICAweGU3NTZiZGZmLCAweGRkMzM2OWFjLCAweGVjMTdiMDM1LCAweDA2NTcyMzI3LCAweDk5YWZjOGIwLCAweDU2YzhjMzkxLCAweDZiNjU4MTFjLCAweDVlMTQ2MTE5LFxuICAgIDB4NmU4NWNiNzUsIDB4YmUwN2MwMDIsIDB4YzIzMjU1NzcsIDB4ODkzZmY0ZWMsIDB4NWJiZmM5MmQsIDB4ZDBlYzNiMjUsIDB4Yjc4MDFhYjcsIDB4OGQ2ZDNiMjQsXG4gICAgMHgyMGM3NjNlZiwgMHhjMzY2YTVmYywgMHg5YzM4Mjg4MCwgMHgwYWNlMzIwNSwgMHhhYWM5NTQ4YSwgMHhlY2ExZDdjNywgMHgwNDFhZmEzMiwgMHgxZDE2NjI1YSxcbiAgICAweDY3MDE5MDJjLCAweDliNzU3YTU0LCAweDMxZDQ3N2Y3LCAweDkxMjZiMDMxLCAweDM2Y2M2ZmRiLCAweGM3MGI4YjQ2LCAweGQ5ZTY2YTQ4LCAweDU2ZTU1YTc5LFxuICAgIDB4MDI2YTRjZWIsIDB4NTI0MzdlZmYsIDB4MmY4Zjc2YjQsIDB4MGRmOTgwYTUsIDB4ODY3NGNkZTMsIDB4ZWRkYTA0ZWIsIDB4MTdhOWJlMDQsIDB4MmMxOGY0ZGYsXG4gICAgMHhiNzc0N2Y5ZCwgMHhhYjJhZjdiNCwgMHhlZmMzNGQyMCwgMHgyZTA5NmI3YywgMHgxNzQxYTI1NCwgMHhlNWI2YTAzNSwgMHgyMTNkNDJmNiwgMHgyYzFjN2MyNixcbiAgICAweDYxYzJmNTBmLCAweDY1NTJkYWY5LCAweGQyYzIzMWY4LCAweDI1MTMwZjY5LCAweGQ4MTY3ZmEyLCAweDA0MThmMmM4LCAweDAwMWE5NmE2LCAweDBkMTUyNmFiLFxuICAgIDB4NjMzMTVjMjEsIDB4NWUwYTcyZWMsIDB4NDliYWZlZmQsIDB4MTg3OTA4ZDksIDB4OGQwZGJkODYsIDB4MzExMTcwYTcsIDB4M2U5YjY0MGMsIDB4Y2MzZTEwZDcsXG4gICAgMHhkNWNhZDNiNiwgMHgwY2FlYzM4OCwgMHhmNzMwMDFlMSwgMHg2YzcyOGFmZiwgMHg3MWVhZTJhMSwgMHgxZjlhZjM2ZSwgMHhjZmNiZDEyZiwgMHhjMWRlODQxNyxcbiAgICAweGFjMDdiZTZiLCAweGNiNDRhMWQ4LCAweDhiOWIwZjU2LCAweDAxMzk4OGMzLCAweGIxYzUyZmNhLCAweGI0YmUzMWNkLCAweGQ4NzgyODA2LCAweDEyYTNhNGUyLFxuICAgIDB4NmY3ZGU1MzIsIDB4NThmZDdlYjYsIDB4ZDAxZWU5MDAsIDB4MjRhZGZmYzIsIDB4ZjQ5OTBmYzUsIDB4OTcxMWFhYzUsIDB4MDAxZDdiOTUsIDB4ODJlNWU3ZDIsXG4gICAgMHgxMDk4NzNmNiwgMHgwMDYxMzA5NiwgMHhjMzJkOTUyMSwgMHhhZGExMjFmZiwgMHgyOTkwODQxNSwgMHg3ZmJiOTc3ZiwgMHhhZjllYjNkYiwgMHgyOWM5ZWQyYSxcbiAgICAweDVjZTJhNDY1LCAweGE3MzBmMzJjLCAweGQwYWEzZmU4LCAweDhhNWNjMDkxLCAweGQ0OWUyY2U3LCAweDBjZTQ1NGE5LCAweGQ2MGFjZDg2LCAweDAxNWYxOTE5LFxuICAgIDB4NzcwNzkxMDMsIDB4ZGVhMDNhZjYsIDB4NzhhODU2NWUsIDB4ZGVlMzU2ZGYsIDB4MjFmMDVjYmUsIDB4OGI3NWUzODcsIDB4YjNjNTA2NTEsIDB4YjhhNWMzZWYsXG4gICAgMHhkOGVlYjZkMiwgMHhlNTIzYmU3NywgMHhjMjE1NDUyOSwgMHgyZjY5ZWZkZiwgMHhhZmU2N2FmYiwgMHhmNDcwYzRiMiwgMHhmM2UwZWI1YiwgMHhkNmNjOTg3NixcbiAgICAweDM5ZTQ0NjBjLCAweDFmZGE4NTM4LCAweDE5ODc4MzJmLCAweGNhMDA3MzY3LCAweGE5OTE0NGY4LCAweDI5NmIyOTllLCAweDQ5MmZjMjk1LCAweDkyNjZiZWFiLFxuICAgIDB4YjU2NzZlNjksIDB4OWJkM2RkZGEsIDB4ZGY3ZTA1MmYsIDB4ZGIyNTcwMWMsIDB4MWI1ZTUxZWUsIDB4ZjY1MzI0ZTYsIDB4NmFmY2UzNmMsIDB4MDMxNmNjMDQsXG4gICAgMHg4NjQ0MjEzZSwgMHhiN2RjNTlkMCwgMHg3OTY1MjkxZiwgMHhjY2Q2ZmQ0MywgMHg0MTgyMzk3OSwgMHg5MzJiY2RmNiwgMHhiNjU3YzM0ZCwgMHg0ZWRmZDI4MixcbiAgICAweDdhZTUyOTBjLCAweDNjYjk1MzZiLCAweDg1MWUyMGZlLCAweDk4MzM1NTdlLCAweDEzZWNmMGIwLCAweGQzZmZiMzcyLCAweDNmODVjNWMxLCAweDBhZWY3ZWQyKTtcblxuICBzQm94WzRdID0gbmV3IEFycmF5KFxuICAgIDB4N2VjOTBjMDQsIDB4MmM2ZTc0YjksIDB4OWIwZTY2ZGYsIDB4YTYzMzc5MTEsIDB4Yjg2YTdmZmYsIDB4MWRkMzU4ZjUsIDB4NDRkZDlkNDQsIDB4MTczMTE2N2YsXG4gICAgMHgwOGZiZjFmYSwgMHhlN2Y1MTFjYywgMHhkMjA1MWIwMCwgMHg3MzVhYmEwMCwgMHgyYWI3MjJkOCwgMHgzODYzODFjYiwgMHhhY2Y2MjQzYSwgMHg2OWJlZmQ3YSxcbiAgICAweGU2YTJlNzdmLCAweGYwYzcyMGNkLCAweGM0NDk0ODE2LCAweGNjZjVjMTgwLCAweDM4ODUxNjQwLCAweDE1YjBhODQ4LCAweGU2OGIxOGNiLCAweDRjYWFkZWZmLFxuICAgIDB4NWY0ODBhMDEsIDB4MDQxMmIyYWEsIDB4MjU5ODE0ZmMsIDB4NDFkMGVmZTIsIDB4NGU0MGI0OGQsIDB4MjQ4ZWI2ZmIsIDB4OGRiYTFjZmUsIDB4NDFhOTliMDIsXG4gICAgMHgxYTU1MGEwNCwgMHhiYThmNjVjYiwgMHg3MjUxZjRlNywgMHg5NWE1MTcyNSwgMHhjMTA2ZWNkNywgMHg5N2E1OTgwYSwgMHhjNTM5YjlhYSwgMHg0ZDc5ZmU2YSxcbiAgICAweGYyZjNmNzYzLCAweDY4YWY4MDQwLCAweGVkMGM5ZTU2LCAweDExYjQ5NThiLCAweGUxZWI1YTg4LCAweDg3MDllNmIwLCAweGQ3ZTA3MTU2LCAweDRlMjlmZWE3LFxuICAgIDB4NjM2NmU1MmQsIDB4MDJkMWMwMDAsIDB4YzRhYzhlMDUsIDB4OTM3N2Y1NzEsIDB4MGMwNTM3MmEsIDB4NTc4NTM1ZjIsIDB4MjI2MWJlMDIsIDB4ZDY0MmEwYzksXG4gICAgMHhkZjEzYTI4MCwgMHg3NGI1NWJkMiwgMHg2ODIxOTljMCwgMHhkNDIxZTVlYywgMHg1M2ZiM2NlOCwgMHhjOGFkZWRiMywgMHgyOGE4N2ZjOSwgMHgzZDk1OTk4MSxcbiAgICAweDVjMWZmOTAwLCAweGZlMzhkMzk5LCAweDBjNGVmZjBiLCAweDA2MjQwN2VhLCAweGFhMmY0ZmIxLCAweDRmYjk2OTc2LCAweDkwYzc5NTA1LCAweGIwYThhNzc0LFxuICAgIDB4ZWY1NWExZmYsIDB4ZTU5Y2EyYzIsIDB4YTZiNjJkMjcsIDB4ZTY2YTQyNjMsIDB4ZGY2NTAwMWYsIDB4MGVjNTA5NjYsIDB4ZGZkZDU1YmMsIDB4MjlkZTA2NTUsXG4gICAgMHg5MTFlNzM5YSwgMHgxN2FmODk3NSwgMHgzMmM3OTExYywgMHg4OWY4OTQ2OCwgMHgwZDAxZTk4MCwgMHg1MjQ3NTVmNCwgMHgwM2I2M2NjOSwgMHgwY2M4NDRiMixcbiAgICAweGJjZjNmMGFhLCAweDg3YWMzNmU5LCAweGU1M2E3NDI2LCAweDAxYjNkODJiLCAweDFhOWU3NDQ5LCAweDY0ZWUyZDdlLCAweGNkZGJiMWRhLCAweDAxYzk0OTEwLFxuICAgIDB4Yjg2OGJmODAsIDB4MGQyNmYzZmQsIDB4OTM0MmVkZTcsIDB4MDRhNWMyODQsIDB4NjM2NzM3YjYsIDB4NTBmNWI2MTYsIDB4ZjI0NzY2ZTMsIDB4OGVjYTM2YzEsXG4gICAgMHgxMzZlMDVkYiwgMHhmZWYxODM5MSwgMHhmYjg4N2EzNywgMHhkNmU3ZjdkNCwgMHhjN2ZiN2RjOSwgMHgzMDYzZmNkZiwgMHhiNmY1ODlkZSwgMHhlYzI5NDFkYSxcbiAgICAweDI2ZTQ2Njk1LCAweGI3NTY2NDE5LCAweGY2NTRlZmM1LCAweGQwOGQ1OGI3LCAweDQ4OTI1NDAxLCAweGMxYmFjYjdmLCAweGU1ZmY1NTBmLCAweGI2MDgzMDQ5LFxuICAgIDB4NWJiNWQwZTgsIDB4ODdkNzJlNWEsIDB4YWI2YTZlZTEsIDB4MjIzYTY2Y2UsIDB4YzYyYmYzY2QsIDB4OWUwODg1ZjksIDB4NjhjYjNlNDcsIDB4MDg2YzAxMGYsXG4gICAgMHhhMjFkZTgyMCwgMHhkMThiNjlkZSwgMHhmM2Y2NTc3NywgMHhmYTAyYzNmNiwgMHg0MDdlZGFjMywgMHhjYmIzZDU1MCwgMHgxNzkzMDg0ZCwgMHhiMGQ3MGViYSxcbiAgICAweDBhYjM3OGQ1LCAweGQ5NTFmYjBjLCAweGRlZDdkYTU2LCAweDQxMjRiYmU0LCAweDk0Y2EwYjU2LCAweDBmNTc1NWQxLCAweGUwZTFlNTZlLCAweDYxODRiNWJlLFxuICAgIDB4NTgwYTI0OWYsIDB4OTRmNzRiYzAsIDB4ZTMyNzg4OGUsIDB4OWY3YjU1NjEsIDB4YzNkYzAyODAsIDB4MDU2ODc3MTUsIDB4NjQ2YzZiZDcsIDB4NDQ5MDRkYjMsXG4gICAgMHg2NmI0ZjBhMywgMHhjMGYxNjQ4YSwgMHg2OTdlZDVhZiwgMHg0OWU5MmZmNiwgMHgzMDllMzc0ZiwgMHgyY2I2MzU2YSwgMHg4NTgwODU3MywgMHg0OTkxZjg0MCxcbiAgICAweDc2ZjBhZTAyLCAweDA4M2JlODRkLCAweDI4NDIxYzlhLCAweDQ0NDg5NDA2LCAweDczNmU0Y2I4LCAweGMxMDkyOTEwLCAweDhiYzk1ZmM2LCAweDdkODY5Y2Y0LFxuICAgIDB4MTM0ZjYxNmYsIDB4MmU3NzExOGQsIDB4YjMxYjJiZTEsIDB4YWE5MGI0NzIsIDB4M2NhNWQ3MTcsIDB4N2QxNjFiYmEsIDB4OWNhZDkwMTAsIDB4YWY0NjJiYTIsXG4gICAgMHg5ZmU0NTlkMiwgMHg0NWQzNDU1OSwgMHhkOWYyZGExMywgMHhkYmM2NTQ4NywgMHhmM2U0Zjk0ZSwgMHgxNzZkNDg2ZiwgMHgwOTdjMTNlYSwgMHg2MzFkYTVjNyxcbiAgICAweDQ0NWY3MzgyLCAweDE3NTY4M2Y0LCAweGNkYzY2YTk3LCAweDcwYmUwMjg4LCAweGIzY2RjZjcyLCAweDZlNWRkMmYzLCAweDIwOTM2MDc5LCAweDQ1OWI4MGE1LFxuICAgIDB4YmU2MGUyZGIsIDB4YTljMjMxMDEsIDB4ZWJhNTMxNWMsIDB4MjI0ZTQyZjIsIDB4MWM1YzE1NzIsIDB4ZjY3MjFiMmMsIDB4MWFkMmZmZjMsIDB4OGMyNTQwNGUsXG4gICAgMHgzMjRlZDcyZiwgMHg0MDY3YjdmZCwgMHgwNTIzMTM4ZSwgMHg1Y2EzYmM3OCwgMHhkYzBmZDY2ZSwgMHg3NTkyMjI4MywgMHg3ODRkNmIxNywgMHg1OGViYjE2ZSxcbiAgICAweDQ0MDk0Zjg1LCAweDNmNDgxZDg3LCAweGZjZmVhZTdiLCAweDc3YjVmZjc2LCAweDhjMjMwMmJmLCAweGFhZjQ3NTU2LCAweDVmNDZiMDJhLCAweDJiMDkyODAxLFxuICAgIDB4M2QzOGY1ZjcsIDB4MGNhODFmMzYsIDB4NTJhZjRhOGEsIDB4NjZkNWU3YzAsIDB4ZGYzYjA4NzQsIDB4OTUwNTUxMTAsIDB4MWI1YWQ3YTgsIDB4ZjYxZWQ1YWQsXG4gICAgMHg2Y2Y2ZTQ3OSwgMHgyMDc1ODE4NCwgMHhkMGNlZmE2NSwgMHg4OGY3YmU1OCwgMHg0YTA0NjgyNiwgMHgwZmY2ZjhmMywgMHhhMDljN2Y3MCwgMHg1MzQ2YWJhMCxcbiAgICAweDVjZTk2YzI4LCAweGUxNzZlZGEzLCAweDZiYWMzMDdmLCAweDM3NjgyOWQyLCAweDg1MzYwZmE5LCAweDE3ZTNmZTJhLCAweDI0Yjc5NzY3LCAweGY1YTk2YjIwLFxuICAgIDB4ZDZjZDI1OTUsIDB4NjhmZjFlYmYsIDB4NzU1NTQ0MmMsIDB4ZjE5ZjA2YmUsIDB4ZjllMDY1OWEsIDB4ZWViOTQ5MWQsIDB4MzQwMTA3MTgsIDB4YmIzMGNhYjgsXG4gICAgMHhlODIyZmUxNSwgMHg4ODU3MDk4MywgMHg3NTBlNjI0OSwgMHhkYTYyN2U1NSwgMHg1ZTc2ZmZhOCwgMHhiMTUzNDU0NiwgMHg2ZDQ3ZGUwOCwgMHhlZmU5ZTdkNCk7XG5cbiAgc0JveFs1XSA9IG5ldyBBcnJheShcbiAgICAweGY2ZmE4ZjlkLCAweDJjYWM2Y2UxLCAweDRjYTM0ODY3LCAweGUyMzM3ZjdjLCAweDk1ZGIwOGU3LCAweDAxNjg0M2I0LCAweGVjZWQ1Y2JjLCAweDMyNTU1M2FjLFxuICAgIDB4YmY5ZjA5NjAsIDB4ZGZhMWUyZWQsIDB4ODNmMDU3OWQsIDB4NjNlZDg2YjksIDB4MWFiNmE2YjgsIDB4ZGU1ZWJlMzksIDB4ZjM4ZmY3MzIsIDB4ODk4OWIxMzgsXG4gICAgMHgzM2YxNDk2MSwgMHhjMDE5MzdiZCwgMHhmNTA2YzZkYSwgMHhlNDYyNWU3ZSwgMHhhMzA4ZWE5OSwgMHg0ZTIzZTMzYywgMHg3OWNiZDdjYywgMHg0OGExNDM2NyxcbiAgICAweGEzMTQ5NjE5LCAweGZlYzk0YmQ1LCAweGExMTQxNzRhLCAweGVhYTAxODY2LCAweGEwODRkYjJkLCAweDA5YTg0ODZmLCAweGE4ODg2MTRhLCAweDI5MDBhZjk4LFxuICAgIDB4MDE2NjU5OTEsIDB4ZTE5OTI4NjMsIDB4YzhmMzBjNjAsIDB4MmU3OGVmM2MsIDB4ZDBkNTE5MzIsIDB4Y2YwZmVjMTQsIDB4ZjdjYTA3ZDIsIDB4ZDBhODIwNzIsXG4gICAgMHhmZDQxMTk3ZSwgMHg5MzA1YTZiMCwgMHhlODZiZTNkYSwgMHg3NGJlZDNjZCwgMHgzNzJkYTUzYywgMHg0YzdmNDQ0OCwgMHhkYWI1ZDQ0MCwgMHg2ZGJhMGVjMyxcbiAgICAweDA4MzkxOWE3LCAweDlmYmFlZWQ5LCAweDQ5ZGJjZmIwLCAweDRlNjcwYzUzLCAweDVjM2Q5YzAxLCAweDY0YmRiOTQxLCAweDJjMGU2MzZhLCAweGJhN2RkOWNkLFxuICAgIDB4ZWE2ZjczODgsIDB4ZTcwYmM3NjIsIDB4MzVmMjlhZGIsIDB4NWM0Y2RkOGQsIDB4ZjBkNDhkOGMsIDB4Yjg4MTUzZTIsIDB4MDhhMTk4NjYsIDB4MWFlMmVhYzgsXG4gICAgMHgyODRjYWY4OSwgMHhhYTkyODIyMywgMHg5MzM0YmU1MywgMHgzYjNhMjFiZiwgMHgxNjQzNGJlMywgMHg5YWVhMzkwNiwgMHhlZmU4YzM2ZSwgMHhmODkwY2RkOSxcbiAgICAweDgwMjI2ZGFlLCAweGMzNDBhNGEzLCAweGRmN2U5YzA5LCAweGE2OTRhODA3LCAweDViN2M1ZWNjLCAweDIyMWRiM2E2LCAweDlhNjlhMDJmLCAweDY4ODE4YTU0LFxuICAgIDB4Y2ViMjI5NmYsIDB4NTNjMDg0M2EsIDB4ZmU4OTM2NTUsIDB4MjViZmU2OGEsIDB4YjQ2MjhhYmMsIDB4Y2YyMjJlYmYsIDB4MjVhYzZmNDgsIDB4YTlhOTkzODcsXG4gICAgMHg1M2JkZGI2NSwgMHhlNzZmZmJlNywgMHhlOTY3ZmQ3OCwgMHgwYmE5MzU2MywgMHg4ZTM0MmJjMSwgMHhlOGExMWJlOSwgMHg0OTgwNzQwZCwgMHhjODA4N2RmYyxcbiAgICAweDhkZTRiZjk5LCAweGExMTEwMWEwLCAweDdmZDM3OTc1LCAweGRhNWEyNmMwLCAweGU4MWY5OTRmLCAweDk1MjhjZDg5LCAweGZkMzM5ZmVkLCAweGI4NzgzNGJmLFxuICAgIDB4NWYwNDQ1NmQsIDB4MjIyNTg2OTgsIDB4YzljNGM4M2IsIDB4MmRjMTU2YmUsIDB4NGY2MjhkYWEsIDB4NTdmNTVlYzUsIDB4ZTIyMjBhYmUsIDB4ZDI5MTZlYmYsXG4gICAgMHg0ZWM3NWI5NSwgMHgyNGYyYzNjMCwgMHg0MmQxNWQ5OSwgMHhjZDBkN2ZhMCwgMHg3YjZlMjdmZiwgMHhhOGRjOGFmMCwgMHg3MzQ1YzEwNiwgMHhmNDFlMjMyZixcbiAgICAweDM1MTYyMzg2LCAweGU2ZWE4OTI2LCAweDMzMzNiMDk0LCAweDE1N2VjNmYyLCAweDM3MmI3NGFmLCAweDY5MjU3M2U0LCAweGU5YTlkODQ4LCAweGYzMTYwMjg5LFxuICAgIDB4M2E2MmVmMWQsIDB4YTc4N2UyMzgsIDB4ZjNhNWY2NzYsIDB4NzQzNjQ4NTMsIDB4MjA5NTEwNjMsIDB4NDU3NjY5OGQsIDB4YjZmYWQ0MDcsIDB4NTkyYWY5NTAsXG4gICAgMHgzNmY3MzUyMywgMHg0Y2ZiNmU4NywgMHg3ZGE0Y2VjMCwgMHg2YzE1MmRhYSwgMHhjYjAzOTZhOCwgMHhjNTBkZmU1ZCwgMHhmY2Q3MDdhYiwgMHgwOTIxYzQyZixcbiAgICAweDg5ZGZmMGJiLCAweDVmZTJiZTc4LCAweDQ0OGY0ZjMzLCAweDc1NDYxM2M5LCAweDJiMDVkMDhkLCAweDQ4YjlkNTg1LCAweGRjMDQ5NDQxLCAweGM4MDk4ZjliLFxuICAgIDB4N2RlZGU3ODYsIDB4YzM5YTMzNzMsIDB4NDI0MTAwMDUsIDB4NmEwOTE3NTEsIDB4MGVmM2M4YTYsIDB4ODkwMDcyZDYsIDB4MjgyMDc2ODIsIDB4YTlhOWY3YmUsXG4gICAgMHhiZjMyNjc5ZCwgMHhkNDViNWI3NSwgMHhiMzUzZmQwMCwgMHhjYmIwZTM1OCwgMHg4MzBmMjIwYSwgMHgxZjhmYjIxNCwgMHhkMzcyY2YwOCwgMHhjYzNjNGExMyxcbiAgICAweDhjZjYzMTY2LCAweDA2MWM4N2JlLCAweDg4Yzk4Zjg4LCAweDYwNjJlMzk3LCAweDQ3Y2Y4ZTdhLCAweGI2Yzg1MjgzLCAweDNjYzJhY2ZiLCAweDNmYzA2OTc2LFxuICAgIDB4NGU4ZjAyNTIsIDB4NjRkODMxNGQsIDB4ZGEzODcwZTMsIDB4MWU2NjU0NTksIDB4YzEwOTA4ZjAsIDB4NTEzMDIxYTUsIDB4NmM1YjY4YjcsIDB4ODIyZjhhYTAsXG4gICAgMHgzMDA3Y2QzZSwgMHg3NDcxOWVlZiwgMHhkYzg3MjY4MSwgMHgwNzMzNDBkNCwgMHg3ZTQzMmZkOSwgMHgwYzVlYzI0MSwgMHg4ODA5Mjg2YywgMHhmNTkyZDg5MSxcbiAgICAweDA4YTkzMGY2LCAweDk1N2VmMzA1LCAweGI3ZmJmZmJkLCAweGMyNjZlOTZmLCAweDZmZTRhYzk4LCAweGIxNzNlY2MwLCAweGJjNjBiNDJhLCAweDk1MzQ5OGRhLFxuICAgIDB4ZmJhMWFlMTIsIDB4MmQ0YmQ3MzYsIDB4MGYyNWZhYWIsIDB4YTRmM2ZjZWIsIDB4ZTI5NjkxMjMsIDB4MjU3ZjBjM2QsIDB4OTM0OGFmNDksIDB4MzYxNDAwYmMsXG4gICAgMHhlODgxNmY0YSwgMHgzODE0ZjIwMCwgMHhhM2Y5NDA0MywgMHg5YzdhNTRjMiwgMHhiYzcwNGY1NywgMHhkYTQxZTdmOSwgMHhjMjVhZDMzYSwgMHg1NGY0YTA4NCxcbiAgICAweGIxN2Y1NTA1LCAweDU5MzU3Y2JlLCAweGVkYmQxNWM4LCAweDdmOTdjNWFiLCAweGJhNWFjN2I1LCAweGI2ZjZkZWFmLCAweDNhNDc5YzNhLCAweDUzMDJkYTI1LFxuICAgIDB4NjUzZDdlNmEsIDB4NTQyNjhkNDksIDB4NTFhNDc3ZWEsIDB4NTAxN2Q1NWIsIDB4ZDdkMjVkODgsIDB4NDQxMzZjNzYsIDB4MDQwNGE4YzgsIDB4YjhlNWExMjEsXG4gICAgMHhiODFhOTI4YSwgMHg2MGVkNTg2OSwgMHg5N2M1NWI5NiwgMHhlYWVjOTkxYiwgMHgyOTkzNTkxMywgMHgwMWZkYjdmMSwgMHgwODhlOGRmYSwgMHg5YWI2ZjZmNSxcbiAgICAweDNiNGNiZjlmLCAweDRhNWRlM2FiLCAweGU2MDUxZDM1LCAweGEwZTFkODU1LCAweGQzNmI0Y2YxLCAweGY1NDRlZGViLCAweGIwZTkzNTI0LCAweGJlYmI4ZmJkLFxuICAgIDB4YTJkNzYyY2YsIDB4NDljOTJmNTQsIDB4MzhiNWYzMzEsIDB4NzEyOGE0NTQsIDB4NDgzOTI5MDUsIDB4YTY1YjFkYjgsIDB4ODUxYzk3YmQsIDB4ZDY3NWNmMmYpO1xuXG4gIHNCb3hbNl0gPSBuZXcgQXJyYXkoXG4gICAgMHg4NWUwNDAxOSwgMHgzMzJiZjU2NywgMHg2NjJkYmZmZiwgMHhjZmM2NTY5MywgMHgyYThkN2Y2ZiwgMHhhYjliYzkxMiwgMHhkZTYwMDhhMSwgMHgyMDI4ZGExZixcbiAgICAweDAyMjdiY2U3LCAweDRkNjQyOTE2LCAweDE4ZmFjMzAwLCAweDUwZjE4YjgyLCAweDJjYjJjYjExLCAweGIyMzJlNzVjLCAweDRiMzY5NWYyLCAweGIyODcwN2RlLFxuICAgIDB4YTA1ZmJjZjYsIDB4Y2Q0MTgxZTksIDB4ZTE1MDIxMGMsIDB4ZTI0ZWYxYmQsIDB4YjE2OGMzODEsIDB4ZmRlNGU3ODksIDB4NWM3OWIwZDgsIDB4MWU4YmZkNDMsXG4gICAgMHg0ZDQ5NTAwMSwgMHgzOGJlNDM0MSwgMHg5MTNjZWUxZCwgMHg5MmE3OWMzZiwgMHgwODk3NjZiZSwgMHhiYWVlYWRmNCwgMHgxMjg2YmVjZiwgMHhiNmVhY2IxOSxcbiAgICAweDI2NjBjMjAwLCAweDc1NjViZGU0LCAweDY0MjQxZjdhLCAweDgyNDhkY2E5LCAweGMzYjNhZDY2LCAweDI4MTM2MDg2LCAweDBiZDhkZmE4LCAweDM1NmQxY2YyLFxuICAgIDB4MTA3Nzg5YmUsIDB4YjNiMmU5Y2UsIDB4MDUwMmFhOGYsIDB4MGJjMDM1MWUsIDB4MTY2YmY1MmEsIDB4ZWIxMmZmODIsIDB4ZTM0ODY5MTEsIDB4ZDM0ZDc1MTYsXG4gICAgMHg0ZTdiM2FmZiwgMHg1ZjQzNjcxYiwgMHg5Y2Y2ZTAzNywgMHg0OTgxYWM4MywgMHgzMzQyNjZjZSwgMHg4YzkzNDFiNywgMHhkMGQ4NTRjMCwgMHhjYjNhNmM4OCxcbiAgICAweDQ3YmMyODI5LCAweDQ3MjViYTM3LCAweGE2NmFkMjJiLCAweDdhZDYxZjFlLCAweDBjNWNiYWZhLCAweDQ0MzdmMTA3LCAweGI2ZTc5OTYyLCAweDQyZDJkODE2LFxuICAgIDB4MGE5NjEyODgsIDB4ZTFhNWMwNmUsIDB4MTM3NDllNjcsIDB4NzJmYzA4MWEsIDB4YjFkMTM5ZjcsIDB4Zjk1ODM3NDUsIDB4Y2YxOWRmNTgsIDB4YmVjM2Y3NTYsXG4gICAgMHhjMDZlYmEzMCwgMHgwNzIxMWIyNCwgMHg0NWMyODgyOSwgMHhjOTVlMzE3ZiwgMHhiYzhlYzUxMSwgMHgzOGJjNDZlOSwgMHhjNmU2ZmExNCwgMHhiYWU4NTg0YSxcbiAgICAweGFkNGViYzQ2LCAweDQ2OGY1MDhiLCAweDc4Mjk0MzVmLCAweGYxMjQxODNiLCAweDgyMWRiYTlmLCAweGFmZjYwZmY0LCAweGVhMmM0ZTZkLCAweDE2ZTM5MjY0LFxuICAgIDB4OTI1NDRhOGIsIDB4MDA5YjRmYzMsIDB4YWJhNjhjZWQsIDB4OWFjOTZmNzgsIDB4MDZhNWI3OWEsIDB4YjI4NTZlNmUsIDB4MWFlYzNjYTksIDB4YmU4Mzg2ODgsXG4gICAgMHgwZTA4MDRlOSwgMHg1NWYxYmU1NiwgMHhlN2U1MzYzYiwgMHhiM2ExZjI1ZCwgMHhmN2RlYmI4NSwgMHg2MWZlMDMzYywgMHgxNjc0NjIzMywgMHgzYzAzNGMyOCxcbiAgICAweGRhNmQwYzc0LCAweDc5YWFjNTZjLCAweDNjZTRlMWFkLCAweDUxZjBjODAyLCAweDk4ZjhmMzVhLCAweDE2MjZhNDlmLCAweGVlZDgyYjI5LCAweDFkMzgyZmUzLFxuICAgIDB4MGM0ZmI5OWEsIDB4YmIzMjU3NzgsIDB4M2VjNmQ5N2IsIDB4NmU3N2E2YTksIDB4Y2I2NThiNWMsIDB4ZDQ1MjMwYzcsIDB4MmJkMTQwOGIsIDB4NjBjMDNlYjcsXG4gICAgMHhiOTA2OGQ3OCwgMHhhMzM3NTRmNCwgMHhmNDMwYzg3ZCwgMHhjOGE3MTMwMiwgMHhiOTZkOGMzMiwgMHhlYmQ0ZTdiZSwgMHhiZThiOWQyZCwgMHg3OTc5ZmIwNixcbiAgICAweGU3MjI1MzA4LCAweDhiNzVjZjc3LCAweDExZWY4ZGE0LCAweGUwODNjODU4LCAweDhkNmI3ODZmLCAweDVhNjMxN2E2LCAweGZhNWNmN2EwLCAweDVkZGEwMDMzLFxuICAgIDB4ZjI4ZWJmYjAsIDB4ZjViOWMzMTAsIDB4YTBlYWMyODAsIDB4MDhiOTc2N2EsIDB4YTNkOWQyYjAsIDB4NzlkMzQyMTcsIDB4MDIxYTcxOGQsIDB4OWFjNjMzNmEsXG4gICAgMHgyNzExZmQ2MCwgMHg0MzgwNTBlMywgMHgwNjk5MDhhOCwgMHgzZDdmZWRjNCwgMHg4MjZkMmJlZiwgMHg0ZWViODQ3NiwgMHg0ODhkY2YyNSwgMHgzNmM5ZDU2NixcbiAgICAweDI4ZTc0ZTQxLCAweGMyNjEwYWNhLCAweDNkNDlhOWNmLCAweGJhZTNiOWRmLCAweGI2NWY4ZGU2LCAweDkyYWVhZjY0LCAweDNhYzdkNWU2LCAweDllYTgwNTA5LFxuICAgIDB4ZjIyYjAxN2QsIDB4YTQxNzNmNzAsIDB4ZGQxZTE2YzMsIDB4MTVlMGQ3ZjksIDB4NTBiMWI4ODcsIDB4MmI5ZjRmZDUsIDB4NjI1YWJhODIsIDB4NmEwMTc5NjIsXG4gICAgMHgyZWMwMWI5YywgMHgxNTQ4OGFhOSwgMHhkNzE2ZTc0MCwgMHg0MDA1NWEyYywgMHg5M2QyOWEyMiwgMHhlMzJkYmY5YSwgMHgwNTg3NDViOSwgMHgzNDUzZGMxZSxcbiAgICAweGQ2OTkyOTZlLCAweDQ5NmNmZjZmLCAweDFjOWY0OTg2LCAweGRmZTJlZDA3LCAweGI4NzI0MmQxLCAweDE5ZGU3ZWFlLCAweDA1M2U1NjFhLCAweDE1YWQ2ZjhjLFxuICAgIDB4NjY2MjZjMWMsIDB4NzE1NGMyNGMsIDB4ZWEwODJiMmEsIDB4OTNlYjI5MzksIDB4MTdkY2IwZjAsIDB4NThkNGYyYWUsIDB4OWVhMjk0ZmIsIDB4NTJjZjU2NGMsXG4gICAgMHg5ODgzZmU2NiwgMHgyZWM0MDU4MSwgMHg3NjM5NTNjMywgMHgwMWQ2NjkyZSwgMHhkM2EwYzEwOCwgMHhhMWU3MTYwZSwgMHhlNGYyZGZhNiwgMHg2OTNlZDI4NSxcbiAgICAweDc0OTA0Njk4LCAweDRjMmIwZWRkLCAweDRmNzU3NjU2LCAweDVkMzkzMzc4LCAweGExMzIyMzRmLCAweDNkMzIxYzVkLCAweGMzZjVlMTk0LCAweDRiMjY5MzAxLFxuICAgIDB4Yzc5ZjAyMmYsIDB4M2M5OTdlN2UsIDB4NWU0Zjk1MDQsIDB4M2ZmYWZiYmQsIDB4NzZmN2FkMGUsIDB4Mjk2NjkzZjQsIDB4M2QxZmNlNmYsIDB4YzYxZTQ1YmUsXG4gICAgMHhkM2I1YWIzNCwgMHhmNzJiZjliNywgMHgxYjA0MzRjMCwgMHg0ZTcyYjU2NywgMHg1NTkyYTMzZCwgMHhiNTIyOTMwMSwgMHhjZmQyYTg3ZiwgMHg2MGFlYjc2NyxcbiAgICAweDE4MTQzODZiLCAweDMwYmNjMzNkLCAweDM4YTBjMDdkLCAweGZkMTYwNmYyLCAweGMzNjM1MTliLCAweDU4OWRkMzkwLCAweDU0NzlmOGU2LCAweDFjYjhkNjQ3LFxuICAgIDB4OTdmZDYxYTksIDB4ZWE3NzU5ZjQsIDB4MmQ1NzUzOWQsIDB4NTY5YTU4Y2YsIDB4ZTg0ZTYzYWQsIDB4NDYyZTFiNzgsIDB4NjU4MGY4N2UsIDB4ZjM4MTc5MTQsXG4gICAgMHg5MWRhNTVmNCwgMHg0MGEyMzBmMywgMHhkMTk4OGYzNSwgMHhiNmUzMThkMiwgMHgzZmZhNTBiYywgMHgzZDQwZjAyMSwgMHhjM2MwYmRhZSwgMHg0OTU4YzI0YyxcbiAgICAweDUxOGYzNmIyLCAweDg0YjFkMzcwLCAweDBmZWRjZTgzLCAweDg3OGRkYWRhLCAweGYyYTI3OWM3LCAweDk0ZTAxYmU4LCAweDkwNzE2ZjRiLCAweDk1NGI4YWEzKTtcblxuICBzQm94WzddID0gbmV3IEFycmF5KFxuICAgIDB4ZTIxNjMwMGQsIDB4YmJkZGZmZmMsIDB4YTdlYmRhYmQsIDB4MzU2NDgwOTUsIDB4Nzc4OWY4YjcsIDB4ZTZjMTEyMWIsIDB4MGUyNDE2MDAsIDB4MDUyY2U4YjUsXG4gICAgMHgxMWE5Y2ZiMCwgMHhlNTk1MmYxMSwgMHhlY2U3OTkwYSwgMHg5Mzg2ZDE3NCwgMHgyYTQyOTMxYywgMHg3NmUzODExMSwgMHhiMTJkZWYzYSwgMHgzN2RkZGRmYyxcbiAgICAweGRlOWFkZWIxLCAweDBhMGNjMzJjLCAweGJlMTk3MDI5LCAweDg0YTAwOTQwLCAweGJiMjQzYTBmLCAweGI0ZDEzN2NmLCAweGI0NGU3OWYwLCAweDA0OWVlZGZkLFxuICAgIDB4MGIxNWExNWQsIDB4NDgwZDMxNjgsIDB4OGJiYmRlNWEsIDB4NjY5ZGVkNDIsIDB4YzdlY2U4MzEsIDB4M2Y4Zjk1ZTcsIDB4NzJkZjE5MWIsIDB4NzU4MDMzMGQsXG4gICAgMHg5NDA3NDI1MSwgMHg1YzdkY2RmYSwgMHhhYmJlNmQ2MywgMHhhYTQwMjE2NCwgMHhiMzAxZDQwYSwgMHgwMmU3ZDFjYSwgMHg1MzU3MWRhZSwgMHg3YTMxODJhMixcbiAgICAweDEyYThkZGVjLCAweGZkYWEzMzVkLCAweDE3NmY0M2U4LCAweDcxZmI0NmQ0LCAweDM4MTI5MDIyLCAweGNlOTQ5YWQ0LCAweGI4NDc2OWFkLCAweDk2NWJkODYyLFxuICAgIDB4ODJmM2QwNTUsIDB4NjZmYjk3NjcsIDB4MTViODBiNGUsIDB4MWQ1YjQ3YTAsIDB4NGNmZGUwNmYsIDB4YzI4ZWM0YjgsIDB4NTdlODcyNmUsIDB4NjQ3YTc4ZmMsXG4gICAgMHg5OTg2NWQ0NCwgMHg2MDhiZDU5MywgMHg2YzIwMGUwMywgMHgzOWRjNWZmNiwgMHg1ZDBiMDBhMywgMHhhZTYzYWZmMiwgMHg3ZThiZDYzMiwgMHg3MDEwOGMwYyxcbiAgICAweGJiZDM1MDQ5LCAweDI5OThkZjA0LCAweDk4MGNmNDJhLCAweDliNmRmNDkxLCAweDllN2VkZDUzLCAweDA2OTE4NTQ4LCAweDU4Y2I3ZTA3LCAweDNiNzRlZjJlLFxuICAgIDB4NTIyZmZmYjEsIDB4ZDI0NzA4Y2MsIDB4MWM3ZTI3Y2QsIDB4YTRlYjIxNWIsIDB4M2NmMWQyZTIsIDB4MTliNDdhMzgsIDB4NDI0Zjc2MTgsIDB4MzU4NTYwMzksXG4gICAgMHg5ZDE3ZGVlNywgMHgyN2ViMzVlNiwgMHhjOWFmZjY3YiwgMHgzNmJhZjViOCwgMHgwOWM0NjdjZCwgMHhjMTg5MTBiMSwgMHhlMTFkYmY3YiwgMHgwNmNkMWFmOCxcbiAgICAweDcxNzBjNjA4LCAweDJkNWUzMzU0LCAweGQ0ZGU0OTVhLCAweDY0YzZkMDA2LCAweGJjYzBjNjJjLCAweDNkZDAwZGIzLCAweDcwOGY4ZjM0LCAweDc3ZDUxYjQyLFxuICAgIDB4MjY0ZjYyMGYsIDB4MjRiOGQyYmYsIDB4MTVjMWI3OWUsIDB4NDZhNTI1NjQsIDB4ZjhkN2U1NGUsIDB4M2UzNzgxNjAsIDB4Nzg5NWNkYTUsIDB4ODU5YzE1YTUsXG4gICAgMHhlNjQ1OTc4OCwgMHhjMzdiYzc1ZiwgMHhkYjA3YmEwYywgMHgwNjc2YTNhYiwgMHg3ZjIyOWIxZSwgMHgzMTg0MmU3YiwgMHgyNDI1OWZkNywgMHhmOGJlZjQ3MixcbiAgICAweDgzNWZmY2I4LCAweDZkZjRjMWYyLCAweDk2ZjViMTk1LCAweGZkMGFmMGZjLCAweGIwZmUxMzRjLCAweGUyNTA2ZDNkLCAweDRmOWIxMmVhLCAweGYyMTVmMjI1LFxuICAgIDB4YTIyMzczNmYsIDB4OWZiNGM0MjgsIDB4MjVkMDQ5NzksIDB4MzRjNzEzZjgsIDB4YzQ2MTgxODcsIDB4ZWE3YTZlOTgsIDB4N2NkMTZlZmMsIDB4MTQzNjg3NmMsXG4gICAgMHhmMTU0NDEwNywgMHhiZWRlZWUxNCwgMHg1NmU5YWYyNywgMHhhMDRhYTQ0MSwgMHgzY2Y3Yzg5OSwgMHg5MmVjYmFlNiwgMHhkZDY3MDE2ZCwgMHgxNTE2ODJlYixcbiAgICAweGE4NDJlZWRmLCAweGZkYmE2MGI0LCAweGYxOTA3Yjc1LCAweDIwZTMwMzBmLCAweDI0ZDhjMjllLCAweGUxMzk2NzNiLCAweGVmYTYzZmI4LCAweDcxODczMDU0LFxuICAgIDB4YjZmMmNmM2IsIDB4OWYzMjY0NDIsIDB4Y2IxNWE0Y2MsIDB4YjAxYTQ1MDQsIDB4ZjFlNDdkOGQsIDB4ODQ0YTFiZTUsIDB4YmFlN2RmZGMsIDB4NDJjYmRhNzAsXG4gICAgMHhjZDdkYWUwYSwgMHg1N2U4NWI3YSwgMHhkNTNmNWFmNiwgMHgyMGNmNGQ4YywgMHhjZWE0ZDQyOCwgMHg3OWQxMzBhNCwgMHgzNDg2ZWJmYiwgMHgzM2QzY2RkYyxcbiAgICAweDc3ODUzYjUzLCAweDM3ZWZmY2I1LCAweGM1MDY4Nzc4LCAweGU1ODBiM2U2LCAweDRlNjhiOGY0LCAweGM1YzhiMzdlLCAweDBkODA5ZWEyLCAweDM5OGZlYjdjLFxuICAgIDB4MTMyYTRmOTQsIDB4NDNiNzk1MGUsIDB4MmZlZTdkMWMsIDB4MjIzNjEzYmQsIDB4ZGQwNmNhYTIsIDB4MzdkZjkzMmIsIDB4YzQyNDgyODksIDB4YWNmM2ViYzMsXG4gICAgMHg1NzE1ZjZiNywgMHhlZjM0NzhkZCwgMHhmMjY3NjE2ZiwgMHhjMTQ4Y2JlNCwgMHg5MDUyODE1ZSwgMHg1ZTQxMGZhYiwgMHhiNDhhMjQ2NSwgMHgyZWRhN2ZhNCxcbiAgICAweGU4N2I0MGU0LCAweGU5OGVhMDg0LCAweDU4ODllOWUxLCAweGVmZDM5MGZjLCAweGRkMDdkMzViLCAweGRiNDg1Njk0LCAweDM4ZDdlNWIyLCAweDU3NzIwMTAxLFxuICAgIDB4NzMwZWRlYmMsIDB4NWI2NDMxMTMsIDB4OTQ5MTdlNGYsIDB4NTAzYzJmYmEsIDB4NjQ2ZjEyODIsIDB4NzUyM2QyNGEsIDB4ZTA3Nzk2OTUsIDB4ZjljMTdhOGYsXG4gICAgMHg3YTViMjEyMSwgMHhkMTg3Yjg5NiwgMHgyOTI2M2E0ZCwgMHhiYTUxMGNkZiwgMHg4MWY0N2M5ZiwgMHhhZDExNjNlZCwgMHhlYTdiNTk2NSwgMHgxYTAwNzI2ZSxcbiAgICAweDExNDAzMDkyLCAweDAwZGE2ZDc3LCAweDRhMGNkZDYxLCAweGFkMWY0NjAzLCAweDYwNWJkZmIwLCAweDllZWRjMzY0LCAweDIyZWJlNmE4LCAweGNlZTdkMjhhLFxuICAgIDB4YTBlNzM2YTAsIDB4NTU2NGE2YjksIDB4MTA4NTMyMDksIDB4YzdlYjhmMzcsIDB4MmRlNzA1Y2EsIDB4ODk1MTU3MGYsIDB4ZGYwOTgyMmIsIDB4YmQ2OTFhNmMsXG4gICAgMHhhYTEyZTRmMiwgMHg4NzQ1MWMwZiwgMHhlMGY2YTI3YSwgMHgzYWRhNDgxOSwgMHg0Y2YxNzY0ZiwgMHgwZDc3MWMyYiwgMHg2N2NkYjE1NiwgMHgzNTBkODM4NCxcbiAgICAweDU5MzhmYTBmLCAweDQyMzk5ZWYzLCAweDM2OTk3YjA3LCAweDBlODQwOTNkLCAweDRhYTkzZTYxLCAweDgzNjBkODdiLCAweDFmYTk4YjBjLCAweDExNDkzODJjLFxuICAgIDB4ZTk3NjI1YTUsIDB4MDYxNGQxYjcsIDB4MGUyNTI0NGIsIDB4MGM3NjgzNDcsIDB4NTg5ZThkODIsIDB4MGQyMDU5ZDEsIDB4YTQ2NmJiMWUsIDB4ZjhkYTBhODIsXG4gICAgMHgwNGYxOTEzMCwgMHhiYTZlNGVjMCwgMHg5OTI2NTE2NCwgMHgxZWU3MjMwZCwgMHg1MGIyYWQ4MCwgMHhlYWVlNjgwMSwgMHg4ZGIyYTI4MywgMHhlYThiZjU5ZSk7XG5cbn07XG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG5mdW5jdGlvbiBjYXN0NShrZXkpIHtcbiAgdGhpcy5jYXN0NSA9IG5ldyBvcGVucGdwX3N5bWVuY19jYXN0NSgpO1xuICB0aGlzLmNhc3Q1LnNldEtleSh1dGlsLnN0cjJiaW4oa2V5KSk7XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oYmxvY2spIHtcbiAgICByZXR1cm4gdGhpcy5jYXN0NS5lbmNyeXB0KGJsb2NrKTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNhc3Q1O1xubW9kdWxlLmV4cG9ydHMuYmxvY2tTaXplID0gY2FzdDUucHJvdG90eXBlLmJsb2NrU2l6ZSA9IDg7XG5tb2R1bGUuZXhwb3J0cy5rZXlTaXplID0gY2FzdDUucHJvdG90eXBlLmtleVNpemUgPSAxNjtcbiIsIi8vUGF1bCBUZXJvLCBKdWx5IDIwMDFcbi8vaHR0cDovL3d3dy50ZXJvLmNvLnVrL2Rlcy9cbi8vXG4vL09wdGltaXNlZCBmb3IgcGVyZm9ybWFuY2Ugd2l0aCBsYXJnZSBibG9ja3MgYnkgTWljaGFlbCBIYXl3b3J0aCwgTm92ZW1iZXIgMjAwMVxuLy9odHRwOi8vd3d3Lm5ldGRlYWxpbmcuY29tXG4vL1xuLy8gTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIXG5cbi8vVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EXG4vL0FOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuLy9JTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRVxuLy9BUkUgRElTQ0xBSU1FRC4gIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRVxuLy9GT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTFxuLy9EQU1BR0VTIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EU1xuLy9PUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTilcbi8vSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1Rcbi8vTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWVxuLy9PVVQgT0YgVEhFIFVTRSBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GXG4vL1NVQ0ggREFNQUdFLlxuXG4vL2Rlc1xuLy90aGlzIHRha2VzIHRoZSBrZXksIHRoZSBtZXNzYWdlLCBhbmQgd2hldGhlciB0byBlbmNyeXB0IG9yIGRlY3J5cHRcblxuXG5cblxuZnVuY3Rpb24gZGVzKGtleXMsIG1lc3NhZ2UsIGVuY3J5cHQsIG1vZGUsIGl2LCBwYWRkaW5nKSB7XG4gIC8vZGVjbGFyaW5nIHRoaXMgbG9jYWxseSBzcGVlZHMgdGhpbmdzIHVwIGEgYml0XG4gIHZhciBzcGZ1bmN0aW9uMSA9IG5ldyBBcnJheSgweDEwMTA0MDAsIDAsIDB4MTAwMDAsIDB4MTAxMDQwNCwgMHgxMDEwMDA0LCAweDEwNDA0LCAweDQsIDB4MTAwMDAsIDB4NDAwLCAweDEwMTA0MDAsXG4gICAgMHgxMDEwNDA0LCAweDQwMCwgMHgxMDAwNDA0LCAweDEwMTAwMDQsIDB4MTAwMDAwMCwgMHg0LCAweDQwNCwgMHgxMDAwNDAwLCAweDEwMDA0MDAsIDB4MTA0MDAsIDB4MTA0MDAsIDB4MTAxMDAwMCxcbiAgICAweDEwMTAwMDAsIDB4MTAwMDQwNCwgMHgxMDAwNCwgMHgxMDAwMDA0LCAweDEwMDAwMDQsIDB4MTAwMDQsIDAsIDB4NDA0LCAweDEwNDA0LCAweDEwMDAwMDAsIDB4MTAwMDAsIDB4MTAxMDQwNCwgMHg0LFxuICAgIDB4MTAxMDAwMCwgMHgxMDEwNDAwLCAweDEwMDAwMDAsIDB4MTAwMDAwMCwgMHg0MDAsIDB4MTAxMDAwNCwgMHgxMDAwMCwgMHgxMDQwMCwgMHgxMDAwMDA0LCAweDQwMCwgMHg0LCAweDEwMDA0MDQsXG4gICAgMHgxMDQwNCwgMHgxMDEwNDA0LCAweDEwMDA0LCAweDEwMTAwMDAsIDB4MTAwMDQwNCwgMHgxMDAwMDA0LCAweDQwNCwgMHgxMDQwNCwgMHgxMDEwNDAwLCAweDQwNCwgMHgxMDAwNDAwLFxuICAgIDB4MTAwMDQwMCwgMCwgMHgxMDAwNCwgMHgxMDQwMCwgMCwgMHgxMDEwMDA0KTtcbiAgdmFyIHNwZnVuY3Rpb24yID0gbmV3IEFycmF5KC0weDdmZWY3ZmUwLCAtMHg3ZmZmODAwMCwgMHg4MDAwLCAweDEwODAyMCwgMHgxMDAwMDAsIDB4MjAsIC0weDdmZWZmZmUwLCAtMHg3ZmZmN2ZlMCwgLVxuICAgIDB4N2ZmZmZmZTAsIC0weDdmZWY3ZmUwLCAtMHg3ZmVmODAwMCwgLTB4ODAwMDAwMDAsIC0weDdmZmY4MDAwLCAweDEwMDAwMCwgMHgyMCwgLTB4N2ZlZmZmZTAsIDB4MTA4MDAwLCAweDEwMDAyMCwgLVxuICAgIDB4N2ZmZjdmZTAsIDAsIC0weDgwMDAwMDAwLCAweDgwMDAsIDB4MTA4MDIwLCAtMHg3ZmYwMDAwMCwgMHgxMDAwMjAsIC0weDdmZmZmZmUwLCAwLCAweDEwODAwMCwgMHg4MDIwLCAtMHg3ZmVmODAwMCwgLVxuICAgIDB4N2ZmMDAwMDAsIDB4ODAyMCwgMCwgMHgxMDgwMjAsIC0weDdmZWZmZmUwLCAweDEwMDAwMCwgLTB4N2ZmZjdmZTAsIC0weDdmZjAwMDAwLCAtMHg3ZmVmODAwMCwgMHg4MDAwLCAtMHg3ZmYwMDAwMCwgLVxuICAgIDB4N2ZmZjgwMDAsIDB4MjAsIC0weDdmZWY3ZmUwLCAweDEwODAyMCwgMHgyMCwgMHg4MDAwLCAtMHg4MDAwMDAwMCwgMHg4MDIwLCAtMHg3ZmVmODAwMCwgMHgxMDAwMDAsIC0weDdmZmZmZmUwLFxuICAgIDB4MTAwMDIwLCAtMHg3ZmZmN2ZlMCwgLTB4N2ZmZmZmZTAsIDB4MTAwMDIwLCAweDEwODAwMCwgMCwgLTB4N2ZmZjgwMDAsIDB4ODAyMCwgLTB4ODAwMDAwMDAsIC0weDdmZWZmZmUwLCAtXG4gICAgMHg3ZmVmN2ZlMCwgMHgxMDgwMDApO1xuICB2YXIgc3BmdW5jdGlvbjMgPSBuZXcgQXJyYXkoMHgyMDgsIDB4ODAyMDIwMCwgMCwgMHg4MDIwMDA4LCAweDgwMDAyMDAsIDAsIDB4MjAyMDgsIDB4ODAwMDIwMCwgMHgyMDAwOCwgMHg4MDAwMDA4LFxuICAgIDB4ODAwMDAwOCwgMHgyMDAwMCwgMHg4MDIwMjA4LCAweDIwMDA4LCAweDgwMjAwMDAsIDB4MjA4LCAweDgwMDAwMDAsIDB4OCwgMHg4MDIwMjAwLCAweDIwMCwgMHgyMDIwMCwgMHg4MDIwMDAwLFxuICAgIDB4ODAyMDAwOCwgMHgyMDIwOCwgMHg4MDAwMjA4LCAweDIwMjAwLCAweDIwMDAwLCAweDgwMDAyMDgsIDB4OCwgMHg4MDIwMjA4LCAweDIwMCwgMHg4MDAwMDAwLCAweDgwMjAyMDAsIDB4ODAwMDAwMCxcbiAgICAweDIwMDA4LCAweDIwOCwgMHgyMDAwMCwgMHg4MDIwMjAwLCAweDgwMDAyMDAsIDAsIDB4MjAwLCAweDIwMDA4LCAweDgwMjAyMDgsIDB4ODAwMDIwMCwgMHg4MDAwMDA4LCAweDIwMCwgMCxcbiAgICAweDgwMjAwMDgsIDB4ODAwMDIwOCwgMHgyMDAwMCwgMHg4MDAwMDAwLCAweDgwMjAyMDgsIDB4OCwgMHgyMDIwOCwgMHgyMDIwMCwgMHg4MDAwMDA4LCAweDgwMjAwMDAsIDB4ODAwMDIwOCwgMHgyMDgsXG4gICAgMHg4MDIwMDAwLCAweDIwMjA4LCAweDgsIDB4ODAyMDAwOCwgMHgyMDIwMCk7XG4gIHZhciBzcGZ1bmN0aW9uNCA9IG5ldyBBcnJheSgweDgwMjAwMSwgMHgyMDgxLCAweDIwODEsIDB4ODAsIDB4ODAyMDgwLCAweDgwMDA4MSwgMHg4MDAwMDEsIDB4MjAwMSwgMCwgMHg4MDIwMDAsXG4gICAgMHg4MDIwMDAsIDB4ODAyMDgxLCAweDgxLCAwLCAweDgwMDA4MCwgMHg4MDAwMDEsIDB4MSwgMHgyMDAwLCAweDgwMDAwMCwgMHg4MDIwMDEsIDB4ODAsIDB4ODAwMDAwLCAweDIwMDEsIDB4MjA4MCxcbiAgICAweDgwMDA4MSwgMHgxLCAweDIwODAsIDB4ODAwMDgwLCAweDIwMDAsIDB4ODAyMDgwLCAweDgwMjA4MSwgMHg4MSwgMHg4MDAwODAsIDB4ODAwMDAxLCAweDgwMjAwMCwgMHg4MDIwODEsIDB4ODEsIDAsXG4gICAgMCwgMHg4MDIwMDAsIDB4MjA4MCwgMHg4MDAwODAsIDB4ODAwMDgxLCAweDEsIDB4ODAyMDAxLCAweDIwODEsIDB4MjA4MSwgMHg4MCwgMHg4MDIwODEsIDB4ODEsIDB4MSwgMHgyMDAwLCAweDgwMDAwMSxcbiAgICAweDIwMDEsIDB4ODAyMDgwLCAweDgwMDA4MSwgMHgyMDAxLCAweDIwODAsIDB4ODAwMDAwLCAweDgwMjAwMSwgMHg4MCwgMHg4MDAwMDAsIDB4MjAwMCwgMHg4MDIwODApO1xuICB2YXIgc3BmdW5jdGlvbjUgPSBuZXcgQXJyYXkoMHgxMDAsIDB4MjA4MDEwMCwgMHgyMDgwMDAwLCAweDQyMDAwMTAwLCAweDgwMDAwLCAweDEwMCwgMHg0MDAwMDAwMCwgMHgyMDgwMDAwLFxuICAgIDB4NDAwODAxMDAsIDB4ODAwMDAsIDB4MjAwMDEwMCwgMHg0MDA4MDEwMCwgMHg0MjAwMDEwMCwgMHg0MjA4MDAwMCwgMHg4MDEwMCwgMHg0MDAwMDAwMCwgMHgyMDAwMDAwLCAweDQwMDgwMDAwLFxuICAgIDB4NDAwODAwMDAsIDAsIDB4NDAwMDAxMDAsIDB4NDIwODAxMDAsIDB4NDIwODAxMDAsIDB4MjAwMDEwMCwgMHg0MjA4MDAwMCwgMHg0MDAwMDEwMCwgMCwgMHg0MjAwMDAwMCwgMHgyMDgwMTAwLFxuICAgIDB4MjAwMDAwMCwgMHg0MjAwMDAwMCwgMHg4MDEwMCwgMHg4MDAwMCwgMHg0MjAwMDEwMCwgMHgxMDAsIDB4MjAwMDAwMCwgMHg0MDAwMDAwMCwgMHgyMDgwMDAwLCAweDQyMDAwMTAwLFxuICAgIDB4NDAwODAxMDAsIDB4MjAwMDEwMCwgMHg0MDAwMDAwMCwgMHg0MjA4MDAwMCwgMHgyMDgwMTAwLCAweDQwMDgwMTAwLCAweDEwMCwgMHgyMDAwMDAwLCAweDQyMDgwMDAwLCAweDQyMDgwMTAwLFxuICAgIDB4ODAxMDAsIDB4NDIwMDAwMDAsIDB4NDIwODAxMDAsIDB4MjA4MDAwMCwgMCwgMHg0MDA4MDAwMCwgMHg0MjAwMDAwMCwgMHg4MDEwMCwgMHgyMDAwMTAwLCAweDQwMDAwMTAwLCAweDgwMDAwLCAwLFxuICAgIDB4NDAwODAwMDAsIDB4MjA4MDEwMCwgMHg0MDAwMDEwMCk7XG4gIHZhciBzcGZ1bmN0aW9uNiA9IG5ldyBBcnJheSgweDIwMDAwMDEwLCAweDIwNDAwMDAwLCAweDQwMDAsIDB4MjA0MDQwMTAsIDB4MjA0MDAwMDAsIDB4MTAsIDB4MjA0MDQwMTAsIDB4NDAwMDAwLFxuICAgIDB4MjAwMDQwMDAsIDB4NDA0MDEwLCAweDQwMDAwMCwgMHgyMDAwMDAxMCwgMHg0MDAwMTAsIDB4MjAwMDQwMDAsIDB4MjAwMDAwMDAsIDB4NDAxMCwgMCwgMHg0MDAwMTAsIDB4MjAwMDQwMTAsXG4gICAgMHg0MDAwLCAweDQwNDAwMCwgMHgyMDAwNDAxMCwgMHgxMCwgMHgyMDQwMDAxMCwgMHgyMDQwMDAxMCwgMCwgMHg0MDQwMTAsIDB4MjA0MDQwMDAsIDB4NDAxMCwgMHg0MDQwMDAsIDB4MjA0MDQwMDAsXG4gICAgMHgyMDAwMDAwMCwgMHgyMDAwNDAwMCwgMHgxMCwgMHgyMDQwMDAxMCwgMHg0MDQwMDAsIDB4MjA0MDQwMTAsIDB4NDAwMDAwLCAweDQwMTAsIDB4MjAwMDAwMTAsIDB4NDAwMDAwLCAweDIwMDA0MDAwLFxuICAgIDB4MjAwMDAwMDAsIDB4NDAxMCwgMHgyMDAwMDAxMCwgMHgyMDQwNDAxMCwgMHg0MDQwMDAsIDB4MjA0MDAwMDAsIDB4NDA0MDEwLCAweDIwNDA0MDAwLCAwLCAweDIwNDAwMDEwLCAweDEwLCAweDQwMDAsXG4gICAgMHgyMDQwMDAwMCwgMHg0MDQwMTAsIDB4NDAwMCwgMHg0MDAwMTAsIDB4MjAwMDQwMTAsIDAsIDB4MjA0MDQwMDAsIDB4MjAwMDAwMDAsIDB4NDAwMDEwLCAweDIwMDA0MDEwKTtcbiAgdmFyIHNwZnVuY3Rpb243ID0gbmV3IEFycmF5KDB4MjAwMDAwLCAweDQyMDAwMDIsIDB4NDAwMDgwMiwgMCwgMHg4MDAsIDB4NDAwMDgwMiwgMHgyMDA4MDIsIDB4NDIwMDgwMCwgMHg0MjAwODAyLFxuICAgIDB4MjAwMDAwLCAwLCAweDQwMDAwMDIsIDB4MiwgMHg0MDAwMDAwLCAweDQyMDAwMDIsIDB4ODAyLCAweDQwMDA4MDAsIDB4MjAwODAyLCAweDIwMDAwMiwgMHg0MDAwODAwLCAweDQwMDAwMDIsXG4gICAgMHg0MjAwMDAwLCAweDQyMDA4MDAsIDB4MjAwMDAyLCAweDQyMDAwMDAsIDB4ODAwLCAweDgwMiwgMHg0MjAwODAyLCAweDIwMDgwMCwgMHgyLCAweDQwMDAwMDAsIDB4MjAwODAwLCAweDQwMDAwMDAsXG4gICAgMHgyMDA4MDAsIDB4MjAwMDAwLCAweDQwMDA4MDIsIDB4NDAwMDgwMiwgMHg0MjAwMDAyLCAweDQyMDAwMDIsIDB4MiwgMHgyMDAwMDIsIDB4NDAwMDAwMCwgMHg0MDAwODAwLCAweDIwMDAwMCxcbiAgICAweDQyMDA4MDAsIDB4ODAyLCAweDIwMDgwMiwgMHg0MjAwODAwLCAweDgwMiwgMHg0MDAwMDAyLCAweDQyMDA4MDIsIDB4NDIwMDAwMCwgMHgyMDA4MDAsIDAsIDB4MiwgMHg0MjAwODAyLCAwLFxuICAgIDB4MjAwODAyLCAweDQyMDAwMDAsIDB4ODAwLCAweDQwMDAwMDIsIDB4NDAwMDgwMCwgMHg4MDAsIDB4MjAwMDAyKTtcbiAgdmFyIHNwZnVuY3Rpb244ID0gbmV3IEFycmF5KDB4MTAwMDEwNDAsIDB4MTAwMCwgMHg0MDAwMCwgMHgxMDA0MTA0MCwgMHgxMDAwMDAwMCwgMHgxMDAwMTA0MCwgMHg0MCwgMHgxMDAwMDAwMCxcbiAgICAweDQwMDQwLCAweDEwMDQwMDAwLCAweDEwMDQxMDQwLCAweDQxMDAwLCAweDEwMDQxMDAwLCAweDQxMDQwLCAweDEwMDAsIDB4NDAsIDB4MTAwNDAwMDAsIDB4MTAwMDAwNDAsIDB4MTAwMDEwMDAsXG4gICAgMHgxMDQwLCAweDQxMDAwLCAweDQwMDQwLCAweDEwMDQwMDQwLCAweDEwMDQxMDAwLCAweDEwNDAsIDAsIDAsIDB4MTAwNDAwNDAsIDB4MTAwMDAwNDAsIDB4MTAwMDEwMDAsIDB4NDEwNDAsXG4gICAgMHg0MDAwMCwgMHg0MTA0MCwgMHg0MDAwMCwgMHgxMDA0MTAwMCwgMHgxMDAwLCAweDQwLCAweDEwMDQwMDQwLCAweDEwMDAsIDB4NDEwNDAsIDB4MTAwMDEwMDAsIDB4NDAsIDB4MTAwMDAwNDAsXG4gICAgMHgxMDA0MDAwMCwgMHgxMDA0MDA0MCwgMHgxMDAwMDAwMCwgMHg0MDAwMCwgMHgxMDAwMTA0MCwgMCwgMHgxMDA0MTA0MCwgMHg0MDA0MCwgMHgxMDAwMDA0MCwgMHgxMDA0MDAwMCwgMHgxMDAwMTAwMCxcbiAgICAweDEwMDAxMDQwLCAwLCAweDEwMDQxMDQwLCAweDQxMDAwLCAweDQxMDAwLCAweDEwNDAsIDB4MTA0MCwgMHg0MDA0MCwgMHgxMDAwMDAwMCwgMHgxMDA0MTAwMCk7XG5cbiAgLy9jcmVhdGUgdGhlIDE2IG9yIDQ4IHN1YmtleXMgd2Ugd2lsbCBuZWVkXG4gIHZhciBtID0gMCxcbiAgICBpLCBqLCB0ZW1wLCB0ZW1wMiwgcmlnaHQxLCByaWdodDIsIGxlZnQsIHJpZ2h0LCBsb29waW5nO1xuICB2YXIgY2JjbGVmdCwgY2JjbGVmdDIsIGNiY3JpZ2h0LCBjYmNyaWdodDJcbiAgdmFyIGVuZGxvb3AsIGxvb3BpbmM7XG4gIHZhciBsZW4gPSBtZXNzYWdlLmxlbmd0aDtcbiAgdmFyIGNodW5rID0gMDtcbiAgLy9zZXQgdXAgdGhlIGxvb3BzIGZvciBzaW5nbGUgYW5kIHRyaXBsZSBkZXNcbiAgdmFyIGl0ZXJhdGlvbnMgPSBrZXlzLmxlbmd0aCA9PSAzMiA/IDMgOiA5OyAvL3NpbmdsZSBvciB0cmlwbGUgZGVzXG4gIGlmIChpdGVyYXRpb25zID09IDMpIHtcbiAgICBsb29waW5nID0gZW5jcnlwdCA/IG5ldyBBcnJheSgwLCAzMiwgMikgOiBuZXcgQXJyYXkoMzAsIC0yLCAtMik7XG4gIH0gZWxzZSB7XG4gICAgbG9vcGluZyA9IGVuY3J5cHQgPyBuZXcgQXJyYXkoMCwgMzIsIDIsIDYyLCAzMCwgLTIsIDY0LCA5NiwgMikgOiBuZXcgQXJyYXkoOTQsIDYyLCAtMiwgMzIsIDY0LCAyLCAzMCwgLTIsIC0yKTtcbiAgfVxuXG4gIC8vcGFkIHRoZSBtZXNzYWdlIGRlcGVuZGluZyBvbiB0aGUgcGFkZGluZyBwYXJhbWV0ZXJcbiAgLy9vbmx5IGFkZCBwYWRkaW5nIGlmIGVuY3J5cHRpbmcgLSBub3RlIHRoYXQgeW91IG5lZWQgdG8gdXNlIHRoZSBzYW1lIHBhZGRpbmcgb3B0aW9uIGZvciBib3RoIGVuY3J5cHQgYW5kIGRlY3J5cHRcbiAgaWYgKGVuY3J5cHQpIHtcbiAgICBtZXNzYWdlID0gZGVzX2FkZFBhZGRpbmcobWVzc2FnZSwgcGFkZGluZyk7XG4gICAgbGVuID0gbWVzc2FnZS5sZW5ndGg7XG4gIH1cblxuICAvL3N0b3JlIHRoZSByZXN1bHQgaGVyZVxuICByZXN1bHQgPSBcIlwiO1xuICB0ZW1wcmVzdWx0ID0gXCJcIjtcblxuICBpZiAobW9kZSA9PSAxKSB7IC8vQ0JDIG1vZGVcbiAgICBjYmNsZWZ0ID0gKGl2LmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAoaXYuY2hhckNvZGVBdChtKyspIDw8IDE2KSB8IChpdi5jaGFyQ29kZUF0KG0rKykgPDwgOCkgfCBpdi5jaGFyQ29kZUF0KG0rKyk7XG4gICAgY2JjcmlnaHQgPSAoaXYuY2hhckNvZGVBdChtKyspIDw8IDI0KSB8IChpdi5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKGl2LmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8IGl2LmNoYXJDb2RlQXQobSsrKTtcbiAgICBtID0gMDtcbiAgfVxuXG4gIC8vbG9vcCB0aHJvdWdoIGVhY2ggNjQgYml0IGNodW5rIG9mIHRoZSBtZXNzYWdlXG4gIHdoaWxlIChtIDwgbGVuKSB7XG4gICAgbGVmdCA9IChtZXNzYWdlLmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAobWVzc2FnZS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKG1lc3NhZ2UuY2hhckNvZGVBdChtKyspIDw8IDgpIHwgbWVzc2FnZVxuICAgICAgLmNoYXJDb2RlQXQobSsrKTtcbiAgICByaWdodCA9IChtZXNzYWdlLmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAobWVzc2FnZS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKG1lc3NhZ2UuY2hhckNvZGVBdChtKyspIDw8IDgpIHxcbiAgICAgIG1lc3NhZ2UuY2hhckNvZGVBdChtKyspO1xuXG4gICAgLy9mb3IgQ2lwaGVyIEJsb2NrIENoYWluaW5nIG1vZGUsIHhvciB0aGUgbWVzc2FnZSB3aXRoIHRoZSBwcmV2aW91cyByZXN1bHRcbiAgICBpZiAobW9kZSA9PSAxKSB7XG4gICAgICBpZiAoZW5jcnlwdCkge1xuICAgICAgICBsZWZ0IF49IGNiY2xlZnQ7XG4gICAgICAgIHJpZ2h0IF49IGNiY3JpZ2h0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2JjbGVmdDIgPSBjYmNsZWZ0O1xuICAgICAgICBjYmNyaWdodDIgPSBjYmNyaWdodDtcbiAgICAgICAgY2JjbGVmdCA9IGxlZnQ7XG4gICAgICAgIGNiY3JpZ2h0ID0gcmlnaHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy9maXJzdCBlYWNoIDY0IGJ1dCBjaHVuayBvZiB0aGUgbWVzc2FnZSBtdXN0IGJlIHBlcm11dGVkIGFjY29yZGluZyB0byBJUFxuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDQpIF4gcmlnaHQpICYgMHgwZjBmMGYwZjtcbiAgICByaWdodCBePSB0ZW1wO1xuICAgIGxlZnQgXj0gKHRlbXAgPDwgNCk7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gMTYpIF4gcmlnaHQpICYgMHgwMDAwZmZmZjtcbiAgICByaWdodCBePSB0ZW1wO1xuICAgIGxlZnQgXj0gKHRlbXAgPDwgMTYpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiAyKSBeIGxlZnQpICYgMHgzMzMzMzMzMztcbiAgICBsZWZ0IF49IHRlbXA7XG4gICAgcmlnaHQgXj0gKHRlbXAgPDwgMik7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IDgpIF4gbGVmdCkgJiAweDAwZmYwMGZmO1xuICAgIGxlZnQgXj0gdGVtcDtcbiAgICByaWdodCBePSAodGVtcCA8PCA4KTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAxKSBeIHJpZ2h0KSAmIDB4NTU1NTU1NTU7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDEpO1xuXG4gICAgbGVmdCA9ICgobGVmdCA8PCAxKSB8IChsZWZ0ID4+PiAzMSkpO1xuICAgIHJpZ2h0ID0gKChyaWdodCA8PCAxKSB8IChyaWdodCA+Pj4gMzEpKTtcblxuICAgIC8vZG8gdGhpcyBlaXRoZXIgMSBvciAzIHRpbWVzIGZvciBlYWNoIGNodW5rIG9mIHRoZSBtZXNzYWdlXG4gICAgZm9yIChqID0gMDsgaiA8IGl0ZXJhdGlvbnM7IGogKz0gMykge1xuICAgICAgZW5kbG9vcCA9IGxvb3BpbmdbaiArIDFdO1xuICAgICAgbG9vcGluYyA9IGxvb3BpbmdbaiArIDJdO1xuICAgICAgLy9ub3cgZ28gdGhyb3VnaCBhbmQgcGVyZm9ybSB0aGUgZW5jcnlwdGlvbiBvciBkZWNyeXB0aW9uICBcbiAgICAgIGZvciAoaSA9IGxvb3Bpbmdbal07IGkgIT0gZW5kbG9vcDsgaSArPSBsb29waW5jKSB7IC8vZm9yIGVmZmljaWVuY3lcbiAgICAgICAgcmlnaHQxID0gcmlnaHQgXiBrZXlzW2ldO1xuICAgICAgICByaWdodDIgPSAoKHJpZ2h0ID4+PiA0KSB8IChyaWdodCA8PCAyOCkpIF4ga2V5c1tpICsgMV07XG4gICAgICAgIC8vdGhlIHJlc3VsdCBpcyBhdHRhaW5lZCBieSBwYXNzaW5nIHRoZXNlIGJ5dGVzIHRocm91Z2ggdGhlIFMgc2VsZWN0aW9uIGZ1bmN0aW9uc1xuICAgICAgICB0ZW1wID0gbGVmdDtcbiAgICAgICAgbGVmdCA9IHJpZ2h0O1xuICAgICAgICByaWdodCA9IHRlbXAgXiAoc3BmdW5jdGlvbjJbKHJpZ2h0MSA+Pj4gMjQpICYgMHgzZl0gfCBzcGZ1bmN0aW9uNFsocmlnaHQxID4+PiAxNikgJiAweDNmXSB8IHNwZnVuY3Rpb242WyhyaWdodDEgPj4+XG4gICAgICAgICAgOCkgJiAweDNmXSB8IHNwZnVuY3Rpb244W3JpZ2h0MSAmIDB4M2ZdIHwgc3BmdW5jdGlvbjFbKHJpZ2h0MiA+Pj4gMjQpICYgMHgzZl0gfCBzcGZ1bmN0aW9uM1socmlnaHQyID4+PiAxNikgJlxuICAgICAgICAgIDB4M2ZdIHwgc3BmdW5jdGlvbjVbKHJpZ2h0MiA+Pj4gOCkgJiAweDNmXSB8IHNwZnVuY3Rpb243W3JpZ2h0MiAmIDB4M2ZdKTtcbiAgICAgIH1cbiAgICAgIHRlbXAgPSBsZWZ0O1xuICAgICAgbGVmdCA9IHJpZ2h0O1xuICAgICAgcmlnaHQgPSB0ZW1wOyAvL3VucmV2ZXJzZSBsZWZ0IGFuZCByaWdodFxuICAgIH0gLy9mb3IgZWl0aGVyIDEgb3IgMyBpdGVyYXRpb25zXG5cbiAgICAvL21vdmUgdGhlbiBlYWNoIG9uZSBiaXQgdG8gdGhlIHJpZ2h0XG4gICAgbGVmdCA9ICgobGVmdCA+Pj4gMSkgfCAobGVmdCA8PCAzMSkpO1xuICAgIHJpZ2h0ID0gKChyaWdodCA+Pj4gMSkgfCAocmlnaHQgPDwgMzEpKTtcblxuICAgIC8vbm93IHBlcmZvcm0gSVAtMSwgd2hpY2ggaXMgSVAgaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvblxuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDEpIF4gcmlnaHQpICYgMHg1NTU1NTU1NTtcbiAgICByaWdodCBePSB0ZW1wO1xuICAgIGxlZnQgXj0gKHRlbXAgPDwgMSk7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IDgpIF4gbGVmdCkgJiAweDAwZmYwMGZmO1xuICAgIGxlZnQgXj0gdGVtcDtcbiAgICByaWdodCBePSAodGVtcCA8PCA4KTtcbiAgICB0ZW1wID0gKChyaWdodCA+Pj4gMikgXiBsZWZ0KSAmIDB4MzMzMzMzMzM7XG4gICAgbGVmdCBePSB0ZW1wO1xuICAgIHJpZ2h0IF49ICh0ZW1wIDw8IDIpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDE2KSBeIHJpZ2h0KSAmIDB4MDAwMGZmZmY7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDE2KTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiA0KSBeIHJpZ2h0KSAmIDB4MGYwZjBmMGY7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDQpO1xuXG4gICAgLy9mb3IgQ2lwaGVyIEJsb2NrIENoYWluaW5nIG1vZGUsIHhvciB0aGUgbWVzc2FnZSB3aXRoIHRoZSBwcmV2aW91cyByZXN1bHRcbiAgICBpZiAobW9kZSA9PSAxKSB7XG4gICAgICBpZiAoZW5jcnlwdCkge1xuICAgICAgICBjYmNsZWZ0ID0gbGVmdDtcbiAgICAgICAgY2JjcmlnaHQgPSByaWdodDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxlZnQgXj0gY2JjbGVmdDI7XG4gICAgICAgIHJpZ2h0IF49IGNiY3JpZ2h0MjtcbiAgICAgIH1cbiAgICB9XG4gICAgdGVtcHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChsZWZ0ID4+PiAyNCksICgobGVmdCA+Pj4gMTYpICYgMHhmZiksICgobGVmdCA+Pj4gOCkgJiAweGZmKSwgKGxlZnQgJiAweGZmKSwgKFxuICAgICAgcmlnaHQgPj4+IDI0KSwgKChyaWdodCA+Pj4gMTYpICYgMHhmZiksICgocmlnaHQgPj4+IDgpICYgMHhmZiksIChyaWdodCAmIDB4ZmYpKTtcblxuICAgIGNodW5rICs9IDg7XG4gICAgaWYgKGNodW5rID09IDUxMikge1xuICAgICAgcmVzdWx0ICs9IHRlbXByZXN1bHQ7XG4gICAgICB0ZW1wcmVzdWx0ID0gXCJcIjtcbiAgICAgIGNodW5rID0gMDtcbiAgICB9XG4gIH0gLy9mb3IgZXZlcnkgOCBjaGFyYWN0ZXJzLCBvciA2NCBiaXRzIGluIHRoZSBtZXNzYWdlXG5cbiAgLy9yZXR1cm4gdGhlIHJlc3VsdCBhcyBhbiBhcnJheVxuICByZXN1bHQgKz0gdGVtcHJlc3VsdDtcblxuICAvL29ubHkgcmVtb3ZlIHBhZGRpbmcgaWYgZGVjcnlwdGluZyAtIG5vdGUgdGhhdCB5b3UgbmVlZCB0byB1c2UgdGhlIHNhbWUgcGFkZGluZyBvcHRpb24gZm9yIGJvdGggZW5jcnlwdCBhbmQgZGVjcnlwdFxuICBpZiAoIWVuY3J5cHQpIHtcbiAgICByZXN1bHQgPSBkZXNfcmVtb3ZlUGFkZGluZyhyZXN1bHQsIHBhZGRpbmcpO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn0gLy9lbmQgb2YgZGVzXG5cblxuXG4vL2Rlc19jcmVhdGVLZXlzXG4vL3RoaXMgdGFrZXMgYXMgaW5wdXQgYSA2NCBiaXQga2V5IChldmVuIHRob3VnaCBvbmx5IDU2IGJpdHMgYXJlIHVzZWQpXG4vL2FzIGFuIGFycmF5IG9mIDIgaW50ZWdlcnMsIGFuZCByZXR1cm5zIDE2IDQ4IGJpdCBrZXlzXG5cbmZ1bmN0aW9uIGRlc19jcmVhdGVLZXlzKGtleSkge1xuICAvL2RlY2xhcmluZyB0aGlzIGxvY2FsbHkgc3BlZWRzIHRoaW5ncyB1cCBhIGJpdFxuICBwYzJieXRlczAgPSBuZXcgQXJyYXkoMCwgMHg0LCAweDIwMDAwMDAwLCAweDIwMDAwMDA0LCAweDEwMDAwLCAweDEwMDA0LCAweDIwMDEwMDAwLCAweDIwMDEwMDA0LCAweDIwMCwgMHgyMDQsXG4gICAgMHgyMDAwMDIwMCwgMHgyMDAwMDIwNCwgMHgxMDIwMCwgMHgxMDIwNCwgMHgyMDAxMDIwMCwgMHgyMDAxMDIwNCk7XG4gIHBjMmJ5dGVzMSA9IG5ldyBBcnJheSgwLCAweDEsIDB4MTAwMDAwLCAweDEwMDAwMSwgMHg0MDAwMDAwLCAweDQwMDAwMDEsIDB4NDEwMDAwMCwgMHg0MTAwMDAxLCAweDEwMCwgMHgxMDEsIDB4MTAwMTAwLFxuICAgIDB4MTAwMTAxLCAweDQwMDAxMDAsIDB4NDAwMDEwMSwgMHg0MTAwMTAwLCAweDQxMDAxMDEpO1xuICBwYzJieXRlczIgPSBuZXcgQXJyYXkoMCwgMHg4LCAweDgwMCwgMHg4MDgsIDB4MTAwMDAwMCwgMHgxMDAwMDA4LCAweDEwMDA4MDAsIDB4MTAwMDgwOCwgMCwgMHg4LCAweDgwMCwgMHg4MDgsXG4gICAgMHgxMDAwMDAwLCAweDEwMDAwMDgsIDB4MTAwMDgwMCwgMHgxMDAwODA4KTtcbiAgcGMyYnl0ZXMzID0gbmV3IEFycmF5KDAsIDB4MjAwMDAwLCAweDgwMDAwMDAsIDB4ODIwMDAwMCwgMHgyMDAwLCAweDIwMjAwMCwgMHg4MDAyMDAwLCAweDgyMDIwMDAsIDB4MjAwMDAsIDB4MjIwMDAwLFxuICAgIDB4ODAyMDAwMCwgMHg4MjIwMDAwLCAweDIyMDAwLCAweDIyMjAwMCwgMHg4MDIyMDAwLCAweDgyMjIwMDApO1xuICBwYzJieXRlczQgPSBuZXcgQXJyYXkoMCwgMHg0MDAwMCwgMHgxMCwgMHg0MDAxMCwgMCwgMHg0MDAwMCwgMHgxMCwgMHg0MDAxMCwgMHgxMDAwLCAweDQxMDAwLCAweDEwMTAsIDB4NDEwMTAsIDB4MTAwMCxcbiAgICAweDQxMDAwLCAweDEwMTAsIDB4NDEwMTApO1xuICBwYzJieXRlczUgPSBuZXcgQXJyYXkoMCwgMHg0MDAsIDB4MjAsIDB4NDIwLCAwLCAweDQwMCwgMHgyMCwgMHg0MjAsIDB4MjAwMDAwMCwgMHgyMDAwNDAwLCAweDIwMDAwMjAsIDB4MjAwMDQyMCxcbiAgICAweDIwMDAwMDAsIDB4MjAwMDQwMCwgMHgyMDAwMDIwLCAweDIwMDA0MjApO1xuICBwYzJieXRlczYgPSBuZXcgQXJyYXkoMCwgMHgxMDAwMDAwMCwgMHg4MDAwMCwgMHgxMDA4MDAwMCwgMHgyLCAweDEwMDAwMDAyLCAweDgwMDAyLCAweDEwMDgwMDAyLCAwLCAweDEwMDAwMDAwLFxuICAgIDB4ODAwMDAsIDB4MTAwODAwMDAsIDB4MiwgMHgxMDAwMDAwMiwgMHg4MDAwMiwgMHgxMDA4MDAwMik7XG4gIHBjMmJ5dGVzNyA9IG5ldyBBcnJheSgwLCAweDEwMDAwLCAweDgwMCwgMHgxMDgwMCwgMHgyMDAwMDAwMCwgMHgyMDAxMDAwMCwgMHgyMDAwMDgwMCwgMHgyMDAxMDgwMCwgMHgyMDAwMCwgMHgzMDAwMCxcbiAgICAweDIwODAwLCAweDMwODAwLCAweDIwMDIwMDAwLCAweDIwMDMwMDAwLCAweDIwMDIwODAwLCAweDIwMDMwODAwKTtcbiAgcGMyYnl0ZXM4ID0gbmV3IEFycmF5KDAsIDB4NDAwMDAsIDAsIDB4NDAwMDAsIDB4MiwgMHg0MDAwMiwgMHgyLCAweDQwMDAyLCAweDIwMDAwMDAsIDB4MjA0MDAwMCwgMHgyMDAwMDAwLCAweDIwNDAwMDAsXG4gICAgMHgyMDAwMDAyLCAweDIwNDAwMDIsIDB4MjAwMDAwMiwgMHgyMDQwMDAyKTtcbiAgcGMyYnl0ZXM5ID0gbmV3IEFycmF5KDAsIDB4MTAwMDAwMDAsIDB4OCwgMHgxMDAwMDAwOCwgMCwgMHgxMDAwMDAwMCwgMHg4LCAweDEwMDAwMDA4LCAweDQwMCwgMHgxMDAwMDQwMCwgMHg0MDgsXG4gICAgMHgxMDAwMDQwOCwgMHg0MDAsIDB4MTAwMDA0MDAsIDB4NDA4LCAweDEwMDAwNDA4KTtcbiAgcGMyYnl0ZXMxMCA9IG5ldyBBcnJheSgwLCAweDIwLCAwLCAweDIwLCAweDEwMDAwMCwgMHgxMDAwMjAsIDB4MTAwMDAwLCAweDEwMDAyMCwgMHgyMDAwLCAweDIwMjAsIDB4MjAwMCwgMHgyMDIwLFxuICAgIDB4MTAyMDAwLCAweDEwMjAyMCwgMHgxMDIwMDAsIDB4MTAyMDIwKTtcbiAgcGMyYnl0ZXMxMSA9IG5ldyBBcnJheSgwLCAweDEwMDAwMDAsIDB4MjAwLCAweDEwMDAyMDAsIDB4MjAwMDAwLCAweDEyMDAwMDAsIDB4MjAwMjAwLCAweDEyMDAyMDAsIDB4NDAwMDAwMCwgMHg1MDAwMDAwLFxuICAgIDB4NDAwMDIwMCwgMHg1MDAwMjAwLCAweDQyMDAwMDAsIDB4NTIwMDAwMCwgMHg0MjAwMjAwLCAweDUyMDAyMDApO1xuICBwYzJieXRlczEyID0gbmV3IEFycmF5KDAsIDB4MTAwMCwgMHg4MDAwMDAwLCAweDgwMDEwMDAsIDB4ODAwMDAsIDB4ODEwMDAsIDB4ODA4MDAwMCwgMHg4MDgxMDAwLCAweDEwLCAweDEwMTAsXG4gICAgMHg4MDAwMDEwLCAweDgwMDEwMTAsIDB4ODAwMTAsIDB4ODEwMTAsIDB4ODA4MDAxMCwgMHg4MDgxMDEwKTtcbiAgcGMyYnl0ZXMxMyA9IG5ldyBBcnJheSgwLCAweDQsIDB4MTAwLCAweDEwNCwgMCwgMHg0LCAweDEwMCwgMHgxMDQsIDB4MSwgMHg1LCAweDEwMSwgMHgxMDUsIDB4MSwgMHg1LCAweDEwMSwgMHgxMDUpO1xuXG4gIC8vaG93IG1hbnkgaXRlcmF0aW9ucyAoMSBmb3IgZGVzLCAzIGZvciB0cmlwbGUgZGVzKVxuICB2YXIgaXRlcmF0aW9ucyA9IGtleS5sZW5ndGggPiA4ID8gMyA6IDE7IC8vY2hhbmdlZCBieSBQYXVsIDE2LzYvMjAwNyB0byB1c2UgVHJpcGxlIERFUyBmb3IgOSsgYnl0ZSBrZXlzXG4gIC8vc3RvcmVzIHRoZSByZXR1cm4ga2V5c1xuICB2YXIga2V5cyA9IG5ldyBBcnJheSgzMiAqIGl0ZXJhdGlvbnMpO1xuICAvL25vdyBkZWZpbmUgdGhlIGxlZnQgc2hpZnRzIHdoaWNoIG5lZWQgdG8gYmUgZG9uZVxuICB2YXIgc2hpZnRzID0gbmV3IEFycmF5KDAsIDAsIDEsIDEsIDEsIDEsIDEsIDEsIDAsIDEsIDEsIDEsIDEsIDEsIDEsIDApO1xuICAvL290aGVyIHZhcmlhYmxlc1xuICB2YXIgbGVmdHRlbXAsIHJpZ2h0dGVtcCwgbSA9IDAsXG4gICAgbiA9IDAsXG4gICAgdGVtcDtcblxuICBmb3IgKHZhciBqID0gMDsgaiA8IGl0ZXJhdGlvbnM7IGorKykgeyAvL2VpdGhlciAxIG9yIDMgaXRlcmF0aW9uc1xuICAgIGxlZnQgPSAoa2V5LmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAoa2V5LmNoYXJDb2RlQXQobSsrKSA8PCAxNikgfCAoa2V5LmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8IGtleS5jaGFyQ29kZUF0KG0rKyk7XG4gICAgcmlnaHQgPSAoa2V5LmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAoa2V5LmNoYXJDb2RlQXQobSsrKSA8PCAxNikgfCAoa2V5LmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8IGtleS5jaGFyQ29kZUF0KG0rKyk7XG5cbiAgICB0ZW1wID0gKChsZWZ0ID4+PiA0KSBeIHJpZ2h0KSAmIDB4MGYwZjBmMGY7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDQpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiAtMTYpIF4gbGVmdCkgJiAweDAwMDBmZmZmO1xuICAgIGxlZnQgXj0gdGVtcDtcbiAgICByaWdodCBePSAodGVtcCA8PCAtMTYpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDIpIF4gcmlnaHQpICYgMHgzMzMzMzMzMztcbiAgICByaWdodCBePSB0ZW1wO1xuICAgIGxlZnQgXj0gKHRlbXAgPDwgMik7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IC0xNikgXiBsZWZ0KSAmIDB4MDAwMGZmZmY7XG4gICAgbGVmdCBePSB0ZW1wO1xuICAgIHJpZ2h0IF49ICh0ZW1wIDw8IC0xNik7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gMSkgXiByaWdodCkgJiAweDU1NTU1NTU1O1xuICAgIHJpZ2h0IF49IHRlbXA7XG4gICAgbGVmdCBePSAodGVtcCA8PCAxKTtcbiAgICB0ZW1wID0gKChyaWdodCA+Pj4gOCkgXiBsZWZ0KSAmIDB4MDBmZjAwZmY7XG4gICAgbGVmdCBePSB0ZW1wO1xuICAgIHJpZ2h0IF49ICh0ZW1wIDw8IDgpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDEpIF4gcmlnaHQpICYgMHg1NTU1NTU1NTtcbiAgICByaWdodCBePSB0ZW1wO1xuICAgIGxlZnQgXj0gKHRlbXAgPDwgMSk7XG5cbiAgICAvL3RoZSByaWdodCBzaWRlIG5lZWRzIHRvIGJlIHNoaWZ0ZWQgYW5kIHRvIGdldCB0aGUgbGFzdCBmb3VyIGJpdHMgb2YgdGhlIGxlZnQgc2lkZVxuICAgIHRlbXAgPSAobGVmdCA8PCA4KSB8ICgocmlnaHQgPj4+IDIwKSAmIDB4MDAwMDAwZjApO1xuICAgIC8vbGVmdCBuZWVkcyB0byBiZSBwdXQgdXBzaWRlIGRvd25cbiAgICBsZWZ0ID0gKHJpZ2h0IDw8IDI0KSB8ICgocmlnaHQgPDwgOCkgJiAweGZmMDAwMCkgfCAoKHJpZ2h0ID4+PiA4KSAmIDB4ZmYwMCkgfCAoKHJpZ2h0ID4+PiAyNCkgJiAweGYwKTtcbiAgICByaWdodCA9IHRlbXA7XG5cbiAgICAvL25vdyBnbyB0aHJvdWdoIGFuZCBwZXJmb3JtIHRoZXNlIHNoaWZ0cyBvbiB0aGUgbGVmdCBhbmQgcmlnaHQga2V5c1xuICAgIGZvciAoaSA9IDA7IGkgPCBzaGlmdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIC8vc2hpZnQgdGhlIGtleXMgZWl0aGVyIG9uZSBvciB0d28gYml0cyB0byB0aGUgbGVmdFxuICAgICAgaWYgKHNoaWZ0c1tpXSkge1xuICAgICAgICBsZWZ0ID0gKGxlZnQgPDwgMikgfCAobGVmdCA+Pj4gMjYpO1xuICAgICAgICByaWdodCA9IChyaWdodCA8PCAyKSB8IChyaWdodCA+Pj4gMjYpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGVmdCA9IChsZWZ0IDw8IDEpIHwgKGxlZnQgPj4+IDI3KTtcbiAgICAgICAgcmlnaHQgPSAocmlnaHQgPDwgMSkgfCAocmlnaHQgPj4+IDI3KTtcbiAgICAgIH1cbiAgICAgIGxlZnQgJj0gLTB4ZjtcbiAgICAgIHJpZ2h0ICY9IC0weGY7XG5cbiAgICAgIC8vbm93IGFwcGx5IFBDLTIsIGluIHN1Y2ggYSB3YXkgdGhhdCBFIGlzIGVhc2llciB3aGVuIGVuY3J5cHRpbmcgb3IgZGVjcnlwdGluZ1xuICAgICAgLy90aGlzIGNvbnZlcnNpb24gd2lsbCBsb29rIGxpa2UgUEMtMiBleGNlcHQgb25seSB0aGUgbGFzdCA2IGJpdHMgb2YgZWFjaCBieXRlIGFyZSB1c2VkXG4gICAgICAvL3JhdGhlciB0aGFuIDQ4IGNvbnNlY3V0aXZlIGJpdHMgYW5kIHRoZSBvcmRlciBvZiBsaW5lcyB3aWxsIGJlIGFjY29yZGluZyB0byBcbiAgICAgIC8vaG93IHRoZSBTIHNlbGVjdGlvbiBmdW5jdGlvbnMgd2lsbCBiZSBhcHBsaWVkOiBTMiwgUzQsIFM2LCBTOCwgUzEsIFMzLCBTNSwgUzdcbiAgICAgIGxlZnR0ZW1wID0gcGMyYnl0ZXMwW2xlZnQgPj4+IDI4XSB8IHBjMmJ5dGVzMVsobGVmdCA+Pj4gMjQpICYgMHhmXSB8IHBjMmJ5dGVzMlsobGVmdCA+Pj4gMjApICYgMHhmXSB8IHBjMmJ5dGVzM1soXG4gICAgICAgIGxlZnQgPj4+IDE2KSAmIDB4Zl0gfCBwYzJieXRlczRbKGxlZnQgPj4+IDEyKSAmIDB4Zl0gfCBwYzJieXRlczVbKGxlZnQgPj4+IDgpICYgMHhmXSB8IHBjMmJ5dGVzNlsobGVmdCA+Pj4gNCkgJlxuICAgICAgICAweGZdO1xuICAgICAgcmlnaHR0ZW1wID0gcGMyYnl0ZXM3W3JpZ2h0ID4+PiAyOF0gfCBwYzJieXRlczhbKHJpZ2h0ID4+PiAyNCkgJiAweGZdIHwgcGMyYnl0ZXM5WyhyaWdodCA+Pj4gMjApICYgMHhmXSB8XG4gICAgICAgIHBjMmJ5dGVzMTBbKHJpZ2h0ID4+PiAxNikgJiAweGZdIHwgcGMyYnl0ZXMxMVsocmlnaHQgPj4+IDEyKSAmIDB4Zl0gfCBwYzJieXRlczEyWyhyaWdodCA+Pj4gOCkgJiAweGZdIHxcbiAgICAgICAgcGMyYnl0ZXMxM1socmlnaHQgPj4+IDQpICYgMHhmXTtcbiAgICAgIHRlbXAgPSAoKHJpZ2h0dGVtcCA+Pj4gMTYpIF4gbGVmdHRlbXApICYgMHgwMDAwZmZmZjtcbiAgICAgIGtleXNbbisrXSA9IGxlZnR0ZW1wIF4gdGVtcDtcbiAgICAgIGtleXNbbisrXSA9IHJpZ2h0dGVtcCBeICh0ZW1wIDw8IDE2KTtcbiAgICB9XG4gIH0gLy9mb3IgZWFjaCBpdGVyYXRpb25zXG4gIC8vcmV0dXJuIHRoZSBrZXlzIHdlJ3ZlIGNyZWF0ZWRcbiAgcmV0dXJuIGtleXM7XG59IC8vZW5kIG9mIGRlc19jcmVhdGVLZXlzXG5cblxuZnVuY3Rpb24gZGVzX2FkZFBhZGRpbmcobWVzc2FnZSwgcGFkZGluZykge1xuICB2YXIgcGFkTGVuZ3RoID0gOCAtIChtZXNzYWdlLmxlbmd0aCAlIDgpO1xuICBpZiAoKHBhZGRpbmcgPT0gMikgJiYgKHBhZExlbmd0aCA8IDgpKSB7IC8vcGFkIHRoZSBtZXNzYWdlIHdpdGggc3BhY2VzXG4gICAgbWVzc2FnZSArPSBcIiAgICAgICAgXCIuc3Vic3RyKDAsIHBhZExlbmd0aCk7XG4gIH0gZWxzZSBpZiAocGFkZGluZyA9PSAxKSB7IC8vUEtDUzcgcGFkZGluZ1xuICAgIG1lc3NhZ2UgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShwYWRMZW5ndGgsIHBhZExlbmd0aCwgcGFkTGVuZ3RoLCBwYWRMZW5ndGgsIHBhZExlbmd0aCwgcGFkTGVuZ3RoLCBwYWRMZW5ndGgsXG4gICAgICBwYWRMZW5ndGgpLnN1YnN0cigwLCBwYWRMZW5ndGgpO1xuICB9IGVsc2UgaWYgKCFwYWRkaW5nICYmIChwYWRMZW5ndGggPCA4KSkgeyAvL3BhZCB0aGUgbWVzc2FnZSBvdXQgd2l0aCBudWxsIGJ5dGVzXG4gICAgbWVzc2FnZSArPSBcIlxcMFxcMFxcMFxcMFxcMFxcMFxcMFxcMFwiLnN1YnN0cigwLCBwYWRMZW5ndGgpO1xuICB9XG4gIHJldHVybiBtZXNzYWdlO1xufVxuXG5mdW5jdGlvbiBkZXNfcmVtb3ZlUGFkZGluZyhtZXNzYWdlLCBwYWRkaW5nKSB7XG4gIGlmIChwYWRkaW5nID09IDIpIHsgLy8gc3BhY2UgcGFkZGVkXG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UucmVwbGFjZSgvICokL2csIFwiXCIpO1xuICB9IGVsc2UgaWYgKHBhZGRpbmcgPT0gMSkgeyAvLyBQS0NTN1xuICAgIHZhciBwYWRDb3VudCA9IG1lc3NhZ2UuY2hhckNvZGVBdChtZXNzYWdlLmxlbmd0aCAtIDEpO1xuICAgIG1lc3NhZ2UgPSBtZXNzYWdlLnN1YnN0cigwLCBtZXNzYWdlLmxlbmd0aCAtIHBhZENvdW50KTtcbiAgfSBlbHNlIGlmICghcGFkZGluZykgeyAvLyBudWxsIHBhZGRpbmdcbiAgICBtZXNzYWdlID0gbWVzc2FnZS5yZXBsYWNlKC9cXDAqJC9nLCBcIlwiKTtcbiAgfVxuICByZXR1cm4gbWVzc2FnZTtcbn1cblxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuXG5mdW5jdGlvbiBEZXMoa2V5KSB7XG4gIHRoaXMua2V5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICB0aGlzLmtleS5wdXNoKGtleS5zdWJzdHIoaSAqIDgsIDgpKTtcbiAgfVxuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGJsb2NrKSB7XG4gICAgcmV0dXJuIHV0aWwuc3RyMmJpbihkZXMoZGVzX2NyZWF0ZUtleXModGhpcy5rZXlbMl0pLFxuICAgICAgZGVzKGRlc19jcmVhdGVLZXlzKHRoaXMua2V5WzFdKSxcbiAgICAgIGRlcyhkZXNfY3JlYXRlS2V5cyh0aGlzLmtleVswXSksXG4gICAgICB1dGlsLmJpbjJzdHIoYmxvY2spLCB0cnVlLCAwLCBudWxsLCBudWxsKSxcbiAgICAgIGZhbHNlLCAwLCBudWxsLCBudWxsKSwgdHJ1ZSwgMCwgbnVsbCwgbnVsbCkpO1xuICB9XG59XG5cbkRlcy5rZXlTaXplID0gRGVzLnByb3RvdHlwZS5rZXlTaXplID0gMjQ7XG5EZXMuYmxvY2tTaXplID0gRGVzLnByb3RvdHlwZS5ibG9ja1NpemUgPSA4O1xuXG4vLyBUaGlzIGlzIFwib3JpZ2luYWxcIiBERVMgLSBEZXMgaXMgYWN0dWFsbHkgVHJpcGxlIERFUy5cbi8vIFRoaXMgaXMgb25seSBleHBvcnRlZCBzbyB3ZSBjYW4gdW5pdCB0ZXN0LlxuXG5mdW5jdGlvbiBPcmlnaW5hbERlcyhrZXkpIHtcbiAgdGhpcy5rZXkgPSBrZXk7XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oYmxvY2ssIHBhZGRpbmcpIHtcbiAgICB2YXIga2V5cyA9IGRlc19jcmVhdGVLZXlzKHRoaXMua2V5KTtcbiAgICByZXR1cm4gdXRpbC5zdHIyYmluKGRlcyhrZXlzLCB1dGlsLmJpbjJzdHIoYmxvY2spLCB0cnVlLCAwLCBudWxsLCBwYWRkaW5nKSk7XG4gIH1cblxuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihibG9jaywgcGFkZGluZykge1xuICAgIHZhciBrZXlzID0gZGVzX2NyZWF0ZUtleXModGhpcy5rZXkpO1xuICAgIHJldHVybiB1dGlsLnN0cjJiaW4oZGVzKGtleXMsIHV0aWwuYmluMnN0cihibG9jayksIGZhbHNlLCAwLCBudWxsLCBwYWRkaW5nKSk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGRlczogRGVzLFxuICBvcmlnaW5hbERlczogT3JpZ2luYWxEZXNcbn1cbiIsInZhciBkZXNNb2R1bGUgPSByZXF1aXJlKCcuL2Rlcy5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZGVzOiBkZXNNb2R1bGVbJ2RlcyddLFxuICBvcmlnaW5hbERlczogZGVzTW9kdWxlWydvcmlnaW5hbERlcyddLFxuICBjYXN0NTogcmVxdWlyZSgnLi9jYXN0NS5qcycpLFxuICB0d29maXNoOiByZXF1aXJlKCcuL3R3b2Zpc2guanMnKSxcbiAgYmxvd2Zpc2g6IHJlcXVpcmUoJy4vYmxvd2Zpc2guanMnKVxufVxuXG52YXIgYWVzID0gcmVxdWlyZSgnLi9hZXMuanMnKTtcblxuZm9yICh2YXIgaSBpbiBhZXMpIHtcbiAgbW9kdWxlLmV4cG9ydHNbJ2FlcycgKyBpXSA9IGFlc1tpXTtcbn1cbiIsIi8qIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSCBcbiAqIFxuICogQ2lwaGVyLmpzXG4gKiBBIGJsb2NrLWNpcGhlciBhbGdvcml0aG0gaW1wbGVtZW50YXRpb24gb24gSmF2YVNjcmlwdFxuICogU2VlIENpcGhlci5yZWFkbWUudHh0IGZvciBmdXJ0aGVyIGluZm9ybWF0aW9uLlxuICpcbiAqIENvcHlyaWdodChjKSAyMDA5IEF0c3VzaGkgT2thIFsgaHR0cDovL29rYS5udS8gXVxuICogVGhpcyBzY3JpcHQgZmlsZSBpcyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTEdQTFxuICpcbiAqIEFDS05PV0xFREdNRU5UXG4gKlxuICogICAgIFRoZSBtYWluIHN1YnJvdXRpbmVzIGFyZSB3cml0dGVuIGJ5IE1pY2hpZWwgdmFuIEV2ZXJkaW5nZW4uXG4gKiBcbiAqICAgICBNaWNoaWVsIHZhbiBFdmVyZGluZ2VuXG4gKiAgICAgaHR0cDovL2hvbWUudmVyc2F0ZWwubmwvTUF2YW5FdmVyZGluZ2VuL2luZGV4Lmh0bWxcbiAqIFxuICogICAgIEFsbCByaWdodHMgZm9yIHRoZXNlIHJvdXRpbmVzIGFyZSByZXNlcnZlZCB0byBNaWNoaWVsIHZhbiBFdmVyZGluZ2VuLlxuICpcbiAqL1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4vL01hdGhcbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG52YXIgTUFYSU5UID0gMHhGRkZGRkZGRjtcblxuZnVuY3Rpb24gcm90YihiLCBuKSB7XG4gIHJldHVybiAoYiA8PCBuIHwgYiA+Pj4gKDggLSBuKSkgJiAweEZGO1xufVxuXG5mdW5jdGlvbiByb3R3KHcsIG4pIHtcbiAgcmV0dXJuICh3IDw8IG4gfCB3ID4+PiAoMzIgLSBuKSkgJiBNQVhJTlQ7XG59XG5cbmZ1bmN0aW9uIGdldFcoYSwgaSkge1xuICByZXR1cm4gYVtpXSB8IGFbaSArIDFdIDw8IDggfCBhW2kgKyAyXSA8PCAxNiB8IGFbaSArIDNdIDw8IDI0O1xufVxuXG5mdW5jdGlvbiBzZXRXKGEsIGksIHcpIHtcbiAgYS5zcGxpY2UoaSwgNCwgdyAmIDB4RkYsICh3ID4+PiA4KSAmIDB4RkYsICh3ID4+PiAxNikgJiAweEZGLCAodyA+Pj4gMjQpICYgMHhGRik7XG59XG5cbmZ1bmN0aW9uIHNldFdJbnYoYSwgaSwgdykge1xuICBhLnNwbGljZShpLCA0LCAodyA+Pj4gMjQpICYgMHhGRiwgKHcgPj4+IDE2KSAmIDB4RkYsICh3ID4+PiA4KSAmIDB4RkYsIHcgJiAweEZGKTtcbn1cblxuZnVuY3Rpb24gZ2V0Qih4LCBuKSB7XG4gIHJldHVybiAoeCA+Pj4gKG4gKiA4KSkgJiAweEZGO1xufVxuXG5mdW5jdGlvbiBnZXROckJpdHMoaSkge1xuICB2YXIgbiA9IDA7XG4gIHdoaWxlIChpID4gMCkge1xuICAgIG4rKztcbiAgICBpID4+Pj0gMTtcbiAgfVxuICByZXR1cm4gbjtcbn1cblxuZnVuY3Rpb24gZ2V0TWFzayhuKSB7XG4gIHJldHVybiAoMSA8PCBuKSAtIDE7XG59XG5cbi8vYWRkZWQgMjAwOC8xMS8xMyBYWFggTVVTVCBVU0UgT05FLVdBWSBIQVNIIEZVTkNUSU9OIEZPUiBTRUNVUklUWSBSRUFTT05cblxuZnVuY3Rpb24gcmFuZEJ5dGUoKSB7XG4gIHJldHVybiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAyNTYpO1xufVxuLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gVHdvZmlzaFxuLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuXG5mdW5jdGlvbiBjcmVhdGVUd29maXNoKCkge1xuICAvL1xuICB2YXIga2V5Qnl0ZXMgPSBudWxsO1xuICB2YXIgZGF0YUJ5dGVzID0gbnVsbDtcbiAgdmFyIGRhdGFPZmZzZXQgPSAtMTtcbiAgLy8gdmFyIGRhdGFMZW5ndGggPSAtMTtcbiAgdmFyIGFsZ29yaXRobU5hbWUgPSBudWxsO1xuICAvLyB2YXIgaWR4MiA9IC0xO1xuICAvL1xuXG4gIGFsZ29yaXRobU5hbWUgPSBcInR3b2Zpc2hcIjtcblxuICB2YXIgdGZzS2V5ID0gW107XG4gIHZhciB0ZnNNID0gW1xuICAgIFtdLFxuICAgIFtdLFxuICAgIFtdLFxuICAgIFtdXG4gIF07XG5cbiAgZnVuY3Rpb24gdGZzSW5pdChrZXkpIHtcbiAgICBrZXlCeXRlcyA9IGtleTtcbiAgICB2YXIgaSwgYSwgYiwgYywgZCwgbWVLZXkgPSBbXSxcbiAgICAgIG1vS2V5ID0gW10sXG4gICAgICBpbktleSA9IFtdO1xuICAgIHZhciBrTGVuO1xuICAgIHZhciBzS2V5ID0gW107XG4gICAgdmFyIGYwMSwgZjViLCBmZWY7XG5cbiAgICB2YXIgcTAgPSBbXG4gICAgICBbOCwgMSwgNywgMTMsIDYsIDE1LCAzLCAyLCAwLCAxMSwgNSwgOSwgMTQsIDEyLCAxMCwgNF0sXG4gICAgICBbMiwgOCwgMTEsIDEzLCAxNSwgNywgNiwgMTQsIDMsIDEsIDksIDQsIDAsIDEwLCAxMiwgNV1cbiAgICBdO1xuICAgIHZhciBxMSA9IFtcbiAgICAgIFsxNCwgMTIsIDExLCA4LCAxLCAyLCAzLCA1LCAxNSwgNCwgMTAsIDYsIDcsIDAsIDksIDEzXSxcbiAgICAgIFsxLCAxNCwgMiwgMTEsIDQsIDEyLCAzLCA3LCA2LCAxMywgMTAsIDUsIDE1LCA5LCAwLCA4XVxuICAgIF07XG4gICAgdmFyIHEyID0gW1xuICAgICAgWzExLCAxMCwgNSwgMTQsIDYsIDEzLCA5LCAwLCAxMiwgOCwgMTUsIDMsIDIsIDQsIDcsIDFdLFxuICAgICAgWzQsIDEyLCA3LCA1LCAxLCA2LCA5LCAxMCwgMCwgMTQsIDEzLCA4LCAyLCAxMSwgMywgMTVdXG4gICAgXTtcbiAgICB2YXIgcTMgPSBbXG4gICAgICBbMTMsIDcsIDE1LCA0LCAxLCAyLCA2LCAxNCwgOSwgMTEsIDMsIDAsIDgsIDUsIDEyLCAxMF0sXG4gICAgICBbMTEsIDksIDUsIDEsIDEyLCAzLCAxMywgMTQsIDYsIDQsIDcsIDE1LCAyLCAwLCA4LCAxMF1cbiAgICBdO1xuICAgIHZhciByb3I0ID0gWzAsIDgsIDEsIDksIDIsIDEwLCAzLCAxMSwgNCwgMTIsIDUsIDEzLCA2LCAxNCwgNywgMTVdO1xuICAgIHZhciBhc2h4ID0gWzAsIDksIDIsIDExLCA0LCAxMywgNiwgMTUsIDgsIDEsIDEwLCAzLCAxMiwgNSwgMTQsIDddO1xuICAgIHZhciBxID0gW1xuICAgICAgW10sXG4gICAgICBbXVxuICAgIF07XG4gICAgdmFyIG0gPSBbXG4gICAgICBbXSxcbiAgICAgIFtdLFxuICAgICAgW10sXG4gICAgICBbXVxuICAgIF07XG5cbiAgICBmdW5jdGlvbiBmZm01Yih4KSB7XG4gICAgICByZXR1cm4geCBeICh4ID4+IDIpIF4gWzAsIDkwLCAxODAsIDIzOF1beCAmIDNdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZmbUVmKHgpIHtcbiAgICAgIHJldHVybiB4IF4gKHggPj4gMSkgXiAoeCA+PiAyKSBeIFswLCAyMzgsIDE4MCwgOTBdW3ggJiAzXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtZHNSZW0ocCwgcSkge1xuICAgICAgdmFyIGksIHQsIHU7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgODsgaSsrKSB7XG4gICAgICAgIHQgPSBxID4+PiAyNDtcbiAgICAgICAgcSA9ICgocSA8PCA4KSAmIE1BWElOVCkgfCBwID4+PiAyNDtcbiAgICAgICAgcCA9IChwIDw8IDgpICYgTUFYSU5UO1xuICAgICAgICB1ID0gdCA8PCAxO1xuICAgICAgICBpZiAodCAmIDEyOCkge1xuICAgICAgICAgIHUgXj0gMzMzO1xuICAgICAgICB9XG4gICAgICAgIHEgXj0gdCBeICh1IDw8IDE2KTtcbiAgICAgICAgdSBePSB0ID4+PiAxO1xuICAgICAgICBpZiAodCAmIDEpIHtcbiAgICAgICAgICB1IF49IDE2NjtcbiAgICAgICAgfVxuICAgICAgICBxIF49IHUgPDwgMjQgfCB1IDw8IDg7XG4gICAgICB9XG4gICAgICByZXR1cm4gcTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBxcChuLCB4KSB7XG4gICAgICB2YXIgYSwgYiwgYywgZDtcbiAgICAgIGEgPSB4ID4+IDQ7XG4gICAgICBiID0geCAmIDE1O1xuICAgICAgYyA9IHEwW25dW2EgXiBiXTtcbiAgICAgIGQgPSBxMVtuXVtyb3I0W2JdIF4gYXNoeFthXV07XG4gICAgICByZXR1cm4gcTNbbl1bcm9yNFtkXSBeIGFzaHhbY11dIDw8IDQgfCBxMltuXVtjIF4gZF07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaEZ1bih4LCBrZXkpIHtcbiAgICAgIHZhciBhID0gZ2V0Qih4LCAwKSxcbiAgICAgICAgYiA9IGdldEIoeCwgMSksXG4gICAgICAgIGMgPSBnZXRCKHgsIDIpLFxuICAgICAgICBkID0gZ2V0Qih4LCAzKTtcbiAgICAgIHN3aXRjaCAoa0xlbikge1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgYSA9IHFbMV1bYV0gXiBnZXRCKGtleVszXSwgMCk7XG4gICAgICAgICAgYiA9IHFbMF1bYl0gXiBnZXRCKGtleVszXSwgMSk7XG4gICAgICAgICAgYyA9IHFbMF1bY10gXiBnZXRCKGtleVszXSwgMik7XG4gICAgICAgICAgZCA9IHFbMV1bZF0gXiBnZXRCKGtleVszXSwgMyk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBhID0gcVsxXVthXSBeIGdldEIoa2V5WzJdLCAwKTtcbiAgICAgICAgICBiID0gcVsxXVtiXSBeIGdldEIoa2V5WzJdLCAxKTtcbiAgICAgICAgICBjID0gcVswXVtjXSBeIGdldEIoa2V5WzJdLCAyKTtcbiAgICAgICAgICBkID0gcVswXVtkXSBeIGdldEIoa2V5WzJdLCAzKTtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIGEgPSBxWzBdW3FbMF1bYV0gXiBnZXRCKGtleVsxXSwgMCldIF4gZ2V0QihrZXlbMF0sIDApO1xuICAgICAgICAgIGIgPSBxWzBdW3FbMV1bYl0gXiBnZXRCKGtleVsxXSwgMSldIF4gZ2V0QihrZXlbMF0sIDEpO1xuICAgICAgICAgIGMgPSBxWzFdW3FbMF1bY10gXiBnZXRCKGtleVsxXSwgMildIF4gZ2V0QihrZXlbMF0sIDIpO1xuICAgICAgICAgIGQgPSBxWzFdW3FbMV1bZF0gXiBnZXRCKGtleVsxXSwgMyldIF4gZ2V0QihrZXlbMF0sIDMpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG1bMF1bYV0gXiBtWzFdW2JdIF4gbVsyXVtjXSBeIG1bM11bZF07XG4gICAgfVxuXG4gICAga2V5Qnl0ZXMgPSBrZXlCeXRlcy5zbGljZSgwLCAzMik7XG4gICAgaSA9IGtleUJ5dGVzLmxlbmd0aDtcbiAgICB3aGlsZSAoaSAhPSAxNiAmJiBpICE9IDI0ICYmIGkgIT0gMzIpXG4gICAgICBrZXlCeXRlc1tpKytdID0gMDtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBrZXlCeXRlcy5sZW5ndGg7IGkgKz0gNCkge1xuICAgICAgaW5LZXlbaSA+PiAyXSA9IGdldFcoa2V5Qnl0ZXMsIGkpO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgMjU2OyBpKyspIHtcbiAgICAgIHFbMF1baV0gPSBxcCgwLCBpKTtcbiAgICAgIHFbMV1baV0gPSBxcCgxLCBpKTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG4gICAgICBmMDEgPSBxWzFdW2ldO1xuICAgICAgZjViID0gZmZtNWIoZjAxKTtcbiAgICAgIGZlZiA9IGZmbUVmKGYwMSk7XG4gICAgICBtWzBdW2ldID0gZjAxICsgKGY1YiA8PCA4KSArIChmZWYgPDwgMTYpICsgKGZlZiA8PCAyNCk7XG4gICAgICBtWzJdW2ldID0gZjViICsgKGZlZiA8PCA4KSArIChmMDEgPDwgMTYpICsgKGZlZiA8PCAyNCk7XG4gICAgICBmMDEgPSBxWzBdW2ldO1xuICAgICAgZjViID0gZmZtNWIoZjAxKTtcbiAgICAgIGZlZiA9IGZmbUVmKGYwMSk7XG4gICAgICBtWzFdW2ldID0gZmVmICsgKGZlZiA8PCA4KSArIChmNWIgPDwgMTYpICsgKGYwMSA8PCAyNCk7XG4gICAgICBtWzNdW2ldID0gZjViICsgKGYwMSA8PCA4KSArIChmZWYgPDwgMTYpICsgKGY1YiA8PCAyNCk7XG4gICAgfVxuXG4gICAga0xlbiA9IGluS2V5Lmxlbmd0aCAvIDI7XG4gICAgZm9yIChpID0gMDsgaSA8IGtMZW47IGkrKykge1xuICAgICAgYSA9IGluS2V5W2kgKyBpXTtcbiAgICAgIG1lS2V5W2ldID0gYTtcbiAgICAgIGIgPSBpbktleVtpICsgaSArIDFdO1xuICAgICAgbW9LZXlbaV0gPSBiO1xuICAgICAgc0tleVtrTGVuIC0gaSAtIDFdID0gbWRzUmVtKGEsIGIpO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgNDA7IGkgKz0gMikge1xuICAgICAgYSA9IDB4MTAxMDEwMSAqIGk7XG4gICAgICBiID0gYSArIDB4MTAxMDEwMTtcbiAgICAgIGEgPSBoRnVuKGEsIG1lS2V5KTtcbiAgICAgIGIgPSByb3R3KGhGdW4oYiwgbW9LZXkpLCA4KTtcbiAgICAgIHRmc0tleVtpXSA9IChhICsgYikgJiBNQVhJTlQ7XG4gICAgICB0ZnNLZXlbaSArIDFdID0gcm90dyhhICsgMiAqIGIsIDkpO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgMjU2OyBpKyspIHtcbiAgICAgIGEgPSBiID0gYyA9IGQgPSBpO1xuICAgICAgc3dpdGNoIChrTGVuKSB7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICBhID0gcVsxXVthXSBeIGdldEIoc0tleVszXSwgMCk7XG4gICAgICAgICAgYiA9IHFbMF1bYl0gXiBnZXRCKHNLZXlbM10sIDEpO1xuICAgICAgICAgIGMgPSBxWzBdW2NdIF4gZ2V0QihzS2V5WzNdLCAyKTtcbiAgICAgICAgICBkID0gcVsxXVtkXSBeIGdldEIoc0tleVszXSwgMyk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBhID0gcVsxXVthXSBeIGdldEIoc0tleVsyXSwgMCk7XG4gICAgICAgICAgYiA9IHFbMV1bYl0gXiBnZXRCKHNLZXlbMl0sIDEpO1xuICAgICAgICAgIGMgPSBxWzBdW2NdIF4gZ2V0QihzS2V5WzJdLCAyKTtcbiAgICAgICAgICBkID0gcVswXVtkXSBeIGdldEIoc0tleVsyXSwgMyk7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICB0ZnNNWzBdW2ldID0gbVswXVtxWzBdW3FbMF1bYV0gXiBnZXRCKHNLZXlbMV0sIDApXSBeIGdldEIoc0tleVswXSwgMCldO1xuICAgICAgICAgIHRmc01bMV1baV0gPSBtWzFdW3FbMF1bcVsxXVtiXSBeIGdldEIoc0tleVsxXSwgMSldIF4gZ2V0QihzS2V5WzBdLCAxKV07XG4gICAgICAgICAgdGZzTVsyXVtpXSA9IG1bMl1bcVsxXVtxWzBdW2NdIF4gZ2V0QihzS2V5WzFdLCAyKV0gXiBnZXRCKHNLZXlbMF0sIDIpXTtcbiAgICAgICAgICB0ZnNNWzNdW2ldID0gbVszXVtxWzFdW3FbMV1bZF0gXiBnZXRCKHNLZXlbMV0sIDMpXSBeIGdldEIoc0tleVswXSwgMyldO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRmc0cwKHgpIHtcbiAgICByZXR1cm4gdGZzTVswXVtnZXRCKHgsIDApXSBeIHRmc01bMV1bZ2V0Qih4LCAxKV0gXiB0ZnNNWzJdW2dldEIoeCwgMildIF4gdGZzTVszXVtnZXRCKHgsIDMpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRmc0cxKHgpIHtcbiAgICByZXR1cm4gdGZzTVswXVtnZXRCKHgsIDMpXSBeIHRmc01bMV1bZ2V0Qih4LCAwKV0gXiB0ZnNNWzJdW2dldEIoeCwgMSldIF4gdGZzTVszXVtnZXRCKHgsIDIpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRmc0ZybmQociwgYmxrKSB7XG4gICAgdmFyIGEgPSB0ZnNHMChibGtbMF0pO1xuICAgIHZhciBiID0gdGZzRzEoYmxrWzFdKTtcbiAgICBibGtbMl0gPSByb3R3KGJsa1syXSBeIChhICsgYiArIHRmc0tleVs0ICogciArIDhdKSAmIE1BWElOVCwgMzEpO1xuICAgIGJsa1szXSA9IHJvdHcoYmxrWzNdLCAxKSBeIChhICsgMiAqIGIgKyB0ZnNLZXlbNCAqIHIgKyA5XSkgJiBNQVhJTlQ7XG4gICAgYSA9IHRmc0cwKGJsa1syXSk7XG4gICAgYiA9IHRmc0cxKGJsa1szXSk7XG4gICAgYmxrWzBdID0gcm90dyhibGtbMF0gXiAoYSArIGIgKyB0ZnNLZXlbNCAqIHIgKyAxMF0pICYgTUFYSU5ULCAzMSk7XG4gICAgYmxrWzFdID0gcm90dyhibGtbMV0sIDEpIF4gKGEgKyAyICogYiArIHRmc0tleVs0ICogciArIDExXSkgJiBNQVhJTlQ7XG4gIH1cblxuICBmdW5jdGlvbiB0ZnNJcm5kKGksIGJsaykge1xuICAgIHZhciBhID0gdGZzRzAoYmxrWzBdKTtcbiAgICB2YXIgYiA9IHRmc0cxKGJsa1sxXSk7XG4gICAgYmxrWzJdID0gcm90dyhibGtbMl0sIDEpIF4gKGEgKyBiICsgdGZzS2V5WzQgKiBpICsgMTBdKSAmIE1BWElOVDtcbiAgICBibGtbM10gPSByb3R3KGJsa1szXSBeIChhICsgMiAqIGIgKyB0ZnNLZXlbNCAqIGkgKyAxMV0pICYgTUFYSU5ULCAzMSk7XG4gICAgYSA9IHRmc0cwKGJsa1syXSk7XG4gICAgYiA9IHRmc0cxKGJsa1szXSk7XG4gICAgYmxrWzBdID0gcm90dyhibGtbMF0sIDEpIF4gKGEgKyBiICsgdGZzS2V5WzQgKiBpICsgOF0pICYgTUFYSU5UO1xuICAgIGJsa1sxXSA9IHJvdHcoYmxrWzFdIF4gKGEgKyAyICogYiArIHRmc0tleVs0ICogaSArIDldKSAmIE1BWElOVCwgMzEpO1xuICB9XG5cbiAgZnVuY3Rpb24gdGZzQ2xvc2UoKSB7XG4gICAgdGZzS2V5ID0gW107XG4gICAgdGZzTSA9IFtcbiAgICAgIFtdLFxuICAgICAgW10sXG4gICAgICBbXSxcbiAgICAgIFtdXG4gICAgXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRmc0VuY3J5cHQoZGF0YSwgb2Zmc2V0KSB7XG4gICAgZGF0YUJ5dGVzID0gZGF0YTtcbiAgICBkYXRhT2Zmc2V0ID0gb2Zmc2V0O1xuICAgIHZhciBibGsgPSBbZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQpIF4gdGZzS2V5WzBdLFxuICAgICAgICBnZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDQpIF4gdGZzS2V5WzFdLFxuICAgICAgICBnZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDgpIF4gdGZzS2V5WzJdLFxuICAgICAgICBnZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDEyKSBeIHRmc0tleVszXVxuICAgIF07XG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCA4OyBqKyspIHtcbiAgICAgIHRmc0ZybmQoaiwgYmxrKTtcbiAgICB9XG4gICAgc2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQsIGJsa1syXSBeIHRmc0tleVs0XSk7XG4gICAgc2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA0LCBibGtbM10gXiB0ZnNLZXlbNV0pO1xuICAgIHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0ICsgOCwgYmxrWzBdIF4gdGZzS2V5WzZdKTtcbiAgICBzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDEyLCBibGtbMV0gXiB0ZnNLZXlbN10pO1xuICAgIGRhdGFPZmZzZXQgKz0gMTY7XG4gICAgcmV0dXJuIGRhdGFCeXRlcztcbiAgfVxuXG4gIGZ1bmN0aW9uIHRmc0RlY3J5cHQoZGF0YSwgb2Zmc2V0KSB7XG4gICAgZGF0YUJ5dGVzID0gZGF0YTtcbiAgICBkYXRhT2Zmc2V0ID0gb2Zmc2V0O1xuICAgIHZhciBibGsgPSBbZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQpIF4gdGZzS2V5WzRdLFxuICAgICAgICBnZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDQpIF4gdGZzS2V5WzVdLFxuICAgICAgICBnZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDgpIF4gdGZzS2V5WzZdLFxuICAgICAgICBnZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDEyKSBeIHRmc0tleVs3XVxuICAgIF07XG4gICAgZm9yICh2YXIgaiA9IDc7IGogPj0gMDsgai0tKSB7XG4gICAgICB0ZnNJcm5kKGosIGJsayk7XG4gICAgfVxuICAgIHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0LCBibGtbMl0gXiB0ZnNLZXlbMF0pO1xuICAgIHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0ICsgNCwgYmxrWzNdIF4gdGZzS2V5WzFdKTtcbiAgICBzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDgsIGJsa1swXSBeIHRmc0tleVsyXSk7XG4gICAgc2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMiwgYmxrWzFdIF4gdGZzS2V5WzNdKTtcbiAgICBkYXRhT2Zmc2V0ICs9IDE2O1xuICB9XG5cbiAgLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuXG4gIGZ1bmN0aW9uIHRmc0ZpbmFsKCkge1xuICAgIHJldHVybiBkYXRhQnl0ZXM7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWU6IFwidHdvZmlzaFwiLFxuICAgIGJsb2Nrc2l6ZTogMTI4IC8gOCxcbiAgICBvcGVuOiB0ZnNJbml0LFxuICAgIGNsb3NlOiB0ZnNDbG9zZSxcbiAgICBlbmNyeXB0OiB0ZnNFbmNyeXB0LFxuICAgIGRlY3J5cHQ6IHRmc0RlY3J5cHQsXG4gICAgLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuICAgIGZpbmFsaXplOiB0ZnNGaW5hbFxuICB9O1xufVxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuXG5mdW5jdGlvbiBURmVuY3J5cHQoYmxvY2ssIGtleSkge1xuICB2YXIgYmxvY2tfY29weSA9IFtdLmNvbmNhdChibG9jayk7XG4gIHZhciB0ZiA9IGNyZWF0ZVR3b2Zpc2goKTtcbiAgdGYub3Blbih1dGlsLnN0cjJiaW4oa2V5KSwgMCk7XG4gIHZhciByZXN1bHQgPSB0Zi5lbmNyeXB0KGJsb2NrX2NvcHksIDApO1xuICB0Zi5jbG9zZSgpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBURihrZXkpIHtcbiAgdGhpcy50ZiA9IGNyZWF0ZVR3b2Zpc2goKTtcbiAgdGhpcy50Zi5vcGVuKHV0aWwuc3RyMmJpbihrZXkpLCAwKTtcblxuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihibG9jaykge1xuICAgIHJldHVybiB0aGlzLnRmLmVuY3J5cHQoW10uY29uY2F0KGJsb2NrKSwgMCk7XG4gIH1cbn1cblxuXG5tb2R1bGUuZXhwb3J0cyA9IFRGO1xubW9kdWxlLmV4cG9ydHMua2V5U2l6ZSA9IFRGLnByb3RvdHlwZS5rZXlTaXplID0gMzI7XG5tb2R1bGUuZXhwb3J0cy5ibG9ja1NpemUgPSBURi5wcm90b3R5cGUuYmxvY2tTaXplID0gMTY7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQSBcblxuLy8gVGhlIEdQRzRCcm93c2VycyBjcnlwdG8gaW50ZXJmYWNlXG5cbnZhciByYW5kb20gPSByZXF1aXJlKCcuL3JhbmRvbS5qcycpLFxuICBjaXBoZXIgPSByZXF1aXJlKCcuL2NpcGhlcicpLFxuICBwdWJsaWNLZXkgPSByZXF1aXJlKCcuL3B1YmxpY19rZXknKSxcbiAgdHlwZV9tcGkgPSByZXF1aXJlKCcuLi90eXBlL21waS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgLyoqXG4gICAqIEVuY3J5cHRzIGRhdGEgdXNpbmcgdGhlIHNwZWNpZmllZCBwdWJsaWMga2V5IG11bHRpcHJlY2lzaW9uIGludGVnZXJzIFxuICAgKiBhbmQgdGhlIHNwZWNpZmllZCBhbGdvcml0aG0uXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gYWxnbyBBbGdvcml0aG0gdG8gYmUgdXNlZCAoU2VlIFJGQzQ4ODAgOS4xKVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gcHVibGljTVBJcyBBbGdvcml0aG0gZGVwZW5kZW50IG11bHRpcHJlY2lzaW9uIGludGVnZXJzXG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waX0gZGF0YSBEYXRhIHRvIGJlIGVuY3J5cHRlZCBhcyBNUElcbiAgICogQHJldHVybiB7b3BlbnBncF90eXBlX21waVtdfSBpZiBSU0EgYW4gb3BlbnBncF90eXBlX21waTsgXG4gICAqIGlmIGVsZ2FtYWwgZW5jcnlwdGlvbiBhbiBhcnJheSBvZiB0d28gb3BlbnBncF90eXBlX21waSBpcyByZXR1cm5lZDsgb3RoZXJ3aXNlIG51bGxcbiAgICovXG4gIHB1YmxpY0tleUVuY3J5cHQ6IGZ1bmN0aW9uKGFsZ28sIHB1YmxpY01QSXMsIGRhdGEpIHtcbiAgICB2YXIgcmVzdWx0ID0gKGZ1bmN0aW9uKCkge1xuICAgICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0JzpcbiAgICAgICAgY2FzZSAncnNhX2VuY3J5cHRfc2lnbic6XG4gICAgICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICAgICAgdmFyIG4gPSBwdWJsaWNNUElzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBlID0gcHVibGljTVBJc1sxXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgbSA9IGRhdGEudG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgcmV0dXJuIFtyc2EuZW5jcnlwdChtLCBlLCBuKV07XG5cbiAgICAgICAgY2FzZSAnZWxnYW1hbCc6XG4gICAgICAgICAgdmFyIGVsZ2FtYWwgPSBuZXcgcHVibGljS2V5LmVsZ2FtYWwoKTtcbiAgICAgICAgICB2YXIgcCA9IHB1YmxpY01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIGcgPSBwdWJsaWNNUElzWzFdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciB5ID0gcHVibGljTVBJc1syXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgbSA9IGRhdGEudG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgcmV0dXJuIGVsZ2FtYWwuZW5jcnlwdChtLCBnLCBwLCB5KTtcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgcmV0dXJuIHJlc3VsdC5tYXAoZnVuY3Rpb24oYm4pIHtcbiAgICAgIHZhciBtcGkgPSBuZXcgdHlwZV9tcGkoKTtcbiAgICAgIG1waS5mcm9tQmlnSW50ZWdlcihibik7XG4gICAgICByZXR1cm4gbXBpO1xuICAgIH0pO1xuICB9LFxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyBkYXRhIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHVibGljIGtleSBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBvZiB0aGUgcHJpdmF0ZSBrZXksXG4gICAqIHRoZSBzcGVjaWZpZWQgc2VjcmV0TVBJcyBvZiB0aGUgcHJpdmF0ZSBrZXkgYW5kIHRoZSBzcGVjaWZpZWQgYWxnb3JpdGhtLlxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIGJlIHVzZWQgKFNlZSBSRkM0ODgwIDkuMSlcbiAgICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IHB1YmxpY01QSXMgQWxnb3JpdGhtIGRlcGVuZGVudCBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBcbiAgICogb2YgdGhlIHB1YmxpYyBrZXkgcGFydCBvZiB0aGUgcHJpdmF0ZSBrZXlcbiAgICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IHNlY3JldE1QSXMgQWxnb3JpdGhtIGRlcGVuZGVudCBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBcbiAgICogb2YgdGhlIHByaXZhdGUga2V5IHVzZWRcbiAgICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpfSBkYXRhIERhdGEgdG8gYmUgZW5jcnlwdGVkIGFzIE1QSVxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3R5cGVfbXBpfSByZXR1cm5zIGEgYmlnIGludGVnZXIgY29udGFpbmluZyB0aGUgZGVjcnlwdGVkIGRhdGE7IG90aGVyd2lzZSBudWxsXG4gICAqL1xuXG4gIHB1YmxpY0tleURlY3J5cHQ6IGZ1bmN0aW9uKGFsZ28sIGtleUludGVnZXJzLCBkYXRhSW50ZWdlcnMpIHtcbiAgICB2YXIgYm4gPSAoZnVuY3Rpb24oKSB7XG4gICAgICBzd2l0Y2ggKGFsZ28pIHtcbiAgICAgICAgY2FzZSAncnNhX2VuY3J5cHRfc2lnbic6XG4gICAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0JzpcbiAgICAgICAgICB2YXIgcnNhID0gbmV3IHB1YmxpY0tleS5yc2EoKTtcbiAgICAgICAgICAvLyAwIGFuZCAxIGFyZSB0aGUgcHVibGljIGtleS5cbiAgICAgICAgICB2YXIgZCA9IGtleUludGVnZXJzWzJdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBwID0ga2V5SW50ZWdlcnNbM10udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIHEgPSBrZXlJbnRlZ2Vyc1s0XS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgdSA9IGtleUludGVnZXJzWzVdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBtID0gZGF0YUludGVnZXJzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHJldHVybiByc2EuZGVjcnlwdChtLCBkLCBwLCBxLCB1KTtcbiAgICAgICAgY2FzZSAnZWxnYW1hbCc6XG4gICAgICAgICAgdmFyIGVsZ2FtYWwgPSBuZXcgcHVibGljS2V5LmVsZ2FtYWwoKTtcbiAgICAgICAgICB2YXIgeCA9IGtleUludGVnZXJzWzNdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBjMSA9IGRhdGFJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgYzIgPSBkYXRhSW50ZWdlcnNbMV0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIHAgPSBrZXlJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICByZXR1cm4gZWxnYW1hbC5kZWNyeXB0KGMxLCBjMiwgcCwgeCk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIHZhciByZXN1bHQgPSBuZXcgdHlwZV9tcGkoKTtcbiAgICByZXN1bHQuZnJvbUJpZ0ludGVnZXIoYm4pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgLyoqIFJldHVybnMgdGhlIG51bWJlciBvZiBpbnRlZ2VycyBjb21wcmlzaW5nIHRoZSBwcml2YXRlIGtleSBvZiBhbiBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtvcGVucGdwLnB1YmxpY2tleX0gYWxnbyBUaGUgcHVibGljIGtleSBhbGdvcml0aG1cbiAgICogQHJldHVybiB7SW50ZWdlcn0gVGhlIG51bWJlciBvZiBpbnRlZ2Vycy5cbiAgICovXG4gIGdldFByaXZhdGVNcGlDb3VudDogZnVuY3Rpb24oYWxnbykge1xuICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgICAgY2FzZSAncnNhX2VuY3J5cHRfc2lnbic6XG4gICAgICBjYXNlICdyc2Ffc2lnbic6XG4gICAgICAgIC8vICAgQWxnb3JpdGhtLVNwZWNpZmljIEZpZWxkcyBmb3IgUlNBIHNlY3JldCBrZXlzOlxuICAgICAgICAvLyAgIC0gbXVsdGlwcmVjaXNpb24gaW50ZWdlciAoTVBJKSBvZiBSU0Egc2VjcmV0IGV4cG9uZW50IGQuXG4gICAgICAgIC8vICAgLSBNUEkgb2YgUlNBIHNlY3JldCBwcmltZSB2YWx1ZSBwLlxuICAgICAgICAvLyAgIC0gTVBJIG9mIFJTQSBzZWNyZXQgcHJpbWUgdmFsdWUgcSAocCA8IHEpLlxuICAgICAgICAvLyAgIC0gTVBJIG9mIHUsIHRoZSBtdWx0aXBsaWNhdGl2ZSBpbnZlcnNlIG9mIHAsIG1vZCBxLlxuICAgICAgICByZXR1cm4gNDtcbiAgICAgIGNhc2UgJ2VsZ2FtYWwnOlxuICAgICAgICAvLyBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBFbGdhbWFsIHNlY3JldCBrZXlzOlxuICAgICAgICAvLyAgIC0gTVBJIG9mIEVsZ2FtYWwgc2VjcmV0IGV4cG9uZW50IHguXG4gICAgICAgIHJldHVybiAxO1xuICAgICAgY2FzZSAnZHNhJzpcbiAgICAgICAgLy8gQWxnb3JpdGhtLVNwZWNpZmljIEZpZWxkcyBmb3IgRFNBIHNlY3JldCBrZXlzOlxuICAgICAgICAvLyAgIC0gTVBJIG9mIERTQSBzZWNyZXQgZXhwb25lbnQgeC5cbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gYWxnb3JpdGhtJyk7XG4gICAgfVxuICB9LFxuXG4gIGdldFB1YmxpY01waUNvdW50OiBmdW5jdGlvbihhbGdvKSB7XG4gICAgLy8gLSBBIHNlcmllcyBvZiBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBjb21wcmlzaW5nIHRoZSBrZXkgbWF0ZXJpYWw6XG4gICAgLy8gICBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBSU0EgcHVibGljIGtleXM6XG4gICAgLy8gICAgICAgLSBhIG11bHRpcHJlY2lzaW9uIGludGVnZXIgKE1QSSkgb2YgUlNBIHB1YmxpYyBtb2R1bHVzIG47XG4gICAgLy8gICAgICAgLSBhbiBNUEkgb2YgUlNBIHB1YmxpYyBlbmNyeXB0aW9uIGV4cG9uZW50IGUuXG4gICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICBjYXNlICdyc2FfZW5jcnlwdCc6XG4gICAgICBjYXNlICdyc2FfZW5jcnlwdF9zaWduJzpcbiAgICAgIGNhc2UgJ3JzYV9zaWduJzpcbiAgICAgICAgcmV0dXJuIDI7XG5cbiAgICAgICAgLy8gICBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBFbGdhbWFsIHB1YmxpYyBrZXlzOlxuICAgICAgICAvLyAgICAgLSBNUEkgb2YgRWxnYW1hbCBwcmltZSBwO1xuICAgICAgICAvLyAgICAgLSBNUEkgb2YgRWxnYW1hbCBncm91cCBnZW5lcmF0b3IgZztcbiAgICAgICAgLy8gICAgIC0gTVBJIG9mIEVsZ2FtYWwgcHVibGljIGtleSB2YWx1ZSB5ICg9IGcqKnggbW9kIHAgd2hlcmUgeCAgaXMgc2VjcmV0KS5cbiAgICAgIGNhc2UgJ2VsZ2FtYWwnOlxuICAgICAgICByZXR1cm4gMztcblxuICAgICAgICAvLyAgIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIERTQSBwdWJsaWMga2V5czpcbiAgICAgICAgLy8gICAgICAgLSBNUEkgb2YgRFNBIHByaW1lIHA7XG4gICAgICAgIC8vICAgICAgIC0gTVBJIG9mIERTQSBncm91cCBvcmRlciBxIChxIGlzIGEgcHJpbWUgZGl2aXNvciBvZiBwLTEpO1xuICAgICAgICAvLyAgICAgICAtIE1QSSBvZiBEU0EgZ3JvdXAgZ2VuZXJhdG9yIGc7XG4gICAgICAgIC8vICAgICAgIC0gTVBJIG9mIERTQSBwdWJsaWMta2V5IHZhbHVlIHkgKD0gZyoqeCBtb2QgcCB3aGVyZSB4ICBpcyBzZWNyZXQpLlxuICAgICAgY2FzZSAnZHNhJzpcbiAgICAgICAgcmV0dXJuIDQ7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBhbGdvcml0aG0uJyk7XG4gICAgfVxuICB9LFxuXG4gIGdlbmVyYXRlTXBpOiBmdW5jdGlvbihhbGdvLCBiaXRzKSB7XG4gICAgdmFyIHJlc3VsdCA9IChmdW5jdGlvbigpIHtcbiAgICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgICBjYXNlICdyc2FfZW5jcnlwdCc6XG4gICAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgICAgICBjYXNlICdyc2Ffc2lnbic6XG4gICAgICAgICAgLy9yZW1lbWJlciBcInB1YmxpY0tleVwiIHJlZmVycyB0byB0aGUgY3J5cHRvL3B1YmxpY19rZXkgZGlyXG4gICAgICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICAgICAgdmFyIGtleU9iamVjdCA9IHJzYS5nZW5lcmF0ZShiaXRzLCBcIjEwMDAxXCIpO1xuICAgICAgICAgIHZhciBvdXRwdXQgPSBbXTtcbiAgICAgICAgICBvdXRwdXQucHVzaChrZXlPYmplY3Qubik7XG4gICAgICAgICAgb3V0cHV0LnB1c2goa2V5T2JqZWN0LmVlKTtcbiAgICAgICAgICBvdXRwdXQucHVzaChrZXlPYmplY3QuZCk7XG4gICAgICAgICAgb3V0cHV0LnB1c2goa2V5T2JqZWN0LnApO1xuICAgICAgICAgIG91dHB1dC5wdXNoKGtleU9iamVjdC5xKTtcbiAgICAgICAgICBvdXRwdXQucHVzaChrZXlPYmplY3QudSk7XG4gICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIGFsZ29yaXRobSBmb3Iga2V5IGdlbmVyYXRpb24uJyk7XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIHJldHVybiByZXN1bHQubWFwKGZ1bmN0aW9uKGJuKSB7XG4gICAgICB2YXIgbXBpID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgICBtcGkuZnJvbUJpZ0ludGVnZXIoYm4pO1xuICAgICAgcmV0dXJuIG1waTtcbiAgICB9KTtcbiAgfSxcblxuXG4gIC8qKlxuICAgKiBnZW5lcmF0ZSByYW5kb20gYnl0ZSBwcmVmaXggYXMgc3RyaW5nIGZvciB0aGUgc3BlY2lmaWVkIGFsZ29yaXRobVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIHVzZSAoc2VlIFJGQzQ4ODAgOS4yKVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFJhbmRvbSBieXRlcyB3aXRoIGxlbmd0aCBlcXVhbCB0byB0aGUgYmxvY2tcbiAgICogc2l6ZSBvZiB0aGUgY2lwaGVyXG4gICAqL1xuICBnZXRQcmVmaXhSYW5kb206IGZ1bmN0aW9uKGFsZ28pIHtcbiAgICByZXR1cm4gcmFuZG9tLmdldFJhbmRvbUJ5dGVzKGNpcGhlclthbGdvXS5ibG9ja1NpemUpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZW5lcmF0aW5nIGEgc2Vzc2lvbiBrZXkgZm9yIHRoZSBzcGVjaWZpZWQgc3ltbWV0cmljIGFsZ29yaXRobVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIHVzZSAoc2VlIFJGQzQ4ODAgOS4yKVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFJhbmRvbSBieXRlcyBhcyBhIHN0cmluZyB0byBiZSB1c2VkIGFzIGEga2V5XG4gICAqL1xuICBnZW5lcmF0ZVNlc3Npb25LZXk6IGZ1bmN0aW9uKGFsZ28pIHtcbiAgICByZXR1cm4gcmFuZG9tLmdldFJhbmRvbUJ5dGVzKGNpcGhlclthbGdvXS5rZXlTaXplKTtcbiAgfSxcblxufTtcbiIsInZhciBzaGEgPSByZXF1aXJlKCcuL3NoYS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbWQ1OiByZXF1aXJlKCcuL21kNS5qcycpLFxuICBzaGExOiBzaGEuc2hhMSxcbiAgc2hhMjU2OiBzaGEuc2hhMjU2LFxuICBzaGEyMjQ6IHNoYS5zaGEyMjQsXG4gIHNoYTM4NDogc2hhLnNoYTM4NCxcbiAgc2hhNTEyOiBzaGEuc2hhNTEyLFxuICByaXBlbWQ6IHJlcXVpcmUoJy4vcmlwZS1tZC5qcycpLFxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBoYXNoIG9uIHRoZSBzcGVjaWZpZWQgZGF0YSB1c2luZyB0aGUgc3BlY2lmaWVkIGFsZ29yaXRobVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gSGFzaCBhbGdvcml0aG0gdHlwZSAoc2VlIFJGQzQ4ODAgOS40KVxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIHRvIGJlIGhhc2hlZFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGhhc2ggdmFsdWVcbiAgICovXG4gIGRpZ2VzdDogZnVuY3Rpb24oYWxnbywgZGF0YSkge1xuICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgY2FzZSAxOlxuICAgICAgICAvLyAtIE1ENSBbSEFDXVxuICAgICAgICByZXR1cm4gdGhpcy5tZDUoZGF0YSk7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIC8vIC0gU0hBLTEgW0ZJUFMxODBdXG4gICAgICAgIHJldHVybiB0aGlzLnNoYTEoZGF0YSk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vIC0gUklQRS1NRC8xNjAgW0hBQ11cbiAgICAgICAgcmV0dXJuIHRoaXMucmlwZW1kKGRhdGEpO1xuICAgICAgY2FzZSA4OlxuICAgICAgICAvLyAtIFNIQTI1NiBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2hhMjU2KGRhdGEpO1xuICAgICAgY2FzZSA5OlxuICAgICAgICAvLyAtIFNIQTM4NCBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2hhMzg0KGRhdGEpO1xuICAgICAgY2FzZSAxMDpcbiAgICAgICAgLy8gLSBTSEE1MTIgW0ZJUFMxODBdXG4gICAgICAgIHJldHVybiB0aGlzLnNoYTUxMihkYXRhKTtcbiAgICAgIGNhc2UgMTE6XG4gICAgICAgIC8vIC0gU0hBMjI0IFtGSVBTMTgwXVxuICAgICAgICByZXR1cm4gdGhpcy5zaGEyMjQoZGF0YSk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaGFzaCBmdW5jdGlvbi4nKTtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGhhc2ggc2l6ZSBpbiBieXRlcyBvZiB0aGUgc3BlY2lmaWVkIGhhc2ggYWxnb3JpdGhtIHR5cGVcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEhhc2ggYWxnb3JpdGhtIHR5cGUgKFNlZSBSRkM0ODgwIDkuNClcbiAgICogQHJldHVybiB7SW50ZWdlcn0gU2l6ZSBpbiBieXRlcyBvZiB0aGUgcmVzdWx0aW5nIGhhc2hcbiAgICovXG4gIGdldEhhc2hCeXRlTGVuZ3RoOiBmdW5jdGlvbihhbGdvKSB7XG4gICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIC8vIC0gTUQ1IFtIQUNdXG4gICAgICAgIHJldHVybiAxNjtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgLy8gLSBTSEEtMSBbRklQUzE4MF1cbiAgICAgIGNhc2UgMzpcbiAgICAgICAgLy8gLSBSSVBFLU1ELzE2MCBbSEFDXVxuICAgICAgICByZXR1cm4gMjA7XG4gICAgICBjYXNlIDg6XG4gICAgICAgIC8vIC0gU0hBMjU2IFtGSVBTMTgwXVxuICAgICAgICByZXR1cm4gMzI7XG4gICAgICBjYXNlIDk6XG4gICAgICAgIC8vIC0gU0hBMzg0IFtGSVBTMTgwXVxuICAgICAgICByZXR1cm4gNDhcbiAgICAgIGNhc2UgMTA6XG4gICAgICAgIC8vIC0gU0hBNTEyIFtGSVBTMTgwXVxuICAgICAgICByZXR1cm4gNjQ7XG4gICAgICBjYXNlIDExOlxuICAgICAgICAvLyAtIFNIQTIyNCBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIDI4O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhhc2ggYWxnb3JpdGhtLicpO1xuICAgIH1cbiAgfVxuXG59XG4iLCIvKipcbiAqIEEgZmFzdCBNRDUgSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvblxuICogQ29weXJpZ2h0IChjKSAyMDEyIEpvc2VwaCBNeWVyc1xuICogaHR0cDovL3d3dy5teWVyc2RhaWx5Lm9yZy9qb3NlcGgvamF2YXNjcmlwdC9tZDUtdGV4dC5odG1sXG4gKlxuICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZVxuICogYW5kIGl0cyBkb2N1bWVudGF0aW9uIGZvciBhbnkgcHVycG9zZXMgYW5kIHdpdGhvdXRcbiAqIGZlZSBpcyBoZXJlYnkgZ3JhbnRlZCBwcm92aWRlZCB0aGF0IHRoaXMgY29weXJpZ2h0IG5vdGljZVxuICogYXBwZWFycyBpbiBhbGwgY29waWVzLlxuICpcbiAqIE9mIGNvdXJzZSwgdGhpcyBzb2Z0IGlzIHByb3ZpZGVkIFwiYXMgaXNcIiB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZFxuICogd2FycmFudHkgb2YgYW55IGtpbmQuXG4gKi9cblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsL3V0aWwuanMnKTtcblxuZnVuY3Rpb24gTUQ1KGVudHJlZSkge1xuICB2YXIgaGV4ID0gbWQ1KGVudHJlZSk7XG4gIHZhciBiaW4gPSB1dGlsLmhleDJiaW4oaGV4KTtcbiAgcmV0dXJuIGJpbjtcbn1cblxuZnVuY3Rpb24gbWQ1Y3ljbGUoeCwgaykge1xuICB2YXIgYSA9IHhbMF0sXG4gICAgYiA9IHhbMV0sXG4gICAgYyA9IHhbMl0sXG4gICAgZCA9IHhbM107XG5cbiAgYSA9IGZmKGEsIGIsIGMsIGQsIGtbMF0sIDcsIC02ODA4NzY5MzYpO1xuICBkID0gZmYoZCwgYSwgYiwgYywga1sxXSwgMTIsIC0zODk1NjQ1ODYpO1xuICBjID0gZmYoYywgZCwgYSwgYiwga1syXSwgMTcsIDYwNjEwNTgxOSk7XG4gIGIgPSBmZihiLCBjLCBkLCBhLCBrWzNdLCAyMiwgLTEwNDQ1MjUzMzApO1xuICBhID0gZmYoYSwgYiwgYywgZCwga1s0XSwgNywgLTE3NjQxODg5Nyk7XG4gIGQgPSBmZihkLCBhLCBiLCBjLCBrWzVdLCAxMiwgMTIwMDA4MDQyNik7XG4gIGMgPSBmZihjLCBkLCBhLCBiLCBrWzZdLCAxNywgLTE0NzMyMzEzNDEpO1xuICBiID0gZmYoYiwgYywgZCwgYSwga1s3XSwgMjIsIC00NTcwNTk4Myk7XG4gIGEgPSBmZihhLCBiLCBjLCBkLCBrWzhdLCA3LCAxNzcwMDM1NDE2KTtcbiAgZCA9IGZmKGQsIGEsIGIsIGMsIGtbOV0sIDEyLCAtMTk1ODQxNDQxNyk7XG4gIGMgPSBmZihjLCBkLCBhLCBiLCBrWzEwXSwgMTcsIC00MjA2Myk7XG4gIGIgPSBmZihiLCBjLCBkLCBhLCBrWzExXSwgMjIsIC0xOTkwNDA0MTYyKTtcbiAgYSA9IGZmKGEsIGIsIGMsIGQsIGtbMTJdLCA3LCAxODA0NjAzNjgyKTtcbiAgZCA9IGZmKGQsIGEsIGIsIGMsIGtbMTNdLCAxMiwgLTQwMzQxMTAxKTtcbiAgYyA9IGZmKGMsIGQsIGEsIGIsIGtbMTRdLCAxNywgLTE1MDIwMDIyOTApO1xuICBiID0gZmYoYiwgYywgZCwgYSwga1sxNV0sIDIyLCAxMjM2NTM1MzI5KTtcblxuICBhID0gZ2coYSwgYiwgYywgZCwga1sxXSwgNSwgLTE2NTc5NjUxMCk7XG4gIGQgPSBnZyhkLCBhLCBiLCBjLCBrWzZdLCA5LCAtMTA2OTUwMTYzMik7XG4gIGMgPSBnZyhjLCBkLCBhLCBiLCBrWzExXSwgMTQsIDY0MzcxNzcxMyk7XG4gIGIgPSBnZyhiLCBjLCBkLCBhLCBrWzBdLCAyMCwgLTM3Mzg5NzMwMik7XG4gIGEgPSBnZyhhLCBiLCBjLCBkLCBrWzVdLCA1LCAtNzAxNTU4NjkxKTtcbiAgZCA9IGdnKGQsIGEsIGIsIGMsIGtbMTBdLCA5LCAzODAxNjA4Myk7XG4gIGMgPSBnZyhjLCBkLCBhLCBiLCBrWzE1XSwgMTQsIC02NjA0NzgzMzUpO1xuICBiID0gZ2coYiwgYywgZCwgYSwga1s0XSwgMjAsIC00MDU1Mzc4NDgpO1xuICBhID0gZ2coYSwgYiwgYywgZCwga1s5XSwgNSwgNTY4NDQ2NDM4KTtcbiAgZCA9IGdnKGQsIGEsIGIsIGMsIGtbMTRdLCA5LCAtMTAxOTgwMzY5MCk7XG4gIGMgPSBnZyhjLCBkLCBhLCBiLCBrWzNdLCAxNCwgLTE4NzM2Mzk2MSk7XG4gIGIgPSBnZyhiLCBjLCBkLCBhLCBrWzhdLCAyMCwgMTE2MzUzMTUwMSk7XG4gIGEgPSBnZyhhLCBiLCBjLCBkLCBrWzEzXSwgNSwgLTE0NDQ2ODE0NjcpO1xuICBkID0gZ2coZCwgYSwgYiwgYywga1syXSwgOSwgLTUxNDAzNzg0KTtcbiAgYyA9IGdnKGMsIGQsIGEsIGIsIGtbN10sIDE0LCAxNzM1MzI4NDczKTtcbiAgYiA9IGdnKGIsIGMsIGQsIGEsIGtbMTJdLCAyMCwgLTE5MjY2MDc3MzQpO1xuXG4gIGEgPSBoaChhLCBiLCBjLCBkLCBrWzVdLCA0LCAtMzc4NTU4KTtcbiAgZCA9IGhoKGQsIGEsIGIsIGMsIGtbOF0sIDExLCAtMjAyMjU3NDQ2Myk7XG4gIGMgPSBoaChjLCBkLCBhLCBiLCBrWzExXSwgMTYsIDE4MzkwMzA1NjIpO1xuICBiID0gaGgoYiwgYywgZCwgYSwga1sxNF0sIDIzLCAtMzUzMDk1NTYpO1xuICBhID0gaGgoYSwgYiwgYywgZCwga1sxXSwgNCwgLTE1MzA5OTIwNjApO1xuICBkID0gaGgoZCwgYSwgYiwgYywga1s0XSwgMTEsIDEyNzI4OTMzNTMpO1xuICBjID0gaGgoYywgZCwgYSwgYiwga1s3XSwgMTYsIC0xNTU0OTc2MzIpO1xuICBiID0gaGgoYiwgYywgZCwgYSwga1sxMF0sIDIzLCAtMTA5NDczMDY0MCk7XG4gIGEgPSBoaChhLCBiLCBjLCBkLCBrWzEzXSwgNCwgNjgxMjc5MTc0KTtcbiAgZCA9IGhoKGQsIGEsIGIsIGMsIGtbMF0sIDExLCAtMzU4NTM3MjIyKTtcbiAgYyA9IGhoKGMsIGQsIGEsIGIsIGtbM10sIDE2LCAtNzIyNTIxOTc5KTtcbiAgYiA9IGhoKGIsIGMsIGQsIGEsIGtbNl0sIDIzLCA3NjAyOTE4OSk7XG4gIGEgPSBoaChhLCBiLCBjLCBkLCBrWzldLCA0LCAtNjQwMzY0NDg3KTtcbiAgZCA9IGhoKGQsIGEsIGIsIGMsIGtbMTJdLCAxMSwgLTQyMTgxNTgzNSk7XG4gIGMgPSBoaChjLCBkLCBhLCBiLCBrWzE1XSwgMTYsIDUzMDc0MjUyMCk7XG4gIGIgPSBoaChiLCBjLCBkLCBhLCBrWzJdLCAyMywgLTk5NTMzODY1MSk7XG5cbiAgYSA9IGlpKGEsIGIsIGMsIGQsIGtbMF0sIDYsIC0xOTg2MzA4NDQpO1xuICBkID0gaWkoZCwgYSwgYiwgYywga1s3XSwgMTAsIDExMjY4OTE0MTUpO1xuICBjID0gaWkoYywgZCwgYSwgYiwga1sxNF0sIDE1LCAtMTQxNjM1NDkwNSk7XG4gIGIgPSBpaShiLCBjLCBkLCBhLCBrWzVdLCAyMSwgLTU3NDM0MDU1KTtcbiAgYSA9IGlpKGEsIGIsIGMsIGQsIGtbMTJdLCA2LCAxNzAwNDg1NTcxKTtcbiAgZCA9IGlpKGQsIGEsIGIsIGMsIGtbM10sIDEwLCAtMTg5NDk4NjYwNik7XG4gIGMgPSBpaShjLCBkLCBhLCBiLCBrWzEwXSwgMTUsIC0xMDUxNTIzKTtcbiAgYiA9IGlpKGIsIGMsIGQsIGEsIGtbMV0sIDIxLCAtMjA1NDkyMjc5OSk7XG4gIGEgPSBpaShhLCBiLCBjLCBkLCBrWzhdLCA2LCAxODczMzEzMzU5KTtcbiAgZCA9IGlpKGQsIGEsIGIsIGMsIGtbMTVdLCAxMCwgLTMwNjExNzQ0KTtcbiAgYyA9IGlpKGMsIGQsIGEsIGIsIGtbNl0sIDE1LCAtMTU2MDE5ODM4MCk7XG4gIGIgPSBpaShiLCBjLCBkLCBhLCBrWzEzXSwgMjEsIDEzMDkxNTE2NDkpO1xuICBhID0gaWkoYSwgYiwgYywgZCwga1s0XSwgNiwgLTE0NTUyMzA3MCk7XG4gIGQgPSBpaShkLCBhLCBiLCBjLCBrWzExXSwgMTAsIC0xMTIwMjEwMzc5KTtcbiAgYyA9IGlpKGMsIGQsIGEsIGIsIGtbMl0sIDE1LCA3MTg3ODcyNTkpO1xuICBiID0gaWkoYiwgYywgZCwgYSwga1s5XSwgMjEsIC0zNDM0ODU1NTEpO1xuXG4gIHhbMF0gPSBhZGQzMihhLCB4WzBdKTtcbiAgeFsxXSA9IGFkZDMyKGIsIHhbMV0pO1xuICB4WzJdID0gYWRkMzIoYywgeFsyXSk7XG4gIHhbM10gPSBhZGQzMihkLCB4WzNdKTtcblxufVxuXG5mdW5jdGlvbiBjbW4ocSwgYSwgYiwgeCwgcywgdCkge1xuICBhID0gYWRkMzIoYWRkMzIoYSwgcSksIGFkZDMyKHgsIHQpKTtcbiAgcmV0dXJuIGFkZDMyKChhIDw8IHMpIHwgKGEgPj4+ICgzMiAtIHMpKSwgYik7XG59XG5cbmZ1bmN0aW9uIGZmKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIGNtbigoYiAmIGMpIHwgKCh+YikgJiBkKSwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIGdnKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIGNtbigoYiAmIGQpIHwgKGMgJiAofmQpKSwgYSwgYiwgeCwgcywgdCk7XG59XG5cbmZ1bmN0aW9uIGhoKGEsIGIsIGMsIGQsIHgsIHMsIHQpIHtcbiAgcmV0dXJuIGNtbihiIF4gYyBeIGQsIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBpaShhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBjbW4oYyBeIChiIHwgKH5kKSksIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBtZDUxKHMpIHtcbiAgdHh0ID0gJyc7XG4gIHZhciBuID0gcy5sZW5ndGgsXG4gICAgc3RhdGUgPSBbMTczMjU4NDE5MywgLTI3MTczMzg3OSwgLTE3MzI1ODQxOTQsIDI3MTczMzg3OF0sXG4gICAgaTtcbiAgZm9yIChpID0gNjQ7IGkgPD0gcy5sZW5ndGg7IGkgKz0gNjQpIHtcbiAgICBtZDVjeWNsZShzdGF0ZSwgbWQ1YmxrKHMuc3Vic3RyaW5nKGkgLSA2NCwgaSkpKTtcbiAgfVxuICBzID0gcy5zdWJzdHJpbmcoaSAtIDY0KTtcbiAgdmFyIHRhaWwgPSBbMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF07XG4gIGZvciAoaSA9IDA7IGkgPCBzLmxlbmd0aDsgaSsrKVxuICAgIHRhaWxbaSA+PiAyXSB8PSBzLmNoYXJDb2RlQXQoaSkgPDwgKChpICUgNCkgPDwgMyk7XG4gIHRhaWxbaSA+PiAyXSB8PSAweDgwIDw8ICgoaSAlIDQpIDw8IDMpO1xuICBpZiAoaSA+IDU1KSB7XG4gICAgbWQ1Y3ljbGUoc3RhdGUsIHRhaWwpO1xuICAgIGZvciAoaSA9IDA7IGkgPCAxNjsgaSsrKSB0YWlsW2ldID0gMDtcbiAgfVxuICB0YWlsWzE0XSA9IG4gKiA4O1xuICBtZDVjeWNsZShzdGF0ZSwgdGFpbCk7XG4gIHJldHVybiBzdGF0ZTtcbn1cblxuLyogdGhlcmUgbmVlZHMgdG8gYmUgc3VwcG9ydCBmb3IgVW5pY29kZSBoZXJlLFxuICogdW5sZXNzIHdlIHByZXRlbmQgdGhhdCB3ZSBjYW4gcmVkZWZpbmUgdGhlIE1ELTVcbiAqIGFsZ29yaXRobSBmb3IgbXVsdGktYnl0ZSBjaGFyYWN0ZXJzIChwZXJoYXBzXG4gKiBieSBhZGRpbmcgZXZlcnkgZm91ciAxNi1iaXQgY2hhcmFjdGVycyBhbmRcbiAqIHNob3J0ZW5pbmcgdGhlIHN1bSB0byAzMiBiaXRzKS4gT3RoZXJ3aXNlXG4gKiBJIHN1Z2dlc3QgcGVyZm9ybWluZyBNRC01IGFzIGlmIGV2ZXJ5IGNoYXJhY3RlclxuICogd2FzIHR3byBieXRlcy0tZS5nLiwgMDA0MCAwMDI1ID0gQCUtLWJ1dCB0aGVuXG4gKiBob3cgd2lsbCBhbiBvcmRpbmFyeSBNRC01IHN1bSBiZSBtYXRjaGVkP1xuICogVGhlcmUgaXMgbm8gd2F5IHRvIHN0YW5kYXJkaXplIHRleHQgdG8gc29tZXRoaW5nXG4gKiBsaWtlIFVURi04IGJlZm9yZSB0cmFuc2Zvcm1hdGlvbjsgc3BlZWQgY29zdCBpc1xuICogdXR0ZXJseSBwcm9oaWJpdGl2ZS4gVGhlIEphdmFTY3JpcHQgc3RhbmRhcmRcbiAqIGl0c2VsZiBuZWVkcyB0byBsb29rIGF0IHRoaXM6IGl0IHNob3VsZCBzdGFydFxuICogcHJvdmlkaW5nIGFjY2VzcyB0byBzdHJpbmdzIGFzIHByZWZvcm1lZCBVVEYtOFxuICogOC1iaXQgdW5zaWduZWQgdmFsdWUgYXJyYXlzLlxuICovXG5mdW5jdGlvbiBtZDVibGsocykgeyAvKiBJIGZpZ3VyZWQgZ2xvYmFsIHdhcyBmYXN0ZXIuICAgKi9cbiAgdmFyIG1kNWJsa3MgPSBbXSxcbiAgICBpOyAvKiBBbmR5IEtpbmcgc2FpZCBkbyBpdCB0aGlzIHdheS4gKi9cbiAgZm9yIChpID0gMDsgaSA8IDY0OyBpICs9IDQpIHtcbiAgICBtZDVibGtzW2kgPj4gMl0gPSBzLmNoYXJDb2RlQXQoaSkgKyAocy5jaGFyQ29kZUF0KGkgKyAxKSA8PCA4KSArIChzLmNoYXJDb2RlQXQoaSArIDIpIDw8IDE2KSArIChzLmNoYXJDb2RlQXQoaSArIDMpIDw8XG4gICAgICAyNCk7XG4gIH1cbiAgcmV0dXJuIG1kNWJsa3M7XG59XG5cbnZhciBoZXhfY2hyID0gJzAxMjM0NTY3ODlhYmNkZWYnLnNwbGl0KCcnKTtcblxuZnVuY3Rpb24gcmhleChuKSB7XG4gIHZhciBzID0gJycsXG4gICAgaiA9IDA7XG4gIGZvciAoOyBqIDwgNDsgaisrKVxuICAgIHMgKz0gaGV4X2NoclsobiA+PiAoaiAqIDggKyA0KSkgJiAweDBGXSArIGhleF9jaHJbKG4gPj4gKGogKiA4KSkgJiAweDBGXTtcbiAgcmV0dXJuIHM7XG59XG5cbmZ1bmN0aW9uIGhleCh4KSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgeC5sZW5ndGg7IGkrKylcbiAgICB4W2ldID0gcmhleCh4W2ldKTtcbiAgcmV0dXJuIHguam9pbignJyk7XG59XG5cbmZ1bmN0aW9uIG1kNShzKSB7XG4gIHJldHVybiBoZXgobWQ1MShzKSk7XG59XG5cbi8qIHRoaXMgZnVuY3Rpb24gaXMgbXVjaCBmYXN0ZXIsXG5zbyBpZiBwb3NzaWJsZSB3ZSB1c2UgaXQuIFNvbWUgSUVzXG5hcmUgdGhlIG9ubHkgb25lcyBJIGtub3cgb2YgdGhhdFxubmVlZCB0aGUgaWRpb3RpYyBzZWNvbmQgZnVuY3Rpb24sXG5nZW5lcmF0ZWQgYnkgYW4gaWYgY2xhdXNlLiAgKi9cblxuZnVuY3Rpb24gYWRkMzIoYSwgYikge1xuICByZXR1cm4gKGEgKyBiKSAmIDB4RkZGRkZGRkY7XG59XG5cbmlmIChtZDUoJ2hlbGxvJykgIT0gJzVkNDE0MDJhYmM0YjJhNzZiOTcxOWQ5MTEwMTdjNTkyJykge1xuICBmdW5jdGlvbiBhZGQzMih4LCB5KSB7XG4gICAgdmFyIGxzdyA9ICh4ICYgMHhGRkZGKSArICh5ICYgMHhGRkZGKSxcbiAgICAgIG1zdyA9ICh4ID4+IDE2KSArICh5ID4+IDE2KSArIChsc3cgPj4gMTYpO1xuICAgIHJldHVybiAobXN3IDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gTUQ1XG4iLCIvKlxuICogQ3J5cHRvTVggVG9vbHNcbiAqIENvcHlyaWdodCAoQykgMjAwNCAtIDIwMDYgRGVyZWsgQnVpdGVuaHVpc1xuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyIHZlcnNpb24gMlxuICogb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4gKlxuICogVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqXG4gKiBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYWxvbmcgd2l0aCB0aGlzIHByb2dyYW07IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSAtIFN1aXRlIDMzMCwgQm9zdG9uLCBNQSAgMDIxMTEtMTMwNywgVVNBLlxuICovXG5cbi8qIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSFxuICovXG5cbnZhciBSTURzaXplID0gMTYwO1xudmFyIFggPSBuZXcgQXJyYXkoKTtcblxuZnVuY3Rpb24gUk9MKHgsIG4pIHtcbiAgcmV0dXJuIG5ldyBOdW1iZXIoKHggPDwgbikgfCAoeCA+Pj4gKDMyIC0gbikpKTtcbn1cblxuZnVuY3Rpb24gRih4LCB5LCB6KSB7XG4gIHJldHVybiBuZXcgTnVtYmVyKHggXiB5IF4geik7XG59XG5cbmZ1bmN0aW9uIEcoeCwgeSwgeikge1xuICByZXR1cm4gbmV3IE51bWJlcigoeCAmIHkpIHwgKH54ICYgeikpO1xufVxuXG5mdW5jdGlvbiBIKHgsIHksIHopIHtcbiAgcmV0dXJuIG5ldyBOdW1iZXIoKHggfCB+eSkgXiB6KTtcbn1cblxuZnVuY3Rpb24gSSh4LCB5LCB6KSB7XG4gIHJldHVybiBuZXcgTnVtYmVyKCh4ICYgeikgfCAoeSAmIH56KSk7XG59XG5cbmZ1bmN0aW9uIEooeCwgeSwgeikge1xuICByZXR1cm4gbmV3IE51bWJlcih4IF4gKHkgfCB+eikpO1xufVxuXG5mdW5jdGlvbiBtaXhPbmVSb3VuZChhLCBiLCBjLCBkLCBlLCB4LCBzLCByb3VuZE51bWJlcikge1xuICBzd2l0Y2ggKHJvdW5kTnVtYmVyKSB7XG4gICAgY2FzZSAwOlxuICAgICAgYSArPSBGKGIsIGMsIGQpICsgeCArIDB4MDAwMDAwMDA7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDE6XG4gICAgICBhICs9IEcoYiwgYywgZCkgKyB4ICsgMHg1YTgyNzk5OTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMjpcbiAgICAgIGEgKz0gSChiLCBjLCBkKSArIHggKyAweDZlZDllYmExO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAzOlxuICAgICAgYSArPSBJKGIsIGMsIGQpICsgeCArIDB4OGYxYmJjZGM7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDQ6XG4gICAgICBhICs9IEooYiwgYywgZCkgKyB4ICsgMHhhOTUzZmQ0ZTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNTpcbiAgICAgIGEgKz0gSihiLCBjLCBkKSArIHggKyAweDUwYTI4YmU2O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA2OlxuICAgICAgYSArPSBJKGIsIGMsIGQpICsgeCArIDB4NWM0ZGQxMjQ7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDc6XG4gICAgICBhICs9IEgoYiwgYywgZCkgKyB4ICsgMHg2ZDcwM2VmMztcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgODpcbiAgICAgIGEgKz0gRyhiLCBjLCBkKSArIHggKyAweDdhNmQ3NmU5O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA5OlxuICAgICAgYSArPSBGKGIsIGMsIGQpICsgeCArIDB4MDAwMDAwMDA7XG4gICAgICBicmVhaztcblxuICAgIGRlZmF1bHQ6XG4gICAgICBkb2N1bWVudC53cml0ZShcIkJvZ3VzIHJvdW5kIG51bWJlclwiKTtcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgYSA9IFJPTChhLCBzKSArIGU7XG4gIGMgPSBST0woYywgMTApO1xuXG4gIGEgJj0gMHhmZmZmZmZmZjtcbiAgYiAmPSAweGZmZmZmZmZmO1xuICBjICY9IDB4ZmZmZmZmZmY7XG4gIGQgJj0gMHhmZmZmZmZmZjtcbiAgZSAmPSAweGZmZmZmZmZmO1xuXG4gIHZhciByZXRCbG9jayA9IG5ldyBBcnJheSgpO1xuICByZXRCbG9ja1swXSA9IGE7XG4gIHJldEJsb2NrWzFdID0gYjtcbiAgcmV0QmxvY2tbMl0gPSBjO1xuICByZXRCbG9ja1szXSA9IGQ7XG4gIHJldEJsb2NrWzRdID0gZTtcbiAgcmV0QmxvY2tbNV0gPSB4O1xuICByZXRCbG9ja1s2XSA9IHM7XG5cbiAgcmV0dXJuIHJldEJsb2NrO1xufVxuXG5mdW5jdGlvbiBNRGluaXQoTURidWYpIHtcbiAgTURidWZbMF0gPSAweDY3NDUyMzAxO1xuICBNRGJ1ZlsxXSA9IDB4ZWZjZGFiODk7XG4gIE1EYnVmWzJdID0gMHg5OGJhZGNmZTtcbiAgTURidWZbM10gPSAweDEwMzI1NDc2O1xuICBNRGJ1Zls0XSA9IDB4YzNkMmUxZjA7XG59XG5cbnZhciBST0xzID0gW1xuICBbMTEsIDE0LCAxNSwgMTIsIDUsIDgsIDcsIDksIDExLCAxMywgMTQsIDE1LCA2LCA3LCA5LCA4XSxcbiAgWzcsIDYsIDgsIDEzLCAxMSwgOSwgNywgMTUsIDcsIDEyLCAxNSwgOSwgMTEsIDcsIDEzLCAxMl0sXG4gIFsxMSwgMTMsIDYsIDcsIDE0LCA5LCAxMywgMTUsIDE0LCA4LCAxMywgNiwgNSwgMTIsIDcsIDVdLFxuICBbMTEsIDEyLCAxNCwgMTUsIDE0LCAxNSwgOSwgOCwgOSwgMTQsIDUsIDYsIDgsIDYsIDUsIDEyXSxcbiAgWzksIDE1LCA1LCAxMSwgNiwgOCwgMTMsIDEyLCA1LCAxMiwgMTMsIDE0LCAxMSwgOCwgNSwgNl0sXG4gIFs4LCA5LCA5LCAxMSwgMTMsIDE1LCAxNSwgNSwgNywgNywgOCwgMTEsIDE0LCAxNCwgMTIsIDZdLFxuICBbOSwgMTMsIDE1LCA3LCAxMiwgOCwgOSwgMTEsIDcsIDcsIDEyLCA3LCA2LCAxNSwgMTMsIDExXSxcbiAgWzksIDcsIDE1LCAxMSwgOCwgNiwgNiwgMTQsIDEyLCAxMywgNSwgMTQsIDEzLCAxMywgNywgNV0sXG4gIFsxNSwgNSwgOCwgMTEsIDE0LCAxNCwgNiwgMTQsIDYsIDksIDEyLCA5LCAxMiwgNSwgMTUsIDhdLFxuICBbOCwgNSwgMTIsIDksIDEyLCA1LCAxNCwgNiwgOCwgMTMsIDYsIDUsIDE1LCAxMywgMTEsIDExXVxuXTtcblxudmFyIGluZGV4ZXMgPSBbXG4gIFswLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1XSxcbiAgWzcsIDQsIDEzLCAxLCAxMCwgNiwgMTUsIDMsIDEyLCAwLCA5LCA1LCAyLCAxNCwgMTEsIDhdLFxuICBbMywgMTAsIDE0LCA0LCA5LCAxNSwgOCwgMSwgMiwgNywgMCwgNiwgMTMsIDExLCA1LCAxMl0sXG4gIFsxLCA5LCAxMSwgMTAsIDAsIDgsIDEyLCA0LCAxMywgMywgNywgMTUsIDE0LCA1LCA2LCAyXSxcbiAgWzQsIDAsIDUsIDksIDcsIDEyLCAyLCAxMCwgMTQsIDEsIDMsIDgsIDExLCA2LCAxNSwgMTNdLFxuICBbNSwgMTQsIDcsIDAsIDksIDIsIDExLCA0LCAxMywgNiwgMTUsIDgsIDEsIDEwLCAzLCAxMl0sXG4gIFs2LCAxMSwgMywgNywgMCwgMTMsIDUsIDEwLCAxNCwgMTUsIDgsIDEyLCA0LCA5LCAxLCAyXSxcbiAgWzE1LCA1LCAxLCAzLCA3LCAxNCwgNiwgOSwgMTEsIDgsIDEyLCAyLCAxMCwgMCwgNCwgMTNdLFxuICBbOCwgNiwgNCwgMSwgMywgMTEsIDE1LCAwLCA1LCAxMiwgMiwgMTMsIDksIDcsIDEwLCAxNF0sXG4gIFsxMiwgMTUsIDEwLCA0LCAxLCA1LCA4LCA3LCA2LCAyLCAxMywgMTQsIDAsIDMsIDksIDExXVxuXTtcblxuZnVuY3Rpb24gY29tcHJlc3MoTURidWYsIFgpIHtcbiAgYmxvY2tBID0gbmV3IEFycmF5KCk7XG4gIGJsb2NrQiA9IG5ldyBBcnJheSgpO1xuXG4gIHZhciByZXRCbG9jaztcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IDU7IGkrKykge1xuICAgIGJsb2NrQVtpXSA9IG5ldyBOdW1iZXIoTURidWZbaV0pO1xuICAgIGJsb2NrQltpXSA9IG5ldyBOdW1iZXIoTURidWZbaV0pO1xuICB9XG5cbiAgdmFyIHN0ZXAgPSAwO1xuICBmb3IgKHZhciBqID0gMDsgaiA8IDU7IGorKykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgcmV0QmxvY2sgPSBtaXhPbmVSb3VuZChcbiAgICAgICAgYmxvY2tBWyhzdGVwICsgMCkgJSA1XSxcbiAgICAgICAgYmxvY2tBWyhzdGVwICsgMSkgJSA1XSxcbiAgICAgICAgYmxvY2tBWyhzdGVwICsgMikgJSA1XSxcbiAgICAgICAgYmxvY2tBWyhzdGVwICsgMykgJSA1XSxcbiAgICAgICAgYmxvY2tBWyhzdGVwICsgNCkgJSA1XSxcbiAgICAgICAgWFtpbmRleGVzW2pdW2ldXSxcbiAgICAgICAgUk9Mc1tqXVtpXSxcbiAgICAgICAgaik7XG5cbiAgICAgIGJsb2NrQVsoc3RlcCArIDApICUgNV0gPSByZXRCbG9ja1swXTtcbiAgICAgIGJsb2NrQVsoc3RlcCArIDEpICUgNV0gPSByZXRCbG9ja1sxXTtcbiAgICAgIGJsb2NrQVsoc3RlcCArIDIpICUgNV0gPSByZXRCbG9ja1syXTtcbiAgICAgIGJsb2NrQVsoc3RlcCArIDMpICUgNV0gPSByZXRCbG9ja1szXTtcbiAgICAgIGJsb2NrQVsoc3RlcCArIDQpICUgNV0gPSByZXRCbG9ja1s0XTtcblxuICAgICAgc3RlcCArPSA0O1xuICAgIH1cbiAgfVxuXG4gIHN0ZXAgPSAwO1xuICBmb3IgKHZhciBqID0gNTsgaiA8IDEwOyBqKyspIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgIHJldEJsb2NrID0gbWl4T25lUm91bmQoXG4gICAgICAgIGJsb2NrQlsoc3RlcCArIDApICUgNV0sXG4gICAgICAgIGJsb2NrQlsoc3RlcCArIDEpICUgNV0sXG4gICAgICAgIGJsb2NrQlsoc3RlcCArIDIpICUgNV0sXG4gICAgICAgIGJsb2NrQlsoc3RlcCArIDMpICUgNV0sXG4gICAgICAgIGJsb2NrQlsoc3RlcCArIDQpICUgNV0sXG4gICAgICAgIFhbaW5kZXhlc1tqXVtpXV0sXG4gICAgICAgIFJPTHNbal1baV0sXG4gICAgICAgIGopO1xuXG4gICAgICBibG9ja0JbKHN0ZXAgKyAwKSAlIDVdID0gcmV0QmxvY2tbMF07XG4gICAgICBibG9ja0JbKHN0ZXAgKyAxKSAlIDVdID0gcmV0QmxvY2tbMV07XG4gICAgICBibG9ja0JbKHN0ZXAgKyAyKSAlIDVdID0gcmV0QmxvY2tbMl07XG4gICAgICBibG9ja0JbKHN0ZXAgKyAzKSAlIDVdID0gcmV0QmxvY2tbM107XG4gICAgICBibG9ja0JbKHN0ZXAgKyA0KSAlIDVdID0gcmV0QmxvY2tbNF07XG5cbiAgICAgIHN0ZXAgKz0gNDtcbiAgICB9XG4gIH1cblxuICBibG9ja0JbM10gKz0gYmxvY2tBWzJdICsgTURidWZbMV07XG4gIE1EYnVmWzFdID0gTURidWZbMl0gKyBibG9ja0FbM10gKyBibG9ja0JbNF07XG4gIE1EYnVmWzJdID0gTURidWZbM10gKyBibG9ja0FbNF0gKyBibG9ja0JbMF07XG4gIE1EYnVmWzNdID0gTURidWZbNF0gKyBibG9ja0FbMF0gKyBibG9ja0JbMV07XG4gIE1EYnVmWzRdID0gTURidWZbMF0gKyBibG9ja0FbMV0gKyBibG9ja0JbMl07XG4gIE1EYnVmWzBdID0gYmxvY2tCWzNdO1xufVxuXG5mdW5jdGlvbiB6ZXJvWChYKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgIFhbaV0gPSAwO1xuICB9XG59XG5cbmZ1bmN0aW9uIE1EZmluaXNoKE1EYnVmLCBzdHJwdHIsIGxzd2xlbiwgbXN3bGVuKSB7XG4gIHZhciBYID0gbmV3IEFycmF5KDE2KTtcbiAgemVyb1goWCk7XG5cbiAgdmFyIGogPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IChsc3dsZW4gJiA2Myk7IGkrKykge1xuICAgIFhbaSA+Pj4gMl0gXj0gKHN0cnB0ci5jaGFyQ29kZUF0KGorKykgJiAyNTUpIDw8ICg4ICogKGkgJiAzKSk7XG4gIH1cblxuICBYWyhsc3dsZW4gPj4+IDIpICYgMTVdIF49IDEgPDwgKDggKiAobHN3bGVuICYgMykgKyA3KTtcblxuICBpZiAoKGxzd2xlbiAmIDYzKSA+IDU1KSB7XG4gICAgY29tcHJlc3MoTURidWYsIFgpO1xuICAgIHZhciBYID0gbmV3IEFycmF5KDE2KTtcbiAgICB6ZXJvWChYKTtcbiAgfVxuXG4gIFhbMTRdID0gbHN3bGVuIDw8IDM7XG4gIFhbMTVdID0gKGxzd2xlbiA+Pj4gMjkpIHwgKG1zd2xlbiA8PCAzKTtcblxuICBjb21wcmVzcyhNRGJ1ZiwgWCk7XG59XG5cbmZ1bmN0aW9uIEJZVEVTX1RPX0RXT1JEKGZvdXJDaGFycykge1xuICB2YXIgdG1wID0gKGZvdXJDaGFycy5jaGFyQ29kZUF0KDMpICYgMjU1KSA8PCAyNDtcbiAgdG1wIHw9IChmb3VyQ2hhcnMuY2hhckNvZGVBdCgyKSAmIDI1NSkgPDwgMTY7XG4gIHRtcCB8PSAoZm91ckNoYXJzLmNoYXJDb2RlQXQoMSkgJiAyNTUpIDw8IDg7XG4gIHRtcCB8PSAoZm91ckNoYXJzLmNoYXJDb2RlQXQoMCkgJiAyNTUpO1xuXG4gIHJldHVybiB0bXA7XG59XG5cbmZ1bmN0aW9uIFJNRChtZXNzYWdlKSB7XG4gIHZhciBNRGJ1ZiA9IG5ldyBBcnJheShSTURzaXplIC8gMzIpO1xuICB2YXIgaGFzaGNvZGUgPSBuZXcgQXJyYXkoUk1Ec2l6ZSAvIDgpO1xuICB2YXIgbGVuZ3RoO1xuICB2YXIgbmJ5dGVzO1xuXG4gIE1EaW5pdChNRGJ1Zik7XG4gIGxlbmd0aCA9IG1lc3NhZ2UubGVuZ3RoO1xuXG4gIHZhciBYID0gbmV3IEFycmF5KDE2KTtcbiAgemVyb1goWCk7XG5cbiAgdmFyIGogPSAwO1xuICBmb3IgKHZhciBuYnl0ZXMgPSBsZW5ndGg7IG5ieXRlcyA+IDYzOyBuYnl0ZXMgLT0gNjQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgIFhbaV0gPSBCWVRFU19UT19EV09SRChtZXNzYWdlLnN1YnN0cihqLCA0KSk7XG4gICAgICBqICs9IDQ7XG4gICAgfVxuICAgIGNvbXByZXNzKE1EYnVmLCBYKTtcbiAgfVxuXG4gIE1EZmluaXNoKE1EYnVmLCBtZXNzYWdlLnN1YnN0cihqKSwgbGVuZ3RoLCAwKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IFJNRHNpemUgLyA4OyBpICs9IDQpIHtcbiAgICBoYXNoY29kZVtpXSA9IE1EYnVmW2kgPj4+IDJdICYgMjU1O1xuICAgIGhhc2hjb2RlW2kgKyAxXSA9IChNRGJ1ZltpID4+PiAyXSA+Pj4gOCkgJiAyNTU7XG4gICAgaGFzaGNvZGVbaSArIDJdID0gKE1EYnVmW2kgPj4+IDJdID4+PiAxNikgJiAyNTU7XG4gICAgaGFzaGNvZGVbaSArIDNdID0gKE1EYnVmW2kgPj4+IDJdID4+PiAyNCkgJiAyNTU7XG4gIH1cblxuICByZXR1cm4gaGFzaGNvZGU7XG59XG5cblxuZnVuY3Rpb24gUk1Ec3RyaW5nKG1lc3NhZ2UpIHtcbiAgdmFyIGhhc2hjb2RlID0gUk1EKG1lc3NhZ2UpO1xuICB2YXIgcmV0U3RyaW5nID0gXCJcIjtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IFJNRHNpemUgLyA4OyBpKyspIHtcbiAgICByZXRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShoYXNoY29kZVtpXSk7XG4gIH1cblxuICByZXR1cm4gcmV0U3RyaW5nO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFJNRHN0cmluZztcbiIsIi8qIEEgSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgU0hBIGZhbWlseSBvZiBoYXNoZXMsIGFzIGRlZmluZWQgaW4gRklQUyBcbiAqIFBVQiAxODAtMiBhcyB3ZWxsIGFzIHRoZSBjb3JyZXNwb25kaW5nIEhNQUMgaW1wbGVtZW50YXRpb24gYXMgZGVmaW5lZCBpblxuICogRklQUyBQVUIgMTk4YVxuICpcbiAqIFZlcnNpb24gMS4zIENvcHlyaWdodCBCcmlhbiBUdXJlayAyMDA4LTIwMTBcbiAqIERpc3RyaWJ1dGVkIHVuZGVyIHRoZSBCU0QgTGljZW5zZVxuICogU2VlIGh0dHA6Ly9qc3NoYS5zb3VyY2Vmb3JnZS5uZXQvIGZvciBtb3JlIGluZm9ybWF0aW9uXG4gKlxuICogU2V2ZXJhbCBmdW5jdGlvbnMgdGFrZW4gZnJvbSBQYXVsIEpvaG5zb25cbiAqL1xuXG4vKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkhcbiAqIFxuICogVGhpcyBjb2RlIGhhcyBiZWVuIHNsaWdodGx5IG1vZGlmaWVkIGRpcmVjdCBzdHJpbmcgb3V0cHV0OlxuICogLSBiaW4yYnN0ciBoYXMgYmVlbiBhZGRlZFxuICogLSBmb2xsb3dpbmcgd3JhcHBlcnMgb2YgdGhpcyBsaWJyYXJ5IGhhdmUgYmVlbiBhZGRlZDpcbiAqICAgLSBzdHJfc2hhMVxuICogICAtIHN0cl9zaGEyNTZcbiAqICAgLSBzdHJfc2hhMjI0XG4gKiAgIC0gc3RyX3NoYTM4NFxuICogICAtIHN0cl9zaGE1MTJcbiAqL1xuXG52YXIganNTSEEgPSAoZnVuY3Rpb24oKSB7XG5cbiAgLypcbiAgICogQ29uZmlndXJhYmxlIHZhcmlhYmxlcy4gRGVmYXVsdHMgdHlwaWNhbGx5IHdvcmtcbiAgICovXG4gIC8qIE51bWJlciBvZiBCaXRzIFBlciBjaGFyYWN0ZXIgKDggZm9yIEFTQ0lJLCAxNiBmb3IgVW5pY29kZSkgKi9cbiAgdmFyIGNoYXJTaXplID0gOCxcbiAgICAvKiBiYXNlLTY0IHBhZCBjaGFyYWN0ZXIuIFwiPVwiIGZvciBzdHJpY3QgUkZDIGNvbXBsaWFuY2UgKi9cbiAgICBiNjRwYWQgPSBcIlwiLFxuICAgIC8qIGhleCBvdXRwdXQgZm9ybWF0LiAwIC0gbG93ZXJjYXNlOyAxIC0gdXBwZXJjYXNlICovXG4gICAgaGV4Q2FzZSA9IDAsXG5cbiAgICAvKlxuICAgICAqIEludF82NCBpcyBhIG9iamVjdCBmb3IgMiAzMi1iaXQgbnVtYmVycyBlbXVsYXRpbmcgYSA2NC1iaXQgbnVtYmVyXG4gICAgICpcbiAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbXNpbnRfMzIgVGhlIG1vc3Qgc2lnbmlmaWNhbnQgMzItYml0cyBvZiBhIDY0LWJpdCBudW1iZXJcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbHNpbnRfMzIgVGhlIGxlYXN0IHNpZ25pZmljYW50IDMyLWJpdHMgb2YgYSA2NC1iaXQgbnVtYmVyXG4gICAgICovXG4gICAgSW50XzY0ID0gZnVuY3Rpb24obXNpbnRfMzIsIGxzaW50XzMyKSB7XG4gICAgICB0aGlzLmhpZ2hPcmRlciA9IG1zaW50XzMyO1xuICAgICAgdGhpcy5sb3dPcmRlciA9IGxzaW50XzMyO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYSBzdHJpbmcgdG8gYW4gYXJyYXkgb2YgYmlnLWVuZGlhbiB3b3Jkc1xuICAgICAqIElmIGNoYXJTaXplIGlzIEFTQ0lJLCBjaGFyYWN0ZXJzID4yNTUgaGF2ZSB0aGVpciBoaS1ieXRlIHNpbGVudGx5XG4gICAgICogaWdub3JlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIGJlIGNvbnZlcnRlZCB0byBiaW5hcnkgcmVwcmVzZW50YXRpb25cbiAgICAgKiBAcmV0dXJuIEludGVnZXIgYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhcmFtZXRlclxuICAgICAqL1xuICAgIHN0cjJiaW5iID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgICB2YXIgYmluID0gW10sXG4gICAgICAgIG1hc2sgPSAoMSA8PCBjaGFyU2l6ZSkgLSAxLFxuICAgICAgICBsZW5ndGggPSBzdHIubGVuZ3RoICogY2hhclNpemUsXG4gICAgICAgIGk7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gY2hhclNpemUpIHtcbiAgICAgICAgYmluW2kgPj4gNV0gfD0gKHN0ci5jaGFyQ29kZUF0KGkgLyBjaGFyU2l6ZSkgJiBtYXNrKSA8PFxuICAgICAgICAgICgzMiAtIGNoYXJTaXplIC0gKGkgJSAzMikpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYmluO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYSBoZXggc3RyaW5nIHRvIGFuIGFycmF5IG9mIGJpZy1lbmRpYW4gd29yZHNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIGJlIGNvbnZlcnRlZCB0byBiaW5hcnkgcmVwcmVzZW50YXRpb25cbiAgICAgKiBAcmV0dXJuIEludGVnZXIgYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhcmFtZXRlclxuICAgICAqL1xuICAgIGhleDJiaW5iID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgICB2YXIgYmluID0gW10sXG4gICAgICAgIGxlbmd0aCA9IHN0ci5sZW5ndGgsXG4gICAgICAgIGksIG51bTtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgIG51bSA9IHBhcnNlSW50KHN0ci5zdWJzdHIoaSwgMiksIDE2KTtcbiAgICAgICAgaWYgKCFpc05hTihudW0pKSB7XG4gICAgICAgICAgYmluW2kgPj4gM10gfD0gbnVtIDw8ICgyNCAtICg0ICogKGkgJSA4KSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBcIklOVkFMSUQgSEVYIFNUUklOR1wiO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBiaW47XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQ29udmVydCBhbiBhcnJheSBvZiBiaWctZW5kaWFuIHdvcmRzIHRvIGEgaGV4IHN0cmluZy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtBcnJheX0gYmluYXJyYXkgQXJyYXkgb2YgaW50ZWdlcnMgdG8gYmUgY29udmVydGVkIHRvIGhleGlkZWNpbWFsXG4gICAgICpcdCByZXByZXNlbnRhdGlvblxuICAgICAqIEByZXR1cm4gSGV4aWRlY2ltYWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhcmFtZXRlciBpbiBTdHJpbmcgZm9ybVxuICAgICAqL1xuICAgIGJpbmIyaGV4ID0gZnVuY3Rpb24oYmluYXJyYXkpIHtcbiAgICAgIHZhciBoZXhfdGFiID0gKGhleENhc2UpID8gXCIwMTIzNDU2Nzg5QUJDREVGXCIgOiBcIjAxMjM0NTY3ODlhYmNkZWZcIixcbiAgICAgICAgc3RyID0gXCJcIixcbiAgICAgICAgbGVuZ3RoID0gYmluYXJyYXkubGVuZ3RoICogNCxcbiAgICAgICAgaSwgc3JjQnl0ZTtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgIHNyY0J5dGUgPSBiaW5hcnJheVtpID4+IDJdID4+ICgoMyAtIChpICUgNCkpICogOCk7XG4gICAgICAgIHN0ciArPSBoZXhfdGFiLmNoYXJBdCgoc3JjQnl0ZSA+PiA0KSAmIDB4RikgK1xuICAgICAgICAgIGhleF90YWIuY2hhckF0KHNyY0J5dGUgJiAweEYpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYW4gYXJyYXkgb2YgYmlnLWVuZGlhbiB3b3JkcyB0byBhIGJhc2UtNjQgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJpbmFycmF5IEFycmF5IG9mIGludGVnZXJzIHRvIGJlIGNvbnZlcnRlZCB0byBiYXNlLTY0XG4gICAgICpcdCByZXByZXNlbnRhdGlvblxuICAgICAqIEByZXR1cm4gQmFzZS02NCBlbmNvZGVkIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYXJhbWV0ZXIgaW4gU3RyaW5nIGZvcm1cbiAgICAgKi9cbiAgICBiaW5iMmI2NCA9IGZ1bmN0aW9uKGJpbmFycmF5KSB7XG4gICAgICB2YXIgdGFiID0gXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XCIgK1xuICAgICAgICBcIjAxMjM0NTY3ODkrL1wiLFxuICAgICAgICBzdHIgPSBcIlwiLFxuICAgICAgICBsZW5ndGggPSBiaW5hcnJheS5sZW5ndGggKiA0LFxuICAgICAgICBpLCBqLFxuICAgICAgICB0cmlwbGV0O1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHtcbiAgICAgICAgdHJpcGxldCA9ICgoKGJpbmFycmF5W2kgPj4gMl0gPj4gOCAqICgzIC0gaSAlIDQpKSAmIDB4RkYpIDw8IDE2KSB8XG4gICAgICAgICAgKCgoYmluYXJyYXlbaSArIDEgPj4gMl0gPj4gOCAqICgzIC0gKGkgKyAxKSAlIDQpKSAmIDB4RkYpIDw8IDgpIHxcbiAgICAgICAgICAoKGJpbmFycmF5W2kgKyAyID4+IDJdID4+IDggKiAoMyAtIChpICsgMikgJSA0KSkgJiAweEZGKTtcbiAgICAgICAgZm9yIChqID0gMDsgaiA8IDQ7IGogKz0gMSkge1xuICAgICAgICAgIGlmIChpICogOCArIGogKiA2IDw9IGJpbmFycmF5Lmxlbmd0aCAqIDMyKSB7XG4gICAgICAgICAgICBzdHIgKz0gdGFiLmNoYXJBdCgodHJpcGxldCA+PiA2ICogKDMgLSBqKSkgJiAweDNGKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RyICs9IGI2NHBhZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBzdHI7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQ29udmVydCBhbiBhcnJheSBvZiBiaWctZW5kaWFuIHdvcmRzIHRvIGEgc3RyaW5nXG4gICAgICovXG4gICAgYmluYjJzdHIgPSBmdW5jdGlvbihiaW4pIHtcbiAgICAgIHZhciBzdHIgPSBcIlwiO1xuICAgICAgdmFyIG1hc2sgPSAoMSA8PCA4KSAtIDE7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbi5sZW5ndGggKiAzMjsgaSArPSA4KVxuICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoYmluW2kgPj4gNV0gPj4+ICgyNCAtIGkgJSAzMikpICYgbWFzayk7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG4gICAgLypcbiAgICAgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIGNpcmN1bGFyIHJvdGF0ZSBsZWZ0XG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgYml0cyB0byBzaGlmdFxuICAgICAqIEByZXR1cm4gVGhlIHggc2hpZnRlZCBjaXJjdWxhcmx5IGJ5IG4gYml0c1xuICAgICAqL1xuICAgIHJvdGxfMzIgPSBmdW5jdGlvbih4LCBuKSB7XG4gICAgICByZXR1cm4gKHggPDwgbikgfCAoeCA+Pj4gKDMyIC0gbikpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgY2lyY3VsYXIgcm90YXRlIHJpZ2h0XG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgYml0cyB0byBzaGlmdFxuICAgICAqIEByZXR1cm4gVGhlIHggc2hpZnRlZCBjaXJjdWxhcmx5IGJ5IG4gYml0c1xuICAgICAqL1xuICAgIHJvdHJfMzIgPSBmdW5jdGlvbih4LCBuKSB7XG4gICAgICByZXR1cm4gKHggPj4+IG4pIHwgKHggPDwgKDMyIC0gbikpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgY2lyY3VsYXIgcm90YXRlIHJpZ2h0XG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBuIFRoZSBudW1iZXIgb2YgYml0cyB0byBzaGlmdFxuICAgICAqIEByZXR1cm4gVGhlIHggc2hpZnRlZCBjaXJjdWxhcmx5IGJ5IG4gYml0c1xuICAgICAqL1xuICAgIHJvdHJfNjQgPSBmdW5jdGlvbih4LCBuKSB7XG4gICAgICBpZiAobiA8PSAzMikge1xuICAgICAgICByZXR1cm4gbmV3IEludF82NChcbiAgICAgICAgKHguaGlnaE9yZGVyID4+PiBuKSB8ICh4Lmxvd09yZGVyIDw8ICgzMiAtIG4pKSwgKHgubG93T3JkZXIgPj4+IG4pIHwgKHguaGlnaE9yZGVyIDw8ICgzMiAtIG4pKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbmV3IEludF82NChcbiAgICAgICAgKHgubG93T3JkZXIgPj4+IG4pIHwgKHguaGlnaE9yZGVyIDw8ICgzMiAtIG4pKSwgKHguaGlnaE9yZGVyID4+PiBuKSB8ICh4Lmxvd09yZGVyIDw8ICgzMiAtIG4pKSk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiBzaGlmdCByaWdodFxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcbiAgICAgKiBAcmV0dXJuIFRoZSB4IHNoaWZ0ZWQgYnkgbiBiaXRzXG4gICAgICovXG4gICAgc2hyXzMyID0gZnVuY3Rpb24oeCwgbikge1xuICAgICAgcmV0dXJuIHggPj4+IG47XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiBzaGlmdCByaWdodFxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcbiAgICAgKiBAcmV0dXJuIFRoZSB4IHNoaWZ0ZWQgYnkgbiBiaXRzXG4gICAgICovXG4gICAgc2hyXzY0ID0gZnVuY3Rpb24oeCwgbikge1xuICAgICAgaWYgKG4gPD0gMzIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgICAgeC5oaWdoT3JkZXIgPj4+IG4sXG4gICAgICAgICAgeC5sb3dPcmRlciA+Pj4gbiB8ICh4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgICAgMCxcbiAgICAgICAgICB4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKSk7XG4gICAgICB9XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgUGFyaXR5IGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSBmaXJzdCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB5IFRoZSBzZWNvbmQgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geiBUaGUgdGhpcmQgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgcGFyaXR5XzMyID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgICAgcmV0dXJuIHggXiB5IF4gejtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBDaCBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geSBUaGUgc2Vjb25kIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHogVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIGNoXzMyID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgICAgcmV0dXJuICh4ICYgeSkgXiAofnggJiB6KTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgNjQtYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBDaCBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgZmlyc3QgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geSBUaGUgc2Vjb25kIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHogVGhlIHRoaXJkIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIGNoXzY0ID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAoeC5oaWdoT3JkZXIgJiB5LmhpZ2hPcmRlcikgXiAofnguaGlnaE9yZGVyICYgei5oaWdoT3JkZXIpLCAoeC5sb3dPcmRlciAmIHkubG93T3JkZXIpIF4gKH54Lmxvd09yZGVyICYgei5sb3dPcmRlcikpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIE1haiBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geSBUaGUgc2Vjb25kIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHogVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIG1hal8zMiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICAgIHJldHVybiAoeCAmIHkpIF4gKHggJiB6KSBeICh5ICYgeik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgTWFqIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSBmaXJzdCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB5IFRoZSBzZWNvbmQgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geiBUaGUgdGhpcmQgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgbWFqXzY0ID0gZnVuY3Rpb24oeCwgeSwgeikge1xuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAoeC5oaWdoT3JkZXIgJiB5LmhpZ2hPcmRlcikgXlxuICAgICAgICAoeC5oaWdoT3JkZXIgJiB6LmhpZ2hPcmRlcikgXlxuICAgICAgICAoeS5oaWdoT3JkZXIgJiB6LmhpZ2hPcmRlciksICh4Lmxvd09yZGVyICYgeS5sb3dPcmRlcikgXlxuICAgICAgICAoeC5sb3dPcmRlciAmIHoubG93T3JkZXIpIF5cbiAgICAgICAgKHkubG93T3JkZXIgJiB6Lmxvd09yZGVyKSk7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgU2lnbWEwIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBzaWdtYTBfMzIgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gcm90cl8zMih4LCAyKSBeIHJvdHJfMzIoeCwgMTMpIF4gcm90cl8zMih4LCAyMik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgU2lnbWEwIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBzaWdtYTBfNjQgPSBmdW5jdGlvbih4KSB7XG4gICAgICB2YXIgcm90cjI4ID0gcm90cl82NCh4LCAyOCksXG4gICAgICAgIHJvdHIzNCA9IHJvdHJfNjQoeCwgMzQpLFxuICAgICAgICByb3RyMzkgPSByb3RyXzY0KHgsIDM5KTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgIHJvdHIyOC5oaWdoT3JkZXIgXiByb3RyMzQuaGlnaE9yZGVyIF4gcm90cjM5LmhpZ2hPcmRlcixcbiAgICAgICAgcm90cjI4Lmxvd09yZGVyIF4gcm90cjM0Lmxvd09yZGVyIF4gcm90cjM5Lmxvd09yZGVyKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBTaWdtYTEgZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIHNpZ21hMV8zMiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiByb3RyXzMyKHgsIDYpIF4gcm90cl8zMih4LCAxMSkgXiByb3RyXzMyKHgsIDI1KTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgNjQtYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBTaWdtYTEgZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIHNpZ21hMV82NCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHZhciByb3RyMTQgPSByb3RyXzY0KHgsIDE0KSxcbiAgICAgICAgcm90cjE4ID0gcm90cl82NCh4LCAxOCksXG4gICAgICAgIHJvdHI0MSA9IHJvdHJfNjQoeCwgNDEpO1xuXG4gICAgICByZXR1cm4gbmV3IEludF82NChcbiAgICAgICAgcm90cjE0LmhpZ2hPcmRlciBeIHJvdHIxOC5oaWdoT3JkZXIgXiByb3RyNDEuaGlnaE9yZGVyLFxuICAgICAgICByb3RyMTQubG93T3JkZXIgXiByb3RyMTgubG93T3JkZXIgXiByb3RyNDEubG93T3JkZXIpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIEdhbW1hMCBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgZ2FtbWEwXzMyID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHJvdHJfMzIoeCwgNykgXiByb3RyXzMyKHgsIDE4KSBeIHNocl8zMih4LCAzKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgNjQtYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBHYW1tYTAgZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIGdhbW1hMF82NCA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHZhciByb3RyMSA9IHJvdHJfNjQoeCwgMSksXG4gICAgICAgIHJvdHI4ID0gcm90cl82NCh4LCA4KSxcbiAgICAgICAgc2hyNyA9IHNocl82NCh4LCA3KTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgIHJvdHIxLmhpZ2hPcmRlciBeIHJvdHI4LmhpZ2hPcmRlciBeIHNocjcuaGlnaE9yZGVyLFxuICAgICAgICByb3RyMS5sb3dPcmRlciBeIHJvdHI4Lmxvd09yZGVyIF4gc2hyNy5sb3dPcmRlcik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgR2FtbWExIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBnYW1tYTFfMzIgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gcm90cl8zMih4LCAxNykgXiByb3RyXzMyKHgsIDE5KSBeIHNocl8zMih4LCAxMCk7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgR2FtbWExIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBnYW1tYTFfNjQgPSBmdW5jdGlvbih4KSB7XG4gICAgICB2YXIgcm90cjE5ID0gcm90cl82NCh4LCAxOSksXG4gICAgICAgIHJvdHI2MSA9IHJvdHJfNjQoeCwgNjEpLFxuICAgICAgICBzaHI2ID0gc2hyXzY0KHgsIDYpO1xuXG4gICAgICByZXR1cm4gbmV3IEludF82NChcbiAgICAgICAgcm90cjE5LmhpZ2hPcmRlciBeIHJvdHI2MS5oaWdoT3JkZXIgXiBzaHI2LmhpZ2hPcmRlcixcbiAgICAgICAgcm90cjE5Lmxvd09yZGVyIF4gcm90cjYxLmxvd09yZGVyIF4gc2hyNi5sb3dPcmRlcik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQWRkIHR3byAzMi1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeMzIuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuICAgICAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHkgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEByZXR1cm4gVGhlIHN1bSBvZiB4ICsgeVxuICAgICAqL1xuICAgIHNhZmVBZGRfMzJfMiA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciBsc3cgPSAoeCAmIDB4RkZGRikgKyAoeSAmIDB4RkZGRiksXG4gICAgICAgIG1zdyA9ICh4ID4+PiAxNikgKyAoeSA+Pj4gMTYpICsgKGxzdyA+Pj4gMTYpO1xuXG4gICAgICByZXR1cm4gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIEFkZCBmb3VyIDMyLWJpdCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zXG4gICAgICogaW50ZXJuYWxseSB0byB3b3JrIGFyb3VuZCBidWdzIGluIHNvbWUgSlMgaW50ZXJwcmV0ZXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYSBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYiBUaGUgc2Vjb25kIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGQgVGhlIGZvdXJ0aCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEByZXR1cm4gVGhlIHN1bSBvZiBhICsgYiArIGMgKyBkXG4gICAgICovXG4gICAgc2FmZUFkZF8zMl80ID0gZnVuY3Rpb24oYSwgYiwgYywgZCkge1xuICAgICAgdmFyIGxzdyA9IChhICYgMHhGRkZGKSArIChiICYgMHhGRkZGKSArIChjICYgMHhGRkZGKSArIChkICYgMHhGRkZGKSxcbiAgICAgICAgbXN3ID0gKGEgPj4+IDE2KSArIChiID4+PiAxNikgKyAoYyA+Pj4gMTYpICsgKGQgPj4+IDE2KSArXG4gICAgICAgICAgKGxzdyA+Pj4gMTYpO1xuXG4gICAgICByZXR1cm4gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIEFkZCBmaXZlIDMyLWJpdCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl4zMi4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zXG4gICAgICogaW50ZXJuYWxseSB0byB3b3JrIGFyb3VuZCBidWdzIGluIHNvbWUgSlMgaW50ZXJwcmV0ZXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYSBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gYiBUaGUgc2Vjb25kIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGMgVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGQgVGhlIGZvdXJ0aCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBlIFRoZSBmaWZ0aCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEByZXR1cm4gVGhlIHN1bSBvZiBhICsgYiArIGMgKyBkICsgZVxuICAgICAqL1xuICAgIHNhZmVBZGRfMzJfNSA9IGZ1bmN0aW9uKGEsIGIsIGMsIGQsIGUpIHtcbiAgICAgIHZhciBsc3cgPSAoYSAmIDB4RkZGRikgKyAoYiAmIDB4RkZGRikgKyAoYyAmIDB4RkZGRikgKyAoZCAmIDB4RkZGRikgK1xuICAgICAgICAoZSAmIDB4RkZGRiksXG4gICAgICAgIG1zdyA9IChhID4+PiAxNikgKyAoYiA+Pj4gMTYpICsgKGMgPj4+IDE2KSArIChkID4+PiAxNikgK1xuICAgICAgICAgIChlID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG5cbiAgICAgIHJldHVybiAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQWRkIHR3byA2NC1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeNjQuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuICAgICAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIGZpcnN0IDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHkgVGhlIHNlY29uZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEByZXR1cm4gVGhlIHN1bSBvZiB4ICsgeVxuICAgICAqL1xuICAgIHNhZmVBZGRfNjRfMiA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHZhciBsc3csIG1zdywgbG93T3JkZXIsIGhpZ2hPcmRlcjtcblxuICAgICAgbHN3ID0gKHgubG93T3JkZXIgJiAweEZGRkYpICsgKHkubG93T3JkZXIgJiAweEZGRkYpO1xuICAgICAgbXN3ID0gKHgubG93T3JkZXIgPj4+IDE2KSArICh5Lmxvd09yZGVyID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG4gICAgICBsb3dPcmRlciA9ICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcblxuICAgICAgbHN3ID0gKHguaGlnaE9yZGVyICYgMHhGRkZGKSArICh5LmhpZ2hPcmRlciAmIDB4RkZGRikgKyAobXN3ID4+PiAxNik7XG4gICAgICBtc3cgPSAoeC5oaWdoT3JkZXIgPj4+IDE2KSArICh5LmhpZ2hPcmRlciA+Pj4gMTYpICsgKGxzdyA+Pj4gMTYpO1xuICAgICAgaGlnaE9yZGVyID0gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXG4gICAgICByZXR1cm4gbmV3IEludF82NChoaWdoT3JkZXIsIGxvd09yZGVyKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBBZGQgZm91ciA2NC1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeNjQuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuICAgICAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IGEgVGhlIGZpcnN0IDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IGIgVGhlIHNlY29uZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSBjIFRoZSB0aGlyZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSBkIFRoZSBmb3V0aCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEByZXR1cm4gVGhlIHN1bSBvZiBhICsgYiArIGMgKyBkXG4gICAgICovXG4gICAgc2FmZUFkZF82NF80ID0gZnVuY3Rpb24oYSwgYiwgYywgZCkge1xuICAgICAgdmFyIGxzdywgbXN3LCBsb3dPcmRlciwgaGlnaE9yZGVyO1xuXG4gICAgICBsc3cgPSAoYS5sb3dPcmRlciAmIDB4RkZGRikgKyAoYi5sb3dPcmRlciAmIDB4RkZGRikgK1xuICAgICAgICAoYy5sb3dPcmRlciAmIDB4RkZGRikgKyAoZC5sb3dPcmRlciAmIDB4RkZGRik7XG4gICAgICBtc3cgPSAoYS5sb3dPcmRlciA+Pj4gMTYpICsgKGIubG93T3JkZXIgPj4+IDE2KSArXG4gICAgICAgIChjLmxvd09yZGVyID4+PiAxNikgKyAoZC5sb3dPcmRlciA+Pj4gMTYpICsgKGxzdyA+Pj4gMTYpO1xuICAgICAgbG93T3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cbiAgICAgIGxzdyA9IChhLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoYi5oaWdoT3JkZXIgJiAweEZGRkYpICtcbiAgICAgICAgKGMuaGlnaE9yZGVyICYgMHhGRkZGKSArIChkLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAobXN3ID4+PiAxNik7XG4gICAgICBtc3cgPSAoYS5oaWdoT3JkZXIgPj4+IDE2KSArIChiLmhpZ2hPcmRlciA+Pj4gMTYpICtcbiAgICAgICAgKGMuaGlnaE9yZGVyID4+PiAxNikgKyAoZC5oaWdoT3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcbiAgICAgIGhpZ2hPcmRlciA9ICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoaGlnaE9yZGVyLCBsb3dPcmRlcik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQWRkIGZpdmUgNjQtYml0IGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjY0LiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnNcbiAgICAgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSBhIFRoZSBmaXJzdCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSBiIFRoZSBzZWNvbmQgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gYyBUaGUgdGhpcmQgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gZCBUaGUgZm91dGggNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gZSBUaGUgZm91dGggNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcmV0dXJuIFRoZSBzdW0gb2YgYSArIGIgKyBjICsgZCArIGVcbiAgICAgKi9cbiAgICBzYWZlQWRkXzY0XzUgPSBmdW5jdGlvbihhLCBiLCBjLCBkLCBlKSB7XG4gICAgICB2YXIgbHN3LCBtc3csIGxvd09yZGVyLCBoaWdoT3JkZXI7XG5cbiAgICAgIGxzdyA9IChhLmxvd09yZGVyICYgMHhGRkZGKSArIChiLmxvd09yZGVyICYgMHhGRkZGKSArXG4gICAgICAgIChjLmxvd09yZGVyICYgMHhGRkZGKSArIChkLmxvd09yZGVyICYgMHhGRkZGKSArXG4gICAgICAgIChlLmxvd09yZGVyICYgMHhGRkZGKTtcbiAgICAgIG1zdyA9IChhLmxvd09yZGVyID4+PiAxNikgKyAoYi5sb3dPcmRlciA+Pj4gMTYpICtcbiAgICAgICAgKGMubG93T3JkZXIgPj4+IDE2KSArIChkLmxvd09yZGVyID4+PiAxNikgKyAoZS5sb3dPcmRlciA+Pj4gMTYpICtcbiAgICAgICAgKGxzdyA+Pj4gMTYpO1xuICAgICAgbG93T3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cbiAgICAgIGxzdyA9IChhLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoYi5oaWdoT3JkZXIgJiAweEZGRkYpICtcbiAgICAgICAgKGMuaGlnaE9yZGVyICYgMHhGRkZGKSArIChkLmhpZ2hPcmRlciAmIDB4RkZGRikgK1xuICAgICAgICAoZS5oaWdoT3JkZXIgJiAweEZGRkYpICsgKG1zdyA+Pj4gMTYpO1xuICAgICAgbXN3ID0gKGEuaGlnaE9yZGVyID4+PiAxNikgKyAoYi5oaWdoT3JkZXIgPj4+IDE2KSArXG4gICAgICAgIChjLmhpZ2hPcmRlciA+Pj4gMTYpICsgKGQuaGlnaE9yZGVyID4+PiAxNikgK1xuICAgICAgICAoZS5oaWdoT3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcbiAgICAgIGhpZ2hPcmRlciA9ICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoaGlnaE9yZGVyLCBsb3dPcmRlcik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgU0hBLTEgaGFzaCBvZiB0aGUgc3RyaW5nIHNldCBhdCBpbnN0YW50aWF0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IG1lc3NhZ2UgVGhlIGJpbmFyeSBhcnJheSByZXByZXNlbnRhdGlvbiBvZiB0aGUgc3RyaW5nIHRvXG4gICAgICpcdCBoYXNoXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG1lc3NhZ2VMZW4gVGhlIG51bWJlciBvZiBiaXRzIGluIHRoZSBtZXNzYWdlXG4gICAgICogQHJldHVybiBUaGUgYXJyYXkgb2YgaW50ZWdlcnMgcmVwcmVzZW50aW5nIHRoZSBTSEEtMSBoYXNoIG9mIG1lc3NhZ2VcbiAgICAgKi9cbiAgICBjb3JlU0hBMSA9IGZ1bmN0aW9uKG1lc3NhZ2UsIG1lc3NhZ2VMZW4pIHtcbiAgICAgIHZhciBXID0gW10sXG4gICAgICAgIGEsIGIsIGMsIGQsIGUsIFQsIGNoID0gY2hfMzIsXG4gICAgICAgIHBhcml0eSA9IHBhcml0eV8zMixcbiAgICAgICAgbWFqID0gbWFqXzMyLFxuICAgICAgICByb3RsID0gcm90bF8zMixcbiAgICAgICAgc2FmZUFkZF8yID0gc2FmZUFkZF8zMl8yLFxuICAgICAgICBpLCB0LFxuICAgICAgICBzYWZlQWRkXzUgPSBzYWZlQWRkXzMyXzUsXG4gICAgICAgIGFwcGVuZGVkTWVzc2FnZUxlbmd0aCxcbiAgICAgICAgSCA9IFtcbiAgICAgICAgICAgIDB4Njc0NTIzMDEsIDB4ZWZjZGFiODksIDB4OThiYWRjZmUsIDB4MTAzMjU0NzYsIDB4YzNkMmUxZjBcbiAgICAgICAgXSxcbiAgICAgICAgSyA9IFtcbiAgICAgICAgICAgIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksXG4gICAgICAgICAgICAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuICAgICAgICAgICAgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSxcbiAgICAgICAgICAgIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksXG4gICAgICAgICAgICAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuICAgICAgICAgICAgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSxcbiAgICAgICAgICAgIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsXG4gICAgICAgICAgICAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuICAgICAgICAgICAgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSxcbiAgICAgICAgICAgIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsXG4gICAgICAgICAgICAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuICAgICAgICAgICAgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYyxcbiAgICAgICAgICAgIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsXG4gICAgICAgICAgICAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuICAgICAgICAgICAgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYyxcbiAgICAgICAgICAgIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsXG4gICAgICAgICAgICAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuICAgICAgICAgICAgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNixcbiAgICAgICAgICAgIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsXG4gICAgICAgICAgICAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2XG4gICAgICAgIF07XG5cbiAgICAgIC8qIEFwcGVuZCAnMScgYXQgdGhlIGVuZCBvZiB0aGUgYmluYXJ5IHN0cmluZyAqL1xuICAgICAgbWVzc2FnZVttZXNzYWdlTGVuID4+IDVdIHw9IDB4ODAgPDwgKDI0IC0gKG1lc3NhZ2VMZW4gJSAzMikpO1xuICAgICAgLyogQXBwZW5kIGxlbmd0aCBvZiBiaW5hcnkgc3RyaW5nIGluIHRoZSBwb3NpdGlvbiBzdWNoIHRoYXQgdGhlIG5ld1xuXHRcdGxlbmd0aCBpcyBhIG11bHRpcGxlIG9mIDUxMi4gIExvZ2ljIGRvZXMgbm90IHdvcmsgZm9yIGV2ZW4gbXVsdGlwbGVzXG5cdFx0b2YgNTEyIGJ1dCB0aGVyZSBjYW4gbmV2ZXIgYmUgZXZlbiBtdWx0aXBsZXMgb2YgNTEyICovXG4gICAgICBtZXNzYWdlWygoKG1lc3NhZ2VMZW4gKyA2NSkgPj4gOSkgPDwgNCkgKyAxNV0gPSBtZXNzYWdlTGVuO1xuXG4gICAgICBhcHBlbmRlZE1lc3NhZ2VMZW5ndGggPSBtZXNzYWdlLmxlbmd0aDtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IGFwcGVuZGVkTWVzc2FnZUxlbmd0aDsgaSArPSAxNikge1xuICAgICAgICBhID0gSFswXTtcbiAgICAgICAgYiA9IEhbMV07XG4gICAgICAgIGMgPSBIWzJdO1xuICAgICAgICBkID0gSFszXTtcbiAgICAgICAgZSA9IEhbNF07XG5cbiAgICAgICAgZm9yICh0ID0gMDsgdCA8IDgwOyB0ICs9IDEpIHtcbiAgICAgICAgICBpZiAodCA8IDE2KSB7XG4gICAgICAgICAgICBXW3RdID0gbWVzc2FnZVt0ICsgaV07XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFdbdF0gPSByb3RsKFdbdCAtIDNdIF4gV1t0IC0gOF0gXiBXW3QgLSAxNF0gXiBXW3QgLSAxNl0sIDEpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0IDwgMjApIHtcbiAgICAgICAgICAgIFQgPSBzYWZlQWRkXzUocm90bChhLCA1KSwgY2goYiwgYywgZCksIGUsIEtbdF0sIFdbdF0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAodCA8IDQwKSB7XG4gICAgICAgICAgICBUID0gc2FmZUFkZF81KHJvdGwoYSwgNSksIHBhcml0eShiLCBjLCBkKSwgZSwgS1t0XSwgV1t0XSk7XG4gICAgICAgICAgfSBlbHNlIGlmICh0IDwgNjApIHtcbiAgICAgICAgICAgIFQgPSBzYWZlQWRkXzUocm90bChhLCA1KSwgbWFqKGIsIGMsIGQpLCBlLCBLW3RdLCBXW3RdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgVCA9IHNhZmVBZGRfNShyb3RsKGEsIDUpLCBwYXJpdHkoYiwgYywgZCksIGUsIEtbdF0sIFdbdF0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGUgPSBkO1xuICAgICAgICAgIGQgPSBjO1xuICAgICAgICAgIGMgPSByb3RsKGIsIDMwKTtcbiAgICAgICAgICBiID0gYTtcbiAgICAgICAgICBhID0gVDtcbiAgICAgICAgfVxuXG4gICAgICAgIEhbMF0gPSBzYWZlQWRkXzIoYSwgSFswXSk7XG4gICAgICAgIEhbMV0gPSBzYWZlQWRkXzIoYiwgSFsxXSk7XG4gICAgICAgIEhbMl0gPSBzYWZlQWRkXzIoYywgSFsyXSk7XG4gICAgICAgIEhbM10gPSBzYWZlQWRkXzIoZCwgSFszXSk7XG4gICAgICAgIEhbNF0gPSBzYWZlQWRkXzIoZSwgSFs0XSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBIO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENhbGN1bGF0ZXMgdGhlIGRlc2lyZWQgU0hBLTIgaGFzaCBvZiB0aGUgc3RyaW5nIHNldCBhdCBpbnN0YW50aWF0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IFRoZSBiaW5hcnkgYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHN0cmluZyB0byBoYXNoXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IFRoZSBudW1iZXIgb2YgYml0cyBpbiBtZXNzYWdlXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHZhcmlhbnQgVGhlIGRlc2lyZWQgU0hBLTIgdmFyaWFudFxuICAgICAqIEByZXR1cm4gVGhlIGFycmF5IG9mIGludGVnZXJzIHJlcHJlc2VudGluZyB0aGUgU0hBLTIgaGFzaCBvZiBtZXNzYWdlXG4gICAgICovXG4gICAgY29yZVNIQTIgPSBmdW5jdGlvbihtZXNzYWdlLCBtZXNzYWdlTGVuLCB2YXJpYW50KSB7XG4gICAgICB2YXIgYSwgYiwgYywgZCwgZSwgZiwgZywgaCwgVDEsIFQyLCBILCBudW1Sb3VuZHMsIGxlbmd0aFBvc2l0aW9uLCBpLCB0LFxuICAgICAgICBiaW5hcnlTdHJpbmdJbmMsIGJpbmFyeVN0cmluZ011bHQsIHNhZmVBZGRfMiwgc2FmZUFkZF80LCBzYWZlQWRkXzUsXG4gICAgICAgIGdhbW1hMCwgZ2FtbWExLCBzaWdtYTAsIHNpZ21hMSwgY2gsIG1haiwgSW50LCBLLCBXID0gW10sXG4gICAgICAgIGFwcGVuZGVkTWVzc2FnZUxlbmd0aDtcblxuICAgICAgLyogU2V0IHVwIHRoZSB2YXJpb3VzIGZ1bmN0aW9uIGhhbmRsZXMgYW5kIHZhcmlhYmxlIGZvciB0aGUgc3BlY2lmaWMgXG4gICAgICAgKiB2YXJpYW50ICovXG4gICAgICBpZiAodmFyaWFudCA9PT0gXCJTSEEtMjI0XCIgfHwgdmFyaWFudCA9PT0gXCJTSEEtMjU2XCIpIHtcbiAgICAgICAgLyogMzItYml0IHZhcmlhbnQgKi9cbiAgICAgICAgbnVtUm91bmRzID0gNjQ7XG4gICAgICAgIGxlbmd0aFBvc2l0aW9uID0gKCgobWVzc2FnZUxlbiArIDY1KSA+PiA5KSA8PCA0KSArIDE1O1xuICAgICAgICBiaW5hcnlTdHJpbmdJbmMgPSAxNjtcbiAgICAgICAgYmluYXJ5U3RyaW5nTXVsdCA9IDE7XG4gICAgICAgIEludCA9IE51bWJlcjtcbiAgICAgICAgc2FmZUFkZF8yID0gc2FmZUFkZF8zMl8yO1xuICAgICAgICBzYWZlQWRkXzQgPSBzYWZlQWRkXzMyXzQ7XG4gICAgICAgIHNhZmVBZGRfNSA9IHNhZmVBZGRfMzJfNTtcbiAgICAgICAgZ2FtbWEwID0gZ2FtbWEwXzMyO1xuICAgICAgICBnYW1tYTEgPSBnYW1tYTFfMzI7XG4gICAgICAgIHNpZ21hMCA9IHNpZ21hMF8zMjtcbiAgICAgICAgc2lnbWExID0gc2lnbWExXzMyO1xuICAgICAgICBtYWogPSBtYWpfMzI7XG4gICAgICAgIGNoID0gY2hfMzI7XG4gICAgICAgIEsgPSBbXG4gICAgICAgICAgICAweDQyOEEyRjk4LCAweDcxMzc0NDkxLCAweEI1QzBGQkNGLCAweEU5QjVEQkE1LFxuICAgICAgICAgICAgMHgzOTU2QzI1QiwgMHg1OUYxMTFGMSwgMHg5MjNGODJBNCwgMHhBQjFDNUVENSxcbiAgICAgICAgICAgIDB4RDgwN0FBOTgsIDB4MTI4MzVCMDEsIDB4MjQzMTg1QkUsIDB4NTUwQzdEQzMsXG4gICAgICAgICAgICAweDcyQkU1RDc0LCAweDgwREVCMUZFLCAweDlCREMwNkE3LCAweEMxOUJGMTc0LFxuICAgICAgICAgICAgMHhFNDlCNjlDMSwgMHhFRkJFNDc4NiwgMHgwRkMxOURDNiwgMHgyNDBDQTFDQyxcbiAgICAgICAgICAgIDB4MkRFOTJDNkYsIDB4NEE3NDg0QUEsIDB4NUNCMEE5REMsIDB4NzZGOTg4REEsXG4gICAgICAgICAgICAweDk4M0U1MTUyLCAweEE4MzFDNjZELCAweEIwMDMyN0M4LCAweEJGNTk3RkM3LFxuICAgICAgICAgICAgMHhDNkUwMEJGMywgMHhENUE3OTE0NywgMHgwNkNBNjM1MSwgMHgxNDI5Mjk2NyxcbiAgICAgICAgICAgIDB4MjdCNzBBODUsIDB4MkUxQjIxMzgsIDB4NEQyQzZERkMsIDB4NTMzODBEMTMsXG4gICAgICAgICAgICAweDY1MEE3MzU0LCAweDc2NkEwQUJCLCAweDgxQzJDOTJFLCAweDkyNzIyQzg1LFxuICAgICAgICAgICAgMHhBMkJGRThBMSwgMHhBODFBNjY0QiwgMHhDMjRCOEI3MCwgMHhDNzZDNTFBMyxcbiAgICAgICAgICAgIDB4RDE5MkU4MTksIDB4RDY5OTA2MjQsIDB4RjQwRTM1ODUsIDB4MTA2QUEwNzAsXG4gICAgICAgICAgICAweDE5QTRDMTE2LCAweDFFMzc2QzA4LCAweDI3NDg3NzRDLCAweDM0QjBCQ0I1LFxuICAgICAgICAgICAgMHgzOTFDMENCMywgMHg0RUQ4QUE0QSwgMHg1QjlDQ0E0RiwgMHg2ODJFNkZGMyxcbiAgICAgICAgICAgIDB4NzQ4RjgyRUUsIDB4NzhBNTYzNkYsIDB4ODRDODc4MTQsIDB4OENDNzAyMDgsXG4gICAgICAgICAgICAweDkwQkVGRkZBLCAweEE0NTA2Q0VCLCAweEJFRjlBM0Y3LCAweEM2NzE3OEYyXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKHZhcmlhbnQgPT09IFwiU0hBLTIyNFwiKSB7XG4gICAgICAgICAgSCA9IFtcbiAgICAgICAgICAgICAgMHhjMTA1OWVkOCwgMHgzNjdjZDUwNywgMHgzMDcwZGQxNywgMHhmNzBlNTkzOSxcbiAgICAgICAgICAgICAgMHhmZmMwMGIzMSwgMHg2ODU4MTUxMSwgMHg2NGY5OGZhNywgMHhiZWZhNGZhNFxuICAgICAgICAgIF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgSCA9IFtcbiAgICAgICAgICAgICAgMHg2QTA5RTY2NywgMHhCQjY3QUU4NSwgMHgzQzZFRjM3MiwgMHhBNTRGRjUzQSxcbiAgICAgICAgICAgICAgMHg1MTBFNTI3RiwgMHg5QjA1Njg4QywgMHgxRjgzRDlBQiwgMHg1QkUwQ0QxOVxuICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodmFyaWFudCA9PT0gXCJTSEEtMzg0XCIgfHwgdmFyaWFudCA9PT0gXCJTSEEtNTEyXCIpIHtcbiAgICAgICAgLyogNjQtYml0IHZhcmlhbnQgKi9cbiAgICAgICAgbnVtUm91bmRzID0gODA7XG4gICAgICAgIGxlbmd0aFBvc2l0aW9uID0gKCgobWVzc2FnZUxlbiArIDEyOCkgPj4gMTApIDw8IDUpICsgMzE7XG4gICAgICAgIGJpbmFyeVN0cmluZ0luYyA9IDMyO1xuICAgICAgICBiaW5hcnlTdHJpbmdNdWx0ID0gMjtcbiAgICAgICAgSW50ID0gSW50XzY0O1xuICAgICAgICBzYWZlQWRkXzIgPSBzYWZlQWRkXzY0XzI7XG4gICAgICAgIHNhZmVBZGRfNCA9IHNhZmVBZGRfNjRfNDtcbiAgICAgICAgc2FmZUFkZF81ID0gc2FmZUFkZF82NF81O1xuICAgICAgICBnYW1tYTAgPSBnYW1tYTBfNjQ7XG4gICAgICAgIGdhbW1hMSA9IGdhbW1hMV82NDtcbiAgICAgICAgc2lnbWEwID0gc2lnbWEwXzY0O1xuICAgICAgICBzaWdtYTEgPSBzaWdtYTFfNjQ7XG4gICAgICAgIG1haiA9IG1hal82NDtcbiAgICAgICAgY2ggPSBjaF82NDtcblxuICAgICAgICBLID0gW1xuICAgICAgICAgICAgbmV3IEludCgweDQyOGEyZjk4LCAweGQ3MjhhZTIyKSwgbmV3IEludCgweDcxMzc0NDkxLCAweDIzZWY2NWNkKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhiNWMwZmJjZiwgMHhlYzRkM2IyZiksIG5ldyBJbnQoMHhlOWI1ZGJhNSwgMHg4MTg5ZGJiYyksXG4gICAgICAgICAgICBuZXcgSW50KDB4Mzk1NmMyNWIsIDB4ZjM0OGI1MzgpLCBuZXcgSW50KDB4NTlmMTExZjEsIDB4YjYwNWQwMTkpLFxuICAgICAgICAgICAgbmV3IEludCgweDkyM2Y4MmE0LCAweGFmMTk0ZjliKSwgbmV3IEludCgweGFiMWM1ZWQ1LCAweGRhNmQ4MTE4KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhkODA3YWE5OCwgMHhhMzAzMDI0MiksIG5ldyBJbnQoMHgxMjgzNWIwMSwgMHg0NTcwNmZiZSksXG4gICAgICAgICAgICBuZXcgSW50KDB4MjQzMTg1YmUsIDB4NGVlNGIyOGMpLCBuZXcgSW50KDB4NTUwYzdkYzMsIDB4ZDVmZmI0ZTIpLFxuICAgICAgICAgICAgbmV3IEludCgweDcyYmU1ZDc0LCAweGYyN2I4OTZmKSwgbmV3IEludCgweDgwZGViMWZlLCAweDNiMTY5NmIxKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg5YmRjMDZhNywgMHgyNWM3MTIzNSksIG5ldyBJbnQoMHhjMTliZjE3NCwgMHhjZjY5MjY5NCksXG4gICAgICAgICAgICBuZXcgSW50KDB4ZTQ5YjY5YzEsIDB4OWVmMTRhZDIpLCBuZXcgSW50KDB4ZWZiZTQ3ODYsIDB4Mzg0ZjI1ZTMpLFxuICAgICAgICAgICAgbmV3IEludCgweDBmYzE5ZGM2LCAweDhiOGNkNWI1KSwgbmV3IEludCgweDI0MGNhMWNjLCAweDc3YWM5YzY1KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgyZGU5MmM2ZiwgMHg1OTJiMDI3NSksIG5ldyBJbnQoMHg0YTc0ODRhYSwgMHg2ZWE2ZTQ4MyksXG4gICAgICAgICAgICBuZXcgSW50KDB4NWNiMGE5ZGMsIDB4YmQ0MWZiZDQpLCBuZXcgSW50KDB4NzZmOTg4ZGEsIDB4ODMxMTUzYjUpLFxuICAgICAgICAgICAgbmV3IEludCgweDk4M2U1MTUyLCAweGVlNjZkZmFiKSwgbmV3IEludCgweGE4MzFjNjZkLCAweDJkYjQzMjEwKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhiMDAzMjdjOCwgMHg5OGZiMjEzZiksIG5ldyBJbnQoMHhiZjU5N2ZjNywgMHhiZWVmMGVlNCksXG4gICAgICAgICAgICBuZXcgSW50KDB4YzZlMDBiZjMsIDB4M2RhODhmYzIpLCBuZXcgSW50KDB4ZDVhNzkxNDcsIDB4OTMwYWE3MjUpLFxuICAgICAgICAgICAgbmV3IEludCgweDA2Y2E2MzUxLCAweGUwMDM4MjZmKSwgbmV3IEludCgweDE0MjkyOTY3LCAweDBhMGU2ZTcwKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgyN2I3MGE4NSwgMHg0NmQyMmZmYyksIG5ldyBJbnQoMHgyZTFiMjEzOCwgMHg1YzI2YzkyNiksXG4gICAgICAgICAgICBuZXcgSW50KDB4NGQyYzZkZmMsIDB4NWFjNDJhZWQpLCBuZXcgSW50KDB4NTMzODBkMTMsIDB4OWQ5NWIzZGYpLFxuICAgICAgICAgICAgbmV3IEludCgweDY1MGE3MzU0LCAweDhiYWY2M2RlKSwgbmV3IEludCgweDc2NmEwYWJiLCAweDNjNzdiMmE4KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg4MWMyYzkyZSwgMHg0N2VkYWVlNiksIG5ldyBJbnQoMHg5MjcyMmM4NSwgMHgxNDgyMzUzYiksXG4gICAgICAgICAgICBuZXcgSW50KDB4YTJiZmU4YTEsIDB4NGNmMTAzNjQpLCBuZXcgSW50KDB4YTgxYTY2NGIsIDB4YmM0MjMwMDEpLFxuICAgICAgICAgICAgbmV3IEludCgweGMyNGI4YjcwLCAweGQwZjg5NzkxKSwgbmV3IEludCgweGM3NmM1MWEzLCAweDA2NTRiZTMwKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhkMTkyZTgxOSwgMHhkNmVmNTIxOCksIG5ldyBJbnQoMHhkNjk5MDYyNCwgMHg1NTY1YTkxMCksXG4gICAgICAgICAgICBuZXcgSW50KDB4ZjQwZTM1ODUsIDB4NTc3MTIwMmEpLCBuZXcgSW50KDB4MTA2YWEwNzAsIDB4MzJiYmQxYjgpLFxuICAgICAgICAgICAgbmV3IEludCgweDE5YTRjMTE2LCAweGI4ZDJkMGM4KSwgbmV3IEludCgweDFlMzc2YzA4LCAweDUxNDFhYjUzKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgyNzQ4Nzc0YywgMHhkZjhlZWI5OSksIG5ldyBJbnQoMHgzNGIwYmNiNSwgMHhlMTliNDhhOCksXG4gICAgICAgICAgICBuZXcgSW50KDB4MzkxYzBjYjMsIDB4YzVjOTVhNjMpLCBuZXcgSW50KDB4NGVkOGFhNGEsIDB4ZTM0MThhY2IpLFxuICAgICAgICAgICAgbmV3IEludCgweDViOWNjYTRmLCAweDc3NjNlMzczKSwgbmV3IEludCgweDY4MmU2ZmYzLCAweGQ2YjJiOGEzKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg3NDhmODJlZSwgMHg1ZGVmYjJmYyksIG5ldyBJbnQoMHg3OGE1NjM2ZiwgMHg0MzE3MmY2MCksXG4gICAgICAgICAgICBuZXcgSW50KDB4ODRjODc4MTQsIDB4YTFmMGFiNzIpLCBuZXcgSW50KDB4OGNjNzAyMDgsIDB4MWE2NDM5ZWMpLFxuICAgICAgICAgICAgbmV3IEludCgweDkwYmVmZmZhLCAweDIzNjMxZTI4KSwgbmV3IEludCgweGE0NTA2Y2ViLCAweGRlODJiZGU5KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhiZWY5YTNmNywgMHhiMmM2NzkxNSksIG5ldyBJbnQoMHhjNjcxNzhmMiwgMHhlMzcyNTMyYiksXG4gICAgICAgICAgICBuZXcgSW50KDB4Y2EyNzNlY2UsIDB4ZWEyNjYxOWMpLCBuZXcgSW50KDB4ZDE4NmI4YzcsIDB4MjFjMGMyMDcpLFxuICAgICAgICAgICAgbmV3IEludCgweGVhZGE3ZGQ2LCAweGNkZTBlYjFlKSwgbmV3IEludCgweGY1N2Q0ZjdmLCAweGVlNmVkMTc4KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgwNmYwNjdhYSwgMHg3MjE3NmZiYSksIG5ldyBJbnQoMHgwYTYzN2RjNSwgMHhhMmM4OThhNiksXG4gICAgICAgICAgICBuZXcgSW50KDB4MTEzZjk4MDQsIDB4YmVmOTBkYWUpLCBuZXcgSW50KDB4MWI3MTBiMzUsIDB4MTMxYzQ3MWIpLFxuICAgICAgICAgICAgbmV3IEludCgweDI4ZGI3N2Y1LCAweDIzMDQ3ZDg0KSwgbmV3IEludCgweDMyY2FhYjdiLCAweDQwYzcyNDkzKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgzYzllYmUwYSwgMHgxNWM5YmViYyksIG5ldyBJbnQoMHg0MzFkNjdjNCwgMHg5YzEwMGQ0YyksXG4gICAgICAgICAgICBuZXcgSW50KDB4NGNjNWQ0YmUsIDB4Y2IzZTQyYjYpLCBuZXcgSW50KDB4NTk3ZjI5OWMsIDB4ZmM2NTdlMmEpLFxuICAgICAgICAgICAgbmV3IEludCgweDVmY2I2ZmFiLCAweDNhZDZmYWVjKSwgbmV3IEludCgweDZjNDQxOThjLCAweDRhNDc1ODE3KVxuICAgICAgICBdO1xuXG4gICAgICAgIGlmICh2YXJpYW50ID09PSBcIlNIQS0zODRcIikge1xuICAgICAgICAgIEggPSBbXG4gICAgICAgICAgICAgIG5ldyBJbnQoMHhjYmJiOWQ1ZCwgMHhjMTA1OWVkOCksIG5ldyBJbnQoMHgwNjI5YTI5MmEsIDB4MzY3Y2Q1MDcpLFxuICAgICAgICAgICAgICBuZXcgSW50KDB4OTE1OTAxNWEsIDB4MzA3MGRkMTcpLCBuZXcgSW50KDB4MDE1MmZlY2Q4LCAweGY3MGU1OTM5KSxcbiAgICAgICAgICAgICAgbmV3IEludCgweDY3MzMyNjY3LCAweGZmYzAwYjMxKSwgbmV3IEludCgweDk4ZWI0NGE4NywgMHg2ODU4MTUxMSksXG4gICAgICAgICAgICAgIG5ldyBJbnQoMHhkYjBjMmUwZCwgMHg2NGY5OGZhNyksIG5ldyBJbnQoMHgwNDdiNTQ4MWQsIDB4YmVmYTRmYTQpXG4gICAgICAgICAgXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBIID0gW1xuICAgICAgICAgICAgICBuZXcgSW50KDB4NmEwOWU2NjcsIDB4ZjNiY2M5MDgpLCBuZXcgSW50KDB4YmI2N2FlODUsIDB4ODRjYWE3M2IpLFxuICAgICAgICAgICAgICBuZXcgSW50KDB4M2M2ZWYzNzIsIDB4ZmU5NGY4MmIpLCBuZXcgSW50KDB4YTU0ZmY1M2EsIDB4NWYxZDM2ZjEpLFxuICAgICAgICAgICAgICBuZXcgSW50KDB4NTEwZTUyN2YsIDB4YWRlNjgyZDEpLCBuZXcgSW50KDB4OWIwNTY4OGMsIDB4MmIzZTZjMWYpLFxuICAgICAgICAgICAgICBuZXcgSW50KDB4MWY4M2Q5YWIsIDB4ZmI0MWJkNmIpLCBuZXcgSW50KDB4NWJlMGNkMTksIDB4MTM3ZTIxNzkpXG4gICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvKiBBcHBlbmQgJzEnIGF0IHRoZSBlbmQgb2YgdGhlIGJpbmFyeSBzdHJpbmcgKi9cbiAgICAgIG1lc3NhZ2VbbWVzc2FnZUxlbiA+PiA1XSB8PSAweDgwIDw8ICgyNCAtIG1lc3NhZ2VMZW4gJSAzMik7XG4gICAgICAvKiBBcHBlbmQgbGVuZ3RoIG9mIGJpbmFyeSBzdHJpbmcgaW4gdGhlIHBvc2l0aW9uIHN1Y2ggdGhhdCB0aGUgbmV3XG4gICAgICAgKiBsZW5ndGggaXMgY29ycmVjdCAqL1xuICAgICAgbWVzc2FnZVtsZW5ndGhQb3NpdGlvbl0gPSBtZXNzYWdlTGVuO1xuXG4gICAgICBhcHBlbmRlZE1lc3NhZ2VMZW5ndGggPSBtZXNzYWdlLmxlbmd0aDtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IGFwcGVuZGVkTWVzc2FnZUxlbmd0aDsgaSArPSBiaW5hcnlTdHJpbmdJbmMpIHtcbiAgICAgICAgYSA9IEhbMF07XG4gICAgICAgIGIgPSBIWzFdO1xuICAgICAgICBjID0gSFsyXTtcbiAgICAgICAgZCA9IEhbM107XG4gICAgICAgIGUgPSBIWzRdO1xuICAgICAgICBmID0gSFs1XTtcbiAgICAgICAgZyA9IEhbNl07XG4gICAgICAgIGggPSBIWzddO1xuXG4gICAgICAgIGZvciAodCA9IDA7IHQgPCBudW1Sb3VuZHM7IHQgKz0gMSkge1xuICAgICAgICAgIGlmICh0IDwgMTYpIHtcbiAgICAgICAgICAgIC8qIEJpdCBvZiBhIGhhY2sgLSBmb3IgMzItYml0LCB0aGUgc2Vjb25kIHRlcm0gaXMgaWdub3JlZCAqL1xuICAgICAgICAgICAgV1t0XSA9IG5ldyBJbnQobWVzc2FnZVt0ICogYmluYXJ5U3RyaW5nTXVsdCArIGldLFxuICAgICAgICAgICAgICBtZXNzYWdlW3QgKiBiaW5hcnlTdHJpbmdNdWx0ICsgaSArIDFdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgV1t0XSA9IHNhZmVBZGRfNChcbiAgICAgICAgICAgICAgZ2FtbWExKFdbdCAtIDJdKSwgV1t0IC0gN10sXG4gICAgICAgICAgICAgIGdhbW1hMChXW3QgLSAxNV0pLCBXW3QgLSAxNl0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIFQxID0gc2FmZUFkZF81KGgsIHNpZ21hMShlKSwgY2goZSwgZiwgZyksIEtbdF0sIFdbdF0pO1xuICAgICAgICAgIFQyID0gc2FmZUFkZF8yKHNpZ21hMChhKSwgbWFqKGEsIGIsIGMpKTtcbiAgICAgICAgICBoID0gZztcbiAgICAgICAgICBnID0gZjtcbiAgICAgICAgICBmID0gZTtcbiAgICAgICAgICBlID0gc2FmZUFkZF8yKGQsIFQxKTtcbiAgICAgICAgICBkID0gYztcbiAgICAgICAgICBjID0gYjtcbiAgICAgICAgICBiID0gYTtcbiAgICAgICAgICBhID0gc2FmZUFkZF8yKFQxLCBUMik7XG4gICAgICAgIH1cblxuICAgICAgICBIWzBdID0gc2FmZUFkZF8yKGEsIEhbMF0pO1xuICAgICAgICBIWzFdID0gc2FmZUFkZF8yKGIsIEhbMV0pO1xuICAgICAgICBIWzJdID0gc2FmZUFkZF8yKGMsIEhbMl0pO1xuICAgICAgICBIWzNdID0gc2FmZUFkZF8yKGQsIEhbM10pO1xuICAgICAgICBIWzRdID0gc2FmZUFkZF8yKGUsIEhbNF0pO1xuICAgICAgICBIWzVdID0gc2FmZUFkZF8yKGYsIEhbNV0pO1xuICAgICAgICBIWzZdID0gc2FmZUFkZF8yKGcsIEhbNl0pO1xuICAgICAgICBIWzddID0gc2FmZUFkZF8yKGgsIEhbN10pO1xuICAgICAgfVxuXG4gICAgICBzd2l0Y2ggKHZhcmlhbnQpIHtcbiAgICAgICAgY2FzZSBcIlNIQS0yMjRcIjpcbiAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgSFswXSwgSFsxXSwgSFsyXSwgSFszXSxcbiAgICAgICAgICAgIEhbNF0sIEhbNV0sIEhbNl1dO1xuICAgICAgICBjYXNlIFwiU0hBLTI1NlwiOlxuICAgICAgICAgIHJldHVybiBIO1xuICAgICAgICBjYXNlIFwiU0hBLTM4NFwiOlxuICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBIWzBdLmhpZ2hPcmRlciwgSFswXS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbMV0uaGlnaE9yZGVyLCBIWzFdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFsyXS5oaWdoT3JkZXIsIEhbMl0ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzNdLmhpZ2hPcmRlciwgSFszXS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbNF0uaGlnaE9yZGVyLCBIWzRdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFs1XS5oaWdoT3JkZXIsIEhbNV0ubG93T3JkZXJdO1xuICAgICAgICBjYXNlIFwiU0hBLTUxMlwiOlxuICAgICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBIWzBdLmhpZ2hPcmRlciwgSFswXS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbMV0uaGlnaE9yZGVyLCBIWzFdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFsyXS5oaWdoT3JkZXIsIEhbMl0ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzNdLmhpZ2hPcmRlciwgSFszXS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbNF0uaGlnaE9yZGVyLCBIWzRdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFs1XS5oaWdoT3JkZXIsIEhbNV0ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzZdLmhpZ2hPcmRlciwgSFs2XS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbN10uaGlnaE9yZGVyLCBIWzddLmxvd09yZGVyXTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAvKiBUaGlzIHNob3VsZCBuZXZlciBiZSByZWFjaGVkICovXG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIGpzU0hBIGlzIHRoZSB3b3JraG9yc2Ugb2YgdGhlIGxpYnJhcnkuICBJbnN0YW50aWF0ZSBpdCB3aXRoIHRoZSBzdHJpbmcgdG9cbiAgICAgKiBiZSBoYXNoZWQgYXMgdGhlIHBhcmFtZXRlclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHNyY1N0cmluZyBUaGUgc3RyaW5nIHRvIGJlIGhhc2hlZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dEZvcm1hdCBUaGUgZm9ybWF0IG9mIHNyY1N0cmluZywgQVNDSUkgb3IgSEVYXG4gICAgICovXG4gICAganNTSEEgPSBmdW5jdGlvbihzcmNTdHJpbmcsIGlucHV0Rm9ybWF0KSB7XG5cbiAgICAgIHRoaXMuc2hhMSA9IG51bGw7XG4gICAgICB0aGlzLnNoYTIyNCA9IG51bGw7XG4gICAgICB0aGlzLnNoYTI1NiA9IG51bGw7XG4gICAgICB0aGlzLnNoYTM4NCA9IG51bGw7XG4gICAgICB0aGlzLnNoYTUxMiA9IG51bGw7XG5cbiAgICAgIHRoaXMuc3RyQmluTGVuID0gbnVsbDtcbiAgICAgIHRoaXMuc3RyVG9IYXNoID0gbnVsbDtcblxuICAgICAgLyogQ29udmVydCB0aGUgaW5wdXQgc3RyaW5nIGludG8gdGhlIGNvcnJlY3QgdHlwZSAqL1xuICAgICAgaWYgKFwiSEVYXCIgPT09IGlucHV0Rm9ybWF0KSB7XG4gICAgICAgIGlmICgwICE9PSAoc3JjU3RyaW5nLmxlbmd0aCAlIDIpKSB7XG4gICAgICAgICAgcmV0dXJuIFwiVEVYVCBNVVNUIEJFIElOIEJZVEUgSU5DUkVNRU5UU1wiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RyQmluTGVuID0gc3JjU3RyaW5nLmxlbmd0aCAqIDQ7XG4gICAgICAgIHRoaXMuc3RyVG9IYXNoID0gaGV4MmJpbmIoc3JjU3RyaW5nKTtcbiAgICAgIH0gZWxzZSBpZiAoKFwiQVNDSUlcIiA9PT0gaW5wdXRGb3JtYXQpIHx8XG4gICAgICAgICgndW5kZWZpbmVkJyA9PT0gdHlwZW9mKGlucHV0Rm9ybWF0KSkpIHtcbiAgICAgICAgdGhpcy5zdHJCaW5MZW4gPSBzcmNTdHJpbmcubGVuZ3RoICogY2hhclNpemU7XG4gICAgICAgIHRoaXMuc3RyVG9IYXNoID0gc3RyMmJpbmIoc3JjU3RyaW5nKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBcIlVOS05PV04gVEVYVCBJTlBVVCBUWVBFXCI7XG4gICAgICB9XG4gICAgfTtcblxuICBqc1NIQS5wcm90b3R5cGUgPSB7XG4gICAgLypcbiAgICAgKiBSZXR1cm5zIHRoZSBkZXNpcmVkIFNIQSBoYXNoIG9mIHRoZSBzdHJpbmcgc3BlY2lmaWVkIGF0IGluc3RhbnRpYXRpb25cbiAgICAgKiB1c2luZyB0aGUgc3BlY2lmaWVkIHBhcmFtZXRlcnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB2YXJpYW50IFRoZSBkZXNpcmVkIFNIQSB2YXJpYW50IChTSEEtMSwgU0hBLTIyNCxcbiAgICAgKlx0IFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIpXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGZvcm1hdCBUaGUgZGVzaXJlZCBvdXRwdXQgZm9ybWF0dGluZyAoQjY0IG9yIEhFWClcbiAgICAgKiBAcmV0dXJuIFRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGhhc2ggaW4gdGhlIGZvcm1hdCBzcGVjaWZpZWRcbiAgICAgKi9cbiAgICBnZXRIYXNoOiBmdW5jdGlvbih2YXJpYW50LCBmb3JtYXQpIHtcbiAgICAgIHZhciBmb3JtYXRGdW5jID0gbnVsbCxcbiAgICAgICAgbWVzc2FnZSA9IHRoaXMuc3RyVG9IYXNoLnNsaWNlKCk7XG5cbiAgICAgIHN3aXRjaCAoZm9ybWF0KSB7XG4gICAgICAgIGNhc2UgXCJIRVhcIjpcbiAgICAgICAgICBmb3JtYXRGdW5jID0gYmluYjJoZXg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJCNjRcIjpcbiAgICAgICAgICBmb3JtYXRGdW5jID0gYmluYjJiNjQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJBU0NJSVwiOlxuICAgICAgICAgIGZvcm1hdEZ1bmMgPSBiaW5iMnN0cjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gXCJGT1JNQVQgTk9UIFJFQ09HTklaRURcIjtcbiAgICAgIH1cblxuICAgICAgc3dpdGNoICh2YXJpYW50KSB7XG4gICAgICAgIGNhc2UgXCJTSEEtMVwiOlxuICAgICAgICAgIGlmIChudWxsID09PSB0aGlzLnNoYTEpIHtcbiAgICAgICAgICAgIHRoaXMuc2hhMSA9IGNvcmVTSEExKG1lc3NhZ2UsIHRoaXMuc3RyQmluTGVuKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmModGhpcy5zaGExKTtcbiAgICAgICAgY2FzZSBcIlNIQS0yMjRcIjpcbiAgICAgICAgICBpZiAobnVsbCA9PT0gdGhpcy5zaGEyMjQpIHtcbiAgICAgICAgICAgIHRoaXMuc2hhMjI0ID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZm9ybWF0RnVuYyh0aGlzLnNoYTIyNCk7XG4gICAgICAgIGNhc2UgXCJTSEEtMjU2XCI6XG4gICAgICAgICAgaWYgKG51bGwgPT09IHRoaXMuc2hhMjU2KSB7XG4gICAgICAgICAgICB0aGlzLnNoYTI1NiA9IGNvcmVTSEEyKG1lc3NhZ2UsIHRoaXMuc3RyQmluTGVuLCB2YXJpYW50KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmModGhpcy5zaGEyNTYpO1xuICAgICAgICBjYXNlIFwiU0hBLTM4NFwiOlxuICAgICAgICAgIGlmIChudWxsID09PSB0aGlzLnNoYTM4NCkge1xuICAgICAgICAgICAgdGhpcy5zaGEzODQgPSBjb3JlU0hBMihtZXNzYWdlLCB0aGlzLnN0ckJpbkxlbiwgdmFyaWFudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhMzg0KTtcbiAgICAgICAgY2FzZSBcIlNIQS01MTJcIjpcbiAgICAgICAgICBpZiAobnVsbCA9PT0gdGhpcy5zaGE1MTIpIHtcbiAgICAgICAgICAgIHRoaXMuc2hhNTEyID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZm9ybWF0RnVuYyh0aGlzLnNoYTUxMik7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIFwiSEFTSCBOT1QgUkVDT0dOSVpFRFwiO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFJldHVybnMgdGhlIGRlc2lyZWQgSE1BQyBvZiB0aGUgc3RyaW5nIHNwZWNpZmllZCBhdCBpbnN0YW50aWF0aW9uXG4gICAgICogdXNpbmcgdGhlIGtleSBhbmQgdmFyaWFudCBwYXJhbS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBrZXkgVGhlIGtleSB1c2VkIHRvIGNhbGN1bGF0ZSB0aGUgSE1BQ1xuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dEZvcm1hdCBUaGUgZm9ybWF0IG9mIGtleSwgQVNDSUkgb3IgSEVYXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IHZhcmlhbnQgVGhlIGRlc2lyZWQgU0hBIHZhcmlhbnQgKFNIQS0xLCBTSEEtMjI0LFxuICAgICAqXHQgU0hBLTI1NiwgU0hBLTM4NCwgb3IgU0hBLTUxMilcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gb3V0cHV0Rm9ybWF0IFRoZSBkZXNpcmVkIG91dHB1dCBmb3JtYXR0aW5nXG4gICAgICpcdCAoQjY0IG9yIEhFWClcbiAgICAgKiBAcmV0dXJuIFRoZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGhhc2ggaW4gdGhlIGZvcm1hdCBzcGVjaWZpZWRcbiAgICAgKi9cbiAgICBnZXRITUFDOiBmdW5jdGlvbihrZXksIGlucHV0Rm9ybWF0LCB2YXJpYW50LCBvdXRwdXRGb3JtYXQpIHtcbiAgICAgIHZhciBmb3JtYXRGdW5jLCBrZXlUb1VzZSwgYmxvY2tCeXRlU2l6ZSwgYmxvY2tCaXRTaXplLCBpLFxuICAgICAgICByZXRWYWwsIGxhc3RBcnJheUluZGV4LCBrZXlCaW5MZW4sIGhhc2hCaXRTaXplLFxuICAgICAgICBrZXlXaXRoSVBhZCA9IFtdLFxuICAgICAgICBrZXlXaXRoT1BhZCA9IFtdO1xuXG4gICAgICAvKiBWYWxpZGF0ZSB0aGUgb3V0cHV0IGZvcm1hdCBzZWxlY3Rpb24gKi9cbiAgICAgIHN3aXRjaCAob3V0cHV0Rm9ybWF0KSB7XG4gICAgICAgIGNhc2UgXCJIRVhcIjpcbiAgICAgICAgICBmb3JtYXRGdW5jID0gYmluYjJoZXg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJCNjRcIjpcbiAgICAgICAgICBmb3JtYXRGdW5jID0gYmluYjJiNjQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJBU0NJSVwiOlxuICAgICAgICAgIGZvcm1hdEZ1bmMgPSBiaW5iMnN0cjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gXCJGT1JNQVQgTk9UIFJFQ09HTklaRURcIjtcbiAgICAgIH1cblxuICAgICAgLyogVmFsaWRhdGUgdGhlIGhhc2ggdmFyaWFudCBzZWxlY3Rpb24gYW5kIHNldCBuZWVkZWQgdmFyaWFibGVzICovXG4gICAgICBzd2l0Y2ggKHZhcmlhbnQpIHtcbiAgICAgICAgY2FzZSBcIlNIQS0xXCI6XG4gICAgICAgICAgYmxvY2tCeXRlU2l6ZSA9IDY0O1xuICAgICAgICAgIGhhc2hCaXRTaXplID0gMTYwO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiU0hBLTIyNFwiOlxuICAgICAgICAgIGJsb2NrQnl0ZVNpemUgPSA2NDtcbiAgICAgICAgICBoYXNoQml0U2l6ZSA9IDIyNDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIlNIQS0yNTZcIjpcbiAgICAgICAgICBibG9ja0J5dGVTaXplID0gNjQ7XG4gICAgICAgICAgaGFzaEJpdFNpemUgPSAyNTY7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJTSEEtMzg0XCI6XG4gICAgICAgICAgYmxvY2tCeXRlU2l6ZSA9IDEyODtcbiAgICAgICAgICBoYXNoQml0U2l6ZSA9IDM4NDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIlNIQS01MTJcIjpcbiAgICAgICAgICBibG9ja0J5dGVTaXplID0gMTI4O1xuICAgICAgICAgIGhhc2hCaXRTaXplID0gNTEyO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBcIkhBU0ggTk9UIFJFQ09HTklaRURcIjtcbiAgICAgIH1cblxuICAgICAgLyogVmFsaWRhdGUgaW5wdXQgZm9ybWF0IHNlbGVjdGlvbiAqL1xuICAgICAgaWYgKFwiSEVYXCIgPT09IGlucHV0Rm9ybWF0KSB7XG4gICAgICAgIC8qIE5pYmJsZXMgbXVzdCBjb21lIGluIHBhaXJzICovXG4gICAgICAgIGlmICgwICE9PSAoa2V5Lmxlbmd0aCAlIDIpKSB7XG4gICAgICAgICAgcmV0dXJuIFwiS0VZIE1VU1QgQkUgSU4gQllURSBJTkNSRU1FTlRTXCI7XG4gICAgICAgIH1cbiAgICAgICAga2V5VG9Vc2UgPSBoZXgyYmluYihrZXkpO1xuICAgICAgICBrZXlCaW5MZW4gPSBrZXkubGVuZ3RoICogNDtcbiAgICAgIH0gZWxzZSBpZiAoXCJBU0NJSVwiID09PSBpbnB1dEZvcm1hdCkge1xuICAgICAgICBrZXlUb1VzZSA9IHN0cjJiaW5iKGtleSk7XG4gICAgICAgIGtleUJpbkxlbiA9IGtleS5sZW5ndGggKiBjaGFyU2l6ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBcIlVOS05PV04gS0VZIElOUFVUIFRZUEVcIjtcbiAgICAgIH1cblxuICAgICAgLyogVGhlc2UgYXJlIHVzZWQgbXVsdGlwbGUgdGltZXMsIGNhbGN1bGF0ZSBhbmQgc3RvcmUgdGhlbSAqL1xuICAgICAgYmxvY2tCaXRTaXplID0gYmxvY2tCeXRlU2l6ZSAqIDg7XG4gICAgICBsYXN0QXJyYXlJbmRleCA9IChibG9ja0J5dGVTaXplIC8gNCkgLSAxO1xuXG4gICAgICAvKiBGaWd1cmUgb3V0IHdoYXQgdG8gZG8gd2l0aCB0aGUga2V5IGJhc2VkIG9uIGl0cyBzaXplIHJlbGF0aXZlIHRvXG4gICAgICAgKiB0aGUgaGFzaCdzIGJsb2NrIHNpemUgKi9cbiAgICAgIGlmIChibG9ja0J5dGVTaXplIDwgKGtleUJpbkxlbiAvIDgpKSB7XG4gICAgICAgIGlmIChcIlNIQS0xXCIgPT09IHZhcmlhbnQpIHtcbiAgICAgICAgICBrZXlUb1VzZSA9IGNvcmVTSEExKGtleVRvVXNlLCBrZXlCaW5MZW4pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGtleVRvVXNlID0gY29yZVNIQTIoa2V5VG9Vc2UsIGtleUJpbkxlbiwgdmFyaWFudCk7XG4gICAgICAgIH1cbiAgICAgICAgLyogRm9yIGFsbCB2YXJpYW50cywgdGhlIGJsb2NrIHNpemUgaXMgYmlnZ2VyIHRoYW4gdGhlIG91dHB1dFxuICAgICAgICAgKiBzaXplIHNvIHRoZXJlIHdpbGwgbmV2ZXIgYmUgYSB1c2VmdWwgYnl0ZSBhdCB0aGUgZW5kIG9mIHRoZVxuICAgICAgICAgKiBzdHJpbmcgKi9cbiAgICAgICAga2V5VG9Vc2VbbGFzdEFycmF5SW5kZXhdICY9IDB4RkZGRkZGMDA7XG4gICAgICB9IGVsc2UgaWYgKGJsb2NrQnl0ZVNpemUgPiAoa2V5QmluTGVuIC8gOCkpIHtcbiAgICAgICAgLyogSWYgdGhlIGJsb2NrQnl0ZVNpemUgaXMgZ3JlYXRlciB0aGFuIHRoZSBrZXkgbGVuZ3RoLCB0aGVyZVxuICAgICAgICAgKiB3aWxsIGFsd2F5cyBiZSBhdCBMRUFTVCBvbmUgXCJ1c2VsZXNzXCIgYnl0ZSBhdCB0aGUgZW5kIG9mIHRoZVxuICAgICAgICAgKiBzdHJpbmcgKi9cbiAgICAgICAga2V5VG9Vc2VbbGFzdEFycmF5SW5kZXhdICY9IDB4RkZGRkZGMDA7XG4gICAgICB9XG5cbiAgICAgIC8qIENyZWF0ZSBpcGFkIGFuZCBvcGFkICovXG4gICAgICBmb3IgKGkgPSAwOyBpIDw9IGxhc3RBcnJheUluZGV4OyBpICs9IDEpIHtcbiAgICAgICAga2V5V2l0aElQYWRbaV0gPSBrZXlUb1VzZVtpXSBeIDB4MzYzNjM2MzY7XG4gICAgICAgIGtleVdpdGhPUGFkW2ldID0ga2V5VG9Vc2VbaV0gXiAweDVDNUM1QzVDO1xuICAgICAgfVxuXG4gICAgICAvKiBDYWxjdWxhdGUgdGhlIEhNQUMgKi9cbiAgICAgIGlmIChcIlNIQS0xXCIgPT09IHZhcmlhbnQpIHtcbiAgICAgICAgcmV0VmFsID0gY29yZVNIQTEoXG4gICAgICAgICAga2V5V2l0aElQYWQuY29uY2F0KHRoaXMuc3RyVG9IYXNoKSxcbiAgICAgICAgICBibG9ja0JpdFNpemUgKyB0aGlzLnN0ckJpbkxlbik7XG4gICAgICAgIHJldFZhbCA9IGNvcmVTSEExKFxuICAgICAgICAgIGtleVdpdGhPUGFkLmNvbmNhdChyZXRWYWwpLFxuICAgICAgICAgIGJsb2NrQml0U2l6ZSArIGhhc2hCaXRTaXplKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldFZhbCA9IGNvcmVTSEEyKFxuICAgICAgICAgIGtleVdpdGhJUGFkLmNvbmNhdCh0aGlzLnN0clRvSGFzaCksXG4gICAgICAgICAgYmxvY2tCaXRTaXplICsgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuICAgICAgICByZXRWYWwgPSBjb3JlU0hBMihcbiAgICAgICAgICBrZXlXaXRoT1BhZC5jb25jYXQocmV0VmFsKSxcbiAgICAgICAgICBibG9ja0JpdFNpemUgKyBoYXNoQml0U2l6ZSwgdmFyaWFudCk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAoZm9ybWF0RnVuYyhyZXRWYWwpKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIGpzU0hBO1xufSgpKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHNoYTE6IGZ1bmN0aW9uKHN0cikge1xuICAgIHZhciBzaGFPYmogPSBuZXcganNTSEEoc3RyLCBcIkFTQ0lJXCIpO1xuICAgIHJldHVybiBzaGFPYmouZ2V0SGFzaChcIlNIQS0xXCIsIFwiQVNDSUlcIik7XG4gIH0sXG4gIHNoYTIyNDogZnVuY3Rpb24oc3RyKSB7XG4gICAgdmFyIHNoYU9iaiA9IG5ldyBqc1NIQShzdHIsIFwiQVNDSUlcIik7XG4gICAgcmV0dXJuIHNoYU9iai5nZXRIYXNoKFwiU0hBLTIyNFwiLCBcIkFTQ0lJXCIpO1xuICB9LFxuICBzaGEyNTY6IGZ1bmN0aW9uKHN0cikge1xuICAgIHZhciBzaGFPYmogPSBuZXcganNTSEEoc3RyLCBcIkFTQ0lJXCIpO1xuICAgIHJldHVybiBzaGFPYmouZ2V0SGFzaChcIlNIQS0yNTZcIiwgXCJBU0NJSVwiKTtcbiAgfSxcbiAgc2hhMzg0OiBmdW5jdGlvbihzdHIpIHtcbiAgICB2YXIgc2hhT2JqID0gbmV3IGpzU0hBKHN0ciwgXCJBU0NJSVwiKTtcbiAgICByZXR1cm4gc2hhT2JqLmdldEhhc2goXCJTSEEtMzg0XCIsIFwiQVNDSUlcIik7XG5cbiAgfSxcbiAgc2hhNTEyOiBmdW5jdGlvbihzdHIpIHtcbiAgICB2YXIgc2hhT2JqID0gbmV3IGpzU0hBKHN0ciwgXCJBU0NJSVwiKTtcbiAgICByZXR1cm4gc2hhT2JqLmdldEhhc2goXCJTSEEtNTEyXCIsIFwiQVNDSUlcIik7XG4gIH1cbn1cbiIsIm1vZHVsZS5leHBvcnRzID0ge1xuICBjaXBoZXI6IHJlcXVpcmUoJy4vY2lwaGVyJyksXG4gIGhhc2g6IHJlcXVpcmUoJy4vaGFzaCcpLFxuICBjZmI6IHJlcXVpcmUoJy4vY2ZiLmpzJyksXG4gIHB1YmxpY0tleTogcmVxdWlyZSgnLi9wdWJsaWNfa2V5JyksXG4gIHNpZ25hdHVyZTogcmVxdWlyZSgnLi9zaWduYXR1cmUuanMnKSxcbiAgcmFuZG9tOiByZXF1aXJlKCcuL3JhbmRvbS5qcycpLFxuICBwa2NzMTogcmVxdWlyZSgnLi9wa2NzMS5qcycpXG5cbn1cblxudmFyIGNyeXB0byA9IHJlcXVpcmUoJy4vY3J5cHRvLmpzJyk7XG5cbmZvciAodmFyIGkgaW4gY3J5cHRvKVxuICBtb2R1bGUuZXhwb3J0c1tpXSA9IGNyeXB0b1tpXTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbi8qKlxuICogQVNOMSBvYmplY3QgaWRlbnRpZmllcnMgZm9yIGhhc2hlcyAoU2VlIFJGQzQ4ODAgNS4yLjIpXG4gKi9cbmhhc2hfaGVhZGVycyA9IG5ldyBBcnJheSgpO1xuaGFzaF9oZWFkZXJzWzFdID0gWzB4MzAsIDB4MjAsIDB4MzAsIDB4MGMsIDB4MDYsIDB4MDgsIDB4MmEsIDB4ODYsIDB4NDgsIDB4ODYsIDB4ZjcsIDB4MGQsIDB4MDIsIDB4MDUsIDB4MDUsIDB4MDAsIDB4MDQsXG4gICAgMHgxMFxuXTtcbmhhc2hfaGVhZGVyc1szXSA9IFsweDMwLCAweDIxLCAweDMwLCAweDA5LCAweDA2LCAweDA1LCAweDJCLCAweDI0LCAweDAzLCAweDAyLCAweDAxLCAweDA1LCAweDAwLCAweDA0LCAweDE0XTtcbmhhc2hfaGVhZGVyc1syXSA9IFsweDMwLCAweDIxLCAweDMwLCAweDA5LCAweDA2LCAweDA1LCAweDJiLCAweDBlLCAweDAzLCAweDAyLCAweDFhLCAweDA1LCAweDAwLCAweDA0LCAweDE0XTtcbmhhc2hfaGVhZGVyc1s4XSA9IFsweDMwLCAweDMxLCAweDMwLCAweDBkLCAweDA2LCAweDA5LCAweDYwLCAweDg2LCAweDQ4LCAweDAxLCAweDY1LCAweDAzLCAweDA0LCAweDAyLCAweDAxLCAweDA1LCAweDAwLFxuICAgIDB4MDQsIDB4MjBcbl07XG5oYXNoX2hlYWRlcnNbOV0gPSBbMHgzMCwgMHg0MSwgMHgzMCwgMHgwZCwgMHgwNiwgMHgwOSwgMHg2MCwgMHg4NiwgMHg0OCwgMHgwMSwgMHg2NSwgMHgwMywgMHgwNCwgMHgwMiwgMHgwMiwgMHgwNSwgMHgwMCxcbiAgICAweDA0LCAweDMwXG5dO1xuaGFzaF9oZWFkZXJzWzEwXSA9IFsweDMwLCAweDUxLCAweDMwLCAweDBkLCAweDA2LCAweDA5LCAweDYwLCAweDg2LCAweDQ4LCAweDAxLCAweDY1LCAweDAzLCAweDA0LCAweDAyLCAweDAzLCAweDA1LFxuICAgIDB4MDAsIDB4MDQsIDB4NDBcbl07XG5oYXNoX2hlYWRlcnNbMTFdID0gWzB4MzAsIDB4MzEsIDB4MzAsIDB4MGQsIDB4MDYsIDB4MDksIDB4NjAsIDB4ODYsIDB4NDgsIDB4MDEsIDB4NjUsIDB4MDMsIDB4MDQsIDB4MDIsIDB4MDQsIDB4MDUsXG4gICAgMHgwMCwgMHgwNCwgMHgxQ1xuXTtcblxuXG52YXIgY3J5cHRvID0gcmVxdWlyZSgnLi9jcnlwdG8uanMnKSxcbiAgcmFuZG9tID0gcmVxdWlyZSgnLi9yYW5kb20uanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4vcHVibGljX2tleS9qc2JuLmpzJyksXG4gIGhhc2ggPSByZXF1aXJlKCcuL2hhc2gnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGVtZToge1xuICAgIC8qKlxuICAgICAqIGNyZWF0ZSBhIEVNRS1QS0NTMS12MV81IHBhZGRpbmcgKFNlZSBSRkM0ODgwIDEzLjEuMSlcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBtZXNzYWdlIHRvIGJlIHBhZGRlZFxuICAgICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuZ3RoIExlbmd0aCB0byB0aGUgcmVzdWx0aW5nIG1lc3NhZ2VcbiAgICAgKiBAcmV0dXJuIHtTdHJpbmd9IEVNRS1QS0NTMSBwYWRkZWQgbWVzc2FnZVxuICAgICAqL1xuICAgIGVuY29kZTogZnVuY3Rpb24obWVzc2FnZSwgbGVuZ3RoKSB7XG4gICAgICBpZiAobWVzc2FnZS5sZW5ndGggPiBsZW5ndGggLSAxMSlcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDIpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGggLSBtZXNzYWdlLmxlbmd0aCAtIDM7IGkrKykge1xuICAgICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShyYW5kb20uZ2V0UHNldWRvUmFuZG9tKDEsIDI1NSkpO1xuICAgICAgfVxuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCk7XG4gICAgICByZXN1bHQgKz0gbWVzc2FnZTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIGRlY29kZXMgYSBFTUUtUEtDUzEtdjFfNSBwYWRkaW5nIChTZWUgUkZDNDg4MCAxMy4xLjIpXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgRU1FLVBLQ1MxIHBhZGRlZCBtZXNzYWdlXG4gICAgICogQHJldHVybiB7U3RyaW5nfSBkZWNvZGVkIG1lc3NhZ2UgXG4gICAgICovXG4gICAgZGVjb2RlOiBmdW5jdGlvbihtZXNzYWdlLCBsZW4pIHtcbiAgICAgIGlmIChtZXNzYWdlLmxlbmd0aCA8IGxlbilcbiAgICAgICAgbWVzc2FnZSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCkgKyBtZXNzYWdlO1xuICAgICAgaWYgKG1lc3NhZ2UubGVuZ3RoIDwgMTIgfHwgbWVzc2FnZS5jaGFyQ29kZUF0KDApICE9IDAgfHwgbWVzc2FnZS5jaGFyQ29kZUF0KDEpICE9IDIpXG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIHZhciBpID0gMjtcbiAgICAgIHdoaWxlIChtZXNzYWdlLmNoYXJDb2RlQXQoaSkgIT0gMCAmJiBtZXNzYWdlLmxlbmd0aCA+IGkpXG4gICAgICAgIGkrKztcbiAgICAgIHJldHVybiBtZXNzYWdlLnN1YnN0cmluZyhpICsgMSwgbWVzc2FnZS5sZW5ndGgpO1xuICAgIH0sXG4gIH0sXG5cbiAgZW1zYToge1xuXG4gICAgLyoqXG4gICAgICogY3JlYXRlIGEgRU1TQS1QS0NTMS12MV81IHBhZGRpbmcgKFNlZSBSRkM0ODgwIDEzLjEuMylcbiAgICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gSGFzaCBhbGdvcml0aG0gdHlwZSB1c2VkXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBiZSBoYXNoZWRcbiAgICAgKiBAcGFyYW0ge0ludGVnZXJ9IGtleWxlbmd0aCBLZXkgc2l6ZSBvZiB0aGUgcHVibGljIG1waSBpbiBieXRlc1xuICAgICAqIEByZXR1cm5zIHtTdHJpbmd9IEhhc2hjb2RlIHdpdGggcGtjczFwYWRkaW5nIGFzIHN0cmluZ1xuICAgICAqL1xuICAgIGVuY29kZTogZnVuY3Rpb24oYWxnbywgZGF0YSwga2V5bGVuZ3RoKSB7XG4gICAgICB2YXIgZGF0YTIgPSBcIlwiO1xuICAgICAgZGF0YTIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDAwKTtcbiAgICAgIGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHgwMSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IChrZXlsZW5ndGggLSBoYXNoX2hlYWRlcnNbYWxnb10ubGVuZ3RoIC0gMyAtXG4gICAgICAgIGhhc2guZ2V0SGFzaEJ5dGVMZW5ndGgoYWxnbykpOyBpKyspXG5cbiAgICAgICAgZGF0YTIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweGZmKTtcblxuICAgICAgZGF0YTIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDAwKTtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXNoX2hlYWRlcnNbYWxnb10ubGVuZ3RoOyBpKyspXG4gICAgICAgIGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoaGFzaF9oZWFkZXJzW2FsZ29dW2ldKTtcblxuICAgICAgZGF0YTIgKz0gaGFzaC5kaWdlc3QoYWxnbywgZGF0YSk7XG4gICAgICByZXR1cm4gbmV3IEJpZ0ludGVnZXIodXRpbC5oZXhzdHJkdW1wKGRhdGEyKSwgMTYpO1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBleHRyYWN0IHRoZSBoYXNoIG91dCBvZiBhbiBFTVNBLVBLQ1MxLXYxLjUgcGFkZGluZyAoU2VlIFJGQzQ4ODAgMTMuMS4zKSBcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBIYXNoIGluIHBrY3MxIGVuY29kaW5nXG4gICAgICogQHJldHVybnMge1N0cmluZ30gVGhlIGhhc2ggYXMgc3RyaW5nXG4gICAgICovXG4gICAgZGVjb2RlOiBmdW5jdGlvbihhbGdvLCBkYXRhKSB7XG4gICAgICB2YXIgaSA9IDA7XG4gICAgICBpZiAoZGF0YS5jaGFyQ29kZUF0KDApID09IDApIGkrKztcbiAgICAgIGVsc2UgaWYgKGRhdGEuY2hhckNvZGVBdCgwKSAhPSAxKSByZXR1cm4gLTE7XG4gICAgICBlbHNlIGkrKztcblxuICAgICAgd2hpbGUgKGRhdGEuY2hhckNvZGVBdChpKSA9PSAweEZGKSBpKys7XG4gICAgICBpZiAoZGF0YS5jaGFyQ29kZUF0KGkrKykgIT0gMCkgcmV0dXJuIC0xO1xuICAgICAgdmFyIGogPSAwO1xuICAgICAgZm9yIChqID0gMDsgaiA8IGhhc2hfaGVhZGVyc1thbGdvXS5sZW5ndGggJiYgaiArIGkgPCBkYXRhLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChkYXRhLmNoYXJDb2RlQXQoaiArIGkpICE9IGhhc2hfaGVhZGVyc1thbGdvXVtqXSkgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgICAgaSArPSBqO1xuICAgICAgaWYgKGRhdGEuc3Vic3RyaW5nKGkpLmxlbmd0aCA8IGhhc2guZ2V0SGFzaEJ5dGVMZW5ndGgoYWxnbykpIHJldHVybiAtMTtcbiAgICAgIHJldHVybiBkYXRhLnN1YnN0cmluZyhpKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG4vL1xuLy8gQSBEaWdpdGFsIHNpZ25hdHVyZSBhbGdvcml0aG0gaW1wbGVtZW50YXRpb25cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2pzYm4uanMnKSxcbiAgcmFuZG9tID0gcmVxdWlyZSgnLi4vcmFuZG9tLmpzJyksXG4gIGhhc2hNb2R1bGUgPSByZXF1aXJlKCcuLi9oYXNoJyksXG4gIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbmZ1bmN0aW9uIERTQSgpIHtcbiAgLy8gczEgPSAoKGcqKnMpIG1vZCBwKSBtb2QgcVxuICAvLyBzMSA9ICgocyoqLTEpKihzaGEtMShtKSsoczEqeCkgbW9kIHEpXG4gIGZ1bmN0aW9uIHNpZ24oaGFzaGFsZ28sIG0sIGcsIHAsIHEsIHgpIHtcbiAgICAvLyBJZiB0aGUgb3V0cHV0IHNpemUgb2YgdGhlIGNob3NlbiBoYXNoIGlzIGxhcmdlciB0aGFuIHRoZSBudW1iZXIgb2ZcbiAgICAvLyBiaXRzIG9mIHEsIHRoZSBoYXNoIHJlc3VsdCBpcyB0cnVuY2F0ZWQgdG8gZml0IGJ5IHRha2luZyB0aGUgbnVtYmVyXG4gICAgLy8gb2YgbGVmdG1vc3QgYml0cyBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIGJpdHMgb2YgcS4gIFRoaXMgKHBvc3NpYmx5XG4gICAgLy8gdHJ1bmNhdGVkKSBoYXNoIGZ1bmN0aW9uIHJlc3VsdCBpcyB0cmVhdGVkIGFzIGEgbnVtYmVyIGFuZCB1c2VkXG4gICAgLy8gZGlyZWN0bHkgaW4gdGhlIERTQSBzaWduYXR1cmUgYWxnb3JpdGhtLlxuICAgIHZhciBoYXNoZWRfZGF0YSA9IHV0aWwuZ2V0TGVmdE5CaXRzKGhhc2hNb2R1bGUuZGlnZXN0KGhhc2hhbGdvLCBtKSwgcS5iaXRMZW5ndGgoKSk7XG4gICAgdmFyIGhhc2ggPSBuZXcgQmlnSW50ZWdlcih1dGlsLmhleHN0cmR1bXAoaGFzaGVkX2RhdGEpLCAxNik7XG4gICAgdmFyIGsgPSByYW5kb20uZ2V0UmFuZG9tQmlnSW50ZWdlckluUmFuZ2UoQmlnSW50ZWdlci5PTkUuYWRkKEJpZ0ludGVnZXIuT05FKSwgcS5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkpO1xuICAgIHZhciBzMSA9IChnLm1vZFBvdyhrLCBwKSkubW9kKHEpO1xuICAgIHZhciBzMiA9IChrLm1vZEludmVyc2UocSkubXVsdGlwbHkoaGFzaC5hZGQoeC5tdWx0aXBseShzMSkpKSkubW9kKHEpO1xuICAgIHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcbiAgICByZXN1bHRbMF0gPSBzMS50b01QSSgpO1xuICAgIHJlc3VsdFsxXSA9IHMyLnRvTVBJKCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNlbGVjdF9oYXNoX2FsZ29yaXRobShxKSB7XG4gICAgdmFyIHVzZXJzZXR0aW5nID0gb3BlbnBncC5jb25maWcuY29uZmlnLnByZWZlcl9oYXNoX2FsZ29yaXRobTtcbiAgICAvKlxuICAgICAqIDEwMjQtYml0IGtleSwgMTYwLWJpdCBxLCBTSEEtMSwgU0hBLTIyNCwgU0hBLTI1NiwgU0hBLTM4NCwgb3IgU0hBLTUxMiBoYXNoXG4gICAgICogMjA0OC1iaXQga2V5LCAyMjQtYml0IHEsIFNIQS0yMjQsIFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIgaGFzaFxuICAgICAqIDIwNDgtYml0IGtleSwgMjU2LWJpdCBxLCBTSEEtMjU2LCBTSEEtMzg0LCBvciBTSEEtNTEyIGhhc2hcbiAgICAgKiAzMDcyLWJpdCBrZXksIDI1Ni1iaXQgcSwgU0hBLTI1NiwgU0hBLTM4NCwgb3IgU0hBLTUxMiBoYXNoXG4gICAgICovXG4gICAgc3dpdGNoIChNYXRoLnJvdW5kKHEuYml0TGVuZ3RoKCkgLyA4KSkge1xuICAgICAgY2FzZSAyMDpcbiAgICAgICAgLy8gMTAyNCBiaXRcbiAgICAgICAgaWYgKHVzZXJzZXR0aW5nICE9IDIgJiZcbiAgICAgICAgICB1c2Vyc2V0dGluZyA+IDExICYmXG4gICAgICAgICAgdXNlcnNldHRpbmcgIT0gMTAgJiZcbiAgICAgICAgICB1c2Vyc2V0dGluZyA8IDgpXG4gICAgICAgICAgcmV0dXJuIDI7IC8vIHByZWZlciBzaGExXG4gICAgICAgIHJldHVybiB1c2Vyc2V0dGluZztcbiAgICAgIGNhc2UgMjg6XG4gICAgICAgIC8vIDIwNDggYml0XG4gICAgICAgIGlmICh1c2Vyc2V0dGluZyA+IDExICYmXG4gICAgICAgICAgdXNlcnNldHRpbmcgPCA4KVxuICAgICAgICAgIHJldHVybiAxMTtcbiAgICAgICAgcmV0dXJuIHVzZXJzZXR0aW5nO1xuICAgICAgY2FzZSAzMjpcbiAgICAgICAgLy8gNDA5NiBiaXQgLy8gcHJlZmVyIHNoYTIyNFxuICAgICAgICBpZiAodXNlcnNldHRpbmcgPiAxMCAmJlxuICAgICAgICAgIHVzZXJzZXR0aW5nIDwgOClcbiAgICAgICAgICByZXR1cm4gODsgLy8gcHJlZmVyIHNoYTI1NlxuICAgICAgICByZXR1cm4gdXNlcnNldHRpbmc7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB1dGlsLnByaW50X2RlYnVnKFwiRFNBIHNlbGVjdCBoYXNoIGFsZ29yaXRobTogcmV0dXJuaW5nIG51bGwgZm9yIGFuIHVua25vd24gbGVuZ3RoIG9mIHFcIik7XG4gICAgICAgIHJldHVybiBudWxsO1xuXG4gICAgfVxuICB9XG4gIHRoaXMuc2VsZWN0X2hhc2hfYWxnb3JpdGhtID0gc2VsZWN0X2hhc2hfYWxnb3JpdGhtO1xuXG4gIGZ1bmN0aW9uIHZlcmlmeShoYXNoYWxnbywgczEsIHMyLCBtLCBwLCBxLCBnLCB5KSB7XG4gICAgdmFyIGhhc2hlZF9kYXRhID0gdXRpbC5nZXRMZWZ0TkJpdHMoaGFzaE1vZHVsZS5kaWdlc3QoaGFzaGFsZ28sIG0pLCBxLmJpdExlbmd0aCgpKTtcbiAgICB2YXIgaGFzaCA9IG5ldyBCaWdJbnRlZ2VyKHV0aWwuaGV4c3RyZHVtcChoYXNoZWRfZGF0YSksIDE2KTtcbiAgICBpZiAoQmlnSW50ZWdlci5aRVJPLmNvbXBhcmVUbyhzMSkgPiAwIHx8XG4gICAgICBzMS5jb21wYXJlVG8ocSkgPiAwIHx8XG4gICAgICBCaWdJbnRlZ2VyLlpFUk8uY29tcGFyZVRvKHMyKSA+IDAgfHxcbiAgICAgIHMyLmNvbXBhcmVUbyhxKSA+IDApIHtcbiAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJpbnZhbGlkIERTQSBTaWduYXR1cmVcIik7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIHcgPSBzMi5tb2RJbnZlcnNlKHEpO1xuICAgIHZhciB1MSA9IGhhc2gubXVsdGlwbHkodykubW9kKHEpO1xuICAgIHZhciB1MiA9IHMxLm11bHRpcGx5KHcpLm1vZChxKTtcbiAgICByZXR1cm4gZy5tb2RQb3codTEsIHApLm11bHRpcGx5KHkubW9kUG93KHUyLCBwKSkubW9kKHApLm1vZChxKTtcbiAgfVxuXG4gIC8qXG5cdCAqIHVudXNlZCBjb2RlLiBUaGlzIGNhbiBiZSB1c2VkIGFzIGEgc3RhcnQgdG8gd3JpdGUgYSBrZXkgZ2VuZXJhdG9yXG5cdCAqIGZ1bmN0aW9uLlxuXHRcblx0ZnVuY3Rpb24gZ2VuZXJhdGVLZXkoYml0Y291bnQpIHtcblx0ICAgIHZhciBxaSA9IG5ldyBCaWdJbnRlZ2VyKGJpdGNvdW50LCBwcmltZUNlbnRlcmllKTtcblx0ICAgIHZhciBwaSA9IGdlbmVyYXRlUChxLCA1MTIpO1xuXHQgICAgdmFyIGdpID0gZ2VuZXJhdGVHKHAsIHEsIGJpdGNvdW50KTtcblx0ICAgIHZhciB4aTtcblx0ICAgIGRvIHtcblx0ICAgICAgICB4aSA9IG5ldyBCaWdJbnRlZ2VyKHEuYml0Q291bnQoKSwgcmFuZCk7XG5cdCAgICB9IHdoaWxlICh4LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pICE9IDEgJiYgeC5jb21wYXJlVG8ocSkgIT0gLTEpO1xuXHQgICAgdmFyIHlpID0gZy5tb2RQb3coeCwgcCk7XG5cdCAgICByZXR1cm4ge3g6IHhpLCBxOiBxaSwgcDogcGksIGc6IGdpLCB5OiB5aX07XG5cdH1cblxuXHRmdW5jdGlvbiBnZW5lcmF0ZVAocSwgYml0bGVuZ3RoLCByYW5kb21mbikge1xuXHQgICAgaWYgKGJpdGxlbmd0aCAlIDY0ICE9IDApIHtcblx0ICAgIFx0cmV0dXJuIGZhbHNlO1xuXHQgICAgfVxuXHQgICAgdmFyIHBUZW1wO1xuXHQgICAgdmFyIHBUZW1wMjtcblx0ICAgIGRvIHtcblx0ICAgICAgICBwVGVtcCA9IHJhbmRvbWZuKGJpdGNvdW50LCB0cnVlKTtcblx0ICAgICAgICBwVGVtcDIgPSBwVGVtcC5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSk7XG5cdCAgICAgICAgcFRlbXAgPSBwVGVtcC5zdWJ0cmFjdChwVGVtcDIucmVtYWluZGVyKHEpKTtcblx0ICAgIH0gd2hpbGUgKCFwVGVtcC5pc1Byb2JhYmxlUHJpbWUocHJpbWVDZW50ZXJpZSkgfHwgcFRlbXAuYml0TGVuZ3RoKCkgIT0gbCk7XG5cdCAgICByZXR1cm4gcFRlbXA7XG5cdH1cblx0XG5cdGZ1bmN0aW9uIGdlbmVyYXRlRyhwLCBxLCBiaXRsZW5ndGgsIHJhbmRvbWZuKSB7XG5cdCAgICB2YXIgYXV4ID0gcC5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSk7XG5cdCAgICB2YXIgcG93ID0gYXV4LmRpdmlkZShxKTtcblx0ICAgIHZhciBnVGVtcDtcblx0ICAgIGRvIHtcblx0ICAgICAgICBnVGVtcCA9IHJhbmRvbWZuKGJpdGxlbmd0aCk7XG5cdCAgICB9IHdoaWxlIChnVGVtcC5jb21wYXJlVG8oYXV4KSAhPSAtMSAmJiBnVGVtcC5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpICE9IDEpO1xuXHQgICAgcmV0dXJuIGdUZW1wLm1vZFBvdyhwb3csIHApO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2VuZXJhdGVLKHEsIGJpdGxlbmd0aCwgcmFuZG9tZm4pIHtcblx0ICAgIHZhciB0ZW1wSztcblx0ICAgIGRvIHtcblx0ICAgICAgICB0ZW1wSyA9IHJhbmRvbWZuKGJpdGxlbmd0aCwgZmFsc2UpO1xuXHQgICAgfSB3aGlsZSAodGVtcEsuY29tcGFyZVRvKHEpICE9IC0xICYmIHRlbXBLLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pICE9IDEpO1xuXHQgICAgcmV0dXJuIHRlbXBLO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2VuZXJhdGVSKHEscCkge1xuXHQgICAgayA9IGdlbmVyYXRlSyhxKTtcblx0ICAgIHZhciByID0gZy5tb2RQb3coaywgcCkubW9kKHEpO1xuXHQgICAgcmV0dXJuIHI7XG5cdH1cblxuXHRmdW5jdGlvbiBnZW5lcmF0ZVMoaGFzaGZuLGsscixtLHEseCkge1xuICAgICAgICB2YXIgaGFzaCA9IGhhc2hmbihtKTtcbiAgICAgICAgcyA9IChrLm1vZEludmVyc2UocSkubXVsdGlwbHkoaGFzaC5hZGQoeC5tdWx0aXBseShyKSkpKS5tb2QocSk7XG5cdCAgICByZXR1cm4gcztcblx0fSAqL1xuICB0aGlzLnNpZ24gPSBzaWduO1xuICB0aGlzLnZlcmlmeSA9IHZlcmlmeTtcbiAgLy8gdGhpcy5nZW5lcmF0ZSA9IGdlbmVyYXRlS2V5O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IERTQTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG4vL1xuLy8gRWxHYW1hbCBpbXBsZW1lbnRhdGlvblxuXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4vanNibi5qcycpLFxuICByYW5kb20gPSByZXF1aXJlKCcuLi9yYW5kb20uanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuZnVuY3Rpb24gRWxnYW1hbCgpIHtcblxuICBmdW5jdGlvbiBlbmNyeXB0KG0sIGcsIHAsIHkpIHtcbiAgICAvLyAgY2hvb3NlIGsgaW4gezIsLi4uLHAtMn1cbiAgICB2YXIgdHdvID0gQmlnSW50ZWdlci5PTkUuYWRkKEJpZ0ludGVnZXIuT05FKTtcbiAgICB2YXIgcE1pbnVzMiA9IHAuc3VidHJhY3QodHdvKTtcbiAgICB2YXIgayA9IHJhbmRvbS5nZXRSYW5kb21CaWdJbnRlZ2VySW5SYW5nZSh0d28sIHBNaW51czIpO1xuICAgIGsgPSBrLm1vZChwTWludXMyKS5hZGQoQmlnSW50ZWdlci5PTkUpO1xuICAgIHZhciBjID0gW107XG4gICAgY1swXSA9IGcubW9kUG93KGssIHApO1xuICAgIGNbMV0gPSB5Lm1vZFBvdyhrLCBwKS5tdWx0aXBseShtKS5tb2QocCk7XG4gICAgcmV0dXJuIGM7XG4gIH1cblxuICBmdW5jdGlvbiBkZWNyeXB0KGMxLCBjMiwgcCwgeCkge1xuICAgIHV0aWwucHJpbnRfZGVidWcoXCJFbGdhbWFsIERlY3J5cHQ6XFxuYzE6XCIgKyB1dGlsLmhleHN0cmR1bXAoYzEudG9NUEkoKSkgKyBcIlxcblwiICtcbiAgICAgIFwiYzI6XCIgKyB1dGlsLmhleHN0cmR1bXAoYzIudG9NUEkoKSkgKyBcIlxcblwiICtcbiAgICAgIFwicDpcIiArIHV0aWwuaGV4c3RyZHVtcChwLnRvTVBJKCkpICsgXCJcXG5cIiArXG4gICAgICBcIng6XCIgKyB1dGlsLmhleHN0cmR1bXAoeC50b01QSSgpKSk7XG4gICAgcmV0dXJuIChjMS5tb2RQb3coeCwgcCkubW9kSW52ZXJzZShwKSkubXVsdGlwbHkoYzIpLm1vZChwKTtcbiAgICAvL3ZhciBjID0gYzEucG93KHgpLm1vZEludmVyc2UocCk7IC8vIGMwXi1hIG1vZCBwXG4gICAgLy9yZXR1cm4gYy5tdWx0aXBseShjMikubW9kKHApO1xuICB9XG5cbiAgLy8gc2lnbmluZyBhbmQgc2lnbmF0dXJlIHZlcmlmaWNhdGlvbiB1c2luZyBFbGdhbWFsIGlzIG5vdCByZXF1aXJlZCBieSBPcGVuUEdQLlxuICB0aGlzLmVuY3J5cHQgPSBlbmNyeXB0O1xuICB0aGlzLmRlY3J5cHQgPSBkZWNyeXB0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEVsZ2FtYWw7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcbiAgcnNhOiByZXF1aXJlKCcuL3JzYS5qcycpLFxuICBlbGdhbWFsOiByZXF1aXJlKCcuL2VsZ2FtYWwuanMnKSxcbiAgZHNhOiByZXF1aXJlKCcuL2RzYS5qcycpXG59XG4iLCIvKlxuICogQ29weXJpZ2h0IChjKSAyMDAzLTIwMDUgIFRvbSBXdSAodGp3QGNzLlN0YW5mb3JkLkVEVSkgXG4gKiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSCBcbiAqIFxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nXG4gKiBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbiAqIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuICogd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuICogZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvXG4gKiBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG9cbiAqIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMtSVNcIiBBTkQgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgXG4gKiBFWFBSRVNTLCBJTVBMSUVEIE9SIE9USEVSV0lTRSwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiwgQU5ZIFxuICogV0FSUkFOVFkgT0YgTUVSQ0hBTlRBQklMSVRZIE9SIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgXG4gKlxuICogSU4gTk8gRVZFTlQgU0hBTEwgVE9NIFdVIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIElOQ0lERU5UQUwsXG4gKiBJTkRJUkVDVCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT0YgQU5ZIEtJTkQsIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVJcbiAqIFJFU1VMVElORyBGUk9NIExPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgT1IgTk9UIEFEVklTRUQgT0ZcbiAqIFRIRSBQT1NTSUJJTElUWSBPRiBEQU1BR0UsIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgQVJJU0lORyBPVVRcbiAqIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SIFBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXG4gKlxuICogSW4gYWRkaXRpb24sIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uIGFwcGxpZXM6XG4gKlxuICogQWxsIHJlZGlzdHJpYnV0aW9ucyBtdXN0IHJldGFpbiBhbiBpbnRhY3QgY29weSBvZiB0aGlzIGNvcHlyaWdodCBub3RpY2VcbiAqIGFuZCBkaXNjbGFpbWVyLlxuICovXG5cblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbi8vIEJhc2ljIEphdmFTY3JpcHQgQk4gbGlicmFyeSAtIHN1YnNldCB1c2VmdWwgZm9yIFJTQSBlbmNyeXB0aW9uLlxuXG4vLyBCaXRzIHBlciBkaWdpdFxudmFyIGRiaXRzO1xuXG4vLyBKYXZhU2NyaXB0IGVuZ2luZSBhbmFseXNpc1xudmFyIGNhbmFyeSA9IDB4ZGVhZGJlZWZjYWZlO1xudmFyIGpfbG0gPSAoKGNhbmFyeSAmIDB4ZmZmZmZmKSA9PSAweGVmY2FmZSk7XG5cbi8vIChwdWJsaWMpIENvbnN0cnVjdG9yXG5cbmZ1bmN0aW9uIEJpZ0ludGVnZXIoYSwgYiwgYykge1xuICBpZiAoYSAhPSBudWxsKVxuICAgIGlmIChcIm51bWJlclwiID09IHR5cGVvZiBhKSB0aGlzLmZyb21OdW1iZXIoYSwgYiwgYyk7XG4gICAgZWxzZSBpZiAoYiA9PSBudWxsICYmIFwic3RyaW5nXCIgIT0gdHlwZW9mIGEpIHRoaXMuZnJvbVN0cmluZyhhLCAyNTYpO1xuICBlbHNlIHRoaXMuZnJvbVN0cmluZyhhLCBiKTtcbn1cblxuLy8gcmV0dXJuIG5ldywgdW5zZXQgQmlnSW50ZWdlclxuXG5mdW5jdGlvbiBuYmkoKSB7XG4gIHJldHVybiBuZXcgQmlnSW50ZWdlcihudWxsKTtcbn1cblxuLy8gYW06IENvbXB1dGUgd19qICs9ICh4KnRoaXNfaSksIHByb3BhZ2F0ZSBjYXJyaWVzLFxuLy8gYyBpcyBpbml0aWFsIGNhcnJ5LCByZXR1cm5zIGZpbmFsIGNhcnJ5LlxuLy8gYyA8IDMqZHZhbHVlLCB4IDwgMipkdmFsdWUsIHRoaXNfaSA8IGR2YWx1ZVxuLy8gV2UgbmVlZCB0byBzZWxlY3QgdGhlIGZhc3Rlc3Qgb25lIHRoYXQgd29ya3MgaW4gdGhpcyBlbnZpcm9ubWVudC5cblxuLy8gYW0xOiB1c2UgYSBzaW5nbGUgbXVsdCBhbmQgZGl2aWRlIHRvIGdldCB0aGUgaGlnaCBiaXRzLFxuLy8gbWF4IGRpZ2l0IGJpdHMgc2hvdWxkIGJlIDI2IGJlY2F1c2Vcbi8vIG1heCBpbnRlcm5hbCB2YWx1ZSA9IDIqZHZhbHVlXjItMipkdmFsdWUgKDwgMl41MylcblxuZnVuY3Rpb24gYW0xKGksIHgsIHcsIGosIGMsIG4pIHtcbiAgd2hpbGUgKC0tbiA+PSAwKSB7XG4gICAgdmFyIHYgPSB4ICogdGhpc1tpKytdICsgd1tqXSArIGM7XG4gICAgYyA9IE1hdGguZmxvb3IodiAvIDB4NDAwMDAwMCk7XG4gICAgd1tqKytdID0gdiAmIDB4M2ZmZmZmZjtcbiAgfVxuICByZXR1cm4gYztcbn1cbi8vIGFtMiBhdm9pZHMgYSBiaWcgbXVsdC1hbmQtZXh0cmFjdCBjb21wbGV0ZWx5LlxuLy8gTWF4IGRpZ2l0IGJpdHMgc2hvdWxkIGJlIDw9IDMwIGJlY2F1c2Ugd2UgZG8gYml0d2lzZSBvcHNcbi8vIG9uIHZhbHVlcyB1cCB0byAyKmhkdmFsdWVeMi1oZHZhbHVlLTEgKDwgMl4zMSlcblxuZnVuY3Rpb24gYW0yKGksIHgsIHcsIGosIGMsIG4pIHtcbiAgdmFyIHhsID0geCAmIDB4N2ZmZixcbiAgICB4aCA9IHggPj4gMTU7XG4gIHdoaWxlICgtLW4gPj0gMCkge1xuICAgIHZhciBsID0gdGhpc1tpXSAmIDB4N2ZmZjtcbiAgICB2YXIgaCA9IHRoaXNbaSsrXSA+PiAxNTtcbiAgICB2YXIgbSA9IHhoICogbCArIGggKiB4bDtcbiAgICBsID0geGwgKiBsICsgKChtICYgMHg3ZmZmKSA8PCAxNSkgKyB3W2pdICsgKGMgJiAweDNmZmZmZmZmKTtcbiAgICBjID0gKGwgPj4+IDMwKSArIChtID4+PiAxNSkgKyB4aCAqIGggKyAoYyA+Pj4gMzApO1xuICAgIHdbaisrXSA9IGwgJiAweDNmZmZmZmZmO1xuICB9XG4gIHJldHVybiBjO1xufVxuLy8gQWx0ZXJuYXRlbHksIHNldCBtYXggZGlnaXQgYml0cyB0byAyOCBzaW5jZSBzb21lXG4vLyBicm93c2VycyBzbG93IGRvd24gd2hlbiBkZWFsaW5nIHdpdGggMzItYml0IG51bWJlcnMuXG5cbmZ1bmN0aW9uIGFtMyhpLCB4LCB3LCBqLCBjLCBuKSB7XG4gIHZhciB4bCA9IHggJiAweDNmZmYsXG4gICAgeGggPSB4ID4+IDE0O1xuICB3aGlsZSAoLS1uID49IDApIHtcbiAgICB2YXIgbCA9IHRoaXNbaV0gJiAweDNmZmY7XG4gICAgdmFyIGggPSB0aGlzW2krK10gPj4gMTQ7XG4gICAgdmFyIG0gPSB4aCAqIGwgKyBoICogeGw7XG4gICAgbCA9IHhsICogbCArICgobSAmIDB4M2ZmZikgPDwgMTQpICsgd1tqXSArIGM7XG4gICAgYyA9IChsID4+IDI4KSArIChtID4+IDE0KSArIHhoICogaDtcbiAgICB3W2orK10gPSBsICYgMHhmZmZmZmZmO1xuICB9XG4gIHJldHVybiBjO1xufVxuLyppZihqX2xtICYmIChuYXZpZ2F0b3IgIT0gdW5kZWZpbmVkICYmIFxuXHRuYXZpZ2F0b3IuYXBwTmFtZSA9PSBcIk1pY3Jvc29mdCBJbnRlcm5ldCBFeHBsb3JlclwiKSkge1xuICBCaWdJbnRlZ2VyLnByb3RvdHlwZS5hbSA9IGFtMjtcbiAgZGJpdHMgPSAzMDtcbn1cbmVsc2UgaWYoal9sbSAmJiAobmF2aWdhdG9yICE9IHVuZGVmaW5lZCAmJiBuYXZpZ2F0b3IuYXBwTmFtZSAhPSBcIk5ldHNjYXBlXCIpKSB7Ki9cbkJpZ0ludGVnZXIucHJvdG90eXBlLmFtID0gYW0xO1xuZGJpdHMgPSAyNjtcbi8qfVxuZWxzZSB7IC8vIE1vemlsbGEvTmV0c2NhcGUgc2VlbXMgdG8gcHJlZmVyIGFtM1xuICBCaWdJbnRlZ2VyLnByb3RvdHlwZS5hbSA9IGFtMztcbiAgZGJpdHMgPSAyODtcbn0qL1xuXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5EQiA9IGRiaXRzO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuRE0gPSAoKDEgPDwgZGJpdHMpIC0gMSk7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5EViA9ICgxIDw8IGRiaXRzKTtcblxudmFyIEJJX0ZQID0gNTI7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5GViA9IE1hdGgucG93KDIsIEJJX0ZQKTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLkYxID0gQklfRlAgLSBkYml0cztcbkJpZ0ludGVnZXIucHJvdG90eXBlLkYyID0gMiAqIGRiaXRzIC0gQklfRlA7XG5cbi8vIERpZ2l0IGNvbnZlcnNpb25zXG52YXIgQklfUk0gPSBcIjAxMjM0NTY3ODlhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elwiO1xudmFyIEJJX1JDID0gbmV3IEFycmF5KCk7XG52YXIgcnIsIHZ2O1xucnIgPSBcIjBcIi5jaGFyQ29kZUF0KDApO1xuZm9yICh2diA9IDA7IHZ2IDw9IDk7ICsrdnYpIEJJX1JDW3JyKytdID0gdnY7XG5yciA9IFwiYVwiLmNoYXJDb2RlQXQoMCk7XG5mb3IgKHZ2ID0gMTA7IHZ2IDwgMzY7ICsrdnYpIEJJX1JDW3JyKytdID0gdnY7XG5yciA9IFwiQVwiLmNoYXJDb2RlQXQoMCk7XG5mb3IgKHZ2ID0gMTA7IHZ2IDwgMzY7ICsrdnYpIEJJX1JDW3JyKytdID0gdnY7XG5cbmZ1bmN0aW9uIGludDJjaGFyKG4pIHtcbiAgcmV0dXJuIEJJX1JNLmNoYXJBdChuKTtcbn1cblxuZnVuY3Rpb24gaW50QXQocywgaSkge1xuICB2YXIgYyA9IEJJX1JDW3MuY2hhckNvZGVBdChpKV07XG4gIHJldHVybiAoYyA9PSBudWxsKSA/IC0xIDogYztcbn1cblxuLy8gKHByb3RlY3RlZCkgY29weSB0aGlzIHRvIHJcblxuZnVuY3Rpb24gYm5wQ29weVRvKHIpIHtcbiAgZm9yICh2YXIgaSA9IHRoaXMudCAtIDE7IGkgPj0gMDsgLS1pKSByW2ldID0gdGhpc1tpXTtcbiAgci50ID0gdGhpcy50O1xuICByLnMgPSB0aGlzLnM7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHNldCBmcm9tIGludGVnZXIgdmFsdWUgeCwgLURWIDw9IHggPCBEVlxuXG5mdW5jdGlvbiBibnBGcm9tSW50KHgpIHtcbiAgdGhpcy50ID0gMTtcbiAgdGhpcy5zID0gKHggPCAwKSA/IC0xIDogMDtcbiAgaWYgKHggPiAwKSB0aGlzWzBdID0geDtcbiAgZWxzZSBpZiAoeCA8IC0xKSB0aGlzWzBdID0geCArIERWO1xuICBlbHNlIHRoaXMudCA9IDA7XG59XG5cbi8vIHJldHVybiBiaWdpbnQgaW5pdGlhbGl6ZWQgdG8gdmFsdWVcblxuZnVuY3Rpb24gbmJ2KGkpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgci5mcm9tSW50KGkpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHByb3RlY3RlZCkgc2V0IGZyb20gc3RyaW5nIGFuZCByYWRpeFxuXG5mdW5jdGlvbiBibnBGcm9tU3RyaW5nKHMsIGIpIHtcbiAgdmFyIGs7XG4gIGlmIChiID09IDE2KSBrID0gNDtcbiAgZWxzZSBpZiAoYiA9PSA4KSBrID0gMztcbiAgZWxzZSBpZiAoYiA9PSAyNTYpIGsgPSA4OyAvLyBieXRlIGFycmF5XG4gIGVsc2UgaWYgKGIgPT0gMikgayA9IDE7XG4gIGVsc2UgaWYgKGIgPT0gMzIpIGsgPSA1O1xuICBlbHNlIGlmIChiID09IDQpIGsgPSAyO1xuICBlbHNlIHtcbiAgICB0aGlzLmZyb21SYWRpeChzLCBiKTtcbiAgICByZXR1cm47XG4gIH1cbiAgdGhpcy50ID0gMDtcbiAgdGhpcy5zID0gMDtcbiAgdmFyIGkgPSBzLmxlbmd0aCxcbiAgICBtaSA9IGZhbHNlLFxuICAgIHNoID0gMDtcbiAgd2hpbGUgKC0taSA+PSAwKSB7XG4gICAgdmFyIHggPSAoayA9PSA4KSA/IHNbaV0gJiAweGZmIDogaW50QXQocywgaSk7XG4gICAgaWYgKHggPCAwKSB7XG4gICAgICBpZiAocy5jaGFyQXQoaSkgPT0gXCItXCIpIG1pID0gdHJ1ZTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBtaSA9IGZhbHNlO1xuICAgIGlmIChzaCA9PSAwKVxuICAgICAgdGhpc1t0aGlzLnQrK10gPSB4O1xuICAgIGVsc2UgaWYgKHNoICsgayA+IHRoaXMuREIpIHtcbiAgICAgIHRoaXNbdGhpcy50IC0gMV0gfD0gKHggJiAoKDEgPDwgKHRoaXMuREIgLSBzaCkpIC0gMSkpIDw8IHNoO1xuICAgICAgdGhpc1t0aGlzLnQrK10gPSAoeCA+PiAodGhpcy5EQiAtIHNoKSk7XG4gICAgfSBlbHNlXG4gICAgICB0aGlzW3RoaXMudCAtIDFdIHw9IHggPDwgc2g7XG4gICAgc2ggKz0gaztcbiAgICBpZiAoc2ggPj0gdGhpcy5EQikgc2ggLT0gdGhpcy5EQjtcbiAgfVxuICBpZiAoayA9PSA4ICYmIChzWzBdICYgMHg4MCkgIT0gMCkge1xuICAgIHRoaXMucyA9IC0xO1xuICAgIGlmIChzaCA+IDApIHRoaXNbdGhpcy50IC0gMV0gfD0gKCgxIDw8ICh0aGlzLkRCIC0gc2gpKSAtIDEpIDw8IHNoO1xuICB9XG4gIHRoaXMuY2xhbXAoKTtcbiAgaWYgKG1pKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8odGhpcywgdGhpcyk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNsYW1wIG9mZiBleGNlc3MgaGlnaCB3b3Jkc1xuXG5mdW5jdGlvbiBibnBDbGFtcCgpIHtcbiAgdmFyIGMgPSB0aGlzLnMgJiB0aGlzLkRNO1xuICB3aGlsZSAodGhpcy50ID4gMCAmJiB0aGlzW3RoaXMudCAtIDFdID09IGMpLS10aGlzLnQ7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiBzdHJpbmcgcmVwcmVzZW50YXRpb24gaW4gZ2l2ZW4gcmFkaXhcblxuZnVuY3Rpb24gYm5Ub1N0cmluZyhiKSB7XG4gIGlmICh0aGlzLnMgPCAwKSByZXR1cm4gXCItXCIgKyB0aGlzLm5lZ2F0ZSgpLnRvU3RyaW5nKGIpO1xuICB2YXIgaztcbiAgaWYgKGIgPT0gMTYpIGsgPSA0O1xuICBlbHNlIGlmIChiID09IDgpIGsgPSAzO1xuICBlbHNlIGlmIChiID09IDIpIGsgPSAxO1xuICBlbHNlIGlmIChiID09IDMyKSBrID0gNTtcbiAgZWxzZSBpZiAoYiA9PSA0KSBrID0gMjtcbiAgZWxzZSByZXR1cm4gdGhpcy50b1JhZGl4KGIpO1xuICB2YXIga20gPSAoMSA8PCBrKSAtIDEsXG4gICAgZCwgbSA9IGZhbHNlLFxuICAgIHIgPSBcIlwiLFxuICAgIGkgPSB0aGlzLnQ7XG4gIHZhciBwID0gdGhpcy5EQiAtIChpICogdGhpcy5EQikgJSBrO1xuICBpZiAoaS0tID4gMCkge1xuICAgIGlmIChwIDwgdGhpcy5EQiAmJiAoZCA9IHRoaXNbaV0gPj4gcCkgPiAwKSB7XG4gICAgICBtID0gdHJ1ZTtcbiAgICAgIHIgPSBpbnQyY2hhcihkKTtcbiAgICB9XG4gICAgd2hpbGUgKGkgPj0gMCkge1xuICAgICAgaWYgKHAgPCBrKSB7XG4gICAgICAgIGQgPSAodGhpc1tpXSAmICgoMSA8PCBwKSAtIDEpKSA8PCAoayAtIHApO1xuICAgICAgICBkIHw9IHRoaXNbLS1pXSA+PiAocCArPSB0aGlzLkRCIC0gayk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkID0gKHRoaXNbaV0gPj4gKHAgLT0gaykpICYga207XG4gICAgICAgIGlmIChwIDw9IDApIHtcbiAgICAgICAgICBwICs9IHRoaXMuREI7XG4gICAgICAgICAgLS1pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZCA+IDApIG0gPSB0cnVlO1xuICAgICAgaWYgKG0pIHIgKz0gaW50MmNoYXIoZCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBtID8gciA6IFwiMFwiO1xufVxuXG4vLyAocHVibGljKSAtdGhpc1xuXG5mdW5jdGlvbiBibk5lZ2F0ZSgpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHRoaXMsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgfHRoaXN8XG5cbmZ1bmN0aW9uIGJuQWJzKCkge1xuICByZXR1cm4gKHRoaXMucyA8IDApID8gdGhpcy5uZWdhdGUoKSA6IHRoaXM7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiArIGlmIHRoaXMgPiBhLCAtIGlmIHRoaXMgPCBhLCAwIGlmIGVxdWFsXG5cbmZ1bmN0aW9uIGJuQ29tcGFyZVRvKGEpIHtcbiAgdmFyIHIgPSB0aGlzLnMgLSBhLnM7XG4gIGlmIChyICE9IDApIHJldHVybiByO1xuICB2YXIgaSA9IHRoaXMudDtcbiAgciA9IGkgLSBhLnQ7XG4gIGlmIChyICE9IDApIHJldHVybiByO1xuICB3aGlsZSAoLS1pID49IDApIGlmICgociA9IHRoaXNbaV0gLSBhW2ldKSAhPSAwKSByZXR1cm4gcjtcbiAgcmV0dXJuIDA7XG59XG5cbi8vIHJldHVybnMgYml0IGxlbmd0aCBvZiB0aGUgaW50ZWdlciB4XG5cbmZ1bmN0aW9uIG5iaXRzKHgpIHtcbiAgdmFyIHIgPSAxLFxuICAgIHQ7XG4gIGlmICgodCA9IHggPj4+IDE2KSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgciArPSAxNjtcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDgpICE9IDApIHtcbiAgICB4ID0gdDtcbiAgICByICs9IDg7XG4gIH1cbiAgaWYgKCh0ID0geCA+PiA0KSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgciArPSA0O1xuICB9XG4gIGlmICgodCA9IHggPj4gMikgIT0gMCkge1xuICAgIHggPSB0O1xuICAgIHIgKz0gMjtcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDEpICE9IDApIHtcbiAgICB4ID0gdDtcbiAgICByICs9IDE7XG4gIH1cbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiB0aGUgbnVtYmVyIG9mIGJpdHMgaW4gXCJ0aGlzXCJcblxuZnVuY3Rpb24gYm5CaXRMZW5ndGgoKSB7XG4gIGlmICh0aGlzLnQgPD0gMCkgcmV0dXJuIDA7XG4gIHJldHVybiB0aGlzLkRCICogKHRoaXMudCAtIDEpICsgbmJpdHModGhpc1t0aGlzLnQgLSAxXSBeICh0aGlzLnMgJiB0aGlzLkRNKSk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIDw8IG4qREJcblxuZnVuY3Rpb24gYm5wRExTaGlmdFRvKG4sIHIpIHtcbiAgdmFyIGk7XG4gIGZvciAoaSA9IHRoaXMudCAtIDE7IGkgPj0gMDsgLS1pKSByW2kgKyBuXSA9IHRoaXNbaV07XG4gIGZvciAoaSA9IG4gLSAxOyBpID49IDA7IC0taSkgcltpXSA9IDA7XG4gIHIudCA9IHRoaXMudCArIG47XG4gIHIucyA9IHRoaXMucztcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXMgPj4gbipEQlxuXG5mdW5jdGlvbiBibnBEUlNoaWZ0VG8obiwgcikge1xuICBmb3IgKHZhciBpID0gbjsgaSA8IHRoaXMudDsgKytpKSByW2kgLSBuXSA9IHRoaXNbaV07XG4gIHIudCA9IE1hdGgubWF4KHRoaXMudCAtIG4sIDApO1xuICByLnMgPSB0aGlzLnM7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIDw8IG5cblxuZnVuY3Rpb24gYm5wTFNoaWZ0VG8obiwgcikge1xuICB2YXIgYnMgPSBuICUgdGhpcy5EQjtcbiAgdmFyIGNicyA9IHRoaXMuREIgLSBicztcbiAgdmFyIGJtID0gKDEgPDwgY2JzKSAtIDE7XG4gIHZhciBkcyA9IE1hdGguZmxvb3IobiAvIHRoaXMuREIpLFxuICAgIGMgPSAodGhpcy5zIDw8IGJzKSAmIHRoaXMuRE0sXG4gICAgaTtcbiAgZm9yIChpID0gdGhpcy50IC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICByW2kgKyBkcyArIDFdID0gKHRoaXNbaV0gPj4gY2JzKSB8IGM7XG4gICAgYyA9ICh0aGlzW2ldICYgYm0pIDw8IGJzO1xuICB9XG4gIGZvciAoaSA9IGRzIC0gMTsgaSA+PSAwOyAtLWkpIHJbaV0gPSAwO1xuICByW2RzXSA9IGM7XG4gIHIudCA9IHRoaXMudCArIGRzICsgMTtcbiAgci5zID0gdGhpcy5zO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzID4+IG5cblxuZnVuY3Rpb24gYm5wUlNoaWZ0VG8obiwgcikge1xuICByLnMgPSB0aGlzLnM7XG4gIHZhciBkcyA9IE1hdGguZmxvb3IobiAvIHRoaXMuREIpO1xuICBpZiAoZHMgPj0gdGhpcy50KSB7XG4gICAgci50ID0gMDtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGJzID0gbiAlIHRoaXMuREI7XG4gIHZhciBjYnMgPSB0aGlzLkRCIC0gYnM7XG4gIHZhciBibSA9ICgxIDw8IGJzKSAtIDE7XG4gIHJbMF0gPSB0aGlzW2RzXSA+PiBicztcbiAgZm9yICh2YXIgaSA9IGRzICsgMTsgaSA8IHRoaXMudDsgKytpKSB7XG4gICAgcltpIC0gZHMgLSAxXSB8PSAodGhpc1tpXSAmIGJtKSA8PCBjYnM7XG4gICAgcltpIC0gZHNdID0gdGhpc1tpXSA+PiBicztcbiAgfVxuICBpZiAoYnMgPiAwKSByW3RoaXMudCAtIGRzIC0gMV0gfD0gKHRoaXMucyAmIGJtKSA8PCBjYnM7XG4gIHIudCA9IHRoaXMudCAtIGRzO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIC0gYVxuXG5mdW5jdGlvbiBibnBTdWJUbyhhLCByKSB7XG4gIHZhciBpID0gMCxcbiAgICBjID0gMCxcbiAgICBtID0gTWF0aC5taW4oYS50LCB0aGlzLnQpO1xuICB3aGlsZSAoaSA8IG0pIHtcbiAgICBjICs9IHRoaXNbaV0gLSBhW2ldO1xuICAgIHJbaSsrXSA9IGMgJiB0aGlzLkRNO1xuICAgIGMgPj49IHRoaXMuREI7XG4gIH1cbiAgaWYgKGEudCA8IHRoaXMudCkge1xuICAgIGMgLT0gYS5zO1xuICAgIHdoaWxlIChpIDwgdGhpcy50KSB7XG4gICAgICBjICs9IHRoaXNbaV07XG4gICAgICByW2krK10gPSBjICYgdGhpcy5ETTtcbiAgICAgIGMgPj49IHRoaXMuREI7XG4gICAgfVxuICAgIGMgKz0gdGhpcy5zO1xuICB9IGVsc2Uge1xuICAgIGMgKz0gdGhpcy5zO1xuICAgIHdoaWxlIChpIDwgYS50KSB7XG4gICAgICBjIC09IGFbaV07XG4gICAgICByW2krK10gPSBjICYgdGhpcy5ETTtcbiAgICAgIGMgPj49IHRoaXMuREI7XG4gICAgfVxuICAgIGMgLT0gYS5zO1xuICB9XG4gIHIucyA9IChjIDwgMCkgPyAtMSA6IDA7XG4gIGlmIChjIDwgLTEpIHJbaSsrXSA9IHRoaXMuRFYgKyBjO1xuICBlbHNlIGlmIChjID4gMCkgcltpKytdID0gYztcbiAgci50ID0gaTtcbiAgci5jbGFtcCgpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyAqIGEsIHIgIT0gdGhpcyxhIChIQUMgMTQuMTIpXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5cbmZ1bmN0aW9uIGJucE11bHRpcGx5VG8oYSwgcikge1xuICB2YXIgeCA9IHRoaXMuYWJzKCksXG4gICAgeSA9IGEuYWJzKCk7XG4gIHZhciBpID0geC50O1xuICByLnQgPSBpICsgeS50O1xuICB3aGlsZSAoLS1pID49IDApIHJbaV0gPSAwO1xuICBmb3IgKGkgPSAwOyBpIDwgeS50OyArK2kpIHJbaSArIHgudF0gPSB4LmFtKDAsIHlbaV0sIHIsIGksIDAsIHgudCk7XG4gIHIucyA9IDA7XG4gIHIuY2xhbXAoKTtcbiAgaWYgKHRoaXMucyAhPSBhLnMpIEJpZ0ludGVnZXIuWkVSTy5zdWJUbyhyLCByKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXNeMiwgciAhPSB0aGlzIChIQUMgMTQuMTYpXG5cbmZ1bmN0aW9uIGJucFNxdWFyZVRvKHIpIHtcbiAgdmFyIHggPSB0aGlzLmFicygpO1xuICB2YXIgaSA9IHIudCA9IDIgKiB4LnQ7XG4gIHdoaWxlICgtLWkgPj0gMCkgcltpXSA9IDA7XG4gIGZvciAoaSA9IDA7IGkgPCB4LnQgLSAxOyArK2kpIHtcbiAgICB2YXIgYyA9IHguYW0oaSwgeFtpXSwgciwgMiAqIGksIDAsIDEpO1xuICAgIGlmICgocltpICsgeC50XSArPSB4LmFtKGkgKyAxLCAyICogeFtpXSwgciwgMiAqIGkgKyAxLCBjLCB4LnQgLSBpIC0gMSkpID49IHguRFYpIHtcbiAgICAgIHJbaSArIHgudF0gLT0geC5EVjtcbiAgICAgIHJbaSArIHgudCArIDFdID0gMTtcbiAgICB9XG4gIH1cbiAgaWYgKHIudCA+IDApIHJbci50IC0gMV0gKz0geC5hbShpLCB4W2ldLCByLCAyICogaSwgMCwgMSk7XG4gIHIucyA9IDA7XG4gIHIuY2xhbXAoKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgZGl2aWRlIHRoaXMgYnkgbSwgcXVvdGllbnQgYW5kIHJlbWFpbmRlciB0byBxLCByIChIQUMgMTQuMjApXG4vLyByICE9IHEsIHRoaXMgIT0gbS4gIHEgb3IgciBtYXkgYmUgbnVsbC5cblxuZnVuY3Rpb24gYm5wRGl2UmVtVG8obSwgcSwgcikge1xuICB2YXIgcG0gPSBtLmFicygpO1xuICBpZiAocG0udCA8PSAwKSByZXR1cm47XG4gIHZhciBwdCA9IHRoaXMuYWJzKCk7XG4gIGlmIChwdC50IDwgcG0udCkge1xuICAgIGlmIChxICE9IG51bGwpIHEuZnJvbUludCgwKTtcbiAgICBpZiAociAhPSBudWxsKSB0aGlzLmNvcHlUbyhyKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHIgPT0gbnVsbCkgciA9IG5iaSgpO1xuICB2YXIgeSA9IG5iaSgpLFxuICAgIHRzID0gdGhpcy5zLFxuICAgIG1zID0gbS5zO1xuICB2YXIgbnNoID0gdGhpcy5EQiAtIG5iaXRzKHBtW3BtLnQgLSAxXSk7IC8vIG5vcm1hbGl6ZSBtb2R1bHVzXG4gIGlmIChuc2ggPiAwKSB7XG4gICAgcG0ubFNoaWZ0VG8obnNoLCB5KTtcbiAgICBwdC5sU2hpZnRUbyhuc2gsIHIpO1xuICB9IGVsc2Uge1xuICAgIHBtLmNvcHlUbyh5KTtcbiAgICBwdC5jb3B5VG8ocik7XG4gIH1cbiAgdmFyIHlzID0geS50O1xuICB2YXIgeTAgPSB5W3lzIC0gMV07XG4gIGlmICh5MCA9PSAwKSByZXR1cm47XG4gIHZhciB5dCA9IHkwICogKDEgPDwgdGhpcy5GMSkgKyAoKHlzID4gMSkgPyB5W3lzIC0gMl0gPj4gdGhpcy5GMiA6IDApO1xuICB2YXIgZDEgPSB0aGlzLkZWIC8geXQsXG4gICAgZDIgPSAoMSA8PCB0aGlzLkYxKSAvIHl0LFxuICAgIGUgPSAxIDw8IHRoaXMuRjI7XG4gIHZhciBpID0gci50LFxuICAgIGogPSBpIC0geXMsXG4gICAgdCA9IChxID09IG51bGwpID8gbmJpKCkgOiBxO1xuICB5LmRsU2hpZnRUbyhqLCB0KTtcbiAgaWYgKHIuY29tcGFyZVRvKHQpID49IDApIHtcbiAgICByW3IudCsrXSA9IDE7XG4gICAgci5zdWJUbyh0LCByKTtcbiAgfVxuICBCaWdJbnRlZ2VyLk9ORS5kbFNoaWZ0VG8oeXMsIHQpO1xuICB0LnN1YlRvKHksIHkpOyAvLyBcIm5lZ2F0aXZlXCIgeSBzbyB3ZSBjYW4gcmVwbGFjZSBzdWIgd2l0aCBhbSBsYXRlclxuICB3aGlsZSAoeS50IDwgeXMpIHlbeS50KytdID0gMDtcbiAgd2hpbGUgKC0taiA+PSAwKSB7XG4gICAgLy8gRXN0aW1hdGUgcXVvdGllbnQgZGlnaXRcbiAgICB2YXIgcWQgPSAoclstLWldID09IHkwKSA/IHRoaXMuRE0gOiBNYXRoLmZsb29yKHJbaV0gKiBkMSArIChyW2kgLSAxXSArIGUpICogZDIpO1xuICAgIGlmICgocltpXSArPSB5LmFtKDAsIHFkLCByLCBqLCAwLCB5cykpIDwgcWQpIHsgLy8gVHJ5IGl0IG91dFxuICAgICAgeS5kbFNoaWZ0VG8oaiwgdCk7XG4gICAgICByLnN1YlRvKHQsIHIpO1xuICAgICAgd2hpbGUgKHJbaV0gPCAtLXFkKSByLnN1YlRvKHQsIHIpO1xuICAgIH1cbiAgfVxuICBpZiAocSAhPSBudWxsKSB7XG4gICAgci5kclNoaWZ0VG8oeXMsIHEpO1xuICAgIGlmICh0cyAhPSBtcykgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHEsIHEpO1xuICB9XG4gIHIudCA9IHlzO1xuICByLmNsYW1wKCk7XG4gIGlmIChuc2ggPiAwKSByLnJTaGlmdFRvKG5zaCwgcik7IC8vIERlbm9ybWFsaXplIHJlbWFpbmRlclxuICBpZiAodHMgPCAwKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8ociwgcik7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgbW9kIGFcblxuZnVuY3Rpb24gYm5Nb2QoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmFicygpLmRpdlJlbVRvKGEsIG51bGwsIHIpO1xuICBpZiAodGhpcy5zIDwgMCAmJiByLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pID4gMCkgYS5zdWJUbyhyLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIE1vZHVsYXIgcmVkdWN0aW9uIHVzaW5nIFwiY2xhc3NpY1wiIGFsZ29yaXRobVxuXG5mdW5jdGlvbiBDbGFzc2ljKG0pIHtcbiAgdGhpcy5tID0gbTtcbn1cblxuZnVuY3Rpb24gY0NvbnZlcnQoeCkge1xuICBpZiAoeC5zIDwgMCB8fCB4LmNvbXBhcmVUbyh0aGlzLm0pID49IDApIHJldHVybiB4Lm1vZCh0aGlzLm0pO1xuICBlbHNlIHJldHVybiB4O1xufVxuXG5mdW5jdGlvbiBjUmV2ZXJ0KHgpIHtcbiAgcmV0dXJuIHg7XG59XG5cbmZ1bmN0aW9uIGNSZWR1Y2UoeCkge1xuICB4LmRpdlJlbVRvKHRoaXMubSwgbnVsbCwgeCk7XG59XG5cbmZ1bmN0aW9uIGNNdWxUbyh4LCB5LCByKSB7XG4gIHgubXVsdGlwbHlUbyh5LCByKTtcbiAgdGhpcy5yZWR1Y2Uocik7XG59XG5cbmZ1bmN0aW9uIGNTcXJUbyh4LCByKSB7XG4gIHguc3F1YXJlVG8ocik7XG4gIHRoaXMucmVkdWNlKHIpO1xufVxuXG5DbGFzc2ljLnByb3RvdHlwZS5jb252ZXJ0ID0gY0NvbnZlcnQ7XG5DbGFzc2ljLnByb3RvdHlwZS5yZXZlcnQgPSBjUmV2ZXJ0O1xuQ2xhc3NpYy5wcm90b3R5cGUucmVkdWNlID0gY1JlZHVjZTtcbkNsYXNzaWMucHJvdG90eXBlLm11bFRvID0gY011bFRvO1xuQ2xhc3NpYy5wcm90b3R5cGUuc3FyVG8gPSBjU3FyVG87XG5cbi8vIChwcm90ZWN0ZWQpIHJldHVybiBcIi0xL3RoaXMgJSAyXkRCXCI7IHVzZWZ1bCBmb3IgTW9udC4gcmVkdWN0aW9uXG4vLyBqdXN0aWZpY2F0aW9uOlxuLy8gICAgICAgICB4eSA9PSAxIChtb2QgbSlcbi8vICAgICAgICAgeHkgPSAgMStrbVxuLy8gICB4eSgyLXh5KSA9ICgxK2ttKSgxLWttKVxuLy8geFt5KDIteHkpXSA9IDEta14ybV4yXG4vLyB4W3koMi14eSldID09IDEgKG1vZCBtXjIpXG4vLyBpZiB5IGlzIDEveCBtb2QgbSwgdGhlbiB5KDIteHkpIGlzIDEveCBtb2QgbV4yXG4vLyBzaG91bGQgcmVkdWNlIHggYW5kIHkoMi14eSkgYnkgbV4yIGF0IGVhY2ggc3RlcCB0byBrZWVwIHNpemUgYm91bmRlZC5cbi8vIEpTIG11bHRpcGx5IFwib3ZlcmZsb3dzXCIgZGlmZmVyZW50bHkgZnJvbSBDL0MrKywgc28gY2FyZSBpcyBuZWVkZWQgaGVyZS5cblxuZnVuY3Rpb24gYm5wSW52RGlnaXQoKSB7XG4gIGlmICh0aGlzLnQgPCAxKSByZXR1cm4gMDtcbiAgdmFyIHggPSB0aGlzWzBdO1xuICBpZiAoKHggJiAxKSA9PSAwKSByZXR1cm4gMDtcbiAgdmFyIHkgPSB4ICYgMzsgLy8geSA9PSAxL3ggbW9kIDJeMlxuICB5ID0gKHkgKiAoMiAtICh4ICYgMHhmKSAqIHkpKSAmIDB4ZjsgLy8geSA9PSAxL3ggbW9kIDJeNFxuICB5ID0gKHkgKiAoMiAtICh4ICYgMHhmZikgKiB5KSkgJiAweGZmOyAvLyB5ID09IDEveCBtb2QgMl44XG4gIHkgPSAoeSAqICgyIC0gKCgoeCAmIDB4ZmZmZikgKiB5KSAmIDB4ZmZmZikpKSAmIDB4ZmZmZjsgLy8geSA9PSAxL3ggbW9kIDJeMTZcbiAgLy8gbGFzdCBzdGVwIC0gY2FsY3VsYXRlIGludmVyc2UgbW9kIERWIGRpcmVjdGx5O1xuICAvLyBhc3N1bWVzIDE2IDwgREIgPD0gMzIgYW5kIGFzc3VtZXMgYWJpbGl0eSB0byBoYW5kbGUgNDgtYml0IGludHNcbiAgeSA9ICh5ICogKDIgLSB4ICogeSAlIHRoaXMuRFYpKSAlIHRoaXMuRFY7IC8vIHkgPT0gMS94IG1vZCAyXmRiaXRzXG4gIC8vIHdlIHJlYWxseSB3YW50IHRoZSBuZWdhdGl2ZSBpbnZlcnNlLCBhbmQgLURWIDwgeSA8IERWXG4gIHJldHVybiAoeSA+IDApID8gdGhpcy5EViAtIHkgOiAteTtcbn1cblxuLy8gTW9udGdvbWVyeSByZWR1Y3Rpb25cblxuZnVuY3Rpb24gTW9udGdvbWVyeShtKSB7XG4gIHRoaXMubSA9IG07XG4gIHRoaXMubXAgPSBtLmludkRpZ2l0KCk7XG4gIHRoaXMubXBsID0gdGhpcy5tcCAmIDB4N2ZmZjtcbiAgdGhpcy5tcGggPSB0aGlzLm1wID4+IDE1O1xuICB0aGlzLnVtID0gKDEgPDwgKG0uREIgLSAxNSkpIC0gMTtcbiAgdGhpcy5tdDIgPSAyICogbS50O1xufVxuXG4vLyB4UiBtb2QgbVxuXG5mdW5jdGlvbiBtb250Q29udmVydCh4KSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHguYWJzKCkuZGxTaGlmdFRvKHRoaXMubS50LCByKTtcbiAgci5kaXZSZW1Ubyh0aGlzLm0sIG51bGwsIHIpO1xuICBpZiAoeC5zIDwgMCAmJiByLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLlpFUk8pID4gMCkgdGhpcy5tLnN1YlRvKHIsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8geC9SIG1vZCBtXG5cbmZ1bmN0aW9uIG1vbnRSZXZlcnQoeCkge1xuICB2YXIgciA9IG5iaSgpO1xuICB4LmNvcHlUbyhyKTtcbiAgdGhpcy5yZWR1Y2Uocik7XG4gIHJldHVybiByO1xufVxuXG4vLyB4ID0geC9SIG1vZCBtIChIQUMgMTQuMzIpXG5cbmZ1bmN0aW9uIG1vbnRSZWR1Y2UoeCkge1xuICB3aGlsZSAoeC50IDw9IHRoaXMubXQyKSAvLyBwYWQgeCBzbyBhbSBoYXMgZW5vdWdoIHJvb20gbGF0ZXJcbiAgICB4W3gudCsrXSA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5tLnQ7ICsraSkge1xuICAgIC8vIGZhc3RlciB3YXkgb2YgY2FsY3VsYXRpbmcgdTAgPSB4W2ldKm1wIG1vZCBEVlxuICAgIHZhciBqID0geFtpXSAmIDB4N2ZmZjtcbiAgICB2YXIgdTAgPSAoaiAqIHRoaXMubXBsICsgKCgoaiAqIHRoaXMubXBoICsgKHhbaV0gPj4gMTUpICogdGhpcy5tcGwpICYgdGhpcy51bSkgPDwgMTUpKSAmIHguRE07XG4gICAgLy8gdXNlIGFtIHRvIGNvbWJpbmUgdGhlIG11bHRpcGx5LXNoaWZ0LWFkZCBpbnRvIG9uZSBjYWxsXG4gICAgaiA9IGkgKyB0aGlzLm0udDtcbiAgICB4W2pdICs9IHRoaXMubS5hbSgwLCB1MCwgeCwgaSwgMCwgdGhpcy5tLnQpO1xuICAgIC8vIHByb3BhZ2F0ZSBjYXJyeVxuICAgIHdoaWxlICh4W2pdID49IHguRFYpIHtcbiAgICAgIHhbal0gLT0geC5EVjtcbiAgICAgIHhbKytqXSsrO1xuICAgIH1cbiAgfVxuICB4LmNsYW1wKCk7XG4gIHguZHJTaGlmdFRvKHRoaXMubS50LCB4KTtcbiAgaWYgKHguY29tcGFyZVRvKHRoaXMubSkgPj0gMCkgeC5zdWJUbyh0aGlzLm0sIHgpO1xufVxuXG4vLyByID0gXCJ4XjIvUiBtb2QgbVwiOyB4ICE9IHJcblxuZnVuY3Rpb24gbW9udFNxclRvKHgsIHIpIHtcbiAgeC5zcXVhcmVUbyhyKTtcbiAgdGhpcy5yZWR1Y2Uocik7XG59XG5cbi8vIHIgPSBcInh5L1IgbW9kIG1cIjsgeCx5ICE9IHJcblxuZnVuY3Rpb24gbW9udE11bFRvKHgsIHksIHIpIHtcbiAgeC5tdWx0aXBseVRvKHksIHIpO1xuICB0aGlzLnJlZHVjZShyKTtcbn1cblxuTW9udGdvbWVyeS5wcm90b3R5cGUuY29udmVydCA9IG1vbnRDb252ZXJ0O1xuTW9udGdvbWVyeS5wcm90b3R5cGUucmV2ZXJ0ID0gbW9udFJldmVydDtcbk1vbnRnb21lcnkucHJvdG90eXBlLnJlZHVjZSA9IG1vbnRSZWR1Y2U7XG5Nb250Z29tZXJ5LnByb3RvdHlwZS5tdWxUbyA9IG1vbnRNdWxUbztcbk1vbnRnb21lcnkucHJvdG90eXBlLnNxclRvID0gbW9udFNxclRvO1xuXG4vLyAocHJvdGVjdGVkKSB0cnVlIGlmZiB0aGlzIGlzIGV2ZW5cblxuZnVuY3Rpb24gYm5wSXNFdmVuKCkge1xuICByZXR1cm4gKCh0aGlzLnQgPiAwKSA/ICh0aGlzWzBdICYgMSkgOiB0aGlzLnMpID09IDA7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXNeZSwgZSA8IDJeMzIsIGRvaW5nIHNxciBhbmQgbXVsIHdpdGggXCJyXCIgKEhBQyAxNC43OSlcblxuZnVuY3Rpb24gYm5wRXhwKGUsIHopIHtcbiAgaWYgKGUgPiAweGZmZmZmZmZmIHx8IGUgPCAxKSByZXR1cm4gQmlnSW50ZWdlci5PTkU7XG4gIHZhciByID0gbmJpKCksXG4gICAgcjIgPSBuYmkoKSxcbiAgICBnID0gei5jb252ZXJ0KHRoaXMpLFxuICAgIGkgPSBuYml0cyhlKSAtIDE7XG4gIGcuY29weVRvKHIpO1xuICB3aGlsZSAoLS1pID49IDApIHtcbiAgICB6LnNxclRvKHIsIHIyKTtcbiAgICBpZiAoKGUgJiAoMSA8PCBpKSkgPiAwKSB6Lm11bFRvKHIyLCBnLCByKTtcbiAgICBlbHNlIHtcbiAgICAgIHZhciB0ID0gcjtcbiAgICAgIHIgPSByMjtcbiAgICAgIHIyID0gdDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHoucmV2ZXJ0KHIpO1xufVxuXG4vLyAocHVibGljKSB0aGlzXmUgJSBtLCAwIDw9IGUgPCAyXjMyXG5cbmZ1bmN0aW9uIGJuTW9kUG93SW50KGUsIG0pIHtcbiAgdmFyIHo7XG4gIGlmIChlIDwgMjU2IHx8IG0uaXNFdmVuKCkpIHogPSBuZXcgQ2xhc3NpYyhtKTtcbiAgZWxzZSB6ID0gbmV3IE1vbnRnb21lcnkobSk7XG4gIHJldHVybiB0aGlzLmV4cChlLCB6KTtcbn1cblxuLy8gcHJvdGVjdGVkXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jb3B5VG8gPSBibnBDb3B5VG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5mcm9tSW50ID0gYm5wRnJvbUludDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmZyb21TdHJpbmcgPSBibnBGcm9tU3RyaW5nO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuY2xhbXAgPSBibnBDbGFtcDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRsU2hpZnRUbyA9IGJucERMU2hpZnRUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRyU2hpZnRUbyA9IGJucERSU2hpZnRUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmxTaGlmdFRvID0gYm5wTFNoaWZ0VG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5yU2hpZnRUbyA9IGJucFJTaGlmdFRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc3ViVG8gPSBibnBTdWJUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLm11bHRpcGx5VG8gPSBibnBNdWx0aXBseVRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc3F1YXJlVG8gPSBibnBTcXVhcmVUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRpdlJlbVRvID0gYm5wRGl2UmVtVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5pbnZEaWdpdCA9IGJucEludkRpZ2l0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuaXNFdmVuID0gYm5wSXNFdmVuO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZXhwID0gYm5wRXhwO1xuXG4vLyBwdWJsaWNcbkJpZ0ludGVnZXIucHJvdG90eXBlLnRvU3RyaW5nID0gYm5Ub1N0cmluZztcbkJpZ0ludGVnZXIucHJvdG90eXBlLm5lZ2F0ZSA9IGJuTmVnYXRlO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYWJzID0gYm5BYnM7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jb21wYXJlVG8gPSBibkNvbXBhcmVUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmJpdExlbmd0aCA9IGJuQml0TGVuZ3RoO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubW9kID0gYm5Nb2Q7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tb2RQb3dJbnQgPSBibk1vZFBvd0ludDtcblxuLy8gXCJjb25zdGFudHNcIlxuQmlnSW50ZWdlci5aRVJPID0gbmJ2KDApO1xuQmlnSW50ZWdlci5PTkUgPSBuYnYoMSk7XG5cbm1vZHVsZS5leHBvcnRzID0gQmlnSW50ZWdlcjtcblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuLypcbiAqIENvcHlyaWdodCAoYykgMjAwMy0yMDA1ICBUb20gV3UgKHRqd0Bjcy5TdGFuZm9yZC5FRFUpIFxuICogQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkhcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmdcbiAqIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuICogXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4gKiB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4gKiBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG9cbiAqIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0b1xuICogdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUy1JU1wiIEFORCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBcbiAqIEVYUFJFU1MsIElNUExJRUQgT1IgT1RIRVJXSVNFLCBJTkNMVURJTkcgV0lUSE9VVCBMSU1JVEFUSU9OLCBBTlkgXG4gKiBXQVJSQU5UWSBPRiBNRVJDSEFOVEFCSUxJVFkgT1IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBcbiAqXG4gKiBJTiBOTyBFVkVOVCBTSEFMTCBUT00gV1UgQkUgTElBQkxFIEZPUiBBTlkgU1BFQ0lBTCwgSU5DSURFTlRBTCxcbiAqIElORElSRUNUIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPRiBBTlkgS0lORCwgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUlxuICogUkVTVUxUSU5HIEZST00gTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBPUiBOT1QgQURWSVNFRCBPRlxuICogVEhFIFBPU1NJQklMSVRZIE9GIERBTUFHRSwgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBBUklTSU5HIE9VVFxuICogT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IgUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cbiAqXG4gKiBJbiBhZGRpdGlvbiwgdGhlIGZvbGxvd2luZyBjb25kaXRpb24gYXBwbGllczpcbiAqXG4gKiBBbGwgcmVkaXN0cmlidXRpb25zIG11c3QgcmV0YWluIGFuIGludGFjdCBjb3B5IG9mIHRoaXMgY29weXJpZ2h0IG5vdGljZVxuICogYW5kIGRpc2NsYWltZXIuXG4gKi9cblxuXG4vLyBFeHRlbmRlZCBKYXZhU2NyaXB0IEJOIGZ1bmN0aW9ucywgcmVxdWlyZWQgZm9yIFJTQSBwcml2YXRlIG9wcy5cblxuLy8gVmVyc2lvbiAxLjE6IG5ldyBCaWdJbnRlZ2VyKFwiMFwiLCAxMCkgcmV0dXJucyBcInByb3BlclwiIHplcm9cbi8vIFZlcnNpb24gMS4yOiBzcXVhcmUoKSBBUEksIGlzUHJvYmFibGVQcmltZSBmaXhcblxuLy8gKHB1YmxpYylcbmZ1bmN0aW9uIGJuQ2xvbmUoKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHRoaXMuY29weVRvKHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgcmV0dXJuIHZhbHVlIGFzIGludGVnZXJcblxuZnVuY3Rpb24gYm5JbnRWYWx1ZSgpIHtcbiAgaWYgKHRoaXMucyA8IDApIHtcbiAgICBpZiAodGhpcy50ID09IDEpIHJldHVybiB0aGlzWzBdIC0gdGhpcy5EVjtcbiAgICBlbHNlIGlmICh0aGlzLnQgPT0gMCkgcmV0dXJuIC0xO1xuICB9IGVsc2UgaWYgKHRoaXMudCA9PSAxKSByZXR1cm4gdGhpc1swXTtcbiAgZWxzZSBpZiAodGhpcy50ID09IDApIHJldHVybiAwO1xuICAvLyBhc3N1bWVzIDE2IDwgREIgPCAzMlxuICByZXR1cm4gKCh0aGlzWzFdICYgKCgxIDw8ICgzMiAtIHRoaXMuREIpKSAtIDEpKSA8PCB0aGlzLkRCKSB8IHRoaXNbMF07XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiB2YWx1ZSBhcyBieXRlXG5cbmZ1bmN0aW9uIGJuQnl0ZVZhbHVlKCkge1xuICByZXR1cm4gKHRoaXMudCA9PSAwKSA/IHRoaXMucyA6ICh0aGlzWzBdIDw8IDI0KSA+PiAyNDtcbn1cblxuLy8gKHB1YmxpYykgcmV0dXJuIHZhbHVlIGFzIHNob3J0IChhc3N1bWVzIERCPj0xNilcblxuZnVuY3Rpb24gYm5TaG9ydFZhbHVlKCkge1xuICByZXR1cm4gKHRoaXMudCA9PSAwKSA/IHRoaXMucyA6ICh0aGlzWzBdIDw8IDE2KSA+PiAxNjtcbn1cblxuLy8gKHByb3RlY3RlZCkgcmV0dXJuIHggcy50LiByXnggPCBEVlxuXG5mdW5jdGlvbiBibnBDaHVua1NpemUocikge1xuICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLkxOMiAqIHRoaXMuREIgLyBNYXRoLmxvZyhyKSk7XG59XG5cbi8vIChwdWJsaWMpIDAgaWYgdGhpcyA9PSAwLCAxIGlmIHRoaXMgPiAwXG5cbmZ1bmN0aW9uIGJuU2lnTnVtKCkge1xuICBpZiAodGhpcy5zIDwgMCkgcmV0dXJuIC0xO1xuICBlbHNlIGlmICh0aGlzLnQgPD0gMCB8fCAodGhpcy50ID09IDEgJiYgdGhpc1swXSA8PSAwKSkgcmV0dXJuIDA7XG4gIGVsc2UgcmV0dXJuIDE7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvbnZlcnQgdG8gcmFkaXggc3RyaW5nXG5cbmZ1bmN0aW9uIGJucFRvUmFkaXgoYikge1xuICBpZiAoYiA9PSBudWxsKSBiID0gMTA7XG4gIGlmICh0aGlzLnNpZ251bSgpID09IDAgfHwgYiA8IDIgfHwgYiA+IDM2KSByZXR1cm4gXCIwXCI7XG4gIHZhciBjcyA9IHRoaXMuY2h1bmtTaXplKGIpO1xuICB2YXIgYSA9IE1hdGgucG93KGIsIGNzKTtcbiAgdmFyIGQgPSBuYnYoYSksXG4gICAgeSA9IG5iaSgpLFxuICAgIHogPSBuYmkoKSxcbiAgICByID0gXCJcIjtcbiAgdGhpcy5kaXZSZW1UbyhkLCB5LCB6KTtcbiAgd2hpbGUgKHkuc2lnbnVtKCkgPiAwKSB7XG4gICAgciA9IChhICsgei5pbnRWYWx1ZSgpKS50b1N0cmluZyhiKS5zdWJzdHIoMSkgKyByO1xuICAgIHkuZGl2UmVtVG8oZCwgeSwgeik7XG4gIH1cbiAgcmV0dXJuIHouaW50VmFsdWUoKS50b1N0cmluZyhiKSArIHI7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvbnZlcnQgZnJvbSByYWRpeCBzdHJpbmdcblxuZnVuY3Rpb24gYm5wRnJvbVJhZGl4KHMsIGIpIHtcbiAgdGhpcy5mcm9tSW50KDApO1xuICBpZiAoYiA9PSBudWxsKSBiID0gMTA7XG4gIHZhciBjcyA9IHRoaXMuY2h1bmtTaXplKGIpO1xuICB2YXIgZCA9IE1hdGgucG93KGIsIGNzKSxcbiAgICBtaSA9IGZhbHNlLFxuICAgIGogPSAwLFxuICAgIHcgPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHMubGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgeCA9IGludEF0KHMsIGkpO1xuICAgIGlmICh4IDwgMCkge1xuICAgICAgaWYgKHMuY2hhckF0KGkpID09IFwiLVwiICYmIHRoaXMuc2lnbnVtKCkgPT0gMCkgbWkgPSB0cnVlO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHcgPSBiICogdyArIHg7XG4gICAgaWYgKCsraiA+PSBjcykge1xuICAgICAgdGhpcy5kTXVsdGlwbHkoZCk7XG4gICAgICB0aGlzLmRBZGRPZmZzZXQodywgMCk7XG4gICAgICBqID0gMDtcbiAgICAgIHcgPSAwO1xuICAgIH1cbiAgfVxuICBpZiAoaiA+IDApIHtcbiAgICB0aGlzLmRNdWx0aXBseShNYXRoLnBvdyhiLCBqKSk7XG4gICAgdGhpcy5kQWRkT2Zmc2V0KHcsIDApO1xuICB9XG4gIGlmIChtaSkgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHRoaXMsIHRoaXMpO1xufVxuXG4vLyAocHJvdGVjdGVkKSBhbHRlcm5hdGUgY29uc3RydWN0b3JcblxuZnVuY3Rpb24gYm5wRnJvbU51bWJlcihhLCBiLCBjKSB7XG4gIGlmIChcIm51bWJlclwiID09IHR5cGVvZiBiKSB7XG4gICAgLy8gbmV3IEJpZ0ludGVnZXIoaW50LGludCxSTkcpXG4gICAgaWYgKGEgPCAyKSB0aGlzLmZyb21JbnQoMSk7XG4gICAgZWxzZSB7XG4gICAgICB0aGlzLmZyb21OdW1iZXIoYSwgYyk7XG4gICAgICBpZiAoIXRoaXMudGVzdEJpdChhIC0gMSkpIC8vIGZvcmNlIE1TQiBzZXRcbiAgICAgICAgdGhpcy5iaXR3aXNlVG8oQmlnSW50ZWdlci5PTkUuc2hpZnRMZWZ0KGEgLSAxKSwgb3Bfb3IsIHRoaXMpO1xuICAgICAgaWYgKHRoaXMuaXNFdmVuKCkpIHRoaXMuZEFkZE9mZnNldCgxLCAwKTsgLy8gZm9yY2Ugb2RkXG4gICAgICB3aGlsZSAoIXRoaXMuaXNQcm9iYWJsZVByaW1lKGIpKSB7XG4gICAgICAgIHRoaXMuZEFkZE9mZnNldCgyLCAwKTtcbiAgICAgICAgaWYgKHRoaXMuYml0TGVuZ3RoKCkgPiBhKSB0aGlzLnN1YlRvKEJpZ0ludGVnZXIuT05FLnNoaWZ0TGVmdChhIC0gMSksIHRoaXMpO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICAvLyBuZXcgQmlnSW50ZWdlcihpbnQsUk5HKVxuICAgIHZhciB4ID0gbmV3IEFycmF5KCksXG4gICAgICB0ID0gYSAmIDc7XG4gICAgeC5sZW5ndGggPSAoYSA+PiAzKSArIDE7XG4gICAgYi5uZXh0Qnl0ZXMoeCk7XG4gICAgaWYgKHQgPiAwKSB4WzBdICY9ICgoMSA8PCB0KSAtIDEpO1xuICAgIGVsc2UgeFswXSA9IDA7XG4gICAgdGhpcy5mcm9tU3RyaW5nKHgsIDI1Nik7XG4gIH1cbn1cblxuLy8gKHB1YmxpYykgY29udmVydCB0byBiaWdlbmRpYW4gYnl0ZSBhcnJheVxuXG5mdW5jdGlvbiBiblRvQnl0ZUFycmF5KCkge1xuICB2YXIgaSA9IHRoaXMudCxcbiAgICByID0gbmV3IEFycmF5KCk7XG4gIHJbMF0gPSB0aGlzLnM7XG4gIHZhciBwID0gdGhpcy5EQiAtIChpICogdGhpcy5EQikgJSA4LFxuICAgIGQsIGsgPSAwO1xuICBpZiAoaS0tID4gMCkge1xuICAgIGlmIChwIDwgdGhpcy5EQiAmJiAoZCA9IHRoaXNbaV0gPj4gcCkgIT0gKHRoaXMucyAmIHRoaXMuRE0pID4+IHApXG4gICAgICByW2srK10gPSBkIHwgKHRoaXMucyA8PCAodGhpcy5EQiAtIHApKTtcbiAgICB3aGlsZSAoaSA+PSAwKSB7XG4gICAgICBpZiAocCA8IDgpIHtcbiAgICAgICAgZCA9ICh0aGlzW2ldICYgKCgxIDw8IHApIC0gMSkpIDw8ICg4IC0gcCk7XG4gICAgICAgIGQgfD0gdGhpc1stLWldID4+IChwICs9IHRoaXMuREIgLSA4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGQgPSAodGhpc1tpXSA+PiAocCAtPSA4KSkgJiAweGZmO1xuICAgICAgICBpZiAocCA8PSAwKSB7XG4gICAgICAgICAgcCArPSB0aGlzLkRCO1xuICAgICAgICAgIC0taTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy9pZigoZCYweDgwKSAhPSAwKSBkIHw9IC0yNTY7XG4gICAgICAvL2lmKGsgPT0gMCAmJiAodGhpcy5zJjB4ODApICE9IChkJjB4ODApKSArK2s7XG4gICAgICBpZiAoayA+IDAgfHwgZCAhPSB0aGlzLnMpIHJbaysrXSA9IGQ7XG4gICAgfVxuICB9XG4gIHJldHVybiByO1xufVxuXG5mdW5jdGlvbiBibkVxdWFscyhhKSB7XG4gIHJldHVybiAodGhpcy5jb21wYXJlVG8oYSkgPT0gMCk7XG59XG5cbmZ1bmN0aW9uIGJuTWluKGEpIHtcbiAgcmV0dXJuICh0aGlzLmNvbXBhcmVUbyhhKSA8IDApID8gdGhpcyA6IGE7XG59XG5cbmZ1bmN0aW9uIGJuTWF4KGEpIHtcbiAgcmV0dXJuICh0aGlzLmNvbXBhcmVUbyhhKSA+IDApID8gdGhpcyA6IGE7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzIG9wIGEgKGJpdHdpc2UpXG5cbmZ1bmN0aW9uIGJucEJpdHdpc2VUbyhhLCBvcCwgcikge1xuICB2YXIgaSwgZiwgbSA9IE1hdGgubWluKGEudCwgdGhpcy50KTtcbiAgZm9yIChpID0gMDsgaSA8IG07ICsraSkgcltpXSA9IG9wKHRoaXNbaV0sIGFbaV0pO1xuICBpZiAoYS50IDwgdGhpcy50KSB7XG4gICAgZiA9IGEucyAmIHRoaXMuRE07XG4gICAgZm9yIChpID0gbTsgaSA8IHRoaXMudDsgKytpKSByW2ldID0gb3AodGhpc1tpXSwgZik7XG4gICAgci50ID0gdGhpcy50O1xuICB9IGVsc2Uge1xuICAgIGYgPSB0aGlzLnMgJiB0aGlzLkRNO1xuICAgIGZvciAoaSA9IG07IGkgPCBhLnQ7ICsraSkgcltpXSA9IG9wKGYsIGFbaV0pO1xuICAgIHIudCA9IGEudDtcbiAgfVxuICByLnMgPSBvcCh0aGlzLnMsIGEucyk7XG4gIHIuY2xhbXAoKTtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAmIGFcblxuZnVuY3Rpb24gb3BfYW5kKHgsIHkpIHtcbiAgcmV0dXJuIHggJiB5O1xufVxuXG5mdW5jdGlvbiBibkFuZChhKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHRoaXMuYml0d2lzZVRvKGEsIG9wX2FuZCwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzIHwgYVxuXG5mdW5jdGlvbiBvcF9vcih4LCB5KSB7XG4gIHJldHVybiB4IHwgeTtcbn1cblxuZnVuY3Rpb24gYm5PcihhKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHRoaXMuYml0d2lzZVRvKGEsIG9wX29yLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgXiBhXG5cbmZ1bmN0aW9uIG9wX3hvcih4LCB5KSB7XG4gIHJldHVybiB4IF4geTtcbn1cblxuZnVuY3Rpb24gYm5Yb3IoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmJpdHdpc2VUbyhhLCBvcF94b3IsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAmIH5hXG5cbmZ1bmN0aW9uIG9wX2FuZG5vdCh4LCB5KSB7XG4gIHJldHVybiB4ICYgfnk7XG59XG5cbmZ1bmN0aW9uIGJuQW5kTm90KGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5iaXR3aXNlVG8oYSwgb3BfYW5kbm90LCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIH50aGlzXG5cbmZ1bmN0aW9uIGJuTm90KCkge1xuICB2YXIgciA9IG5iaSgpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMudDsgKytpKSByW2ldID0gdGhpcy5ETSAmIH50aGlzW2ldO1xuICByLnQgPSB0aGlzLnQ7XG4gIHIucyA9IH50aGlzLnM7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzIDw8IG5cblxuZnVuY3Rpb24gYm5TaGlmdExlZnQobikge1xuICB2YXIgciA9IG5iaSgpO1xuICBpZiAobiA8IDApIHRoaXMuclNoaWZ0VG8oLW4sIHIpO1xuICBlbHNlIHRoaXMubFNoaWZ0VG8obiwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzID4+IG5cblxuZnVuY3Rpb24gYm5TaGlmdFJpZ2h0KG4pIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgaWYgKG4gPCAwKSB0aGlzLmxTaGlmdFRvKC1uLCByKTtcbiAgZWxzZSB0aGlzLnJTaGlmdFRvKG4sIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gcmV0dXJuIGluZGV4IG9mIGxvd2VzdCAxLWJpdCBpbiB4LCB4IDwgMl4zMVxuXG5mdW5jdGlvbiBsYml0KHgpIHtcbiAgaWYgKHggPT0gMCkgcmV0dXJuIC0xO1xuICB2YXIgciA9IDA7XG4gIGlmICgoeCAmIDB4ZmZmZikgPT0gMCkge1xuICAgIHggPj49IDE2O1xuICAgIHIgKz0gMTY7XG4gIH1cbiAgaWYgKCh4ICYgMHhmZikgPT0gMCkge1xuICAgIHggPj49IDg7XG4gICAgciArPSA4O1xuICB9XG4gIGlmICgoeCAmIDB4ZikgPT0gMCkge1xuICAgIHggPj49IDQ7XG4gICAgciArPSA0O1xuICB9XG4gIGlmICgoeCAmIDMpID09IDApIHtcbiAgICB4ID4+PSAyO1xuICAgIHIgKz0gMjtcbiAgfVxuICBpZiAoKHggJiAxKSA9PSAwKSsrcjtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybnMgaW5kZXggb2YgbG93ZXN0IDEtYml0IChvciAtMSBpZiBub25lKVxuXG5mdW5jdGlvbiBibkdldExvd2VzdFNldEJpdCgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnQ7ICsraSlcbiAgICBpZiAodGhpc1tpXSAhPSAwKSByZXR1cm4gaSAqIHRoaXMuREIgKyBsYml0KHRoaXNbaV0pO1xuICBpZiAodGhpcy5zIDwgMCkgcmV0dXJuIHRoaXMudCAqIHRoaXMuREI7XG4gIHJldHVybiAtMTtcbn1cblxuLy8gcmV0dXJuIG51bWJlciBvZiAxIGJpdHMgaW4geFxuXG5mdW5jdGlvbiBjYml0KHgpIHtcbiAgdmFyIHIgPSAwO1xuICB3aGlsZSAoeCAhPSAwKSB7XG4gICAgeCAmPSB4IC0gMTtcbiAgICArK3I7XG4gIH1cbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiBudW1iZXIgb2Ygc2V0IGJpdHNcblxuZnVuY3Rpb24gYm5CaXRDb3VudCgpIHtcbiAgdmFyIHIgPSAwLFxuICAgIHggPSB0aGlzLnMgJiB0aGlzLkRNO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMudDsgKytpKSByICs9IGNiaXQodGhpc1tpXSBeIHgpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdHJ1ZSBpZmYgbnRoIGJpdCBpcyBzZXRcblxuZnVuY3Rpb24gYm5UZXN0Qml0KG4pIHtcbiAgdmFyIGogPSBNYXRoLmZsb29yKG4gLyB0aGlzLkRCKTtcbiAgaWYgKGogPj0gdGhpcy50KSByZXR1cm4gKHRoaXMucyAhPSAwKTtcbiAgcmV0dXJuICgodGhpc1tqXSAmICgxIDw8IChuICUgdGhpcy5EQikpKSAhPSAwKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgdGhpcyBvcCAoMTw8bilcblxuZnVuY3Rpb24gYm5wQ2hhbmdlQml0KG4sIG9wKSB7XG4gIHZhciByID0gQmlnSW50ZWdlci5PTkUuc2hpZnRMZWZ0KG4pO1xuICB0aGlzLmJpdHdpc2VUbyhyLCBvcCwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzIHwgKDE8PG4pXG5cbmZ1bmN0aW9uIGJuU2V0Qml0KG4pIHtcbiAgcmV0dXJuIHRoaXMuY2hhbmdlQml0KG4sIG9wX29yKTtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAmIH4oMTw8bilcblxuZnVuY3Rpb24gYm5DbGVhckJpdChuKSB7XG4gIHJldHVybiB0aGlzLmNoYW5nZUJpdChuLCBvcF9hbmRub3QpO1xufVxuXG4vLyAocHVibGljKSB0aGlzIF4gKDE8PG4pXG5cbmZ1bmN0aW9uIGJuRmxpcEJpdChuKSB7XG4gIHJldHVybiB0aGlzLmNoYW5nZUJpdChuLCBvcF94b3IpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyArIGFcblxuZnVuY3Rpb24gYm5wQWRkVG8oYSwgcikge1xuICB2YXIgaSA9IDAsXG4gICAgYyA9IDAsXG4gICAgbSA9IE1hdGgubWluKGEudCwgdGhpcy50KTtcbiAgd2hpbGUgKGkgPCBtKSB7XG4gICAgYyArPSB0aGlzW2ldICsgYVtpXTtcbiAgICByW2krK10gPSBjICYgdGhpcy5ETTtcbiAgICBjID4+PSB0aGlzLkRCO1xuICB9XG4gIGlmIChhLnQgPCB0aGlzLnQpIHtcbiAgICBjICs9IGEucztcbiAgICB3aGlsZSAoaSA8IHRoaXMudCkge1xuICAgICAgYyArPSB0aGlzW2ldO1xuICAgICAgcltpKytdID0gYyAmIHRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjICs9IHRoaXMucztcbiAgfSBlbHNlIHtcbiAgICBjICs9IHRoaXMucztcbiAgICB3aGlsZSAoaSA8IGEudCkge1xuICAgICAgYyArPSBhW2ldO1xuICAgICAgcltpKytdID0gYyAmIHRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjICs9IGEucztcbiAgfVxuICByLnMgPSAoYyA8IDApID8gLTEgOiAwO1xuICBpZiAoYyA+IDApIHJbaSsrXSA9IGM7XG4gIGVsc2UgaWYgKGMgPCAtMSkgcltpKytdID0gdGhpcy5EViArIGM7XG4gIHIudCA9IGk7XG4gIHIuY2xhbXAoKTtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyArIGFcblxuZnVuY3Rpb24gYm5BZGQoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmFkZFRvKGEsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAtIGFcblxuZnVuY3Rpb24gYm5TdWJ0cmFjdChhKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHRoaXMuc3ViVG8oYSwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzICogYVxuXG5mdW5jdGlvbiBibk11bHRpcGx5KGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5tdWx0aXBseVRvKGEsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpc14yXG5cbmZ1bmN0aW9uIGJuU3F1YXJlKCkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLnNxdWFyZVRvKHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAvIGFcblxuZnVuY3Rpb24gYm5EaXZpZGUoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmRpdlJlbVRvKGEsIHIsIG51bGwpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAlIGFcblxuZnVuY3Rpb24gYm5SZW1haW5kZXIoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmRpdlJlbVRvKGEsIG51bGwsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgW3RoaXMvYSx0aGlzJWFdXG5cbmZ1bmN0aW9uIGJuRGl2aWRlQW5kUmVtYWluZGVyKGEpIHtcbiAgdmFyIHEgPSBuYmkoKSxcbiAgICByID0gbmJpKCk7XG4gIHRoaXMuZGl2UmVtVG8oYSwgcSwgcik7XG4gIHJldHVybiBuZXcgQXJyYXkocSwgcik7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgKj0gbiwgdGhpcyA+PSAwLCAxIDwgbiA8IERWXG5cbmZ1bmN0aW9uIGJucERNdWx0aXBseShuKSB7XG4gIHRoaXNbdGhpcy50XSA9IHRoaXMuYW0oMCwgbiAtIDEsIHRoaXMsIDAsIDAsIHRoaXMudCk7XG4gICsrdGhpcy50O1xuICB0aGlzLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgKz0gbiA8PCB3IHdvcmRzLCB0aGlzID49IDBcblxuZnVuY3Rpb24gYm5wREFkZE9mZnNldChuLCB3KSB7XG4gIGlmIChuID09IDApIHJldHVybjtcbiAgd2hpbGUgKHRoaXMudCA8PSB3KSB0aGlzW3RoaXMudCsrXSA9IDA7XG4gIHRoaXNbd10gKz0gbjtcbiAgd2hpbGUgKHRoaXNbd10gPj0gdGhpcy5EVikge1xuICAgIHRoaXNbd10gLT0gdGhpcy5EVjtcbiAgICBpZiAoKyt3ID49IHRoaXMudCkgdGhpc1t0aGlzLnQrK10gPSAwO1xuICAgICsrdGhpc1t3XTtcbiAgfVxufVxuXG4vLyBBIFwibnVsbFwiIHJlZHVjZXJcblxuZnVuY3Rpb24gTnVsbEV4cCgpIHt9XG5cbmZ1bmN0aW9uIG5Ob3AoeCkge1xuICByZXR1cm4geDtcbn1cblxuZnVuY3Rpb24gbk11bFRvKHgsIHksIHIpIHtcbiAgeC5tdWx0aXBseVRvKHksIHIpO1xufVxuXG5mdW5jdGlvbiBuU3FyVG8oeCwgcikge1xuICB4LnNxdWFyZVRvKHIpO1xufVxuXG5OdWxsRXhwLnByb3RvdHlwZS5jb252ZXJ0ID0gbk5vcDtcbk51bGxFeHAucHJvdG90eXBlLnJldmVydCA9IG5Ob3A7XG5OdWxsRXhwLnByb3RvdHlwZS5tdWxUbyA9IG5NdWxUbztcbk51bGxFeHAucHJvdG90eXBlLnNxclRvID0gblNxclRvO1xuXG4vLyAocHVibGljKSB0aGlzXmVcblxuZnVuY3Rpb24gYm5Qb3coZSkge1xuICByZXR1cm4gdGhpcy5leHAoZSwgbmV3IE51bGxFeHAoKSk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSBsb3dlciBuIHdvcmRzIG9mIFwidGhpcyAqIGFcIiwgYS50IDw9IG5cbi8vIFwidGhpc1wiIHNob3VsZCBiZSB0aGUgbGFyZ2VyIG9uZSBpZiBhcHByb3ByaWF0ZS5cblxuZnVuY3Rpb24gYm5wTXVsdGlwbHlMb3dlclRvKGEsIG4sIHIpIHtcbiAgdmFyIGkgPSBNYXRoLm1pbih0aGlzLnQgKyBhLnQsIG4pO1xuICByLnMgPSAwOyAvLyBhc3N1bWVzIGEsdGhpcyA+PSAwXG4gIHIudCA9IGk7XG4gIHdoaWxlIChpID4gMCkgclstLWldID0gMDtcbiAgdmFyIGo7XG4gIGZvciAoaiA9IHIudCAtIHRoaXMudDsgaSA8IGo7ICsraSkgcltpICsgdGhpcy50XSA9IHRoaXMuYW0oMCwgYVtpXSwgciwgaSwgMCwgdGhpcy50KTtcbiAgZm9yIChqID0gTWF0aC5taW4oYS50LCBuKTsgaSA8IGo7ICsraSkgdGhpcy5hbSgwLCBhW2ldLCByLCBpLCAwLCBuIC0gaSk7XG4gIHIuY2xhbXAoKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IFwidGhpcyAqIGFcIiB3aXRob3V0IGxvd2VyIG4gd29yZHMsIG4gPiAwXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5cbmZ1bmN0aW9uIGJucE11bHRpcGx5VXBwZXJUbyhhLCBuLCByKSB7XG4gIC0tbjtcbiAgdmFyIGkgPSByLnQgPSB0aGlzLnQgKyBhLnQgLSBuO1xuICByLnMgPSAwOyAvLyBhc3N1bWVzIGEsdGhpcyA+PSAwXG4gIHdoaWxlICgtLWkgPj0gMCkgcltpXSA9IDA7XG4gIGZvciAoaSA9IE1hdGgubWF4KG4gLSB0aGlzLnQsIDApOyBpIDwgYS50OyArK2kpXG4gICAgclt0aGlzLnQgKyBpIC0gbl0gPSB0aGlzLmFtKG4gLSBpLCBhW2ldLCByLCAwLCAwLCB0aGlzLnQgKyBpIC0gbik7XG4gIHIuY2xhbXAoKTtcbiAgci5kclNoaWZ0VG8oMSwgcik7XG59XG5cbi8vIEJhcnJldHQgbW9kdWxhciByZWR1Y3Rpb25cblxuZnVuY3Rpb24gQmFycmV0dChtKSB7XG4gIC8vIHNldHVwIEJhcnJldHRcbiAgdGhpcy5yMiA9IG5iaSgpO1xuICB0aGlzLnEzID0gbmJpKCk7XG4gIEJpZ0ludGVnZXIuT05FLmRsU2hpZnRUbygyICogbS50LCB0aGlzLnIyKTtcbiAgdGhpcy5tdSA9IHRoaXMucjIuZGl2aWRlKG0pO1xuICB0aGlzLm0gPSBtO1xufVxuXG5mdW5jdGlvbiBiYXJyZXR0Q29udmVydCh4KSB7XG4gIGlmICh4LnMgPCAwIHx8IHgudCA+IDIgKiB0aGlzLm0udCkgcmV0dXJuIHgubW9kKHRoaXMubSk7XG4gIGVsc2UgaWYgKHguY29tcGFyZVRvKHRoaXMubSkgPCAwKSByZXR1cm4geDtcbiAgZWxzZSB7XG4gICAgdmFyIHIgPSBuYmkoKTtcbiAgICB4LmNvcHlUbyhyKTtcbiAgICB0aGlzLnJlZHVjZShyKTtcbiAgICByZXR1cm4gcjtcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXJyZXR0UmV2ZXJ0KHgpIHtcbiAgcmV0dXJuIHg7XG59XG5cbi8vIHggPSB4IG1vZCBtIChIQUMgMTQuNDIpXG5cbmZ1bmN0aW9uIGJhcnJldHRSZWR1Y2UoeCkge1xuICB4LmRyU2hpZnRUbyh0aGlzLm0udCAtIDEsIHRoaXMucjIpO1xuICBpZiAoeC50ID4gdGhpcy5tLnQgKyAxKSB7XG4gICAgeC50ID0gdGhpcy5tLnQgKyAxO1xuICAgIHguY2xhbXAoKTtcbiAgfVxuICB0aGlzLm11Lm11bHRpcGx5VXBwZXJUbyh0aGlzLnIyLCB0aGlzLm0udCArIDEsIHRoaXMucTMpO1xuICB0aGlzLm0ubXVsdGlwbHlMb3dlclRvKHRoaXMucTMsIHRoaXMubS50ICsgMSwgdGhpcy5yMik7XG4gIHdoaWxlICh4LmNvbXBhcmVUbyh0aGlzLnIyKSA8IDApIHguZEFkZE9mZnNldCgxLCB0aGlzLm0udCArIDEpO1xuICB4LnN1YlRvKHRoaXMucjIsIHgpO1xuICB3aGlsZSAoeC5jb21wYXJlVG8odGhpcy5tKSA+PSAwKSB4LnN1YlRvKHRoaXMubSwgeCk7XG59XG5cbi8vIHIgPSB4XjIgbW9kIG07IHggIT0gclxuXG5mdW5jdGlvbiBiYXJyZXR0U3FyVG8oeCwgcikge1xuICB4LnNxdWFyZVRvKHIpO1xuICB0aGlzLnJlZHVjZShyKTtcbn1cblxuLy8gciA9IHgqeSBtb2QgbTsgeCx5ICE9IHJcblxuZnVuY3Rpb24gYmFycmV0dE11bFRvKHgsIHksIHIpIHtcbiAgeC5tdWx0aXBseVRvKHksIHIpO1xuICB0aGlzLnJlZHVjZShyKTtcbn1cblxuQmFycmV0dC5wcm90b3R5cGUuY29udmVydCA9IGJhcnJldHRDb252ZXJ0O1xuQmFycmV0dC5wcm90b3R5cGUucmV2ZXJ0ID0gYmFycmV0dFJldmVydDtcbkJhcnJldHQucHJvdG90eXBlLnJlZHVjZSA9IGJhcnJldHRSZWR1Y2U7XG5CYXJyZXR0LnByb3RvdHlwZS5tdWxUbyA9IGJhcnJldHRNdWxUbztcbkJhcnJldHQucHJvdG90eXBlLnNxclRvID0gYmFycmV0dFNxclRvO1xuXG4vLyAocHVibGljKSB0aGlzXmUgJSBtIChIQUMgMTQuODUpXG5cbmZ1bmN0aW9uIGJuTW9kUG93KGUsIG0pIHtcbiAgdmFyIGkgPSBlLmJpdExlbmd0aCgpLFxuICAgIGssIHIgPSBuYnYoMSksXG4gICAgejtcbiAgaWYgKGkgPD0gMCkgcmV0dXJuIHI7XG4gIGVsc2UgaWYgKGkgPCAxOCkgayA9IDE7XG4gIGVsc2UgaWYgKGkgPCA0OCkgayA9IDM7XG4gIGVsc2UgaWYgKGkgPCAxNDQpIGsgPSA0O1xuICBlbHNlIGlmIChpIDwgNzY4KSBrID0gNTtcbiAgZWxzZSBrID0gNjtcbiAgaWYgKGkgPCA4KVxuICAgIHogPSBuZXcgQ2xhc3NpYyhtKTtcbiAgZWxzZSBpZiAobS5pc0V2ZW4oKSlcbiAgICB6ID0gbmV3IEJhcnJldHQobSk7XG4gIGVsc2VcbiAgICB6ID0gbmV3IE1vbnRnb21lcnkobSk7XG5cbiAgLy8gcHJlY29tcHV0YXRpb25cbiAgdmFyIGcgPSBuZXcgQXJyYXkoKSxcbiAgICBuID0gMyxcbiAgICBrMSA9IGsgLSAxLFxuICAgIGttID0gKDEgPDwgaykgLSAxO1xuICBnWzFdID0gei5jb252ZXJ0KHRoaXMpO1xuICBpZiAoayA+IDEpIHtcbiAgICB2YXIgZzIgPSBuYmkoKTtcbiAgICB6LnNxclRvKGdbMV0sIGcyKTtcbiAgICB3aGlsZSAobiA8PSBrbSkge1xuICAgICAgZ1tuXSA9IG5iaSgpO1xuICAgICAgei5tdWxUbyhnMiwgZ1tuIC0gMl0sIGdbbl0pO1xuICAgICAgbiArPSAyO1xuICAgIH1cbiAgfVxuXG4gIHZhciBqID0gZS50IC0gMSxcbiAgICB3LCBpczEgPSB0cnVlLFxuICAgIHIyID0gbmJpKCksXG4gICAgdDtcbiAgaSA9IG5iaXRzKGVbal0pIC0gMTtcbiAgd2hpbGUgKGogPj0gMCkge1xuICAgIGlmIChpID49IGsxKSB3ID0gKGVbal0gPj4gKGkgLSBrMSkpICYga207XG4gICAgZWxzZSB7XG4gICAgICB3ID0gKGVbal0gJiAoKDEgPDwgKGkgKyAxKSkgLSAxKSkgPDwgKGsxIC0gaSk7XG4gICAgICBpZiAoaiA+IDApIHcgfD0gZVtqIC0gMV0gPj4gKHRoaXMuREIgKyBpIC0gazEpO1xuICAgIH1cblxuICAgIG4gPSBrO1xuICAgIHdoaWxlICgodyAmIDEpID09IDApIHtcbiAgICAgIHcgPj49IDE7XG4gICAgICAtLW47XG4gICAgfVxuICAgIGlmICgoaSAtPSBuKSA8IDApIHtcbiAgICAgIGkgKz0gdGhpcy5EQjtcbiAgICAgIC0tajtcbiAgICB9XG4gICAgaWYgKGlzMSkgeyAvLyByZXQgPT0gMSwgZG9uJ3QgYm90aGVyIHNxdWFyaW5nIG9yIG11bHRpcGx5aW5nIGl0XG4gICAgICBnW3ddLmNvcHlUbyhyKTtcbiAgICAgIGlzMSA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAobiA+IDEpIHtcbiAgICAgICAgei5zcXJUbyhyLCByMik7XG4gICAgICAgIHouc3FyVG8ocjIsIHIpO1xuICAgICAgICBuIC09IDI7XG4gICAgICB9XG4gICAgICBpZiAobiA+IDApIHouc3FyVG8ociwgcjIpO1xuICAgICAgZWxzZSB7XG4gICAgICAgIHQgPSByO1xuICAgICAgICByID0gcjI7XG4gICAgICAgIHIyID0gdDtcbiAgICAgIH1cbiAgICAgIHoubXVsVG8ocjIsIGdbd10sIHIpO1xuICAgIH1cblxuICAgIHdoaWxlIChqID49IDAgJiYgKGVbal0gJiAoMSA8PCBpKSkgPT0gMCkge1xuICAgICAgei5zcXJUbyhyLCByMik7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSByMjtcbiAgICAgIHIyID0gdDtcbiAgICAgIGlmICgtLWkgPCAwKSB7XG4gICAgICAgIGkgPSB0aGlzLkRCIC0gMTtcbiAgICAgICAgLS1qO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gei5yZXZlcnQocik7XG59XG5cbi8vIChwdWJsaWMpIGdjZCh0aGlzLGEpIChIQUMgMTQuNTQpXG5cbmZ1bmN0aW9uIGJuR0NEKGEpIHtcbiAgdmFyIHggPSAodGhpcy5zIDwgMCkgPyB0aGlzLm5lZ2F0ZSgpIDogdGhpcy5jbG9uZSgpO1xuICB2YXIgeSA9IChhLnMgPCAwKSA/IGEubmVnYXRlKCkgOiBhLmNsb25lKCk7XG4gIGlmICh4LmNvbXBhcmVUbyh5KSA8IDApIHtcbiAgICB2YXIgdCA9IHg7XG4gICAgeCA9IHk7XG4gICAgeSA9IHQ7XG4gIH1cbiAgdmFyIGkgPSB4LmdldExvd2VzdFNldEJpdCgpLFxuICAgIGcgPSB5LmdldExvd2VzdFNldEJpdCgpO1xuICBpZiAoZyA8IDApIHJldHVybiB4O1xuICBpZiAoaSA8IGcpIGcgPSBpO1xuICBpZiAoZyA+IDApIHtcbiAgICB4LnJTaGlmdFRvKGcsIHgpO1xuICAgIHkuclNoaWZ0VG8oZywgeSk7XG4gIH1cbiAgd2hpbGUgKHguc2lnbnVtKCkgPiAwKSB7XG4gICAgaWYgKChpID0geC5nZXRMb3dlc3RTZXRCaXQoKSkgPiAwKSB4LnJTaGlmdFRvKGksIHgpO1xuICAgIGlmICgoaSA9IHkuZ2V0TG93ZXN0U2V0Qml0KCkpID4gMCkgeS5yU2hpZnRUbyhpLCB5KTtcbiAgICBpZiAoeC5jb21wYXJlVG8oeSkgPj0gMCkge1xuICAgICAgeC5zdWJUbyh5LCB4KTtcbiAgICAgIHguclNoaWZ0VG8oMSwgeCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHkuc3ViVG8oeCwgeSk7XG4gICAgICB5LnJTaGlmdFRvKDEsIHkpO1xuICAgIH1cbiAgfVxuICBpZiAoZyA+IDApIHkubFNoaWZ0VG8oZywgeSk7XG4gIHJldHVybiB5O1xufVxuXG4vLyAocHJvdGVjdGVkKSB0aGlzICUgbiwgbiA8IDJeMjZcblxuZnVuY3Rpb24gYm5wTW9kSW50KG4pIHtcbiAgaWYgKG4gPD0gMCkgcmV0dXJuIDA7XG4gIHZhciBkID0gdGhpcy5EViAlIG4sXG4gICAgciA9ICh0aGlzLnMgPCAwKSA/IG4gLSAxIDogMDtcbiAgaWYgKHRoaXMudCA+IDApXG4gICAgaWYgKGQgPT0gMCkgciA9IHRoaXNbMF0gJSBuO1xuICAgIGVsc2UgZm9yICh2YXIgaSA9IHRoaXMudCAtIDE7IGkgPj0gMDsgLS1pKSByID0gKGQgKiByICsgdGhpc1tpXSkgJSBuO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgMS90aGlzICUgbSAoSEFDIDE0LjYxKVxuXG5mdW5jdGlvbiBibk1vZEludmVyc2UobSkge1xuICB2YXIgYWMgPSBtLmlzRXZlbigpO1xuICBpZiAoKHRoaXMuaXNFdmVuKCkgJiYgYWMpIHx8IG0uc2lnbnVtKCkgPT0gMCkgcmV0dXJuIEJpZ0ludGVnZXIuWkVSTztcbiAgdmFyIHUgPSBtLmNsb25lKCksXG4gICAgdiA9IHRoaXMuY2xvbmUoKTtcbiAgdmFyIGEgPSBuYnYoMSksXG4gICAgYiA9IG5idigwKSxcbiAgICBjID0gbmJ2KDApLFxuICAgIGQgPSBuYnYoMSk7XG4gIHdoaWxlICh1LnNpZ251bSgpICE9IDApIHtcbiAgICB3aGlsZSAodS5pc0V2ZW4oKSkge1xuICAgICAgdS5yU2hpZnRUbygxLCB1KTtcbiAgICAgIGlmIChhYykge1xuICAgICAgICBpZiAoIWEuaXNFdmVuKCkgfHwgIWIuaXNFdmVuKCkpIHtcbiAgICAgICAgICBhLmFkZFRvKHRoaXMsIGEpO1xuICAgICAgICAgIGIuc3ViVG8obSwgYik7XG4gICAgICAgIH1cbiAgICAgICAgYS5yU2hpZnRUbygxLCBhKTtcbiAgICAgIH0gZWxzZSBpZiAoIWIuaXNFdmVuKCkpIGIuc3ViVG8obSwgYik7XG4gICAgICBiLnJTaGlmdFRvKDEsIGIpO1xuICAgIH1cbiAgICB3aGlsZSAodi5pc0V2ZW4oKSkge1xuICAgICAgdi5yU2hpZnRUbygxLCB2KTtcbiAgICAgIGlmIChhYykge1xuICAgICAgICBpZiAoIWMuaXNFdmVuKCkgfHwgIWQuaXNFdmVuKCkpIHtcbiAgICAgICAgICBjLmFkZFRvKHRoaXMsIGMpO1xuICAgICAgICAgIGQuc3ViVG8obSwgZCk7XG4gICAgICAgIH1cbiAgICAgICAgYy5yU2hpZnRUbygxLCBjKTtcbiAgICAgIH0gZWxzZSBpZiAoIWQuaXNFdmVuKCkpIGQuc3ViVG8obSwgZCk7XG4gICAgICBkLnJTaGlmdFRvKDEsIGQpO1xuICAgIH1cbiAgICBpZiAodS5jb21wYXJlVG8odikgPj0gMCkge1xuICAgICAgdS5zdWJUbyh2LCB1KTtcbiAgICAgIGlmIChhYykgYS5zdWJUbyhjLCBhKTtcbiAgICAgIGIuc3ViVG8oZCwgYik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHYuc3ViVG8odSwgdik7XG4gICAgICBpZiAoYWMpIGMuc3ViVG8oYSwgYyk7XG4gICAgICBkLnN1YlRvKGIsIGQpO1xuICAgIH1cbiAgfVxuICBpZiAodi5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpICE9IDApIHJldHVybiBCaWdJbnRlZ2VyLlpFUk87XG4gIGlmIChkLmNvbXBhcmVUbyhtKSA+PSAwKSByZXR1cm4gZC5zdWJ0cmFjdChtKTtcbiAgaWYgKGQuc2lnbnVtKCkgPCAwKSBkLmFkZFRvKG0sIGQpO1xuICBlbHNlIHJldHVybiBkO1xuICBpZiAoZC5zaWdudW0oKSA8IDApIHJldHVybiBkLmFkZChtKTtcbiAgZWxzZSByZXR1cm4gZDtcbn1cblxudmFyIGxvd3ByaW1lcyA9IFsyLCAzLCA1LCA3LCAxMSwgMTMsIDE3LCAxOSwgMjMsIDI5LCAzMSwgMzcsIDQxLCA0MywgNDcsIDUzLCA1OSwgNjEsIDY3LCA3MSwgNzMsIDc5LCA4MywgODksIDk3LCAxMDEsXG4gICAgMTAzLCAxMDcsIDEwOSwgMTEzLCAxMjcsIDEzMSwgMTM3LCAxMzksIDE0OSwgMTUxLCAxNTcsIDE2MywgMTY3LCAxNzMsIDE3OSwgMTgxLCAxOTEsIDE5MywgMTk3LCAxOTksIDIxMSwgMjIzLCAyMjcsXG4gICAgMjI5LCAyMzMsIDIzOSwgMjQxLCAyNTEsIDI1NywgMjYzLCAyNjksIDI3MSwgMjc3LCAyODEsIDI4MywgMjkzLCAzMDcsIDMxMSwgMzEzLCAzMTcsIDMzMSwgMzM3LCAzNDcsIDM0OSwgMzUzLCAzNTksXG4gICAgMzY3LCAzNzMsIDM3OSwgMzgzLCAzODksIDM5NywgNDAxLCA0MDksIDQxOSwgNDIxLCA0MzEsIDQzMywgNDM5LCA0NDMsIDQ0OSwgNDU3LCA0NjEsIDQ2MywgNDY3LCA0NzksIDQ4NywgNDkxLCA0OTksXG4gICAgNTAzLCA1MDksIDUyMSwgNTIzLCA1NDEsIDU0NywgNTU3LCA1NjMsIDU2OSwgNTcxLCA1NzcsIDU4NywgNTkzLCA1OTksIDYwMSwgNjA3LCA2MTMsIDYxNywgNjE5LCA2MzEsIDY0MSwgNjQzLCA2NDcsXG4gICAgNjUzLCA2NTksIDY2MSwgNjczLCA2NzcsIDY4MywgNjkxLCA3MDEsIDcwOSwgNzE5LCA3MjcsIDczMywgNzM5LCA3NDMsIDc1MSwgNzU3LCA3NjEsIDc2OSwgNzczLCA3ODcsIDc5NywgODA5LCA4MTEsXG4gICAgODIxLCA4MjMsIDgyNywgODI5LCA4MzksIDg1MywgODU3LCA4NTksIDg2MywgODc3LCA4ODEsIDg4MywgODg3LCA5MDcsIDkxMSwgOTE5LCA5MjksIDkzNywgOTQxLCA5NDcsIDk1MywgOTY3LCA5NzEsXG4gICAgOTc3LCA5ODMsIDk5MSwgOTk3XG5dO1xudmFyIGxwbGltID0gKDEgPDwgMjYpIC8gbG93cHJpbWVzW2xvd3ByaW1lcy5sZW5ndGggLSAxXTtcblxuLy8gKHB1YmxpYykgdGVzdCBwcmltYWxpdHkgd2l0aCBjZXJ0YWludHkgPj0gMS0uNV50XG5cbmZ1bmN0aW9uIGJuSXNQcm9iYWJsZVByaW1lKHQpIHtcbiAgdmFyIGksIHggPSB0aGlzLmFicygpO1xuICBpZiAoeC50ID09IDEgJiYgeFswXSA8PSBsb3dwcmltZXNbbG93cHJpbWVzLmxlbmd0aCAtIDFdKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IGxvd3ByaW1lcy5sZW5ndGg7ICsraSlcbiAgICAgIGlmICh4WzBdID09IGxvd3ByaW1lc1tpXSkgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICh4LmlzRXZlbigpKSByZXR1cm4gZmFsc2U7XG4gIGkgPSAxO1xuICB3aGlsZSAoaSA8IGxvd3ByaW1lcy5sZW5ndGgpIHtcbiAgICB2YXIgbSA9IGxvd3ByaW1lc1tpXSxcbiAgICAgIGogPSBpICsgMTtcbiAgICB3aGlsZSAoaiA8IGxvd3ByaW1lcy5sZW5ndGggJiYgbSA8IGxwbGltKSBtICo9IGxvd3ByaW1lc1tqKytdO1xuICAgIG0gPSB4Lm1vZEludChtKTtcbiAgICB3aGlsZSAoaSA8IGopIGlmIChtICUgbG93cHJpbWVzW2krK10gPT0gMCkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB4Lm1pbGxlclJhYmluKHQpO1xufVxuXG4vKiBhZGRlZCBieSBSZWN1cml0eSBMYWJzICovXG5cbmZ1bmN0aW9uIG5iaXRzKHgpIHtcbiAgdmFyIG4gPSAxLFxuICAgIHQ7XG4gIGlmICgodCA9IHggPj4+IDE2KSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgbiArPSAxNjtcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDgpICE9IDApIHtcbiAgICB4ID0gdDtcbiAgICBuICs9IDg7XG4gIH1cbiAgaWYgKCh0ID0geCA+PiA0KSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgbiArPSA0O1xuICB9XG4gIGlmICgodCA9IHggPj4gMikgIT0gMCkge1xuICAgIHggPSB0O1xuICAgIG4gKz0gMjtcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDEpICE9IDApIHtcbiAgICB4ID0gdDtcbiAgICBuICs9IDE7XG4gIH1cbiAgcmV0dXJuIG47XG59XG5cbmZ1bmN0aW9uIGJuVG9NUEkoKSB7XG4gIHZhciBiYSA9IHRoaXMudG9CeXRlQXJyYXkoKTtcbiAgdmFyIHNpemUgPSAoYmEubGVuZ3RoIC0gMSkgKiA4ICsgbmJpdHMoYmFbMF0pO1xuICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKHNpemUgJiAweEZGMDApID4+IDgpO1xuICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShzaXplICYgMHhGRik7XG4gIHJlc3VsdCArPSB1dGlsLmJpbjJzdHIoYmEpO1xuICByZXR1cm4gcmVzdWx0O1xufVxuLyogRU5EIG9mIGFkZGl0aW9uICovXG5cbi8vIChwcm90ZWN0ZWQpIHRydWUgaWYgcHJvYmFibHkgcHJpbWUgKEhBQyA0LjI0LCBNaWxsZXItUmFiaW4pXG5mdW5jdGlvbiBibnBNaWxsZXJSYWJpbih0KSB7XG4gIHZhciBuMSA9IHRoaXMuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpO1xuICB2YXIgayA9IG4xLmdldExvd2VzdFNldEJpdCgpO1xuICBpZiAoayA8PSAwKSByZXR1cm4gZmFsc2U7XG4gIHZhciByID0gbjEuc2hpZnRSaWdodChrKTtcbiAgdCA9ICh0ICsgMSkgPj4gMTtcbiAgaWYgKHQgPiBsb3dwcmltZXMubGVuZ3RoKSB0ID0gbG93cHJpbWVzLmxlbmd0aDtcbiAgdmFyIGEgPSBuYmkoKTtcbiAgdmFyIGosIGJhc2VzID0gW107XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdDsgKytpKSB7XG4gICAgLy9QaWNrIGJhc2VzIGF0IHJhbmRvbSwgaW5zdGVhZCBvZiBzdGFydGluZyBhdCAyXG4gICAgZm9yICg7Oykge1xuICAgICAgaiA9IGxvd3ByaW1lc1tNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBsb3dwcmltZXMubGVuZ3RoKV07XG4gICAgICBpZiAoYmFzZXMuaW5kZXhPZihqKSA9PSAtMSkgYnJlYWs7XG4gICAgfVxuICAgIGJhc2VzLnB1c2goaik7XG4gICAgYS5mcm9tSW50KGopO1xuICAgIHZhciB5ID0gYS5tb2RQb3cociwgdGhpcyk7XG4gICAgaWYgKHkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSAhPSAwICYmIHkuY29tcGFyZVRvKG4xKSAhPSAwKSB7XG4gICAgICB2YXIgaiA9IDE7XG4gICAgICB3aGlsZSAoaisrIDwgayAmJiB5LmNvbXBhcmVUbyhuMSkgIT0gMCkge1xuICAgICAgICB5ID0geS5tb2RQb3dJbnQoMiwgdGhpcyk7XG4gICAgICAgIGlmICh5LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPT0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgaWYgKHkuY29tcGFyZVRvKG4xKSAhPSAwKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4vanNibi5qcycpO1xuXG4vLyBwcm90ZWN0ZWRcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNodW5rU2l6ZSA9IGJucENodW5rU2l6ZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnRvUmFkaXggPSBibnBUb1JhZGl4O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZnJvbVJhZGl4ID0gYm5wRnJvbVJhZGl4O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZnJvbU51bWJlciA9IGJucEZyb21OdW1iZXI7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5iaXR3aXNlVG8gPSBibnBCaXR3aXNlVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jaGFuZ2VCaXQgPSBibnBDaGFuZ2VCaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hZGRUbyA9IGJucEFkZFRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZE11bHRpcGx5ID0gYm5wRE11bHRpcGx5O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZEFkZE9mZnNldCA9IGJucERBZGRPZmZzZXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tdWx0aXBseUxvd2VyVG8gPSBibnBNdWx0aXBseUxvd2VyVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tdWx0aXBseVVwcGVyVG8gPSBibnBNdWx0aXBseVVwcGVyVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tb2RJbnQgPSBibnBNb2RJbnQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5taWxsZXJSYWJpbiA9IGJucE1pbGxlclJhYmluO1xuXG4vLyBwdWJsaWNcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNsb25lID0gYm5DbG9uZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmludFZhbHVlID0gYm5JbnRWYWx1ZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmJ5dGVWYWx1ZSA9IGJuQnl0ZVZhbHVlO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc2hvcnRWYWx1ZSA9IGJuU2hvcnRWYWx1ZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnNpZ251bSA9IGJuU2lnTnVtO1xuQmlnSW50ZWdlci5wcm90b3R5cGUudG9CeXRlQXJyYXkgPSBiblRvQnl0ZUFycmF5O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZXF1YWxzID0gYm5FcXVhbHM7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5taW4gPSBibk1pbjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1heCA9IGJuTWF4O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYW5kID0gYm5BbmQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5vciA9IGJuT3I7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS54b3IgPSBiblhvcjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmFuZE5vdCA9IGJuQW5kTm90O1xuQmlnSW50ZWdlci5wcm90b3R5cGUubm90ID0gYm5Ob3Q7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zaGlmdExlZnQgPSBiblNoaWZ0TGVmdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnNoaWZ0UmlnaHQgPSBiblNoaWZ0UmlnaHQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5nZXRMb3dlc3RTZXRCaXQgPSBibkdldExvd2VzdFNldEJpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmJpdENvdW50ID0gYm5CaXRDb3VudDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnRlc3RCaXQgPSBiblRlc3RCaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zZXRCaXQgPSBiblNldEJpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNsZWFyQml0ID0gYm5DbGVhckJpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmZsaXBCaXQgPSBibkZsaXBCaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hZGQgPSBibkFkZDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnN1YnRyYWN0ID0gYm5TdWJ0cmFjdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm11bHRpcGx5ID0gYm5NdWx0aXBseTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRpdmlkZSA9IGJuRGl2aWRlO1xuQmlnSW50ZWdlci5wcm90b3R5cGUucmVtYWluZGVyID0gYm5SZW1haW5kZXI7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kaXZpZGVBbmRSZW1haW5kZXIgPSBibkRpdmlkZUFuZFJlbWFpbmRlcjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1vZFBvdyA9IGJuTW9kUG93O1xuQmlnSW50ZWdlci5wcm90b3R5cGUubW9kSW52ZXJzZSA9IGJuTW9kSW52ZXJzZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnBvdyA9IGJuUG93O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZ2NkID0gYm5HQ0Q7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5pc1Byb2JhYmxlUHJpbWUgPSBibklzUHJvYmFibGVQcmltZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnRvTVBJID0gYm5Ub01QSTtcblxuLy8gSlNCTi1zcGVjaWZpYyBleHRlbnNpb25cbkJpZ0ludGVnZXIucHJvdG90eXBlLnNxdWFyZSA9IGJuU3F1YXJlO1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0Fcbi8vXG4vLyBSU0EgaW1wbGVtZW50YXRpb25cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2pzYm4uanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKSxcbiAgcmFuZG9tID0gcmVxdWlyZSgnLi4vcmFuZG9tLmpzJyk7XG5cbmZ1bmN0aW9uIFNlY3VyZVJhbmRvbSgpIHtcbiAgZnVuY3Rpb24gbmV4dEJ5dGVzKGJ5dGVBcnJheSkge1xuICAgIGZvciAodmFyIG4gPSAwOyBuIDwgYnl0ZUFycmF5Lmxlbmd0aDsgbisrKSB7XG4gICAgICBieXRlQXJyYXlbbl0gPSByYW5kb20uZ2V0U2VjdXJlUmFuZG9tT2N0ZXQoKTtcbiAgICB9XG4gIH1cbiAgdGhpcy5uZXh0Qnl0ZXMgPSBuZXh0Qnl0ZXM7XG59XG5cbmZ1bmN0aW9uIFJTQSgpIHtcbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gdXNlcyBqc2JuIEJpZyBOdW0gbGlicmFyeSB0byBkZWNyeXB0IFJTQVxuICAgKiBAcGFyYW0gbVxuICAgKiAgICAgICAgICAgIG1lc3NhZ2VcbiAgICogQHBhcmFtIGRcbiAgICogICAgICAgICAgICBSU0EgZCBhcyBCaWdJbnRlZ2VyXG4gICAqIEBwYXJhbSBwXG4gICAqICAgICAgICAgICAgUlNBIHAgYXMgQmlnSW50ZWdlclxuICAgKiBAcGFyYW0gcVxuICAgKiAgICAgICAgICAgIFJTQSBxIGFzIEJpZ0ludGVnZXJcbiAgICogQHBhcmFtIHVcbiAgICogICAgICAgICAgICBSU0EgdSBhcyBCaWdJbnRlZ2VyXG4gICAqIEByZXR1cm4ge0JpZ0ludGVnZXJ9IFRoZSBkZWNyeXB0ZWQgdmFsdWUgb2YgdGhlIG1lc3NhZ2VcbiAgICovXG4gIGZ1bmN0aW9uIGRlY3J5cHQobSwgZCwgcCwgcSwgdSkge1xuICAgIHZhciB4cCA9IG0ubW9kKHApLm1vZFBvdyhkLm1vZChwLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKSksIHApO1xuICAgIHZhciB4cSA9IG0ubW9kKHEpLm1vZFBvdyhkLm1vZChxLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKSksIHEpO1xuICAgIHV0aWwucHJpbnRfZGVidWcoXCJyc2EuanMgZGVjcnlwdFxcbnhwbjpcIiArIHV0aWwuaGV4c3RyZHVtcCh4cC50b01QSSgpKSArIFwiXFxueHFuOlwiICsgdXRpbC5oZXhzdHJkdW1wKHhxLnRvTVBJKCkpKTtcblxuICAgIHZhciB0ID0geHEuc3VidHJhY3QoeHApO1xuICAgIGlmICh0WzBdID09IDApIHtcbiAgICAgIHQgPSB4cC5zdWJ0cmFjdCh4cSk7XG4gICAgICB0ID0gdC5tdWx0aXBseSh1KS5tb2QocSk7XG4gICAgICB0ID0gcS5zdWJ0cmFjdCh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdCA9IHQubXVsdGlwbHkodSkubW9kKHEpO1xuICAgIH1cbiAgICByZXR1cm4gdC5tdWx0aXBseShwKS5hZGQoeHApO1xuICB9XG5cbiAgLyoqXG4gICAqIGVuY3J5cHQgbWVzc2FnZVxuICAgKiBAcGFyYW0gbSBtZXNzYWdlIGFzIEJpZ0ludGVnZXJcbiAgICogQHBhcmFtIGUgcHVibGljIE1QSSBwYXJ0IGFzIEJpZ0ludGVnZXJcbiAgICogQHBhcmFtIG4gcHVibGljIE1QSSBwYXJ0IGFzIEJpZ0ludGVnZXJcbiAgICogQHJldHVybiBCaWdJbnRlZ2VyXG4gICAqL1xuICBmdW5jdGlvbiBlbmNyeXB0KG0sIGUsIG4pIHtcbiAgICByZXR1cm4gbS5tb2RQb3dJbnQoZSwgbik7XG4gIH1cblxuICAvKiBTaWduIGFuZCBWZXJpZnkgKi9cbiAgZnVuY3Rpb24gc2lnbihtLCBkLCBuKSB7XG4gICAgcmV0dXJuIG0ubW9kUG93KGQsIG4pO1xuICB9XG5cbiAgZnVuY3Rpb24gdmVyaWZ5KHgsIGUsIG4pIHtcbiAgICByZXR1cm4geC5tb2RQb3dJbnQoZSwgbik7XG4gIH1cblxuICAvLyBcImVtcHR5XCIgUlNBIGtleSBjb25zdHJ1Y3RvclxuXG4gIGZ1bmN0aW9uIGtleU9iamVjdCgpIHtcbiAgICB0aGlzLm4gPSBudWxsO1xuICAgIHRoaXMuZSA9IDA7XG4gICAgdGhpcy5lZSA9IG51bGw7XG4gICAgdGhpcy5kID0gbnVsbDtcbiAgICB0aGlzLnAgPSBudWxsO1xuICAgIHRoaXMucSA9IG51bGw7XG4gICAgdGhpcy5kbXAxID0gbnVsbDtcbiAgICB0aGlzLmRtcTEgPSBudWxsO1xuICAgIHRoaXMudSA9IG51bGw7XG4gIH1cblxuICAvLyBHZW5lcmF0ZSBhIG5ldyByYW5kb20gcHJpdmF0ZSBrZXkgQiBiaXRzIGxvbmcsIHVzaW5nIHB1YmxpYyBleHB0IEVcblxuICBmdW5jdGlvbiBnZW5lcmF0ZShCLCBFKSB7XG4gICAgdmFyIGtleSA9IG5ldyBrZXlPYmplY3QoKTtcbiAgICB2YXIgcm5nID0gbmV3IFNlY3VyZVJhbmRvbSgpO1xuICAgIHZhciBxcyA9IEIgPj4gMTtcbiAgICBrZXkuZSA9IHBhcnNlSW50KEUsIDE2KTtcbiAgICBrZXkuZWUgPSBuZXcgQmlnSW50ZWdlcihFLCAxNik7XG4gICAgZm9yICg7Oykge1xuICAgICAgZm9yICg7Oykge1xuICAgICAgICBrZXkucCA9IG5ldyBCaWdJbnRlZ2VyKEIgLSBxcywgMSwgcm5nKTtcbiAgICAgICAgaWYgKGtleS5wLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKS5nY2Qoa2V5LmVlKS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpID09IDAgJiYga2V5LnAuaXNQcm9iYWJsZVByaW1lKDEwKSlcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGZvciAoOzspIHtcbiAgICAgICAga2V5LnEgPSBuZXcgQmlnSW50ZWdlcihxcywgMSwgcm5nKTtcbiAgICAgICAgaWYgKGtleS5xLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKS5nY2Qoa2V5LmVlKS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpID09IDAgJiYga2V5LnEuaXNQcm9iYWJsZVByaW1lKDEwKSlcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChrZXkucC5jb21wYXJlVG8oa2V5LnEpIDw9IDApIHtcbiAgICAgICAgdmFyIHQgPSBrZXkucDtcbiAgICAgICAga2V5LnAgPSBrZXkucTtcbiAgICAgICAga2V5LnEgPSB0O1xuICAgICAgfVxuICAgICAgdmFyIHAxID0ga2V5LnAuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpO1xuICAgICAgdmFyIHExID0ga2V5LnEuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpO1xuICAgICAgdmFyIHBoaSA9IHAxLm11bHRpcGx5KHExKTtcbiAgICAgIGlmIChwaGkuZ2NkKGtleS5lZSkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA9PSAwKSB7XG4gICAgICAgIGtleS5uID0ga2V5LnAubXVsdGlwbHkoa2V5LnEpO1xuICAgICAgICBrZXkuZCA9IGtleS5lZS5tb2RJbnZlcnNlKHBoaSk7XG4gICAgICAgIGtleS5kbXAxID0ga2V5LmQubW9kKHAxKTtcbiAgICAgICAga2V5LmRtcTEgPSBrZXkuZC5tb2QocTEpO1xuICAgICAgICBrZXkudSA9IGtleS5wLm1vZEludmVyc2Uoa2V5LnEpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGtleTtcbiAgfVxuXG4gIHRoaXMuZW5jcnlwdCA9IGVuY3J5cHQ7XG4gIHRoaXMuZGVjcnlwdCA9IGRlY3J5cHQ7XG4gIHRoaXMudmVyaWZ5ID0gdmVyaWZ5O1xuICB0aGlzLnNpZ24gPSBzaWduO1xuICB0aGlzLmdlbmVyYXRlID0gZ2VuZXJhdGU7XG4gIHRoaXMua2V5T2JqZWN0ID0ga2V5T2JqZWN0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFJTQTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBIFxuXG4vLyBUaGUgR1BHNEJyb3dzZXJzIGNyeXB0byBpbnRlcmZhY2VcblxudmFyIHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIC8qKlxuICAgKiBSZXRyaWV2ZSBzZWN1cmUgcmFuZG9tIGJ5dGUgc3RyaW5nIG9mIHRoZSBzcGVjaWZpZWQgbGVuZ3RoXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuZ3RoIExlbmd0aCBpbiBieXRlcyB0byBnZW5lcmF0ZVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFJhbmRvbSBieXRlIHN0cmluZ1xuICAgKi9cbiAgZ2V0UmFuZG9tQnl0ZXM6IGZ1bmN0aW9uKGxlbmd0aCkge1xuICAgIHZhciByZXN1bHQgPSAnJztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLmdldFNlY3VyZVJhbmRvbU9jdGV0KCkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBwc2V1ZG8tcmFuZG9tIG51bWJlciBpbiB0aGUgc3BlY2lmaWVkIHJhbmdlXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gZnJvbSBNaW4gb2YgdGhlIHJhbmRvbSBudW1iZXJcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSB0byBNYXggb2YgdGhlIHJhbmRvbSBudW1iZXIgKG1heCAzMmJpdClcbiAgICogQHJldHVybiB7SW50ZWdlcn0gQSBwc2V1ZG8gcmFuZG9tIG51bWJlclxuICAgKi9cbiAgZ2V0UHNldWRvUmFuZG9tOiBmdW5jdGlvbihmcm9tLCB0bykge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKE1hdGgucmFuZG9tKCkgKiAodG8gLSBmcm9tKSkgKyBmcm9tO1xuICB9LFxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBzZWN1cmUgcmFuZG9tIG51bWJlciBpbiB0aGUgc3BlY2lmaWVkIHJhbmdlXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gZnJvbSBNaW4gb2YgdGhlIHJhbmRvbSBudW1iZXJcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSB0byBNYXggb2YgdGhlIHJhbmRvbSBudW1iZXIgKG1heCAzMmJpdClcbiAgICogQHJldHVybiB7SW50ZWdlcn0gQSBzZWN1cmUgcmFuZG9tIG51bWJlclxuICAgKi9cbiAgZ2V0U2VjdXJlUmFuZG9tOiBmdW5jdGlvbihmcm9tLCB0bykge1xuICAgIHZhciBidWYgPSBuZXcgVWludDMyQXJyYXkoMSk7XG4gICAgd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYnVmKTtcbiAgICB2YXIgYml0cyA9ICgodG8gLSBmcm9tKSkudG9TdHJpbmcoMikubGVuZ3RoO1xuICAgIHdoaWxlICgoYnVmWzBdICYgKE1hdGgucG93KDIsIGJpdHMpIC0gMSkpID4gKHRvIC0gZnJvbSkpXG4gICAgICB3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhidWYpO1xuICAgIHJldHVybiBmcm9tICsgKE1hdGguYWJzKGJ1ZlswXSAmIChNYXRoLnBvdygyLCBiaXRzKSAtIDEpKSk7XG4gIH0sXG5cbiAgZ2V0U2VjdXJlUmFuZG9tT2N0ZXQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBidWYgPSBuZXcgVWludDMyQXJyYXkoMSk7XG4gICAgd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYnVmKTtcbiAgICByZXR1cm4gYnVmWzBdICYgMHhGRjtcbiAgfSxcblxuICAvKipcbiAgICogQ3JlYXRlIGEgc2VjdXJlIHJhbmRvbSBiaWcgaW50ZWdlciBvZiBiaXRzIGxlbmd0aFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGJpdHMgQml0IGxlbmd0aCBvZiB0aGUgTVBJIHRvIGNyZWF0ZVxuICAgKiBAcmV0dXJuIHtCaWdJbnRlZ2VyfSBSZXN1bHRpbmcgYmlnIGludGVnZXJcbiAgICovXG4gIGdldFJhbmRvbUJpZ0ludGVnZXI6IGZ1bmN0aW9uKGJpdHMpIHtcbiAgICBpZiAoYml0cyA8IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB2YXIgbnVtQnl0ZXMgPSBNYXRoLmZsb29yKChiaXRzICsgNykgLyA4KTtcblxuICAgIHZhciByYW5kb21CaXRzID0gdGhpcy5nZXRSYW5kb21CeXRlcyhudW1CeXRlcyk7XG4gICAgaWYgKGJpdHMgJSA4ID4gMCkge1xuXG4gICAgICByYW5kb21CaXRzID0gU3RyaW5nLmZyb21DaGFyQ29kZShcbiAgICAgIChNYXRoLnBvdygyLCBiaXRzICUgOCkgLSAxKSAmXG4gICAgICAgIHJhbmRvbUJpdHMuY2hhckNvZGVBdCgwKSkgK1xuICAgICAgICByYW5kb21CaXRzLnN1YnN0cmluZygxKTtcbiAgICB9XG4gICAgdmFyIG1waSA9IG5ldyB0eXBlX21waSgpO1xuICAgIG1waS5mcm9tQnl0ZXMocmFuZG9tQml0cyk7XG4gICAgcmV0dXJuIG1waS50b0JpZ0ludGVnZXIoKTtcbiAgfSxcblxuICBnZXRSYW5kb21CaWdJbnRlZ2VySW5SYW5nZTogZnVuY3Rpb24obWluLCBtYXgpIHtcbiAgICBpZiAobWF4LmNvbXBhcmVUbyhtaW4pIDw9IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgcmFuZ2UgPSBtYXguc3VidHJhY3QobWluKTtcbiAgICB2YXIgciA9IHRoaXMuZ2V0UmFuZG9tQmlnSW50ZWdlcihyYW5nZS5iaXRMZW5ndGgoKSk7XG4gICAgd2hpbGUgKHIgPiByYW5nZSkge1xuICAgICAgciA9IHRoaXMuZ2V0UmFuZG9tQmlnSW50ZWdlcihyYW5nZS5iaXRMZW5ndGgoKSk7XG4gICAgfVxuICAgIHJldHVybiBtaW4uYWRkKHIpO1xuICB9XG5cbn07XG4iLCJ2YXIgcHVibGljS2V5ID0gcmVxdWlyZSgnLi9wdWJsaWNfa2V5JyksXG4gIHBrY3MxID0gcmVxdWlyZSgnLi9wa2NzMS5qcycpLFxuICBoYXNoTW9kdWxlID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAvKipcbiAgICogXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gYWxnbyBwdWJsaWMgS2V5IGFsZ29yaXRobVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGhhc2hfYWxnbyBIYXNoIGFsZ29yaXRobVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gbXNnX01QSXMgU2lnbmF0dXJlIG11bHRpcHJlY2lzaW9uIGludGVnZXJzXG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBwdWJsaWNrZXlfTVBJcyBQdWJsaWMga2V5IG11bHRpcHJlY2lzaW9uIGludGVnZXJzIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIG9uIHdoZXJlIHRoZSBzaWduYXR1cmUgd2FzIGNvbXB1dGVkIG9uLlxuICAgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHNpZ25hdHVyZSAoc2lnX2RhdGEgd2FzIGVxdWFsIHRvIGRhdGEgb3ZlciBoYXNoKVxuICAgKi9cbiAgdmVyaWZ5OiBmdW5jdGlvbihhbGdvLCBoYXNoX2FsZ28sIG1zZ19NUElzLCBwdWJsaWNrZXlfTVBJcywgZGF0YSkge1xuICAgIHZhciBjYWxjX2hhc2ggPSBoYXNoTW9kdWxlLmRpZ2VzdChoYXNoX2FsZ28sIGRhdGEpO1xuXG4gICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIC8vIFJTQSAoRW5jcnlwdCBvciBTaWduKSBbSEFDXSAgXG4gICAgICBjYXNlIDI6XG4gICAgICAgIC8vIFJTQSBFbmNyeXB0LU9ubHkgW0hBQ11cbiAgICAgIGNhc2UgMzpcbiAgICAgICAgLy8gUlNBIFNpZ24tT25seSBbSEFDXVxuICAgICAgICB2YXIgcnNhID0gbmV3IHB1YmxpY0tleS5yc2EoKTtcbiAgICAgICAgdmFyIG4gPSBwdWJsaWNrZXlfTVBJc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIGUgPSBwdWJsaWNrZXlfTVBJc1sxXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHggPSBtc2dfTVBJc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIGRvcHVibGljID0gcnNhLnZlcmlmeSh4LCBlLCBuKTtcbiAgICAgICAgdmFyIGhhc2ggPSBwa2NzMS5lbXNhLmRlY29kZShoYXNoX2FsZ28sIGRvcHVibGljLnRvTVBJKCkuc3Vic3RyaW5nKDIpKTtcbiAgICAgICAgaWYgKGhhc2ggPT0gLTEpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BLQ1MxIHBhZGRpbmcgaW4gbWVzc2FnZSBvciBrZXkgaW5jb3JyZWN0LiBBYm9ydGluZy4uLicpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBoYXNoID09IGNhbGNfaGFzaDtcblxuICAgICAgY2FzZSAxNjpcbiAgICAgICAgLy8gRWxnYW1hbCAoRW5jcnlwdC1Pbmx5KSBbRUxHQU1BTF0gW0hBQ11cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2lnbmluZyB3aXRoIEVsZ2FtYWwgaXMgbm90IGRlZmluZWQgaW4gdGhlIE9wZW5QR1Agc3RhbmRhcmQuXCIpO1xuICAgICAgY2FzZSAxNzpcbiAgICAgICAgLy8gRFNBIChEaWdpdGFsIFNpZ25hdHVyZSBBbGdvcml0aG0pIFtGSVBTMTg2XSBbSEFDXVxuICAgICAgICB2YXIgZHNhID0gbmV3IHB1YmxpY0tleS5kc2EoKTtcbiAgICAgICAgdmFyIHMxID0gbXNnX01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgIHZhciBzMiA9IG1zZ19NUElzWzFdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgcCA9IHB1YmxpY2tleV9NUElzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgcSA9IHB1YmxpY2tleV9NUElzWzFdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgZyA9IHB1YmxpY2tleV9NUElzWzJdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgeSA9IHB1YmxpY2tleV9NUElzWzNdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgbSA9IGRhdGE7XG4gICAgICAgIHZhciBkb3B1YmxpYyA9IGRzYS52ZXJpZnkoaGFzaF9hbGdvLCBzMSwgczIsIG0sIHAsIHEsIGcsIHkpO1xuICAgICAgICByZXR1cm4gZG9wdWJsaWMuY29tcGFyZVRvKHMxKSA9PSAwO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpZ25hdHVyZSBhbGdvcml0aG0uJyk7XG4gICAgfVxuXG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHNpZ25hdHVyZSBvbiBkYXRhIHVzaW5nIHRoZSBzcGVjaWZpZWQgYWxnb3JpdGhtXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaGFzaF9hbGdvIGhhc2ggQWxnb3JpdGhtIHRvIHVzZSAoU2VlIFJGQzQ4ODAgOS40KVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQXN5bW1ldHJpYyBjaXBoZXIgYWxnb3JpdGhtIHRvIHVzZSAoU2VlIFJGQzQ4ODAgOS4xKVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gcHVibGljTVBJcyBQdWJsaWMga2V5IG11bHRpcHJlY2lzaW9uIGludGVnZXJzIFxuICAgKiBvZiB0aGUgcHJpdmF0ZSBrZXkgXG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBzZWNyZXRNUElzIFByaXZhdGUga2V5IG11bHRpcHJlY2lzaW9uIFxuICAgKiBpbnRlZ2VycyB3aGljaCBpcyB1c2VkIHRvIHNpZ24gdGhlIGRhdGFcbiAgICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBiZSBzaWduZWRcbiAgICogQHJldHVybiB7b3BlbnBncF90eXBlX21waVtdfVxuICAgKi9cbiAgc2lnbjogZnVuY3Rpb24oaGFzaF9hbGdvLCBhbGdvLCBrZXlJbnRlZ2VycywgZGF0YSkge1xuXG4gICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIC8vIFJTQSAoRW5jcnlwdCBvciBTaWduKSBbSEFDXSAgXG4gICAgICBjYXNlIDI6XG4gICAgICAgIC8vIFJTQSBFbmNyeXB0LU9ubHkgW0hBQ11cbiAgICAgIGNhc2UgMzpcbiAgICAgICAgLy8gUlNBIFNpZ24tT25seSBbSEFDXVxuICAgICAgICB2YXIgcnNhID0gbmV3IHB1YmxpY0tleS5yc2EoKTtcbiAgICAgICAgdmFyIGQgPSBrZXlJbnRlZ2Vyc1syXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIG4gPSBrZXlJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIG0gPSBwa2NzMS5lbXNhLmVuY29kZShoYXNoX2FsZ28sXG4gICAgICAgICAgZGF0YSwga2V5SW50ZWdlcnNbMF0uYnl0ZUxlbmd0aCgpKTtcblxuICAgICAgICByZXR1cm4gcnNhLnNpZ24obSwgZCwgbikudG9NUEkoKTtcblxuICAgICAgY2FzZSAxNzpcbiAgICAgICAgLy8gRFNBIChEaWdpdGFsIFNpZ25hdHVyZSBBbGdvcml0aG0pIFtGSVBTMTg2XSBbSEFDXVxuICAgICAgICB2YXIgZHNhID0gbmV3IHB1YmxpY0tleS5kc2EoKTtcblxuICAgICAgICB2YXIgcCA9IGtleUludGVnZXJzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgcSA9IGtleUludGVnZXJzWzFdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgZyA9IGtleUludGVnZXJzWzJdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgeSA9IGtleUludGVnZXJzWzNdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgeCA9IGtleUludGVnZXJzWzRdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgbSA9IGRhdGE7XG4gICAgICAgIHZhciByZXN1bHQgPSBkc2Euc2lnbihoYXNoX2FsZ28sIG0sIGcsIHAsIHEsIHgpO1xuXG4gICAgICAgIHJldHVybiByZXN1bHRbMF0udG9TdHJpbmcoKSArIHJlc3VsdFsxXS50b1N0cmluZygpO1xuICAgICAgY2FzZSAxNjpcbiAgICAgICAgLy8gRWxnYW1hbCAoRW5jcnlwdC1Pbmx5KSBbRUxHQU1BTF0gW0hBQ11cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaWduaW5nIHdpdGggRWxnYW1hbCBpcyBub3QgZGVmaW5lZCBpbiB0aGUgT3BlblBHUCBzdGFuZGFyZC4nKTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzaWduYXR1cmUgYWxnb3JpdGhtLicpO1xuICAgIH1cbiAgfVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vL1xuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGJhc2U2NCA9IHJlcXVpcmUoJy4vYmFzZTY0LmpzJyk7XG52YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpO1xudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4uL2NvbmZpZycpO1xuXG4vKipcbiAqIEZpbmRzIG91dCB3aGljaCBBc2NpaSBBcm1vcmluZyB0eXBlIGlzIHVzZWQuIFRoaXMgaXMgYW4gaW50ZXJuYWwgZnVuY3Rpb25cbiAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0IFtTdHJpbmddIGFzY2lpIGFybW9yZWQgdGV4dFxuICogQHJldHVybnMge0ludGVnZXJ9IDAgPSBNRVNTQUdFIFBBUlQgbiBvZiBtXG4gKiAgICAgICAgIDEgPSBNRVNTQUdFIFBBUlQgblxuICogICAgICAgICAyID0gU0lHTkVEIE1FU1NBR0VcbiAqICAgICAgICAgMyA9IFBHUCBNRVNTQUdFXG4gKiAgICAgICAgIDQgPSBQVUJMSUMgS0VZIEJMT0NLXG4gKiAgICAgICAgIDUgPSBQUklWQVRFIEtFWSBCTE9DS1xuICogICAgICAgICBudWxsID0gdW5rbm93blxuICovXG5mdW5jdGlvbiBnZXRfdHlwZSh0ZXh0KSB7XG4gIHZhciBzcGxpdHRlZHRleHQgPSB0ZXh0LnNwbGl0KCctLS0tLScpO1xuICAvLyBCRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBYL1lcbiAgLy8gVXNlZCBmb3IgbXVsdGktcGFydCBtZXNzYWdlcywgd2hlcmUgdGhlIGFybW9yIGlzIHNwbGl0IGFtb25nc3QgWVxuICAvLyBwYXJ0cywgYW5kIHRoaXMgaXMgdGhlIFh0aCBwYXJ0IG91dCBvZiBZLlxuICBpZiAoc3BsaXR0ZWR0ZXh0WzFdLm1hdGNoKC9CRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBcXGQrXFwvXFxkKy8pKSB7XG4gICAgcmV0dXJuIGVudW1zLmFybW9yLm11bHRpcGFydF9zZWN0aW9uO1xuICB9IGVsc2VcbiAgLy8gQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgWFxuICAvLyBVc2VkIGZvciBtdWx0aS1wYXJ0IG1lc3NhZ2VzLCB3aGVyZSB0aGlzIGlzIHRoZSBYdGggcGFydCBvZiBhblxuICAvLyB1bnNwZWNpZmllZCBudW1iZXIgb2YgcGFydHMuIFJlcXVpcmVzIHRoZSBNRVNTQUdFLUlEIEFybW9yXG4gIC8vIEhlYWRlciB0byBiZSB1c2VkLlxuICBpZiAoc3BsaXR0ZWR0ZXh0WzFdLm1hdGNoKC9CRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBcXGQrLykpIHtcbiAgICByZXR1cm4gZW51bXMuYXJtb3IubXVsdGlwYXJ0X2xhc3Q7XG5cbiAgfSBlbHNlXG4gIC8vIEJFR0lOIFBHUCBTSUdOQVRVUkVcbiAgLy8gVXNlZCBmb3IgZGV0YWNoZWQgc2lnbmF0dXJlcywgT3BlblBHUC9NSU1FIHNpZ25hdHVyZXMsIGFuZFxuICAvLyBjbGVhcnRleHQgc2lnbmF0dXJlcy4gTm90ZSB0aGF0IFBHUCAyLnggdXNlcyBCRUdJTiBQR1AgTUVTU0FHRVxuICAvLyBmb3IgZGV0YWNoZWQgc2lnbmF0dXJlcy5cbiAgaWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIFNJR05FRCBNRVNTQUdFLykpIHtcbiAgICByZXR1cm4gZW51bXMuYXJtb3Iuc2lnbmVkO1xuXG4gIH0gZWxzZVxuICAvLyBCRUdJTiBQR1AgTUVTU0FHRVxuICAvLyBVc2VkIGZvciBzaWduZWQsIGVuY3J5cHRlZCwgb3IgY29tcHJlc3NlZCBmaWxlcy5cbiAgaWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIE1FU1NBR0UvKSkge1xuICAgIHJldHVybiBlbnVtcy5hcm1vci5tZXNzYWdlO1xuXG4gIH0gZWxzZVxuICAvLyBCRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DS1xuICAvLyBVc2VkIGZvciBhcm1vcmluZyBwdWJsaWMga2V5cy5cbiAgaWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0svKSkge1xuICAgIHJldHVybiBlbnVtcy5hcm1vci5wdWJsaWNfa2V5O1xuXG4gIH0gZWxzZVxuICAvLyBCRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0tcbiAgLy8gVXNlZCBmb3IgYXJtb3JpbmcgcHJpdmF0ZSBrZXlzLlxuICBpZiAoc3BsaXR0ZWR0ZXh0WzFdLm1hdGNoKC9CRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0svKSkge1xuICAgIHJldHVybiBlbnVtcy5hcm1vci5wcml2YXRlX2tleTtcbiAgfVxufVxuXG4vKipcbiAqIEFkZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHRvIHRoZSBhcm1vciB2ZXJzaW9uIG9mIGFuIE9wZW5QR1AgYmluYXJ5XG4gKiBwYWNrZXQgYmxvY2suXG4gKiBAYXV0aG9yICBBbGV4XG4gKiBAdmVyc2lvbiAyMDExLTEyLTE2XG4gKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgaGVhZGVyIGluZm9ybWF0aW9uXG4gKi9cbmZ1bmN0aW9uIGFybW9yX2FkZGhlYWRlcigpIHtcbiAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gIGlmIChjb25maWcuc2hvd192ZXJzaW9uKSB7XG4gICAgcmVzdWx0ICs9IFwiVmVyc2lvbjogXCIgKyBjb25maWcudmVyc2lvbnN0cmluZyArICdcXHJcXG4nO1xuICB9XG4gIGlmIChjb25maWcuc2hvd19jb21tZW50KSB7XG4gICAgcmVzdWx0ICs9IFwiQ29tbWVudDogXCIgKyBjb25maWcuY29tbWVudHN0cmluZyArICdcXHJcXG4nO1xuICB9XG4gIHJlc3VsdCArPSAnXFxyXFxuJztcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuXG5cbi8qKlxuICogQ2FsY3VsYXRlcyBhIGNoZWNrc3VtIG92ZXIgdGhlIGdpdmVuIGRhdGEgYW5kIHJldHVybnMgaXQgYmFzZTY0IGVuY29kZWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIERhdGEgdG8gY3JlYXRlIGEgQ1JDLTI0IGNoZWNrc3VtIGZvclxuICogQHJldHVybiB7U3RyaW5nfSBCYXNlNjQgZW5jb2RlZCBjaGVja3N1bVxuICovXG5mdW5jdGlvbiBnZXRDaGVja1N1bShkYXRhKSB7XG4gIHZhciBjID0gY3JlYXRlY3JjMjQoZGF0YSk7XG4gIHZhciBzdHIgPSBcIlwiICsgU3RyaW5nLmZyb21DaGFyQ29kZShjID4+IDE2KSArXG4gICAgU3RyaW5nLmZyb21DaGFyQ29kZSgoYyA+PiA4KSAmIDB4RkYpICtcbiAgICBTdHJpbmcuZnJvbUNoYXJDb2RlKGMgJiAweEZGKTtcbiAgcmV0dXJuIGJhc2U2NC5lbmNvZGUoc3RyKTtcbn1cblxuLyoqXG4gKiBDYWxjdWxhdGVzIHRoZSBjaGVja3N1bSBvdmVyIHRoZSBnaXZlbiBkYXRhIGFuZCBjb21wYXJlcyBpdCB3aXRoIHRoZSBcbiAqIGdpdmVuIGJhc2U2NCBlbmNvZGVkIGNoZWNrc3VtXG4gKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIHRvIGNyZWF0ZSBhIENSQy0yNCBjaGVja3N1bSBmb3JcbiAqIEBwYXJhbSB7U3RyaW5nfSBjaGVja3N1bSBCYXNlNjQgZW5jb2RlZCBjaGVja3N1bVxuICogQHJldHVybiB7Qm9vbGVhbn0gVHJ1ZSBpZiB0aGUgZ2l2ZW4gY2hlY2tzdW0gaXMgY29ycmVjdDsgb3RoZXJ3aXNlIGZhbHNlXG4gKi9cbmZ1bmN0aW9uIHZlcmlmeUNoZWNrU3VtKGRhdGEsIGNoZWNrc3VtKSB7XG4gIHZhciBjID0gZ2V0Q2hlY2tTdW0oZGF0YSk7XG4gIHZhciBkID0gY2hlY2tzdW07XG4gIHJldHVybiBjWzBdID09IGRbMF0gJiYgY1sxXSA9PSBkWzFdICYmIGNbMl0gPT0gZFsyXTtcbn1cbi8qKlxuICogSW50ZXJuYWwgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIGEgQ1JDLTI0IGNoZWNrc3VtIG92ZXIgYSBnaXZlbiBzdHJpbmcgKGRhdGEpXG4gKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIHRvIGNyZWF0ZSBhIENSQy0yNCBjaGVja3N1bSBmb3JcbiAqIEByZXR1cm4ge0ludGVnZXJ9IFRoZSBDUkMtMjQgY2hlY2tzdW0gYXMgbnVtYmVyXG4gKi9cbnZhciBjcmNfdGFibGUgPSBbXG4gICAgMHgwMDAwMDAwMCwgMHgwMDg2NGNmYiwgMHgwMThhZDUwZCwgMHgwMTBjOTlmNiwgMHgwMzkzZTZlMSwgMHgwMzE1YWExYSwgMHgwMjE5MzNlYywgMHgwMjlmN2YxNywgMHgwN2ExODEzOSxcbiAgICAweDA3MjdjZGMyLCAweDA2MmI1NDM0LCAweDA2YWQxOGNmLCAweDA0MzI2N2Q4LCAweDA0YjQyYjIzLCAweDA1YjhiMmQ1LCAweDA1M2VmZTJlLCAweDBmYzU0ZTg5LCAweDBmNDMwMjcyLFxuICAgIDB4MGU0ZjliODQsIDB4MGVjOWQ3N2YsIDB4MGM1NmE4NjgsIDB4MGNkMGU0OTMsIDB4MGRkYzdkNjUsIDB4MGQ1YTMxOWUsIDB4MDg2NGNmYjAsIDB4MDhlMjgzNGIsIDB4MDllZTFhYmQsXG4gICAgMHgwOTY4NTY0NiwgMHgwYmY3Mjk1MSwgMHgwYjcxNjVhYSwgMHgwYTdkZmM1YywgMHgwYWZiYjBhNywgMHgxZjBjZDFlOSwgMHgxZjhhOWQxMiwgMHgxZTg2MDRlNCwgMHgxZTAwNDgxZixcbiAgICAweDFjOWYzNzA4LCAweDFjMTk3YmYzLCAweDFkMTVlMjA1LCAweDFkOTNhZWZlLCAweDE4YWQ1MGQwLCAweDE4MmIxYzJiLCAweDE5Mjc4NWRkLCAweDE5YTFjOTI2LCAweDFiM2ViNjMxLFxuICAgIDB4MWJiOGZhY2EsIDB4MWFiNDYzM2MsIDB4MWEzMjJmYzcsIDB4MTBjOTlmNjAsIDB4MTA0ZmQzOWIsIDB4MTE0MzRhNmQsIDB4MTFjNTA2OTYsIDB4MTM1YTc5ODEsIDB4MTNkYzM1N2EsXG4gICAgMHgxMmQwYWM4YywgMHgxMjU2ZTA3NywgMHgxNzY4MWU1OSwgMHgxN2VlNTJhMiwgMHgxNmUyY2I1NCwgMHgxNjY0ODdhZiwgMHgxNGZiZjhiOCwgMHgxNDdkYjQ0MywgMHgxNTcxMmRiNSxcbiAgICAweDE1Zjc2MTRlLCAweDNlMTlhM2QyLCAweDNlOWZlZjI5LCAweDNmOTM3NmRmLCAweDNmMTUzYTI0LCAweDNkOGE0NTMzLCAweDNkMGMwOWM4LCAweDNjMDA5MDNlLCAweDNjODZkY2M1LFxuICAgIDB4MzliODIyZWIsIDB4MzkzZTZlMTAsIDB4MzgzMmY3ZTYsIDB4MzhiNGJiMWQsIDB4M2EyYmM0MGEsIDB4M2FhZDg4ZjEsIDB4M2JhMTExMDcsIDB4M2IyNzVkZmMsIDB4MzFkY2VkNWIsXG4gICAgMHgzMTVhYTFhMCxcbiAgICAweDMwNTYzODU2LCAweDMwZDA3NGFkLCAweDMyNGYwYmJhLCAweDMyYzk0NzQxLCAweDMzYzVkZWI3LCAweDMzNDM5MjRjLCAweDM2N2Q2YzYyLCAweDM2ZmIyMDk5LCAweDM3ZjdiOTZmLFxuICAgIDB4Mzc3MWY1OTQsIDB4MzVlZThhODMsIDB4MzU2OGM2NzgsIDB4MzQ2NDVmOGUsIDB4MzRlMjEzNzUsIDB4MjExNTcyM2IsIDB4MjE5MzNlYzAsIDB4MjA5ZmE3MzYsIDB4MjAxOWViY2QsXG4gICAgMHgyMjg2OTRkYSwgMHgyMjAwZDgyMSwgMHgyMzBjNDFkNywgMHgyMzhhMGQyYywgMHgyNmI0ZjMwMiwgMHgyNjMyYmZmOSwgMHgyNzNlMjYwZiwgMHgyN2I4NmFmNCwgMHgyNTI3MTVlMyxcbiAgICAweDI1YTE1OTE4LCAweDI0YWRjMGVlLCAweDI0MmI4YzE1LCAweDJlZDAzY2IyLCAweDJlNTY3MDQ5LCAweDJmNWFlOWJmLCAweDJmZGNhNTQ0LCAweDJkNDNkYTUzLCAweDJkYzU5NmE4LFxuICAgIDB4MmNjOTBmNWUsIDB4MmM0ZjQzYTUsIDB4Mjk3MWJkOGIsIDB4MjlmN2YxNzAsIDB4MjhmYjY4ODYsIDB4Mjg3ZDI0N2QsIDB4MmFlMjViNmEsIDB4MmE2NDE3OTEsIDB4MmI2ODhlNjcsXG4gICAgMHgyYmVlYzI5YywgMHg3YzMzNDdhNCwgMHg3Y2I1MGI1ZiwgMHg3ZGI5OTJhOSwgMHg3ZDNmZGU1MiwgMHg3ZmEwYTE0NSwgMHg3ZjI2ZWRiZSwgMHg3ZTJhNzQ0OCwgMHg3ZWFjMzhiMyxcbiAgICAweDdiOTJjNjlkLCAweDdiMTQ4YTY2LCAweDdhMTgxMzkwLCAweDdhOWU1ZjZiLCAweDc4MDEyMDdjLCAweDc4ODc2Yzg3LCAweDc5OGJmNTcxLCAweDc5MGRiOThhLCAweDczZjYwOTJkLFxuICAgIDB4NzM3MDQ1ZDYsIDB4NzI3Y2RjMjAsIDB4NzJmYTkwZGIsIDB4NzA2NWVmY2MsIDB4NzBlM2EzMzcsIDB4NzFlZjNhYzEsIDB4NzE2OTc2M2EsIDB4NzQ1Nzg4MTQsIDB4NzRkMWM0ZWYsXG4gICAgMHg3NWRkNWQxOSwgMHg3NTViMTFlMiwgMHg3N2M0NmVmNSwgMHg3NzQyMjIwZSwgMHg3NjRlYmJmOCwgMHg3NmM4ZjcwMywgMHg2MzNmOTY0ZCwgMHg2M2I5ZGFiNiwgMHg2MmI1NDM0MCxcbiAgICAweDYyMzMwZmJiLFxuICAgIDB4NjBhYzcwYWMsIDB4NjAyYTNjNTcsIDB4NjEyNmE1YTEsIDB4NjFhMGU5NWEsIDB4NjQ5ZTE3NzQsIDB4NjQxODViOGYsIDB4NjUxNGMyNzksIDB4NjU5MjhlODIsIDB4NjcwZGYxOTUsXG4gICAgMHg2NzhiYmQ2ZSwgMHg2Njg3MjQ5OCwgMHg2NjAxNjg2MywgMHg2Y2ZhZDhjNCwgMHg2YzdjOTQzZiwgMHg2ZDcwMGRjOSwgMHg2ZGY2NDEzMiwgMHg2ZjY5M2UyNSwgMHg2ZmVmNzJkZSxcbiAgICAweDZlZTNlYjI4LCAweDZlNjVhN2QzLCAweDZiNWI1OWZkLCAweDZiZGQxNTA2LCAweDZhZDE4Y2YwLCAweDZhNTdjMDBiLCAweDY4YzhiZjFjLCAweDY4NGVmM2U3LCAweDY5NDI2YTExLFxuICAgIDB4NjljNDI2ZWEsIDB4NDIyYWU0NzYsIDB4NDJhY2E4OGQsIDB4NDNhMDMxN2IsIDB4NDMyNjdkODAsIDB4NDFiOTAyOTcsIDB4NDEzZjRlNmMsIDB4NDAzM2Q3OWEsIDB4NDBiNTliNjEsXG4gICAgMHg0NThiNjU0ZiwgMHg0NTBkMjliNCwgMHg0NDAxYjA0MiwgMHg0NDg3ZmNiOSwgMHg0NjE4ODNhZSwgMHg0NjllY2Y1NSwgMHg0NzkyNTZhMywgMHg0NzE0MWE1OCwgMHg0ZGVmYWFmZixcbiAgICAweDRkNjllNjA0LCAweDRjNjU3ZmYyLCAweDRjZTMzMzA5LCAweDRlN2M0YzFlLCAweDRlZmEwMGU1LCAweDRmZjY5OTEzLCAweDRmNzBkNWU4LCAweDRhNGUyYmM2LCAweDRhYzg2NzNkLFxuICAgIDB4NGJjNGZlY2IsIDB4NGI0MmIyMzAsIDB4NDlkZGNkMjcsIDB4NDk1YjgxZGMsIDB4NDg1NzE4MmEsIDB4NDhkMTU0ZDEsIDB4NWQyNjM1OWYsIDB4NWRhMDc5NjQsIDB4NWNhY2UwOTIsXG4gICAgMHg1YzJhYWM2OSwgMHg1ZWI1ZDM3ZSwgMHg1ZTMzOWY4NSwgMHg1ZjNmMDY3MywgMHg1ZmI5NGE4OCwgMHg1YTg3YjRhNiwgMHg1YTAxZjg1ZCwgMHg1YjBkNjFhYiwgMHg1YjhiMmQ1MCxcbiAgICAweDU5MTQ1MjQ3LCAweDU5OTIxZWJjLCAweDU4OWU4NzRhLCAweDU4MThjYmIxLCAweDUyZTM3YjE2LCAweDUyNjUzN2VkLCAweDUzNjlhZTFiLCAweDUzZWZlMmUwLCAweDUxNzA5ZGY3LFxuICAgIDB4NTFmNmQxMGMsXG4gICAgMHg1MGZhNDhmYSwgMHg1MDdjMDQwMSwgMHg1NTQyZmEyZiwgMHg1NWM0YjZkNCwgMHg1NGM4MmYyMiwgMHg1NDRlNjNkOSwgMHg1NmQxMWNjZSwgMHg1NjU3NTAzNSwgMHg1NzViYzljMyxcbiAgICAweDU3ZGQ4NTM4XG5dO1xuXG5mdW5jdGlvbiBjcmVhdGVjcmMyNChpbnB1dCkge1xuICB2YXIgY3JjID0gMHhCNzA0Q0U7XG4gIHZhciBpbmRleCA9IDA7XG5cbiAgd2hpbGUgKChpbnB1dC5sZW5ndGggLSBpbmRleCkgPiAxNikge1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMSkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMikpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMykpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgNCkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgNSkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgNikpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgNykpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgOCkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgOSkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMTApKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDExKSkgJiAweGZmXTtcbiAgICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXggKyAxMikpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMTMpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDE0KSkgJiAweGZmXTtcbiAgICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXggKyAxNSkpICYgMHhmZl07XG4gICAgaW5kZXggKz0gMTY7XG4gIH1cblxuICBmb3IgKHZhciBqID0gaW5kZXg7IGogPCBpbnB1dC5sZW5ndGg7IGorKykge1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCsrKSkgJiAweGZmXTtcbiAgfVxuICByZXR1cm4gY3JjICYgMHhmZmZmZmY7XG59XG5cbi8qKlxuICogRGVBcm1vciBhbiBPcGVuUEdQIGFybW9yZWQgbWVzc2FnZTsgdmVyaWZ5IHRoZSBjaGVja3N1bSBhbmQgcmV0dXJuIFxuICogdGhlIGVuY29kZWQgYnl0ZXNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0IE9wZW5QR1AgYXJtb3JlZCBtZXNzYWdlXG4gKiBAcmV0dXJucyB7KEJvb2xlYW58T2JqZWN0KX0gRWl0aGVyIGZhbHNlIGluIGNhc2Ugb2YgYW4gZXJyb3IgXG4gKiBvciBhbiBvYmplY3Qgd2l0aCBhdHRyaWJ1dGUgXCJ0ZXh0XCIgY29udGFpbmluZyB0aGUgbWVzc2FnZSB0ZXh0XG4gKiBhbmQgYW4gYXR0cmlidXRlIFwib3BlbnBncFwiIGNvbnRhaW5pbmcgdGhlIGJ5dGVzLlxuICovXG5mdW5jdGlvbiBkZWFybW9yKHRleHQpIHtcbiAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxyL2csICcnKTtcblxuICB2YXIgdHlwZSA9IGdldF90eXBlKHRleHQpO1xuXG4gIGlmICh0eXBlICE9IDIpIHtcbiAgICB2YXIgc3BsaXR0ZWR0ZXh0ID0gdGV4dC5zcGxpdCgnLS0tLS0nKTtcblxuICAgIHZhciBkYXRhID0ge1xuICAgICAgb3BlbnBncDogYmFzZTY0LmRlY29kZShcbiAgICAgICAgc3BsaXR0ZWR0ZXh0WzJdXG4gICAgICAgIC5zcGxpdCgnXFxuXFxuJylbMV1cbiAgICAgICAgLnNwbGl0KFwiXFxuPVwiKVswXVxuICAgICAgICAucmVwbGFjZSgvXFxuLSAvZywgXCJcXG5cIikpLFxuICAgICAgdHlwZTogdHlwZVxuICAgIH07XG5cbiAgICBpZiAodmVyaWZ5Q2hlY2tTdW0oZGF0YS5vcGVucGdwLFxuICAgICAgc3BsaXR0ZWR0ZXh0WzJdXG4gICAgICAuc3BsaXQoJ1xcblxcbicpWzFdXG4gICAgICAuc3BsaXQoXCJcXG49XCIpWzFdXG4gICAgICAuc3BsaXQoJ1xcbicpWzBdKSlcblxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgZWxzZSB7XG4gICAgICB1dGlsLnByaW50X2Vycm9yKFwiQXNjaWkgYXJtb3IgaW50ZWdyaXR5IGNoZWNrIG9uIG1lc3NhZ2UgZmFpbGVkOiAnXCIgKyBzcGxpdHRlZHRleHRbMl1cbiAgICAgICAgLnNwbGl0KCdcXG5cXG4nKVsxXVxuICAgICAgICAuc3BsaXQoXCJcXG49XCIpWzFdXG4gICAgICAgIC5zcGxpdCgnXFxuJylbMF0gKyBcIicgc2hvdWxkIGJlICdcIiArIGdldENoZWNrU3VtKGRhdGEpKSArIFwiJ1wiO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgc3BsaXR0ZWR0ZXh0ID0gdGV4dC5zcGxpdCgnLS0tLS0nKTtcblxuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICB0ZXh0OiBzcGxpdHRlZHRleHRbMl1cbiAgICAgICAgLnJlcGxhY2UoL1xcbi0gL2csIFwiXFxuXCIpXG4gICAgICAgIC5zcGxpdChcIlxcblxcblwiKVsxXSxcbiAgICAgIG9wZW5wZ3A6IGJhc2U2NC5kZWNvZGUoc3BsaXR0ZWR0ZXh0WzRdXG4gICAgICAgIC5zcGxpdChcIlxcblxcblwiKVsxXVxuICAgICAgICAuc3BsaXQoXCJcXG49XCIpWzBdKSxcbiAgICAgIHR5cGU6IHR5cGVcbiAgICB9O1xuXG4gICAgaWYgKHZlcmlmeUNoZWNrU3VtKHJlc3VsdC5vcGVucGdwLCBzcGxpdHRlZHRleHRbNF1cbiAgICAgIC5zcGxpdChcIlxcblxcblwiKVsxXVxuICAgICAgLnNwbGl0KFwiXFxuPVwiKVsxXSkpXG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgZWxzZSB7XG4gICAgICB1dGlsLnByaW50X2Vycm9yKFwiQXNjaWkgYXJtb3IgaW50ZWdyaXR5IGNoZWNrIG9uIG1lc3NhZ2UgZmFpbGVkXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxufVxuXG5cbi8qKlxuICogQXJtb3IgYW4gT3BlblBHUCBiaW5hcnkgcGFja2V0IGJsb2NrXG4gKiBAcGFyYW0ge0ludGVnZXJ9IG1lc3NhZ2V0eXBlIHR5cGUgb2YgdGhlIG1lc3NhZ2VcbiAqIEBwYXJhbSBkYXRhXG4gKiBAcGFyYW0ge0ludGVnZXJ9IHBhcnRpbmRleFxuICogQHBhcmFtIHtJbnRlZ2VyfSBwYXJ0dG90YWxcbiAqIEByZXR1cm5zIHtTdHJpbmd9IEFybW9yZWQgdGV4dFxuICovXG5mdW5jdGlvbiBhcm1vcihtZXNzYWdldHlwZSwgZGF0YSwgcGFydGluZGV4LCBwYXJ0dG90YWwpIHtcbiAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gIHN3aXRjaCAobWVzc2FnZXR5cGUpIHtcbiAgICBjYXNlIGVudW1zLmFybW9yLm11bHRpcGFydF9zZWN0aW9uOlxuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1CRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBcIiArIHBhcnRpbmRleCArIFwiL1wiICsgcGFydHRvdGFsICsgXCItLS0tLVxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuICAgICAgcmVzdWx0ICs9IGJhc2U2NC5lbmNvZGUoZGF0YSk7XG4gICAgICByZXN1bHQgKz0gXCJcXHJcXG49XCIgKyBnZXRDaGVja1N1bShkYXRhKSArIFwiXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUVORCBQR1AgTUVTU0FHRSwgUEFSVCBcIiArIHBhcnRpbmRleCArIFwiL1wiICsgcGFydHRvdGFsICsgXCItLS0tLVxcclxcblwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBlbnVtcy5hcm1vci5tdXRsaXBhcnRfbGFzdDpcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgXCIgKyBwYXJ0aW5kZXggKyBcIi0tLS0tXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gYXJtb3JfYWRkaGVhZGVyKCk7XG4gICAgICByZXN1bHQgKz0gYmFzZTY0LmVuY29kZShkYXRhKTtcbiAgICAgIHJlc3VsdCArPSBcIlxcclxcbj1cIiArIGdldENoZWNrU3VtKGRhdGEpICsgXCJcXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBNRVNTQUdFLCBQQVJUIFwiICsgcGFydGluZGV4ICsgXCItLS0tLVxcclxcblwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBlbnVtcy5hcm1vci5zaWduZWQ6XG4gICAgICByZXN1bHQgKz0gXCJcXHJcXG4tLS0tLUJFR0lOIFBHUCBTSUdORUQgTUVTU0FHRS0tLS0tXFxyXFxuSGFzaDogXCIgKyBkYXRhLmhhc2ggKyBcIlxcclxcblxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IGRhdGEudGV4dC5yZXBsYWNlKC9cXG4tL2csIFwiXFxuLSAtXCIpO1xuICAgICAgcmVzdWx0ICs9IFwiXFxyXFxuLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS1cXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBhcm1vcl9hZGRoZWFkZXIoKTtcbiAgICAgIHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGRhdGEub3BlbnBncCk7XG4gICAgICByZXN1bHQgKz0gXCJcXHJcXG49XCIgKyBnZXRDaGVja1N1bShkYXRhLm9wZW5wZ3ApICsgXCJcXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBTSUdOQVRVUkUtLS0tLVxcclxcblwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBlbnVtcy5hcm1vci5tZXNzYWdlOlxuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gYXJtb3JfYWRkaGVhZGVyKCk7XG4gICAgICByZXN1bHQgKz0gYmFzZTY0LmVuY29kZShkYXRhKTtcbiAgICAgIHJlc3VsdCArPSBcIlxcclxcbj1cIiArIGdldENoZWNrU3VtKGRhdGEpICsgXCJcXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBNRVNTQUdFLS0tLS1cXHJcXG5cIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgZW51bXMuYXJtb3IucHVibGljX2tleTpcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLVxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuICAgICAgcmVzdWx0ICs9IGJhc2U2NC5lbmNvZGUoZGF0YSk7XG4gICAgICByZXN1bHQgKz0gXCJcXHJcXG49XCIgKyBnZXRDaGVja1N1bShkYXRhKSArIFwiXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUVORCBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tXFxyXFxuXFxyXFxuXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIGVudW1zLmFybW9yLnByaXZhdGVfa2V5OlxuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1CRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLVxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuICAgICAgcmVzdWx0ICs9IGJhc2U2NC5lbmNvZGUoZGF0YSk7XG4gICAgICByZXN1bHQgKz0gXCJcXHJcXG49XCIgKyBnZXRDaGVja1N1bShkYXRhKSArIFwiXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLVxcclxcblwiO1xuICAgICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZW5jb2RlOiBhcm1vcixcbiAgZGVjb2RlOiBkZWFybW9yXG59O1xuIiwiLyogT3BlblBHUCByYWRpeC02NC9iYXNlNjQgc3RyaW5nIGVuY29kaW5nL2RlY29kaW5nXG4gKiBDb3B5cmlnaHQgMjAwNSBIZXJiZXJ0IEhhbmV3aW5rZWwsIHd3dy5oYW5lV0lOLmRlXG4gKiB2ZXJzaW9uIDEuMCwgY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxuICpcbiAqIFRoaXMgc29mdHdhcmUgaXMgcHJvdmlkZWQgYXMtaXMsIHdpdGhvdXQgZXhwcmVzcyBvciBpbXBsaWVkIHdhcnJhbnR5LiAgXG4gKiBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlIG9yIHNlbGwgdGhpcyBzb2Z0d2FyZSwgd2l0aCBvclxuICogd2l0aG91dCBmZWUsIGZvciBhbnkgcHVycG9zZSBhbmQgYnkgYW55IGluZGl2aWR1YWwgb3Igb3JnYW5pemF0aW9uLCBpcyBoZXJlYnlcbiAqIGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGFyYWdyYXBoIGFwcGVhciBcbiAqIGluIGFsbCBjb3BpZXMuIERpc3RyaWJ1dGlvbiBhcyBhIHBhcnQgb2YgYW4gYXBwbGljYXRpb24gb3IgYmluYXJ5IG11c3RcbiAqIGluY2x1ZGUgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgaW4gdGhlIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFsc1xuICogcHJvdmlkZWQgd2l0aCB0aGUgYXBwbGljYXRpb24gb3IgZGlzdHJpYnV0aW9uLlxuICovXG5cbnZhciBiNjRzID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nO1xuXG5mdW5jdGlvbiBzMnIodCkge1xuICB2YXIgYSwgYywgbjtcbiAgdmFyIHIgPSAnJyxcbiAgICBsID0gMCxcbiAgICBzID0gMDtcbiAgdmFyIHRsID0gdC5sZW5ndGg7XG5cbiAgZm9yIChuID0gMDsgbiA8IHRsOyBuKyspIHtcbiAgICBjID0gdC5jaGFyQ29kZUF0KG4pO1xuICAgIGlmIChzID09IDApIHtcbiAgICAgIHIgKz0gYjY0cy5jaGFyQXQoKGMgPj4gMikgJiA2Myk7XG4gICAgICBhID0gKGMgJiAzKSA8PCA0O1xuICAgIH0gZWxzZSBpZiAocyA9PSAxKSB7XG4gICAgICByICs9IGI2NHMuY2hhckF0KChhIHwgKGMgPj4gNCkgJiAxNSkpO1xuICAgICAgYSA9IChjICYgMTUpIDw8IDI7XG4gICAgfSBlbHNlIGlmIChzID09IDIpIHtcbiAgICAgIHIgKz0gYjY0cy5jaGFyQXQoYSB8ICgoYyA+PiA2KSAmIDMpKTtcbiAgICAgIGwgKz0gMTtcbiAgICAgIGlmICgobCAlIDYwKSA9PSAwKVxuICAgICAgICByICs9IFwiXFxuXCI7XG4gICAgICByICs9IGI2NHMuY2hhckF0KGMgJiA2Myk7XG4gICAgfVxuICAgIGwgKz0gMTtcbiAgICBpZiAoKGwgJSA2MCkgPT0gMClcbiAgICAgIHIgKz0gXCJcXG5cIjtcblxuICAgIHMgKz0gMTtcbiAgICBpZiAocyA9PSAzKVxuICAgICAgcyA9IDA7XG4gIH1cbiAgaWYgKHMgPiAwKSB7XG4gICAgciArPSBiNjRzLmNoYXJBdChhKTtcbiAgICBsICs9IDE7XG4gICAgaWYgKChsICUgNjApID09IDApXG4gICAgICByICs9IFwiXFxuXCI7XG4gICAgciArPSAnPSc7XG4gICAgbCArPSAxO1xuICB9XG4gIGlmIChzID09IDEpIHtcbiAgICBpZiAoKGwgJSA2MCkgPT0gMClcbiAgICAgIHIgKz0gXCJcXG5cIjtcbiAgICByICs9ICc9JztcbiAgfVxuXG4gIHJldHVybiByO1xufVxuXG5mdW5jdGlvbiByMnModCkge1xuICB2YXIgYywgbjtcbiAgdmFyIHIgPSAnJyxcbiAgICBzID0gMCxcbiAgICBhID0gMDtcbiAgdmFyIHRsID0gdC5sZW5ndGg7XG5cbiAgZm9yIChuID0gMDsgbiA8IHRsOyBuKyspIHtcbiAgICBjID0gYjY0cy5pbmRleE9mKHQuY2hhckF0KG4pKTtcbiAgICBpZiAoYyA+PSAwKSB7XG4gICAgICBpZiAocylcbiAgICAgICAgciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGEgfCAoYyA+PiAoNiAtIHMpKSAmIDI1NSk7XG4gICAgICBzID0gKHMgKyAyKSAmIDc7XG4gICAgICBhID0gKGMgPDwgcykgJiAyNTU7XG4gICAgfVxuICB9XG4gIHJldHVybiByO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZW5jb2RlOiBzMnIsXG4gIGRlY29kZTogcjJzXG59XG4iLCJ2YXIgZW51bXMgPSB7XG5cbiAgLyoqIEEgc3RyaW5nIHRvIGtleSBzcGVjaWZpZXIgdHlwZVxuICAgKiBAZW51bSB7SW50ZWdlcn1cbiAgICovXG4gIHMyazoge1xuICAgIHNpbXBsZTogMCxcbiAgICBzYWx0ZWQ6IDEsXG4gICAgaXRlcmF0ZWQ6IDMsXG4gICAgZ251OiAxMDFcbiAgfSxcblxuICAvKiogUkZDNDg4MCwgc2VjdGlvbiA5LjEgXG4gICAqIEBlbnVtIHtTdHJpbmd9XG4gICAqL1xuICBwdWJsaWNLZXk6IHtcbiAgICByc2FfZW5jcnlwdF9zaWduOiAxLFxuICAgIHJzYV9lbmNyeXB0OiAyLFxuICAgIHJzYV9zaWduOiAzLFxuICAgIGVsZ2FtYWw6IDE2LFxuICAgIGRzYTogMTdcbiAgfSxcblxuICAvKiogUkZDNDg4MCwgc2VjdGlvbiA5LjIgXG4gICAqIEBlbnVtIHtTdHJpbmd9XG4gICAqL1xuICBzeW1tZXRyaWM6IHtcbiAgICBwbGFpbnRleHQ6IDAsXG4gICAgLyoqIE5vdCBpbXBsZW1lbnRlZCEgKi9cbiAgICBpZGVhOiAxLFxuICAgIHRyaXBsZWRlczogMixcbiAgICBjYXN0NTogMyxcbiAgICBibG93ZmlzaDogNCxcbiAgICBhZXMxMjg6IDcsXG4gICAgYWVzMTkyOiA4LFxuICAgIGFlczI1NjogOSxcbiAgICB0d29maXNoOiAxMFxuICB9LFxuXG4gIC8qKiBSRkM0ODgwLCBzZWN0aW9uIDkuM1xuICAgKiBAZW51bSB7U3RyaW5nfVxuICAgKi9cbiAgY29tcHJlc3Npb246IHtcbiAgICB1bmNvbXByZXNzZWQ6IDAsXG4gICAgLyoqIFJGQzE5NTEgKi9cbiAgICB6aXA6IDEsXG4gICAgLyoqIFJGQzE5NTAgKi9cbiAgICB6bGliOiAyLFxuICAgIGJ6aXAyOiAzXG4gIH0sXG5cbiAgLyoqIFJGQzQ4ODAsIHNlY3Rpb24gOS40XG4gICAqIEBlbnVtIHtTdHJpbmd9XG4gICAqL1xuICBoYXNoOiB7XG4gICAgbWQ1OiAxLFxuICAgIHNoYTE6IDIsXG4gICAgcmlwZW1kOiAzLFxuICAgIHNoYTI1NjogOCxcbiAgICBzaGEzODQ6IDksXG4gICAgc2hhNTEyOiAxMCxcbiAgICBzaGEyMjQ6IDExXG4gIH0sXG5cblxuICAvKipcbiAgICogQGVudW0ge1N0cmluZ31cbiAgICogQSBsaXN0IG9mIHBhY2tldCB0eXBlcyBhbmQgbnVtZXJpYyB0YWdzIGFzc29jaWF0ZWQgd2l0aCB0aGVtLlxuICAgKi9cbiAgcGFja2V0OiB7XG4gICAgcHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXk6IDEsXG4gICAgc2lnbmF0dXJlOiAyLFxuICAgIHN5bV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXk6IDMsXG4gICAgb25lX3Bhc3Nfc2lnbmF0dXJlOiA0LFxuICAgIHNlY3JldF9rZXk6IDUsXG4gICAgcHVibGljX2tleTogNixcbiAgICBzZWNyZXRfc3Via2V5OiA3LFxuICAgIGNvbXByZXNzZWQ6IDgsXG4gICAgc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQ6IDksXG4gICAgbWFya2VyOiAxMCxcbiAgICBsaXRlcmFsOiAxMSxcbiAgICB0cnVzdDogMTIsXG4gICAgdXNlcmlkOiAxMyxcbiAgICBwdWJsaWNfc3Via2V5OiAxNCxcbiAgICB1c2VyX2F0dHJpYnV0ZTogMTcsXG4gICAgc3ltX2VuY3J5cHRlZF9pbnRlZ3JpdHlfcHJvdGVjdGVkOiAxOCxcbiAgICBtb2RpZmljYXRpb25fZGV0ZWN0aW9uX2NvZGU6IDE5XG4gIH0sXG5cblxuICAvKipcbiAgICogRGF0YSB0eXBlcyBpbiB0aGUgbGl0ZXJhbCBwYWNrZXRcbiAgICogQHJlYWRvbmx5XG4gICAqIEBlbnVtIHtTdHJpbmd9XG4gICAqL1xuICBsaXRlcmFsOiB7XG4gICAgLyoqIEJpbmFyeSBkYXRhICovXG4gICAgYmluYXJ5OiAnYicuY2hhckNvZGVBdCgpLFxuICAgIC8qKiBUZXh0IGRhdGEgKi9cbiAgICB0ZXh0OiAndCcuY2hhckNvZGVBdCgpLFxuICAgIC8qKiBVdGY4IGRhdGEgKi9cbiAgICB1dGY4OiAndScuY2hhckNvZGVBdCgpXG4gIH0sXG5cblxuICAvKiogT25lIHBhc3Mgc2lnbmF0dXJlIHBhY2tldCB0eXBlXG4gICAqIEBlbnVtIHtTdHJpbmd9ICovXG4gIHNpZ25hdHVyZToge1xuICAgIC8qKiAweDAwOiBTaWduYXR1cmUgb2YgYSBiaW5hcnkgZG9jdW1lbnQuICovXG4gICAgYmluYXJ5OiAwLFxuICAgIC8qKiAweDAxOiBTaWduYXR1cmUgb2YgYSBjYW5vbmljYWwgdGV4dCBkb2N1bWVudC5cbiAgICAgKiBDYW5vbmljYWx5emluZyB0aGUgZG9jdW1lbnQgYnkgY29udmVydGluZyBsaW5lIGVuZGluZ3MuICovXG4gICAgdGV4dDogMSxcbiAgICAvKiogMHgwMjogU3RhbmRhbG9uZSBzaWduYXR1cmUuXG4gICAgICogVGhpcyBzaWduYXR1cmUgaXMgYSBzaWduYXR1cmUgb2Ygb25seSBpdHMgb3duIHN1YnBhY2tldCBjb250ZW50cy5cbiAgICAgKiBJdCBpcyBjYWxjdWxhdGVkIGlkZW50aWNhbGx5IHRvIGEgc2lnbmF0dXJlIG92ZXIgYSB6ZXJvLWxlbmdoXG4gICAgICogYmluYXJ5IGRvY3VtZW50LiAgTm90ZSB0aGF0IGl0IGRvZXNuJ3QgbWFrZSBzZW5zZSB0byBoYXZlIGEgVjNcbiAgICAgKiBzdGFuZGFsb25lIHNpZ25hdHVyZS4gKi9cbiAgICBzdGFuZGFsb25lOiAyLFxuICAgIC8qKiAweDEwOiBHZW5lcmljIGNlcnRpZmljYXRpb24gb2YgYSBVc2VyIElEIGFuZCBQdWJsaWMtS2V5IHBhY2tldC5cbiAgICAgKiBUaGUgaXNzdWVyIG9mIHRoaXMgY2VydGlmaWNhdGlvbiBkb2VzIG5vdCBtYWtlIGFueSBwYXJ0aWN1bGFyXG4gICAgICogYXNzZXJ0aW9uIGFzIHRvIGhvdyB3ZWxsIHRoZSBjZXJ0aWZpZXIgaGFzIGNoZWNrZWQgdGhhdCB0aGUgb3duZXJcbiAgICAgKiBvZiB0aGUga2V5IGlzIGluIGZhY3QgdGhlIHBlcnNvbiBkZXNjcmliZWQgYnkgdGhlIFVzZXIgSUQuICovXG4gICAgY2VydF9nZW5lcmljOiAxNixcbiAgICAvKiogMHgxMTogUGVyc29uYSBjZXJ0aWZpY2F0aW9uIG9mIGEgVXNlciBJRCBhbmQgUHVibGljLUtleSBwYWNrZXQuXG4gICAgICogVGhlIGlzc3VlciBvZiB0aGlzIGNlcnRpZmljYXRpb24gaGFzIG5vdCBkb25lIGFueSB2ZXJpZmljYXRpb24gb2ZcbiAgICAgKiB0aGUgY2xhaW0gdGhhdCB0aGUgb3duZXIgb2YgdGhpcyBrZXkgaXMgdGhlIFVzZXIgSUQgc3BlY2lmaWVkLiAqL1xuICAgIGNlcnRfcGVyc29uYTogMTcsXG4gICAgLyoqIDB4MTI6IENhc3VhbCBjZXJ0aWZpY2F0aW9uIG9mIGEgVXNlciBJRCBhbmQgUHVibGljLUtleSBwYWNrZXQuXG4gICAgICogVGhlIGlzc3VlciBvZiB0aGlzIGNlcnRpZmljYXRpb24gaGFzIGRvbmUgc29tZSBjYXN1YWxcbiAgICAgKiB2ZXJpZmljYXRpb24gb2YgdGhlIGNsYWltIG9mIGlkZW50aXR5LiAqL1xuICAgIGNlcnRfY2FzdWFsOiAxOCxcbiAgICAvKiogMHgxMzogUG9zaXRpdmUgY2VydGlmaWNhdGlvbiBvZiBhIFVzZXIgSUQgYW5kIFB1YmxpYy1LZXkgcGFja2V0LlxuICAgICAqIFRoZSBpc3N1ZXIgb2YgdGhpcyBjZXJ0aWZpY2F0aW9uIGhhcyBkb25lIHN1YnN0YW50aWFsXG4gICAgICogdmVyaWZpY2F0aW9uIG9mIHRoZSBjbGFpbSBvZiBpZGVudGl0eS5cbiAgICAgKiBcbiAgICAgKiBNb3N0IE9wZW5QR1AgaW1wbGVtZW50YXRpb25zIG1ha2UgdGhlaXIgXCJrZXkgc2lnbmF0dXJlc1wiIGFzIDB4MTBcbiAgICAgKiBjZXJ0aWZpY2F0aW9ucy4gIFNvbWUgaW1wbGVtZW50YXRpb25zIGNhbiBpc3N1ZSAweDExLTB4MTNcbiAgICAgKiBjZXJ0aWZpY2F0aW9ucywgYnV0IGZldyBkaWZmZXJlbnRpYXRlIGJldHdlZW4gdGhlIHR5cGVzLiAqL1xuICAgIGNlcnRfcG9zaXRpdmU6IDE5LFxuICAgIC8qKiAweDMwOiBDZXJ0aWZpY2F0aW9uIHJldm9jYXRpb24gc2lnbmF0dXJlXG4gICAgICogVGhpcyBzaWduYXR1cmUgcmV2b2tlcyBhbiBlYXJsaWVyIFVzZXIgSUQgY2VydGlmaWNhdGlvbiBzaWduYXR1cmVcbiAgICAgKiAoc2lnbmF0dXJlIGNsYXNzIDB4MTAgdGhyb3VnaCAweDEzKSBvciBkaXJlY3Qta2V5IHNpZ25hdHVyZVxuICAgICAqICgweDFGKS4gIEl0IHNob3VsZCBiZSBpc3N1ZWQgYnkgdGhlIHNhbWUga2V5IHRoYXQgaXNzdWVkIHRoZVxuICAgICAqIHJldm9rZWQgc2lnbmF0dXJlIG9yIGFuIGF1dGhvcml6ZWQgcmV2b2NhdGlvbiBrZXkuICBUaGUgc2lnbmF0dXJlXG4gICAgICogaXMgY29tcHV0ZWQgb3ZlciB0aGUgc2FtZSBkYXRhIGFzIHRoZSBjZXJ0aWZpY2F0ZSB0aGF0IGl0XG4gICAgICogcmV2b2tlcywgYW5kIHNob3VsZCBoYXZlIGEgbGF0ZXIgY3JlYXRpb24gZGF0ZSB0aGFuIHRoYXRcbiAgICAgKiBjZXJ0aWZpY2F0ZS4gKi9cbiAgICBjZXJ0X3Jldm9jYXRpb246IDQ4LFxuICAgIC8qKiAweDE4OiBTdWJrZXkgQmluZGluZyBTaWduYXR1cmVcbiAgICAgKiBUaGlzIHNpZ25hdHVyZSBpcyBhIHN0YXRlbWVudCBieSB0aGUgdG9wLWxldmVsIHNpZ25pbmcga2V5IHRoYXRcbiAgICAgKiBpbmRpY2F0ZXMgdGhhdCBpdCBvd25zIHRoZSBzdWJrZXkuICBUaGlzIHNpZ25hdHVyZSBpcyBjYWxjdWxhdGVkXG4gICAgICogZGlyZWN0bHkgb24gdGhlIHByaW1hcnkga2V5IGFuZCBzdWJrZXksIGFuZCBub3Qgb24gYW55IFVzZXIgSUQgb3JcbiAgICAgKiBvdGhlciBwYWNrZXRzLiAgQSBzaWduYXR1cmUgdGhhdCBiaW5kcyBhIHNpZ25pbmcgc3Via2V5IE1VU1QgaGF2ZVxuICAgICAqIGFuIEVtYmVkZGVkIFNpZ25hdHVyZSBzdWJwYWNrZXQgaW4gdGhpcyBiaW5kaW5nIHNpZ25hdHVyZSB0aGF0XG4gICAgICogY29udGFpbnMgYSAweDE5IHNpZ25hdHVyZSBtYWRlIGJ5IHRoZSBzaWduaW5nIHN1YmtleSBvbiB0aGVcbiAgICAgKiBwcmltYXJ5IGtleSBhbmQgc3Via2V5LiAqL1xuICAgIHN1YmtleV9iaW5kaW5nOiAyNCxcbiAgICAvKiogMHgxOTogUHJpbWFyeSBLZXkgQmluZGluZyBTaWduYXR1cmVcblx0XHQqIFRoaXMgc2lnbmF0dXJlIGlzIGEgc3RhdGVtZW50IGJ5IGEgc2lnbmluZyBzdWJrZXksIGluZGljYXRpbmdcblx0XHQqIHRoYXQgaXQgaXMgb3duZWQgYnkgdGhlIHByaW1hcnkga2V5IGFuZCBzdWJrZXkuICBUaGlzIHNpZ25hdHVyZVxuXHRcdCogaXMgY2FsY3VsYXRlZCB0aGUgc2FtZSB3YXkgYXMgYSAweDE4IHNpZ25hdHVyZTogZGlyZWN0bHkgb24gdGhlXG5cdFx0KiBwcmltYXJ5IGtleSBhbmQgc3Via2V5LCBhbmQgbm90IG9uIGFueSBVc2VyIElEIG9yIG90aGVyIHBhY2tldHMuXG5cdFx0XG5cdFx0KiBXaGVuIGEgc2lnbmF0dXJlIGlzIG1hZGUgb3ZlciBhIGtleSwgdGhlIGhhc2ggZGF0YSBzdGFydHMgd2l0aCB0aGVcblx0XHQqIG9jdGV0IDB4OTksIGZvbGxvd2VkIGJ5IGEgdHdvLW9jdGV0IGxlbmd0aCBvZiB0aGUga2V5LCBhbmQgdGhlbiBib2R5XG5cdFx0KiBvZiB0aGUga2V5IHBhY2tldC4gIChOb3RlIHRoYXQgdGhpcyBpcyBhbiBvbGQtc3R5bGUgcGFja2V0IGhlYWRlciBmb3Jcblx0XHQqIGEga2V5IHBhY2tldCB3aXRoIHR3by1vY3RldCBsZW5ndGguKSAgQSBzdWJrZXkgYmluZGluZyBzaWduYXR1cmVcblx0XHQqICh0eXBlIDB4MTgpIG9yIHByaW1hcnkga2V5IGJpbmRpbmcgc2lnbmF0dXJlICh0eXBlIDB4MTkpIHRoZW4gaGFzaGVzXG5cdFx0KiB0aGUgc3Via2V5IHVzaW5nIHRoZSBzYW1lIGZvcm1hdCBhcyB0aGUgbWFpbiBrZXkgKGFsc28gdXNpbmcgMHg5OSBhc1xuXHRcdCogdGhlIGZpcnN0IG9jdGV0KS4gKi9cbiAgICBrZXlfYmluZGluZzogMjUsXG4gICAgLyoqIDB4MUY6IFNpZ25hdHVyZSBkaXJlY3RseSBvbiBhIGtleVxuICAgICAqIFRoaXMgc2lnbmF0dXJlIGlzIGNhbGN1bGF0ZWQgZGlyZWN0bHkgb24gYSBrZXkuICBJdCBiaW5kcyB0aGVcbiAgICAgKiBpbmZvcm1hdGlvbiBpbiB0aGUgU2lnbmF0dXJlIHN1YnBhY2tldHMgdG8gdGhlIGtleSwgYW5kIGlzXG4gICAgICogYXBwcm9wcmlhdGUgdG8gYmUgdXNlZCBmb3Igc3VicGFja2V0cyB0aGF0IHByb3ZpZGUgaW5mb3JtYXRpb25cbiAgICAgKiBhYm91dCB0aGUga2V5LCBzdWNoIGFzIHRoZSBSZXZvY2F0aW9uIEtleSBzdWJwYWNrZXQuICBJdCBpcyBhbHNvXG4gICAgICogYXBwcm9wcmlhdGUgZm9yIHN0YXRlbWVudHMgdGhhdCBub24tc2VsZiBjZXJ0aWZpZXJzIHdhbnQgdG8gbWFrZVxuICAgICAqIGFib3V0IHRoZSBrZXkgaXRzZWxmLCByYXRoZXIgdGhhbiB0aGUgYmluZGluZyBiZXR3ZWVuIGEga2V5IGFuZCBhXG4gICAgICogbmFtZS4gKi9cbiAgICBrZXk6IDMxLFxuICAgIC8qKiAweDIwOiBLZXkgcmV2b2NhdGlvbiBzaWduYXR1cmVcbiAgICAgKiBUaGUgc2lnbmF0dXJlIGlzIGNhbGN1bGF0ZWQgZGlyZWN0bHkgb24gdGhlIGtleSBiZWluZyByZXZva2VkLiAgQVxuICAgICAqIHJldm9rZWQga2V5IGlzIG5vdCB0byBiZSB1c2VkLiAgT25seSByZXZvY2F0aW9uIHNpZ25hdHVyZXMgYnkgdGhlXG4gICAgICoga2V5IGJlaW5nIHJldm9rZWQsIG9yIGJ5IGFuIGF1dGhvcml6ZWQgcmV2b2NhdGlvbiBrZXksIHNob3VsZCBiZVxuICAgICAqIGNvbnNpZGVyZWQgdmFsaWQgcmV2b2NhdGlvbiBzaWduYXR1cmVzLmEgKi9cbiAgICBrZXlfcmV2b2NhdGlvbjogMzIsXG4gICAgLyoqIDB4Mjg6IFN1YmtleSByZXZvY2F0aW9uIHNpZ25hdHVyZVxuICAgICAqIFRoZSBzaWduYXR1cmUgaXMgY2FsY3VsYXRlZCBkaXJlY3RseSBvbiB0aGUgc3Via2V5IGJlaW5nIHJldm9rZWQuXG4gICAgICogQSByZXZva2VkIHN1YmtleSBpcyBub3QgdG8gYmUgdXNlZC4gIE9ubHkgcmV2b2NhdGlvbiBzaWduYXR1cmVzXG4gICAgICogYnkgdGhlIHRvcC1sZXZlbCBzaWduYXR1cmUga2V5IHRoYXQgaXMgYm91bmQgdG8gdGhpcyBzdWJrZXksIG9yXG4gICAgICogYnkgYW4gYXV0aG9yaXplZCByZXZvY2F0aW9uIGtleSwgc2hvdWxkIGJlIGNvbnNpZGVyZWQgdmFsaWRcbiAgICAgKiByZXZvY2F0aW9uIHNpZ25hdHVyZXMuXG4gICAgICogS2V5IHJldm9jYXRpb24gc2lnbmF0dXJlcyAodHlwZXMgMHgyMCBhbmQgMHgyOClcbiAgICAgKiBoYXNoIG9ubHkgdGhlIGtleSBiZWluZyByZXZva2VkLiAqL1xuICAgIHN1YmtleV9yZXZvY2F0aW9uOiA0MCxcbiAgICAvKiogMHg0MDogVGltZXN0YW1wIHNpZ25hdHVyZS5cbiAgICAgKiBUaGlzIHNpZ25hdHVyZSBpcyBvbmx5IG1lYW5pbmdmdWwgZm9yIHRoZSB0aW1lc3RhbXAgY29udGFpbmVkIGluXG4gICAgICogaXQuICovXG4gICAgdGltZXN0YW1wOiA2NCxcbiAgICAvKiogICAgMHg1MDogVGhpcmQtUGFydHkgQ29uZmlybWF0aW9uIHNpZ25hdHVyZS5cbiAgICAgKiBUaGlzIHNpZ25hdHVyZSBpcyBhIHNpZ25hdHVyZSBvdmVyIHNvbWUgb3RoZXIgT3BlblBHUCBTaWduYXR1cmVcbiAgICAgKiBwYWNrZXQocykuICBJdCBpcyBhbmFsb2dvdXMgdG8gYSBub3Rhcnkgc2VhbCBvbiB0aGUgc2lnbmVkIGRhdGEuXG4gICAgICogQSB0aGlyZC1wYXJ0eSBzaWduYXR1cmUgU0hPVUxEIGluY2x1ZGUgU2lnbmF0dXJlIFRhcmdldFxuICAgICAqIHN1YnBhY2tldChzKSB0byBnaXZlIGVhc3kgaWRlbnRpZmljYXRpb24uICBOb3RlIHRoYXQgd2UgcmVhbGx5IGRvXG4gICAgICogbWVhbiBTSE9VTEQuICBUaGVyZSBhcmUgcGxhdXNpYmxlIHVzZXMgZm9yIHRoaXMgKHN1Y2ggYXMgYSBibGluZFxuICAgICAqIHBhcnR5IHRoYXQgb25seSBzZWVzIHRoZSBzaWduYXR1cmUsIG5vdCB0aGUga2V5IG9yIHNvdXJjZVxuICAgICAqIGRvY3VtZW50KSB0aGF0IGNhbm5vdCBpbmNsdWRlIGEgdGFyZ2V0IHN1YnBhY2tldC4gKi9cbiAgICB0aGlyZF9wYXJ0eTogODBcbiAgfSxcblxuICBzaWduYXR1cmVTdWJwYWNrZXQ6IHtcbiAgICBzaWduYXR1cmVfY3JlYXRpb25fdGltZTogMixcbiAgICBzaWduYXR1cmVfZXhwaXJhdGlvbl90aW1lOiAzLFxuICAgIGV4cG9ydGFibGVfY2VydGlmaWNhdGlvbjogNCxcbiAgICB0cnVzdF9zaWduYXR1cmU6IDUsXG4gICAgcmVndWxhcl9leHByZXNzaW9uOiA2LFxuICAgIHJldm9jYWJsZTogNyxcbiAgICByZXNlcnZlZDogOCxcbiAgICBrZXlfZXhwaXJhdGlvbl90aW1lOiA5LFxuICAgIHBsYWNlaG9sZGVyX2JhY2t3YXJkc19jb21wYXRpYmlsaXR5OiAxMCxcbiAgICBwcmVmZXJyZWRfc3ltbWV0cmljX2FsZ29yaXRobXM6IDExLFxuICAgIHJldm9jYXRpb25fa2V5OiAxMixcbiAgICBpc3N1ZXI6IDE2LFxuICAgIG5vdGlmaWNhdGlvbl9kYXRhOiAyMCxcbiAgICBwcmVmZXJyZWRfaGFzaF9hbGdvcml0aG1zOiAyMSxcbiAgICBwcmVmZXJyZWRfY29tcHJlc3Npb25fYWxnb3JpdGhtczogMjIsXG4gICAga2V5X3NlcnZlcl9wcmVmZXJlbmNlczogMjMsXG4gICAgcHJlZmVycmVkX2tleV9zZXJ2ZXI6IDI0LFxuICAgIHByaW1hcnlfdXNlcl9pZDogMjUsXG4gICAgcG9saWN5X3VyaTogMjYsXG4gICAga2V5X2ZsYWdzOiAyNyxcbiAgICBzaWduZXJzX3VzZXJfaWQ6IDI4LFxuICAgIHJlYXNvbl9mb3JfcmV2b2NhdGlvbjogMjksXG4gICAgZmVhdHVyZXM6IDMwLFxuICAgIHNpZ25hdHVyZV90YXJnZXQ6IDMxLFxuICAgIGVtYmVkZGVkX3NpZ25hdHVyZTogMzJcbiAgfSxcblxuICBhcm1vcjoge1xuICAgIG11bHRpcGFydF9zZWN0aW9uOiAwLFxuICAgIG11bHRpcGFydF9sYXN0OiAxLFxuICAgIHNpZ25lZDogMixcbiAgICBtZXNzYWdlOiAzLFxuICAgIHB1YmxpY19rZXk6IDQsXG4gICAgcHJpdmF0ZV9rZXk6IDVcbiAgfSxcblxuICAvLyBBc3NlcnRzIHZhbGlkaXR5IGFuZCBjb252ZXJ0cyBmcm9tIHN0cmluZy9pbnRlZ2VyIHRvIGludGVnZXIuXG4gIHdyaXRlOiBmdW5jdGlvbih0eXBlLCBlKSB7XG4gICAgaWYgKHR5cGVvZiBlID09ICdudW1iZXInKSB7XG4gICAgICBlID0gdGhpcy5yZWFkKHR5cGUsIGUpO1xuICAgIH1cblxuICAgIGlmICh0eXBlW2VdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB0eXBlW2VdO1xuICAgIH0gZWxzZSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZW51bSB2YWx1ZS4nKTtcbiAgfSxcbiAgLy8gQ29udmVydHMgZnJvbSBhbiBpbnRlZ2VyIHRvIHN0cmluZy5cbiAgcmVhZDogZnVuY3Rpb24odHlwZSwgZSkge1xuICAgIGZvciAodmFyIGkgaW4gdHlwZSlcbiAgICAgIGlmICh0eXBlW2ldID09IGUpIHJldHVybiBpO1xuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGVudW0gdmFsdWUuJyk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlbnVtcztcbiIsIlxubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL29wZW5wZ3AuanMnKTtcbm1vZHVsZS5leHBvcnRzLmtleSA9IHJlcXVpcmUoJy4va2V5LmpzJyk7XG5tb2R1bGUuZXhwb3J0cy5tZXNzYWdlID0gcmVxdWlyZSgnLi9tZXNzYWdlLmpzJyk7XG5tb2R1bGUuZXhwb3J0cy51dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5tb2R1bGUuZXhwb3J0cy5wYWNrZXQgPSByZXF1aXJlKCcuL3BhY2tldCcpO1xubW9kdWxlLmV4cG9ydHMubXBpID0gcmVxdWlyZSgnLi90eXBlL21waS5qcycpO1xubW9kdWxlLmV4cG9ydHMuczJrID0gcmVxdWlyZSgnLi90eXBlL3Myay5qcycpO1xubW9kdWxlLmV4cG9ydHMua2V5aWQgPSByZXF1aXJlKCcuL3R5cGUva2V5aWQuanMnKTtcbm1vZHVsZS5leHBvcnRzLmFybW9yID0gcmVxdWlyZSgnLi9lbmNvZGluZy9hcm1vci5qcycpO1xubW9kdWxlLmV4cG9ydHMuZW51bXMgPSByZXF1aXJlKCcuL2VudW1zLmpzJyk7XG5tb2R1bGUuZXhwb3J0cy5jb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xubW9kdWxlLmV4cG9ydHMuY3J5cHRvID0gcmVxdWlyZSgnLi9jcnlwdG8nKTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBwYWNrZXQgPSByZXF1aXJlKCcuL3BhY2tldCcpO1xudmFyIGVudW1zID0gcmVxdWlyZSgnLi9lbnVtcy5qcycpO1xudmFyIGFybW9yID0gcmVxdWlyZSgnLi9lbmNvZGluZy9hcm1vci5qcycpO1xudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4vY29uZmlnJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIENsYXNzIHRoYXQgcmVwcmVzZW50cyBhbiBPcGVuUEdQIGtleS4gTXVzdCBjb250YWluIGEgbWFzdGVyIGtleS4gXG4gKiBAcGFyYW0gIHtwYWNrZXRsaXN0fSBwYWNrZXRsaXN0IFtkZXNjcmlwdGlvbl1cbiAqIENhbiBjb250YWluIGFkZGl0aW9uYWwgc3Via2V5cywgc2lnbmF0dXJlcyxcbiAqIHVzZXIgaWRzLCB1c2VyIGF0dHJpYnV0ZXMuXG4gKi9cblxuIGZ1bmN0aW9uIGtleShwYWNrZXRsaXN0KSB7XG5cbiAgdGhpcy5wYWNrZXRzID0gcGFja2V0bGlzdCB8fCBuZXcgcGFja2V0Lmxpc3QoKTtcblxuICB0aGlzLnBhc3NwaHJhc2UgPSBudWxsO1xuXG4gIC8qKiBcbiAgICogUmV0dXJucyB0aGUgcHJpbWFyeSBrZXkgcGFja2V0IChzZWNyZXQgb3IgcHVibGljKVxuICAgKiBAcmV0dXJucyB7cGFja2V0X3NlY3JldF9rZXl8cGFja2V0X3B1YmxpY19rZXl8bnVsbH0gXG4gICAqL1xuICB0aGlzLmdldEtleVBhY2tldCA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5wYWNrZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5wYWNrZXRzW2ldLnRhZyA9PSBlbnVtcy5wYWNrZXQucHVibGljX2tleSB8fFxuICAgICAgICB0aGlzLnBhY2tldHNbaV0udGFnID09IGVudW1zLnBhY2tldC5zZWNyZXRfa2V5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnBhY2tldHNbaV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIFxuICAgKiBSZXR1cm5zIGFsbCB0aGUgcHJpdmF0ZSBhbmQgcHVibGljIHN1YmtleSBwYWNrZXRzXG4gICAqIEByZXR1cm5zIHtbcHVibGljX3N1YmtleXxzZWNyZXRfc3Via2V5XX0gXG4gICAqL1xuICB0aGlzLmdldFN1YmtleVBhY2tldHMgPSBmdW5jdGlvbigpIHtcblxuICAgIHZhciBzdWJrZXlzID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFja2V0cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHRoaXMucGFja2V0c1tpXS50YWcgPT0gZW51bXMucGFja2V0LnB1YmxpY19zdWJrZXkgfHxcbiAgICAgICAgdGhpcy5wYWNrZXRzW2ldLnRhZyA9PSBlbnVtcy5wYWNrZXQuc2VjcmV0X3N1YmtleSkge1xuICAgICAgICBzdWJrZXlzLnB1c2godGhpcy5wYWNrZXRzW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3Via2V5cztcbiAgfVxuXG4gIC8qKiBcbiAgICogUmV0dXJucyBhbGwgdGhlIHByaXZhdGUgYW5kIHB1YmxpYyBrZXkgYW5kIHN1YmtleSBwYWNrZXRzXG4gICAqIEByZXR1cm5zIHtbcHVibGljX3N1YmtleXxzZWNyZXRfc3Via2V5fHBhY2tldF9zZWNyZXRfa2V5fHBhY2tldF9wdWJsaWNfa2V5XX0gXG4gICAqL1xuICB0aGlzLmdldEFsbEtleVBhY2tldHMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gW3RoaXMuZ2V0S2V5UGFja2V0KCldLmNvbmNhdCh0aGlzLmdldFN1YmtleVBhY2tldHMoKSk7XG4gIH1cblxuICAvKiogXG4gICAqIFJldHVybnMga2V5IElEcyBvZiBhbGwga2V5IHBhY2tldHNcbiAgICogQHJldHVybnMge1trZXlpZF19IFxuICAgKi9cbiAgdGhpcy5nZXRLZXlJZHMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIga2V5SWRzID0gW107XG4gICAgdmFyIGtleXMgPSB0aGlzLmdldEFsbEtleVBhY2tldHMoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGtleUlkcy5wdXNoKGtleXNbaV0uZ2V0S2V5SWQoKSk7XG4gICAgfVxuICAgIHJldHVybiBrZXlJZHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBmaXJzdCBrZXkgcGFja2V0IGZvciBnaXZlbiBhcnJheSBvZiBrZXkgSURzXG4gICAqIEBwYXJhbSAge1trZXlpZF19IGtleUlkcyBcbiAgICogQHJldHVybiB7cHVibGljX3N1YmtleXxzZWNyZXRfc3Via2V5fHBhY2tldF9zZWNyZXRfa2V5fHBhY2tldF9wdWJsaWNfa2V5fG51bGx9ICAgICAgIFxuICAgKi9cbiAgdGhpcy5nZXRLZXlQYWNrZXQgPSBmdW5jdGlvbihrZXlJZHMpIHtcbiAgICB2YXIga2V5cyA9IHRoaXMuZ2V0QWxsS2V5UGFja2V0cygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGtleUlkID0ga2V5c1tpXS5nZXRLZXlJZCgpOyBcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5SWRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChrZXlJZC5lcXVhbHMoa2V5SWRzW2pdKSkge1xuICAgICAgICAgIC8vVE9ETyByZXR1cm4gb25seSB2ZXJpZmllZCBrZXlzXG4gICAgICAgICAgcmV0dXJuIGtleXNbaV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBmaXJzdCBwcml2YXRlIGtleSBwYWNrZXQgZm9yIGdpdmVuIGFycmF5IG9mIGtleSBJRHNcbiAgICogQHBhcmFtICB7W2tleWlkXX0ga2V5SWRzXG4gICAqIEBwYXJhbSAge0Jvb2xlYW59IGRlY3J5cHRlZCBkZWNyeXB0IHByaXZhdGUga2V5IHBhY2tldFxuICAgKiBAcmV0dXJuIHtzZWNyZXRfc3Via2V5fHBhY2tldF9zZWNyZXRfa2V5fG51bGx9ICAgICAgIFxuICAgKi9cbiAgdGhpcy5nZXRQcml2YXRlS2V5UGFja2V0ID0gZnVuY3Rpb24oa2V5SWRzLCBkZWNyeXB0ZWQpIHtcbiAgICB2YXIga2V5cyA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQuc2VjcmV0X2tleSwgZW51bXMucGFja2V0LnNlY3JldF9zdWJrZXkpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGtleUlkID0ga2V5c1tpXS5nZXRLZXlJZCgpOyBcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5SWRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChrZXlJZC5lcXVhbHMoa2V5SWRzW2pdKSkge1xuICAgICAgICAgIC8vVE9ETyByZXR1cm4gb25seSB2ZXJpZmllZCBrZXlzXG4gICAgICAgICAgaWYgKGRlY3J5cHRlZCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnBhc3NwaHJhc2UpIHRocm93IG5ldyBFcnJvcignTm8gcGFzc3BocmFzZSB0byBkZWNyeXB0IGtleS4nKTtcbiAgICAgICAgICAgIGtleXNbaV0uZGVjcnlwdCh0aGlzLnBhc3NwaHJhc2UpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4ga2V5c1tpXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBpcyBhIHB1YmxpYyBrZXlcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIHRoaXMuaXNQdWJsaWMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcHVibGljS2V5UGFja2V0cyA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQucHVibGljX2tleSk7XG4gICAgcmV0dXJuIHB1YmxpY0tleVBhY2tldHMubGVuZ3RoID8gdHJ1ZSA6IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIGlzIGEgcHJpdmF0ZSBrZXlcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIHRoaXMuaXNQcml2YXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByaXZhdGVLZXlQYWNrZXRzID0gdGhpcy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5wcml2YXRlX2tleSk7XG4gICAgcmV0dXJuIHByaXZhdGVLZXlQYWNrZXRzLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGZpcnN0IGtleSBwYWNrZXQgdGhhdCBpcyBhdmFpbGFibGUgZm9yIHNpZ25pbmdcbiAgICogQHJldHVybiB7cHVibGljX3N1YmtleXxzZWNyZXRfc3Via2V5fHBhY2tldF9zZWNyZXRfa2V5fHBhY2tldF9wdWJsaWNfa2V5fG51bGx9XG4gICAqL1xuICB0aGlzLmdldFNpZ25pbmdLZXlQYWNrZXQgPSBmdW5jdGlvbigpIHtcblxuICAgIHZhciBzaWduaW5nID0gWyBlbnVtcy5wdWJsaWNLZXkucnNhX2VuY3J5cHRfc2lnbiwgZW51bXMucHVibGljS2V5LnJzYV9zaWduLCBlbnVtcy5wdWJsaWNLZXkuZHNhXTtcblxuICAgIHNpZ25pbmcgPSBzaWduaW5nLm1hcChmdW5jdGlvbihzKSB7XG4gICAgICByZXR1cm4gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIHMpO1xuICAgIH0pO1xuXG4gICAgdmFyIGtleXMgPSB0aGlzLmdldEFsbEtleVBhY2tldHMoKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHNpZ25pbmcuaW5kZXhPZihrZXlzW2ldLmFsZ29yaXRobSkgIT09IC0xKSB7XG4gICAgICAgIHJldHVybiBrZXlzW2ldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgcHJlZmVycmVkIHNpZ25hdHVyZSBoYXNoIGFsZ29yaXRobSBvZiB0aGlzIGtleVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9XG4gICAqL1xuICBmdW5jdGlvbiBnZXRQcmVmZXJyZWRTaWduYXR1cmVIYXNoQWxnb3JpdGhtKCkge1xuICAgIC8vVE9ETyBpbXBsZW1lbnQ6IGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM0ODgwI3NlY3Rpb24tNS4yLjMuOFxuICAgIC8vc2VwYXJhdGUgcHJpdmF0ZSBrZXkgcHJlZmVyZW5jZSBmcm9tIGRpZ2VzdCBwcmVmZXJlbmNlc1xuICAgIHJldHVybiBjb25maWcucHJlZmVyX2hhc2hfYWxnb3JpdGhtO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGZpcnN0IHZhbGlkIGVuY3J5cHRpb24ga2V5IHBhY2tldCBmb3IgdGhpcyBrZXlcbiAgICogQHJldHVybnMge3B1YmxpY19zdWJrZXl8c2VjcmV0X3N1YmtleXxwYWNrZXRfc2VjcmV0X2tleXxwYWNrZXRfcHVibGljX2tleXxudWxsfSBrZXkgcGFja2V0IG9yIG51bGwgaWYgbm8gZW5jcnlwdGlvbiBrZXkgaGFzIGJlZW4gZm91bmRcbiAgICovXG4gIHRoaXMuZ2V0RW5jcnlwdGlvbktleVBhY2tldCA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIFY0OiBieSBjb252ZW50aW9uIHN1YmtleXMgYXJlIHByZWZlcmVkIGZvciBlbmNyeXB0aW9uIHNlcnZpY2VcbiAgICAvLyBWMzoga2V5cyBNVVNUIE5PVCBoYXZlIHN1YmtleXNcbiAgICB2YXIgaXNWYWxpZEVuY3J5cHRpb25LZXkgPSBmdW5jdGlvbihrZXkpIHtcbiAgICAgIC8vVE9ETyBldmFsdWF0ZSBrZXkgZmxhZ3M6IGh0dHA6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzQ4ODAjc2VjdGlvbi01LjIuMy4yMVxuICAgICAgcmV0dXJuIGtleS5hbGdvcml0aG0gIT0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGVudW1zLnB1YmxpY0tleS5kc2EpICYmIGtleS5hbGdvcml0aG0gIT0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksXG4gICAgICAgIGVudW1zLnB1YmxpY0tleS5yc2Ffc2lnbik7XG4gICAgICAvL1RPRE8gdmVyaWZ5IGtleVxuICAgICAgLy8mJiBrZXlzLnZlcmlmeUtleSgpXG4gICAgfTtcblxuICAgIHZhciBzdWJrZXlzID0gdGhpcy5nZXRTdWJrZXlQYWNrZXRzKCk7XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IHN1YmtleXMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGlmIChpc1ZhbGlkRW5jcnlwdGlvbktleShzdWJrZXlzW2pdKSkge1xuICAgICAgICByZXR1cm4gc3Via2V5c1tqXTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gaWYgbm8gdmFsaWQgc3Via2V5IGZvciBlbmNyeXB0aW9uLCB1c2UgcHJpbWFyeSBrZXlcbiAgICB2YXIgcHJpbWFyeUtleSA9IHRoaXMuZ2V0S2V5UGFja2V0KCk7XG4gICAgaWYgKGlzVmFsaWRFbmNyeXB0aW9uS2V5KHByaW1hcnlLZXkpKSB7XG4gICAgICByZXR1cm4gcHJpbWFyeUtleTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogRGVjcnlwdHMgYWxsIHNlY3JldCBrZXkgYW5kIHN1YmtleSBwYWNrZXRzXG4gICAqIEBwYXJhbSAge1N0cmluZ30gcGFzc3BocmFzZSBcbiAgICogQHJldHVybiB7dW5kZWZpbmVkfVxuICAgKi9cbiAgdGhpcy5kZWNyeXB0ID0gZnVuY3Rpb24ocGFzc3BocmFzZSkge1xuICAgIC8vVE9ETyByZXR1cm4gdmFsdWVcbiAgICB2YXIga2V5cyA9IHRoaXMuZ2V0QWxsS2V5UGFja2V0cygpO1xuICAgIGZvciAodmFyIGkgaW4ga2V5cykge1xuICAgICAgaWYgKGtleXNbaV0udGFnID09IGVudW1zLnBhY2tldC5zZWNyZXRfc3Via2V5IHx8XG4gICAgICAgIGtleXNbaV0udGFnID09IGVudW1zLnBhY2tldC5zZWNyZXRfa2V5KSB7XG4gICAgICAgICAgaWYgKCFwYXNzcGhyYXNlICYmICF0aGlzLnBhc3NwaHJhc2UpIHRocm93IG5ldyBFcnJvcignTm8gcGFzc3BocmFzZSB0byBkZWNyeXB0IGtleS4nKTtcbiAgICAgICAgICBrZXlzW2ldLmRlY3J5cHQocGFzc3BocmFzZSB8fCB0aGlzLnBhc3NwaHJhc2UpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBVbmxvY2tzIHRoZSBrZXkgd2l0aCBwYXNzcGhyYXNlLCBkZWNyeXB0aW9uIG9mIHNlY3JldCBrZXlzIGRlZmVycmVkLiBUaGlzIGFsbG93cyB0byBkZWNyeXB0IHRoZSByZXF1aXJlZCBwcml2YXRlIGtleSBwYWNrZXRzIG9uIGRlbWFuZFxuICAgKiBAcGFyYW0gIHtTdHJpbmd9IHBhc3NwaHJhc2UgXG4gICAqIEByZXR1cm4ge3VuZGVmaW5lZH1cbiAgICovXG4gIHRoaXMudW5sb2NrID0gZnVuY3Rpb24ocGFzc3BocmFzZSkge1xuICAgIHRoaXMucGFzc3BocmFzZSA9IHBhc3NwaHJhc2U7XG4gIH1cblxuICAvLyBUT0RPXG4gIHRoaXMudmVyaWZ5ID0gZnVuY3Rpb24oKSB7XG5cbiAgfVxuICAvLyBUT0RPXG4gIHRoaXMucmV2b2tlID0gZnVuY3Rpb24oKSB7XG5cbiAgfVxuXG59XG5cbi8qKlxuICogcmVhZHMgYW4gT3BlblBHUCBhcm1vcmVkIHRleHQgYW5kIHJldHVybnMgYSBrZXkgb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gYXJtb3JlZFRleHQgdGV4dCB0byBiZSBwYXJzZWRcbiAqIEByZXR1cm4ge2tleX0gbmV3IGtleSBvYmplY3RcbiAqL1xua2V5LnJlYWRBcm1vcmVkID0gZnVuY3Rpb24oYXJtb3JlZFRleHQpIHtcbiAgLy9UT0RPIGhvdyBkbyB3ZSB3YW50IHRvIGhhbmRsZSBiYWQgdGV4dD8gRXhjZXB0aW9uIHRocm93aW5nXG4gIC8vVE9ETyBkb24ndCBhY2NlcHQgbm9uLWtleSBhcm1vcmVkIHRleHRzXG4gIHZhciBpbnB1dCA9IGFybW9yLmRlY29kZShhcm1vcmVkVGV4dCkub3BlbnBncDtcbiAgdmFyIHBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcbiAgcGFja2V0bGlzdC5yZWFkKGlucHV0KTtcbiAgdmFyIG5ld0tleSA9IG5ldyBrZXkocGFja2V0bGlzdCk7XG4gIHJldHVybiBuZXdLZXk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ga2V5O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHBhY2tldCA9IHJlcXVpcmUoJy4vcGFja2V0Jyk7XG52YXIgZW51bXMgPSByZXF1aXJlKCcuL2VudW1zLmpzJyk7XG52YXIgYXJtb3IgPSByZXF1aXJlKCcuL2VuY29kaW5nL2FybW9yLmpzJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIFRoZSBjbGFzcyB0aGF0IGRlYWxzIHdpdGggc3RvcmFnZSBvZiB0aGUga2V5cmluZy4gQ3VycmVudGx5IHRoZSBvbmx5IG9wdGlvbiBpcyB0byB1c2UgSFRNTDUgbG9jYWwgc3RvcmFnZS5cbiAqL1xudmFyIGtleXJpbmcgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5hcm1vcmVkUGFja2V0bGlzdHMgPSBbXTtcbiAgdGhpcy5wYXJzZWRQYWNrZXRsaXN0cyA9IFtdO1xuXG4gIC8qKlxuICAgKiBJbml0aWFsaXphdGlvbiByb3V0aW5lIGZvciB0aGUga2V5cmluZy4gVGhpcyBtZXRob2QgcmVhZHMgdGhlIFxuICAgKiBrZXlyaW5nIGZyb20gSFRNTDUgbG9jYWwgc3RvcmFnZSBhbmQgaW5pdGlhbGl6ZXMgdGhpcyBpbnN0YW5jZS5cbiAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IG9wZW5wZ3AuaW5pdCgpLlxuICAgKi9cbiAgZnVuY3Rpb24gaW5pdCgpIHtcbiAgICB2YXIgYXJtb3JlZFBhY2tldGxpc3RzID0gSlNPTi5wYXJzZSh3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oXCJhcm1vcmVkUGFja2V0bGlzdHNcIikpO1xuICAgIGlmIChhcm1vcmVkUGFja2V0bGlzdHMgPT09IG51bGwgfHwgYXJtb3JlZFBhY2tldGxpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXJtb3JlZFBhY2tldGxpc3RzID0gW107XG4gICAgfVxuICAgIHRoaXMuYXJtb3JlZFBhY2tldGxpc3RzID0gYXJtb3JlZFBhY2tldGxpc3RzO1xuXG4gICAgdmFyIHBhY2tldGxpc3Q7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcm1vcmVkUGFja2V0bGlzdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcbiAgICAgIHBhY2tldGxpc3QucmVhZChhcm1vcmVkUGFja2V0bGlzdHNbaV0pO1xuICAgICAgdGhpcy5wYXJzZWRQYWNrZXRsaXN0cy5wdXNoKHBhY2tldGxpc3QpO1xuICAgIH1cbiAgfVxuICB0aGlzLmluaXQgPSBpbml0O1xuXG4gIC8qKlxuICAgKiBTYXZlcyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUga2V5cmluZyB0byBIVE1MNSBsb2NhbCBzdG9yYWdlLlxuICAgKiBUaGUgcHJpdmF0ZUtleXMgYXJyYXkgYW5kIHB1YmxpY0tleXMgYXJyYXkgZ2V0cyBTdHJpbmdpZmllZCB1c2luZyBKU09OXG4gICAqL1xuICBmdW5jdGlvbiBzdG9yZSgpIHtcbiAgICB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oXCJhcm1vcmVkUGFja2V0bGlzdHNcIiwgSlNPTi5zdHJpbmdpZnkodGhpcy5hcm1vcmVkUGFja2V0bGlzdHMpKTtcbiAgfVxuICB0aGlzLnN0b3JlID0gc3RvcmU7XG5cbiAgZnVuY3Rpb24gZW1haWxQYWNrZXRDaGVjayhwYWNrZXQsIGVtYWlsKSB7XG4gICAgdmFyIGVtYWlsTWF0Y2ggPSBmYWxzZTtcbiAgICB2YXIgcGFja2V0RW1haWw7XG4gICAgZW1haWwgPSBlbWFpbC50b0xvd2VyQ2FzZSgpO1xuICAgIGlmIChwYWNrZXQudGFnID09IGVudW1zLnBhY2tldC51c2VyaWQpIHtcbiAgICAgIHBhY2tldEVtYWlsID0gcGFja2V0LnVzZXJpZDtcbiAgICAgIC8vd2UgbmVlZCB0byBnZXQganVzdCB0aGUgZW1haWwgZnJvbSB0aGUgdXNlcmlkIHBhY2tldFxuICAgICAgcGFja2V0RW1haWwgPSBwYWNrZXRFbWFpbC5zcGxpdCgnPCcpWzFdLnNwbGl0KCc8JylbMF0udHJpbS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKHBhY2tldEVtYWlsID09IGVtYWlsKSB7XG4gICAgICAgIGVtYWlsTWF0Y2ggPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZW1haWxNYXRjaDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGlkUGFja2V0Q2hlY2socGFja2V0LCBpZCkge1xuICAgIGlmIChwYWNrZXQuZ2V0S2V5SWQgJiYgcGFja2V0LmdldEtleUlkKCkud3JpdGUoKSA9PSBpZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGhlbHBlckNoZWNrSWRlbnRpdHlBbmRQYWNrZXRNYXRjaChpZGVudGl0eUZ1bmN0aW9uLCBpZGVudGl0eUlucHV0LCBwYWNrZXRUeXBlLCBwYWNrZXRsaXN0KSB7XG4gICAgdmFyIHBhY2tldDtcbiAgICBmb3IgKHZhciBsID0gMDsgbCA8IHBhY2tldGxpc3QubGVuZ3RoOyBsKyspIHtcbiAgICAgIHBhY2tldCA9IHBhY2tldGxpc3RbbF07XG4gICAgICBpZGVudGl0eU1hdGNoID0gaWRlbnRpdHlGdW5jdGlvbihwYWNrZXQsIGlkZW50aXR5SW5wdXQpO1xuICAgICAgaWYgKCFwYWNrZXRUeXBlKSB7XG4gICAgICAgIHBhY2tldE1hdGNoID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAocGFja2V0LnRhZyA9PSBwYWNrZXRUeXBlKSB7XG4gICAgICAgIHBhY2tldE1hdGNoID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChwYWNrZXRNYXRjaCAmJiBpZGVudGl0eU1hdGNoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBmdW5jdGlvbiBjaGVja0ZvcklkZW50aXR5QW5kUGFja2V0TWF0Y2goaWRlbnRpdHlGdW5jdGlvbiwgaWRlbnRpdHlJbnB1dCwgcGFja2V0VHlwZSkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgdmFyIHBhY2tldGxpc3Q7XG4gICAgdmFyIGlkZW50aXR5TWF0Y2g7XG4gICAgdmFyIHBhY2tldE1hdGNoO1xuICAgIGZvciAodmFyIHAgPSAwOyBwIDwgdGhpcy5wYXJzZWRQYWNrZXRsaXN0cy5sZW5ndGg7IHArKykge1xuICAgICAgaWRlbnRpdHlNYXRjaCA9IGZhbHNlO1xuICAgICAgcGFja2V0TWF0Y2ggPSBmYWxzZTtcbiAgICAgIHBhY2tldGxpc3QgPSB0aGlzLnBhcnNlZFBhY2tldGxpc3RzW3BdO1xuICAgICAgaWYgKGhlbHBlckNoZWNrSWRlbnRpdHlBbmRQYWNrZXRNYXRjaChpZGVudGl0eUZ1bmN0aW9uLCBpZGVudGl0eUlucHV0LCBwYWNrZXRUeXBlLCBwYWNrZXRsaXN0KSkge1xuICAgICAgICByZXN1bHRzLnB1c2gocGFja2V0bGlzdCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG4gIHRoaXMuY2hlY2tGb3JJZGVudGl0eUFuZFBhY2tldE1hdGNoID0gY2hlY2tGb3JJZGVudGl0eUFuZFBhY2tldE1hdGNoO1xuXG4gIC8qKlxuICAgKiBzZWFyY2hlcyBhbGwgcHVibGljIGtleXMgaW4gdGhlIGtleXJpbmcgbWF0Y2hpbmcgdGhlIGFkZHJlc3Mgb3IgYWRkcmVzcyBwYXJ0IG9mIHRoZSB1c2VyIGlkc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gZW1haWxfYWRkcmVzc1xuICAgKiBAcmV0dXJuIHtvcGVucGdwX21zZ19wdWJsaWNrZXlbXX0gVGhlIHB1YmxpYyBrZXlzIGFzc29jaWF0ZWQgd2l0aCBwcm92aWRlZCBlbWFpbCBhZGRyZXNzLlxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0UHVibGljS2V5Rm9yQWRkcmVzcyhlbWFpbCkge1xuICAgIHJldHVybiBjaGVja0ZvcklkZW50aXR5QW5kUGFja2V0TWF0Y2goZW1haWxQYWNrZXRDaGVjaywgZW1haWwsIGVudW1zLnBhY2tldC5wdWJsaWNfa2V5KTtcbiAgfVxuICB0aGlzLmdldFB1YmxpY0tleUZvckFkZHJlc3MgPSBnZXRQdWJsaWNLZXlGb3JBZGRyZXNzO1xuXG4gIC8qKlxuICAgKiBTZWFyY2hlcyB0aGUga2V5cmluZyBmb3IgYSBwcml2YXRlIGtleSBjb250YWluaW5nIHRoZSBzcGVjaWZpZWQgZW1haWwgYWRkcmVzc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gZW1haWxfYWRkcmVzcyBlbWFpbCBhZGRyZXNzIHRvIHNlYXJjaCBmb3JcbiAgICogQHJldHVybiB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleVtdfSBwcml2YXRlIGtleXMgZm91bmRcbiAgICovXG4gIGZ1bmN0aW9uIGdldFByaXZhdGVLZXlGb3JBZGRyZXNzKGVtYWlsX2FkZHJlc3MpIHtcbiAgICByZXR1cm4gY2hlY2tGb3JJZGVudGl0eUFuZFBhY2tldE1hdGNoKGVtYWlsUGFja2V0Q2hlY2ssIGVtYWlsLCBlbnVtcy5wYWNrZXQuc2VjcmV0X2tleSk7XG4gIH1cbiAgdGhpcy5nZXRQcml2YXRlS2V5Rm9yQWRkcmVzcyA9IGdldFByaXZhdGVLZXlGb3JBZGRyZXNzO1xuXG4gIC8qKlxuICAgKiBTZWFyY2hlcyB0aGUga2V5cmluZyBmb3IgcHVibGljIGtleXMgaGF2aW5nIHRoZSBzcGVjaWZpZWQga2V5IGlkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBrZXlJZCBwcm92aWRlZCBhcyBzdHJpbmcgb2YgaGV4IG51bWJlciAobG93ZXJjYXNlKVxuICAgKiBAcmV0dXJuIHtvcGVucGdwX21zZ19wcml2YXRla2V5W119IHB1YmxpYyBrZXlzIGZvdW5kXG4gICAqL1xuICBmdW5jdGlvbiBnZXRQYWNrZXRsaXN0c0ZvcktleUlkKGtleUlkKSB7XG4gICAgcmV0dXJuIHRoaXMuY2hlY2tGb3JJZGVudGl0eUFuZFBhY2tldE1hdGNoKGlkUGFja2V0Q2hlY2ssIGtleUlkKTtcbiAgfVxuICB0aGlzLmdldFBhY2tldGxpc3RzRm9yS2V5SWQgPSBnZXRQYWNrZXRsaXN0c0ZvcktleUlkO1xuXG4gIC8qKlxuICAgKiBJbXBvcnRzIGEgcGFja2V0IGxpc3QgKHB1YmxpYyBvciBwcml2YXRlIGtleSBibG9jaykgZnJvbSBhbiBhc2NpaSBhcm1vcmVkIG1lc3NhZ2UgXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBhcm1vcmVkIG1lc3NhZ2UgdG8gcmVhZCB0aGUgcGFja2V0cy9rZXkgZnJvbVxuICAgKi9cbiAgZnVuY3Rpb24gaW1wb3J0UGFja2V0bGlzdChhcm1vcmVkKSB7XG4gICAgdGhpcy5hcm1vcmVkUGFja2V0bGlzdHMucHVzaChhcm1vcmVkKTtcblxuICAgIHZhciBkZWFybW9yZWQgPSBhcm1vci5kZWNvZGUoYXJtb3JlZC5yZXBsYWNlKC9cXHIvZywgJycpKS5vcGVucGdwO1xuXG4gICAgcGFja2V0bGlzdCA9IG5ldyBwYWNrZXQubGlzdCgpO1xuICAgIHBhY2tldGxpc3QucmVhZChkZWFybW9yZWQpO1xuICAgIHRoaXMucGFyc2VkUGFja2V0bGlzdHMucHVzaChwYWNrZXRsaXN0KTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHRoaXMuaW1wb3J0UGFja2V0bGlzdCA9IGltcG9ydFBhY2tldGxpc3Q7XG5cbiAgLyoqXG4gICAqIFRPRE9cbiAgICogcmV0dXJucyB0aGUgb3BlbnBncF9tc2dfcHJpdmF0ZWtleSByZXByZXNlbnRhdGlvbiBvZiB0aGUgcHVibGljIGtleSBhdCBwdWJsaWMga2V5IHJpbmcgaW5kZXggIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGluZGV4IHRoZSBpbmRleCBvZiB0aGUgcHVibGljIGtleSB3aXRoaW4gdGhlIHB1YmxpY0tleXMgYXJyYXlcbiAgICogQHJldHVybiB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0gdGhlIHB1YmxpYyBrZXkgb2JqZWN0XG4gICAqL1xuICBmdW5jdGlvbiBleHBvcnRQdWJsaWNLZXkoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5wdWJsaWNLZXlbaW5kZXhdO1xuICB9XG4gIHRoaXMuZXhwb3J0UHVibGljS2V5ID0gZXhwb3J0UHVibGljS2V5O1xuXG4gIC8qKlxuICAgKiBUT0RPXG4gICAqIFJlbW92ZXMgYSBwdWJsaWMga2V5IGZyb20gdGhlIHB1YmxpYyBrZXkga2V5cmluZyBhdCB0aGUgc3BlY2lmaWVkIGluZGV4IFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGluZGV4IHRoZSBpbmRleCBvZiB0aGUgcHVibGljIGtleSB3aXRoaW4gdGhlIHB1YmxpY0tleXMgYXJyYXlcbiAgICogQHJldHVybiB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0gVGhlIHB1YmxpYyBrZXkgb2JqZWN0IHdoaWNoIGhhcyBiZWVuIHJlbW92ZWRcbiAgICovXG4gIGZ1bmN0aW9uIHJlbW92ZVB1YmxpY0tleShpbmRleCkge1xuICAgIHZhciByZW1vdmVkID0gdGhpcy5wdWJsaWNLZXlzLnNwbGljZShpbmRleCwgMSk7XG4gICAgdGhpcy5zdG9yZSgpO1xuICAgIHJldHVybiByZW1vdmVkO1xuICB9XG4gIHRoaXMucmVtb3ZlUHVibGljS2V5ID0gcmVtb3ZlUHVibGljS2V5O1xuXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBrZXlyaW5nKCk7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgcGFja2V0ID0gcmVxdWlyZSgnLi9wYWNrZXQnKTtcbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4vZW51bXMuanMnKTtcbnZhciBhcm1vciA9IHJlcXVpcmUoJy4vZW5jb2RpbmcvYXJtb3IuanMnKTtcbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xudmFyIGNyeXB0byA9IHJlcXVpcmUoJy4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEEgZ2VuZXJpYyBtZXNzYWdlIGNvbnRhaW5pbmcgb25lIG9yIG1vcmUgbGl0ZXJhbCBwYWNrZXRzLlxuICovXG5cbmZ1bmN0aW9uIG1lc3NhZ2UocGFja2V0bGlzdCkge1xuXG4gIHRoaXMucGFja2V0cyA9IHBhY2tldGxpc3QgfHwgbmV3IHBhY2tldC5saXN0KCk7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGtleSBJRHMgb2YgdGhlIHB1YmxpYyBrZXlzIHRvIHdoaWNoIHRoZSBzZXNzaW9uIGtleSBpcyBlbmNyeXB0ZWRcbiAgICogQHJldHVybiB7W2tleUlkXX0gYXJyYXkgb2Yga2V5aWQgb2JqZWN0c1xuICAgKi9cbiAgdGhpcy5nZXRFbmNyeXB0aW9uS2V5SWRzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGtleUlkcyA9IFtdO1xuICAgIHZhciBwa0VTS2V5UGFja2V0bGlzdCA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQucHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkpO1xuICAgIHBrRVNLZXlQYWNrZXRsaXN0LmZvckVhY2goZnVuY3Rpb24ocGFja2V0KSB7XG4gICAgICBrZXlJZHMucHVzaChwYWNrZXQucHVibGljS2V5SWQpO1xuICAgIH0pO1xuICAgIHJldHVybiBrZXlJZHM7XG4gIH1cblxuICAvKipcbiAgICogRGVjcnlwdCB0aGUgbWVzc2FnZVxuICAgKiBAcGFyYW0ge2tleX0gcHJpdmF0ZUtleSB1bmxvY2tlZCBwcml2YXRlIGtleSBmb3Igd2hpY2ggdGhlIG1lc3NhZ2UgaXMgZW5jcnlwdGVkIChjb3JyZXNwb25kaW5nIHRvIHRoZSBzZXNzaW9uIGtleSlcbiAgICogQHJldHVybiB7W21lc3NhZ2VdfSBuZXcgbWVzc2FnZSB3aXRoIGRlY3J5cHRlZCBjb250ZW50XG4gICAqL1xuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihwcml2YXRlS2V5KSB7XG4gICAgdmFyIGVuY3J5cHRpb25LZXlJZHMgPSB0aGlzLmdldEVuY3J5cHRpb25LZXlJZHMoKTtcbiAgICBpZiAoIWVuY3J5cHRpb25LZXlJZHMubGVuZ3RoKSB7XG4gICAgICAvLyBub3RoaW5nIHRvIGRlY3J5cHQgcmV0dXJuIHVubW9kaWZpZWQgbWVzc2FnZVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIHZhciBwcml2YXRlS2V5UGFja2V0ID0gcHJpdmF0ZUtleS5nZXRQcml2YXRlS2V5UGFja2V0KGVuY3J5cHRpb25LZXlJZHMsIHRydWUpO1xuICAgIHZhciBwa0VTS2V5UGFja2V0bGlzdCA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQucHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkpO1xuICAgIHZhciBwa0VTS2V5UGFja2V0O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGtFU0tleVBhY2tldGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChwa0VTS2V5UGFja2V0bGlzdFtpXS5wdWJsaWNLZXlJZC5lcXVhbHMocHJpdmF0ZUtleVBhY2tldC5nZXRLZXlJZCgpKSkge1xuICAgICAgICBwa0VTS2V5UGFja2V0ID0gcGtFU0tleVBhY2tldGxpc3RbaV07XG4gICAgICAgIHBrRVNLZXlQYWNrZXQuZGVjcnlwdChwcml2YXRlS2V5UGFja2V0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChwa0VTS2V5UGFja2V0KSB7XG4gICAgICB2YXIgc3ltRW5jcnlwdGVkUGFja2V0bGlzdCA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQuc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQsIGVudW1zLnBhY2tldC5zeW1fZW5jcnlwdGVkX2ludGVncml0eV9wcm90ZWN0ZWQpO1xuICAgICAgaWYgKHN5bUVuY3J5cHRlZFBhY2tldGxpc3QubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIHZhciBzeW1FbmNyeXB0ZWRQYWNrZXQgPSBzeW1FbmNyeXB0ZWRQYWNrZXRsaXN0WzBdO1xuICAgICAgICBzeW1FbmNyeXB0ZWRQYWNrZXQuZGVjcnlwdChwa0VTS2V5UGFja2V0LnNlc3Npb25LZXlBbGdvcml0aG0sIHBrRVNLZXlQYWNrZXQuc2Vzc2lvbktleSk7XG4gICAgICAgIHJldHVybiBuZXcgbWVzc2FnZShzeW1FbmNyeXB0ZWRQYWNrZXQucGFja2V0cyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBsaXRlcmFsIGRhdGEgdGhhdCBpcyB0aGUgYm9keSBvZiB0aGUgbWVzc2FnZVxuICAgKiBAcmV0dXJuIHtTdHJpbmd8bnVsbH0gbGl0ZXJhbCBib2R5IG9mIHRoZSBtZXNzYWdlIGFzIHN0cmluZ1xuICAgKi9cbiAgdGhpcy5nZXRMaXRlcmFsID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGxpdGVyYWwgPSB0aGlzLnBhY2tldHMuZmluZFBhY2tldChlbnVtcy5wYWNrZXQubGl0ZXJhbCk7XG4gICAgcmV0dXJuIGxpdGVyYWwgJiYgbGl0ZXJhbC5kYXRhIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogRW5jcnlwdCB0aGUgbWVzc2FnZVxuICAgKiBAcGFyYW0gIHtba2V5XX0ga2V5cyBhcnJheSBvZiBrZXlzLCB1c2VkIHRvIGVuY3J5cHQgdGhlIG1lc3NhZ2VcbiAgICogQHJldHVybiB7W21lc3NhZ2VdfSBuZXcgbWVzc2FnZSB3aXRoIGVuY3J5cHRlZCBjb250ZW50XG4gICAqL1xuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihrZXlzKSB7XG4gICAgdmFyIHBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcbiAgICAvL1RPRE8gZ2V0IHByZWZlcnJlZCBhbGdvIGZyb20gc2lnbmF0dXJlXG4gICAgdmFyIHNlc3Npb25LZXkgPSBjcnlwdG8uZ2VuZXJhdGVTZXNzaW9uS2V5KGVudW1zLnJlYWQoZW51bXMuc3ltbWV0cmljLCBjb25maWcuZW5jcnlwdGlvbl9jaXBoZXIpKTtcbiAgICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgICB2YXIgZW5jcnlwdGlvbktleVBhY2tldCA9IGtleS5nZXRFbmNyeXB0aW9uS2V5UGFja2V0KCk7XG4gICAgICBpZiAoZW5jcnlwdGlvbktleVBhY2tldCkge1xuICAgICAgICB2YXIgcGtFU0tleVBhY2tldCA9IG5ldyBwYWNrZXQucHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkoKTtcbiAgICAgICAgcGtFU0tleVBhY2tldC5wdWJsaWNLZXlJZCA9IGVuY3J5cHRpb25LZXlQYWNrZXQuZ2V0S2V5SWQoKTtcbiAgICAgICAgcGtFU0tleVBhY2tldC5wdWJsaWNLZXlBbGdvcml0aG0gPSBlbmNyeXB0aW9uS2V5UGFja2V0LmFsZ29yaXRobTtcbiAgICAgICAgcGtFU0tleVBhY2tldC5zZXNzaW9uS2V5ID0gc2Vzc2lvbktleTtcbiAgICAgICAgLy9UT0RPIGdldCBwcmVmZXJyZWQgYWxnbyBmcm9tIHNpZ25hdHVyZVxuICAgICAgICBwa0VTS2V5UGFja2V0LnNlc3Npb25LZXlBbGdvcml0aG0gPSBlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyKTtcbiAgICAgICAgcGtFU0tleVBhY2tldC5lbmNyeXB0KGVuY3J5cHRpb25LZXlQYWNrZXQpO1xuICAgICAgICBwYWNrZXRsaXN0LnB1c2gocGtFU0tleVBhY2tldCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdmFyIHN5bUVuY3J5cHRlZFBhY2tldDtcbiAgICBpZiAoY29uZmlnLmludGVncml0eV9wcm90ZWN0KSB7XG4gICAgICBzeW1FbmNyeXB0ZWRQYWNrZXQgPSBuZXcgcGFja2V0LnN5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzeW1FbmNyeXB0ZWRQYWNrZXQgPSBuZXcgcGFja2V0LnN5bW1ldHJpY2FsbHlfZW5jcnlwdGVkKCk7XG4gICAgfVxuICAgIHN5bUVuY3J5cHRlZFBhY2tldC5wYWNrZXRzID0gdGhpcy5wYWNrZXRzO1xuICAgIC8vVE9ETyBnZXQgcHJlZmVycmVkIGFsZ28gZnJvbSBzaWduYXR1cmVcbiAgICBzeW1FbmNyeXB0ZWRQYWNrZXQuZW5jcnlwdChlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyKSwgc2Vzc2lvbktleSk7XG4gICAgcGFja2V0bGlzdC5wdXNoKHN5bUVuY3J5cHRlZFBhY2tldCk7XG4gICAgcmV0dXJuIG5ldyBtZXNzYWdlKHBhY2tldGxpc3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIGEgbWVzc2FnZSBhbmQgZ2VuZXJhdGVzIHVzZXIgaW50ZXJmYWNlIG1lc3NhZ2Ugb3V0IG9mIHRoZSBmb3VuZC5cbiAgICogTURDIHdpbGwgYmUgdmVyaWZpZWQgYXMgd2VsbCBhcyBtZXNzYWdlIHNpZ25hdHVyZXNcbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19wcml2YXRla2V5fSBwcml2YXRlX2tleSB0aGUgcHJpdmF0ZSB0aGUgbWVzc2FnZSBpcyBlbmNyeXB0ZWQgd2l0aCAoY29ycmVzcG9uZGluZyB0byB0aGUgc2Vzc2lvbiBrZXkpXG4gICAqIEBwYXJhbSB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkc2Vzc2lvbmtleX0gc2Vzc2lvbmtleSB0aGUgc2Vzc2lvbiBrZXkgdG8gYmUgdXNlZCB0byBkZWNyeXB0IHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHVibGlja2V5fSBwdWJrZXkgQXJyYXkgb2YgcHVibGljIGtleXMgdG8gY2hlY2sgc2lnbmF0dXJlIGFnYWluc3QuIElmIG5vdCBwcm92aWRlZCwgY2hlY2tzIGxvY2FsIGtleXN0b3JlLlxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IHBsYWludGV4dCBvZiB0aGUgbWVzc2FnZSBvciBudWxsIG9uIGVycm9yXG4gICAqL1xuICBmdW5jdGlvbiBkZWNyeXB0QW5kVmVyaWZ5U2lnbmF0dXJlKHByaXZhdGVfa2V5LCBzZXNzaW9ua2V5LCBwdWJrZXkpIHtcbiAgICBpZiAocHJpdmF0ZV9rZXkgPT0gbnVsbCB8fCBzZXNzaW9ua2V5ID09IG51bGwgfHwgc2Vzc2lvbmtleSA9PSBcIlwiKVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgdmFyIGRlY3J5cHRlZCA9IHNlc3Npb25rZXkuZGVjcnlwdCh0aGlzLCBwcml2YXRlX2tleS5rZXltYXRlcmlhbCk7XG4gICAgaWYgKGRlY3J5cHRlZCA9PSBudWxsKVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgdmFyIHBhY2tldDtcbiAgICB2YXIgcG9zaXRpb24gPSAwO1xuICAgIHZhciBsZW4gPSBkZWNyeXB0ZWQubGVuZ3RoO1xuICAgIHZhciB2YWxpZFNpZ25hdHVyZXMgPSBuZXcgQXJyYXkoKTtcbiAgICB1dGlsLnByaW50X2RlYnVnX2hleHN0cl9kdW1wKFwib3BlbnBncC5tc2cubWVzc2dlIGRlY3J5cHQ6XFxuXCIsIGRlY3J5cHRlZCk7XG5cbiAgICB2YXIgbWVzc2FnZXMgPSBvcGVucGdwLnJlYWRfbWVzc2FnZXNfZGVhcm1vcmVkKHtcbiAgICAgIHRleHQ6IGRlY3J5cHRlZCxcbiAgICAgIG9wZW5wZ3A6IGRlY3J5cHRlZFxuICAgIH0pO1xuICAgIGZvciAodmFyIG0gaW4gbWVzc2FnZXMpIHtcbiAgICAgIGlmIChtZXNzYWdlc1ttXS5kYXRhKSB7XG4gICAgICAgIHRoaXMudGV4dCA9IG1lc3NhZ2VzW21dLmRhdGE7XG4gICAgICB9XG4gICAgICBpZiAobWVzc2FnZXNbbV0uc2lnbmF0dXJlKSB7XG4gICAgICAgIHZhbGlkU2lnbmF0dXJlcy5wdXNoKG1lc3NhZ2VzW21dLnZlcmlmeVNpZ25hdHVyZShwdWJrZXkpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHRleHQ6IHRoaXMudGV4dCxcbiAgICAgIHZhbGlkU2lnbmF0dXJlczogdmFsaWRTaWduYXR1cmVzXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWZXJpZmllcyBhIG1lc3NhZ2Ugc2lnbmF0dXJlLiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBjYWxsZWQgYWZ0ZXIgcmVhZF9tZXNzYWdlIGlmIHRoZSBtZXNzYWdlIHdhcyBzaWduZWQgb25seS5cbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19wdWJsaWNrZXl9IHB1YmtleSBBcnJheSBvZiBwdWJsaWMga2V5cyB0byBjaGVjayBzaWduYXR1cmUgYWdhaW5zdC4gSWYgbm90IHByb3ZpZGVkLCBjaGVja3MgbG9jYWwga2V5c3RvcmUuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgdGhlIHNpZ25hdHVyZSB3YXMgY29ycmVjdDsgb3RoZXJ3aXNlIGZhbHNlXG4gICAqL1xuICBmdW5jdGlvbiB2ZXJpZnlTaWduYXR1cmUocHVia2V5KSB7XG4gICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLnNpZ25hdHVyZS50YWdUeXBlID09IDIpIHtcbiAgICAgIGlmICghcHVia2V5IHx8IHB1YmtleS5sZW5ndGggPT0gMCkge1xuICAgICAgICB2YXIgcHVia2V5O1xuICAgICAgICBpZiAodGhpcy5zaWduYXR1cmUudmVyc2lvbiA9PSA0KSB7XG4gICAgICAgICAgcHVia2V5ID0gb3BlbnBncC5rZXlyaW5nLmdldFB1YmxpY0tleXNGb3JLZXlJZCh0aGlzLnNpZ25hdHVyZS5pc3N1ZXJLZXlJZCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zaWduYXR1cmUudmVyc2lvbiA9PSAzKSB7XG4gICAgICAgICAgcHVia2V5ID0gb3BlbnBncC5rZXlyaW5nLmdldFB1YmxpY0tleXNGb3JLZXlJZCh0aGlzLnNpZ25hdHVyZS5rZXlJZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXRpbC5wcmludF9lcnJvcihcInVua25vd24gc2lnbmF0dXJlIHR5cGUgb24gbWVzc2FnZSFcIik7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocHVia2V5Lmxlbmd0aCA9PSAwKVxuICAgICAgICB1dGlsLnByaW50X3dhcm5pbmcoXCJVbmFibGUgdG8gdmVyaWZ5IHNpZ25hdHVyZSBvZiBpc3N1ZXI6IFwiICsgdXRpbC5oZXhzdHJkdW1wKHRoaXMuc2lnbmF0dXJlLmlzc3VlcktleUlkKSArXG4gICAgICAgICAgXCIuIFB1YmxpYyBrZXkgbm90IGZvdW5kIGluIGtleXJpbmcuXCIpO1xuICAgICAgZWxzZSB7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHVia2V5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHRvaGFzaCA9IHRoaXMudGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZSgvXFxuL2csIFwiXFxyXFxuXCIpO1xuICAgICAgICAgIGlmICh0aGlzLnNpZ25hdHVyZS52ZXJpZnkodG9oYXNoLCBwdWJrZXlbaV0pKSB7XG4gICAgICAgICAgICB1dGlsLnByaW50X2luZm8oXCJGb3VuZCBHb29kIFNpZ25hdHVyZSBmcm9tIFwiICsgcHVia2V5W2ldLm9iai51c2VySWRzWzBdLnRleHQgKyBcIiAoMHhcIiArIHV0aWwuaGV4c3RyZHVtcChcbiAgICAgICAgICAgICAgcHVia2V5W2ldLm9iai5nZXRLZXlJZCgpKS5zdWJzdHJpbmcoOCkgKyBcIilcIik7XG4gICAgICAgICAgICByZXN1bHQgPSB0cnVlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1dGlsLnByaW50X2Vycm9yKFwiU2lnbmF0dXJlIHZlcmlmaWNhdGlvbiBmYWlsZWQ6IEJhZCBTaWduYXR1cmUgZnJvbSBcIiArIHB1YmtleVtpXS5vYmoudXNlcklkc1swXS50ZXh0ICtcbiAgICAgICAgICAgICAgXCIgKDB4XCIgKyB1dGlsLmhleHN0cmR1bXAocHVia2V5WzBdLm9iai5nZXRLZXlJZCgpKS5zdWJzdHJpbmcoOCkgKyBcIilcIik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxuLyoqXG4gKiByZWFkcyBhbiBPcGVuUEdQIGFybW9yZWQgbWVzc2FnZSBhbmQgcmV0dXJucyBhIG1lc3NhZ2Ugb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gYXJtb3JlZFRleHQgdGV4dCB0byBiZSBwYXJzZWRcbiAqIEByZXR1cm4ge21lc3NhZ2V9IG5ldyBtZXNzYWdlIG9iamVjdFxuICovXG5tZXNzYWdlLnJlYWRBcm1vcmVkID0gZnVuY3Rpb24oYXJtb3JlZFRleHQpIHtcbiAgLy9UT0RPIGhvdyBkbyB3ZSB3YW50IHRvIGhhbmRsZSBiYWQgdGV4dD8gRXhjZXB0aW9uIHRocm93aW5nXG4gIC8vVE9ETyBkb24ndCBhY2NlcHQgbm9uLW1lc3NhZ2UgYXJtb3JlZCB0ZXh0c1xuICB2YXIgaW5wdXQgPSBhcm1vci5kZWNvZGUoYXJtb3JlZFRleHQpLm9wZW5wZ3A7XG4gIHZhciBwYWNrZXRsaXN0ID0gbmV3IHBhY2tldC5saXN0KCk7XG4gIHBhY2tldGxpc3QucmVhZChpbnB1dCk7XG4gIHZhciBuZXdNZXNzYWdlID0gbmV3IG1lc3NhZ2UocGFja2V0bGlzdCk7XG4gIHJldHVybiBuZXdNZXNzYWdlO1xufVxuXG4vKipcbiAqIGNyZWF0ZXMgbmV3IG1lc3NhZ2Ugb2JqZWN0IGZyb20gdGV4dFxuICogQHBhcmFtIHtTdHJpbmd9IHRleHRcbiAqIEByZXR1cm4ge21lc3NhZ2V9IG5ldyBtZXNzYWdlIG9iamVjdFxuICovXG5tZXNzYWdlLmZyb21UZXh0ID0gZnVuY3Rpb24odGV4dCkge1xuICB2YXIgbGl0ZXJhbERhdGFQYWNrZXQgPSBuZXcgcGFja2V0LmxpdGVyYWwoKTtcbiAgLy8gdGV4dCB3aWxsIGJlIGNvbnZlcnRlZCB0byBVVEY4XG4gIGxpdGVyYWxEYXRhUGFja2V0LnNldCh0ZXh0KTtcbiAgdmFyIGxpdGVyYWxEYXRhUGFja2V0bGlzdCA9IG5ldyBwYWNrZXQubGlzdCgpO1xuICBsaXRlcmFsRGF0YVBhY2tldGxpc3QucHVzaChsaXRlcmFsRGF0YVBhY2tldCk7XG4gIHZhciBuZXdNZXNzYWdlID0gbmV3IG1lc3NhZ2UobGl0ZXJhbERhdGFQYWNrZXRsaXN0KTtcbiAgcmV0dXJuIG5ld01lc3NhZ2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWVzc2FnZTsiLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXcgVGhlIG9wZW5wZ3AgYmFzZSBjbGFzcyBzaG91bGQgcHJvdmlkZSBhbGwgb2YgdGhlIGZ1bmN0aW9uYWxpdHkgXG4gKiB0byBjb25zdW1lIHRoZSBvcGVucGdwLmpzIGxpYnJhcnkuIEFsbCBhZGRpdGlvbmFsIGNsYXNzZXMgYXJlIGRvY3VtZW50ZWQgXG4gKiBmb3IgZXh0ZW5kaW5nIGFuZCBkZXZlbG9waW5nIG9uIHRvcCBvZiB0aGUgYmFzZSBsaWJyYXJ5LlxuICovXG5cbnZhciBhcm1vciA9IHJlcXVpcmUoJy4vZW5jb2RpbmcvYXJtb3IuanMnKTtcbnZhciBwYWNrZXQgPSByZXF1aXJlKCcuL3BhY2tldCcpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4vZW51bXMuanMnKTtcbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xudmFyIG1lc3NhZ2UgPSByZXF1aXJlKCcuL21lc3NhZ2UuanMnKTtcblxuLyoqXG4gKiBHUEc0QnJvd3NlcnMgQ29yZSBpbnRlcmZhY2UuIEEgc2luZ2xlIGluc3RhbmNlIGlzIGhvbGRcbiAqIGZyb20gdGhlIGJlZ2lubmluZy4gVG8gdXNlIHRoaXMgbGlicmFyeSBjYWxsIFwib3BlbnBncC5pbml0KClcIlxuICogQGFsaWFzIG9wZW5wZ3BcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBNYWluIE9wZW5wZ3AuanMgY2xhc3MuIFVzZSB0aGlzIHRvIGluaXRpYXRlIGFuZCBtYWtlIGFsbCBjYWxscyB0byB0aGlzIGxpYnJhcnkuXG4gKi9cbmZ1bmN0aW9uIF9vcGVucGdwKCkge1xuXG4gIC8qKlxuICAgKiBlbmNyeXB0cyBtZXNzYWdlIHdpdGgga2V5c1xuICAgKiBAcGFyYW0gIHtba2V5XX0ga2V5cyAgICBhcnJheSBvZiBrZXlzLCB1c2VkIHRvIGVuY3J5cHQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtICB7U3RyaW5nfSB0ZXh0IG1lc3NhZ2UgYXMgbmF0aXZlIEphdmFTY3JpcHQgc3RyaW5nXG4gICAqIEByZXR1cm4ge1N0cmluZ30gICAgICAgICBlbmNyeXB0ZWQgQVNDSUkgYXJtb3JlZCBtZXNzYWdlIFxuICAgKi9cbiAgZnVuY3Rpb24gZW5jcnlwdE1lc3NhZ2Uoa2V5cywgdGV4dCkge1xuICAgIHZhciBtc2cgPSBtZXNzYWdlLmZyb21UZXh0KHRleHQpO1xuICAgIG1zZyA9IG1zZy5lbmNyeXB0KGtleXMpO1xuICAgIHZhciBhcm1vcmVkID0gYXJtb3IuZW5jb2RlKGVudW1zLmFybW9yLm1lc3NhZ2UsIG1zZy5wYWNrZXRzLndyaXRlKCkpO1xuICAgIHJldHVybiBhcm1vcmVkO1xuICB9XG5cbiAgZnVuY3Rpb24gZW5jcnlwdEFuZFNpZ25NZXNzYWdlKHB1YmxpY0tleXMsIHByaXZhdGVLZXksIG1lc3NhZ2UpIHtcblxuICB9XG5cbiAgLyoqXG4gICAqIGRlY3J5cHRzIG1lc3NhZ2VcbiAgICogQHBhcmFtICB7a2V5fSBwcml2YXRlS2V5IHVubG9ja2VkIHByaXZhdGUga2V5XG4gICAqIEBwYXJhbSAge21lc3NhZ2V9IG1lc3NhZ2UgdGhlIG1lc3NhZ2Ugb2JqZWN0IHdpdGggdGhlIGVuY3J5cHRlZCBkYXRhXG4gICAqIEByZXR1cm4ge1N0cmluZ3xudWxsfSAgICAgICAgIGRlY3J5cHRlZCBtZXNzYWdlIGFzIGFzIG5hdGl2ZSBKYXZhU2NyaXB0IHN0cmluZ1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvciBudWxsIGlmIG5vIGxpdGVyYWwgZGF0YSBmb3VuZFxuICAgKi9cbiAgZnVuY3Rpb24gZGVjcnlwdE1lc3NhZ2UocHJpdmF0ZUtleSwgbWVzc2FnZSkge1xuICAgIG1lc3NhZ2UgPSBtZXNzYWdlLmRlY3J5cHQocHJpdmF0ZUtleSk7XG4gICAgcmV0dXJuIG1lc3NhZ2UuZ2V0TGl0ZXJhbCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVjcnlwdEFuZFZlcmlmeU1lc3NhZ2UocHJpdmF0ZUtleSwgcHVibGljS2V5cywgbWVzc2FnZVBhY2tldGxpc3QpIHtcblxuICB9XG5cbiAgZnVuY3Rpb24gdmVyaWZ5TWVzc2FnZShwdWJsaWNLZXlzLCBtZXNzYWdlUGFja2V0bGlzdCkge1xuXG4gIH1cblxuICBmdW5jdGlvbiBzaWduTWVzc2FnZShwcml2YXRlS2V5LCBtZXNzYWdlUGFja2V0bGlzdCkge1xuXG4gIH1cblxuICAvKipcbiAgICogVE9ETzogdXBkYXRlIHRoaXMgZG9jXG4gICAqIGdlbmVyYXRlcyBhIG5ldyBrZXkgcGFpciBmb3Igb3BlbnBncC4gQmV0YSBzdGFnZS4gQ3VycmVudGx5IG9ubHkgXG4gICAqIHN1cHBvcnRzIFJTQSBrZXlzLCBhbmQgbm8gc3Via2V5cy5cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBrZXlUeXBlIHRvIGluZGljYXRlIHdoYXQgdHlwZSBvZiBrZXkgdG8gbWFrZS4gXG4gICAqIFJTQSBpcyAxLiBGb2xsb3dzIGFsZ29yaXRobXMgb3V0bGluZWQgaW4gT3BlblBHUC5cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBudW1CaXRzIG51bWJlciBvZiBiaXRzIGZvciB0aGUga2V5IGNyZWF0aW9uLiAoc2hvdWxkIFxuICAgKiBiZSAxMDI0KywgZ2VuZXJhbGx5KVxuICAgKiBAcGFyYW0ge1N0cmluZ30gdXNlcklkIGFzc3VtZXMgYWxyZWFkeSBpbiBmb3JtIG9mIFwiVXNlciBOYW1lIFxuICAgKiA8dXNlcm5hbWVAZW1haWwuY29tPlwiXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYXNzcGhyYXNlIFRoZSBwYXNzcGhyYXNlIHVzZWQgdG8gZW5jcnlwdCB0aGUgcmVzdWx0aW5nIHByaXZhdGUga2V5XG4gICAqIEByZXR1cm4ge09iamVjdH0ge3ByaXZhdGVLZXk6IFtvcGVucGdwX21zZ19wcml2YXRla2V5XSwgXG4gICAqIHByaXZhdGVLZXlBcm1vcmVkOiBbc3RyaW5nXSwgcHVibGljS2V5QXJtb3JlZDogW3N0cmluZ119XG4gICAqL1xuICBmdW5jdGlvbiBnZW5lcmF0ZUtleVBhaXIoa2V5VHlwZSwgbnVtQml0cywgdXNlcklkLCBwYXNzcGhyYXNlKSB7XG4gICAgdmFyIHBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcblxuICAgIHZhciBzZWNyZXRLZXlQYWNrZXQgPSBuZXcgcGFja2V0LnNlY3JldF9rZXkoKTtcbiAgICBzZWNyZXRLZXlQYWNrZXQuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGtleVR5cGUpO1xuICAgIHNlY3JldEtleVBhY2tldC5nZW5lcmF0ZShudW1CaXRzKTtcbiAgICBzZWNyZXRLZXlQYWNrZXQuZW5jcnlwdChwYXNzcGhyYXNlKTtcblxuICAgIHZhciB1c2VySWRQYWNrZXQgPSBuZXcgcGFja2V0LnVzZXJpZCgpO1xuICAgIHVzZXJJZFBhY2tldC5yZWFkKHVzZXJJZCk7XG5cbiAgICB2YXIgZGF0YVRvU2lnbiA9IHt9O1xuICAgIGRhdGFUb1NpZ24udXNlcmlkID0gdXNlcklkUGFja2V0O1xuICAgIGRhdGFUb1NpZ24ua2V5ID0gc2VjcmV0S2V5UGFja2V0O1xuICAgIHZhciBzaWduYXR1cmVQYWNrZXQgPSBuZXcgcGFja2V0LnNpZ25hdHVyZSgpO1xuICAgIHNpZ25hdHVyZVBhY2tldC5pc3N1ZXJLZXlJZCA9IHNlY3JldEtleVBhY2tldC5nZXRLZXlJZCgpLndyaXRlKCk7XG4gICAgc2lnbmF0dXJlUGFja2V0LnNpZ25hdHVyZVR5cGUgPSBlbnVtcy5zaWduYXR1cmUuY2VydF9nZW5lcmljO1xuICAgIHNpZ25hdHVyZVBhY2tldC5wdWJsaWNLZXlBbGdvcml0aG0gPSBrZXlUeXBlO1xuICAgIC8vVE9ETyB3ZSBzaG91bGQgbG9hZCBwcmVmZXJyZWQgaGFzaCBmcm9tIGNvbmZpZywgb3IgYXMgaW5wdXQgdG8gdGhpcyBmdW5jdGlvblxuICAgIHNpZ25hdHVyZVBhY2tldC5oYXNoQWxnb3JpdGhtID0gZW51bXMuaGFzaC5zaGEyNTY7XG4gICAgc2lnbmF0dXJlUGFja2V0LnNpZ24oc2VjcmV0S2V5UGFja2V0LCBkYXRhVG9TaWduKTtcblxuICAgIHZhciBzZWNyZXRTdWJrZXlQYWNrZXQgPSBuZXcgcGFja2V0LnNlY3JldF9zdWJrZXkoKTtcbiAgICBzZWNyZXRTdWJrZXlQYWNrZXQuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGtleVR5cGUpO1xuICAgIHNlY3JldFN1YmtleVBhY2tldC5nZW5lcmF0ZShudW1CaXRzKTtcbiAgICBzZWNyZXRTdWJrZXlQYWNrZXQuZW5jcnlwdChwYXNzcGhyYXNlKTtcblxuICAgIGRhdGFUb1NpZ24gPSB7fTtcbiAgICBkYXRhVG9TaWduLmtleSA9IHNlY3JldEtleVBhY2tldDtcbiAgICBkYXRhVG9TaWduLmJpbmQgPSBzZWNyZXRTdWJrZXlQYWNrZXQ7XG4gICAgdmFyIHN1YmtleVNpZ25hdHVyZVBhY2tldCA9IG5ldyBwYWNrZXQuc2lnbmF0dXJlKCk7XG4gICAgc3Via2V5U2lnbmF0dXJlUGFja2V0Lmlzc3VlcktleUlkID0gc2VjcmV0U3Via2V5UGFja2V0LmdldEtleUlkKCkud3JpdGUoKTtcbiAgICBzdWJrZXlTaWduYXR1cmVQYWNrZXQuc2lnbmF0dXJlVHlwZSA9IGVudW1zLnNpZ25hdHVyZS5zdWJrZXlfYmluZGluZztcbiAgICBzdWJrZXlTaWduYXR1cmVQYWNrZXQucHVibGljS2V5QWxnb3JpdGhtID0ga2V5VHlwZTtcbiAgICAvL1RPRE8gd2Ugc2hvdWxkIGxvYWQgcHJlZmVycmVkIGhhc2ggZnJvbSBjb25maWcsIG9yIGFzIGlucHV0IHRvIHRoaXMgZnVuY3Rpb25cbiAgICBzdWJrZXlTaWduYXR1cmVQYWNrZXQuaGFzaEFsZ29yaXRobSA9IGVudW1zLmhhc2guc2hhMjU2O1xuICAgIHN1YmtleVNpZ25hdHVyZVBhY2tldC5zaWduKHNlY3JldFN1YmtleVBhY2tldCwgZGF0YVRvU2lnbik7XG5cbiAgICBwYWNrZXRsaXN0LnB1c2goc2VjcmV0S2V5UGFja2V0KTtcbiAgICBwYWNrZXRsaXN0LnB1c2godXNlcklkUGFja2V0KTtcbiAgICBwYWNrZXRsaXN0LnB1c2goc2lnbmF0dXJlUGFja2V0KTtcbiAgICBwYWNrZXRsaXN0LnB1c2goc2VjcmV0U3Via2V5UGFja2V0KTtcbiAgICBwYWNrZXRsaXN0LnB1c2goc3Via2V5U2lnbmF0dXJlUGFja2V0KTtcblxuICAgIHZhciBhcm1vcmVkID0gYXJtb3IuZW5jb2RlKGVudW1zLmFybW9yLnByaXZhdGVfa2V5LCBwYWNrZXRsaXN0LndyaXRlKCkpO1xuICAgIHJldHVybiBhcm1vcmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIGNyZWF0ZXMgYSBiaW5hcnkgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGFuIGVuY3J5cHRlZCBhbmQgc2lnbmVkIG1lc3NhZ2UuXG4gICAqIFRoZSBtZXNzYWdlIHdpbGwgYmUgZW5jcnlwdGVkIHdpdGggdGhlIHB1YmxpYyBrZXlzIHNwZWNpZmllZCBhbmQgc2lnbmVkXG4gICAqIHdpdGggdGhlIHNwZWNpZmllZCBwcml2YXRlIGtleS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHByaXZhdGVrZXkge29iajogW29wZW5wZ3BfbXNnX3ByaXZhdGVrZXldfSBQcml2YXRlIGtleSBcbiAgICogdG8gYmUgdXNlZCB0byBzaWduIHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7T2JqZWN0W119IHB1YmxpY2tleXMgQW4gYXJyYWYgb2Yge29iajogW29wZW5wZ3BfbXNnX3B1YmxpY2tleV19XG4gICAqIC0gcHVibGljIGtleXMgdG8gYmUgdXNlZCB0byBlbmNyeXB0IHRoZSBtZXNzYWdlIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZXRleHQgbWVzc2FnZSB0ZXh0IHRvIGVuY3J5cHQgYW5kIHNpZ25cbiAgICogQHJldHVybiB7U3RyaW5nfSBhIGJpbmFyeSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1lc3NhZ2Ugd2hpY2ggXG4gICAqIGNhbiBiZSBPcGVuUEdQIGFybW9yZWRcbiAgICovXG4gIGZ1bmN0aW9uIHdyaXRlX3NpZ25lZF9hbmRfZW5jcnlwdGVkX21lc3NhZ2UocHJpdmF0ZWtleSwgcHVibGlja2V5cywgbWVzc2FnZXRleHQpIHtcbiAgICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgICB2YXIgaTtcbiAgICB2YXIgbGl0ZXJhbCA9IG5ldyBvcGVucGdwX3BhY2tldF9saXRlcmFsZGF0YSgpLndyaXRlX3BhY2tldChtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZSgvXFxuL2csXG4gICAgICBcIlxcclxcblwiKSk7XG4gICAgdXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcImxpdGVyYWxfcGFja2V0OiB8XCIgKyBsaXRlcmFsICsgXCJ8XFxuXCIsIGxpdGVyYWwpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBwdWJsaWNrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgb25lcGFzc3NpZ25hdHVyZSA9IG5ldyBvcGVucGdwX3BhY2tldF9vbmVwYXNzc2lnbmF0dXJlKCk7XG4gICAgICB2YXIgb25lcGFzc3NpZ3N0ciA9IFwiXCI7XG4gICAgICBpZiAoaSA9PT0gMClcbiAgICAgICAgb25lcGFzc3NpZ3N0ciA9IG9uZXBhc3NzaWduYXR1cmUud3JpdGVfcGFja2V0KDEsIG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5wcmVmZXJfaGFzaF9hbGdvcml0aG0sIHByaXZhdGVrZXksIGZhbHNlKTtcbiAgICAgIGVsc2VcbiAgICAgICAgb25lcGFzc3NpZ3N0ciA9IG9uZXBhc3NzaWduYXR1cmUud3JpdGVfcGFja2V0KDEsIG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5wcmVmZXJfaGFzaF9hbGdvcml0aG0sIHByaXZhdGVrZXksIGZhbHNlKTtcbiAgICAgIHV0aWwucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAoXCJvbmVwYXNzc2lnc3RyOiB8XCIgKyBvbmVwYXNzc2lnc3RyICsgXCJ8XFxuXCIsIG9uZXBhc3NzaWdzdHIpO1xuICAgICAgdmFyIGRhdGFzaWduYXR1cmUgPSBuZXcgb3BlbnBncF9wYWNrZXRfc2lnbmF0dXJlKCkud3JpdGVfbWVzc2FnZV9zaWduYXR1cmUoMSwgbWVzc2FnZXRleHQucmVwbGFjZSgvXFxyXFxuL2csIFwiXFxuXCIpLnJlcGxhY2UoXG4gICAgICAgIC9cXG4vZywgXCJcXHJcXG5cIiksIHByaXZhdGVrZXkpO1xuICAgICAgdXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcImRhdGFzaWduYXR1cmU6IHxcIiArIGRhdGFzaWduYXR1cmUub3BlbnBncCArIFwifFxcblwiLCBkYXRhc2lnbmF0dXJlLm9wZW5wZ3ApO1xuICAgICAgaWYgKGkgPT09IDApIHtcbiAgICAgICAgcmVzdWx0ID0gb25lcGFzc3NpZ3N0ciArIGxpdGVyYWwgKyBkYXRhc2lnbmF0dXJlLm9wZW5wZ3A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQgPSBvbmVwYXNzc2lnc3RyICsgcmVzdWx0ICsgZGF0YXNpZ25hdHVyZS5vcGVucGdwO1xuICAgICAgfVxuICAgIH1cblxuICAgIHV0aWwucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAoXCJzaWduZWQgcGFja2V0OiB8XCIgKyByZXN1bHQgKyBcInxcXG5cIiwgcmVzdWx0KTtcbiAgICAvLyBzaWduYXR1cmVzIGRvbmUuLiBub3cgZW5jcnlwdGlvblxuICAgIHZhciBzZXNzaW9ua2V5ID0gb3BlbnBncF9jcnlwdG9fZ2VuZXJhdGVTZXNzaW9uS2V5KG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcik7XG4gICAgdmFyIHJlc3VsdDIgPSBcIlwiO1xuXG4gICAgLy8gY3JlYXRpbmcgc2Vzc2lvbiBrZXlzIGZvciBlYWNoIHJlY2lwaWVudFxuICAgIGZvciAoaSA9IDA7IGkgPCBwdWJsaWNrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcGtleSA9IHB1YmxpY2tleXNbaV0uZ2V0RW5jcnlwdGlvbktleSgpO1xuICAgICAgaWYgKHBrZXkgPT09IG51bGwpIHtcbiAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIm5vIGVuY3J5cHRpb24ga2V5IGZvdW5kISBLZXkgaXMgZm9yIHNpZ25pbmcgb25seS5cIik7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkc2Vzc2lvbmtleSgpLlxuICAgICAgd3JpdGVfcHViX2tleV9wYWNrZXQoXG4gICAgICAgIHBrZXkuZ2V0S2V5SWQoKSxcbiAgICAgICAgcGtleS5NUElzLFxuICAgICAgICBwa2V5LnB1YmxpY0tleUFsZ29yaXRobSxcbiAgICAgICAgb3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyLFxuICAgICAgICBzZXNzaW9ua2V5KTtcbiAgICB9XG4gICAgaWYgKG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5pbnRlZ3JpdHlfcHJvdGVjdCkge1xuICAgICAgcmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkaW50ZWdyaXR5cHJvdGVjdGVkZGF0YSgpLndyaXRlX3BhY2tldChvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsXG4gICAgICAgIHNlc3Npb25rZXksIHJlc3VsdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdDIgKz0gbmV3IG9wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGEoKS53cml0ZV9wYWNrZXQob3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyLCBzZXNzaW9ua2V5LFxuICAgICAgICByZXN1bHQpO1xuICAgIH1cbiAgICByZXR1cm4gYXJtb3IuZW5jb2RlKDMsIHJlc3VsdDIsIG51bGwsIG51bGwpO1xuICB9XG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgYmluYXJ5IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhbiBlbmNyeXB0ZWQgbWVzc2FnZS5cbiAgICogVGhlIG1lc3NhZ2Ugd2lsbCBiZSBlbmNyeXB0ZWQgd2l0aCB0aGUgcHVibGljIGtleXMgc3BlY2lmaWVkIFxuICAgKiBAcGFyYW0ge09iamVjdFtdfSBwdWJsaWNrZXlzIEFuIGFycmF5IG9mIHtvYmo6IFtvcGVucGdwX21zZ19wdWJsaWNrZXldfVxuICAgKiAtcHVibGljIGtleXMgdG8gYmUgdXNlZCB0byBlbmNyeXB0IHRoZSBtZXNzYWdlIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZXRleHQgbWVzc2FnZSB0ZXh0IHRvIGVuY3J5cHRcbiAgICogQHJldHVybiB7U3RyaW5nfSBhIGJpbmFyeSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIG1lc3NhZ2VcbiAgICogd2hpY2ggY2FuIGJlIE9wZW5QR1AgYXJtb3JlZFxuICAgKi9cbiAgZnVuY3Rpb24gd3JpdGVfZW5jcnlwdGVkX21lc3NhZ2UocHVibGlja2V5cywgbWVzc2FnZXRleHQpIHtcbiAgICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgICB2YXIgbGl0ZXJhbCA9IG5ldyBvcGVucGdwX3BhY2tldF9saXRlcmFsZGF0YSgpLndyaXRlX3BhY2tldChtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZSgvXFxuL2csXG4gICAgICBcIlxcclxcblwiKSk7XG4gICAgdXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcImxpdGVyYWxfcGFja2V0OiB8XCIgKyBsaXRlcmFsICsgXCJ8XFxuXCIsIGxpdGVyYWwpO1xuICAgIHJlc3VsdCA9IGxpdGVyYWw7XG5cbiAgICAvLyBzaWduYXR1cmVzIGRvbmUuLiBub3cgZW5jcnlwdGlvblxuICAgIHZhciBzZXNzaW9ua2V5ID0gb3BlbnBncF9jcnlwdG9fZ2VuZXJhdGVTZXNzaW9uS2V5KG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcik7XG4gICAgdmFyIHJlc3VsdDIgPSBcIlwiO1xuXG4gICAgLy8gY3JlYXRpbmcgc2Vzc2lvbiBrZXlzIGZvciBlYWNoIHJlY2lwaWVudFxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHVibGlja2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHBrZXkgPSBwdWJsaWNrZXlzW2ldLmdldEVuY3J5cHRpb25LZXkoKTtcbiAgICAgIGlmIChwa2V5ID09PSBudWxsKSB7XG4gICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJubyBlbmNyeXB0aW9uIGtleSBmb3VuZCEgS2V5IGlzIGZvciBzaWduaW5nIG9ubHkuXCIpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIHJlc3VsdDIgKz0gbmV3IG9wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZHNlc3Npb25rZXkoKS5cbiAgICAgIHdyaXRlX3B1Yl9rZXlfcGFja2V0KFxuICAgICAgICBwa2V5LmdldEtleUlkKCksXG4gICAgICAgIHBrZXkuTVBJcyxcbiAgICAgICAgcGtleS5wdWJsaWNLZXlBbGdvcml0aG0sXG4gICAgICAgIG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcixcbiAgICAgICAgc2Vzc2lvbmtleSk7XG4gICAgfVxuICAgIGlmIChvcGVucGdwLmNvbmZpZy5jb25maWcuaW50ZWdyaXR5X3Byb3RlY3QpIHtcbiAgICAgIHJlc3VsdDIgKz0gbmV3IG9wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGludGVncml0eXByb3RlY3RlZGRhdGEoKS53cml0ZV9wYWNrZXQob3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyLFxuICAgICAgICBzZXNzaW9ua2V5LCByZXN1bHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQyICs9IG5ldyBvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhKCkud3JpdGVfcGFja2V0KG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlciwgc2Vzc2lvbmtleSxcbiAgICAgICAgcmVzdWx0KTtcbiAgICB9XG4gICAgcmV0dXJuIGFybW9yLmVuY29kZSgzLCByZXN1bHQyLCBudWxsLCBudWxsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgYmluYXJ5IHN0cmluZyByZXByZXNlbnRhdGlvbiBhIHNpZ25lZCBtZXNzYWdlLlxuICAgKiBUaGUgbWVzc2FnZSB3aWxsIGJlIHNpZ25lZCB3aXRoIHRoZSBzcGVjaWZpZWQgcHJpdmF0ZSBrZXkuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBwcml2YXRla2V5IHtvYmo6IFtvcGVucGdwX21zZ19wcml2YXRla2V5XX1cbiAgICogLSB0aGUgcHJpdmF0ZSBrZXkgdG8gYmUgdXNlZCB0byBzaWduIHRoZSBtZXNzYWdlIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZXRleHQgbWVzc2FnZSB0ZXh0IHRvIHNpZ25cbiAgICogQHJldHVybiB7T2JqZWN0fSB7T2JqZWN0OiB0ZXh0IFtTdHJpbmddfSwgb3BlbnBncDoge1N0cmluZ30gYSBiaW5hcnlcbiAgICogIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgbWVzc2FnZSB3aGljaCBjYW4gYmUgT3BlblBHUFxuICAgKiAgIGFybW9yZWQob3BlbnBncCkgYW5kIGEgdGV4dCByZXByZXNlbnRhdGlvbiBvZiB0aGUgbWVzc2FnZSAodGV4dCkuIFxuICAgKiBUaGlzIGNhbiBiZSBkaXJlY3RseSB1c2VkIHRvIE9wZW5QR1AgYXJtb3IgdGhlIG1lc3NhZ2VcbiAgICovXG4gIGZ1bmN0aW9uIHdyaXRlX3NpZ25lZF9tZXNzYWdlKHByaXZhdGVrZXksIG1lc3NhZ2V0ZXh0KSB7XG4gICAgdmFyIHNpZyA9IG5ldyBvcGVucGdwX3BhY2tldF9zaWduYXR1cmUoKS53cml0ZV9tZXNzYWdlX3NpZ25hdHVyZSgxLCBtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZSgvXFxuLyxcbiAgICAgIFwiXFxyXFxuXCIpLCBwcml2YXRla2V5KTtcbiAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgdGV4dDogbWVzc2FnZXRleHQucmVwbGFjZSgvXFxyXFxuL2csIFwiXFxuXCIpLnJlcGxhY2UoL1xcbi8sIFwiXFxyXFxuXCIpLFxuICAgICAgb3BlbnBncDogc2lnLm9wZW5wZ3AsXG4gICAgICBoYXNoOiBzaWcuaGFzaFxuICAgIH07XG4gICAgcmV0dXJuIGFybW9yLmVuY29kZSgyLCByZXN1bHQsIG51bGwsIG51bGwpO1xuICB9XG5cbiAgdGhpcy5nZW5lcmF0ZUtleVBhaXIgPSBnZW5lcmF0ZUtleVBhaXI7XG4gIHRoaXMud3JpdGVfc2lnbmVkX21lc3NhZ2UgPSB3cml0ZV9zaWduZWRfbWVzc2FnZTtcbiAgdGhpcy53cml0ZV9zaWduZWRfYW5kX2VuY3J5cHRlZF9tZXNzYWdlID0gd3JpdGVfc2lnbmVkX2FuZF9lbmNyeXB0ZWRfbWVzc2FnZTtcbiAgdGhpcy5lbmNyeXB0TWVzc2FnZSA9IGVuY3J5cHRNZXNzYWdlO1xuICB0aGlzLmRlY3J5cHRNZXNzYWdlID0gZGVjcnlwdE1lc3NhZ2U7XG5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgX29wZW5wZ3AoKTtcbiIsInZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyk7XG5cbi8vIFRoaXMgaXMgcHJldHR5IHVnbHksIGJ1dCBicm93c2VyaWZ5IG5lZWRzIHRvIGhhdmUgdGhlIHJlcXVpcmVzIGV4cGxpY2l0bHkgd3JpdHRlbi5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBjb21wcmVzc2VkOiByZXF1aXJlKCcuL2NvbXByZXNzZWQuanMnKSxcbiAgc3ltX2VuY3J5cHRlZF9pbnRlZ3JpdHlfcHJvdGVjdGVkOiByZXF1aXJlKCcuL3N5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZC5qcycpLFxuICBwdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleTogcmVxdWlyZSgnLi9wdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleS5qcycpLFxuICBzeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5OiByZXF1aXJlKCcuL3N5bV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkuanMnKSxcbiAgbGl0ZXJhbDogcmVxdWlyZSgnLi9saXRlcmFsLmpzJyksXG4gIHB1YmxpY19rZXk6IHJlcXVpcmUoJy4vcHVibGljX2tleS5qcycpLFxuICBzeW1tZXRyaWNhbGx5X2VuY3J5cHRlZDogcmVxdWlyZSgnLi9zeW1tZXRyaWNhbGx5X2VuY3J5cHRlZC5qcycpLFxuICBtYXJrZXI6IHJlcXVpcmUoJy4vbWFya2VyLmpzJyksXG4gIHB1YmxpY19zdWJrZXk6IHJlcXVpcmUoJy4vcHVibGljX3N1YmtleS5qcycpLFxuICB1c2VyX2F0dHJpYnV0ZTogcmVxdWlyZSgnLi91c2VyX2F0dHJpYnV0ZS5qcycpLFxuICBvbmVfcGFzc19zaWduYXR1cmU6IHJlcXVpcmUoJy4vb25lX3Bhc3Nfc2lnbmF0dXJlLmpzJyksXG4gIHNlY3JldF9rZXk6IHJlcXVpcmUoJy4vc2VjcmV0X2tleS5qcycpLFxuICB1c2VyaWQ6IHJlcXVpcmUoJy4vdXNlcmlkLmpzJyksXG4gIHNlY3JldF9zdWJrZXk6IHJlcXVpcmUoJy4vc2VjcmV0X3N1YmtleS5qcycpLFxuICBzaWduYXR1cmU6IHJlcXVpcmUoJy4vc2lnbmF0dXJlLmpzJyksXG4gIHRydXN0OiByZXF1aXJlKCcuL3RydXN0LmpzJylcbn1cblxuZm9yICh2YXIgaSBpbiBlbnVtcy5wYWNrZXQpIHtcbiAgdmFyIHBhY2tldENsYXNzID0gbW9kdWxlLmV4cG9ydHNbaV07XG5cbiAgaWYgKHBhY2tldENsYXNzICE9IHVuZGVmaW5lZClcbiAgICBwYWNrZXRDbGFzcy5wcm90b3R5cGUudGFnID0gZW51bXMucGFja2V0W2ldO1xufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgSlhHID0gcmVxdWlyZSgnLi4vY29tcHJlc3Npb24vanhnLmpzJyksXG4gIGJhc2U2NCA9IHJlcXVpcmUoJy4uL2VuY29kaW5nL2Jhc2U2NC5qcycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgQ29tcHJlc3NlZCBEYXRhIFBhY2tldCAoVGFnIDgpXG4gKiBcbiAqIFJGQzQ4ODAgNS42OlxuICogVGhlIENvbXByZXNzZWQgRGF0YSBwYWNrZXQgY29udGFpbnMgY29tcHJlc3NlZCBkYXRhLiAgVHlwaWNhbGx5LCB0aGlzXG4gKiBwYWNrZXQgaXMgZm91bmQgYXMgdGhlIGNvbnRlbnRzIG9mIGFuIGVuY3J5cHRlZCBwYWNrZXQsIG9yIGZvbGxvd2luZ1xuICogYSBTaWduYXR1cmUgb3IgT25lLVBhc3MgU2lnbmF0dXJlIHBhY2tldCwgYW5kIGNvbnRhaW5zIGEgbGl0ZXJhbCBkYXRhXG4gKiBwYWNrZXQuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X2NvbXByZXNzZWQoKSB7XG4gIC8qKiBAdHlwZSB7cGFja2V0bGlzdH0gKi9cbiAgdGhpcy5wYWNrZXRzO1xuICAvKiogQHR5cGUge2NvbXByZXNzaW9ufSAqL1xuICB0aGlzLmFsZ29yaXRobSA9ICd1bmNvbXByZXNzZWQnO1xuXG4gIHRoaXMuY29tcHJlc3NlZCA9IG51bGw7XG5cblxuICAvKipcbiAgICogUGFyc2luZyBmdW5jdGlvbiBmb3IgdGhlIHBhY2tldC5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2YgYSB0YWcgOCBwYWNrZXRcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBQb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuICAgKiBAcGFyQU0ge2lOVEVHRVJ9IExFTiBsRU5HVEggT0YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBcbiAgICogaW5wdXQgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfY29tcHJlc3NlZH0gT2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIC8vIE9uZSBvY3RldCB0aGF0IGdpdmVzIHRoZSBhbGdvcml0aG0gdXNlZCB0byBjb21wcmVzcyB0aGUgcGFja2V0LlxuICAgIHRoaXMuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5jb21wcmVzc2lvbiwgYnl0ZXMuY2hhckNvZGVBdCgwKSk7XG5cbiAgICAvLyBDb21wcmVzc2VkIGRhdGEsIHdoaWNoIG1ha2VzIHVwIHRoZSByZW1haW5kZXIgb2YgdGhlIHBhY2tldC5cbiAgICB0aGlzLmNvbXByZXNzZWQgPSBieXRlcy5zdWJzdHIoMSk7XG5cbiAgICB0aGlzLmRlY29tcHJlc3MoKTtcbiAgfVxuXG5cblxuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuY29tcHJlc3NlZCA9PSBudWxsKVxuICAgICAgdGhpcy5jb21wcmVzcygpO1xuXG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuY29tcHJlc3Npb24sIHRoaXMuYWxnb3JpdGhtKSkgKyB0aGlzLmNvbXByZXNzZWQ7XG4gIH1cblxuXG4gIC8qKlxuICAgKiBEZWNvbXByZXNzaW9uIG1ldGhvZCBmb3IgZGVjb21wcmVzc2luZyB0aGUgY29tcHJlc3NlZCBkYXRhXG4gICAqIHJlYWQgYnkgcmVhZF9wYWNrZXRcbiAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgZGVjb21wcmVzc2VkIGRhdGFcbiAgICovXG4gIHRoaXMuZGVjb21wcmVzcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBkZWNvbXByZXNzZWQ7XG5cbiAgICBzd2l0Y2ggKHRoaXMuYWxnb3JpdGhtKSB7XG4gICAgICBjYXNlICd1bmNvbXByZXNzZWQnOlxuICAgICAgICBkZWNvbXByZXNzZWQgPSB0aGlzLmNvbXByZXNzZWQ7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICd6aXAnOlxuICAgICAgICB2YXIgY29tcERhdGEgPSB0aGlzLmNvbXByZXNzZWQ7XG5cbiAgICAgICAgdmFyIHJhZGl4ID0gYmFzZTY0LmVuY29kZShjb21wRGF0YSkucmVwbGFjZSgvXFxuL2csIFwiXCIpO1xuICAgICAgICAvLyBubyBoZWFkZXIgaW4gdGhpcyBjYXNlLCBkaXJlY3RseSBjYWxsIGRlZmxhdGVcbiAgICAgICAgdmFyIGp4Z19vYmogPSBuZXcgSlhHLlV0aWwuVW56aXAoSlhHLlV0aWwuQmFzZTY0LmRlY29kZUFzQXJyYXkocmFkaXgpKTtcblxuICAgICAgICBkZWNvbXByZXNzZWQgPSB1bmVzY2FwZShqeGdfb2JqLmRlZmxhdGUoKVswXVswXSk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICd6bGliJzpcbiAgICAgICAgLy9SRkMgMTk1MC4gQml0cyAwLTMgQ29tcHJlc3Npb24gTWV0aG9kXG4gICAgICAgIHZhciBjb21wcmVzc2lvbk1ldGhvZCA9IHRoaXMuY29tcHJlc3NlZC5jaGFyQ29kZUF0KDApICUgMHgxMDtcblxuICAgICAgICAvL0JpdHMgNC03IFJGQyAxOTUwIGFyZSBMWjc3IFdpbmRvdy4gR2VuZXJhbGx5IHRoaXMgdmFsdWUgaXMgNyA9PSAzMmsgd2luZG93IHNpemUuXG4gICAgICAgIC8vIDJuZCBCeXRlIGluIFJGQyAxOTUwIGlzIGZvciBcIkZMQUdzXCIgQWxsb3dzIGZvciBhIERpY3Rpb25hcnkgXG4gICAgICAgIC8vIChob3cgaXMgdGhpcyBkZWZpbmVkKS4gQmFzaWMgY2hlY2tzdW0sIGFuZCBjb21wcmVzc2lvbiBsZXZlbC5cblxuICAgICAgICBpZiAoY29tcHJlc3Npb25NZXRob2QgPT0gOCkgeyAvL0NNIDggaXMgZm9yIERFRkxBVEUsIFJGQyAxOTUxXG4gICAgICAgICAgLy8gcmVtb3ZlIDQgYnl0ZXMgQURMRVIzMiBjaGVja3N1bSBmcm9tIHRoZSBlbmRcbiAgICAgICAgICB2YXIgY29tcERhdGEgPSB0aGlzLmNvbXByZXNzZWQuc3Vic3RyaW5nKDAsIHRoaXMuY29tcHJlc3NlZC5sZW5ndGggLSA0KTtcbiAgICAgICAgICB2YXIgcmFkaXggPSBiYXNlNjQuZW5jb2RlKGNvbXBEYXRhKS5yZXBsYWNlKC9cXG4vZywgXCJcIik7XG4gICAgICAgICAgLy9UT0RPIGNoZWNrIEFETEVSMzIgY2hlY2tzdW1cbiAgICAgICAgICBkZWNvbXByZXNzZWQgPSBKWEcuZGVjb21wcmVzcyhyYWRpeCk7XG4gICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1dGlsLnByaW50X2Vycm9yKFwiQ29tcHJlc3Npb24gYWxnb3JpdGhtIFpMSUIgb25seSBzdXBwb3J0cyBcIiArXG4gICAgICAgICAgICBcIkRFRkxBVEUgY29tcHJlc3Npb24gbWV0aG9kLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnYnppcDInOlxuICAgICAgICAvLyBUT0RPOiBuZWVkIHRvIGltcGxlbWVudCB0aGlzXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ29tcHJlc3Npb24gYWxnb3JpdGhtIEJaaXAyIFtCWjJdIGlzIG5vdCBpbXBsZW1lbnRlZC4nKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSB1bmtub3duIDpcIiArIHRoaXMuYWxvZ3JpdGhtKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgdGhpcy5wYWNrZXRzLnJlYWQoZGVjb21wcmVzc2VkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wcmVzcyB0aGUgcGFja2V0IGRhdGEgKG1lbWJlciBkZWNvbXByZXNzZWREYXRhKVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHR5cGUgQWxnb3JpdGhtIHRvIGJlIHVzZWQgLy8gU2VlIFJGQyA0ODgwIDkuM1xuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIHRvIGJlIGNvbXByZXNzZWRcbiAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgY29tcHJlc3NlZCBkYXRhIHN0b3JlZCBpbiBhdHRyaWJ1dGUgY29tcHJlc3NlZERhdGFcbiAgICovXG4gIHRoaXMuY29tcHJlc3MgPSBmdW5jdGlvbigpIHtcbiAgICBzd2l0Y2ggKHRoaXMuYWxnb3JpdGhtKSB7XG5cbiAgICAgIGNhc2UgJ3VuY29tcHJlc3NlZCc6XG4gICAgICAgIC8vIC0gVW5jb21wcmVzc2VkXG4gICAgICAgIHRoaXMuY29tcHJlc3NlZCA9IHRoaXMucGFja2V0cy53cml0ZSgpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnemlwJzpcbiAgICAgICAgLy8gLSBaSVAgW1JGQzE5NTFdXG4gICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJDb21wcmVzc2lvbiBhbGdvcml0aG0gWklQIFtSRkMxOTUxXSBpcyBub3QgaW1wbGVtZW50ZWQuXCIpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnemxpYic6XG4gICAgICAgIC8vIC0gWkxJQiBbUkZDMTk1MF1cbiAgICAgICAgLy8gVE9ETzogbmVlZCB0byBpbXBsZW1lbnQgdGhpc1xuICAgICAgICB1dGlsLnByaW50X2Vycm9yKFwiQ29tcHJlc3Npb24gYWxnb3JpdGhtIFpMSUIgW1JGQzE5NTBdIGlzIG5vdCBpbXBsZW1lbnRlZC5cIik7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdiemlwMic6XG4gICAgICAgIC8vICAtIEJaaXAyIFtCWjJdXG4gICAgICAgIC8vIFRPRE86IG5lZWQgdG8gaW1wbGVtZW50IHRoaXNcbiAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSBCWmlwMiBbQloyXSBpcyBub3QgaW1wbGVtZW50ZWQuXCIpO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSB1bmtub3duIDpcIiArIHRoaXMudHlwZSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufTtcbiIsInZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBsaXN0OiByZXF1aXJlKCcuL3BhY2tldGxpc3QuanMnKSxcbn07XG5cbnZhciBwYWNrZXRzID0gcmVxdWlyZSgnLi9hbGxfcGFja2V0cy5qcycpO1xuXG5mb3IgKHZhciBpIGluIHBhY2tldHMpXG4gIG1vZHVsZS5leHBvcnRzW2ldID0gcGFja2V0c1tpXTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBMaXRlcmFsIERhdGEgUGFja2V0IChUYWcgMTEpXG4gKiBcbiAqIFJGQzQ4ODAgNS45OiBBIExpdGVyYWwgRGF0YSBwYWNrZXQgY29udGFpbnMgdGhlIGJvZHkgb2YgYSBtZXNzYWdlOyBkYXRhIHRoYXRcbiAqIGlzIG5vdCB0byBiZSBmdXJ0aGVyIGludGVycHJldGVkLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9saXRlcmFsKCkge1xuICB0aGlzLmZvcm1hdCA9ICd1dGY4JzsgLy8gZGVmYXVsdCBmb3JtYXQgZm9yIGxpdGVyYWwgZGF0YSBwYWNrZXRzXG4gIHRoaXMuZGF0YSA9ICcnOyAvLyBsaXRlcmFsIGRhdGEgcmVwcmVzZW50YXRpb24gYXMgbmF0aXZlIEphdmFTY3JpcHQgc3RyaW5nIG9yIGJ5dGVzXG4gIHRoaXMuZGF0ZSA9IG5ldyBEYXRlKCk7XG5cblxuICAvKipcbiAgICogU2V0IHRoZSBwYWNrZXQgZGF0YSB0byBhIGphdmFzY3JpcHQgbmF0aXZlIHN0cmluZyBvciBhIHNxdWVuY2Ugb2YgXG4gICAqIGJ5dGVzLiBDb252ZXJzaW9uIHRvIHRoZSBwcm92aWRlZCBmb3JtYXQgdGFrZXMgcGxhY2Ugd2hlbiB0aGUgXG4gICAqIHBhY2tldCBpcyB3cml0dGVuLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIEFueSBuYXRpdmUgamF2YXNjcmlwdCBzdHJpbmdcbiAgICogQHBhcmFtIHsndXRmOHwnYmluYXJ5J3wndGV4dCd9IGZvcm1hdCBUaGUgZm9ybWF0IHRoZSBwYWNrZXQgZGF0YSB3aWxsIGJlIHdyaXR0ZW4gdG8sXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0cyB0byAndXRmOCdcbiAgICovXG4gIHRoaXMuc2V0ID0gZnVuY3Rpb24oc3RyLCBmb3JtYXQpIHtcbiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdCB8fCB0aGlzLmZvcm1hdDtcbiAgICB0aGlzLmRhdGEgPSBzdHI7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBwYWNrZXQgZGF0YSB0byB2YWx1ZSByZXByZXNlbnRlZCBieSB0aGUgcHJvdmlkZWQgc3RyaW5nIG9mIGJ5dGVzLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gYnl0ZXMgVGhlIHN0cmluZyBvZiBieXRlc1xuICAgKiBAcGFyYW0geyd1dGY4fCdiaW5hcnknfCd0ZXh0J30gZm9ybWF0IFRoZSBmb3JtYXQgb2YgdGhlIHN0cmluZyBvZiBieXRlc1xuICAgKi9cbiAgdGhpcy5zZXRCeXRlcyA9IGZ1bmN0aW9uKGJ5dGVzLCBmb3JtYXQpIHtcbiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDtcbiAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICAgIGJ5dGVzID0gdXRpbC5kZWNvZGVfdXRmOChieXRlcyk7XG4gICAgICAgIGJ5dGVzID0gYnl0ZXMucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0ZXh0JzpcbiAgICAgICAgYnl0ZXMgPSBieXRlcy5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgdGhpcy5kYXRhID0gYnl0ZXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBieXRlIHNlcXVlbmNlIHJlcHJlc2VudGluZyB0aGUgbGl0ZXJhbCBwYWNrZXQgZGF0YVxuICAgKiBAcmV0dXJucyB7U3RyaW5nfSBBIHNlcXVlbmNlIG9mIGJ5dGVzXG4gICAqL1xuICB0aGlzLmdldEJ5dGVzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGJ5dGVzID0gdGhpcy5kYXRhO1xuICAgIHN3aXRjaCAodGhpcy5mb3JtYXQpIHtcbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgICBieXRlcyA9IGJ5dGVzLnJlcGxhY2UoL1xcbi9nLCAnXFxyXFxuJyk7XG4gICAgICAgIGJ5dGVzID0gdXRpbC5lbmNvZGVfdXRmOChieXRlcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndGV4dCc6XG4gICAgICAgIGJ5dGVzID0gYnl0ZXMucmVwbGFjZSgvXFxuL2csICdcXHJcXG4nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG5cblxuICAvKipcbiAgICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBsaXRlcmFsIGRhdGEgcGFja2V0ICh0YWcgMTEpLlxuICAgKiBcbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2YgYSB0YWcgMTEgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb25cbiAgICogICAgICAgICAgICBQb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlblxuICAgKiAgICAgICAgICAgIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mXG4gICAqICAgICAgICAgICAgaW5wdXQgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YX0gb2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIC8vIC0gQSBvbmUtb2N0ZXQgZmllbGQgdGhhdCBkZXNjcmliZXMgaG93IHRoZSBkYXRhIGlzIGZvcm1hdHRlZC5cblxuICAgIHZhciBmb3JtYXQgPSBlbnVtcy5yZWFkKGVudW1zLmxpdGVyYWwsIGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSk7XG5cbiAgICB2YXIgZmlsZW5hbWVfbGVuID0gYnl0ZXMuY2hhckNvZGVBdCgxKTtcbiAgICB0aGlzLmZpbGVuYW1lID0gdXRpbC5kZWNvZGVfdXRmOChieXRlcy5zdWJzdHIoMiwgZmlsZW5hbWVfbGVuKSk7XG5cbiAgICB0aGlzLmRhdGUgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cigyICsgZmlsZW5hbWVfbGVuLCA0KSk7XG5cbiAgICB2YXIgZGF0YSA9IGJ5dGVzLnN1YnN0cmluZyg2ICsgZmlsZW5hbWVfbGVuKTtcblxuICAgIHRoaXMuc2V0Qnl0ZXMoZGF0YSwgZm9ybWF0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYWNrZXRcbiAgICogXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIFRoZSBkYXRhIHRvIGJlIGluc2VydGVkIGFzIGJvZHlcbiAgICogQHJldHVybiB7U3RyaW5nfSBzdHJpbmctcmVwcmVzZW50YXRpb24gb2YgdGhlIHBhY2tldFxuICAgKi9cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmaWxlbmFtZSA9IHV0aWwuZW5jb2RlX3V0ZjgoXCJtc2cudHh0XCIpO1xuXG4gICAgdmFyIGRhdGEgPSB0aGlzLmdldEJ5dGVzKCk7XG5cbiAgICB2YXIgcmVzdWx0ID0gJyc7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMubGl0ZXJhbCwgdGhpcy5mb3JtYXQpKTtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShmaWxlbmFtZS5sZW5ndGgpO1xuICAgIHJlc3VsdCArPSBmaWxlbmFtZTtcbiAgICByZXN1bHQgKz0gdXRpbC53cml0ZURhdGUodGhpcy5kYXRlKTtcbiAgICByZXN1bHQgKz0gZGF0YTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgc3RyYW5nZSBcIk1hcmtlciBwYWNrZXRcIiAoVGFnIDEwKVxuICogXG4gKiBSRkM0ODgwIDUuODogQW4gZXhwZXJpbWVudGFsIHZlcnNpb24gb2YgUEdQIHVzZWQgdGhpcyBwYWNrZXQgYXMgdGhlIExpdGVyYWxcbiAqIHBhY2tldCwgYnV0IG5vIHJlbGVhc2VkIHZlcnNpb24gb2YgUEdQIGdlbmVyYXRlZCBMaXRlcmFsIHBhY2tldHMgd2l0aCB0aGlzXG4gKiB0YWcuIFdpdGggUEdQIDUueCwgdGhpcyBwYWNrZXQgaGFzIGJlZW4gcmVhc3NpZ25lZCBhbmQgaXMgcmVzZXJ2ZWQgZm9yIHVzZSBhc1xuICogdGhlIE1hcmtlciBwYWNrZXQuXG4gKiBcbiAqIFN1Y2ggYSBwYWNrZXQgTVVTVCBiZSBpZ25vcmVkIHdoZW4gcmVjZWl2ZWQuXG4gKi9cbmZ1bmN0aW9uIHBhY2tldF9tYXJrZXIoKSB7XG4gIC8qKlxuICAgKiBQYXJzaW5nIGZ1bmN0aW9uIGZvciBhIGxpdGVyYWwgZGF0YSBwYWNrZXQgKHRhZyAxMCkuXG4gICAqIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgUGF5bG9hZCBvZiBhIHRhZyAxMCBwYWNrZXRcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvblxuICAgKiAgICAgICAgICAgIFBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgc3RyaW5nXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuXG4gICAqICAgICAgICAgICAgTGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2ZcbiAgICogICAgICAgICAgICBpbnB1dCBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBPYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgaWYgKGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSA9PSAweDUwICYmIC8vIFBcbiAgICBieXRlc1sxXS5jaGFyQ29kZUF0KCkgPT0gMHg0NyAmJiAvLyBHXG4gICAgYnl0ZXNbMl0uY2hhckNvZGVBdCgpID09IDB4NTApIC8vIFBcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIC8vIG1hcmtlciBwYWNrZXQgZG9lcyBub3QgY29udGFpbiBcIlBHUFwiXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcGFja2V0X21hcmtlcjtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBPbmUtUGFzcyBTaWduYXR1cmUgUGFja2V0cyAoVGFnIDQpXG4gKiBcbiAqIFJGQzQ4ODAgNS40OlxuICogVGhlIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQgcHJlY2VkZXMgdGhlIHNpZ25lZCBkYXRhIGFuZCBjb250YWluc1xuICogZW5vdWdoIGluZm9ybWF0aW9uIHRvIGFsbG93IHRoZSByZWNlaXZlciB0byBiZWdpbiBjYWxjdWxhdGluZyBhbnlcbiAqIGhhc2hlcyBuZWVkZWQgdG8gdmVyaWZ5IHRoZSBzaWduYXR1cmUuICBJdCBhbGxvd3MgdGhlIFNpZ25hdHVyZVxuICogcGFja2V0IHRvIGJlIHBsYWNlZCBhdCB0aGUgZW5kIG9mIHRoZSBtZXNzYWdlLCBzbyB0aGF0IHRoZSBzaWduZXJcbiAqIGNhbiBjb21wdXRlIHRoZSBlbnRpcmUgc2lnbmVkIG1lc3NhZ2UgaW4gb25lIHBhc3MuXG4gKi9cblxudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgdHlwZV9rZXlpZCA9IHJlcXVpcmUoJy4uL3R5cGUva2V5aWQuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfb25lX3Bhc3Nfc2lnbmF0dXJlKCkge1xuICB0aGlzLnZlcnNpb24gPSBudWxsOyAvLyBBIG9uZS1vY3RldCB2ZXJzaW9uIG51bWJlci4gIFRoZSBjdXJyZW50IHZlcnNpb24gaXMgMy5cbiAgdGhpcy50eXBlID0gbnVsbDsgLy8gQSBvbmUtb2N0ZXQgc2lnbmF0dXJlIHR5cGUuICBTaWduYXR1cmUgdHlwZXMgYXJlIGRlc2NyaWJlZCBpbiBSRkM0ODgwIFNlY3Rpb24gNS4yLjEuXG4gIHRoaXMuaGFzaEFsZ29yaXRobSA9IG51bGw7IC8vIEEgb25lLW9jdGV0IG51bWJlciBkZXNjcmliaW5nIHRoZSBoYXNoIGFsZ29yaXRobSB1c2VkLiAoU2VlIFJGQzQ4ODAgOS40KVxuICB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSA9IG51bGw7IC8vIEEgb25lLW9jdGV0IG51bWJlciBkZXNjcmliaW5nIHRoZSBwdWJsaWMta2V5IGFsZ29yaXRobSB1c2VkLiAoU2VlIFJGQzQ4ODAgOS4xKVxuICB0aGlzLnNpZ25pbmdLZXlJZCA9IG51bGw7IC8vIEFuIGVpZ2h0LW9jdGV0IG51bWJlciBob2xkaW5nIHRoZSBLZXkgSUQgb2YgdGhlIHNpZ25pbmcga2V5LlxuICB0aGlzLmZsYWdzID0gbnVsbDsgLy8gIEEgb25lLW9jdGV0IG51bWJlciBob2xkaW5nIGEgZmxhZyBzaG93aW5nIHdoZXRoZXIgdGhlIHNpZ25hdHVyZSBpcyBuZXN0ZWQuICBBIHplcm8gdmFsdWUgaW5kaWNhdGVzIHRoYXQgdGhlIG5leHQgcGFja2V0IGlzIGFub3RoZXIgT25lLVBhc3MgU2lnbmF0dXJlIHBhY2tldCB0aGF0IGRlc2NyaWJlcyBhbm90aGVyIHNpZ25hdHVyZSB0byBiZSBhcHBsaWVkIHRvIHRoZSBzYW1lIG1lc3NhZ2UgZGF0YS5cblxuICAvKipcbiAgICogcGFyc2luZyBmdW5jdGlvbiBmb3IgYSBvbmUtcGFzcyBzaWduYXR1cmUgcGFja2V0ICh0YWcgNCkuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBieXRlcyBwYXlsb2FkIG9mIGEgdGFnIDQgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gcG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBieXRlcyBzdHJpbmdcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW4gbGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2YgYnl0ZXMgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YX0gb2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIHZhciBteXBvcyA9IDA7XG4gICAgLy8gQSBvbmUtb2N0ZXQgdmVyc2lvbiBudW1iZXIuICBUaGUgY3VycmVudCB2ZXJzaW9uIGlzIDMuXG4gICAgdGhpcy52ZXJzaW9uID0gYnl0ZXMuY2hhckNvZGVBdChteXBvcysrKTtcblxuICAgIC8vIEEgb25lLW9jdGV0IHNpZ25hdHVyZSB0eXBlLiAgU2lnbmF0dXJlIHR5cGVzIGFyZSBkZXNjcmliZWQgaW5cbiAgICAvLyAgIFNlY3Rpb24gNS4yLjEuXG4gICAgdGhpcy50eXBlID0gZW51bXMucmVhZChlbnVtcy5zaWduYXR1cmUsIGJ5dGVzLmNoYXJDb2RlQXQobXlwb3MrKykpO1xuXG4gICAgLy8gQSBvbmUtb2N0ZXQgbnVtYmVyIGRlc2NyaWJpbmcgdGhlIGhhc2ggYWxnb3JpdGhtIHVzZWQuXG4gICAgdGhpcy5oYXNoQWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5oYXNoLCBieXRlcy5jaGFyQ29kZUF0KG15cG9zKyspKTtcblxuICAgIC8vIEEgb25lLW9jdGV0IG51bWJlciBkZXNjcmliaW5nIHRoZSBwdWJsaWMta2V5IGFsZ29yaXRobSB1c2VkLlxuICAgIHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGJ5dGVzLmNoYXJDb2RlQXQobXlwb3MrKykpO1xuXG4gICAgLy8gQW4gZWlnaHQtb2N0ZXQgbnVtYmVyIGhvbGRpbmcgdGhlIEtleSBJRCBvZiB0aGUgc2lnbmluZyBrZXkuXG4gICAgdGhpcy5zaWduaW5nS2V5SWQgPSBuZXcgdHlwZV9rZXlpZCgpO1xuICAgIHRoaXMuc2lnbmluZ0tleUlkLnJlYWQoYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgbXlwb3MgKz0gODtcblxuICAgIC8vIEEgb25lLW9jdGV0IG51bWJlciBob2xkaW5nIGEgZmxhZyBzaG93aW5nIHdoZXRoZXIgdGhlIHNpZ25hdHVyZVxuICAgIC8vICAgaXMgbmVzdGVkLiAgQSB6ZXJvIHZhbHVlIGluZGljYXRlcyB0aGF0IHRoZSBuZXh0IHBhY2tldCBpc1xuICAgIC8vICAgYW5vdGhlciBPbmUtUGFzcyBTaWduYXR1cmUgcGFja2V0IHRoYXQgZGVzY3JpYmVzIGFub3RoZXJcbiAgICAvLyAgIHNpZ25hdHVyZSB0byBiZSBhcHBsaWVkIHRvIHRoZSBzYW1lIG1lc3NhZ2UgZGF0YS5cbiAgICB0aGlzLmZsYWdzID0gYnl0ZXMuY2hhckNvZGVBdChteXBvcysrKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgb25lLXBhc3Mgc2lnbmF0dXJlIHBhY2tldFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHR5cGUgU2lnbmF0dXJlIHR5cGVzIGFzIGRlc2NyaWJlZCBpbiBSRkM0ODgwIFNlY3Rpb24gNS4yLjEuXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gaGFzaGFsZ29yaXRobSB0aGUgaGFzaCBhbGdvcml0aG0gdXNlZCB3aXRoaW4gdGhlIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXl9IHByaXZhdGVrZXkgdGhlIHByaXZhdGUga2V5IHVzZWQgdG8gZ2VuZXJhdGUgdGhlIHNpZ25hdHVyZVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBsZW5ndGggb2YgZGF0YSB0byBiZSBzaWduZWRcbiAgICogQHBhcmFtIHtib29sZWFufSBuZXN0ZWQgYm9vbGVhbiBzaG93aW5nIHdoZXRoZXIgdGhlIHNpZ25hdHVyZSBpcyBuZXN0ZWQuIFxuICAgKiAgXCJ0cnVlXCIgaW5kaWNhdGVzIHRoYXQgdGhlIG5leHQgcGFja2V0IGlzIGFub3RoZXIgT25lLVBhc3MgU2lnbmF0dXJlIHBhY2tldFxuICAgKiAgIHRoYXQgZGVzY3JpYmVzIGFub3RoZXIgc2lnbmF0dXJlIHRvIGJlIGFwcGxpZWQgdG8gdGhlIHNhbWUgbWVzc2FnZSBkYXRhLiBcbiAgICogQHJldHVybiB7U3RyaW5nfSBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIG9uZS1wYXNzIHNpZ25hdHVyZSBwYWNrZXRcbiAgICovXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbih0eXBlLCBoYXNoYWxnb3JpdGhtLCBwcml2YXRla2V5LCBsZW5ndGgsIG5lc3RlZCkge1xuICAgIHZhciByZXN1bHQgPSBcIlwiO1xuXG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMyk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuc2lnbmF0dXJlLCB0eXBlKSk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuaGFzaCwgdGhpcy5oYXNoQWxnb3JpdGhtKSk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMucHVibGljS2V5LCBwcml2YXRla2V5LmFsZ29yaXRobSkpO1xuICAgIHJlc3VsdCArPSBwcml2YXRla2V5LmdldEtleUlkKCkud3JpdGUoKTtcbiAgICBpZiAobmVzdGVkKVxuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCk7XG4gICAgZWxzZVxuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgcmVhZFNpbXBsZUxlbmd0aDogZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgbGVuID0gMCxcbiAgICAgIG9mZnNldCxcbiAgICAgIHR5cGUgPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG5cblxuICAgIGlmICh0eXBlIDwgMTkyKSB7XG4gICAgICBsZW4gPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG4gICAgICBvZmZzZXQgPSAxO1xuICAgIH0gZWxzZSBpZiAodHlwZSA8IDI1NSkge1xuICAgICAgbGVuID0gKChieXRlc1swXS5jaGFyQ29kZUF0KCkgLSAxOTIpIDw8IDgpICsgKGJ5dGVzWzFdLmNoYXJDb2RlQXQoKSkgKyAxOTI7XG4gICAgICBvZmZzZXQgPSAyO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PSAyNTUpIHtcbiAgICAgIGxlbiA9IHV0aWwucmVhZE51bWJlcihieXRlcy5zdWJzdHIoMSwgNCkpO1xuICAgICAgb2Zmc2V0ID0gNTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbGVuOiBsZW4sXG4gICAgICBvZmZzZXQ6IG9mZnNldFxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIEVuY29kZXMgYSBnaXZlbiBpbnRlZ2VyIG9mIGxlbmd0aCB0byB0aGUgb3BlbnBncCBsZW5ndGggc3BlY2lmaWVyIHRvIGFcbiAgICogc3RyaW5nXG4gICAqIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBUaGUgbGVuZ3RoIHRvIGVuY29kZVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFN0cmluZyB3aXRoIG9wZW5wZ3AgbGVuZ3RoIHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB3cml0ZVNpbXBsZUxlbmd0aDogZnVuY3Rpb24obGVuZ3RoKSB7XG4gICAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gICAgaWYgKGxlbmd0aCA8IDE5Mikge1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUobGVuZ3RoKTtcbiAgICB9IGVsc2UgaWYgKGxlbmd0aCA+IDE5MSAmJiBsZW5ndGggPCA4Mzg0KSB7XG4gICAgICAvKlxuICAgICAgICogbGV0IGEgPSAodG90YWwgZGF0YSBwYWNrZXQgbGVuZ3RoKSAtIDE5MiBsZXQgYmMgPSB0d28gb2N0ZXRcbiAgICAgICAqIHJlcHJlc2VudGF0aW9uIG9mIGEgbGV0IGQgPSBiICsgMTkyXG4gICAgICAgKi9cbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCgobGVuZ3RoIC0gMTkyKSA+PiA4KSArIDE5Mik7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgobGVuZ3RoIC0gMTkyKSAmIDB4RkYpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgyNTUpO1xuICAgICAgcmVzdWx0ICs9IHV0aWwud3JpdGVOdW1iZXIobGVuZ3RoLCA0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICAvKipcbiAgICogV3JpdGVzIGEgcGFja2V0IGhlYWRlciB2ZXJzaW9uIDQgd2l0aCB0aGUgZ2l2ZW4gdGFnX3R5cGUgYW5kIGxlbmd0aCB0byBhXG4gICAqIHN0cmluZ1xuICAgKiBcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSB0YWdfdHlwZSBUYWcgdHlwZVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBMZW5ndGggb2YgdGhlIHBheWxvYWRcbiAgICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgb2YgdGhlIGhlYWRlclxuICAgKi9cbiAgd3JpdGVIZWFkZXI6IGZ1bmN0aW9uKHRhZ190eXBlLCBsZW5ndGgpIHtcbiAgICAvKiB3ZSdyZSBvbmx5IGdlbmVyYXRpbmcgdjQgcGFja2V0IGhlYWRlcnMgaGVyZSAqL1xuICAgIHZhciByZXN1bHQgPSBcIlwiO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4QzAgfCB0YWdfdHlwZSk7XG4gICAgcmVzdWx0ICs9IHRoaXMud3JpdGVTaW1wbGVMZW5ndGgobGVuZ3RoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIC8qKlxuICAgKiBXcml0ZXMgYSBwYWNrZXQgaGVhZGVyIFZlcnNpb24gMyB3aXRoIHRoZSBnaXZlbiB0YWdfdHlwZSBhbmQgbGVuZ3RoIHRvIGFcbiAgICogc3RyaW5nXG4gICAqIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHRhZ190eXBlIFRhZyB0eXBlXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuZ3RoIExlbmd0aCBvZiB0aGUgcGF5bG9hZFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFN0cmluZyBvZiB0aGUgaGVhZGVyXG4gICAqL1xuICB3cml0ZU9sZEhlYWRlcjogZnVuY3Rpb24odGFnX3R5cGUsIGxlbmd0aCkge1xuICAgIHZhciByZXN1bHQgPSBcIlwiO1xuICAgIGlmIChsZW5ndGggPCAyNTYpIHtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4ODAgfCAodGFnX3R5cGUgPDwgMikpO1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUobGVuZ3RoKTtcbiAgICB9IGVsc2UgaWYgKGxlbmd0aCA8IDY1NTM2KSB7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDgwIHwgKHRhZ190eXBlIDw8IDIpIHwgMSk7XG4gICAgICByZXN1bHQgKz0gdXRpbC53cml0ZU51bWJlcihsZW5ndGgsIDIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDgwIHwgKHRhZ190eXBlIDw8IDIpIHwgMik7XG4gICAgICByZXN1bHQgKz0gdXRpbC53cml0ZU51bWJlcihsZW5ndGgsIDQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIC8qKlxuICAgKiBHZW5lcmljIHN0YXRpYyBQYWNrZXQgUGFyc2VyIGZ1bmN0aW9uXG4gICAqIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgSW5wdXQgc3RyZWFtIGFzIHN0cmluZ1xuICAgKiBAcGFyYW0ge2ludGVnZXJ9IHBvc2l0aW9uIFBvc2l0aW9uIHRvIHN0YXJ0IHBhcnNpbmdcbiAgICogQHBhcmFtIHtpbnRlZ2VyfSBsZW4gTGVuZ3RoIG9mIHRoZSBpbnB1dCBmcm9tIHBvc2l0aW9uIG9uXG4gICAqIEByZXR1cm4ge09iamVjdH0gUmV0dXJucyBhIHBhcnNlZCBvcGVucGdwX3BhY2tldFxuICAgKi9cbiAgcmVhZDogZnVuY3Rpb24oaW5wdXQsIHBvc2l0aW9uLCBsZW4pIHtcbiAgICAvLyBzb21lIHNhbml0eSBjaGVja3NcbiAgICBpZiAoaW5wdXQgPT0gbnVsbCB8fCBpbnB1dC5sZW5ndGggPD0gcG9zaXRpb24gfHwgaW5wdXQuc3Vic3RyaW5nKHBvc2l0aW9uKS5sZW5ndGggPCAyIHx8IChpbnB1dFtwb3NpdGlvbl0uY2hhckNvZGVBdCgpICZcbiAgICAgIDB4ODApID09IDApIHtcbiAgICAgIHV0aWxcbiAgICAgICAgLnByaW50X2Vycm9yKFwiRXJyb3IgZHVyaW5nIHBhcnNpbmcuIFRoaXMgbWVzc2FnZSAvIGtleSBpcyBwcm9iYWJseSBub3QgY29udGFpbmluZyBhIHZhbGlkIE9wZW5QR1AgZm9ybWF0LlwiKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICB2YXIgbXlwb3MgPSBwb3NpdGlvbjtcbiAgICB2YXIgdGFnID0gLTE7XG4gICAgdmFyIGZvcm1hdCA9IC0xO1xuICAgIHZhciBwYWNrZXRfbGVuZ3RoO1xuXG4gICAgZm9ybWF0ID0gMDsgLy8gMCA9IG9sZCBmb3JtYXQ7IDEgPSBuZXcgZm9ybWF0XG4gICAgaWYgKChpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpICYgMHg0MCkgIT0gMCkge1xuICAgICAgZm9ybWF0ID0gMTtcbiAgICB9XG5cbiAgICB2YXIgcGFja2V0X2xlbmd0aF90eXBlO1xuICAgIGlmIChmb3JtYXQpIHtcbiAgICAgIC8vIG5ldyBmb3JtYXQgaGVhZGVyXG4gICAgICB0YWcgPSBpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpICYgMHgzRjsgLy8gYml0IDUtMFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBvbGQgZm9ybWF0IGhlYWRlclxuICAgICAgdGFnID0gKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDNGKSA+PiAyOyAvLyBiaXQgNS0yXG4gICAgICBwYWNrZXRfbGVuZ3RoX3R5cGUgPSBpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpICYgMHgwMzsgLy8gYml0IDEtMFxuICAgIH1cblxuICAgIC8vIGhlYWRlciBvY3RldCBwYXJzaW5nIGRvbmVcbiAgICBteXBvcysrO1xuXG4gICAgLy8gcGFyc2VkIGxlbmd0aCBmcm9tIGxlbmd0aCBmaWVsZFxuICAgIHZhciBib2R5ZGF0YSA9IG51bGw7XG5cbiAgICAvLyB1c2VkIGZvciBwYXJ0aWFsIGJvZHkgbGVuZ3Roc1xuICAgIHZhciByZWFsX3BhY2tldF9sZW5ndGggPSAtMTtcbiAgICBpZiAoIWZvcm1hdCkge1xuICAgICAgLy8gNC4yLjEuIE9sZCBGb3JtYXQgUGFja2V0IExlbmd0aHNcbiAgICAgIHN3aXRjaCAocGFja2V0X2xlbmd0aF90eXBlKSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAvLyBUaGUgcGFja2V0IGhhcyBhIG9uZS1vY3RldCBsZW5ndGguIFRoZSBoZWFkZXIgaXMgMiBvY3RldHNcbiAgICAgICAgICAvLyBsb25nLlxuICAgICAgICAgIHBhY2tldF9sZW5ndGggPSBpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAvLyBUaGUgcGFja2V0IGhhcyBhIHR3by1vY3RldCBsZW5ndGguIFRoZSBoZWFkZXIgaXMgMyBvY3RldHNcbiAgICAgICAgICAvLyBsb25nLlxuICAgICAgICAgIHBhY2tldF9sZW5ndGggPSAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpIDw8IDgpIHwgaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgLy8gVGhlIHBhY2tldCBoYXMgYSBmb3VyLW9jdGV0IGxlbmd0aC4gVGhlIGhlYWRlciBpcyA1XG4gICAgICAgICAgLy8gb2N0ZXRzIGxvbmcuXG4gICAgICAgICAgcGFja2V0X2xlbmd0aCA9IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgMjQpIHwgKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCAxNikgfCAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpIDw8XG4gICAgICAgICAgICA4KSB8IGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAvLyAzIC0gVGhlIHBhY2tldCBpcyBvZiBpbmRldGVybWluYXRlIGxlbmd0aC4gVGhlIGhlYWRlciBpcyAxXG4gICAgICAgICAgLy8gb2N0ZXQgbG9uZywgYW5kIHRoZSBpbXBsZW1lbnRhdGlvbiBtdXN0IGRldGVybWluZSBob3cgbG9uZ1xuICAgICAgICAgIC8vIHRoZSBwYWNrZXQgaXMuIElmIHRoZSBwYWNrZXQgaXMgaW4gYSBmaWxlLCB0aGlzIG1lYW5zIHRoYXRcbiAgICAgICAgICAvLyB0aGUgcGFja2V0IGV4dGVuZHMgdW50aWwgdGhlIGVuZCBvZiB0aGUgZmlsZS4gSW4gZ2VuZXJhbCwgXG4gICAgICAgICAgLy8gYW4gaW1wbGVtZW50YXRpb24gU0hPVUxEIE5PVCB1c2UgaW5kZXRlcm1pbmF0ZS1sZW5ndGggXG4gICAgICAgICAgLy8gcGFja2V0cyBleGNlcHQgd2hlcmUgdGhlIGVuZCBvZiB0aGUgZGF0YSB3aWxsIGJlIGNsZWFyIFxuICAgICAgICAgIC8vIGZyb20gdGhlIGNvbnRleHQsIGFuZCBldmVuIHRoZW4gaXQgaXMgYmV0dGVyIHRvIHVzZSBhIFxuICAgICAgICAgIC8vIGRlZmluaXRlIGxlbmd0aCwgb3IgYSBuZXcgZm9ybWF0IGhlYWRlci4gVGhlIG5ldyBmb3JtYXQgXG4gICAgICAgICAgLy8gaGVhZGVycyBkZXNjcmliZWQgYmVsb3cgaGF2ZSBhIG1lY2hhbmlzbSBmb3IgcHJlY2lzZWx5XG4gICAgICAgICAgLy8gZW5jb2RpbmcgZGF0YSBvZiBpbmRldGVybWluYXRlIGxlbmd0aC5cbiAgICAgICAgICBwYWNrZXRfbGVuZ3RoID0gbGVuO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgfSBlbHNlIC8vIDQuMi4yLiBOZXcgRm9ybWF0IFBhY2tldCBMZW5ndGhzXG4gICAge1xuXG4gICAgICAvLyA0LjIuMi4xLiBPbmUtT2N0ZXQgTGVuZ3Roc1xuICAgICAgaWYgKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgPCAxOTIpIHtcbiAgICAgICAgcGFja2V0X2xlbmd0aCA9IGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgdXRpbC5wcmludF9kZWJ1ZyhcIjEgYnl0ZSBsZW5ndGg6XCIgKyBwYWNrZXRfbGVuZ3RoKTtcbiAgICAgICAgLy8gNC4yLjIuMi4gVHdvLU9jdGV0IExlbmd0aHNcbiAgICAgIH0gZWxzZSBpZiAoaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSA+PSAxOTIgJiYgaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSA8IDIyNCkge1xuICAgICAgICBwYWNrZXRfbGVuZ3RoID0gKChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgLSAxOTIpIDw8IDgpICsgKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSkgKyAxOTI7XG4gICAgICAgIHV0aWwucHJpbnRfZGVidWcoXCIyIGJ5dGUgbGVuZ3RoOlwiICsgcGFja2V0X2xlbmd0aCk7XG4gICAgICAgIC8vIDQuMi4yLjQuIFBhcnRpYWwgQm9keSBMZW5ndGhzXG4gICAgICB9IGVsc2UgaWYgKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgPiAyMjMgJiYgaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSA8IDI1NSkge1xuICAgICAgICBwYWNrZXRfbGVuZ3RoID0gMSA8PCAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpICYgMHgxRik7XG4gICAgICAgIHV0aWwucHJpbnRfZGVidWcoXCI0IGJ5dGUgbGVuZ3RoOlwiICsgcGFja2V0X2xlbmd0aCk7XG4gICAgICAgIC8vIEVFRUssIHdlJ3JlIHJlYWRpbmcgdGhlIGZ1bGwgZGF0YSBoZXJlLi4uXG4gICAgICAgIHZhciBteXBvczIgPSBteXBvcyArIHBhY2tldF9sZW5ndGg7XG4gICAgICAgIGJvZHlkYXRhID0gaW5wdXQuc3Vic3RyaW5nKG15cG9zLCBteXBvcyArIHBhY2tldF9sZW5ndGgpO1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGlmIChpbnB1dFtteXBvczJdLmNoYXJDb2RlQXQoKSA8IDE5Mikge1xuICAgICAgICAgICAgdmFyIHRtcGxlbiA9IGlucHV0W215cG9zMisrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgICAgICBwYWNrZXRfbGVuZ3RoICs9IHRtcGxlbjtcbiAgICAgICAgICAgIGJvZHlkYXRhICs9IGlucHV0LnN1YnN0cmluZyhteXBvczIsIG15cG9zMiArIHRtcGxlbik7XG4gICAgICAgICAgICBteXBvczIgKz0gdG1wbGVuO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfSBlbHNlIGlmIChpbnB1dFtteXBvczJdLmNoYXJDb2RlQXQoKSA+PSAxOTIgJiYgaW5wdXRbbXlwb3MyXS5jaGFyQ29kZUF0KCkgPCAyMjQpIHtcbiAgICAgICAgICAgIHZhciB0bXBsZW4gPSAoKGlucHV0W215cG9zMisrXS5jaGFyQ29kZUF0KCkgLSAxOTIpIDw8IDgpICsgKGlucHV0W215cG9zMisrXS5jaGFyQ29kZUF0KCkpICsgMTkyO1xuICAgICAgICAgICAgcGFja2V0X2xlbmd0aCArPSB0bXBsZW47XG4gICAgICAgICAgICBib2R5ZGF0YSArPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MyLCBteXBvczIgKyB0bXBsZW4pO1xuICAgICAgICAgICAgbXlwb3MyICs9IHRtcGxlbjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH0gZWxzZSBpZiAoaW5wdXRbbXlwb3MyXS5jaGFyQ29kZUF0KCkgPiAyMjMgJiYgaW5wdXRbbXlwb3MyXS5jaGFyQ29kZUF0KCkgPCAyNTUpIHtcbiAgICAgICAgICAgIHZhciB0bXBsZW4gPSAxIDw8IChpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpICYgMHgxRik7XG4gICAgICAgICAgICBwYWNrZXRfbGVuZ3RoICs9IHRtcGxlbjtcbiAgICAgICAgICAgIGJvZHlkYXRhICs9IGlucHV0LnN1YnN0cmluZyhteXBvczIsIG15cG9zMiArIHRtcGxlbik7XG4gICAgICAgICAgICBteXBvczIgKz0gdG1wbGVuO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBteXBvczIrKztcbiAgICAgICAgICAgIHZhciB0bXBsZW4gPSAoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSA8PCAyNCkgfCAoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSA8PCAxNikgfCAoaW5wdXRbbXlwb3MyKytdXG4gICAgICAgICAgICAgIC5jaGFyQ29kZUF0KCkgPDwgOCkgfCBpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICAgICAgYm9keWRhdGEgKz0gaW5wdXQuc3Vic3RyaW5nKG15cG9zMiwgbXlwb3MyICsgdG1wbGVuKTtcbiAgICAgICAgICAgIHBhY2tldF9sZW5ndGggKz0gdG1wbGVuO1xuICAgICAgICAgICAgbXlwb3MyICs9IHRtcGxlbjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZWFsX3BhY2tldF9sZW5ndGggPSBteXBvczI7XG4gICAgICAgIC8vIDQuMi4yLjMuIEZpdmUtT2N0ZXQgTGVuZ3Roc1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbXlwb3MrKztcbiAgICAgICAgcGFja2V0X2xlbmd0aCA9IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgMjQpIHwgKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCAxNikgfCAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpIDw8XG4gICAgICAgICAgOCkgfCBpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gaWYgdGhlcmUgd2FzJ250IGEgcGFydGlhbCBib2R5IGxlbmd0aDogdXNlIHRoZSBzcGVjaWZpZWRcbiAgICAvLyBwYWNrZXRfbGVuZ3RoXG4gICAgaWYgKHJlYWxfcGFja2V0X2xlbmd0aCA9PSAtMSkge1xuICAgICAgcmVhbF9wYWNrZXRfbGVuZ3RoID0gcGFja2V0X2xlbmd0aDtcbiAgICB9XG5cbiAgICBpZiAoYm9keWRhdGEgPT0gbnVsbCkge1xuICAgICAgYm9keWRhdGEgPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MsIG15cG9zICsgcmVhbF9wYWNrZXRfbGVuZ3RoKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdGFnOiB0YWcsXG4gICAgICBwYWNrZXQ6IGJvZHlkYXRhLFxuICAgICAgb2Zmc2V0OiBteXBvcyArIHJlYWxfcGFja2V0X2xlbmd0aFxuICAgIH07XG4gIH1cbn1cbiIsInZhciBwYWNrZXRQYXJzZXIgPSByZXF1aXJlKCcuL3BhY2tldC5qcycpLFxuICBwYWNrZXRzID0gcmVxdWlyZSgnLi9hbGxfcGFja2V0cy5qcycpLFxuICBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIFRoaXMgY2xhc3MgcmVwcmVzZW50cyBhIGxpc3Qgb2Ygb3BlbnBncCBwYWNrZXRzLlxuICogVGFrZSBjYXJlIHdoZW4gaXRlcmF0aW5nIG92ZXIgaXQgLSB0aGUgcGFja2V0cyB0aGVtc2VsdmVzXG4gKiBhcmUgc3RvcmVkIGFzIG51bWVyaWNhbCBpbmRpY2VzLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldGxpc3QoKSB7XG4gIC8qKiBUaGUgbnVtYmVyIG9mIHBhY2tldHMgY29udGFpbmVkIHdpdGhpbiB0aGUgbGlzdC5cbiAgICogQHJlYWRvbmx5XG4gICAqIEB0eXBlIHtJbnRlZ2VyfSAqL1xuICB0aGlzLmxlbmd0aCA9IDA7XG5cbiAgLyoqXG4gICAqIFJlYWRzIGEgc3RyZWFtIG9mIGJpbmFyeSBkYXRhIGFuZCBpbnRlcnByZW50cyBpdCBhcyBhIGxpc3Qgb2YgcGFja2V0cy5cbiAgICogQHBhcmFtIHtvcGVucGdwX2J5dGVhcnJheX0gQW4gYXJyYXkgb2YgYnl0ZXMuXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIHZhciBpID0gMDtcblxuICAgIHdoaWxlIChpIDwgYnl0ZXMubGVuZ3RoKSB7XG4gICAgICB2YXIgcGFyc2VkID0gcGFja2V0UGFyc2VyLnJlYWQoYnl0ZXMsIGksIGJ5dGVzLmxlbmd0aCAtIGkpO1xuICAgICAgaSA9IHBhcnNlZC5vZmZzZXQ7XG5cbiAgICAgIHZhciB0YWcgPSBlbnVtcy5yZWFkKGVudW1zLnBhY2tldCwgcGFyc2VkLnRhZyk7XG4gICAgICB2YXIgcGFja2V0ID0gbmV3IHBhY2tldHNbdGFnXSgpO1xuXG4gICAgICB0aGlzLnB1c2gocGFja2V0KTtcblxuICAgICAgcGFja2V0LnJlYWQocGFyc2VkLnBhY2tldCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBiaW5hcnkgcmVwcmVzZW50YXRpb24gb2Ygb3BlbnBncCBvYmplY3RzIGNvbnRhaW5lZCB3aXRoaW4gdGhlXG4gICAqIGNsYXNzIGluc3RhbmNlLlxuICAgKiBAcmV0dXJucyB7b3BlbnBncF9ieXRlYXJyYXl9IEFuIGFycmF5IG9mIGJ5dGVzIGNvbnRhaW5pbmcgdmFsaWQgb3BlbnBncCBwYWNrZXRzLlxuICAgKi9cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBieXRlcyA9ICcnO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcGFja2V0Ynl0ZXMgPSB0aGlzW2ldLndyaXRlKCk7XG4gICAgICBieXRlcyArPSBwYWNrZXRQYXJzZXIud3JpdGVIZWFkZXIodGhpc1tpXS50YWcsIHBhY2tldGJ5dGVzLmxlbmd0aCk7XG4gICAgICBieXRlcyArPSBwYWNrZXRieXRlcztcbiAgICB9XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHBhY2tldCB0byB0aGUgbGlzdC4gVGhpcyBpcyB0aGUgb25seSBzdXBwb3J0ZWQgbWV0aG9kIG9mIGRvaW5nIHNvO1xuICAgKiB3cml0aW5nIHRvIHBhY2tldGxpc3RbaV0gZGlyZWN0bHkgd2lsbCByZXN1bHQgaW4gYW4gZXJyb3IuXG4gICAqL1xuICB0aGlzLnB1c2ggPSBmdW5jdGlvbihwYWNrZXQpIHtcbiAgICBwYWNrZXQucGFja2V0cyA9IG5ldyBwYWNrZXRsaXN0KCk7XG5cbiAgICB0aGlzW3RoaXMubGVuZ3RoXSA9IHBhY2tldDtcbiAgICB0aGlzLmxlbmd0aCsrO1xuICB9XG5cbiAgLyoqXG4gICogQ3JlYXRlcyBhIG5ldyBwYWNrZXRMaXN0IHdpdGggYWxsIHBhY2tldHMgdGhhdCBwYXNzIHRoZSB0ZXN0IGltcGxlbWVudGVkIGJ5IHRoZSBwcm92aWRlZCBmdW5jdGlvbi5cbiAgKi9cbiAgdGhpcy5maWx0ZXIgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuXG4gICAgdmFyIGZpbHRlcmVkID0gbmV3IHBhY2tldGxpc3QoKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGNhbGxiYWNrKHRoaXNbaV0sIGksIHRoaXMpKSB7XG4gICAgICAgIGZpbHRlcmVkLnB1c2godGhpc1tpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbHRlcmVkO1xuICB9XG5cbiAgLyoqXG4gICogQ3JlYXRlcyBhIG5ldyBwYWNrZXRMaXN0IHdpdGggYWxsIHBhY2tldHMgZnJvbSB0aGUgZ2l2ZW4gdHlwZXNcbiAgKi9cbiAgdGhpcy5maWx0ZXJCeVRhZyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICB2YXIgZmlsdGVyZWQgPSBuZXcgcGFja2V0bGlzdCgpO1xuICAgIHZhciB0aGF0ID0gdGhpcztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFyZ3Muc29tZShmdW5jdGlvbihwYWNrZXRUeXBlKSB7cmV0dXJuIHRoYXRbaV0udGFnID09IHBhY2tldFR5cGV9KSkge1xuICAgICAgICBmaWx0ZXJlZC5wdXNoKHRoaXNbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmaWx0ZXJlZDtcbiAgfSBcblxuICAvKipcbiAgKiBFeGVjdXRlcyB0aGUgcHJvdmlkZWQgY2FsbGJhY2sgb25jZSBmb3IgZWFjaCBlbGVtZW50XG4gICovXG4gIHRoaXMuZm9yRWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjYWxsYmFjayh0aGlzW2ldKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJhdmVyc2VzIHBhY2tldCB0cmVlIGFuZCByZXR1cm5zIGZpcnN0IG1hdGNoaW5nIHBhY2tldFxuICAgKiBAcGFyYW0gIHtlbnVtcy5wYWNrZXR9IHR5cGUgVGhlIHBhY2tldCB0eXBlXG4gICAqIEByZXR1cm4ge1t0eXBlXX0gICAgICBcbiAgICovXG4gIHRoaXMuZmluZFBhY2tldCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICB2YXIgcGFja2V0bGlzdCA9IHRoaXMuZmlsdGVyQnlUYWcodHlwZSk7XG4gICAgaWYgKHBhY2tldGxpc3QubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gcGFja2V0bGlzdFswXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGZvdW5kID0gbnVsbDtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpc1tpXS5wYWNrZXRzLmxlbmd0aCkge1xuICAgICAgICAgIGZvdW5kID0gdGhpc1tpXS5wYWNrZXRzLmZpbmRQYWNrZXQodHlwZSk7XG4gICAgICAgICAgaWYgKGZvdW5kKSByZXR1cm4gZm91bmQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG4gIHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKSxcbiAgdHlwZV9rZXlpZCA9IHJlcXVpcmUoJy4uL3R5cGUva2V5aWQuanMnKSxcbiAgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuICBjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIEtleSBNYXRlcmlhbCBQYWNrZXQgKFRhZyA1LDYsNywxNClcbiAqICAgXG4gKiBSRkM0NDgwIDUuNTpcbiAqIEEga2V5IG1hdGVyaWFsIHBhY2tldCBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IGEgcHVibGljIG9yXG4gKiBwcml2YXRlIGtleS4gIFRoZXJlIGFyZSBmb3VyIHZhcmlhbnRzIG9mIHRoaXMgcGFja2V0IHR5cGUsIGFuZCB0d29cbiAqIG1ham9yIHZlcnNpb25zLiAgQ29uc2VxdWVudGx5LCB0aGlzIHNlY3Rpb24gaXMgY29tcGxleC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfcHVibGljX2tleSgpIHtcbiAgLyoqIEtleSBjcmVhdGlvbiBkYXRlLlxuICAgKiBAdHlwZSB7RGF0ZX0gKi9cbiAgdGhpcy5jcmVhdGVkID0gbmV3IERhdGUoKTtcbiAgLyoqIEEgbGlzdCBvZiBtdWx0aXByZWNpc2lvbiBpbnRlZ2Vyc1xuICAgKiBAdHlwZSB7b3BlbnBncF90eXBlX21waX0gKi9cbiAgdGhpcy5tcGkgPSBbXTtcbiAgLyoqIFB1YmxpYyBrZXkgYWxnb3JpdGhtXG4gICAqIEB0eXBlIHtvcGVucGdwLnB1YmxpY2tleX0gKi9cbiAgdGhpcy5hbGdvcml0aG0gPSAncnNhX3NpZ24nO1xuXG5cbiAgLyoqXG4gICAqIEludGVybmFsIFBhcnNlciBmb3IgcHVibGljIGtleXMgYXMgc3BlY2lmaWVkIGluIFJGQyA0ODgwIHNlY3Rpb24gXG4gICAqIDUuNS4yIFB1YmxpYy1LZXkgUGFja2V0IEZvcm1hdHNcbiAgICogY2FsbGVkIGJ5IHJlYWRfdGFnJmx0O251bSZndDtcbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IElucHV0IHN0cmluZyB0byByZWFkIHRoZSBwYWNrZXQgZnJvbVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFN0YXJ0IHBvc2l0aW9uIGZvciB0aGUgcGFyc2VyXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHJlbWFpbmluZyBsZW5ndGggb2YgaW5wdXRcbiAgICogQHJldHVybiB7T2JqZWN0fSBUaGlzIG9iamVjdCB3aXRoIGF0dHJpYnV0ZXMgc2V0IGJ5IHRoZSBwYXJzZXJcbiAgICovXG4gIHRoaXMucmVhZFB1YmxpY0tleSA9IHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgLy8gQSBvbmUtb2N0ZXQgdmVyc2lvbiBudW1iZXIgKDMgb3IgNCkuXG4gICAgdmFyIHZlcnNpb24gPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG5cbiAgICBpZiAodmVyc2lvbiA9PSA0KSB7XG4gICAgICAvLyAtIEEgZm91ci1vY3RldCBudW1iZXIgZGVub3RpbmcgdGhlIHRpbWUgdGhhdCB0aGUga2V5IHdhcyBjcmVhdGVkLlxuICAgICAgdGhpcy5jcmVhdGVkID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIoMSwgNCkpO1xuXG4gICAgICAvLyAtIEEgb25lLW9jdGV0IG51bWJlciBkZW5vdGluZyB0aGUgcHVibGljLWtleSBhbGdvcml0aG0gb2YgdGhpcyBrZXkuXG4gICAgICB0aGlzLmFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMucHVibGljS2V5LCBieXRlc1s1XS5jaGFyQ29kZUF0KCkpO1xuXG4gICAgICB2YXIgbXBpY291bnQgPSBjcnlwdG8uZ2V0UHVibGljTXBpQ291bnQodGhpcy5hbGdvcml0aG0pO1xuICAgICAgdGhpcy5tcGkgPSBbXTtcblxuICAgICAgdmFyIGJtcGkgPSBieXRlcy5zdWJzdHIoNik7XG4gICAgICB2YXIgcCA9IDA7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbXBpY291bnQgJiYgcCA8IGJtcGkubGVuZ3RoOyBpKyspIHtcblxuICAgICAgICB0aGlzLm1waVtpXSA9IG5ldyB0eXBlX21waSgpO1xuXG4gICAgICAgIHAgKz0gdGhpcy5tcGlbaV0ucmVhZChibXBpLnN1YnN0cihwKSlcblxuICAgICAgICBpZiAocCA+IGJtcGkubGVuZ3RoKVxuICAgICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJvcGVucGdwLnBhY2tldC5rZXltYXRlcmlhbC5qc1xcblwiICsgJ2Vycm9yIHJlYWRpbmcgTVBJIEA6JyArIHApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcCArIDY7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVmVyc2lvbiAnICsgdmVyc2lvbiArICcgb2YgdGhlIGtleSBwYWNrZXQgaXMgdW5zdXBwb3J0ZWQuJyk7XG4gICAgfVxuICB9XG5cbiAgLypcbiAgICogU2FtZSBhcyB3cml0ZV9wcml2YXRlX2tleSwgYnV0IGhhcyBsZXNzIGluZm9ybWF0aW9uIGJlY2F1c2Ugb2YgXG4gICAqIHB1YmxpYyBrZXkuXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0ga2V5VHlwZSBGb2xsb3dzIHRoZSBPcGVuUEdQIGFsZ29yaXRobSBzdGFuZGFyZCwgXG4gICAqIElFIDEgY29ycmVzcG9uZHMgdG8gUlNBLlxuICAgKiBAcGFyYW0ge1JTQS5rZXlPYmplY3R9IGtleVxuICAgKiBAcGFyYW0gdGltZVBhY2tldFxuICAgKiBAcmV0dXJuIHtPYmplY3R9IHtib2R5OiBbc3RyaW5nXU9wZW5QR1AgcGFja2V0IGJvZHkgY29udGVudHMsIFxuICAgKiBoZWFkZXI6IFtzdHJpbmddIE9wZW5QR1AgcGFja2V0IGhlYWRlciwgc3RyaW5nOiBbc3RyaW5nXSBoZWFkZXIrYm9keX1cbiAgICovXG4gIHRoaXMud3JpdGVQdWJsaWNLZXkgPSB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgLy8gVmVyc2lvblxuICAgIHZhciByZXN1bHQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDQpO1xuICAgIHJlc3VsdCArPSB1dGlsLndyaXRlRGF0ZSh0aGlzLmNyZWF0ZWQpO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLnB1YmxpY0tleSwgdGhpcy5hbGdvcml0aG0pKTtcblxuICAgIHZhciBtcGljb3VudCA9IGNyeXB0by5nZXRQdWJsaWNNcGlDb3VudCh0aGlzLmFsZ29yaXRobSk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1waWNvdW50OyBpKyspIHtcbiAgICAgIHJlc3VsdCArPSB0aGlzLm1waVtpXS53cml0ZSgpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvLyBXcml0ZSBhbiBvbGQgdmVyc2lvbiBwYWNrZXQgLSBpdCdzIHVzZWQgYnkgc29tZSBvZiB0aGUgaW50ZXJuYWwgcm91dGluZXMuXG4gIHRoaXMud3JpdGVPbGQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnl0ZXMgPSB0aGlzLndyaXRlUHVibGljS2V5KCk7XG5cbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgweDk5KSArXG4gICAgICB1dGlsLndyaXRlTnVtYmVyKGJ5dGVzLmxlbmd0aCwgMikgK1xuICAgICAgYnl0ZXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUga2V5IGlkIG9mIHRoZSBrZXkgXG4gICAqIEByZXR1cm4ge1N0cmluZ30gQSA4IGJ5dGUga2V5IGlkXG4gICAqL1xuICB0aGlzLmdldEtleUlkID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGtleWlkID0gbmV3IHR5cGVfa2V5aWQoKTtcbiAgICBrZXlpZC5yZWFkKHRoaXMuZ2V0RmluZ2VycHJpbnQoKS5zdWJzdHIoMTIsIDgpKTtcbiAgICByZXR1cm4ga2V5aWQ7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgZmluZ2VycHJpbnQgb2YgdGhlIGtleVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEEgc3RyaW5nIGNvbnRhaW5pbmcgdGhlIGZpbmdlcnByaW50XG4gICAqL1xuICB0aGlzLmdldEZpbmdlcnByaW50ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHRvSGFzaCA9IHRoaXMud3JpdGVPbGQoKTtcbiAgICByZXR1cm4gY3J5cHRvLmhhc2guc2hhMSh0b0hhc2gsIHRvSGFzaC5sZW5ndGgpO1xuICB9XG5cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB0eXBlX2tleWlkID0gcmVxdWlyZSgnLi4vdHlwZS9rZXlpZC5qcycpLFxuICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICB0eXBlX21waSA9IHJlcXVpcmUoJy4uL3R5cGUvbXBpLmpzJyksXG4gIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgY3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgUGFja2V0cyAoVGFnIDEpXG4gKiBcbiAqIFJGQzQ4ODAgNS4xOiBBIFB1YmxpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldCBob2xkcyB0aGUgc2Vzc2lvbiBrZXlcbiAqIHVzZWQgdG8gZW5jcnlwdCBhIG1lc3NhZ2UuIFplcm8gb3IgbW9yZSBQdWJsaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleVxuICogcGFja2V0cyBhbmQvb3IgU3ltbWV0cmljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgcGFja2V0cyBtYXkgcHJlY2VkZSBhXG4gKiBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIFBhY2tldCwgd2hpY2ggaG9sZHMgYW4gZW5jcnlwdGVkIG1lc3NhZ2UuIFRoZVxuICogbWVzc2FnZSBpcyBlbmNyeXB0ZWQgd2l0aCB0aGUgc2Vzc2lvbiBrZXksIGFuZCB0aGUgc2Vzc2lvbiBrZXkgaXMgaXRzZWxmXG4gKiBlbmNyeXB0ZWQgYW5kIHN0b3JlZCBpbiB0aGUgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldChzKS4gVGhlXG4gKiBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIFBhY2tldCBpcyBwcmVjZWRlZCBieSBvbmUgUHVibGljLUtleSBFbmNyeXB0ZWRcbiAqIFNlc3Npb24gS2V5IHBhY2tldCBmb3IgZWFjaCBPcGVuUEdQIGtleSB0byB3aGljaCB0aGUgbWVzc2FnZSBpcyBlbmNyeXB0ZWQuXG4gKiBUaGUgcmVjaXBpZW50IG9mIHRoZSBtZXNzYWdlIGZpbmRzIGEgc2Vzc2lvbiBrZXkgdGhhdCBpcyBlbmNyeXB0ZWQgdG8gdGhlaXJcbiAqIHB1YmxpYyBrZXksIGRlY3J5cHRzIHRoZSBzZXNzaW9uIGtleSwgYW5kIHRoZW4gdXNlcyB0aGUgc2Vzc2lvbiBrZXkgdG9cbiAqIGRlY3J5cHQgdGhlIG1lc3NhZ2UuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3B1YmxpY19rZXlfZW5jcnlwdGVkX3Nlc3Npb25fa2V5KCkge1xuICB0aGlzLnZlcnNpb24gPSAzO1xuXG4gIHRoaXMucHVibGljS2V5SWQgPSBuZXcgdHlwZV9rZXlpZCgpO1xuICB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSA9ICdyc2FfZW5jcnlwdCc7XG5cbiAgdGhpcy5zZXNzaW9uS2V5ID0gbnVsbDtcbiAgdGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtID0gJ2FlczI1Nic7XG5cbiAgLyoqIEB0eXBlIHtvcGVucGdwX3R5cGVfbXBpW119ICovXG4gIHRoaXMuZW5jcnlwdGVkID0gW107XG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgcHVibGlja2V5IGVuY3J5cHRlZCBzZXNzaW9uIGtleSBwYWNrZXQgKHRhZyAxKS5cbiAgICogXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIGEgdGFnIDEgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gUG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW4gTGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2ZcbiAgICogICAgICAgICAgICBpbnB1dCBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBPYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG5cbiAgICB0aGlzLnZlcnNpb24gPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG4gICAgdGhpcy5wdWJsaWNLZXlJZC5yZWFkKGJ5dGVzLnN1YnN0cigxKSk7XG4gICAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSBlbnVtcy5yZWFkKGVudW1zLnB1YmxpY0tleSwgYnl0ZXNbOV0uY2hhckNvZGVBdCgpKTtcblxuICAgIHZhciBpID0gMTA7XG5cbiAgICB2YXIgaW50ZWdlckNvdW50ID0gKGZ1bmN0aW9uKGFsZ28pIHtcbiAgICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgICBjYXNlICdyc2FfZW5jcnlwdCc6XG4gICAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgICAgICAgIHJldHVybiAxO1xuXG4gICAgICAgIGNhc2UgJ2VsZ2FtYWwnOlxuICAgICAgICAgIHJldHVybiAyO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBhbGdvcml0aG0uXCIpO1xuICAgICAgfVxuICAgIH0pKHRoaXMucHVibGljS2V5QWxnb3JpdGhtKTtcblxuICAgIHRoaXMuZW5jcnlwdGVkID0gW107XG5cbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IGludGVnZXJDb3VudDsgaisrKSB7XG4gICAgICB2YXIgbXBpID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgICBpICs9IG1waS5yZWFkKGJ5dGVzLnN1YnN0cihpKSk7XG4gICAgICB0aGlzLmVuY3J5cHRlZC5wdXNoKG1waSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBhIHRhZyAxIHBhY2tldFxuICAgKiBcbiAgICogQHBhcmFtIHtTdHJpbmd9IHB1YmxpY0tleUlkXG4gICAqICAgICAgICAgICAgIFRoZSBwdWJsaWMga2V5IGlkIGNvcnJlc3BvbmRpbmcgdG8gcHVibGljTVBJcyBrZXkgYXMgc3RyaW5nXG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBwdWJsaWNNUElzXG4gICAqICAgICAgICAgICAgTXVsdGlwcmVjaXNpb24gaW50ZWdlciBvYmplY3RzIGRlc2NyaWJpbmcgdGhlIHB1YmxpYyBrZXlcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwdWJhbGdvXG4gICAqICAgICAgICAgICAgVGhlIGNvcnJlc3BvbmRpbmcgcHVibGljIGtleSBhbGdvcml0aG0gLy8gU2VlIFJGQzQ4ODAgOS4xXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gc3ltbWFsZ29cbiAgICogICAgICAgICAgICBUaGUgc3ltbWV0cmljIGNpcGhlciBhbGdvcml0aG0gdXNlZCB0byBlbmNyeXB0IHRoZSBkYXRhIFxuICAgKiAgICAgICAgICAgIHdpdGhpbiBhbiBlbmNyeXB0ZWRkYXRhcGFja2V0IG9yIGVuY3J5cHRlZGludGVncml0eS1cbiAgICogICAgICAgICAgICBwcm90ZWN0ZWRkYXRhcGFja2V0IFxuICAgKiAgICAgICAgICAgIGZvbGxvd2luZyB0aGlzIHBhY2tldCAvL1NlZSBSRkM0ODgwIDkuMlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc2Vzc2lvbmtleVxuICAgKiAgICAgICAgICAgIEEgc3RyaW5nIG9mIHJhbmRvbWJ5dGVzIHJlcHJlc2VudGluZyB0aGUgc2Vzc2lvbiBrZXlcbiAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG5cbiAgICB2YXIgcmVzdWx0ID0gU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLnZlcnNpb24pO1xuICAgIHJlc3VsdCArPSB0aGlzLnB1YmxpY0tleUlkLndyaXRlKCk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICBlbnVtcy53cml0ZShlbnVtcy5wdWJsaWNLZXksIHRoaXMucHVibGljS2V5QWxnb3JpdGhtKSk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZW5jcnlwdGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHQgKz0gdGhpcy5lbmNyeXB0ZWRbaV0ud3JpdGUoKVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICB2YXIgZGF0YSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICBlbnVtcy53cml0ZShlbnVtcy5zeW1tZXRyaWMsIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSkpO1xuXG4gICAgZGF0YSArPSB0aGlzLnNlc3Npb25LZXk7XG4gICAgdmFyIGNoZWNrc3VtID0gdXRpbC5jYWxjX2NoZWNrc3VtKHRoaXMuc2Vzc2lvbktleSk7XG4gICAgZGF0YSArPSB1dGlsLndyaXRlTnVtYmVyKGNoZWNrc3VtLCAyKTtcblxuICAgIHZhciBtcGkgPSBuZXcgdHlwZV9tcGkoKTtcbiAgICBtcGkuZnJvbUJ5dGVzKGNyeXB0by5wa2NzMS5lbWUuZW5jb2RlKFxuICAgICAgZGF0YSxcbiAgICAgIGtleS5tcGlbMF0uYnl0ZUxlbmd0aCgpKSk7XG5cbiAgICB0aGlzLmVuY3J5cHRlZCA9IGNyeXB0by5wdWJsaWNLZXlFbmNyeXB0KFxuICAgICAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0sXG4gICAgICBrZXkubXBpLFxuICAgICAgbXBpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyB0aGUgc2Vzc2lvbiBrZXkgKG9ubHkgZm9yIHB1YmxpYyBrZXkgZW5jcnlwdGVkIHNlc3Npb24ga2V5XG4gICAqIHBhY2tldHMgKHRhZyAxKVxuICAgKiBcbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19tZXNzYWdlfSBtc2dcbiAgICogICAgICAgICAgICBUaGUgbWVzc2FnZSBvYmplY3QgKHdpdGggbWVtYmVyIGVuY3J5cHRlZERhdGFcbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19wcml2YXRla2V5fSBrZXlcbiAgICogICAgICAgICAgICBQcml2YXRlIGtleSB3aXRoIHNlY01QSXMgdW5sb2NrZWRcbiAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgdW5lbmNyeXB0ZWQgc2Vzc2lvbiBrZXlcbiAgICovXG4gIHRoaXMuZGVjcnlwdCA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHZhciByZXN1bHQgPSBjcnlwdG8ucHVibGljS2V5RGVjcnlwdChcbiAgICAgIHRoaXMucHVibGljS2V5QWxnb3JpdGhtLFxuICAgICAga2V5Lm1waSxcbiAgICAgIHRoaXMuZW5jcnlwdGVkKS50b0J5dGVzKCk7XG5cbiAgICB2YXIgY2hlY2tzdW0gPSB1dGlsLnJlYWROdW1iZXIocmVzdWx0LnN1YnN0cihyZXN1bHQubGVuZ3RoIC0gMikpO1xuXG4gICAgdmFyIGRlY29kZWQgPSBjcnlwdG8ucGtjczEuZW1lLmRlY29kZShcbiAgICAgIHJlc3VsdCxcbiAgICAgIGtleS5tcGlbMF0uYnl0ZUxlbmd0aCgpKTtcblxuICAgIHZhciBrZXkgPSBkZWNvZGVkLnN1YnN0cmluZygxLCBkZWNvZGVkLmxlbmd0aCAtIDIpO1xuXG4gICAgaWYgKGNoZWNrc3VtICE9IHV0aWwuY2FsY19jaGVja3N1bShrZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NoZWNrc3VtIG1pc21hdGNoJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2Vzc2lvbktleSA9IGtleTtcbiAgICAgIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA9XG4gICAgICAgIGVudW1zLnJlYWQoZW51bXMuc3ltbWV0cmljLCBkZWNvZGVkLmNoYXJDb2RlQXQoMCkpO1xuICAgIH1cbiAgfVxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBwdWJsaWNfa2V5ID0gcmVxdWlyZSgnLi9wdWJsaWNfa2V5LmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcHVibGljX3N1YmtleSgpIHtcbiAgcHVibGljX2tleS5jYWxsKHRoaXMpO1xufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHB1YmxpY0tleSA9IHJlcXVpcmUoJy4vcHVibGljX2tleS5qcycpLFxuICBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG4gIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG4gIGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpLFxuICB0eXBlX21waSA9IHJlcXVpcmUoJy4uL3R5cGUvbXBpLmpzJyksXG4gIHR5cGVfczJrID0gcmVxdWlyZSgnLi4vdHlwZS9zMmsuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIEtleSBNYXRlcmlhbCBQYWNrZXQgKFRhZyA1LDYsNywxNClcbiAqICAgXG4gKiBSRkM0NDgwIDUuNTpcbiAqIEEga2V5IG1hdGVyaWFsIHBhY2tldCBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uIGFib3V0IGEgcHVibGljIG9yXG4gKiBwcml2YXRlIGtleS4gIFRoZXJlIGFyZSBmb3VyIHZhcmlhbnRzIG9mIHRoaXMgcGFja2V0IHR5cGUsIGFuZCB0d29cbiAqIG1ham9yIHZlcnNpb25zLiAgQ29uc2VxdWVudGx5LCB0aGlzIHNlY3Rpb24gaXMgY29tcGxleC5cbiAqL1xuZnVuY3Rpb24gcGFja2V0X3NlY3JldF9rZXkoKSB7XG4gIHB1YmxpY0tleS5jYWxsKHRoaXMpO1xuICAvLyBlbmNyeXB0ZWQgc2VjcmV0LWtleSBkYXRhXG4gIHRoaXMuZW5jcnlwdGVkID0gbnVsbDtcbiAgLy8gaW5kaWNhdG9yIGlmIHNlY3JldC1rZXkgZGF0YSBpcyBhdmFpbGFibGUgaW4gZGVjcnlwdGVkIGZvcm1cbiAgdGhpcy5pc0RlY3J5cHRlZCA9IGZhbHNlO1xuXG5cbiAgZnVuY3Rpb24gZ2V0X2hhc2hfbGVuKGhhc2gpIHtcbiAgICBpZiAoaGFzaCA9PSAnc2hhMScpXG4gICAgICByZXR1cm4gMjA7XG4gICAgZWxzZVxuICAgICAgcmV0dXJuIDI7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRfaGFzaF9mbihoYXNoKSB7XG4gICAgaWYgKGhhc2ggPT0gJ3NoYTEnKVxuICAgICAgcmV0dXJuIGNyeXB0by5oYXNoLnNoYTE7XG4gICAgZWxzZVxuICAgICAgcmV0dXJuIGZ1bmN0aW9uKGMpIHtcbiAgICAgICAgcmV0dXJuIHV0aWwud3JpdGVOdW1iZXIodXRpbC5jYWxjX2NoZWNrc3VtKGMpLCAyKTtcbiAgICB9O1xuICB9XG5cbiAgLy8gSGVscGVyIGZ1bmN0aW9uXG5cbiAgZnVuY3Rpb24gcGFyc2VfY2xlYXJ0ZXh0X21waShoYXNoX2FsZ29yaXRobSwgY2xlYXJ0ZXh0LCBhbGdvcml0aG0pIHtcbiAgICB2YXIgaGFzaGxlbiA9IGdldF9oYXNoX2xlbihoYXNoX2FsZ29yaXRobSksXG4gICAgICBoYXNoZm4gPSBnZXRfaGFzaF9mbihoYXNoX2FsZ29yaXRobSk7XG5cbiAgICB2YXIgaGFzaHRleHQgPSBjbGVhcnRleHQuc3Vic3RyKGNsZWFydGV4dC5sZW5ndGggLSBoYXNobGVuKTtcbiAgICBjbGVhcnRleHQgPSBjbGVhcnRleHQuc3Vic3RyKDAsIGNsZWFydGV4dC5sZW5ndGggLSBoYXNobGVuKTtcblxuICAgIHZhciBoYXNoID0gaGFzaGZuKGNsZWFydGV4dCk7XG5cbiAgICBpZiAoaGFzaCAhPSBoYXNodGV4dClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkhhc2ggbWlzbWF0Y2guXCIpO1xuXG4gICAgdmFyIG1waXMgPSBjcnlwdG8uZ2V0UHJpdmF0ZU1waUNvdW50KGFsZ29yaXRobSk7XG5cbiAgICB2YXIgaiA9IDA7XG4gICAgdmFyIG1waSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtcGlzICYmIGogPCBjbGVhcnRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgIG1waVtpXSA9IG5ldyB0eXBlX21waSgpO1xuICAgICAgaiArPSBtcGlbaV0ucmVhZChjbGVhcnRleHQuc3Vic3RyKGopKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbXBpO1xuICB9XG5cbiAgZnVuY3Rpb24gd3JpdGVfY2xlYXJ0ZXh0X21waShoYXNoX2FsZ29yaXRobSwgYWxnb3JpdGhtLCBtcGkpIHtcbiAgICB2YXIgYnl0ZXMgPSAnJztcbiAgICB2YXIgZGlzY2FyZCA9IGNyeXB0by5nZXRQdWJsaWNNcGlDb3VudChhbGdvcml0aG0pO1xuXG4gICAgZm9yICh2YXIgaSA9IGRpc2NhcmQ7IGkgPCBtcGkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGJ5dGVzICs9IG1waVtpXS53cml0ZSgpO1xuICAgIH1cblxuXG4gICAgYnl0ZXMgKz0gZ2V0X2hhc2hfZm4oaGFzaF9hbGdvcml0aG0pKGJ5dGVzKTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG5cbiAgLy8gNS41LjMuICBTZWNyZXQtS2V5IFBhY2tldCBGb3JtYXRzXG5cbiAgLyoqXG4gICAqIEludGVybmFsIHBhcnNlciBmb3IgcHJpdmF0ZSBrZXlzIGFzIHNwZWNpZmllZCBpbiBSRkMgNDg4MCBzZWN0aW9uIDUuNS4zXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBieXRlcyBJbnB1dCBzdHJpbmcgdG8gcmVhZCB0aGUgcGFja2V0IGZyb21cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBTdGFydCBwb3NpdGlvbiBmb3IgdGhlIHBhcnNlclxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBMZW5ndGggb2YgdGhlIHBhY2tldCBvciByZW1haW5pbmcgbGVuZ3RoIG9mIGJ5dGVzXG4gICAqIEByZXR1cm4ge09iamVjdH0gVGhpcyBvYmplY3Qgd2l0aCBhdHRyaWJ1dGVzIHNldCBieSB0aGUgcGFyc2VyXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIC8vIC0gQSBQdWJsaWMtS2V5IG9yIFB1YmxpYy1TdWJrZXkgcGFja2V0LCBhcyBkZXNjcmliZWQgYWJvdmUuXG4gICAgdmFyIGxlbiA9IHRoaXMucmVhZFB1YmxpY0tleShieXRlcyk7XG5cbiAgICBieXRlcyA9IGJ5dGVzLnN1YnN0cihsZW4pO1xuXG5cbiAgICAvLyAtIE9uZSBvY3RldCBpbmRpY2F0aW5nIHN0cmluZy10by1rZXkgdXNhZ2UgY29udmVudGlvbnMuICBaZXJvXG4gICAgLy8gICBpbmRpY2F0ZXMgdGhhdCB0aGUgc2VjcmV0LWtleSBkYXRhIGlzIG5vdCBlbmNyeXB0ZWQuICAyNTUgb3IgMjU0XG4gICAgLy8gICBpbmRpY2F0ZXMgdGhhdCBhIHN0cmluZy10by1rZXkgc3BlY2lmaWVyIGlzIGJlaW5nIGdpdmVuLiAgQW55XG4gICAgLy8gICBvdGhlciB2YWx1ZSBpcyBhIHN5bW1ldHJpYy1rZXkgZW5jcnlwdGlvbiBhbGdvcml0aG0gaWRlbnRpZmllci5cbiAgICB2YXIgaXNFbmNyeXB0ZWQgPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG5cbiAgICBpZiAoaXNFbmNyeXB0ZWQpIHtcbiAgICAgIHRoaXMuZW5jcnlwdGVkID0gYnl0ZXM7XG4gICAgfSBlbHNlIHtcblxuICAgICAgLy8gLSBQbGFpbiBvciBlbmNyeXB0ZWQgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgY29tcHJpc2luZyB0aGUgc2VjcmV0XG4gICAgICAvLyAgIGtleSBkYXRhLiAgVGhlc2UgYWxnb3JpdGhtLXNwZWNpZmljIGZpZWxkcyBhcmUgYXMgZGVzY3JpYmVkXG4gICAgICAvLyAgIGJlbG93LlxuXG4gICAgICB0aGlzLm1waSA9IHRoaXMubXBpLmNvbmNhdChwYXJzZV9jbGVhcnRleHRfbXBpKCdtb2QnLCBieXRlcy5zdWJzdHIoMSksXG4gICAgICAgIHRoaXMuYWxnb3JpdGhtKSk7XG4gICAgICB0aGlzLmlzRGVjcnlwdGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgfTtcblxuICAvKlxuICAgICAqIENyZWF0ZXMgYW4gT3BlblBHUCBrZXkgcGFja2V0IGZvciB0aGUgZ2l2ZW4ga2V5LiBtdWNoIFxuXHQgKiBUT0RPIGluIHJlZ2FyZHMgdG8gczJrLCBzdWJrZXlzLlxuICAgICAqIEBwYXJhbSB7SW50ZWdlcn0ga2V5VHlwZSBGb2xsb3dzIHRoZSBPcGVuUEdQIGFsZ29yaXRobSBzdGFuZGFyZCwgXG5cdCAqIElFIDEgY29ycmVzcG9uZHMgdG8gUlNBLlxuICAgICAqIEBwYXJhbSB7UlNBLmtleU9iamVjdH0ga2V5XG4gICAgICogQHBhcmFtIHBhc3NwaHJhc2VcbiAgICAgKiBAcGFyYW0gczJrSGFzaFxuICAgICAqIEBwYXJhbSBzeW1tZXRyaWNFbmNyeXB0aW9uQWxnb3JpdGhtXG4gICAgICogQHBhcmFtIHRpbWVQYWNrZXRcbiAgICAgKiBAcmV0dXJuIHtPYmplY3R9IHtib2R5OiBbc3RyaW5nXU9wZW5QR1AgcGFja2V0IGJvZHkgY29udGVudHMsIFxuXHRcdGhlYWRlcjogW3N0cmluZ10gT3BlblBHUCBwYWNrZXQgaGVhZGVyLCBzdHJpbmc6IFtzdHJpbmddIGhlYWRlcitib2R5fVxuICAgICAqL1xuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGJ5dGVzID0gdGhpcy53cml0ZVB1YmxpY0tleSgpO1xuXG4gICAgaWYgKCF0aGlzLmVuY3J5cHRlZCkge1xuICAgICAgYnl0ZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcblxuICAgICAgYnl0ZXMgKz0gd3JpdGVfY2xlYXJ0ZXh0X21waSgnbW9kJywgdGhpcy5hbGdvcml0aG0sIHRoaXMubXBpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYnl0ZXMgKz0gdGhpcy5lbmNyeXB0ZWQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9O1xuXG5cblxuXG4gIC8qKiBFbmNyeXB0IHRoZSBwYXlsb2FkLiBCeSBkZWZhdWx0LCB3ZSB1c2UgYWVzMjU2IGFuZCBpdGVyYXRlZCwgc2FsdGVkIHN0cmluZ1xuICAgKiB0byBrZXkgc3BlY2lmaWVyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYXNzcGhyYXNlXG4gICAqL1xuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihwYXNzcGhyYXNlKSB7XG5cbiAgICB2YXIgczJrID0gbmV3IHR5cGVfczJrKCksXG4gICAgICBzeW1tZXRyaWMgPSAnYWVzMjU2JyxcbiAgICAgIGNsZWFydGV4dCA9IHdyaXRlX2NsZWFydGV4dF9tcGkoJ3NoYTEnLCB0aGlzLmFsZ29yaXRobSwgdGhpcy5tcGkpLFxuICAgICAga2V5ID0gcHJvZHVjZUVuY3J5cHRpb25LZXkoczJrLCBwYXNzcGhyYXNlLCBzeW1tZXRyaWMpLFxuICAgICAgYmxvY2tMZW4gPSBjcnlwdG8uY2lwaGVyW3N5bW1ldHJpY10uYmxvY2tTaXplLFxuICAgICAgaXYgPSBjcnlwdG8ucmFuZG9tLmdldFJhbmRvbUJ5dGVzKGJsb2NrTGVuKTtcblxuXG4gICAgdGhpcy5lbmNyeXB0ZWQgPSAnJztcbiAgICB0aGlzLmVuY3J5cHRlZCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDI1NCk7XG4gICAgdGhpcy5lbmNyeXB0ZWQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5zeW1tZXRyaWMsIHN5bW1ldHJpYykpO1xuICAgIHRoaXMuZW5jcnlwdGVkICs9IHMyay53cml0ZSgpO1xuICAgIHRoaXMuZW5jcnlwdGVkICs9IGl2O1xuXG4gICAgdGhpcy5lbmNyeXB0ZWQgKz0gY3J5cHRvLmNmYi5ub3JtYWxFbmNyeXB0KHN5bW1ldHJpYywga2V5LCBjbGVhcnRleHQsIGl2KTtcbiAgfTtcblxuICBmdW5jdGlvbiBwcm9kdWNlRW5jcnlwdGlvbktleShzMmssIHBhc3NwaHJhc2UsIGFsZ29yaXRobSkge1xuICAgIHJldHVybiBzMmsucHJvZHVjZV9rZXkocGFzc3BocmFzZSxcbiAgICAgIGNyeXB0by5jaXBoZXJbYWxnb3JpdGhtXS5rZXlTaXplKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyB0aGUgcHJpdmF0ZSBrZXkgTVBJcyB3aGljaCBhcmUgbmVlZGVkIHRvIHVzZSB0aGUga2V5LlxuICAgKiBvcGVucGdwX3BhY2tldF9rZXltYXRlcmlhbC5oYXNVbmVuY3J5cHRlZFNlY3JldEtleURhdGEgc2hvdWxkIGJlIFxuICAgKiBmYWxzZSBvdGhlcndpc2VcbiAgICogYSBjYWxsIHRvIHRoaXMgZnVuY3Rpb24gaXMgbm90IG5lZWRlZFxuICAgKiBcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0cl9wYXNzcGhyYXNlIFRoZSBwYXNzcGhyYXNlIGZvciB0aGlzIHByaXZhdGUga2V5IFxuICAgKiBhcyBzdHJpbmdcbiAgICogQHJldHVybiB7Qm9vbGVhbn0gVHJ1ZSBpZiB0aGUgcGFzc3BocmFzZSB3YXMgY29ycmVjdDsgZmFsc2UgaWYgbm90XG4gICAqL1xuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihwYXNzcGhyYXNlKSB7XG4gICAgaWYgKHRoaXMuaXNEZWNyeXB0ZWQpXG4gICAgICByZXR1cm47XG5cbiAgICB2YXIgaSA9IDAsXG4gICAgICBzeW1tZXRyaWMsXG4gICAgICBrZXk7XG5cbiAgICB2YXIgczJrX3VzYWdlID0gdGhpcy5lbmNyeXB0ZWRbaSsrXS5jaGFyQ29kZUF0KCk7XG5cbiAgICAvLyAtIFtPcHRpb25hbF0gSWYgc3RyaW5nLXRvLWtleSB1c2FnZSBvY3RldCB3YXMgMjU1IG9yIDI1NCwgYSBvbmUtXG4gICAgLy8gICBvY3RldCBzeW1tZXRyaWMgZW5jcnlwdGlvbiBhbGdvcml0aG0uXG4gICAgaWYgKHMya191c2FnZSA9PSAyNTUgfHwgczJrX3VzYWdlID09IDI1NCkge1xuICAgICAgc3ltbWV0cmljID0gdGhpcy5lbmNyeXB0ZWRbaSsrXS5jaGFyQ29kZUF0KCk7XG4gICAgICBzeW1tZXRyaWMgPSBlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgc3ltbWV0cmljKTtcblxuICAgICAgLy8gLSBbT3B0aW9uYWxdIElmIHN0cmluZy10by1rZXkgdXNhZ2Ugb2N0ZXQgd2FzIDI1NSBvciAyNTQsIGFcbiAgICAgIC8vICAgc3RyaW5nLXRvLWtleSBzcGVjaWZpZXIuICBUaGUgbGVuZ3RoIG9mIHRoZSBzdHJpbmctdG8ta2V5XG4gICAgICAvLyAgIHNwZWNpZmllciBpcyBpbXBsaWVkIGJ5IGl0cyB0eXBlLCBhcyBkZXNjcmliZWQgYWJvdmUuXG4gICAgICB2YXIgczJrID0gbmV3IHR5cGVfczJrKCk7XG4gICAgICBpICs9IHMyay5yZWFkKHRoaXMuZW5jcnlwdGVkLnN1YnN0cihpKSk7XG5cbiAgICAgIGtleSA9IHByb2R1Y2VFbmNyeXB0aW9uS2V5KHMyaywgcGFzc3BocmFzZSwgc3ltbWV0cmljKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3ltbWV0cmljID0gczJrX3VzYWdlO1xuICAgICAgc3ltbWV0cmljID0gZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsIHN5bW1ldHJpYyk7XG4gICAgICBrZXkgPSBjcnlwdG8uaGFzaC5tZDUocGFzc3BocmFzZSk7XG4gICAgfVxuXG5cbiAgICAvLyAtIFtPcHRpb25hbF0gSWYgc2VjcmV0IGRhdGEgaXMgZW5jcnlwdGVkIChzdHJpbmctdG8ta2V5IHVzYWdlIG9jdGV0XG4gICAgLy8gICBub3QgemVybyksIGFuIEluaXRpYWwgVmVjdG9yIChJVikgb2YgdGhlIHNhbWUgbGVuZ3RoIGFzIHRoZVxuICAgIC8vICAgY2lwaGVyJ3MgYmxvY2sgc2l6ZS5cbiAgICB2YXIgaXYgPSB0aGlzLmVuY3J5cHRlZC5zdWJzdHIoaSxcbiAgICAgIGNyeXB0by5jaXBoZXJbc3ltbWV0cmljXS5ibG9ja1NpemUpO1xuXG4gICAgaSArPSBpdi5sZW5ndGg7XG5cbiAgICB2YXIgY2xlYXJ0ZXh0LFxuICAgICAgY2lwaGVydGV4dCA9IHRoaXMuZW5jcnlwdGVkLnN1YnN0cihpKTtcblxuICAgIGNsZWFydGV4dCA9IGNyeXB0by5jZmIubm9ybWFsRGVjcnlwdChzeW1tZXRyaWMsIGtleSwgY2lwaGVydGV4dCwgaXYpO1xuXG4gICAgdmFyIGhhc2ggPSBzMmtfdXNhZ2UgPT0gMjU0ID9cbiAgICAgICdzaGExJyA6XG4gICAgICAnbW9kJztcblxuXG4gICAgdGhpcy5tcGkgPSB0aGlzLm1waS5jb25jYXQocGFyc2VfY2xlYXJ0ZXh0X21waShoYXNoLCBjbGVhcnRleHQsXG4gICAgICB0aGlzLmFsZ29yaXRobSkpO1xuICAgIHRoaXMuaXNEZWNyeXB0ZWQgPSB0cnVlO1xuICB9O1xuXG4gIHRoaXMuZ2VuZXJhdGUgPSBmdW5jdGlvbihiaXRzLCBwYXNzcGhyYXNlKSB7XG4gICAgdGhpcy5tcGkgPSBjcnlwdG8uZ2VuZXJhdGVNcGkodGhpcy5hbGdvcml0aG0sIGJpdHMpO1xuICAgIHRoaXMuaXNEZWNyeXB0ZWQgPSB0cnVlO1xuICB9O1xuXG59XG5cbnBhY2tldF9zZWNyZXRfa2V5LnByb3RvdHlwZSA9IG5ldyBwdWJsaWNLZXk7XG5cbm1vZHVsZS5leHBvcnRzID0gcGFja2V0X3NlY3JldF9rZXk7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgc2VjcmV0X2tleSA9IHJlcXVpcmUoJy4vc2VjcmV0X2tleS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNlY3JldF9zdWJrZXkoKSB7XG4gIHNlY3JldF9rZXkuY2FsbCh0aGlzKTtcbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICBwYWNrZXQgPSByZXF1aXJlKCcuL3BhY2tldC5qcycpLFxuICBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG4gIGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpLFxuICB0eXBlX21waSA9IHJlcXVpcmUoJy4uL3R5cGUvbXBpLmpzJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBTaWduYXR1cmUgUGFja2V0IChUYWcgMilcbiAqIFxuICogUkZDNDQ4MCA1LjI6XG4gKiBBIFNpZ25hdHVyZSBwYWNrZXQgZGVzY3JpYmVzIGEgYmluZGluZyBiZXR3ZWVuIHNvbWUgcHVibGljIGtleSBhbmRcbiAqIHNvbWUgZGF0YS4gIFRoZSBtb3N0IGNvbW1vbiBzaWduYXR1cmVzIGFyZSBhIHNpZ25hdHVyZSBvZiBhIGZpbGUgb3IgYVxuICogYmxvY2sgb2YgdGV4dCwgYW5kIGEgc2lnbmF0dXJlIHRoYXQgaXMgYSBjZXJ0aWZpY2F0aW9uIG9mIGEgVXNlciBJRC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfc2lnbmF0dXJlKCkge1xuXG4gIHRoaXMuc2lnbmF0dXJlVHlwZSA9IG51bGw7XG4gIHRoaXMuaGFzaEFsZ29yaXRobSA9IG51bGw7XG4gIHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gbnVsbDtcblxuICB0aGlzLnNpZ25hdHVyZURhdGEgPSBudWxsO1xuICB0aGlzLnNpZ25lZEhhc2hWYWx1ZSA9IG51bGw7XG4gIHRoaXMubXBpID0gbnVsbDtcblxuICB0aGlzLmNyZWF0ZWQgPSBudWxsO1xuICB0aGlzLnNpZ25hdHVyZUV4cGlyYXRpb25UaW1lID0gbnVsbDtcbiAgdGhpcy5zaWduYXR1cmVOZXZlckV4cGlyZXMgPSBudWxsO1xuICB0aGlzLmV4cG9ydGFibGUgPSBudWxsO1xuICB0aGlzLnRydXN0TGV2ZWwgPSBudWxsO1xuICB0aGlzLnRydXN0QW1vdW50ID0gbnVsbDtcbiAgdGhpcy5yZWd1bGFyRXhwcmVzc2lvbiA9IG51bGw7XG4gIHRoaXMucmV2b2NhYmxlID0gbnVsbDtcbiAgdGhpcy5rZXlFeHBpcmF0aW9uVGltZSA9IG51bGw7XG4gIHRoaXMua2V5TmV2ZXJFeHBpcmVzID0gbnVsbDtcbiAgdGhpcy5wcmVmZXJyZWRTeW1tZXRyaWNBbGdvcml0aG1zID0gbnVsbDtcbiAgdGhpcy5yZXZvY2F0aW9uS2V5Q2xhc3MgPSBudWxsO1xuICB0aGlzLnJldm9jYXRpb25LZXlBbGdvcml0aG0gPSBudWxsO1xuICB0aGlzLnJldm9jYXRpb25LZXlGaW5nZXJwcmludCA9IG51bGw7XG4gIHRoaXMuaXNzdWVyS2V5SWQgPSBudWxsO1xuICB0aGlzLm5vdGF0aW9uID0ge307XG4gIHRoaXMucHJlZmVycmVkSGFzaEFsZ29yaXRobXMgPSBudWxsO1xuICB0aGlzLnByZWZlcnJlZENvbXByZXNzaW9uQWxnb3JpdGhtcyA9IG51bGw7XG4gIHRoaXMua2V5U2VydmVyUHJlZmVyZW5jZXMgPSBudWxsO1xuICB0aGlzLnByZWZlcnJlZEtleVNlcnZlciA9IG51bGw7XG4gIHRoaXMuaXNQcmltYXJ5VXNlcklEID0gbnVsbDtcbiAgdGhpcy5wb2xpY3lVUkkgPSBudWxsO1xuICB0aGlzLmtleUZsYWdzID0gbnVsbDtcbiAgdGhpcy5zaWduZXJzVXNlcklkID0gbnVsbDtcbiAgdGhpcy5yZWFzb25Gb3JSZXZvY2F0aW9uRmxhZyA9IG51bGw7XG4gIHRoaXMucmVhc29uRm9yUmV2b2NhdGlvblN0cmluZyA9IG51bGw7XG4gIHRoaXMuc2lnbmF0dXJlVGFyZ2V0UHVibGljS2V5QWxnb3JpdGhtID0gbnVsbDtcbiAgdGhpcy5zaWduYXR1cmVUYXJnZXRIYXNoQWxnb3JpdGhtID0gbnVsbDtcbiAgdGhpcy5zaWduYXR1cmVUYXJnZXRIYXNoID0gbnVsbDtcbiAgdGhpcy5lbWJlZGRlZFNpZ25hdHVyZSA9IG51bGw7XG5cbiAgdGhpcy52ZXJpZmllZCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBwYXJzaW5nIGZ1bmN0aW9uIGZvciBhIHNpZ25hdHVyZSBwYWNrZXQgKHRhZyAyKS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGJ5dGVzIHBheWxvYWQgb2YgYSB0YWcgMiBwYWNrZXRcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBwb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGJ5dGVzIHN0cmluZ1xuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBsZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBieXRlcyBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBvYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIGkgPSAwO1xuXG4gICAgdmFyIHZlcnNpb24gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcbiAgICAvLyBzd2l0Y2ggb24gdmVyc2lvbiAoMyBhbmQgNClcbiAgICBzd2l0Y2ggKHZlcnNpb24pIHtcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgLy8gT25lLW9jdGV0IGxlbmd0aCBvZiBmb2xsb3dpbmcgaGFzaGVkIG1hdGVyaWFsLiBNVVNUIGJlIDUuXG4gICAgICAgIGlmIChieXRlc1tpKytdLmNoYXJDb2RlQXQoKSAhPSA1KVxuICAgICAgICAgIHV0aWwucHJpbnRfZGVidWcoXCJvcGVucGdwLnBhY2tldC5zaWduYXR1cmUuanNcXG5cIiArXG4gICAgICAgICAgICAnaW52YWxpZCBPbmUtb2N0ZXQgbGVuZ3RoIG9mIGZvbGxvd2luZyBoYXNoZWQgbWF0ZXJpYWwuJyArXG4gICAgICAgICAgICAnTVVTVCBiZSA1LiBAOicgKyAoaSAtIDEpKTtcblxuICAgICAgICB2YXIgc2lncG9zID0gaTtcbiAgICAgICAgLy8gT25lLW9jdGV0IHNpZ25hdHVyZSB0eXBlLlxuICAgICAgICB0aGlzLnNpZ25hdHVyZVR5cGUgPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcblxuICAgICAgICAvLyBGb3VyLW9jdGV0IGNyZWF0aW9uIHRpbWUuXG4gICAgICAgIHRoaXMuY3JlYXRlZCA9IHV0aWwucmVhZERhdGUoYnl0ZXMuc3Vic3RyKGksIDQpKTtcbiAgICAgICAgaSArPSA0O1xuXG4gICAgICAgIC8vIHN0b3JpbmcgZGF0YSBhcHBlbmRlZCB0byBkYXRhIHdoaWNoIGdldHMgdmVyaWZpZWRcbiAgICAgICAgdGhpcy5zaWduYXR1cmVEYXRhID0gYnl0ZXMuc3Vic3RyaW5nKHBvc2l0aW9uLCBpKTtcblxuICAgICAgICAvLyBFaWdodC1vY3RldCBLZXkgSUQgb2Ygc2lnbmVyLlxuICAgICAgICB0aGlzLmlzc3VlcktleUlkID0gYnl0ZXMuc3Vic3RyaW5nKGksIGkgKyA4KTtcbiAgICAgICAgaSArPSA4O1xuXG4gICAgICAgIC8vIE9uZS1vY3RldCBwdWJsaWMta2V5IGFsZ29yaXRobS5cbiAgICAgICAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcblxuICAgICAgICAvLyBPbmUtb2N0ZXQgaGFzaCBhbGdvcml0aG0uXG4gICAgICAgIHRoaXMuaGFzaEFsZ29yaXRobSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNDpcbiAgICAgICAgdGhpcy5zaWduYXR1cmVUeXBlID0gYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMuaGFzaEFsZ29yaXRobSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuXG5cbiAgICAgICAgZnVuY3Rpb24gc3VicGFja2V0cyhieXRlcywgc2lnbmVkKSB7XG4gICAgICAgICAgLy8gVHdvLW9jdGV0IHNjYWxhciBvY3RldCBjb3VudCBmb3IgZm9sbG93aW5nIGhhc2hlZCBzdWJwYWNrZXRcbiAgICAgICAgICAvLyBkYXRhLlxuICAgICAgICAgIHZhciBzdWJwYWNrZXRfbGVuZ3RoID0gdXRpbC5yZWFkTnVtYmVyKFxuICAgICAgICAgICAgYnl0ZXMuc3Vic3RyKDAsIDIpKTtcblxuICAgICAgICAgIHZhciBpID0gMjtcblxuICAgICAgICAgIC8vIEhhc2hlZCBzdWJwYWNrZXQgZGF0YSBzZXQgKHplcm8gb3IgbW9yZSBzdWJwYWNrZXRzKVxuICAgICAgICAgIHZhciBzdWJwYWNrZWRfcmVhZCA9IDA7XG4gICAgICAgICAgd2hpbGUgKGkgPCAyICsgc3VicGFja2V0X2xlbmd0aCkge1xuXG4gICAgICAgICAgICB2YXIgbGVuID0gcGFja2V0LnJlYWRTaW1wbGVMZW5ndGgoYnl0ZXMuc3Vic3RyKGkpKTtcbiAgICAgICAgICAgIGkgKz0gbGVuLm9mZnNldDtcblxuICAgICAgICAgICAgLy8gU2luY2UgaXQgaXMgdHJpdmlhbCB0byBhZGQgZGF0YSB0byB0aGUgdW5oYXNoZWQgcG9ydGlvbiBvZiBcbiAgICAgICAgICAgIC8vIHRoZSBwYWNrZXQgd2Ugc2ltcGx5IGlnbm9yZSBhbGwgdW5hdXRoZW50aWNhdGVkIGRhdGEuXG4gICAgICAgICAgICBpZiAoc2lnbmVkKVxuICAgICAgICAgICAgICB0aGlzLnJlYWRfc3ViX3BhY2tldChieXRlcy5zdWJzdHIoaSwgbGVuLmxlbikpO1xuXG4gICAgICAgICAgICBpICs9IGxlbi5sZW47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cblxuICAgICAgICBpICs9IHN1YnBhY2tldHMuY2FsbCh0aGlzLCBieXRlcy5zdWJzdHIoaSksIHRydWUpO1xuXG4gICAgICAgIC8vIEEgVjQgc2lnbmF0dXJlIGhhc2hlcyB0aGUgcGFja2V0IGJvZHlcbiAgICAgICAgLy8gc3RhcnRpbmcgZnJvbSBpdHMgZmlyc3QgZmllbGQsIHRoZSB2ZXJzaW9uIG51bWJlciwgdGhyb3VnaCB0aGUgZW5kXG4gICAgICAgIC8vIG9mIHRoZSBoYXNoZWQgc3VicGFja2V0IGRhdGEuICBUaHVzLCB0aGUgZmllbGRzIGhhc2hlZCBhcmUgdGhlXG4gICAgICAgIC8vIHNpZ25hdHVyZSB2ZXJzaW9uLCB0aGUgc2lnbmF0dXJlIHR5cGUsIHRoZSBwdWJsaWMta2V5IGFsZ29yaXRobSwgdGhlXG4gICAgICAgIC8vIGhhc2ggYWxnb3JpdGhtLCB0aGUgaGFzaGVkIHN1YnBhY2tldCBsZW5ndGgsIGFuZCB0aGUgaGFzaGVkXG4gICAgICAgIC8vIHN1YnBhY2tldCBib2R5LlxuICAgICAgICB0aGlzLnNpZ25hdHVyZURhdGEgPSBieXRlcy5zdWJzdHIoMCwgaSk7XG5cbiAgICAgICAgaSArPSBzdWJwYWNrZXRzLmNhbGwodGhpcywgYnl0ZXMuc3Vic3RyKGkpLCBmYWxzZSk7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ZlcnNpb24gJyArIHZlcnNpb24gKyAnIG9mIHRoZSBzaWduYXR1cmUgaXMgdW5zdXBwb3J0ZWQuJyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIFR3by1vY3RldCBmaWVsZCBob2xkaW5nIGxlZnQgMTYgYml0cyBvZiBzaWduZWQgaGFzaCB2YWx1ZS5cbiAgICB0aGlzLnNpZ25lZEhhc2hWYWx1ZSA9IGJ5dGVzLnN1YnN0cihpLCAyKTtcbiAgICBpICs9IDI7XG5cbiAgICB0aGlzLnNpZ25hdHVyZSA9IGJ5dGVzLnN1YnN0cihpKTtcbiAgfTtcblxuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuc2lnbmF0dXJlRGF0YSArXG4gICAgICB1dGlsLndyaXRlTnVtYmVyKDAsIDIpICsgLy8gTnVtYmVyIG9mIHVuc2lnbmVkIHN1YnBhY2tldHMuXG4gICAgdGhpcy5zaWduZWRIYXNoVmFsdWUgK1xuICAgICAgdGhpcy5zaWduYXR1cmU7XG4gIH07XG5cbiAgLyoqXG4gICAqIFNpZ25zIHByb3ZpZGVkIGRhdGEuIFRoaXMgbmVlZHMgdG8gYmUgZG9uZSBwcmlvciB0byBzZXJpYWxpemF0aW9uLlxuICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YSBDb250YWlucyBwYWNrZXRzIHRvIGJlIHNpZ25lZC5cbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19wcml2YXRla2V5fSBwcml2YXRla2V5IHByaXZhdGUga2V5IHVzZWQgdG8gc2lnbiB0aGUgbWVzc2FnZS4gXG4gICAqL1xuICB0aGlzLnNpZ24gPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB2YXIgc2lnbmF0dXJlVHlwZSA9IGVudW1zLndyaXRlKGVudW1zLnNpZ25hdHVyZSwgdGhpcy5zaWduYXR1cmVUeXBlKSxcbiAgICAgIHB1YmxpY0tleUFsZ29yaXRobSA9IGVudW1zLndyaXRlKGVudW1zLnB1YmxpY0tleSwgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0pLFxuICAgICAgaGFzaEFsZ29yaXRobSA9IGVudW1zLndyaXRlKGVudW1zLmhhc2gsIHRoaXMuaGFzaEFsZ29yaXRobSk7XG5cbiAgICB2YXIgcmVzdWx0ID0gU3RyaW5nLmZyb21DaGFyQ29kZSg0KTtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShzaWduYXR1cmVUeXBlKTtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShwdWJsaWNLZXlBbGdvcml0aG0pO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGhhc2hBbGdvcml0aG0pO1xuXG4gICAgLy9DYWxjdWxhdGUgc3VicGFja2V0c1xuICAgIHZhciBjcmVhdGlvblRpbWVTdWJwYWNrZXQgPSB3cml0ZV9zdWJfcGFja2V0KGVudW1zLnNpZ25hdHVyZVN1YnBhY2tldC5zaWduYXR1cmVfY3JlYXRpb25fdGltZSxcbiAgICAgIHV0aWwud3JpdGVEYXRlKG5ldyBEYXRlKCkpKTtcblxuICAgIHZhciBpc3N1ZXJTdWJwYWNrZXQgPSB3cml0ZV9zdWJfcGFja2V0KGVudW1zLnNpZ25hdHVyZVN1YnBhY2tldC5pc3N1ZXIsIGtleS5nZXRLZXlJZCgpLndyaXRlKCkpO1xuXG4gICAgLy8gQWRkIHN1YnBhY2tldHMgaGVyZVxuICAgIHJlc3VsdCArPSB1dGlsLndyaXRlTnVtYmVyKGNyZWF0aW9uVGltZVN1YnBhY2tldC5sZW5ndGggKyBpc3N1ZXJTdWJwYWNrZXQubGVuZ3RoLCAyKTtcbiAgICByZXN1bHQgKz0gY3JlYXRpb25UaW1lU3VicGFja2V0ICsgaXNzdWVyU3VicGFja2V0O1xuXG4gICAgdGhpcy5zaWduYXR1cmVEYXRhID0gcmVzdWx0O1xuXG4gICAgdmFyIHRyYWlsZXIgPSB0aGlzLmNhbGN1bGF0ZVRyYWlsZXIoKTtcblxuICAgIHZhciB0b0hhc2ggPSB0aGlzLnRvU2lnbihzaWduYXR1cmVUeXBlLCBkYXRhKSArXG4gICAgICB0aGlzLnNpZ25hdHVyZURhdGEgKyB0cmFpbGVyO1xuXG4gICAgdmFyIGhhc2ggPSBjcnlwdG8uaGFzaC5kaWdlc3QoaGFzaEFsZ29yaXRobSwgdG9IYXNoKTtcblxuICAgIHRoaXMuc2lnbmVkSGFzaFZhbHVlID0gaGFzaC5zdWJzdHIoMCwgMik7XG5cbiAgICB0aGlzLnNpZ25hdHVyZSA9IGNyeXB0by5zaWduYXR1cmUuc2lnbihoYXNoQWxnb3JpdGhtLFxuICAgICAgcHVibGljS2V5QWxnb3JpdGhtLCBrZXkubXBpLCB0b0hhc2gpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgc3ViIHNpZ25hdHVyZSBwYWNrZXQgKFNlZSBSRkMgNDg4MCA1LjIuMy4xKVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHR5cGUgc3VicGFja2V0IHNpZ25hdHVyZSB0eXBlLiBTaWduYXR1cmUgdHlwZXMgYXMgZGVzY3JpYmVkIFxuICAgKiBpbiBSRkM0ODgwIFNlY3Rpb24gNS4yLjMuMlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBkYXRhIHRvIGJlIGluY2x1ZGVkXG4gICAqIEByZXR1cm4ge1N0cmluZ30gYSBzdHJpbmctcmVwcmVzZW50YXRpb24gb2YgYSBzdWIgc2lnbmF0dXJlIHBhY2tldCAoU2VlIFJGQyA0ODgwIDUuMi4zLjEpXG4gICAqL1xuICBmdW5jdGlvbiB3cml0ZV9zdWJfcGFja2V0KHR5cGUsIGRhdGEpIHtcbiAgICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgICByZXN1bHQgKz0gcGFja2V0LndyaXRlU2ltcGxlTGVuZ3RoKGRhdGEubGVuZ3RoICsgMSk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodHlwZSk7XG4gICAgcmVzdWx0ICs9IGRhdGE7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIFY0IHNpZ25hdHVyZSBzdWIgcGFja2V0c1xuXG4gIHRoaXMucmVhZF9zdWJfcGFja2V0ID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgbXlwb3MgPSAwO1xuXG4gICAgZnVuY3Rpb24gcmVhZF9hcnJheShwcm9wLCBieXRlcykge1xuICAgICAgdGhpc1twcm9wXSA9IFtdO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXNbcHJvcF0ucHVzaChieXRlc1tpXS5jaGFyQ29kZUF0KCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRoZSBsZWZ0d29zdCBiaXQgZGVub3RlcyBhIFwiY3JpdGljYWxcIiBwYWNrZXQsIGJ1dCB3ZSBpZ25vcmUgaXQuXG4gICAgdmFyIHR5cGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgJiAweDdGO1xuXG4gICAgLy8gc3VicGFja2V0IHR5cGVcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgLy8gU2lnbmF0dXJlIENyZWF0aW9uIFRpbWVcbiAgICAgICAgdGhpcy5jcmVhdGVkID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vIFNpZ25hdHVyZSBFeHBpcmF0aW9uIFRpbWVcbiAgICAgICAgdmFyIHRpbWUgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXG4gICAgICAgIHRoaXMuc2lnbmF0dXJlTmV2ZXJFeHBpcmVzID0gdGltZS5nZXRUaW1lKCkgPT0gMDtcbiAgICAgICAgdGhpcy5zaWduYXR1cmVFeHBpcmF0aW9uVGltZSA9IHRpbWU7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIC8vIEV4cG9ydGFibGUgQ2VydGlmaWNhdGlvblxuICAgICAgICB0aGlzLmV4cG9ydGFibGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgPT0gMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDU6XG4gICAgICAgIC8vIFRydXN0IFNpZ25hdHVyZVxuICAgICAgICB0aGlzLnRydXN0TGV2ZWwgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMudHJ1c3RBbW91bnQgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA2OlxuICAgICAgICAvLyBSZWd1bGFyIEV4cHJlc3Npb25cbiAgICAgICAgdGhpcy5yZWd1bGFyRXhwcmVzc2lvbiA9IGJ5dGVzLnN1YnN0cihteXBvcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA3OlxuICAgICAgICAvLyBSZXZvY2FibGVcbiAgICAgICAgdGhpcy5yZXZvY2FibGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgPT0gMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDk6XG4gICAgICAgIC8vIEtleSBFeHBpcmF0aW9uIFRpbWVcbiAgICAgICAgdmFyIHRpbWUgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXG4gICAgICAgIHRoaXMua2V5RXhwaXJhdGlvblRpbWUgPSB0aW1lO1xuICAgICAgICB0aGlzLmtleU5ldmVyRXhwaXJlcyA9IHRpbWUuZ2V0VGltZSgpID09IDA7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDExOlxuICAgICAgICAvLyBQcmVmZXJyZWQgU3ltbWV0cmljIEFsZ29yaXRobXNcbiAgICAgICAgdGhpcy5wcmVmZXJyZWRTeW1tZXRyaWNBbGdvcml0aG1zID0gW107XG5cbiAgICAgICAgd2hpbGUgKG15cG9zICE9IGJ5dGVzLmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMucHJlZmVycmVkU3ltbWV0cmljQWxnb3JpdGhtcy5wdXNoKGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKSk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTI6XG4gICAgICAgIC8vIFJldm9jYXRpb24gS2V5XG4gICAgICAgIC8vICgxIG9jdGV0IG9mIGNsYXNzLCAxIG9jdGV0IG9mIHB1YmxpYy1rZXkgYWxnb3JpdGhtIElELCAyMFxuICAgICAgICAvLyBvY3RldHMgb2ZcbiAgICAgICAgLy8gZmluZ2VycHJpbnQpXG4gICAgICAgIHRoaXMucmV2b2NhdGlvbktleUNsYXNzID0gYnl0ZXNbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICB0aGlzLnJldm9jYXRpb25LZXlBbGdvcml0aG0gPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMucmV2b2NhdGlvbktleUZpbmdlcnByaW50ID0gYnl0ZXMuc3Vic3RyKG15cG9zLCAyMCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIDE2OlxuICAgICAgICAvLyBJc3N1ZXJcbiAgICAgICAgdGhpcy5pc3N1ZXJLZXlJZCA9IGJ5dGVzLnN1YnN0cihteXBvcywgOCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIDIwOlxuICAgICAgICAvLyBOb3RhdGlvbiBEYXRhXG4gICAgICAgIC8vIFdlIGRvbid0IGtub3cgaG93IHRvIGhhbmRsZSBhbnl0aGluZyBidXQgYSB0ZXh0IGZsYWdnZWQgZGF0YS5cbiAgICAgICAgaWYgKGJ5dGVzW215cG9zXS5jaGFyQ29kZUF0KCkgPT0gMHg4MCkge1xuXG4gICAgICAgICAgLy8gV2UgZXh0cmFjdCBrZXkvdmFsdWUgdHVwbGUgZnJvbSB0aGUgYnl0ZSBzdHJlYW0uXG4gICAgICAgICAgbXlwb3MgKz0gNDtcbiAgICAgICAgICB2YXIgbSA9IHV0aWwud3JpdGVOdW1iZXIoYnl0ZXMuc3Vic3RyKG15cG9zLCAyKSk7XG4gICAgICAgICAgbXlwb3MgKz0gMlxuICAgICAgICAgIHZhciBuID0gdXRpbC53cml0ZU51bWJlcihieXRlcy5zdWJzdHIobXlwb3MsIDIpKTtcbiAgICAgICAgICBteXBvcyArPSAyXG5cbiAgICAgICAgICB2YXIgbmFtZSA9IGJ5dGVzLnN1YnN0cihteXBvcywgbSksXG4gICAgICAgICAgICB2YWx1ZSA9IGJ5dGVzLnN1YnN0cihteXBvcyArIG0sIG4pO1xuXG4gICAgICAgICAgdGhpcy5ub3RhdGlvbltuYW1lXSA9IHZhbHVlO1xuICAgICAgICB9IGVsc2UgdGhyb3cgbmV3IEVycm9yKFwiVW5zdXBwb3J0ZWQgbm90YXRpb24gZmxhZy5cIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyMTpcbiAgICAgICAgLy8gUHJlZmVycmVkIEhhc2ggQWxnb3JpdGhtc1xuICAgICAgICByZWFkX2FycmF5LmNhbGwodGhpcywgJ3ByZWZlcnJlZEhhc2hBbGdvcml0aG1zJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyMjpcbiAgICAgICAgLy8gUHJlZmVycmVkIENvbXByZXNzaW9uIEFsZ29yaXRobXNcbiAgICAgICAgcmVhZF9hcnJheS5jYWxsKHRoaXMsICdwcmVmZXJyZWRDb21wcmVzc2lvbkFsZ29yaXRobXMgJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyMzpcbiAgICAgICAgLy8gS2V5IFNlcnZlciBQcmVmZXJlbmNlc1xuICAgICAgICByZWFkX2FycmF5LmNhbGwodGhpcywgJ2tleVNlcnZlclByZWZlcmVuY2VzcycsIGJ5dGVzLnN1YnN0cihteXBvcykpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjQ6XG4gICAgICAgIC8vIFByZWZlcnJlZCBLZXkgU2VydmVyXG4gICAgICAgIHRoaXMucHJlZmVycmVkS2V5U2VydmVyID0gYnl0ZXMuc3Vic3RyKG15cG9zKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI1OlxuICAgICAgICAvLyBQcmltYXJ5IFVzZXIgSURcbiAgICAgICAgdGhpcy5pc1ByaW1hcnlVc2VySUQgPSBieXRlc1tteXBvcysrXSAhPSAwO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjY6XG4gICAgICAgIC8vIFBvbGljeSBVUklcbiAgICAgICAgdGhpcy5wb2xpY3lVUkkgPSBieXRlcy5zdWJzdHIobXlwb3MpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjc6XG4gICAgICAgIC8vIEtleSBGbGFnc1xuICAgICAgICByZWFkX2FycmF5LmNhbGwodGhpcywgJ2tleUZsYWdzJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyODpcbiAgICAgICAgLy8gU2lnbmVyJ3MgVXNlciBJRFxuICAgICAgICB0aGlzLnNpZ25lcnNVc2VySWQgKz0gYnl0ZXMuc3Vic3RyKG15cG9zKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI5OlxuICAgICAgICAvLyBSZWFzb24gZm9yIFJldm9jYXRpb25cbiAgICAgICAgdGhpcy5yZWFzb25Gb3JSZXZvY2F0aW9uRmxhZyA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgdGhpcy5yZWFzb25Gb3JSZXZvY2F0aW9uU3RyaW5nID0gYnl0ZXMuc3Vic3RyKG15cG9zKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDMwOlxuICAgICAgICAvLyBGZWF0dXJlc1xuICAgICAgICByZWFkX2FycmF5LmNhbGwodGhpcywgJ2ZlYXR1cmVzJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzMTpcbiAgICAgICAgLy8gU2lnbmF0dXJlIFRhcmdldFxuICAgICAgICAvLyAoMSBvY3RldCBwdWJsaWMta2V5IGFsZ29yaXRobSwgMSBvY3RldCBoYXNoIGFsZ29yaXRobSwgTiBvY3RldHMgaGFzaClcbiAgICAgICAgdGhpcy5zaWduYXR1cmVUYXJnZXRQdWJsaWNLZXlBbGdvcml0aG0gPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlVGFyZ2V0SGFzaEFsZ29yaXRobSA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKTtcblxuICAgICAgICB2YXIgbGVuID0gY3J5cHRvLmdldEhhc2hCeXRlTGVuZ3RoKHRoaXMuc2lnbmF0dXJlVGFyZ2V0SGFzaEFsZ29yaXRobSk7XG5cbiAgICAgICAgdGhpcy5zaWduYXR1cmVUYXJnZXRIYXNoID0gYnl0ZXMuc3Vic3RyKG15cG9zLCBsZW4pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzI6XG4gICAgICAgIC8vIEVtYmVkZGVkIFNpZ25hdHVyZVxuICAgICAgICB0aGlzLmVtYmVkZGVkU2lnbmF0dXJlID0gbmV3IHBhY2tldF9zaWduYXR1cmUoKTtcbiAgICAgICAgdGhpcy5lbWJlZGRlZFNpZ25hdHVyZS5yZWFkKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJvcGVucGdwLnBhY2tldC5zaWduYXR1cmUuanNcXG5cIiArXG4gICAgICAgICAgJ3Vua25vd24gc2lnbmF0dXJlIHN1YnBhY2tldCB0eXBlICcgKyB0eXBlICsgXCIgQDpcIiArIG15cG9zICtcbiAgICAgICAgICBcIiBzdWJwbGVuOlwiICsgc3VicGxlbiArIFwiIGxlbjpcIiArIGxlbik7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfTtcblxuICAvLyBQcm9kdWNlcyBkYXRhIHRvIHByb2R1Y2Ugc2lnbmF0dXJlIG9uXG4gIHRoaXMudG9TaWduID0gZnVuY3Rpb24odHlwZSwgZGF0YSkge1xuICAgIHZhciB0ID0gZW51bXMuc2lnbmF0dXJlO1xuXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlIHQuYmluYXJ5OlxuICAgICAgICByZXR1cm4gZGF0YS5nZXRCeXRlcygpO1xuXG4gICAgICBjYXNlIHQudGV4dDpcbiAgICAgICAgcmV0dXJuIHRoaXMudG9TaWduKHQuYmluYXJ5LCBkYXRhKVxuICAgICAgICAgIC5yZXBsYWNlKC9cXHJcXG4vZywgJ1xcbicpXG4gICAgICAgICAgLnJlcGxhY2UoL1xcbi9nLCAnXFxyXFxuJyk7XG5cbiAgICAgIGNhc2UgdC5zdGFuZGFsb25lOlxuICAgICAgICByZXR1cm4gJyc7XG5cbiAgICAgIGNhc2UgdC5jZXJ0X2dlbmVyaWM6XG4gICAgICBjYXNlIHQuY2VydF9wZXJzb25hOlxuICAgICAgY2FzZSB0LmNlcnRfY2FzdWFsOlxuICAgICAgY2FzZSB0LmNlcnRfcG9zaXRpdmU6XG4gICAgICBjYXNlIHQuY2VydF9yZXZvY2F0aW9uOlxuICAgICAgICB7XG4gICAgICAgICAgdmFyIHBhY2tldCwgdGFnO1xuXG4gICAgICAgICAgaWYgKGRhdGEudXNlcmlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRhZyA9IDB4QjQ7XG4gICAgICAgICAgICBwYWNrZXQgPSBkYXRhLnVzZXJpZDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEudXNlcmF0dHJpYnV0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0YWcgPSAweEQxO1xuICAgICAgICAgICAgcGFja2V0ID0gZGF0YS51c2VyYXR0cmlidXRlO1xuICAgICAgICAgIH0gZWxzZSB0aHJvdyBuZXcgRXJyb3IoJ0VpdGhlciBhIHVzZXJpZCBvciB1c2VyYXR0cmlidXRlIHBhY2tldCBuZWVkcyB0byBiZSAnICtcbiAgICAgICAgICAgICAgJ3N1cHBsaWVkIGZvciBjZXJ0aWZpY2F0aW9uLicpO1xuXG4gICAgICAgICAgdmFyIGJ5dGVzID0gcGFja2V0LndyaXRlKCk7XG5cbiAgICAgICAgICByZXR1cm4gdGhpcy50b1NpZ24odC5rZXksIGRhdGEpICtcbiAgICAgICAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUodGFnKSArXG4gICAgICAgICAgICB1dGlsLndyaXRlTnVtYmVyKGJ5dGVzLmxlbmd0aCwgNCkgK1xuICAgICAgICAgICAgYnl0ZXM7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgdC5zdWJrZXlfYmluZGluZzpcbiAgICAgIGNhc2UgdC5rZXlfYmluZGluZzpcbiAgICAgICAge1xuICAgICAgICAgIHJldHVybiB0aGlzLnRvU2lnbih0LmtleSwgZGF0YSkgKyB0aGlzLnRvU2lnbih0LmtleSwge1xuICAgICAgICAgICAga2V5OiBkYXRhLmJpbmRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSB0LmtleTpcbiAgICAgICAge1xuICAgICAgICAgIGlmIChkYXRhLmtleSA9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBwYWNrZXQgaXMgcmVxdWlyZWQgZm9yIHRoaXMgc2lndGF0dXJlLicpO1xuXG4gICAgICAgICAgcmV0dXJuIGRhdGEua2V5LndyaXRlT2xkKCk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgdC5rZXlfcmV2b2NhdGlvbjpcbiAgICAgIGNhc2UgdC5zdWJrZXlfcmV2b2NhdGlvbjpcbiAgICAgICAgcmV0dXJuIHRoaXMudG9TaWduKHQua2V5LCBkYXRhKTtcbiAgICAgIGNhc2UgdC50aW1lc3RhbXA6XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIGNhc2UgdC50aHJpZF9wYXJ0eTpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gc2lnbmF0dXJlIHR5cGUuJylcbiAgICB9XG4gIH1cblxuXG4gIHRoaXMuY2FsY3VsYXRlVHJhaWxlciA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIGNhbGN1bGF0aW5nIHRoZSB0cmFpbGVyXG4gICAgdmFyIHRyYWlsZXIgPSAnJztcbiAgICB0cmFpbGVyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoNCk7IC8vIFZlcnNpb25cbiAgICB0cmFpbGVyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhGRik7XG4gICAgdHJhaWxlciArPSB1dGlsLndyaXRlTnVtYmVyKHRoaXMuc2lnbmF0dXJlRGF0YS5sZW5ndGgsIDQpO1xuICAgIHJldHVybiB0cmFpbGVyXG4gIH1cblxuXG4gIC8qKlxuICAgKiB2ZXJpZnlzIHRoZSBzaWduYXR1cmUgcGFja2V0LiBOb3RlOiBub3Qgc2lnbmF0dXJlIHR5cGVzIGFyZSBpbXBsZW1lbnRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBkYXRhIHdoaWNoIG9uIHRoZSBzaWduYXR1cmUgYXBwbGllc1xuICAgKiBAcGFyYW0ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXl9IGtleSB0aGUgcHVibGljIGtleSB0byB2ZXJpZnkgdGhlIHNpZ25hdHVyZVxuICAgKiBAcmV0dXJuIHtib29sZWFufSBUcnVlIGlmIG1lc3NhZ2UgaXMgdmVyaWZpZWQsIGVsc2UgZmFsc2UuXG4gICAqL1xuICB0aGlzLnZlcmlmeSA9IGZ1bmN0aW9uKGtleSwgZGF0YSkge1xuICAgIHZhciBzaWduYXR1cmVUeXBlID0gZW51bXMud3JpdGUoZW51bXMuc2lnbmF0dXJlLCB0aGlzLnNpZ25hdHVyZVR5cGUpLFxuICAgICAgcHVibGljS2V5QWxnb3JpdGhtID0gZW51bXMud3JpdGUoZW51bXMucHVibGljS2V5LCB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSksXG4gICAgICBoYXNoQWxnb3JpdGhtID0gZW51bXMud3JpdGUoZW51bXMuaGFzaCwgdGhpcy5oYXNoQWxnb3JpdGhtKTtcblxuICAgIHZhciBieXRlcyA9IHRoaXMudG9TaWduKHNpZ25hdHVyZVR5cGUsIGRhdGEpLFxuICAgICAgdHJhaWxlciA9IHRoaXMuY2FsY3VsYXRlVHJhaWxlcigpO1xuXG5cbiAgICB2YXIgbXBpY291bnQgPSAwO1xuICAgIC8vIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIFJTQSBzaWduYXR1cmVzOlxuICAgIC8vIFx0ICAgIC0gbXVsdGlwcmVjaXNpb24gbnVtYmVyIChNUEkpIG9mIFJTQSBzaWduYXR1cmUgdmFsdWUgbSoqZCBtb2Qgbi5cbiAgICBpZiAocHVibGljS2V5QWxnb3JpdGhtID4gMCAmJiBwdWJsaWNLZXlBbGdvcml0aG0gPCA0KVxuICAgICAgbXBpY291bnQgPSAxO1xuICAgIC8vICAgIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIERTQSBzaWduYXR1cmVzOlxuICAgIC8vICAgICAgLSBNUEkgb2YgRFNBIHZhbHVlIHIuXG4gICAgLy8gICAgICAtIE1QSSBvZiBEU0EgdmFsdWUgcy5cbiAgICBlbHNlIGlmIChwdWJsaWNLZXlBbGdvcml0aG0gPT0gMTcpXG4gICAgICBtcGljb3VudCA9IDI7XG5cbiAgICB2YXIgbXBpID0gW10sXG4gICAgICBpID0gMDtcbiAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1waWNvdW50OyBqKyspIHtcbiAgICAgIG1waVtqXSA9IG5ldyB0eXBlX21waSgpO1xuICAgICAgaSArPSBtcGlbal0ucmVhZCh0aGlzLnNpZ25hdHVyZS5zdWJzdHIoaSkpO1xuICAgIH1cblxuICAgIHRoaXMudmVyaWZpZWQgPSBjcnlwdG8uc2lnbmF0dXJlLnZlcmlmeShwdWJsaWNLZXlBbGdvcml0aG0sXG4gICAgICBoYXNoQWxnb3JpdGhtLCBtcGksIGtleS5tcGksXG4gICAgICBieXRlcyArIHRoaXMuc2lnbmF0dXJlRGF0YSArIHRyYWlsZXIpO1xuXG4gICAgcmV0dXJuIHRoaXMudmVyaWZpZWQ7XG4gIH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICBjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIFN5bS4gRW5jcnlwdGVkIEludGVncml0eSBQcm90ZWN0ZWQgRGF0YSBcbiAqIFBhY2tldCAoVGFnIDE4KVxuICogXG4gKiBSRkM0ODgwIDUuMTM6IFRoZSBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBJbnRlZ3JpdHkgUHJvdGVjdGVkIERhdGEgcGFja2V0IGlzXG4gKiBhIHZhcmlhbnQgb2YgdGhlIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgcGFja2V0LiBJdCBpcyBhIG5ldyBmZWF0dXJlXG4gKiBjcmVhdGVkIGZvciBPcGVuUEdQIHRoYXQgYWRkcmVzc2VzIHRoZSBwcm9ibGVtIG9mIGRldGVjdGluZyBhIG1vZGlmaWNhdGlvbiB0b1xuICogZW5jcnlwdGVkIGRhdGEuIEl0IGlzIHVzZWQgaW4gY29tYmluYXRpb24gd2l0aCBhIE1vZGlmaWNhdGlvbiBEZXRlY3Rpb24gQ29kZVxuICogcGFja2V0LlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3N5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZCgpIHtcbiAgLyoqIFRoZSBlbmNyeXB0ZWQgcGF5bG9hZC4gKi9cbiAgdGhpcy5lbmNyeXB0ZWQgPSBudWxsOyAvLyBzdHJpbmdcbiAgLyoqIEB0eXBlIHtCb29sZWFufVxuICAgKiBJZiBhZnRlciBkZWNyeXB0aW5nIHRoZSBwYWNrZXQgdGhpcyBpcyBzZXQgdG8gdHJ1ZSxcbiAgICogYSBtb2RpZmljYXRpb24gaGFzIGJlZW4gZGV0ZWN0ZWQgYW5kIHRodXMgdGhlIGNvbnRlbnRzXG4gICAqIHNob3VsZCBiZSBkaXNjYXJkZWQuXG4gICAqL1xuICB0aGlzLm1vZGlmaWNhdGlvbiA9IGZhbHNlO1xuICB0aGlzLnBhY2tldHM7XG5cblxuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIC8vIC0gQSBvbmUtb2N0ZXQgdmVyc2lvbiBudW1iZXIuIFRoZSBvbmx5IGN1cnJlbnRseSBkZWZpbmVkIHZhbHVlIGlzXG4gICAgLy8gMS5cbiAgICB2YXIgdmVyc2lvbiA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblxuICAgIGlmICh2ZXJzaW9uICE9IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwYWNrZXQgdmVyc2lvbi4nKTtcbiAgICB9XG5cbiAgICAvLyAtIEVuY3J5cHRlZCBkYXRhLCB0aGUgb3V0cHV0IG9mIHRoZSBzZWxlY3RlZCBzeW1tZXRyaWMta2V5IGNpcGhlclxuICAgIC8vICAgb3BlcmF0aW5nIGluIENpcGhlciBGZWVkYmFjayBtb2RlIHdpdGggc2hpZnQgYW1vdW50IGVxdWFsIHRvIHRoZVxuICAgIC8vICAgYmxvY2sgc2l6ZSBvZiB0aGUgY2lwaGVyIChDRkItbiB3aGVyZSBuIGlzIHRoZSBibG9jayBzaXplKS5cbiAgICB0aGlzLmVuY3J5cHRlZCA9IGJ5dGVzLnN1YnN0cigxKTtcbiAgfVxuXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcblxuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKDEpIC8vIFZlcnNpb25cbiAgICArIHRoaXMuZW5jcnlwdGVkO1xuICB9XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oc2Vzc2lvbktleUFsZ29yaXRobSwga2V5KSB7XG4gICAgdmFyIGJ5dGVzID0gdGhpcy5wYWNrZXRzLndyaXRlKClcblxuICAgIHZhciBwcmVmaXhyYW5kb20gPSBjcnlwdG8uZ2V0UHJlZml4UmFuZG9tKHNlc3Npb25LZXlBbGdvcml0aG0pO1xuICAgIHZhciBwcmVmaXggPSBwcmVmaXhyYW5kb20gKyBwcmVmaXhyYW5kb20uY2hhckF0KHByZWZpeHJhbmRvbS5sZW5ndGggLSAyKSArIHByZWZpeHJhbmRvbS5jaGFyQXQocHJlZml4cmFuZG9tLmxlbmd0aCAtXG4gICAgICAxKVxuXG4gICAgdmFyIHRvaGFzaCA9IGJ5dGVzO1xuXG5cbiAgICAvLyBNb2RpZmljYXRpb24gZGV0ZWN0aW9uIGNvZGUgcGFja2V0LlxuICAgIHRvaGFzaCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4RDMpO1xuICAgIHRvaGFzaCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MTQpO1xuXG5cbiAgICB0b2hhc2ggKz0gY3J5cHRvLmhhc2guc2hhMShwcmVmaXggKyB0b2hhc2gpO1xuXG5cbiAgICB0aGlzLmVuY3J5cHRlZCA9IGNyeXB0by5jZmIuZW5jcnlwdChwcmVmaXhyYW5kb20sXG4gICAgICBzZXNzaW9uS2V5QWxnb3JpdGhtLCB0b2hhc2gsIGtleSwgZmFsc2UpLnN1YnN0cmluZygwLFxuICAgICAgcHJlZml4Lmxlbmd0aCArIHRvaGFzaC5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIHRoZSBlbmNyeXB0ZWQgZGF0YSBjb250YWluZWQgaW4gdGhpcyBvYmplY3QgcmVhZF9wYWNrZXQgbXVzdFxuICAgKiBoYXZlIGJlZW4gY2FsbGVkIGJlZm9yZVxuICAgKiBcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBzZXNzaW9uS2V5QWxnb3JpdGhtXG4gICAqICAgICAgICAgICAgVGhlIHNlbGVjdGVkIHN5bW1ldHJpYyBlbmNyeXB0aW9uIGFsZ29yaXRobSB0byBiZSB1c2VkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBrZXkgVGhlIGtleSBvZiBjaXBoZXIgYmxvY2tzaXplIGxlbmd0aCB0byBiZSB1c2VkXG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIGRlY3J5cHRlZCBkYXRhIG9mIHRoaXMgcGFja2V0XG4gICAqL1xuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihzZXNzaW9uS2V5QWxnb3JpdGhtLCBrZXkpIHtcbiAgICB2YXIgZGVjcnlwdGVkID0gY3J5cHRvLmNmYi5kZWNyeXB0KFxuICAgICAgc2Vzc2lvbktleUFsZ29yaXRobSwga2V5LCB0aGlzLmVuY3J5cHRlZCwgZmFsc2UpO1xuXG5cbiAgICAvLyB0aGVyZSBtdXN0IGJlIGEgbW9kaWZpY2F0aW9uIGRldGVjdGlvbiBjb2RlIHBhY2tldCBhcyB0aGVcbiAgICAvLyBsYXN0IHBhY2tldCBhbmQgZXZlcnl0aGluZyBnZXRzIGhhc2hlZCBleGNlcHQgdGhlIGhhc2ggaXRzZWxmXG4gICAgdGhpcy5oYXNoID0gY3J5cHRvLmhhc2guc2hhMShcbiAgICAgIGNyeXB0by5jZmIubWRjKHNlc3Npb25LZXlBbGdvcml0aG0sIGtleSwgdGhpcy5lbmNyeXB0ZWQpICsgZGVjcnlwdGVkLnN1YnN0cmluZygwLCBkZWNyeXB0ZWQubGVuZ3RoIC0gMjApKTtcblxuXG4gICAgdmFyIG1kYyA9IGRlY3J5cHRlZC5zdWJzdHIoZGVjcnlwdGVkLmxlbmd0aCAtIDIwLCAyMCk7XG5cbiAgICBpZiAodGhpcy5oYXNoICE9IG1kYykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdNb2RpZmljYXRpb24gZGV0ZWN0ZWQuJyk7XG4gICAgfSBlbHNlXG4gICAgICB0aGlzLnBhY2tldHMucmVhZChkZWNyeXB0ZWQuc3Vic3RyKDAsIGRlY3J5cHRlZC5sZW5ndGggLSAyMikpO1xuICB9XG59O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHR5cGVfczJrID0gcmVxdWlyZSgnLi4vdHlwZS9zMmsuanMnKSxcbiAgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuICBjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgUGFja2V0cyAoVGFnIDEpXG4gKiBcbiAqIFJGQzQ4ODAgNS4xOiBBIFB1YmxpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldCBob2xkcyB0aGUgc2Vzc2lvbiBrZXlcbiAqIHVzZWQgdG8gZW5jcnlwdCBhIG1lc3NhZ2UuIFplcm8gb3IgbW9yZSBQdWJsaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleVxuICogcGFja2V0cyBhbmQvb3IgU3ltbWV0cmljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXkgcGFja2V0cyBtYXkgcHJlY2VkZSBhXG4gKiBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIFBhY2tldCwgd2hpY2ggaG9sZHMgYW4gZW5jcnlwdGVkIG1lc3NhZ2UuIFRoZVxuICogbWVzc2FnZSBpcyBlbmNyeXB0ZWQgd2l0aCB0aGUgc2Vzc2lvbiBrZXksIGFuZCB0aGUgc2Vzc2lvbiBrZXkgaXMgaXRzZWxmXG4gKiBlbmNyeXB0ZWQgYW5kIHN0b3JlZCBpbiB0aGUgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldChzKS4gVGhlXG4gKiBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIFBhY2tldCBpcyBwcmVjZWRlZCBieSBvbmUgUHVibGljLUtleSBFbmNyeXB0ZWRcbiAqIFNlc3Npb24gS2V5IHBhY2tldCBmb3IgZWFjaCBPcGVuUEdQIGtleSB0byB3aGljaCB0aGUgbWVzc2FnZSBpcyBlbmNyeXB0ZWQuXG4gKiBUaGUgcmVjaXBpZW50IG9mIHRoZSBtZXNzYWdlIGZpbmRzIGEgc2Vzc2lvbiBrZXkgdGhhdCBpcyBlbmNyeXB0ZWQgdG8gdGhlaXJcbiAqIHB1YmxpYyBrZXksIGRlY3J5cHRzIHRoZSBzZXNzaW9uIGtleSwgYW5kIHRoZW4gdXNlcyB0aGUgc2Vzc2lvbiBrZXkgdG9cbiAqIGRlY3J5cHQgdGhlIG1lc3NhZ2UuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3N5bV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkoKSB7XG4gIHRoaXMudGFnID0gMztcbiAgdGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSA9IG51bGw7XG4gIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA9ICdhZXMyNTYnO1xuICB0aGlzLmVuY3J5cHRlZCA9IG51bGw7XG4gIHRoaXMuczJrID0gbmV3IHR5cGVfczJrKCk7XG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgc3ltbWV0cmljIGVuY3J5cHRlZCBzZXNzaW9uIGtleSBwYWNrZXQgKHRhZyAzKS5cbiAgICogXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIGEgdGFnIDEgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gUG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5cbiAgICogICAgICAgICAgICBMZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZlxuICAgKiAgICAgICAgICAgIGlucHV0IGF0IHBvc2l0aW9uXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IE9iamVjdCByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAvLyBBIG9uZS1vY3RldCB2ZXJzaW9uIG51bWJlci4gVGhlIG9ubHkgY3VycmVudGx5IGRlZmluZWQgdmVyc2lvbiBpcyA0LlxuICAgIHRoaXMudmVyc2lvbiA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblxuICAgIC8vIEEgb25lLW9jdGV0IG51bWJlciBkZXNjcmliaW5nIHRoZSBzeW1tZXRyaWMgYWxnb3JpdGhtIHVzZWQuXG4gICAgdmFyIGFsZ28gPSBlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgYnl0ZXNbMV0uY2hhckNvZGVBdCgpKTtcblxuICAgIC8vIEEgc3RyaW5nLXRvLWtleSAoUzJLKSBzcGVjaWZpZXIsIGxlbmd0aCBhcyBkZWZpbmVkIGFib3ZlLlxuICAgIHZhciBzMmtsZW5ndGggPSB0aGlzLnMyay5yZWFkKGJ5dGVzLnN1YnN0cigyKSk7XG5cbiAgICAvLyBPcHRpb25hbGx5LCB0aGUgZW5jcnlwdGVkIHNlc3Npb24ga2V5IGl0c2VsZiwgd2hpY2ggaXMgZGVjcnlwdGVkXG4gICAgLy8gd2l0aCB0aGUgc3RyaW5nLXRvLWtleSBvYmplY3QuXG4gICAgdmFyIGRvbmUgPSBzMmtsZW5ndGggKyAyO1xuXG4gICAgaWYgKGRvbmUgPCBieXRlcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZW5jcnlwdGVkID0gYnl0ZXMuc3Vic3RyKGRvbmUpO1xuICAgICAgdGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSA9IGFsZ29cbiAgICB9IGVsc2VcbiAgICAgIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA9IGFsZ287XG4gIH1cblxuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGFsZ28gPSB0aGlzLmVuY3J5cHRlZCA9PSBudWxsID9cbiAgICAgIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA6XG4gICAgICB0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtO1xuXG4gICAgdmFyIGJ5dGVzID0gU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLnZlcnNpb24pICtcbiAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuc3ltbWV0cmljLCBhbGdvKSkgK1xuICAgICAgdGhpcy5zMmsud3JpdGUoKTtcblxuICAgIGlmICh0aGlzLmVuY3J5cHRlZCAhPSBudWxsKVxuICAgICAgYnl0ZXMgKz0gdGhpcy5lbmNyeXB0ZWQ7XG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIHRoZSBzZXNzaW9uIGtleSAob25seSBmb3IgcHVibGljIGtleSBlbmNyeXB0ZWQgc2Vzc2lvbiBrZXlcbiAgICogcGFja2V0cyAodGFnIDEpXG4gICAqIFxuICAgKiBAcGFyYW0ge29wZW5wZ3BfbXNnX21lc3NhZ2V9IG1zZ1xuICAgKiAgICAgICAgICAgIFRoZSBtZXNzYWdlIG9iamVjdCAod2l0aCBtZW1iZXIgZW5jcnlwdGVkRGF0YVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXl9IGtleVxuICAgKiAgICAgICAgICAgIFByaXZhdGUga2V5IHdpdGggc2VjTVBJcyB1bmxvY2tlZFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSB1bmVuY3J5cHRlZCBzZXNzaW9uIGtleVxuICAgKi9cbiAgdGhpcy5kZWNyeXB0ID0gZnVuY3Rpb24ocGFzc3BocmFzZSkge1xuICAgIHZhciBhbGdvID0gdGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSAhPSBudWxsID9cbiAgICAgIHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0gOlxuICAgICAgdGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtO1xuXG5cbiAgICB2YXIgbGVuZ3RoID0gY3J5cHRvLmNpcGhlclthbGdvXS5rZXlTaXplO1xuICAgIHZhciBrZXkgPSB0aGlzLnMyay5wcm9kdWNlX2tleShwYXNzcGhyYXNlLCBsZW5ndGgpO1xuXG4gICAgaWYgKHRoaXMuZW5jcnlwdGVkID09IG51bGwpIHtcbiAgICAgIHRoaXMuc2Vzc2lvbktleSA9IGtleTtcblxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgZGVjcnlwdGVkID0gY3J5cHRvLmNmYi5kZWNyeXB0KFxuICAgICAgICB0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtLCBrZXksIHRoaXMuZW5jcnlwdGVkLCB0cnVlKTtcblxuICAgICAgdGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsXG4gICAgICAgIGRlY3J5cHRlZFswXS5rZXlDb2RlQXQoKSk7XG5cbiAgICAgIHRoaXMuc2Vzc2lvbktleSA9IGRlY3J5cHRlZC5zdWJzdHIoMSk7XG4gICAgfVxuICB9XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24ocGFzc3BocmFzZSkge1xuICAgIHZhciBsZW5ndGggPSBjcnlwdG8uZ2V0S2V5TGVuZ3RoKHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0pO1xuICAgIHZhciBrZXkgPSB0aGlzLnMyay5wcm9kdWNlX2tleShwYXNzcGhyYXNlLCBsZW5ndGgpO1xuXG4gICAgdmFyIHByaXZhdGVfa2V5ID0gU3RyaW5nLmZyb21DaGFyQ29kZShcbiAgICAgIGVudW1zLndyaXRlKGVudW1zLnN5bW1ldHJpYywgdGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtKSkgK1xuXG4gICAgY3J5cHRvLmdldFJhbmRvbUJ5dGVzKFxuICAgICAgY3J5cHRvLmdldEtleUxlbmd0aCh0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0pKTtcblxuICAgIHRoaXMuZW5jcnlwdGVkID0gY3J5cHRvLmNmYi5lbmNyeXB0KFxuICAgICAgY3J5cHRvLmdldFByZWZpeFJhbmRvbSh0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtKSxcbiAgICAgIHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0sIGtleSwgcHJpdmF0ZV9rZXksIHRydWUpO1xuICB9XG59O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQgKFRhZyA5KVxuICogXG4gKiBSRkM0ODgwIDUuNzogVGhlIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgcGFja2V0IGNvbnRhaW5zIGRhdGEgZW5jcnlwdGVkXG4gKiB3aXRoIGEgc3ltbWV0cmljLWtleSBhbGdvcml0aG0uIFdoZW4gaXQgaGFzIGJlZW4gZGVjcnlwdGVkLCBpdCBjb250YWlucyBvdGhlclxuICogcGFja2V0cyAodXN1YWxseSBhIGxpdGVyYWwgZGF0YSBwYWNrZXQgb3IgY29tcHJlc3NlZCBkYXRhIHBhY2tldCwgYnV0IGluXG4gKiB0aGVvcnkgb3RoZXIgU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBwYWNrZXRzIG9yIHNlcXVlbmNlcyBvZiBwYWNrZXRzXG4gKiB0aGF0IGZvcm0gd2hvbGUgT3BlblBHUCBtZXNzYWdlcykuXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQoKSB7XG4gIHRoaXMuZW5jcnlwdGVkID0gbnVsbDtcbiAgLyoqIERlY3J5cHRlZCBwYWNrZXRzIGNvbnRhaW5lZCB3aXRoaW4uIFxuICAgKiBAdHlwZSB7b3BlbnBncF9wYWNrZXRsaXN0fSAqL1xuICB0aGlzLnBhY2tldHM7XG5cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB0aGlzLmVuY3J5cHRlZCA9IGJ5dGVzO1xuICB9XG5cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmVuY3J5cHRlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTeW1tZXRyaWNhbGx5IGRlY3J5cHQgdGhlIHBhY2tldCBkYXRhXG4gICAqIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHNlc3Npb25LZXlBbGdvcml0aG1cbiAgICogICAgICAgICAgICAgU3ltbWV0cmljIGtleSBhbGdvcml0aG0gdG8gdXNlIC8vIFNlZSBSRkM0ODgwIDkuMlxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5XG4gICAqICAgICAgICAgICAgIEtleSBhcyBzdHJpbmcgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBsZW5ndGggdG8gdGhlXG4gICAqICAgICAgICAgICAgYWxnb3JpdGhtXG4gICAqIEByZXR1cm4gVGhlIGRlY3J5cHRlZCBkYXRhO1xuICAgKi9cbiAgdGhpcy5kZWNyeXB0ID0gZnVuY3Rpb24oc2Vzc2lvbktleUFsZ29yaXRobSwga2V5KSB7XG4gICAgdmFyIGRlY3J5cHRlZCA9IGNyeXB0by5jZmIuZGVjcnlwdChcbiAgICAgIHNlc3Npb25LZXlBbGdvcml0aG0sIGtleSwgdGhpcy5lbmNyeXB0ZWQsIHRydWUpO1xuXG4gICAgdGhpcy5wYWNrZXRzLnJlYWQoZGVjcnlwdGVkKTtcbiAgfVxuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGFsZ28sIGtleSkge1xuICAgIHZhciBkYXRhID0gdGhpcy5wYWNrZXRzLndyaXRlKCk7XG5cbiAgICB0aGlzLmVuY3J5cHRlZCA9IGNyeXB0by5jZmIuZW5jcnlwdChcbiAgICAgIGNyeXB0by5nZXRQcmVmaXhSYW5kb20oYWxnbyksIGFsZ28sIGRhdGEsIGtleSwgdHJ1ZSk7XG4gIH1cbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF90cnVzdCgpIHtcblxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbi8qKiBcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgVXNlciBBdHRyaWJ1dGUgUGFja2V0IChUYWcgMTcpXG4gKiAgVGhlIFVzZXIgQXR0cmlidXRlIHBhY2tldCBpcyBhIHZhcmlhdGlvbiBvZiB0aGUgVXNlciBJRCBwYWNrZXQuICBJdFxuICogIGlzIGNhcGFibGUgb2Ygc3RvcmluZyBtb3JlIHR5cGVzIG9mIGRhdGEgdGhhbiB0aGUgVXNlciBJRCBwYWNrZXQsXG4gKiAgd2hpY2ggaXMgbGltaXRlZCB0byB0ZXh0LiAgTGlrZSB0aGUgVXNlciBJRCBwYWNrZXQsIGEgVXNlciBBdHRyaWJ1dGVcbiAqICBwYWNrZXQgbWF5IGJlIGNlcnRpZmllZCBieSB0aGUga2V5IG93bmVyIChcInNlbGYtc2lnbmVkXCIpIG9yIGFueSBvdGhlclxuICogIGtleSBvd25lciB3aG8gY2FyZXMgdG8gY2VydGlmeSBpdC4gIEV4Y2VwdCBhcyBub3RlZCwgYSBVc2VyIEF0dHJpYnV0ZVxuICogIHBhY2tldCBtYXkgYmUgdXNlZCBhbnl3aGVyZSB0aGF0IGEgVXNlciBJRCBwYWNrZXQgbWF5IGJlIHVzZWQuXG4gKlxuICogIFdoaWxlIFVzZXIgQXR0cmlidXRlIHBhY2tldHMgYXJlIG5vdCBhIHJlcXVpcmVkIHBhcnQgb2YgdGhlIE9wZW5QR1BcbiAqICBzdGFuZGFyZCwgaW1wbGVtZW50YXRpb25zIFNIT1VMRCBwcm92aWRlIGF0IGxlYXN0IGVub3VnaFxuICogIGNvbXBhdGliaWxpdHkgdG8gcHJvcGVybHkgaGFuZGxlIGEgY2VydGlmaWNhdGlvbiBzaWduYXR1cmUgb24gdGhlXG4gKiAgVXNlciBBdHRyaWJ1dGUgcGFja2V0LiAgQSBzaW1wbGUgd2F5IHRvIGRvIHRoaXMgaXMgYnkgdHJlYXRpbmcgdGhlXG4gKiAgVXNlciBBdHRyaWJ1dGUgcGFja2V0IGFzIGEgVXNlciBJRCBwYWNrZXQgd2l0aCBvcGFxdWUgY29udGVudHMsIGJ1dFxuICogIGFuIGltcGxlbWVudGF0aW9uIG1heSB1c2UgYW55IG1ldGhvZCBkZXNpcmVkLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF91c2VyX2F0dHJpYnV0ZSgpIHtcbiAgdGhpcy50YWcgPSAxNztcbiAgdGhpcy5hdHRyaWJ1dGVzID0gW107XG5cbiAgLyoqXG4gICAqIHBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgdXNlciBhdHRyaWJ1dGUgcGFja2V0ICh0YWcgMTcpLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgcGF5bG9hZCBvZiBhIHRhZyAxNyBwYWNrZXRcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBwb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBsZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBpbnB1dCBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBvYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIGkgPSAwO1xuICAgIHdoaWxlIChpIDwgYnl0ZXMubGVuZ3RoKSB7XG4gICAgICB2YXIgbGVuID0gb3BlbnBncF9wYWNrZXQucmVhZF9zaW1wbGVfbGVuZ3RoKGJ5dGVzKTtcblxuICAgICAgaSArPSBsZW4ub2Zmc2V0O1xuICAgICAgdGhpcy5hdHRyaWJ1dGVzLnB1c2goYnl0ZXMuc3Vic3RyKGksIGxlbi5sZW4pKTtcbiAgICAgIGkgKz0gbGVuLmxlbjtcbiAgICB9XG4gIH1cbn07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIFVzZXIgSUQgUGFja2V0IChUYWcgMTMpXG4gKiBBIFVzZXIgSUQgcGFja2V0IGNvbnNpc3RzIG9mIFVURi04IHRleHQgdGhhdCBpcyBpbnRlbmRlZCB0byByZXByZXNlbnRcbiAqIHRoZSBuYW1lIGFuZCBlbWFpbCBhZGRyZXNzIG9mIHRoZSBrZXkgaG9sZGVyLiAgQnkgY29udmVudGlvbiwgaXRcbiAqIGluY2x1ZGVzIGFuIFJGQyAyODIyIFtSRkMyODIyXSBtYWlsIG5hbWUtYWRkciwgYnV0IHRoZXJlIGFyZSBub1xuICogcmVzdHJpY3Rpb25zIG9uIGl0cyBjb250ZW50LiAgVGhlIHBhY2tldCBsZW5ndGggaW4gdGhlIGhlYWRlclxuICogc3BlY2lmaWVzIHRoZSBsZW5ndGggb2YgdGhlIFVzZXIgSUQuIFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF91c2VyaWQoKSB7XG4gIC8qKiBAdHlwZSB7U3RyaW5nfSBBIHN0cmluZyBjb250YWluaW5nIHRoZSB1c2VyIGlkLiBVc3VhbGx5IGluIHRoZSBmb3JtXG4gICAqIEpvaG4gRG9lIDxqb2huQGV4YW1wbGUuY29tPiBcbiAgICovXG4gIHRoaXMudXNlcmlkID0gJyc7XG5cblxuICAvKipcbiAgICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSB1c2VyIGlkIHBhY2tldCAodGFnIDEzKS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IHBheWxvYWQgb2YgYSB0YWcgMTMgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gcG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW4gbGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2YgaW5wdXQgXG4gICAqIGF0IHBvc2l0aW9uXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IG9iamVjdCByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB0aGlzLnVzZXJpZCA9IHV0aWwuZGVjb2RlX3V0ZjgoYnl0ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHVzZXIgaWQgcGFja2V0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB1c2VyX2lkIHRoZSB1c2VyIGlkIGFzIHN0cmluZyAoXCJKb2huIERvZSA8am9obi5kb2VAbWFpbC51c1wiKVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IHN0cmluZyByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB1dGlsLmVuY29kZV91dGY4KHRoaXMudXNlcmlkKTtcbiAgfVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHR5cGUga2V5IGlkIChSRkM0ODgwIDMuMylcbiAqICBBIEtleSBJRCBpcyBhbiBlaWdodC1vY3RldCBzY2FsYXIgdGhhdCBpZGVudGlmaWVzIGEga2V5LlxuICAgSW1wbGVtZW50YXRpb25zIFNIT1VMRCBOT1QgYXNzdW1lIHRoYXQgS2V5IElEcyBhcmUgdW5pcXVlLiAgVGhlXG4gICBzZWN0aW9uIFwiRW5oYW5jZWQgS2V5IEZvcm1hdHNcIiBiZWxvdyBkZXNjcmliZXMgaG93IEtleSBJRHMgYXJlXG4gICBmb3JtZWQuXG4gKi9cbmZ1bmN0aW9uIGtleWlkKCkge1xuXG4gIC8vIGluaXRpYWxpemUga2V5aWQgd2l0aCAweDAwMDAwMDAwMDAwMDAwMDBcbiAgdmFyIHN0ckFycmF5ID0gW107XG4gIHZhciB6ZXJvID0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA4OyBpKyspIHtcbiAgICBzdHJBcnJheVtpXSA9IHplcm87XG4gIH1cbiAgdGhpcy5ieXRlcyA9IHN0ckFycmF5LmpvaW4oJycpO1xuXG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgbWV0aG9kIGZvciBhIGtleSBpZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgSW5wdXQgdG8gcmVhZCB0aGUga2V5IGlkIGZyb20gXG4gICAqIEBwYXJhbSB7aW50ZWdlcn0gcG9zaXRpb24gUG9zaXRpb24gd2hlcmUgdG8gc3RhcnQgcmVhZGluZyB0aGUga2V5IFxuICAgKiBpZCBmcm9tIGlucHV0XG4gICAqIEByZXR1cm4ge29wZW5wZ3BfdHlwZV9rZXlpZH0gVGhpcyBvYmplY3RcbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdGhpcy5ieXRlcyA9IGJ5dGVzLnN1YnN0cigwLCA4KTtcbiAgfVxuXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5ieXRlcztcbiAgfVxuXG4gIHRoaXMudG9IZXggPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdXRpbC5oZXhzdHJkdW1wKHRoaXMuYnl0ZXMpO1xuICB9XG5cbiAgdGhpcy5lcXVhbHMgPSBmdW5jdGlvbihrZXlpZCkge1xuICAgIHJldHVybiB0aGlzLmJ5dGVzID09IGtleWlkLmJ5dGVzO1xuICB9XG59XG5cbmtleWlkLm1hcFRvSGV4ID0gZnVuY3Rpb24oa2V5aWQpIHtcbiAgcmV0dXJuIGtleWlkLnRvSGV4KCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ga2V5aWQ7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vLyBIaW50OiBXZSBob2xkIG91ciBNUElzIGFzIGFuIGFycmF5IG9mIG9jdGV0cyBpbiBiaWcgZW5kaWFuIGZvcm1hdCBwcmVjZWVkaW5nIGEgdHdvXG4vLyBvY3RldCBzY2FsYXI6IE1QSTogW2EsYixjLGQsZSxmXVxuLy8gLSBNUEkgc2l6ZTogKGEgPDwgOCkgfCBiIFxuLy8gLSBNUEkgPSBjIHwgZCA8PCA4IHwgZSA8PCAoKE1QSS5sZW5ndGggLTIpKjgpIHwgZiAoKE1QSS5sZW5ndGggLTIpKjgpXG5cbnZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnLi4vY3J5cHRvL3B1YmxpY19rZXkvanNibi5qcycpLFxuICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzY0ltcGxlbWVudGF0aW9uIG9mIHR5cGUgTVBJIChSRkM0ODgwIDMuMilcbiAqIE11bHRpcHJlY2lzaW9uIGludGVnZXJzIChhbHNvIGNhbGxlZCBNUElzKSBhcmUgdW5zaWduZWQgaW50ZWdlcnMgdXNlZFxuICogdG8gaG9sZCBsYXJnZSBpbnRlZ2VycyBzdWNoIGFzIHRoZSBvbmVzIHVzZWQgaW4gY3J5cHRvZ3JhcGhpY1xuICogY2FsY3VsYXRpb25zLlxuICogQW4gTVBJIGNvbnNpc3RzIG9mIHR3byBwaWVjZXM6IGEgdHdvLW9jdGV0IHNjYWxhciB0aGF0IGlzIHRoZSBsZW5ndGhcbiAqIG9mIHRoZSBNUEkgaW4gYml0cyBmb2xsb3dlZCBieSBhIHN0cmluZyBvZiBvY3RldHMgdGhhdCBjb250YWluIHRoZVxuICogYWN0dWFsIGludGVnZXIuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gbXBpKCkge1xuICAvKiogQW4gaW1wbGVtZW50YXRpb24gZGVwZW5kZW50IGludGVnZXIgKi9cbiAgdGhpcy5kYXRhID0gbnVsbDtcblxuICAvKipcbiAgICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBtcGkgKFJGQyA0ODgwIDMuMikuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIG1waSBkYXRhXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gUG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBcbiAgICogc3RyaW5nXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mIFxuICAgKiBpbnB1dCBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3R5cGVfbXBpfSBPYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIGJpdHMgPSAoYnl0ZXNbMF0uY2hhckNvZGVBdCgpIDw8IDgpIHwgYnl0ZXNbMV0uY2hhckNvZGVBdCgpO1xuXG4gICAgLy8gQWRkaXRpb25hbCBydWxlczpcbiAgICAvL1xuICAgIC8vICAgIFRoZSBzaXplIG9mIGFuIE1QSSBpcyAoKE1QSS5sZW5ndGggKyA3KSAvIDgpICsgMiBvY3RldHMuXG4gICAgLy9cbiAgICAvLyAgICBUaGUgbGVuZ3RoIGZpZWxkIG9mIGFuIE1QSSBkZXNjcmliZXMgdGhlIGxlbmd0aCBzdGFydGluZyBmcm9tIGl0c1xuICAgIC8vXHQgIG1vc3Qgc2lnbmlmaWNhbnQgbm9uLXplcm8gYml0LiAgVGh1cywgdGhlIE1QSSBbMDAgMDIgMDFdIGlzIG5vdFxuICAgIC8vICAgIGZvcm1lZCBjb3JyZWN0bHkuICBJdCBzaG91bGQgYmUgWzAwIDAxIDAxXS5cblxuICAgIC8vIFRPRE86IFZlcmlmaWNhdGlvbiBvZiB0aGlzIHNpemUgbWV0aG9kISBUaGlzIHNpemUgY2FsY3VsYXRpb24gYXNcbiAgICAvLyBcdFx0IHNwZWNpZmllZCBhYm92ZSBpcyBub3QgYXBwbGljYWJsZSBpbiBKYXZhU2NyaXB0XG4gICAgdmFyIGJ5dGVsZW4gPSBNYXRoLmNlaWwoYml0cyAvIDgpO1xuXG4gICAgdmFyIHJhdyA9IGJ5dGVzLnN1YnN0cigyLCBieXRlbGVuKTtcbiAgICB0aGlzLmZyb21CeXRlcyhyYXcpO1xuXG4gICAgcmV0dXJuIDIgKyBieXRlbGVuO1xuICB9XG5cbiAgdGhpcy5mcm9tQnl0ZXMgPSBmdW5jdGlvbihieXRlcykge1xuICAgIHRoaXMuZGF0YSA9IG5ldyBCaWdJbnRlZ2VyKHV0aWwuaGV4c3RyZHVtcChieXRlcyksIDE2KTtcbiAgfVxuXG4gIHRoaXMudG9CeXRlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLndyaXRlKCkuc3Vic3RyKDIpO1xuICB9XG5cbiAgdGhpcy5ieXRlTGVuZ3RoID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudG9CeXRlcygpLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyB0aGUgbXBpIG9iamVjdCB0byBhIHN0cmluZyBhcyBzcGVjaWZpZWQgaW4gUkZDNDg4MCAzLjJcbiAgICogQHJldHVybiB7U3RyaW5nfSBtcGkgQnl0ZSByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmRhdGEudG9NUEkoKTtcbiAgfVxuXG4gIHRoaXMudG9CaWdJbnRlZ2VyID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YS5jbG9uZSgpO1xuICB9XG5cbiAgdGhpcy5mcm9tQmlnSW50ZWdlciA9IGZ1bmN0aW9uKGJuKSB7XG4gICAgdGhpcy5kYXRhID0gYm4uY2xvbmUoKTtcbiAgfVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgY3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBTdHJpbmctdG8ta2V5IHNwZWNpZmllciAoUkZDNDg4MCAzLjcpXG4gKiBTdHJpbmctdG8ta2V5IChTMkspIHNwZWNpZmllcnMgYXJlIHVzZWQgdG8gY29udmVydCBwYXNzcGhyYXNlIHN0cmluZ3NcbiAgIGludG8gc3ltbWV0cmljLWtleSBlbmNyeXB0aW9uL2RlY3J5cHRpb24ga2V5cy4gIFRoZXkgYXJlIHVzZWQgaW4gdHdvXG4gICBwbGFjZXMsIGN1cnJlbnRseTogdG8gZW5jcnlwdCB0aGUgc2VjcmV0IHBhcnQgb2YgcHJpdmF0ZSBrZXlzIGluIHRoZVxuICAgcHJpdmF0ZSBrZXlyaW5nLCBhbmQgdG8gY29udmVydCBwYXNzcGhyYXNlcyB0byBlbmNyeXB0aW9uIGtleXMgZm9yXG4gICBzeW1tZXRyaWNhbGx5IGVuY3J5cHRlZCBtZXNzYWdlcy5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzMmsoKSB7XG4gIC8qKiBAdHlwZSB7b3BlbnBncC5oYXNofSAqL1xuICB0aGlzLmFsZ29yaXRobSA9ICdzaGEyNTYnO1xuICAvKiogQHR5cGUge29wZW5wZ3BfdHlwZV9zMmsudHlwZX0gKi9cbiAgdGhpcy50eXBlID0gJ2l0ZXJhdGVkJztcbiAgdGhpcy5jID0gOTY7XG4gIC8qKiBAdHlwZSB7b3BlbnBncF9ieXRlYXJyYXl9IFxuICAgKiBFaWdodCBieXRlcyBvZiBzYWx0LiAqL1xuICB0aGlzLnNhbHQgPSBjcnlwdG8ucmFuZG9tLmdldFJhbmRvbUJ5dGVzKDgpO1xuXG5cbiAgLy8gRXhwb25lbiBiaWFzLCBkZWZpbmVkIGluIFJGQzQ4ODBcbiAgdmFyIGV4cGJpYXMgPSA2O1xuXG4gIHRoaXMuZ2V0X2NvdW50ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICgxNiArICh0aGlzLmMgJiAxNSkpIDw8ICgodGhpcy5jID4+IDQpICsgZXhwYmlhcyk7XG4gIH1cblxuICAvKipcbiAgICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBzdHJpbmctdG8ta2V5IHNwZWNpZmllciAoUkZDIDQ4ODAgMy43KS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2Ygc3RyaW5nLXRvLWtleSBzcGVjaWZpZXJcbiAgICogQHJldHVybiB7SW50ZWdlcn0gQWN0dWFsIGxlbmd0aCBvZiB0aGUgb2JqZWN0XG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIHZhciBpID0gMDtcbiAgICB0aGlzLnR5cGUgPSBlbnVtcy5yZWFkKGVudW1zLnMyaywgYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCkpO1xuICAgIHRoaXMuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5oYXNoLCBieXRlc1tpKytdLmNoYXJDb2RlQXQoKSk7XG5cbiAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgY2FzZSAnc2ltcGxlJzpcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3NhbHRlZCc6XG4gICAgICAgIHRoaXMuc2FsdCA9IGJ5dGVzLnN1YnN0cihpLCA4KTtcbiAgICAgICAgaSArPSA4O1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnaXRlcmF0ZWQnOlxuICAgICAgICB0aGlzLnNhbHQgPSBieXRlcy5zdWJzdHIoaSwgOCk7XG4gICAgICAgIGkgKz0gODtcblxuICAgICAgICAvLyBPY3RldCAxMDogY291bnQsIGEgb25lLW9jdGV0LCBjb2RlZCB2YWx1ZVxuICAgICAgICB0aGlzLmMgPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2dudSc6XG4gICAgICAgIGlmIChieXRlcy5zdWJzdHIoaSwgMykgPT0gXCJHTlVcIikge1xuICAgICAgICAgIGkgKz0gMzsgLy8gR05VXG4gICAgICAgICAgdmFyIGdudUV4dFR5cGUgPSAxMDAwICsgYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgICAgaWYgKGdudUV4dFR5cGUgPT0gMTAwMSkge1xuICAgICAgICAgICAgdGhpcy50eXBlID0gZ251RXh0VHlwZTtcbiAgICAgICAgICAgIC8vIEdudVBHIGV4dGVuc2lvbiBtb2RlIDEwMDEgLS0gZG9uJ3Qgd3JpdGUgc2VjcmV0IGtleSBhdCBhbGxcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBzMmsgZ251IHByb3RlY3Rpb24gbW9kZS5cIik7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gczJrIHR5cGUuXCIpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHMyayB0eXBlLlwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIGk7XG4gIH1cblxuXG4gIC8qKlxuICAgKiB3cml0ZXMgYW4gczJrIGhhc2ggYmFzZWQgb24gdGhlIGlucHV0cy5cbiAgICogQHJldHVybiB7U3RyaW5nfSBQcm9kdWNlZCBrZXkgb2YgaGFzaEFsZ29yaXRobSBoYXNoIGxlbmd0aFxuICAgKi9cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBieXRlcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoZW51bXMud3JpdGUoZW51bXMuczJrLCB0aGlzLnR5cGUpKTtcbiAgICBieXRlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLmhhc2gsIHRoaXMuYWxnb3JpdGhtKSk7XG5cbiAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgY2FzZSAnc2ltcGxlJzpcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzYWx0ZWQnOlxuICAgICAgICBieXRlcyArPSB0aGlzLnNhbHQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaXRlcmF0ZWQnOlxuICAgICAgICBieXRlcyArPSB0aGlzLnNhbHQ7XG4gICAgICAgIGJ5dGVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy5jKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9kdWNlcyBhIGtleSB1c2luZyB0aGUgc3BlY2lmaWVkIHBhc3NwaHJhc2UgYW5kIHRoZSBkZWZpbmVkIFxuICAgKiBoYXNoQWxnb3JpdGhtIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGFzc3BocmFzZSBQYXNzcGhyYXNlIGNvbnRhaW5pbmcgdXNlciBpbnB1dFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFByb2R1Y2VkIGtleSB3aXRoIGEgbGVuZ3RoIGNvcnJlc3BvbmRpbmcgdG8gXG4gICAqIGhhc2hBbGdvcml0aG0gaGFzaCBsZW5ndGhcbiAgICovXG4gIHRoaXMucHJvZHVjZV9rZXkgPSBmdW5jdGlvbihwYXNzcGhyYXNlLCBudW1CeXRlcykge1xuICAgIHBhc3NwaHJhc2UgPSB1dGlsLmVuY29kZV91dGY4KHBhc3NwaHJhc2UpO1xuXG4gICAgZnVuY3Rpb24gcm91bmQocHJlZml4LCBzMmspIHtcbiAgICAgIHZhciBhbGdvcml0aG0gPSBlbnVtcy53cml0ZShlbnVtcy5oYXNoLCBzMmsuYWxnb3JpdGhtKTtcblxuICAgICAgc3dpdGNoIChzMmsudHlwZSkge1xuICAgICAgICBjYXNlICdzaW1wbGUnOlxuICAgICAgICAgIHJldHVybiBjcnlwdG8uaGFzaC5kaWdlc3QoYWxnb3JpdGhtLCBwcmVmaXggKyBwYXNzcGhyYXNlKTtcblxuICAgICAgICBjYXNlICdzYWx0ZWQnOlxuICAgICAgICAgIHJldHVybiBjcnlwdG8uaGFzaC5kaWdlc3QoYWxnb3JpdGhtLFxuICAgICAgICAgICAgcHJlZml4ICsgczJrLnNhbHQgKyBwYXNzcGhyYXNlKTtcblxuICAgICAgICBjYXNlICdpdGVyYXRlZCc6XG4gICAgICAgICAgdmFyIGlzcCA9IFtdLFxuICAgICAgICAgICAgY291bnQgPSBzMmsuZ2V0X2NvdW50KCk7XG4gICAgICAgICAgZGF0YSA9IHMyay5zYWx0ICsgcGFzc3BocmFzZTtcblxuICAgICAgICAgIHdoaWxlIChpc3AubGVuZ3RoICogZGF0YS5sZW5ndGggPCBjb3VudClcbiAgICAgICAgICAgIGlzcC5wdXNoKGRhdGEpO1xuXG4gICAgICAgICAgaXNwID0gaXNwLmpvaW4oJycpO1xuXG4gICAgICAgICAgaWYgKGlzcC5sZW5ndGggPiBjb3VudClcbiAgICAgICAgICAgIGlzcCA9IGlzcC5zdWJzdHIoMCwgY291bnQpO1xuXG4gICAgICAgICAgcmV0dXJuIGNyeXB0by5oYXNoLmRpZ2VzdChhbGdvcml0aG0sIHByZWZpeCArIGlzcCk7XG4gICAgICB9O1xuICAgIH1cblxuICAgIHZhciByZXN1bHQgPSAnJyxcbiAgICAgIHByZWZpeCA9ICcnO1xuXG4gICAgd2hpbGUgKHJlc3VsdC5sZW5ndGggPD0gbnVtQnl0ZXMpIHtcbiAgICAgIHJlc3VsdCArPSByb3VuZChwcmVmaXgsIHRoaXMpO1xuICAgICAgcHJlZml4ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdC5zdWJzdHIoMCwgbnVtQnl0ZXMpO1xuICB9XG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgVXRpbCA9IGZ1bmN0aW9uKCkge1xuXG4gIHRoaXMucmVhZE51bWJlciA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIG4gPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbiA8PD0gODtcbiAgICAgIG4gKz0gYnl0ZXNbaV0uY2hhckNvZGVBdCgpO1xuICAgIH1cblxuICAgIHJldHVybiBuO1xuICB9O1xuXG4gIHRoaXMud3JpdGVOdW1iZXIgPSBmdW5jdGlvbihuLCBieXRlcykge1xuICAgIHZhciBiID0gJyc7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlczsgaSsrKSB7XG4gICAgICBiICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKG4gPj4gKDggKiAoYnl0ZXMgLSBpIC0gMSkpKSAmIDB4RkYpO1xuICAgIH1cblxuICAgIHJldHVybiBiO1xuICB9O1xuXG5cblxuICB0aGlzLnJlYWREYXRlID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgbiA9IHRoaXMucmVhZE51bWJlcihieXRlcyk7XG4gICAgdmFyIGQgPSBuZXcgRGF0ZSgpO1xuICAgIGQuc2V0VGltZShuICogMTAwMCk7XG4gICAgcmV0dXJuIGQ7XG4gIH07XG5cbiAgdGhpcy53cml0ZURhdGUgPSBmdW5jdGlvbih0aW1lKSB7XG4gICAgdmFyIG51bWVyaWMgPSBNYXRoLnJvdW5kKHRpbWUuZ2V0VGltZSgpIC8gMTAwMCk7XG5cbiAgICByZXR1cm4gdGhpcy53cml0ZU51bWJlcihudW1lcmljLCA0KTtcbiAgfTtcblxuICB0aGlzLmVtYWlsUmVnRXggPSAvXlsrYS16QS1aMC05Xy4tXStAKFthLXpBLVowLTktXStcXC4pK1thLXpBLVowLTldezIsNn0kLztcblxuICB0aGlzLmRlYnVnID0gZmFsc2U7XG5cbiAgdGhpcy5oZXhkdW1wID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgdmFyIHIgPSBbXTtcbiAgICB2YXIgZSA9IHN0ci5sZW5ndGg7XG4gICAgdmFyIGMgPSAwO1xuICAgIHZhciBoO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoYyA8IGUpIHtcbiAgICAgIGggPSBzdHIuY2hhckNvZGVBdChjKyspLnRvU3RyaW5nKDE2KTtcbiAgICAgIHdoaWxlIChoLmxlbmd0aCA8IDIpIGggPSBcIjBcIiArIGg7XG4gICAgICByLnB1c2goXCIgXCIgKyBoKTtcbiAgICAgIGkrKztcbiAgICAgIGlmIChpICUgMzIgPT0gMClcbiAgICAgICAgci5wdXNoKFwiXFxuICAgICAgICAgICBcIik7XG4gICAgfVxuICAgIHJldHVybiByLmpvaW4oJycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgaGV4c3RyaW5nIGZyb20gYSBiaW5hcnlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gY29udmVydFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFN0cmluZyBjb250YWluaW5nIHRoZSBoZXhhZGVjaW1hbCB2YWx1ZXNcbiAgICovXG4gIHRoaXMuaGV4c3RyZHVtcCA9IGZ1bmN0aW9uKHN0cikge1xuICAgIGlmIChzdHIgPT0gbnVsbClcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIHZhciByID0gW107XG4gICAgdmFyIGUgPSBzdHIubGVuZ3RoO1xuICAgIHZhciBjID0gMDtcbiAgICB2YXIgaDtcbiAgICB3aGlsZSAoYyA8IGUpIHtcbiAgICAgIGggPSBzdHJbYysrXS5jaGFyQ29kZUF0KCkudG9TdHJpbmcoMTYpO1xuICAgICAgd2hpbGUgKGgubGVuZ3RoIDwgMikgaCA9IFwiMFwiICsgaDtcbiAgICAgIHIucHVzaChcIlwiICsgaCk7XG4gICAgfVxuICAgIHJldHVybiByLmpvaW4oJycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYmluYXJ5IHN0cmluZyBmcm9tIGEgaGV4IGVuY29kZWQgc3RyaW5nXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgSGV4IHN0cmluZyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gU3RyaW5nIGNvbnRhaW5pbmcgdGhlIGJpbmFyeSB2YWx1ZXNcbiAgICovXG4gIHRoaXMuaGV4MmJpbiA9IGZ1bmN0aW9uKGhleCkge1xuICAgIHZhciBzdHIgPSAnJztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhleC5sZW5ndGg7IGkgKz0gMilcbiAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHBhcnNlSW50KGhleC5zdWJzdHIoaSwgMiksIDE2KSk7XG4gICAgcmV0dXJuIHN0cjtcbiAgfTtcblxuICAvKipcbiAgICogQ3JlYXRpbmcgYSBoZXggc3RyaW5nIGZyb20gYW4gYmluYXJ5IGFycmF5IG9mIGludGVnZXJzICgwLi4yNTUpXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgQXJyYXkgb2YgYnl0ZXMgdG8gY29udmVydFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEhleGFkZWNpbWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBhcnJheVxuICAgKi9cbiAgdGhpcy5oZXhpZHVtcCA9IGZ1bmN0aW9uKHN0cikge1xuICAgIHZhciByID0gW107XG4gICAgdmFyIGUgPSBzdHIubGVuZ3RoO1xuICAgIHZhciBjID0gMDtcbiAgICB2YXIgaDtcbiAgICB3aGlsZSAoYyA8IGUpIHtcbiAgICAgIGggPSBzdHJbYysrXS50b1N0cmluZygxNik7XG4gICAgICB3aGlsZSAoaC5sZW5ndGggPCAyKSBoID0gXCIwXCIgKyBoO1xuICAgICAgci5wdXNoKFwiXCIgKyBoKTtcbiAgICB9XG4gICAgcmV0dXJuIHIuam9pbignJyk7XG4gIH07XG5cblxuICAvKipcbiAgICogQ29udmVydCBhIG5hdGl2ZSBqYXZhc2NyaXB0IHN0cmluZyB0byBhIHN0cmluZyBvZiB1dGY4IGJ5dGVzXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gQSB2YWxpZCBzcXVlbmNlIG9mIHV0ZjggYnl0ZXNcbiAgICovXG4gIHRoaXMuZW5jb2RlX3V0ZjggPSBmdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gdW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgc3RyaW5nIG9mIHV0ZjggYnl0ZXMgdG8gYSBuYXRpdmUgamF2YXNjcmlwdCBzdHJpbmdcbiAgICogQHBhcmFtIHtTdHJpbmd9IHV0ZjggQSB2YWxpZCBzcXVlbmNlIG9mIHV0ZjggYnl0ZXNcbiAgICogQHJldHVybiB7U3RyaW5nfSBBIG5hdGl2ZSBqYXZhc2NyaXB0IHN0cmluZ1xuICAgKi9cbiAgdGhpcy5kZWNvZGVfdXRmOCA9IGZ1bmN0aW9uKHV0ZjgpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUodXRmOCkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiB1dGY4O1xuICAgIH1cbiAgfTtcblxuICB2YXIgc3RyMmJpbiA9IGZ1bmN0aW9uKHN0ciwgcmVzdWx0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFtpXSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgdmFyIGJpbjJzdHIgPSBmdW5jdGlvbihiaW4pIHtcbiAgICB2YXIgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbi5sZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShiaW5baV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0LmpvaW4oJycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGFuIGFycmF5IG9mIGludGVnZXJzKDAuMjU1KVxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge0ludGVnZXJbXX0gQW4gYXJyYXkgb2YgKGJpbmFyeSkgaW50ZWdlcnNcbiAgICovXG4gIHRoaXMuc3RyMmJpbiA9IGZ1bmN0aW9uKHN0cikge1xuICAgIHJldHVybiBzdHIyYmluKHN0ciwgbmV3IEFycmF5KHN0ci5sZW5ndGgpKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGludGVnZXJzKDAuMjU1KSB0byBhIHN0cmluZyBcbiAgICogQHBhcmFtIHtJbnRlZ2VyW119IGJpbiBBbiBhcnJheSBvZiAoYmluYXJ5KSBpbnRlZ2VycyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgYXJyYXlcbiAgICovXG4gIHRoaXMuYmluMnN0ciA9IGJpbjJzdHI7XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgYSBzdHJpbmcgdG8gYSBVaW50OEFycmF5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIGNvbnZlcnRcbiAgICogQHJldHVybiB7VWludDhBcnJheX0gVGhlIGFycmF5IG9mIChiaW5hcnkpIGludGVnZXJzXG4gICAqL1xuICB0aGlzLnN0cjJVaW50OEFycmF5ID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgcmV0dXJuIHN0cjJiaW4oc3RyLCBuZXcgVWludDhBcnJheShuZXcgQXJyYXlCdWZmZXIoc3RyLmxlbmd0aCkpKTtcbiAgfTtcblxuICAvKipcbiAgICogQ29udmVydCBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmcuIFRoaXMgY3VycmVudGx5IGZ1bmN0aW9ucyBcbiAgICogdGhlIHNhbWUgYXMgYmluMnN0ci4gXG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0gYmluIEFuIGFycmF5IG9mIChiaW5hcnkpIGludGVnZXJzIHRvIGNvbnZlcnRcbiAgICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGFycmF5XG4gICAqL1xuICB0aGlzLlVpbnQ4QXJyYXkyc3RyID0gYmluMnN0cjtcblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyBhIDE2Yml0IHN1bSBvZiBhIHN0cmluZyBieSBhZGRpbmcgZWFjaCBjaGFyYWN0ZXIgXG4gICAqIGNvZGVzIG1vZHVsdXMgNjU1MzVcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRleHQgU3RyaW5nIHRvIGNyZWF0ZSBhIHN1bSBvZlxuICAgKiBAcmV0dXJuIHtJbnRlZ2VyfSBBbiBpbnRlZ2VyIGNvbnRhaW5pbmcgdGhlIHN1bSBvZiBhbGwgY2hhcmFjdGVyIFxuICAgKiBjb2RlcyAlIDY1NTM1XG4gICAqL1xuICB0aGlzLmNhbGNfY2hlY2tzdW0gPSBmdW5jdGlvbih0ZXh0KSB7XG4gICAgdmFyIGNoZWNrc3VtID0ge1xuICAgICAgczogMCxcbiAgICAgIGFkZDogZnVuY3Rpb24oc2FkZCkge1xuICAgICAgICB0aGlzLnMgPSAodGhpcy5zICsgc2FkZCkgJSA2NTUzNjtcbiAgICAgIH1cbiAgICB9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgY2hlY2tzdW0uYWRkKHRleHQuY2hhckNvZGVBdChpKSk7XG4gICAgfVxuICAgIHJldHVybiBjaGVja3N1bS5zO1xuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYSBkZWJ1ZyBtZXNzYWdlLiBEZWJ1ZyBcbiAgICogbWVzc2FnZXMgYXJlIG9ubHkgcHJpbnRlZCBpZlxuICAgKiBvcGVucGdwLmNvbmZpZy5kZWJ1ZyBpcyBzZXQgdG8gdHJ1ZS4gVGhlIGNhbGxpbmdcbiAgICogSmF2YXNjcmlwdCBjb250ZXh0IE1VU1QgZGVmaW5lXG4gICAqIGEgXCJzaG93TWVzc2FnZXModGV4dClcIiBmdW5jdGlvbi4gTGluZSBmZWVkcyAoJ1xcbicpXG4gICAqIGFyZSBhdXRvbWF0aWNhbGx5IGNvbnZlcnRlZCB0byBIVE1MIGxpbmUgZmVlZHMgJzxici8+J1xuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyBvZiB0aGUgZGVidWcgbWVzc2FnZVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEFuIEhUTUwgdHQgZW50aXR5IGNvbnRhaW5pbmcgYSBwYXJhZ3JhcGggd2l0aCBhIFxuICAgKiBzdHlsZSBhdHRyaWJ1dGUgd2hlcmUgdGhlIGRlYnVnIG1lc3NhZ2UgaXMgSFRNTGVuY29kZWQgaW4uIFxuICAgKi9cbiAgdGhpcy5wcmludF9kZWJ1ZyA9IGZ1bmN0aW9uKHN0cikge1xuICAgIGlmICh0aGlzLmRlYnVnKSB7XG4gICAgICBjb25zb2xlLmxvZyhzdHIpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIHRvIHByaW50IGEgZGVidWcgbWVzc2FnZS4gRGVidWcgXG4gICAqIG1lc3NhZ2VzIGFyZSBvbmx5IHByaW50ZWQgaWZcbiAgICogb3BlbnBncC5jb25maWcuZGVidWcgaXMgc2V0IHRvIHRydWUuIFRoZSBjYWxsaW5nXG4gICAqIEphdmFzY3JpcHQgY29udGV4dCBNVVNUIGRlZmluZVxuICAgKiBhIFwic2hvd01lc3NhZ2VzKHRleHQpXCIgZnVuY3Rpb24uIExpbmUgZmVlZHMgKCdcXG4nKVxuICAgKiBhcmUgYXV0b21hdGljYWxseSBjb252ZXJ0ZWQgdG8gSFRNTCBsaW5lIGZlZWRzICc8YnIvPidcbiAgICogRGlmZmVyZW50IHRoYW4gcHJpbnRfZGVidWcgYmVjYXVzZSB3aWxsIGNhbGwgaGV4c3RyZHVtcCBpZmYgbmVjZXNzYXJ5LlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyBvZiB0aGUgZGVidWcgbWVzc2FnZVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEFuIEhUTUwgdHQgZW50aXR5IGNvbnRhaW5pbmcgYSBwYXJhZ3JhcGggd2l0aCBhIFxuICAgKiBzdHlsZSBhdHRyaWJ1dGUgd2hlcmUgdGhlIGRlYnVnIG1lc3NhZ2UgaXMgSFRNTGVuY29kZWQgaW4uIFxuICAgKi9cbiAgdGhpcy5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcCA9IGZ1bmN0aW9uKHN0ciwgc3RyVG9IZXgpIHtcbiAgICBpZiAodGhpcy5kZWJ1Zykge1xuICAgICAgc3RyID0gc3RyICsgdGhpcy5oZXhzdHJkdW1wKHN0clRvSGV4KTtcbiAgICAgIGNvbnNvbGUubG9nKHN0cik7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYW4gZXJyb3IgbWVzc2FnZS4gXG4gICAqIFRoZSBjYWxsaW5nIEphdmFzY3JpcHQgY29udGV4dCBNVVNUIGRlZmluZVxuICAgKiBhIFwic2hvd01lc3NhZ2VzKHRleHQpXCIgZnVuY3Rpb24uIExpbmUgZmVlZHMgKCdcXG4nKVxuICAgKiBhcmUgYXV0b21hdGljYWxseSBjb252ZXJ0ZWQgdG8gSFRNTCBsaW5lIGZlZWRzICc8YnIvPidcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgb2YgdGhlIGVycm9yIG1lc3NhZ2VcbiAgICogQHJldHVybiB7U3RyaW5nfSBBIEhUTUwgcGFyYWdyYXBoIGVudGl0eSB3aXRoIGEgc3R5bGUgYXR0cmlidXRlIFxuICAgKiBjb250YWluaW5nIHRoZSBIVE1MIGVuY29kZWQgZXJyb3IgbWVzc2FnZVxuICAgKi9cbiAgdGhpcy5wcmludF9lcnJvciA9IGZ1bmN0aW9uKHN0cikge1xuICAgIGlmICh0aGlzLmRlYnVnKVxuICAgICAgdGhyb3cgc3RyO1xuICAgIGNvbnNvbGUubG9nKHN0cik7XG4gIH07XG5cbiAgLyoqXG4gICAqIEhlbHBlciBmdW5jdGlvbiB0byBwcmludCBhbiBpbmZvIG1lc3NhZ2UuIFxuICAgKiBUaGUgY2FsbGluZyBKYXZhc2NyaXB0IGNvbnRleHQgTVVTVCBkZWZpbmVcbiAgICogYSBcInNob3dNZXNzYWdlcyh0ZXh0KVwiIGZ1bmN0aW9uLiBMaW5lIGZlZWRzICgnXFxuJylcbiAgICogYXJlIGF1dG9tYXRpY2FsbHkgY29udmVydGVkIHRvIEhUTUwgbGluZSBmZWVkcyAnPGJyLz4nLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyBvZiB0aGUgaW5mbyBtZXNzYWdlXG4gICAqIEByZXR1cm4ge1N0cmluZ30gQSBIVE1MIHBhcmFncmFwaCBlbnRpdHkgd2l0aCBhIHN0eWxlIGF0dHJpYnV0ZSBcbiAgICogY29udGFpbmluZyB0aGUgSFRNTCBlbmNvZGVkIGluZm8gbWVzc2FnZVxuICAgKi9cbiAgdGhpcy5wcmludF9pbmZvID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgaWYgKHRoaXMuZGVidWcpXG4gICAgICBjb25zb2xlLmxvZyhzdHIpO1xuICB9O1xuXG4gIHRoaXMucHJpbnRfd2FybmluZyA9IGZ1bmN0aW9uKHN0cikge1xuICAgIGNvbnNvbGUubG9nKHN0cik7XG4gIH07XG5cbiAgdGhpcy5nZXRMZWZ0TkJpdHMgPSBmdW5jdGlvbihzdHJpbmcsIGJpdGNvdW50KSB7XG4gICAgdmFyIHJlc3QgPSBiaXRjb3VudCAlIDg7XG4gICAgaWYgKHJlc3QgPT0gMClcbiAgICAgIHJldHVybiBzdHJpbmcuc3Vic3RyaW5nKDAsIGJpdGNvdW50IC8gOCk7XG4gICAgdmFyIGJ5dGVzID0gKGJpdGNvdW50IC0gcmVzdCkgLyA4ICsgMTtcbiAgICB2YXIgcmVzdWx0ID0gc3RyaW5nLnN1YnN0cmluZygwLCBieXRlcyk7XG4gICAgcmV0dXJuIHRoaXMuc2hpZnRSaWdodChyZXN1bHQsIDggLSByZXN0KTsgLy8gK1N0cmluZy5mcm9tQ2hhckNvZGUoc3RyaW5nLmNoYXJDb2RlQXQoYnl0ZXMgLTEpIDw8ICg4LXJlc3QpICYgMHhGRik7XG4gIH07XG5cbiAgLyoqXG4gICAqIFNoaWZ0aW5nIGEgc3RyaW5nIHRvIG4gYml0cyByaWdodFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgVGhlIHN0cmluZyB0byBzaGlmdFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGJpdGNvdW50IEFtb3VudCBvZiBiaXRzIHRvIHNoaWZ0IChNVVNUIGJlIHNtYWxsZXIgXG4gICAqIHRoYW4gOSlcbiAgICogQHJldHVybiB7U3RyaW5nfSBSZXN1bHRpbmcgc3RyaW5nLiBcbiAgICovXG4gIHRoaXMuc2hpZnRSaWdodCA9IGZ1bmN0aW9uKHZhbHVlLCBiaXRjb3VudCkge1xuICAgIHZhciB0ZW1wID0gdXRpbC5zdHIyYmluKHZhbHVlKTtcbiAgICBpZiAoYml0Y291bnQgJSA4ICE9IDApIHtcbiAgICAgIGZvciAodmFyIGkgPSB0ZW1wLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHRlbXBbaV0gPj49IGJpdGNvdW50ICUgODtcbiAgICAgICAgaWYgKGkgPiAwKVxuICAgICAgICAgIHRlbXBbaV0gfD0gKHRlbXBbaSAtIDFdIDw8ICg4IC0gKGJpdGNvdW50ICUgOCkpKSAmIDB4RkY7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHV0aWwuYmluMnN0cih0ZW1wKTtcbiAgfTtcblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBhbGdvcml0aG0gdHlwZSBhcyBzdHJpbmdcbiAgICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBtZXNzYWdlIHR5cGVcbiAgICovXG4gIHRoaXMuZ2V0X2hhc2hBbGdvcml0aG1TdHJpbmcgPSBmdW5jdGlvbihhbGdvKSB7XG4gICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIHJldHVybiBcIk1ENVwiO1xuICAgICAgY2FzZSAyOlxuICAgICAgICByZXR1cm4gXCJTSEExXCI7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiBcIlJJUEVNRDE2MFwiO1xuICAgICAgY2FzZSA4OlxuICAgICAgICByZXR1cm4gXCJTSEEyNTZcIjtcbiAgICAgIGNhc2UgOTpcbiAgICAgICAgcmV0dXJuIFwiU0hBMzg0XCI7XG4gICAgICBjYXNlIDEwOlxuICAgICAgICByZXR1cm4gXCJTSEE1MTJcIjtcbiAgICAgIGNhc2UgMTE6XG4gICAgICAgIHJldHVybiBcIlNIQTIyNFwiO1xuICAgIH1cbiAgICByZXR1cm4gXCJ1bmtub3duXCI7XG4gIH07XG5cbn07XG5cbi8qKlxuICogYW4gaW5zdGFuY2UgdGhhdCBzaG91bGQgYmUgdXNlZC4gXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gbmV3IFV0aWwoKTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vLi4vdW5pdC5qcycpO1xuXG51bml0LnJlZ2lzdGVyKFwiQUVTIFJpam5kYWVsIGNpcGhlciB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gZWNiX3RibC50eHRcIiwgZnVuY3Rpb24oKSB7XG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyk7XG4gIHZhciB1dGlsID0gb3BlbnBncC51dGlsO1xuXG4gIHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblxuICBmdW5jdGlvbiB0ZXN0X2FlcyhpbnB1dCwga2V5LCBvdXRwdXQpIHtcbiAgICB2YXIgYWVzID0gbmV3IG9wZW5wZ3AuY3J5cHRvLmNpcGhlci5hZXMxMjgodXRpbC5iaW4yc3RyKGtleSkpO1xuXG4gICAgdmFyIHJlc3VsdCA9IHV0aWwuYmluMnN0cihhZXMuZW5jcnlwdChpbnB1dCkpO1xuXG4gICAgcmV0dXJuIHV0aWwuaGV4c3RyZHVtcChyZXN1bHQpID09IHV0aWwuaGV4c3RyZHVtcCh1dGlsLmJpbjJzdHIob3V0cHV0KSk7XG4gIH07XG5cbiAgdmFyIHRlc3R2ZWN0b3JzMTI4ID0gW1tbMHgwMCwweDAxLDB4MDIsMHgwMywweDA1LDB4MDYsMHgwNywweDA4LDB4MEEsMHgwQiwweDBDLDB4MEQsMHgwRiwweDEwLDB4MTEsMHgxMl0sWzB4NTAsMHg2OCwweDEyLDB4QTQsMHg1RiwweDA4LDB4QzgsMHg4OSwweEI5LDB4N0YsMHg1OSwweDgwLDB4MDMsMHg4QiwweDgzLDB4NTldLFsweEQ4LDB4RjUsMHgzMiwweDUzLDB4ODIsMHg4OSwweEVGLDB4N0QsMHgwNiwweEI1LDB4MDYsMHhBNCwweEZELDB4NUIsMHhFOSwweEM5XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MTQsMHgxNSwweDE2LDB4MTcsMHgxOSwweDFBLDB4MUIsMHgxQywweDFFLDB4MUYsMHgyMCwweDIxLDB4MjMsMHgyNCwweDI1LDB4MjZdLFsweDVDLDB4NkQsMHg3MSwweENBLDB4MzAsMHhERSwweDhCLDB4OEIsMHgwMCwweDU0LDB4OTksMHg4NCwweEQyLDB4RUMsMHg3RCwweDRCXSxbMHg1OSwweEFCLDB4MzAsMHhGNCwweEQ0LDB4RUUsMHg2RSwweDRGLDB4RjksMHg5MCwweDdFLDB4RjYsMHg1QiwweDFGLDB4QjYsMHg4Q11dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDI4LDB4MjksMHgyQSwweDJCLDB4MkQsMHgyRSwweDJGLDB4MzAsMHgzMiwweDMzLDB4MzQsMHgzNSwweDM3LDB4MzgsMHgzOSwweDNBXSxbMHg1MywweEYzLDB4RjQsMHhDNiwweDRGLDB4ODYsMHgxNiwweEU0LDB4RTcsMHhDNSwweDYxLDB4OTksMHhGNCwweDhGLDB4MjEsMHhGNl0sWzB4QkYsMHgxRSwweEQyLDB4RkMsMHhCMiwweEFGLDB4M0YsMHhENCwweDE0LDB4NDMsMHhCNSwweDZELDB4ODUsMHgwMiwweDVDLDB4QjFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgzQywweDNELDB4M0UsMHgzRiwweDQxLDB4NDIsMHg0MywweDQ0LDB4NDYsMHg0NywweDQ4LDB4NDksMHg0QiwweDRDLDB4NEQsMHg0RV0sWzB4QTEsMHhFQiwweDY1LDB4QTMsMHg0OCwweDcxLDB4NjUsMHhGQiwweDBGLDB4MUMsMHgyNywweEZGLDB4OTksMHg1OSwweEY3LDB4MDNdLFsweDczLDB4MTYsMHg2MywweDJELDB4NUMsMHgzMiwweDIzLDB4M0UsMHhEQywweEIwLDB4NzgsMHgwNSwweDYwLDB4RUEsMHhFOCwweEIyXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NTAsMHg1MSwweDUyLDB4NTMsMHg1NSwweDU2LDB4NTcsMHg1OCwweDVBLDB4NUIsMHg1QywweDVELDB4NUYsMHg2MCwweDYxLDB4NjJdLFsweDM1LDB4NTMsMHhFQywweEYwLDB4QjEsMHg3MywweDk1LDB4NTgsMHhCMCwweDhFLDB4MzUsMHgwQSwweDk4LDB4QTMsMHg5QiwweEZBXSxbMHg0MCwweDhDLDB4MDcsMHgzRSwweDNFLDB4MjUsMHgzOCwweDA3LDB4MkIsMHg3MiwweDYyLDB4NUUsMHg2OCwweEI4LDB4MzYsMHg0Ql1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDY0LDB4NjUsMHg2NiwweDY3LDB4NjksMHg2QSwweDZCLDB4NkMsMHg2RSwweDZGLDB4NzAsMHg3MSwweDczLDB4NzQsMHg3NSwweDc2XSxbMHg2NywweDQyLDB4OTksMHg2OSwweDQ5LDB4MEIsMHg5NywweDExLDB4QUUsMHgyQiwweDAxLDB4REMsMHg0OSwweDdBLDB4RkQsMHhFOF0sWzB4RTEsMHhGOSwweDRELDB4RkEsMHg3NywweDY1LDB4OTcsMHhCRSwweEFDLDB4QTIsMHg2MiwweEYyLDB4RjYsMHgzNiwweDZGLDB4RUFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg3OCwweDc5LDB4N0EsMHg3QiwweDdELDB4N0UsMHg3RiwweDgwLDB4ODIsMHg4MywweDg0LDB4ODUsMHg4NywweDg4LDB4ODksMHg4QV0sWzB4OTMsMHgzOCwweDVDLDB4MUYsMHgyQSwweEVDLDB4OEIsMHhFRCwweDE5LDB4MkYsMHg1QSwweDhFLDB4MTYsMHgxRCwweEQ1LDB4MDhdLFsweEYyLDB4OUUsMHg5OCwweDZDLDB4NkEsMHgxQywweDI3LDB4RDcsMHhCMiwweDlGLDB4RkQsMHg3RSwweEU5LDB4MkIsMHg3NSwweEYxXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4OEMsMHg4RCwweDhFLDB4OEYsMHg5MSwweDkyLDB4OTMsMHg5NCwweDk2LDB4OTcsMHg5OCwweDk5LDB4OUIsMHg5QywweDlELDB4OUVdLFsweEI1LDB4QkYsMHg5NCwweDZCLDB4RTEsMHg5QiwweEVCLDB4OEQsMHhCMywweDk4LDB4M0IsMHg1RiwweDRDLDB4NkUsMHg4RCwweERCXSxbMHgxMywweDFDLDB4ODgsMHg2QSwweDU3LDB4RjgsMHhDMiwweEU3LDB4MTMsMHhBQiwweEE2LDB4OTUsMHg1RSwweDJCLDB4NTUsMHhCNV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEEwLDB4QTEsMHhBMiwweEEzLDB4QTUsMHhBNiwweEE3LDB4QTgsMHhBQSwweEFCLDB4QUMsMHhBRCwweEFGLDB4QjAsMHhCMSwweEIyXSxbMHg0MSwweDMyLDB4MUUsMHhFMSwweDBFLDB4MjEsMHhCRCwweDkwLDB4NzIsMHgyNywweEM0LDB4NDUsMHgwRiwweEY0LDB4MjMsMHgyNF0sWzB4RDIsMHhBQiwweDc2LDB4NjIsMHhERiwweDlCLDB4OEMsMHg3NCwweDAyLDB4MTAsMHhFNSwweEVFLDB4QjYsMHgxQywweDE5LDB4OURdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhCNCwweEI1LDB4QjYsMHhCNywweEI5LDB4QkEsMHhCQiwweEJDLDB4QkUsMHhCRiwweEMwLDB4QzEsMHhDMywweEM0LDB4QzUsMHhDNl0sWzB4MDAsMHhBOCwweDJGLDB4NTksMHhDOSwweDFDLDB4ODQsMHg4NiwweEQxLDB4MkMsMHgwQSwweDgwLDB4MTIsMHg0RiwweDYwLDB4ODldLFsweDE0LDB4QzEsMHgwNSwweDU0LDB4QjIsMHg4NSwweDlDLDB4NDgsMHg0QywweEFCLDB4NTgsMHg2OSwweEJCLDB4RTcsMHhDNCwweDcwXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4QzgsMHhDOSwweENBLDB4Q0IsMHhDRCwweENFLDB4Q0YsMHhEMCwweEQyLDB4RDMsMHhENCwweEQ1LDB4RDcsMHhEOCwweEQ5LDB4REFdLFsweDdDLDB4RTAsMHhGRCwweDA3LDB4NjcsMHg1NCwweDY5LDB4MUIsMHg0QiwweEJELDB4OUYsMHhBRiwweDhBLDB4MTMsMHg3MiwweEZFXSxbMHhEQiwweDRELDB4NDksMHg4RiwweDBBLDB4NDksMHhDRiwweDU1LDB4NDQsMHg1RCwweDUwLDB4MkMsMHgxRiwweDlBLDB4QjMsMHhCNV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweERDLDB4REQsMHhERSwweERGLDB4RTEsMHhFMiwweEUzLDB4RTQsMHhFNiwweEU3LDB4RTgsMHhFOSwweEVCLDB4RUMsMHhFRCwweEVFXSxbMHgyMywweDYwLDB4NUEsMHg4MiwweDQzLDB4RDAsMHg3NywweDY0LDB4NTQsMHgxQiwweEM1LDB4QUQsMHgzNSwweDVCLDB4MzEsMHgyOV0sWzB4NkQsMHg5NiwweEZFLDB4RjcsMHhENiwweDY1LDB4OTAsMHhBNywweDdBLDB4NzcsMHhCQiwweDIwLDB4NTYsMHg2NiwweDdGLDB4N0ZdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhGMCwweEYxLDB4RjIsMHhGMywweEY1LDB4RjYsMHhGNywweEY4LDB4RkEsMHhGQiwweEZDLDB4RkQsMHhGRSwweDAxLDB4MDAsMHgwMl0sWzB4MTIsMHhBOCwweENGLDB4QTIsMHgzRSwweEE3LDB4NjQsMHhGRCwweDg3LDB4NjIsMHgzMiwweEI0LDB4RTgsMHg0MiwweEJDLDB4NDRdLFsweDMxLDB4NkYsMHhCNiwweDhFLDB4REIsMHhBNywweDM2LDB4QzUsMHgzRSwweDc4LDB4NDcsMHg3QiwweEY5LDB4MTMsMHg3MiwweDVDXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MDQsMHgwNSwweDA2LDB4MDcsMHgwOSwweDBBLDB4MEIsMHgwQywweDBFLDB4MEYsMHgxMCwweDExLDB4MTMsMHgxNCwweDE1LDB4MTZdLFsweEJDLDB4QUYsMHgzMiwweDQxLDB4NUUsMHg4MywweDA4LDB4QjMsMHg3MiwweDNFLDB4NUYsMHhERCwweDg1LDB4M0MsMHhDQywweDgwXSxbMHg2OSwweDM2LDB4RjIsMHhCOSwweDNBLDB4RjgsMHgzOSwweDdGLDB4RDMsMHhBNywweDcxLDB4RkMsMHgwMSwweDFDLDB4OEMsMHgzN11dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDJDLDB4MkQsMHgyRSwweDJGLDB4MzEsMHgzMiwweDMzLDB4MzQsMHgzNiwweDM3LDB4MzgsMHgzOSwweDNCLDB4M0MsMHgzRCwweDNFXSxbMHg4OSwweEFGLDB4QUUsMHg2OCwweDVELDB4ODAsMHgxQSwweEQ3LDB4NDcsMHhBQywweEU5LDB4MUYsMHhDNCwweDlBLDB4REQsMHhFMF0sWzB4RjMsMHhGOSwweDJGLDB4N0EsMHg5QywweDU5LDB4MTcsMHg5QywweDFGLDB4Q0MsMHgyQywweDJCLDB4QTAsMHhCMCwweDgyLDB4Q0RdXV07XG4gIFxuICB2YXIgdGVzdHZlY3RvcnMxOTIgPSBbW1sweDAwLDB4MDEsMHgwMiwweDAzLDB4MDUsMHgwNiwweDA3LDB4MDgsMHgwQSwweDBCLDB4MEMsMHgwRCwweDBGLDB4MTAsMHgxMSwweDEyLDB4MTQsMHgxNSwweDE2LDB4MTcsMHgxOSwweDFBLDB4MUIsMHgxQ10sWzB4MkQsMHgzMywweEVFLDB4RjIsMHhDMCwweDQzLDB4MEEsMHg4QSwweDlFLDB4QkYsMHg0NSwweEU4LDB4MDksMHhDNCwweDBCLDB4QjZdLFsweERGLDB4RjQsMHg5NCwweDVFLDB4MDMsMHgzNiwweERGLDB4NEMsMHgxQywweDU2LDB4QkMsMHg3MCwweDBFLDB4RkYsMHg4MywweDdGXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MUUsMHgxRiwweDIwLDB4MjEsMHgyMywweDI0LDB4MjUsMHgyNiwweDI4LDB4MjksMHgyQSwweDJCLDB4MkQsMHgyRSwweDJGLDB4MzAsMHgzMiwweDMzLDB4MzQsMHgzNSwweDM3LDB4MzgsMHgzOSwweDNBXSxbMHg2QSwweEEzLDB4NzUsMHhEMSwweEZBLDB4MTUsMHg1QSwweDYxLDB4RkIsMHg3MiwweDM1LDB4M0UsMHgwQSwweDVBLDB4ODcsMHg1Nl0sWzB4QjYsMHhGRCwweERFLDB4RjQsMHg3NSwweDI3LDB4NjUsMHhFMywweDQ3LDB4RDUsMHhEMiwweERDLDB4MTksMHg2RCwweDEyLDB4NTJdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgzQywweDNELDB4M0UsMHgzRiwweDQxLDB4NDIsMHg0MywweDQ0LDB4NDYsMHg0NywweDQ4LDB4NDksMHg0QiwweDRDLDB4NEQsMHg0RSwweDUwLDB4NTEsMHg1MiwweDUzLDB4NTUsMHg1NiwweDU3LDB4NThdLFsweEJDLDB4MzcsMHgzNiwweDUxLDB4OEIsMHg5NCwweDkwLDB4REMsMHhCOCwweEVELDB4NjAsMHhFQiwweDI2LDB4NzUsMHg4RSwweEQ0XSxbMHhEMiwweDM2LDB4ODQsMHhFMywweEQ5LDB4NjMsMHhCMywweEFGLDB4Q0YsMHgxQSwweDExLDB4NEEsMHhDQSwweDkwLDB4Q0IsMHhENl1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDVBLDB4NUIsMHg1QywweDVELDB4NUYsMHg2MCwweDYxLDB4NjIsMHg2NCwweDY1LDB4NjYsMHg2NywweDY5LDB4NkEsMHg2QiwweDZDLDB4NkUsMHg2RiwweDcwLDB4NzEsMHg3MywweDc0LDB4NzUsMHg3Nl0sWzB4QUEsMHgyMSwweDQ0LDB4MDIsMHhCNCwweDZDLDB4RkYsMHhCOSwweEY3LDB4NjEsMHhFQywweDExLDB4MjYsMHgzQSwweDMxLDB4MUVdLFsweDNBLDB4N0EsMHhDMCwweDI3LDB4NzUsMHgzRSwweDJBLDB4MTgsMHhDMiwweENFLDB4QUIsMHg5RSwweDE3LDB4QzEsMHgxRiwweEQwXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NzgsMHg3OSwweDdBLDB4N0IsMHg3RCwweDdFLDB4N0YsMHg4MCwweDgyLDB4ODMsMHg4NCwweDg1LDB4ODcsMHg4OCwweDg5LDB4OEEsMHg4QywweDhELDB4OEUsMHg4RiwweDkxLDB4OTIsMHg5MywweDk0XSxbMHgwMiwweEFFLDB4QTgsMHg2RSwweDU3LDB4MkUsMHhFQSwweEI2LDB4NkIsMHgyQywweDNBLDB4RjUsMHhFOSwweEE0LDB4NkYsMHhENl0sWzB4OEYsMHg2NywweDg2LDB4QkQsMHgwMCwweDc1LDB4MjgsMHhCQSwweDI2LDB4NjAsMHgzQywweDE2LDB4MDEsMHhDRCwweEQwLDB4RDhdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg5NiwweDk3LDB4OTgsMHg5OSwweDlCLDB4OUMsMHg5RCwweDlFLDB4QTAsMHhBMSwweEEyLDB4QTMsMHhBNSwweEE2LDB4QTcsMHhBOCwweEFBLDB4QUIsMHhBQywweEFELDB4QUYsMHhCMCwweEIxLDB4QjJdLFsweEUyLDB4QUUsMHhGNiwweEFDLDB4QzMsMHgzQiwweDk2LDB4NUMsMHg0RiwweEExLDB4RjksMHgxQywweDc1LDB4RkYsMHg2RiwweDM2XSxbMHhEMSwweDdELDB4MDcsMHgzQiwweDAxLDB4RTcsMHgxNSwweDAyLDB4RTIsMHg4QiwweDQ3LDB4QUIsMHg1NSwweDExLDB4NjgsMHhCM11dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEI0LDB4QjUsMHhCNiwweEI3LDB4QjksMHhCQSwweEJCLDB4QkMsMHhCRSwweEJGLDB4QzAsMHhDMSwweEMzLDB4QzQsMHhDNSwweEM2LDB4QzgsMHhDOSwweENBLDB4Q0IsMHhDRCwweENFLDB4Q0YsMHhEMF0sWzB4MDYsMHg1OSwweERGLDB4NDYsMHg0MiwweDcxLDB4NjIsMHhCOSwweDQzLDB4NDgsMHg2NSwweERELDB4OTQsMHg5OSwweEY5LDB4MURdLFsweEE0LDB4NjksMHhEQSwweDUxLDB4NzEsMHgxOSwweEZBLDB4QjksMHg1OCwweDc2LDB4RjQsMHgxRCwweDA2LDB4RDQsMHgwRiwweEZBXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4RDIsMHhEMywweEQ0LDB4RDUsMHhENywweEQ4LDB4RDksMHhEQSwweERDLDB4REQsMHhERSwweERGLDB4RTEsMHhFMiwweEUzLDB4RTQsMHhFNiwweEU3LDB4RTgsMHhFOSwweEVCLDB4RUMsMHhFRCwweEVFXSxbMHg0OSwweEE0LDB4NDIsMHgzOSwweEM3LDB4NDgsMHhGRSwweEI0LDB4NTYsMHhGNSwweDlDLDB4MjcsMHg2QSwweDU2LDB4NTgsMHhERl0sWzB4NjAsMHg5MSwweEFBLDB4M0IsMHg2OSwweDVDLDB4MTEsMHhGNSwweEMwLDB4QjYsMHhBRCwweDI2LDB4RDMsMHhEOCwweDYyLDB4RkZdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhGMCwweEYxLDB4RjIsMHhGMywweEY1LDB4RjYsMHhGNywweEY4LDB4RkEsMHhGQiwweEZDLDB4RkQsMHhGRSwweDAxLDB4MDAsMHgwMiwweDA0LDB4MDUsMHgwNiwweDA3LDB4MDksMHgwQSwweDBCLDB4MENdLFsweDY2LDB4MjAsMHg4RiwweDZFLDB4OUQsMHgwNCwweDUyLDB4NUIsMHhERSwweERCLDB4MjcsMHgzMywweEI2LDB4QTYsMHhCRSwweDM3XSxbMHg3MCwweEY5LDB4RTYsMHg3RiwweDlGLDB4OEQsMHhGMSwweDI5LDB4NDEsMHgzMSwweDY2LDB4MkQsMHhDNiwweEU2LDB4OTMsMHg2NF1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDBFLDB4MEYsMHgxMCwweDExLDB4MTMsMHgxNCwweDE1LDB4MTYsMHgxOCwweDE5LDB4MUEsMHgxQiwweDFELDB4MUUsMHgxRiwweDIwLDB4MjIsMHgyMywweDI0LDB4MjUsMHgyNywweDI4LDB4MjksMHgyQV0sWzB4MzMsMHg5MywweEY4LDB4REYsMHhDNywweDI5LDB4QzksMHg3RiwweDU0LDB4ODAsMHhCOSwweDUwLDB4QkMsMHg5NiwweDY2LDB4QjBdLFsweEQxLDB4NTQsMHhEQywweEFGLDB4QUQsMHg4QiwweDIwLDB4N0YsMHhBNSwweENCLDB4QzksMHg1RSwweDk5LDB4OTYsMHhCNSwweDU5XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MkMsMHgyRCwweDJFLDB4MkYsMHgzMSwweDMyLDB4MzMsMHgzNCwweDM2LDB4MzcsMHgzOCwweDM5LDB4M0IsMHgzQywweDNELDB4M0UsMHg0MCwweDQxLDB4NDIsMHg0MywweDQ1LDB4NDYsMHg0NywweDQ4XSxbMHg2MCwweDY4LDB4MzQsMHhDOCwweENFLDB4MDYsMHgzRiwweDMyLDB4MzQsMHhDRiwweDExLDB4NDUsMHgzMiwweDVELDB4QkQsMHg3MV0sWzB4NDksMHgzNCwweEQ1LDB4NDEsMHhFOCwweEI0LDB4NkYsMHhBMywweDM5LDB4QzgsMHgwNSwweEE3LDB4QUUsMHhCOSwweEU1LDB4REFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg0QSwweDRCLDB4NEMsMHg0RCwweDRGLDB4NTAsMHg1MSwweDUyLDB4NTQsMHg1NSwweDU2LDB4NTcsMHg1OSwweDVBLDB4NUIsMHg1QywweDVFLDB4NUYsMHg2MCwweDYxLDB4NjMsMHg2NCwweDY1LDB4NjZdLFsweEZFLDB4QzEsMHhDMCwweDRGLDB4NTIsMHg5QiwweEJELDB4MTcsMHhEOCwweENFLDB4Q0YsMHhDQywweDQ3LDB4MTgsMHhCMSwweDdGXSxbMHg2MiwweDU2LDB4NEMsMHg3MywweDhGLDB4M0UsMHhGRSwweDE4LDB4NkUsMHgxQSwweDEyLDB4N0EsMHgwQywweDRELDB4M0MsMHg2MV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDY4LDB4NjksMHg2QSwweDZCLDB4NkQsMHg2RSwweDZGLDB4NzAsMHg3MiwweDczLDB4NzQsMHg3NSwweDc3LDB4NzgsMHg3OSwweDdBLDB4N0MsMHg3RCwweDdFLDB4N0YsMHg4MSwweDgyLDB4ODMsMHg4NF0sWzB4MzIsMHhERiwweDk5LDB4QjQsMHgzMSwweEVELDB4NUQsMHhDNSwweEFDLDB4RjgsMHhDQSwweEY2LDB4REMsMHg2QywweEU0LDB4NzVdLFsweDA3LDB4ODAsMHg1QSwweEEwLDB4NDMsMHg5OCwweDZFLDB4QjIsMHgzNiwweDkzLDB4RTIsMHgzQiwweEVGLDB4OEYsMHgzNCwweDM4XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4ODYsMHg4NywweDg4LDB4ODksMHg4QiwweDhDLDB4OEQsMHg4RSwweDkwLDB4OTEsMHg5MiwweDkzLDB4OTUsMHg5NiwweDk3LDB4OTgsMHg5QSwweDlCLDB4OUMsMHg5RCwweDlGLDB4QTAsMHhBMSwweEEyXSxbMHg3RiwweERDLDB4MkIsMHg3NCwweDZGLDB4M0YsMHg2NiwweDUyLDB4OTYsMHg5NCwweDNCLDB4ODMsMHg3MSwweDBELDB4MUYsMHg4Ml0sWzB4REYsMHgwQiwweDQ5LDB4MzEsMHgwMywweDhCLDB4QUQsMHhFOCwweDQ4LDB4REUsMHhFMywweEI0LDB4QjgsMHg1QSwweEE0LDB4NEJdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhBNCwweEE1LDB4QTYsMHhBNywweEE5LDB4QUEsMHhBQiwweEFDLDB4QUUsMHhBRiwweEIwLDB4QjEsMHhCMywweEI0LDB4QjUsMHhCNiwweEI4LDB4QjksMHhCQSwweEJCLDB4QkQsMHhCRSwweEJGLDB4QzBdLFsweDhGLDB4QkEsMHgxNSwweDEwLDB4QTMsMHhDNSwweEI4LDB4N0UsMHgyRSwweEFBLDB4M0YsMHg3QSwweDkxLDB4NDUsMHg1QywweEEyXSxbMHg1OSwweDJELDB4NUYsMHhERSwweEQ3LDB4NjUsMHg4MiwweEU0LDB4MTQsMHgzQywweDY1LDB4MDksMHg5MywweDA5LDB4NDcsMHg3Q11dXTtcbiAgXG4gIHZhciB0ZXN0dmVjdG9yczI1NiA9IFtbWzB4MDAsMHgwMSwweDAyLDB4MDMsMHgwNSwweDA2LDB4MDcsMHgwOCwweDBBLDB4MEIsMHgwQywweDBELDB4MEYsMHgxMCwweDExLDB4MTIsMHgxNCwweDE1LDB4MTYsMHgxNywweDE5LDB4MUEsMHgxQiwweDFDLDB4MUUsMHgxRiwweDIwLDB4MjEsMHgyMywweDI0LDB4MjUsMHgyNl0sWzB4ODMsMHg0RSwweEFELDB4RkMsMHhDQSwweEM3LDB4RTEsMHhCMywweDA2LDB4NjQsMHhCMSwweEFCLDB4QTQsMHg0OCwweDE1LDB4QUJdLFsweDE5LDB4NDYsMHhEQSwweEJGLDB4NkEsMHgwMywweEEyLDB4QTIsMHhDMywweEQwLDB4QjAsMHg1MCwweDgwLDB4QUUsMHhENiwweEZDXV0sXG4gICAgICAgICAgICAgIFtbMHgyOCwweDI5LDB4MkEsMHgyQiwweDJELDB4MkUsMHgyRiwweDMwLDB4MzIsMHgzMywweDM0LDB4MzUsMHgzNywweDM4LDB4MzksMHgzQSwweDNDLDB4M0QsMHgzRSwweDNGLDB4NDEsMHg0MiwweDQzLDB4NDQsMHg0NiwweDQ3LDB4NDgsMHg0OSwweDRCLDB4NEMsMHg0RCwweDRFXSxbMHhEOSwweERDLDB4NEQsMHhCQSwweDMwLDB4MjEsMHhCMCwweDVELDB4NjcsMHhDMCwweDUxLDB4OEYsMHg3MiwweEI2LDB4MkIsMHhGMV0sWzB4NUUsMHhEMywweDAxLDB4RDcsMHg0NywweEQzLDB4Q0MsMHg3MSwweDU0LDB4NDUsMHhFQiwweERFLDB4QzYsMHgyRiwweDJGLDB4QjRdXSxcbiAgICAgICAgICAgICAgW1sweDUwLDB4NTEsMHg1MiwweDUzLDB4NTUsMHg1NiwweDU3LDB4NTgsMHg1QSwweDVCLDB4NUMsMHg1RCwweDVGLDB4NjAsMHg2MSwweDYyLDB4NjQsMHg2NSwweDY2LDB4NjcsMHg2OSwweDZBLDB4NkIsMHg2QywweDZFLDB4NkYsMHg3MCwweDcxLDB4NzMsMHg3NCwweDc1LDB4NzZdLFsweEEyLDB4OTEsMHhEOCwweDYzLDB4MDEsMHhBNCwweEE3LDB4MzksMHhGNywweDM5LDB4MjEsMHg3MywweEFBLDB4M0MsMHg2MCwweDRDXSxbMHg2NSwweDg1LDB4QzgsMHhGNCwweDNELDB4MTMsMHhBNiwweEJFLDB4QUIsMHg2NCwweDE5LDB4RkMsMHg1OSwweDM1LDB4QjksMHhEMF1dLFxuICAgICAgICAgICAgICBbWzB4NzgsMHg3OSwweDdBLDB4N0IsMHg3RCwweDdFLDB4N0YsMHg4MCwweDgyLDB4ODMsMHg4NCwweDg1LDB4ODcsMHg4OCwweDg5LDB4OEEsMHg4QywweDhELDB4OEUsMHg4RiwweDkxLDB4OTIsMHg5MywweDk0LDB4OTYsMHg5NywweDk4LDB4OTksMHg5QiwweDlDLDB4OUQsMHg5RV0sWzB4NDIsMHg2NCwweEIyLDB4NjksMHg2NCwweDk4LDB4REUsMHg0RCwweEY3LDB4OTcsMHg4OCwweEE5LDB4RjgsMHgzRSwweDkzLDB4OTBdLFsweDJBLDB4NUIsMHg1NiwweEE1LDB4OTYsMHg2OCwweDBGLDB4Q0MsMHgwRSwweDA1LDB4RjUsMHhFMCwweEYxLDB4NTEsMHhFQywweEFFXV0sXG4gICAgICAgICAgICAgIFtbMHhBMCwweEExLDB4QTIsMHhBMywweEE1LDB4QTYsMHhBNywweEE4LDB4QUEsMHhBQiwweEFDLDB4QUQsMHhBRiwweEIwLDB4QjEsMHhCMiwweEI0LDB4QjUsMHhCNiwweEI3LDB4QjksMHhCQSwweEJCLDB4QkMsMHhCRSwweEJGLDB4QzAsMHhDMSwweEMzLDB4QzQsMHhDNSwweEM2XSxbMHhFRSwweDk5LDB4MzIsMHhCMywweDcyLDB4MTgsMHgwNCwweEQ1LDB4QTgsMHgzRSwweEY1LDB4OTQsMHg5MiwweDQ1LDB4QjYsMHhGNl0sWzB4RjUsMHhENiwweEZGLDB4NDEsMHg0RiwweEQyLDB4QzYsMHgxOCwweDE0LDB4OTQsMHhEMiwweDBDLDB4MzcsMHhGMiwweEI4LDB4QzRdXSxcbiAgICAgICAgICAgICAgW1sweEM4LDB4QzksMHhDQSwweENCLDB4Q0QsMHhDRSwweENGLDB4RDAsMHhEMiwweEQzLDB4RDQsMHhENSwweEQ3LDB4RDgsMHhEOSwweERBLDB4REMsMHhERCwweERFLDB4REYsMHhFMSwweEUyLDB4RTMsMHhFNCwweEU2LDB4RTcsMHhFOCwweEU5LDB4RUIsMHhFQywweEVELDB4RUVdLFsweEU2LDB4MjQsMHg4RiwweDU1LDB4QzUsMHhGRCwweENCLDB4Q0EsMHg5QywweEJCLDB4QjAsMHgxQywweDg4LDB4QTIsMHhFQSwweDc3XSxbMHg4NSwweDM5LDB4OUMsMHgwMSwweEY1LDB4OUYsMHhGRiwweEI1LDB4MjAsMHg0RiwweDE5LDB4RjgsMHg0OCwweDJGLDB4MDAsMHhCOF1dLFxuICAgICAgICAgICAgICBbWzB4RjAsMHhGMSwweEYyLDB4RjMsMHhGNSwweEY2LDB4RjcsMHhGOCwweEZBLDB4RkIsMHhGQywweEZELDB4RkUsMHgwMSwweDAwLDB4MDIsMHgwNCwweDA1LDB4MDYsMHgwNywweDA5LDB4MEEsMHgwQiwweDBDLDB4MEUsMHgwRiwweDEwLDB4MTEsMHgxMywweDE0LDB4MTUsMHgxNl0sWzB4QjgsMHgzNSwweDhFLDB4NDEsMHhCOSwweERGLDB4RjYsMHg1RiwweEQ0LDB4NjEsMHhENSwweDVBLDB4OTksMHgyNiwweDYyLDB4NDddLFsweDkyLDB4MDksMHg3QiwweDRDLDB4ODgsMHhBMCwweDQxLDB4REQsMHhGOSwweDgxLDB4NDQsMHhCQywweDhELDB4MjIsMHhFOCwweEU3XV0sXG4gICAgICAgICAgICAgIFtbMHgxOCwweDE5LDB4MUEsMHgxQiwweDFELDB4MUUsMHgxRiwweDIwLDB4MjIsMHgyMywweDI0LDB4MjUsMHgyNywweDI4LDB4MjksMHgyQSwweDJDLDB4MkQsMHgyRSwweDJGLDB4MzEsMHgzMiwweDMzLDB4MzQsMHgzNiwweDM3LDB4MzgsMHgzOSwweDNCLDB4M0MsMHgzRCwweDNFXSxbMHhGMCwweEUyLDB4RDcsMHgyMiwweDYwLDB4QUYsMHg1OCwweEUyLDB4MUUsMHgwMSwweDVBLDB4QjMsMHhBNCwweEMwLDB4RDksMHgwNl0sWzB4ODksMHhCRCwweDVCLDB4NzMsMHhCMywweDU2LDB4QUIsMHg0MSwweDJBLDB4RUYsMHg5RiwweDc2LDB4Q0UsMHhBMiwweEQ2LDB4NUNdXSxcbiAgICAgICAgICAgICAgW1sweDQwLDB4NDEsMHg0MiwweDQzLDB4NDUsMHg0NiwweDQ3LDB4NDgsMHg0QSwweDRCLDB4NEMsMHg0RCwweDRGLDB4NTAsMHg1MSwweDUyLDB4NTQsMHg1NSwweDU2LDB4NTcsMHg1OSwweDVBLDB4NUIsMHg1QywweDVFLDB4NUYsMHg2MCwweDYxLDB4NjMsMHg2NCwweDY1LDB4NjZdLFsweDQ3LDB4NUIsMHg4QiwweDgyLDB4M0MsMHhFOCwweDg5LDB4M0QsMHhCMywweEM0LDB4NEEsMHg5RiwweDJBLDB4MzcsMHg5RiwweEY3XSxbMHgyNSwweDM2LDB4OTYsMHg5MCwweDkzLDB4QzUsMHg1RiwweEY5LDB4NDUsMHg0NiwweDkyLDB4RjIsMHhGQSwweEMyLDB4RjUsMHgzMF1dLFxuICAgICAgICAgICAgICBbWzB4NjgsMHg2OSwweDZBLDB4NkIsMHg2RCwweDZFLDB4NkYsMHg3MCwweDcyLDB4NzMsMHg3NCwweDc1LDB4NzcsMHg3OCwweDc5LDB4N0EsMHg3QywweDdELDB4N0UsMHg3RiwweDgxLDB4ODIsMHg4MywweDg0LDB4ODYsMHg4NywweDg4LDB4ODksMHg4QiwweDhDLDB4OEQsMHg4RV0sWzB4NjgsMHg4RiwweDUyLDB4ODEsMHg5NCwweDU4LDB4MTIsMHg4NiwweDJGLDB4NUYsMHgzMCwweDc2LDB4Q0YsMHg4MCwweDQxLDB4MkZdLFsweDA3LDB4RkMsMHg3NiwweEE4LDB4NzIsMHg4NCwweDNGLDB4M0YsMHg2RSwweDAwLDB4ODEsMHhFRSwweDkzLDB4OTYsMHhENiwweDM3XV0sXG4gICAgICAgICAgICAgIFtbMHg5MCwweDkxLDB4OTIsMHg5MywweDk1LDB4OTYsMHg5NywweDk4LDB4OUEsMHg5QiwweDlDLDB4OUQsMHg5RiwweEEwLDB4QTEsMHhBMiwweEE0LDB4QTUsMHhBNiwweEE3LDB4QTksMHhBQSwweEFCLDB4QUMsMHhBRSwweEFGLDB4QjAsMHhCMSwweEIzLDB4QjQsMHhCNSwweEI2XSxbMHgwOCwweEQxLDB4RDIsMHhCQywweDc1LDB4MEEsMHhGNSwweDUzLDB4MzYsMHg1RCwweDM1LDB4RTcsMHg1QSwweEZBLDB4Q0UsMHhBQV0sWzB4RTMsMHg4QiwweEE4LDB4RUMsMHgyQSwweEE3LDB4NDEsMHgzNSwweDhELDB4Q0MsMHg5MywweEU4LDB4RjEsMHg0MSwweEM0LDB4OTFdXSxcbiAgICAgICAgICAgICAgW1sweEI4LDB4QjksMHhCQSwweEJCLDB4QkQsMHhCRSwweEJGLDB4QzAsMHhDMiwweEMzLDB4QzQsMHhDNSwweEM3LDB4QzgsMHhDOSwweENBLDB4Q0MsMHhDRCwweENFLDB4Q0YsMHhEMSwweEQyLDB4RDMsMHhENCwweEQ2LDB4RDcsMHhEOCwweEQ5LDB4REIsMHhEQywweERELDB4REVdLFsweDg3LDB4MDcsMHgxMiwweDFGLDB4NDcsMHhDQywweDNFLDB4RkMsMHhFQywweEE1LDB4RjksMHhBOCwweDQ3LDB4NDksMHg1MCwweEExXSxbMHhEMCwweDI4LDB4RUUsMHgyMywweEU0LDB4QTgsMHg5MCwweDc1LDB4RDAsMHhCMCwweDNFLDB4ODYsMHg4RCwweDdELDB4M0EsMHg0Ml1dLFxuICAgICAgICAgICAgICBbWzB4RTAsMHhFMSwweEUyLDB4RTMsMHhFNSwweEU2LDB4RTcsMHhFOCwweEVBLDB4RUIsMHhFQywweEVELDB4RUYsMHhGMCwweEYxLDB4RjIsMHhGNCwweEY1LDB4RjYsMHhGNywweEY5LDB4RkEsMHhGQiwweEZDLDB4RkUsMHhGRSwweDAxLDB4MDEsMHgwMywweDA0LDB4MDUsMHgwNl0sWzB4RTUsMHgxQSwweEEwLDB4QjEsMHgzNSwweERCLDB4QTUsMHg2NiwweDkzLDB4OUMsMHgzQiwweDYzLDB4NTksMHhBOSwweDgwLDB4QzVdLFsweDhDLDB4RDksMHg0MiwweDNELDB4RkMsMHg0NSwweDlFLDB4NTQsMHg3MSwweDU1LDB4QzUsMHhEMSwweEQ1LDB4MjIsMHhFNSwweDQwXV0sXG4gICAgICAgICAgICAgIFtbMHgwOCwweDA5LDB4MEEsMHgwQiwweDBELDB4MEUsMHgwRiwweDEwLDB4MTIsMHgxMywweDE0LDB4MTUsMHgxNywweDE4LDB4MTksMHgxQSwweDFDLDB4MUQsMHgxRSwweDFGLDB4MjEsMHgyMiwweDIzLDB4MjQsMHgyNiwweDI3LDB4MjgsMHgyOSwweDJCLDB4MkMsMHgyRCwweDJFXSxbMHgwNiwweDlBLDB4MDAsMHg3RiwweEM3LDB4NkEsMHg0NSwweDlGLDB4OTgsMHhCQSwweEY5LDB4MTcsMHhGRSwweERGLDB4OTUsMHgyMV0sWzB4MDgsMHgwRSwweDk1LDB4MTcsMHhFQiwweDE2LDB4NzcsMHg3MSwweDlBLDB4Q0YsMHg3MiwweDgwLDB4ODYsMHgwNCwweDBBLDB4RTNdXSxcbiAgICAgICAgICAgICAgW1sweDMwLDB4MzEsMHgzMiwweDMzLDB4MzUsMHgzNiwweDM3LDB4MzgsMHgzQSwweDNCLDB4M0MsMHgzRCwweDNGLDB4NDAsMHg0MSwweDQyLDB4NDQsMHg0NSwweDQ2LDB4NDcsMHg0OSwweDRBLDB4NEIsMHg0QywweDRFLDB4NEYsMHg1MCwweDUxLDB4NTMsMHg1NCwweDU1LDB4NTZdLFsweDcyLDB4NjEsMHg2NSwweEMxLDB4NzIsMHgzRiwweEJDLDB4RjYsMHhDMCwweDI2LDB4RDcsMHhEMCwweDBCLDB4MDksMHgxMCwweDI3XSxbMHg3QywweDE3LDB4MDAsMHgyMSwweDFBLDB4MzksMHg5MSwweEZDLDB4MEUsMHhDRCwweEVELDB4MEEsMHhCMywweEU1LDB4NzYsMHhCMF1dXTtcblxuICB2YXIgcmVzID0gdHJ1ZTtcbiAgdmFyIGogPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzMTI4Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJlczIgPSB0ZXN0X2Flcyh0ZXN0dmVjdG9yczEyOFtpXVsxXSx0ZXN0dmVjdG9yczEyOFtpXVswXSx0ZXN0dmVjdG9yczEyOFtpXVsyXSk7XG4gICAgcmVzICY9IHJlczI7XG4gICAgaWYgKCFyZXMyKSB7XG4gICAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIDEyOCBiaXQga2V5IHZlY3RvciB3aXRoIGJsb2NrIFwiK1xuICAgICAgICB1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMTI4W2ldWzFdKStcbiAgICAgICAgXCIgYW5kIGtleSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMTI4W2ldWzBdKStcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMxMjhbaV1bMl0pLFxuICAgICAgICBmYWxzZSk7XG4gICAgICBqKys7XG4gICAgfVxuICB9XG4gIGlmIChyZXMpIHtcbiAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCIxMjggYml0IGtleSB0ZXN0IHZlY3RvcnMgY29tcGxldGVkLlwiLHRydWUpXG4gICAgaisrO1xuICB9XG4gIFxuICByZXMgPSB0cnVlO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzMTkyLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJlczIgPSB0ZXN0X2Flcyh0ZXN0dmVjdG9yczE5MltpXVsxXSx0ZXN0dmVjdG9yczE5MltpXVswXSx0ZXN0dmVjdG9yczE5MltpXVsyXSk7XG4gICAgcmVzICY9IHJlczI7XG4gICAgaWYgKCFyZXMyKSB7XG4gICAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIDE5MiBiaXQga2V5IHZlY3RvciB3aXRoIGJsb2NrIFwiK1xuICAgICAgICB1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMTkyW2ldWzFdKStcbiAgICAgICAgXCIgYW5kIGtleSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMTkyW2ldWzBdKStcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMxOTJbaV1bMl0pLFxuICAgICAgICBmYWxzZSk7XG4gICAgICBqKys7XG4gICAgfVxuICB9XG4gIGlmIChyZXMpIHtcbiAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCIxOTIgYml0IGtleSB0ZXN0IHZlY3RvcnMgY29tcGxldGVkLlwiLHRydWUpXG4gICAgaisrO1xuICB9XG5cbiAgcmVzID0gdHJ1ZTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0ZXN0dmVjdG9yczI1Ni5sZW5ndGg7IGkrKykge1xuICAgIHZhciByZXMyID0gdGVzdF9hZXModGVzdHZlY3RvcnMyNTZbaV1bMV0sdGVzdHZlY3RvcnMyNTZbaV1bMF0sdGVzdHZlY3RvcnMyNTZbaV1bMl0pO1xuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyAyNTYgYml0IGtleSB2ZWN0b3Igd2l0aCBibG9jayBcIitcbiAgICAgICAgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczI1NltpXVsxXSkrXG4gICAgICAgIFwiIGFuZCBrZXkgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczI1NltpXVswXSkrXG4gICAgICAgIFwiIHNob3VsZCBiZSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMjU2W2ldWzJdKSxcbiAgICAgICAgZmFsc2UpO1xuICAgICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiMjU2IGJpdCBrZXkgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZC5cIiwgdHJ1ZSlcbiAgICBqKys7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIkJsb3dmaXNoIGNpcGhlciB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gaHR0cDovL3d3dy5zY2huZWllci5jb20vY29kZS92ZWN0b3JzLnR4dFwiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcbiAgICB1dGlsID0gb3BlbnBncC51dGlsLFxuICAgIEJGZW5jcnlwdCA9IG9wZW5wZ3AuY3J5cHRvLmNpcGhlci5ibG93ZmlzaDtcblxuICB2YXIgcmVzdWx0ID0gW107XG4gIGZ1bmN0aW9uIHRlc3RfYmYoaW5wdXQsIGtleSwgb3V0cHV0KSB7XG4gICAgdmFyIGJsb3dmaXNoID0gbmV3IG9wZW5wZ3AuY3J5cHRvLmNpcGhlci5ibG93ZmlzaCh1dGlsLmJpbjJzdHIoa2V5KSk7XG4gICAgdmFyIHJlc3VsdCA9IHV0aWwuYmluMnN0cihibG93ZmlzaC5lbmNyeXB0KGlucHV0KSk7XG5cbiAgICByZXR1cm4gKHV0aWwuaGV4c3RyZHVtcChyZXN1bHQpID09IHV0aWwuaGV4c3RyZHVtcCh1dGlsLmJpbjJzdHIob3V0cHV0KSkpO1xuICB9XG4gIHZhciB0ZXN0dmVjdG9ycyA9IFtbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NEUsMHhGOSwweDk3LDB4NDUsMHg2MSwweDk4LDB4REQsMHg3OF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkZdLFsweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkZdLFsweDUxLDB4ODYsMHg2RiwweEQ1LDB4QjgsMHg1RSwweENCLDB4OEFdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgzMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgxMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAxXSxbMHg3RCwweDg1LDB4NkYsMHg5QSwweDYxLDB4MzAsMHg2MywweEYyXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMV0sWzB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMV0sWzB4MjQsMHg2NiwweERELDB4ODcsMHg4QiwweDk2LDB4M0MsMHg5RF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTFdLFsweDYxLDB4RjksMHhDMywweDgwLDB4MjIsMHg4MSwweEIwLDB4OTZdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExXSxbMHgwMSwweDIzLDB4NDUsMHg2NywweDg5LDB4QUIsMHhDRCwweEVGXSxbMHg3RCwweDBDLDB4QzYsMHgzMCwweEFGLDB4REEsMHgxRSwweEM3XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NEUsMHhGOSwweDk3LDB4NDUsMHg2MSwweDk4LDB4REQsMHg3OF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweEZFLDB4REMsMHhCQSwweDk4LDB4NzYsMHg1NCwweDMyLDB4MTBdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDBBLDB4Q0UsMHhBQiwweDBGLDB4QzYsMHhBMCwweEEyLDB4OERdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg3QywweEExLDB4MTAsMHg0NSwweDRBLDB4MUEsMHg2RSwweDU3XSxbMHgwMSwweEExLDB4RDYsMHhEMCwweDM5LDB4NzcsMHg2NywweDQyXSxbMHg1OSwweEM2LDB4ODIsMHg0NSwweEVCLDB4MDUsMHgyOCwweDJCXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgzMSwweEQ5LDB4NjEsMHg5RCwweEMxLDB4MzcsMHg2RV0sWzB4NUMsMHhENSwweDRDLDB4QTgsMHgzRCwweEVGLDB4NTcsMHhEQV0sWzB4QjEsMHhCOCwweENDLDB4MEIsMHgyNSwweDBGLDB4MDksMHhBMF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDA3LDB4QTEsMHgxMywweDNFLDB4NEEsMHgwQiwweDI2LDB4ODZdLFsweDAyLDB4NDgsMHhENCwweDM4LDB4MDYsMHhGNiwweDcxLDB4NzJdLFsweDE3LDB4MzAsMHhFNSwweDc3LDB4OEIsMHhFQSwweDFELDB4QTRdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgzOCwweDQ5LDB4NjcsMHg0QywweDI2LDB4MDIsMHgzMSwweDlFXSxbMHg1MSwweDQ1LDB4NEIsMHg1OCwweDJELDB4REYsMHg0NCwweDBBXSxbMHhBMiwweDVFLDB4NzgsMHg1NiwweENGLDB4MjYsMHg1MSwweEVCXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDQsMHhCOSwweDE1LDB4QkEsMHg0MywweEZFLDB4QjUsMHhCNl0sWzB4NDIsMHhGRCwweDQ0LDB4MzAsMHg1OSwweDU3LDB4N0YsMHhBMl0sWzB4MzUsMHgzOCwweDgyLDB4QjEsMHgwOSwweENFLDB4OEYsMHgxQV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4MTMsMHhCOSwweDcwLDB4RkQsMHgzNCwweEYyLDB4Q0VdLFsweDA1LDB4OUIsMHg1RSwweDA4LDB4NTEsMHhDRiwweDE0LDB4M0FdLFsweDQ4LDB4RjQsMHhEMCwweDg4LDB4NEMsMHgzNywweDk5LDB4MThdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMSwweDcwLDB4RjEsMHg3NSwweDQ2LDB4OEYsMHhCNSwweEU2XSxbMHgwNywweDU2LDB4RDgsMHhFMCwweDc3LDB4NDcsMHg2MSwweEQyXSxbMHg0MywweDIxLDB4OTMsMHhCNywweDg5LDB4NTEsMHhGQywweDk4XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4NDMsMHgyOSwweDdGLDB4QUQsMHgzOCwweEUzLDB4NzMsMHhGRV0sWzB4NzYsMHgyNSwweDE0LDB4QjgsMHgyOSwweEJGLDB4NDgsMHg2QV0sWzB4MTMsMHhGMCwweDQxLDB4NTQsMHhENiwweDlELDB4MUEsMHhFNV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDA3LDB4QTcsMHgxMywweDcwLDB4NDUsMHhEQSwweDJBLDB4MTZdLFsweDNCLDB4REQsMHgxMSwweDkwLDB4NDksMHgzNywweDI4LDB4MDJdLFsweDJFLDB4RUQsMHhEQSwweDkzLDB4RkYsMHhEMywweDlDLDB4NzldXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwNCwweDY4LDB4OTEsMHgwNCwweEMyLDB4RkQsMHgzQiwweDJGXSxbMHgyNiwweDk1LDB4NUYsMHg2OCwweDM1LDB4QUYsMHg2MCwweDlBXSxbMHhEOCwweDg3LDB4RTAsMHgzOSwweDNDLDB4MkQsMHhBNiwweEUzXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MzcsMHhEMCwweDZCLDB4QjUsMHgxNiwweENCLDB4NzUsMHg0Nl0sWzB4MTYsMHg0RCwweDVFLDB4NDAsMHg0RiwweDI3LDB4NTIsMHgzMl0sWzB4NUYsMHg5OSwweEQwLDB4NEYsMHg1QiwweDE2LDB4MzksMHg2OV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDFGLDB4MDgsMHgyNiwweDBELDB4MUEsMHhDMiwweDQ2LDB4NUVdLFsweDZCLDB4MDUsMHg2RSwweDE4LDB4NzUsMHg5RiwweDVDLDB4Q0FdLFsweDRBLDB4MDUsMHg3QSwweDNCLDB4MjQsMHhEMywweDk3LDB4N0JdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg1OCwweDQwLDB4MjMsMHg2NCwweDFBLDB4QkEsMHg2MSwweDc2XSxbMHgwMCwweDRCLDB4RDYsMHhFRiwweDA5LDB4MTcsMHg2MCwweDYyXSxbMHg0NSwweDIwLDB4MzEsMHhDMSwweEU0LDB4RkEsMHhEQSwweDhFXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDIsMHg1OCwweDE2LDB4MTYsMHg0NiwweDI5LDB4QjAsMHgwN10sWzB4NDgsMHgwRCwweDM5LDB4MDAsMHg2RSwweEU3LDB4NjIsMHhGMl0sWzB4NzUsMHg1NSwweEFFLDB4MzksMHhGNSwweDlCLDB4ODcsMHhCRF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDQ5LDB4NzksMHgzRSwweEJDLDB4NzksMHhCMywweDI1LDB4OEZdLFsweDQzLDB4NzUsMHg0MCwweEM4LDB4NjksMHg4RiwweDNDLDB4RkFdLFsweDUzLDB4QzUsMHg1RiwweDlDLDB4QjQsMHg5RiwweEMwLDB4MTldXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg0RiwweEIwLDB4NUUsMHgxNSwweDE1LDB4QUIsMHg3MywweEE3XSxbMHgwNywweDJELDB4NDMsMHhBMCwweDc3LDB4MDcsMHg1MiwweDkyXSxbMHg3QSwweDhFLDB4N0IsMHhGQSwweDkzLDB4N0UsMHg4OSwweEEzXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4NDksMHhFOSwweDVELDB4NkQsMHg0QywweEEyLDB4MjksMHhCRl0sWzB4MDIsMHhGRSwweDU1LDB4NzcsMHg4MSwweDE3LDB4RjEsMHgyQV0sWzB4Q0YsMHg5QywweDVELDB4N0EsMHg0OSwweDg2LDB4QUQsMHhCNV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4ODMsMHgxMCwweERDLDB4NDAsMHg5QiwweDI2LDB4RDZdLFsweDFELDB4OUQsMHg1QywweDUwLDB4MTgsMHhGNywweDI4LDB4QzJdLFsweEQxLDB4QUIsMHhCMiwweDkwLDB4NjUsMHg4QiwweEM3LDB4NzhdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgxQywweDU4LDB4N0YsMHgxQywweDEzLDB4OTIsMHg0RiwweEVGXSxbMHgzMCwweDU1LDB4MzIsMHgyOCwweDZELDB4NkYsMHgyOSwweDVBXSxbMHg1NSwweENCLDB4MzcsMHg3NCwweEQxLDB4M0UsMHhGMiwweDAxXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgwMSwweDAxLDB4MDEsMHgwMSwweDAxLDB4MDEsMHgwMV0sWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4RkEsMHgzNCwweEVDLDB4NDgsMHg0NywweEIyLDB4NjgsMHhCMl1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDFGLDB4MUYsMHgxRiwweDFGLDB4MEUsMHgwRSwweDBFLDB4MEVdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweEE3LDB4OTAsMHg3OSwweDUxLDB4MDgsMHhFQSwweDNDLDB4QUVdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHhFMCwweEZFLDB4RTAsMHhGRSwweEYxLDB4RkUsMHhGMSwweEZFXSxbMHgwMSwweDIzLDB4NDUsMHg2NywweDg5LDB4QUIsMHhDRCwweEVGXSxbMHhDMywweDlFLDB4MDcsMHgyRCwweDlGLDB4QUMsMHg2MywweDFEXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4MDEsMHg0OSwweDMzLDB4RTAsMHhDRCwweEFGLDB4RjYsMHhFNF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkZdLFsweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEYyLDB4MUUsMHg5QSwweDc3LDB4QjcsMHgxQywweDQ5LDB4QkNdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMSwweDIzLDB4NDUsMHg2NywweDg5LDB4QUIsMHhDRCwweEVGXSxbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgyNCwweDU5LDB4NDYsMHg4OCwweDU3LDB4NTQsMHgzNiwweDlBXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkUsMHhEQywweEJBLDB4OTgsMHg3NiwweDU0LDB4MzIsMHgxMF0sWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4NkIsMHg1QywweDVBLDB4OUMsMHg1RCwweDlFLDB4MEEsMHg1QV1dXTtcblxuICB2YXIgcmVzID0gdHJ1ZTtcbiAgdmFyIGogPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJlczIgPSB0ZXN0X2JmKHRlc3R2ZWN0b3JzW2ldWzFdLHRlc3R2ZWN0b3JzW2ldWzBdLHRlc3R2ZWN0b3JzW2ldWzJdKTtcbiAgICByZXMgJj0gcmVzMjtcbiAgICBpZiAoIXJlczIpIHtcbiAgICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgdmVjdG9yIFwiK2krXCIgd2l0aCBibG9jayBcIitcbiAgICAgICAgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVswXSkrXG4gICAgICAgIFwiIGFuZCBrZXkgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVsxXSkrXG4gICAgICAgIFwiIHNob3VsZCBiZSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzJdKSwgZmFsc2UpO1xuICAgICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiMzQgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZCBcIiwgdHJ1ZSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJDQVNULTEyOCBjaXBoZXIgdGVzdCB3aXRoIHRlc3QgdmVjdG9ycyBmcm9tIFJGQzIxNDRcIiwgZnVuY3Rpb24oKSB7XG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG5cdFx0dXRpbCA9IG9wZW5wZ3AudXRpbDtcblxuXHR2YXIgcmVzdWx0ID0gW107XG5cdGZ1bmN0aW9uIHRlc3RfY2FzdChpbnB1dCwga2V5LCBvdXRwdXQpIHtcblx0XHR2YXIgY2FzdDUgPSBuZXcgb3BlbnBncC5jcnlwdG8uY2lwaGVyLmNhc3Q1KHV0aWwuYmluMnN0cihrZXkpKTtcblx0XHR2YXIgcmVzdWx0ID0gdXRpbC5iaW4yc3RyKGNhc3Q1LmVuY3J5cHQoaW5wdXQpKTtcblxuXHRcdHJldHVybiB1dGlsLmhleHN0cmR1bXAocmVzdWx0KSA9PSB1dGlsLmhleHN0cmR1bXAodXRpbC5iaW4yc3RyKG91dHB1dCkpO1xuXHR9XG5cdFxuXHR2YXIgdGVzdHZlY3RvcnMgPSBbW1sweDAxLDB4MjMsMHg0NSwweDY3LDB4MTIsMHgzNCwweDU2LDB4NzgsMHgyMywweDQ1LDB4NjcsMHg4OSwweDM0LDB4NTYsMHg3OCwweDlBXSxbMHgwMSwweDIzLDB4NDUsMHg2NywweDg5LDB4QUIsMHhDRCwweEVGXSxbMHgyMywweDhCLDB4NEYsMHhFNSwweDg0LDB4N0UsMHg0NCwweEIyXV1dO1xuXG5cdGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMubGVuZ3RoOyBpKyspIHtcblx0XHRyZXN1bHRbaV0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIHZlY3RvciB3aXRoIGJsb2NrIFwiK1xuXHRcdFx0XHR1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzBdKStcblx0XHRcdFx0XCIgYW5kIGtleSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzFdKStcblx0XHRcdFx0XCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMl0pLFxuXHRcdFx0dGVzdF9jYXN0KHRlc3R2ZWN0b3JzW2ldWzFdLHRlc3R2ZWN0b3JzW2ldWzBdLHRlc3R2ZWN0b3JzW2ldWzJdKSk7XG5cdH1cblx0cmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XHJcblxyXG51bml0LnJlZ2lzdGVyKFwiVHJpcGxlREVTIChFREUpIGNpcGhlciB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gaHR0cDovL2NzcmMubmlzdC5nb3YvcHVibGljYXRpb25zL25pc3RwdWJzLzgwMC0yMC84MDAtMjAucGRmXCIsIGZ1bmN0aW9uKCkge1xyXG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXHJcbiAgICB1dGlsID0gb3BlbnBncC51dGlsO1xyXG5cclxuICB2YXIgcmVzdWx0ID0gW107XHJcbiAgdmFyIGtleSA9IHV0aWwuYmluMnN0cihbMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDFdKTtcclxuICB2YXIgdGVzdHZlY3RvcnMgPSBbW1sweDgwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDk1LDB4RjgsMHhBNSwweEU1LDB4REQsMHgzMSwweEQ5LDB4MDBdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDQwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweERELDB4N0YsMHgxMiwweDFDLDB4QTUsMHgwMSwweDU2LDB4MTldXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDIwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDJFLDB4ODYsMHg1MywweDEwLDB4NEYsMHgzOCwweDM0LDB4RUFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDEwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDRCLDB4RDMsMHg4OCwweEZGLDB4NkMsMHhEOCwweDFELDB4NEZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDA4LDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDIwLDB4QjksMHhFNywweDY3LDB4QjIsMHhGQiwweDE0LDB4NTZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDA0LDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDU1LDB4NTcsMHg5MywweDgwLDB4RDcsMHg3MSwweDM4LDB4RUZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAyLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDZDLDB4QzUsMHhERSwweEZBLDB4QUYsMHgwNCwweDUxLDB4MkZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDBELDB4OUYsMHgyNywweDlCLDB4QTUsMHhEOCwweDcyLDB4NjBdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4ODAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEQ5LDB4MDMsMHgxQiwweDAyLDB4NzEsMHhCRCwweDVBLDB4MEFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4NDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDQyLDB4NDIsMHg1MCwweEIzLDB4N0MsMHgzRCwweEQ5LDB4NTFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MjAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEI4LDB4MDYsMHgxQiwweDdFLDB4Q0QsMHg5QSwweDIxLDB4RTVdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MTAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEYxLDB4NUQsMHgwRiwweDI4LDB4NkIsMHg2NSwweEJELDB4MjhdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDgsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEFELDB4RDAsMHhDQywweDhELDB4NkUsMHg1RCwweEVCLDB4QTFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDQsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEU2LDB4RDUsMHhGOCwweDI3LDB4NTIsMHhBRCwweDYzLDB4RDFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDIsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEVDLDB4QkYsMHhFMywweEJELDB4M0YsMHg1OSwweDFBLDB4NUVdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDEsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEYzLDB4NTYsMHg4MywweDQzLDB4NzksMHhEMSwweDY1LDB4Q0RdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHg4MCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDJCLDB4OUYsMHg5OCwweDJGLDB4MjAsMHgwMywweDdGLDB4QTldXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHg0MCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDg4LDB4OUQsMHhFMCwweDY4LDB4QTEsMHg2RiwweDBCLDB4RTZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgyMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEUxLDB4OUUsMHgyNywweDVELDB4ODQsMHg2QSwweDEyLDB4OThdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgxMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDMyLDB4OUEsMHg4RSwweEQ1LDB4MjMsMHhENywweDFBLDB4RUNdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwOCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEU3LDB4RkMsMHhFMiwweDI1LDB4NTcsMHhEMiwweDNDLDB4OTddXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwNCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDEyLDB4QTksMHhGNSwweDgxLDB4N0YsMHhGMiwweEQ2LDB4NURdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMiwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEE0LDB4ODQsMHhDMywweEFELDB4MzgsMHhEQywweDlDLDB4MTldXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMSwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEZCLDB4RTAsMHgwQSwweDhBLDB4MUUsMHhGOCwweEFELDB4NzJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDgwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDc1LDB4MEQsMHgwNywweDk0LDB4MDcsMHg1MiwweDEzLDB4NjNdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDQwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDY0LDB4RkUsMHhFRCwweDlDLDB4NzIsMHg0QywweDJGLDB4QUZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDIwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEYwLDB4MkIsMHgyNiwweDNCLDB4MzIsMHg4RSwweDJCLDB4NjBdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDEwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDlELDB4NjQsMHg1NSwweDVBLDB4OUEsMHgxMCwweEI4LDB4NTJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDA4LDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEQxLDB4MDYsMHhGRiwweDBCLDB4RUQsMHg1MiwweDU1LDB4RDddXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDA0LDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEUxLDB4NjUsMHgyQywweDZCLDB4MTMsMHg4QywweDY0LDB4QTVdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAyLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEU0LDB4MjgsMHg1OCwweDExLDB4ODYsMHhFQywweDhGLDB4NDZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAxLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweEFFLDB4QjUsMHhGNSwweEVELDB4RTIsMHgyRCwweDFBLDB4MzZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4ODAsMHgwMCwweDAwLDB4MDBdLFsweEU5LDB4NDMsMHhENywweDU2LDB4OEEsMHhFQywweDBDLDB4NUNdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4NDAsMHgwMCwweDAwLDB4MDBdLFsweERGLDB4OTgsMHhDOCwweDI3LDB4NkYsMHg1NCwweEIwLDB4NEJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MjAsMHgwMCwweDAwLDB4MDBdLFsweEIxLDB4NjAsMHhFNCwweDY4LDB4MEYsMHg2QywweDY5LDB4NkZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MTAsMHgwMCwweDAwLDB4MDBdLFsweEZBLDB4MDcsMHg1MiwweEIwLDB4N0QsMHg5QywweDRBLDB4QjhdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDgsMHgwMCwweDAwLDB4MDBdLFsweENBLDB4M0EsMHgyQiwweDAzLDB4NkQsMHhCQywweDg1LDB4MDJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDQsMHgwMCwweDAwLDB4MDBdLFsweDVFLDB4MDksMHgwNSwweDUxLDB4N0IsMHhCNSwweDlCLDB4Q0ZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDIsMHgwMCwweDAwLDB4MDBdLFsweDgxLDB4NEUsMHhFQiwweDNCLDB4OTEsMHhEOSwweDA3LDB4MjZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDEsMHgwMCwweDAwLDB4MDBdLFsweDRELDB4NDksMHhEQiwweDE1LDB4MzIsMHg5MSwweDlDLDB4OUZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHg4MCwweDAwLDB4MDBdLFsweDI1LDB4RUIsMHg1RiwweEMzLDB4RjgsMHhDRiwweDA2LDB4MjFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHg0MCwweDAwLDB4MDBdLFsweEFCLDB4NkEsMHgyMCwweEMwLDB4NjIsMHgwRCwweDFDLDB4NkZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgyMCwweDAwLDB4MDBdLFsweDc5LDB4RTksMHgwRCwweEJDLDB4OTgsMHhGOSwweDJDLDB4Q0FdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgxMCwweDAwLDB4MDBdLFsweDg2LDB4NkUsMHhDRSwweERELDB4ODAsMHg3MiwweEJCLDB4MEVdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwOCwweDAwLDB4MDBdLFsweDhCLDB4NTQsMHg1MywweDZGLDB4MkYsMHgzRSwweDY0LDB4QThdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwNCwweDAwLDB4MDBdLFsweEVBLDB4NTEsMHhEMywweDk3LDB4NTUsMHg5NSwweEI4LDB4NkJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMiwweDAwLDB4MDBdLFsweENBLDB4RkYsMHhDNiwweEFDLDB4NDUsMHg0MiwweERFLDB4MzFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMSwweDAwLDB4MDBdLFsweDhELDB4RDQsMHg1QSwweDJELDB4REYsMHg5MCwweDc5LDB4NkNdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDgwLDB4MDBdLFsweDEwLDB4MjksMHhENSwweDVFLDB4ODgsMHgwRSwweEMyLDB4RDBdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDQwLDB4MDBdLFsweDVELDB4ODYsMHhDQiwweDIzLDB4NjMsMHg5RCwweEJFLDB4QTldXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDIwLDB4MDBdLFsweDFELDB4MUMsMHhBOCwweDUzLDB4QUUsMHg3QywweDBDLDB4NUZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDEwLDB4MDBdLFsweENFLDB4MzMsMHgyMywweDI5LDB4MjQsMHg4RiwweDMyLDB4MjhdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDA4LDB4MDBdLFsweDg0LDB4MDUsMHhEMSwweEFCLDB4RTIsMHg0RiwweEI5LDB4NDJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDA0LDB4MDBdLFsweEU2LDB4NDMsMHhENywweDgwLDB4OTAsMHhDQSwweDQyLDB4MDddXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAyLDB4MDBdLFsweDQ4LDB4MjIsMHgxQiwweDk5LDB4MzcsMHg3NCwweDhBLDB4MjNdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAxLDB4MDBdLFsweERELDB4N0MsMHgwQiwweEJELDB4NjEsMHhGQSwweEZELDB4NTRdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4ODBdLFsweDJGLDB4QkMsMHgyOSwweDFBLDB4NTcsMHgwRCwweEI1LDB4QzRdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4NDBdLFsweEUwLDB4N0MsMHgzMCwweEQ3LDB4RTQsMHhFMiwweDZFLDB4MTJdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MjBdLFsweDA5LDB4NTMsMHhFMiwweDI1LDB4OEUsMHg4RSwweDkwLDB4QTFdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MTBdLFsweDVCLDB4NzEsMHgxQiwweEM0LDB4Q0UsMHhFQiwweEYyLDB4RUVdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDhdLFsweENDLDB4MDgsMHgzRiwweDFFLDB4NkQsMHg5RSwweDg1LDB4RjZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDRdLFsweEQyLDB4RkQsMHg4OCwweDY3LDB4RDUsMHgwRCwweDJELDB4RkVdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDJdLFsweDA2LDB4RTcsMHhFQSwweDIyLDB4Q0UsMHg5MiwweDcwLDB4OEZdXSxcclxuICAgICAgICAgICAgICAgICAgICAgW1sweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDFdLFsweDE2LDB4NkIsMHg0MCwweEI0LDB4NEEsMHhCQSwweDRCLDB4RDZdXV07XHJcblxyXG4gIHZhciByZXMgPSB0cnVlO1xyXG4gIHZhciBqID0gMDtcclxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICB2YXIgZGVzID0gbmV3IG9wZW5wZ3AuY3J5cHRvLmNpcGhlci5kZXMoa2V5KTtcclxuXHJcbiAgICB2YXIgZW5jciA9IHV0aWwuYmluMnN0cihkZXMuZW5jcnlwdCh0ZXN0dmVjdG9yc1tpXVswXSwga2V5KSk7XHJcbiAgICB2YXIgcmVzMiA9IGVuY3IgPT0gdXRpbC5iaW4yc3RyKHRlc3R2ZWN0b3JzW2ldWzFdKTtcclxuXHJcbiAgICByZXMgJj0gcmVzMjtcclxuXHJcbiAgICBpZiAoIXJlczIpIHtcclxuICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgdmVjdG9yIHdpdGggYmxvY2sgXCIgK1xyXG4gICAgICAgIHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMF0pICtcclxuICAgICAgICBcIiBhbmQga2V5IFwiICsgdXRpbC5oZXhzdHJkdW1wKGtleSkgK1xyXG4gICAgICAgIFwiIHNob3VsZCBiZSBcIiArIHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMV0pICsgXCIgIT0gXCIgK1xyXG4gICAgICAgIHV0aWwuaGV4aWR1bXAoZW5jciksXHJcbiAgICAgIGZhbHNlKTtcclxuICAgIGorKztcclxuICAgIH1cclxuICB9XHJcbiAgaWYgKHJlcykge1xyXG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiQWxsIDNERVMgRURFIHRlc3QgdmVjdG9ycyBjb21wbGV0ZWRcIiwgdHJ1ZSk7XHJcbiAgfVxyXG4gIHJldHVybiByZXN1bHQ7XHJcbn0pO1xyXG5cclxuXHJcbnVuaXQucmVnaXN0ZXIoXCJERVMgZW5jcnlwdC9kZWNyeXB0IHBhZGRpbmcgdGVzdHNcIiwgZnVuY3Rpb24gKCkge1xyXG4gICAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcclxuICAgICAgdXRpbCA9IG9wZW5wZ3AudXRpbDtcclxuXHJcbiAgICB2YXIgcmVzdWx0ID0gW107XHJcbiAgICB2YXIga2V5ID0gdXRpbC5iaW4yc3RyKFsweDAxLCAweDIzLCAweDQ1LCAweDY3LCAweDg5LCAweEFCLCAweENELCAweEVGXSk7XHJcbiAgICB2YXIgdGVzdHZlY3RvcnMgPSBuZXcgQXJyYXkoKTtcclxuICAgIHRlc3R2ZWN0b3JzWzBdID0gW1tbMHgwMV0sIFsweDI0LCAweEM3LCAweDRBLCAweDlBLCAweDc5LCAweDc1LCAweDRCLCAweEM3XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDAyLCAweDAzXSwgWzB4QTcsIDB4N0EsIDB4OUEsIDB4NTksIDB4OEEsIDB4ODYsIDB4ODUsIDB4QzVdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDMsIDB4MDQsIDB4MDVdLCBbMHgwMSwgMHhDRiwgMHhFQiwgMHg2QSwgMHg3NCwgMHg2MCwgMHhGNSwgMHgwMl1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNCwgMHgwNSwgMHgwNiwgMHgwN10sIFsweEE4LCAweEYwLCAweDNELCAweDU5LCAweEJBLCAweDZCLCAweDBFLCAweDc2XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA1LCAweDA2LCAweDA3LCAweDA4LCAweDA5XSwgWzB4ODYsIDB4NDAsIDB4MzMsIDB4NjEsIDB4M0YsIDB4NTUsIDB4NzMsIDB4NDldXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDYsIDB4MDcsIDB4MDgsIDB4MDksIDB4MEEsIDB4MEJdLCBbMHgxMywgMHgyMSwgMHgzRSwgMHgwRSwgMHhDRSwgMHgyQywgMHg5NCwgMHgwMV1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNywgMHgwOCwgMHgwOSwgMHgwQSwgMHgwQiwgMHgwQywgMHgwRF0sIFsweDMwLCAweDQ5LCAweDk3LCAweEMxLCAweERBLCAweEQ1LCAweDU5LCAweEE1XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA4LCAweDA5LCAweDBBLCAweDBCLCAweDBDLCAweDBELCAweDBFLCAweDBGXSwgWzB4ODMsIDB4MjUsIDB4NzksIDB4MDYsIDB4NTQsIDB4QTQsIDB4NDQsIDB4RDldXV07XHJcbiAgICB0ZXN0dmVjdG9yc1sxXSA9IFtbWzB4MDFdLCBbMHhGMiwgMHhBQiwgMHgxQywgMHg5RSwgMHg3MCwgMHg3RCwgMHhDQywgMHg5Ml1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwMiwgMHgwM10sIFsweDZCLCAweDRDLCAweDY3LCAweDI0LCAweDlGLCAweEI3LCAweDRELCAweEFDXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDAzLCAweDA0LCAweDA1XSwgWzB4NjgsIDB4OTUsIDB4QUIsIDB4QTgsIDB4RUEsIDB4NTMsIDB4MTMsIDB4MjNdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDQsIDB4MDUsIDB4MDYsIDB4MDddLCBbMHhDOCwgMHhERSwgMHg2MCwgMHg4RiwgMHhGNiwgMHgwOSwgMHg5MCwgMHhCNV1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNSwgMHgwNiwgMHgwNywgMHgwOCwgMHgwOV0sIFsweDE5LCAweDEzLCAweDUwLCAweDIwLCAweDcwLCAweDQwLCAweDJFLCAweDA5XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA2LCAweDA3LCAweDA4LCAweDA5LCAweDBBLCAweDBCXSwgWzB4QTgsIDB4MjMsIDB4NDAsIDB4QzYsIDB4MTcsIDB4QTYsIDB4MzEsIDB4NEFdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDcsIDB4MDgsIDB4MDksIDB4MEEsIDB4MEIsIDB4MEMsIDB4MERdLCBbMHgzNiwgMHg2MiwgMHhGMiwgMHg5OSwgMHg2OCwgMHhENCwgMHhCRiwgMHg3Q11dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwOCwgMHgwOSwgMHgwQSwgMHgwQiwgMHgwQywgMHgwRCwgMHgwRSwgMHgwRl0sIFsweDgzLCAweDI1LCAweDc5LCAweDA2LCAweDU0LCAweEE0LCAweDQ0LCAweEQ5LCAweDA4LCAweDZGLCAweDlBLCAweDFELCAweDc0LCAweEM5LCAweDRELCAweDRFXV1dO1xyXG4gICAgdGVzdHZlY3RvcnNbMl0gPSBbW1sweDAxXSwgWzB4ODMsIDB4NjgsIDB4RTQsIDB4OUMsIDB4ODQsIDB4Q0MsIDB4Q0IsIDB4RjBdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDIsIDB4MDNdLCBbMHhCQiwgMHhBOCwgMHgwQiwgMHg2NiwgMHgxQiwgMHg2MiwgMHhDNCwgMHhDOF1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwMywgMHgwNCwgMHgwNV0sIFsweDlBLCAweEQ3LCAweDVBLCAweDI0LCAweEZELCAweDNGLCAweEJGLCAweDIyXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA0LCAweDA1LCAweDA2LCAweDA3XSwgWzB4MTQsIDB4NEUsIDB4NjgsIDB4NkQsIDB4MkUsIDB4QzEsIDB4QjcsIDB4NTJdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDUsIDB4MDYsIDB4MDcsIDB4MDgsIDB4MDldLCBbMHgxMiwgMHgwQSwgMHg1MSwgMHgwOCwgMHhGOSwgMHhBMywgMHgwMywgMHg3NF1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNiwgMHgwNywgMHgwOCwgMHgwOSwgMHgwQSwgMHgwQl0sIFsweEIyLCAweDA3LCAweEQxLCAweDA1LCAweEY2LCAweDY3LCAweEFGLCAweEJBXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA3LCAweDA4LCAweDA5LCAweDBBLCAweDBCLCAweDBDLCAweDBEXSwgWzB4Q0EsIDB4NTksIDB4NjEsIDB4M0EsIDB4ODMsIDB4MjMsIDB4MjYsIDB4RERdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDgsIDB4MDksIDB4MEEsIDB4MEIsIDB4MEMsIDB4MEQsIDB4MEUsIDB4MEZdLCBbMHg4MywgMHgyNSwgMHg3OSwgMHgwNiwgMHg1NCwgMHhBNCwgMHg0NCwgMHhEOV1dXTtcclxuXHJcbiAgICB2YXIgZGVzID0gbmV3IG9wZW5wZ3AuY3J5cHRvLmNpcGhlci5vcmlnaW5hbERlcyhrZXkpO1xyXG5cclxuICAgIHZhciByZXMgPSB0cnVlO1xyXG4gICAgdmFyIGogPSAwO1xyXG5cclxuICAgIGZvciAodmFyIHBhZGRpbmcgPSAwOyBwYWRkaW5nIDwgMzsgcGFkZGluZysrKSB7XHJcbiAgICAgICAgdmFyIHRoaXNWZWN0b3JTZXQgPSB0ZXN0dmVjdG9yc1twYWRkaW5nXTtcclxuXHJcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzVmVjdG9yU2V0Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIHZhciBlbmNyeXB0ZWQgPSBkZXMuZW5jcnlwdCh0aGlzVmVjdG9yU2V0W2ldWzBdLCBwYWRkaW5nKTtcclxuICAgICAgICAgICAgdmFyIGRlY3J5cHRlZCA9IGRlcy5kZWNyeXB0KGVuY3J5cHRlZCwgcGFkZGluZyk7XHJcblxyXG4gICAgICAgICAgICB2YXIgcmVzMiA9ICh1dGlsLmJpbjJzdHIoZW5jcnlwdGVkKSA9PSB1dGlsLmJpbjJzdHIodGhpc1ZlY3RvclNldFtpXVsxXSkpO1xyXG4gICAgICAgICAgICB2YXIgcmVzMyA9ICh1dGlsLmJpbjJzdHIoZGVjcnlwdGVkKSA9PSB1dGlsLmJpbjJzdHIodGhpc1ZlY3RvclNldFtpXVswXSkpO1xyXG4gICAgICAgICAgICByZXMgJj0gcmVzMjtcclxuICAgICAgICAgICAgcmVzICY9IHJlczM7XHJcbiAgICAgICAgICAgIGlmICghcmVzMiB8fCAhcmVzMykge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFxyXG4gICAgICAgICAgICAgICAgICAgIFwiVGVzdGluZyB2ZWN0b3Igd2l0aCBibG9jayBbXCIgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB1dGlsLmhleGlkdW1wKHRoaXNWZWN0b3JTZXRbaV1bMF0pICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgXCJdIGFuZCBrZXkgW1wiICsgdXRpbC5oZXhzdHJkdW1wKGtleSkgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcIl0gYW5kIHBhZGRpbmcgW1wiICsgcGFkZGluZyArXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiXSBzaG91bGQgYmUgXCIgKyB1dGlsLmhleGlkdW1wKHRoaXNWZWN0b3JTZXRbaV1bMV0pICsgXCIgLSBBY3R1YWxseSBbRU5DOlwiICsgdXRpbC5oZXhpZHVtcChlbmNyeXB0ZWQpICsgXCIsIERFQzpcIiArIHV0aWwuaGV4aWR1bXAoZGVjcnlwdGVkKSArIFwiXVwiLFxyXG4gICAgICAgICAgICAgICAgICAgIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIGorKztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChyZXMpIHtcclxuICAgICAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCJBbGwgREVTIHRlc3QgdmVjdG9ycyBjb21wbGV0ZWRcIiwgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzdWx0O1xyXG59KTtcclxuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJUd29maXNoIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBodHRwOi8vd3d3LnNjaG5laWVyLmNvbS9jb2RlL2VjYl9pdmFsLnR4dFwiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcbiAgICB1dGlsID0gb3BlbnBncC51dGlsO1xuXG4gIGZ1bmN0aW9uIFRGZW5jcnlwdChibG9jaywga2V5KSB7XG4gICAgdmFyIHRmID0gbmV3IG9wZW5wZ3AuY3J5cHRvLmNpcGhlci50d29maXNoKGtleSk7XG5cbiAgICByZXR1cm4gdGYuZW5jcnlwdChibG9jayk7XG4gIH1cblxuXG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIHN0YXJ0ID0gWzAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMF07XG4gIHZhciBzdGFydF9zaG9ydCA9IFswLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXTtcbiAgdmFyIHRlc3R2ZWN0b3JzID0gW1sweDU3LDB4RkYsMHg3MywweDlELDB4NEQsMHhDOSwweDJDLDB4MUIsMHhENywweEZDLDB4MDEsMHg3MCwweDBDLDB4QzgsMHgyMSwweDZGXSxcbiAgICAgICAgICAgIFsweEQ0LDB4M0IsMHhCNywweDU1LDB4NkUsMHhBMywweDJFLDB4NDYsMHhGMiwweEEyLDB4ODIsMHhCNywweEQ0LDB4NUIsMHg0RSwweDBEXSxcbiAgICAgICAgICAgIFsweDkwLDB4QUYsMHhFOSwweDFCLDB4QjIsMHg4OCwweDU0LDB4NEYsMHgyQywweDMyLDB4REMsMHgyMywweDlCLDB4MjYsMHgzNSwweEU2XSxcbiAgICAgICAgICAgIFsweDZDLDB4QjQsMHg1NiwweDFDLDB4NDAsMHhCRiwweDBBLDB4OTcsMHgwNSwweDkzLDB4MUMsMHhCNiwweEQ0LDB4MDgsMHhFNywweEZBXSxcbiAgICAgICAgICAgIFsweDMwLDB4NTksMHhENiwweEQ2LDB4MTcsMHg1MywweEI5LDB4NTgsMHhEOSwweDJGLDB4NDcsMHg4MSwweEM4LDB4NjQsMHgwRSwweDU4XSxcbiAgICAgICAgICAgIFsweEU2LDB4OTQsMHg2NSwweDc3LDB4MDUsMHgwNSwweEQ3LDB4RjgsMHgwRSwweEY2LDB4OEMsMHhBMywweDhBLDB4QjMsMHhBMywweEQ2XSxcbiAgICAgICAgICAgIFsweDVBLDB4QjYsMHg3QSwweDVGLDB4ODUsMHgzOSwweEE0LDB4QTUsMHhGRCwweDlGLDB4MDMsMHg3MywweEJBLDB4NDYsMHgzNCwweDY2XSxcbiAgICAgICAgICAgIFsweERDLDB4MDksMHg2QiwweENELDB4OTksMHhGQywweDcyLDB4RjcsMHg5OSwweDM2LDB4RDQsMHhDNywweDQ4LDB4RTcsMHg1QSwweEY3XSxcbiAgICAgICAgICAgIFsweEM1LDB4QTMsMHhFNywweENFLDB4RTAsMHhGMSwweEI3LDB4MjYsMHgwNSwweDI4LDB4QTYsMHg4RiwweEI0LDB4RUEsMHgwNSwweEYyXSxcbiAgICAgICAgICAgIFsweDQzLDB4RDUsMHhDRSwweEMzLDB4MjcsMHhCMiwweDRBLDB4QjksMHgwQSwweEQzLDB4NEEsMHg3OSwweEQwLDB4NDYsMHg5MSwweDUxXV07XG4gIHRlc3R2ZWN0b3JzWzQ3XSA9ICBbMHg0MywweDEwLDB4NTgsMHhGNCwweERCLDB4QzcsMHhGNywweDM0LDB4REEsMHg0RiwweDAyLDB4RjAsMHg0QywweEM0LDB4RjQsMHg1OV07XG4gIHRlc3R2ZWN0b3JzWzQ4XSA9ICBbMHgzNywweEZFLDB4MjYsMHhGRiwweDFDLDB4RjYsMHg2MSwweDc1LDB4RjUsMHhERCwweEY0LDB4QzMsMHgzQiwweDk3LDB4QTIsMHgwNV07XG4gIHZhciByZXMgPSB0cnVlO1xuICB2YXIgaiA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgNDk7IGkrKykge1xuICAgIHZhciByZXMyID0gZmFsc2U7XG4gICAgdmFyIGJsaywga2V5LCBjdDtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgYmxrID0gc3RhcnRfc2hvcnQ7XG4gICAgICBrZXkgPSB1dGlsLmJpbjJzdHIoc3RhcnQpO1xuICAgICAgY3QgPSB0ZXN0dmVjdG9yc1swXTtcbiAgICAgIHJlczIgPSAodXRpbC5iaW4yc3RyKFRGZW5jcnlwdChibGssa2V5KSkgPT0gdXRpbC5iaW4yc3RyKGN0KSk7XG4gICAgfSBlbHNlIGlmIChpID09PSAxKSB7XG4gICAgICBibGsgPSB0ZXN0dmVjdG9yc1swXTtcbiAgICAgIGtleSA9IHV0aWwuYmluMnN0cihzdGFydCk7XG4gICAgICBjdCA9IHRlc3R2ZWN0b3JzWzFdO1xuICAgICAgcmVzMiA9ICh1dGlsLmJpbjJzdHIoVEZlbmNyeXB0KGJsayxrZXkpKSA9PSB1dGlsLmJpbjJzdHIoY3QpKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IDIpIHtcbiAgICAgIGJsayA9IHRlc3R2ZWN0b3JzW2ktMV07XG4gICAgICBrZXkgPSB1dGlsLmJpbjJzdHIodGVzdHZlY3RvcnNbaS0yXS5jb25jYXQoc3RhcnRfc2hvcnQpKTtcbiAgICAgIGN0ID0gdGVzdHZlY3RvcnNbaV07XG4gICAgICByZXMyID0gKHV0aWwuYmluMnN0cihURmVuY3J5cHQoYmxrLGtleSkpID09IHV0aWwuYmluMnN0cihjdCkpO1xuICAgIH0gZWxzZSBpZiAoaSA8IDEwIHx8IGkgPiA0Nikge1xuICAgICAgYmxrID0gdGVzdHZlY3RvcnNbaS0xXTtcbiAgICAgIGtleSA9IHV0aWwuYmluMnN0cih0ZXN0dmVjdG9yc1tpLTJdLmNvbmNhdCh0ZXN0dmVjdG9yc1tpLTNdKSk7XG4gICAgICBjdCA9IHRlc3R2ZWN0b3JzW2ldO1xuICAgICAgcmVzMiA9ICh1dGlsLmJpbjJzdHIoVEZlbmNyeXB0KGJsayxrZXkpKSA9PSB1dGlsLmJpbjJzdHIoY3QpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGVzdHZlY3RvcnNbaV0gPSBURmVuY3J5cHQodGVzdHZlY3RvcnNbaS0xXSx1dGlsLmJpbjJzdHIodGVzdHZlY3RvcnNbaS0yXS5jb25jYXQodGVzdHZlY3RvcnNbaS0zXSkpKTtcbiAgICAgIHJlczIgPSB0cnVlO1xuICAgIH1cbiAgICByZXMgJj0gcmVzMjtcbiAgICBpZiAoIXJlczIpIHtcbiAgICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgdmVjdG9yIHdpdGggYmxvY2sgXCIrdXRpbC5oZXhpZHVtcChibGspK1wiIHdpdGgga2V5IFwiKyB1dGlsLmhleHN0cmR1bXAoa2V5KSArXCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAoY3QpK1wiIGJ1dCBpcyBcIit1dGlsLmhleGlkdW1wKFRGZW5jcnlwdChibGssa2V5KSksIGZhbHNlKTtcbiAgICAgIGorKztcbiAgICB9XG4gIH1cbiAgaWYgKHJlcykge1xuICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIjQ5IHRlc3QgdmVjdG9ycyBjb21wbGV0ZWRcIiwgdHJ1ZSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJNRDUgdGVzdCB3aXRoIHRlc3QgdmVjdG9ycyBmcm9tIFJGQyAxMzIxXCIsIGZ1bmN0aW9uKCkge1xuXHR2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLy4uLycpLFxuXHRcdHV0aWwgPSBvcGVucGdwLnV0aWwsXG5cdFx0TUQ1ID0gb3BlbnBncC5jcnlwdG8uaGFzaC5tZDU7XG5cblx0dmFyIHJlc3VsdCA9IG5ldyBBcnJheSgpO1xuXHRyZXN1bHRbMF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJNRDUgKFxcXCJcXFwiKSA9IGQ0MWQ4Y2Q5OGYwMGIyMDRlOTgwMDk5OGVjZjg0MjdlXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoTUQ1KFwiXCIpKSA9PSBcImQ0MWQ4Y2Q5OGYwMGIyMDRlOTgwMDk5OGVjZjg0MjdlXCIpO1xuXHRyZXN1bHRbMV0gPSBuZXcgdW5pdC5yZXN1bHQoXCJNRDUgKFxcXCJhXFxcIikgPSAwY2MxNzViOWMwZjFiNmE4MzFjMzk5ZTI2OTc3MjY2MVwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKE1ENSAoXCJhYmNcIikpID09IFwiOTAwMTUwOTgzY2QyNGZiMGQ2OTYzZjdkMjhlMTdmNzJcIik7XG5cdHJlc3VsdFsyXSA9IG5ldyB1bml0LnJlc3VsdChcIk1ENSAoXFxcIm1lc3NhZ2UgZGlnZXN0XFxcIikgPSBmOTZiNjk3ZDdjYjc5MzhkNTI1YTJmMzFhYWYxNjFkMFwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKE1ENSAoXCJtZXNzYWdlIGRpZ2VzdFwiKSkgPT0gXCJmOTZiNjk3ZDdjYjc5MzhkNTI1YTJmMzFhYWYxNjFkMFwiKTtcblx0cmVzdWx0WzNdID0gbmV3IHVuaXQucmVzdWx0KFwiTUQ1IChcXFwiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpcXFwiKSA9IGMzZmNkM2Q3NjE5MmU0MDA3ZGZiNDk2Y2NhNjdlMTNiXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoTUQ1IChcImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XCIpKSA9PSBcImMzZmNkM2Q3NjE5MmU0MDA3ZGZiNDk2Y2NhNjdlMTNiXCIpO1xuXHRyZXN1bHRbNF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJNRDUgKFxcXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OVxcXCIpID0gZDE3NGFiOThkMjc3ZDlmNWE1NjExYzJjOWY0MTlkOWZcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChNRDUgKFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODlcIikpID09IFwiZDE3NGFiOThkMjc3ZDlmNWE1NjExYzJjOWY0MTlkOWZcIik7XG5cdHJlc3VsdFs1XSA9IG5ldyB1bml0LnJlc3VsdChcIk1ENSAoXFxcIjEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwXFxcIikgPSA1N2VkZjRhMjJiZTNjOTU1YWM0OWRhMmUyMTA3YjY3YVwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKE1ENSAoXCIxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MFwiKSkgPT0gXCI1N2VkZjRhMjJiZTNjOTU1YWM0OWRhMmUyMTA3YjY3YVwiKTtcblx0cmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJSSVBFLU1EIDE2MCBiaXRzIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBodHRwOi8vaG9tZXMuZXNhdC5rdWxldXZlbi5iZS9+Ym9zc2VsYWUvcmlwZW1kMTYwLmh0bWxcIiwgZnVuY3Rpb24oKSB7XG5cblx0dmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcblx0XHR1dGlsID0gb3BlbnBncC51dGlsLFxuXHRcdFJNRHN0cmluZyA9IG9wZW5wZ3AuY3J5cHRvLmhhc2gucmlwZW1kO1xuXG5cdHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblx0cmVzdWx0WzBdID0gbmV3IHVuaXQucmVzdWx0KFwiUk1Ec3RyaW5nIChcXFwiXFxcIikgPSA5YzExODVhNWM1ZTlmYzU0NjEyODA4OTc3ZWU4ZjU0OGIyMjU4ZDMxXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoUk1Ec3RyaW5nKFwiXCIpKSA9PSBcIjljMTE4NWE1YzVlOWZjNTQ2MTI4MDg5NzdlZThmNTQ4YjIyNThkMzFcIik7XG5cdHJlc3VsdFsxXSA9IG5ldyB1bml0LnJlc3VsdChcIlJNRHN0cmluZyAoXFxcImFcXFwiKSA9IDBiZGM5ZDJkMjU2YjNlZTlkYWFlMzQ3YmU2ZjRkYzgzNWE0NjdmZmVcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChSTURzdHJpbmcoXCJhXCIpKSA9PSBcIjBiZGM5ZDJkMjU2YjNlZTlkYWFlMzQ3YmU2ZjRkYzgzNWE0NjdmZmVcIik7XG5cdHJlc3VsdFsyXSA9IG5ldyB1bml0LnJlc3VsdChcIlJNRHN0cmluZyAoXFxcImFiY1xcXCIpID0gOGViMjA4ZjdlMDVkOTg3YTliMDQ0YThlOThjNmIwODdmMTVhMGJmY1wiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKFJNRHN0cmluZyhcImFiY1wiKSkgPT0gXCI4ZWIyMDhmN2UwNWQ5ODdhOWIwNDRhOGU5OGM2YjA4N2YxNWEwYmZjXCIpO1xuXHRyZXN1bHRbM10gPSBuZXcgdW5pdC5yZXN1bHQoXCJSTURzdHJpbmcgKFxcXCJtZXNzYWdlIGRpZ2VzdFxcXCIpID0gNWQwNjg5ZWY0OWQyZmFlNTcyYjg4MWIxMjNhODVmZmEyMTU5NWYzNlwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKFJNRHN0cmluZyhcIm1lc3NhZ2UgZGlnZXN0XCIpKSA9PSBcIjVkMDY4OWVmNDlkMmZhZTU3MmI4ODFiMTIzYTg1ZmZhMjE1OTVmMzZcIik7XG5cdHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vLi4vdW5pdC5qcycpO1xuXG5cbnVuaXQucmVnaXN0ZXIoXCJTSEEqIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBOSVNUIEZJUFMgMTgwLTJcIiwgZnVuY3Rpb24oKSB7XG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG5cdFx0dXRpbCA9IG9wZW5wZ3AudXRpbCxcblx0XHRoYXNoID0gb3BlbnBncC5jcnlwdG8uaGFzaDtcblxuXHR2YXIgcmVzdWx0ID0gbmV3IEFycmF5KCk7XG5cdFxuXHRyZXN1bHRbMF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEExIC0gYTk5OTNlMzY0NzA2ODE2YWJhM2UyNTcxNzg1MGMyNmM5Y2QwZDg5ZCA9IGhhc2guc2hhMShcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcImE5OTkzZTM2NDcwNjgxNmFiYTNlMjU3MTc4NTBjMjZjOWNkMGQ4OWRcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGExKFwiYWJjXCIpKSk7XG5cdHJlc3VsdFsxXSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTEgLSA4NDk4M2U0NDFjM2JkMjZlYmFhZTRhYTFmOTUxMjllNWU1NDY3MGYxID0gaGFzaC5zaGExKFxcXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVxcXCIpIFwiLFxuXHRcdFx0XCI4NDk4M2U0NDFjM2JkMjZlYmFhZTRhYTFmOTUxMjllNWU1NDY3MGYxXCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhMShcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXCIpKSk7XG5cdHJlc3VsdFsyXSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTIyNCAtIDIzMDk3ZDIyMzQwNWQ4MjI4NjQyYTQ3N2JkYTI1NWIzMmFhZGJjZTRiZGEwYjNmN2UzNmM5ZGE3ID0gaGFzaC5zaGEyMjQoXFxcImFiY1xcXCIpIFwiLFxuXHRcdFx0XCIyMzA5N2QyMjM0MDVkODIyODY0MmE0NzdiZGEyNTViMzJhYWRiY2U0YmRhMGIzZjdlMzZjOWRhN1wiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTIyNChcImFiY1wiKSkpO1xuXHRyZXN1bHRbM10gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEyMjQgLSA3NTM4OGIxNjUxMjc3NmNjNWRiYTVkYTFmZDg5MDE1MGIwYzY0NTVjYjRmNThiMTk1MjUyMjUyNSA9IGhhc2guc2hhMjI0KFxcXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVxcXCIpIFwiLFxuXHRcdFx0XCI3NTM4OGIxNjUxMjc3NmNjNWRiYTVkYTFmZDg5MDE1MGIwYzY0NTVjYjRmNThiMTk1MjUyMjUyNVwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTIyNChcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXCIpKSk7XG5cdHJlc3VsdFs0XSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTI1NiAtIGJhNzgxNmJmOGYwMWNmZWE0MTQxNDBkZTVkYWUyMjIzYjAwMzYxYTM5NjE3N2E5Y2I0MTBmZjYxZjIwMDE1YWQgPSBoYXNoLnNoYTI1NihcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcImJhNzgxNmJmOGYwMWNmZWE0MTQxNDBkZTVkYWUyMjIzYjAwMzYxYTM5NjE3N2E5Y2I0MTBmZjYxZjIwMDE1YWRcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGEyNTYoXCJhYmNcIikpKTtcblx0cmVzdWx0WzVdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMjU2IC0gMjQ4ZDZhNjFkMjA2MzhiOGU1YzAyNjkzMGMzZTYwMzlhMzNjZTQ1OTY0ZmYyMTY3ZjZlY2VkZDQxOWRiMDZjMSA9IGhhc2guc2hhMjU2KFxcXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVxcXCIpIFwiLFxuXHRcdFx0XCIyNDhkNmE2MWQyMDYzOGI4ZTVjMDI2OTMwYzNlNjAzOWEzM2NlNDU5NjRmZjIxNjdmNmVjZWRkNDE5ZGIwNmMxXCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhMjU2KFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcIikpKTtcblx0cmVzdWx0WzZdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMzg0IC0gY2IwMDc1M2Y0NWEzNWU4YmI1YTAzZDY5OWFjNjUwMDcyNzJjMzJhYjBlZGVkMTYzMWE4YjYwNWE0M2ZmNWJlZDgwODYwNzJiYTFlN2NjMjM1OGJhZWNhMTM0YzgyNWE3ID0gaGFzaC5zaGEzODQoXFxcImFiY1xcXCIpIFwiLFxuXHRcdFx0XCJjYjAwNzUzZjQ1YTM1ZThiYjVhMDNkNjk5YWM2NTAwNzI3MmMzMmFiMGVkZWQxNjMxYThiNjA1YTQzZmY1YmVkODA4NjA3MmJhMWU3Y2MyMzU4YmFlY2ExMzRjODI1YTdcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGEzODQoXCJhYmNcIikpKTtcblx0cmVzdWx0WzddID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMzg0IC0gMzM5MWZkZGRmYzhkYzczOTM3MDdhNjViMWI0NzA5Mzk3Y2Y4YjFkMTYyYWYwNWFiZmU4ZjQ1MGRlNWYzNmJjNmIwNDU1YTg1MjBiYzRlNmY1ZmU5NWIxZmUzYzg0NTJiID0gc3RyMzg0KFxcXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVxcXCIpIFwiLFxuXHRcdFx0XCIzMzkxZmRkZGZjOGRjNzM5MzcwN2E2NWIxYjQ3MDkzOTdjZjhiMWQxNjJhZjA1YWJmZThmNDUwZGU1ZjM2YmM2YjA0NTVhODUyMGJjNGU2ZjVmZTk1YjFmZTNjODQ1MmJcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGEzODQoXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVwiKSkpO1x0XHRcdFx0XHRcblx0cmVzdWx0WzhdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBNTEyIC0gZGRhZjM1YTE5MzYxN2FiYWNjNDE3MzQ5YWUyMDQxMzExMmU2ZmE0ZTg5YTk3ZWEyMGE5ZWVlZTY0YjU1ZDM5YTIxOTI5OTJhMjc0ZmMxYTgzNmJhM2MyM2EzZmVlYmJkNDU0ZDQ0MjM2NDNjZTgwZTJhOWFjOTRmYTU0Y2E0OWYgPSBoYXNoLnNoYTUxMihcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcImRkYWYzNWExOTM2MTdhYmFjYzQxNzM0OWFlMjA0MTMxMTJlNmZhNGU4OWE5N2VhMjBhOWVlZWU2NGI1NWQzOWEyMTkyOTkyYTI3NGZjMWE4MzZiYTNjMjNhM2ZlZWJiZDQ1NGQ0NDIzNjQzY2U4MGUyYTlhYzk0ZmE1NGNhNDlmXCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhNTEyKFwiYWJjXCIpKSk7XG5cdHJlc3VsdFs5XSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTUxMiAtIDIwNGE4ZmM2ZGRhODJmMGEwY2VkN2JlYjhlMDhhNDE2NTdjMTZlZjQ2OGIyMjhhODI3OWJlMzMxYTcwM2MzMzU5NmZkMTVjMTNiMWIwN2Y5YWExZDNiZWE1Nzc4OWNhMDMxYWQ4NWM3YTcxZGQ3MDM1NGVjNjMxMjM4Y2EzNDQ1ID0gaGFzaC5zaGE1MTIoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjIwNGE4ZmM2ZGRhODJmMGEwY2VkN2JlYjhlMDhhNDE2NTdjMTZlZjQ2OGIyMjhhODI3OWJlMzMxYTcwM2MzMzU5NmZkMTVjMTNiMWIwN2Y5YWExZDNiZWE1Nzc4OWNhMDMxYWQ4NWM3YTcxZGQ3MDM1NGVjNjMxMjM4Y2EzNDQ1XCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhNTEyKFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcIikpKTtcdFx0XHRcdFx0XG5cdHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vdW5pdC5qcycpO1xuXG51bml0LnJlZ2lzdGVyKFwiRnVuY3Rpb25hbCB0ZXN0aW5nIG9mIG9wZW5wZ3AuY3J5cHRvLiogbWV0aG9kc1wiLCBmdW5jdGlvbigpIHtcblx0dmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8nKTtcbiAgdmFyIHV0aWwgPSBvcGVucGdwLnV0aWw7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIFJTQXB1Yk1QSXN0cnMgPSBbXG4gICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwOCwweDAwLDB4YWMsMHgxNSwweGIzLDB4ZDYsMHhkMiwweDBmLDB4ZjAsMHg3YSwweGRkLDB4MjEsMHhiNyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGJmLDB4NjEsMHhmYSwweGNhLDB4OTMsMHg4NiwweGM4LDB4NTUsMHg1YSwweDRiLDB4YTYsMHhhNCwweDFhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NjAsMHhhMiwweDNhLDB4MzcsMHgwNiwweDA4LDB4ZDgsMHgxNSwweDhlLDB4ODUsMHg0NSwweGFhLDB4YjcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxZCwweDdiLDB4MGIsMHg3MywweDk0LDB4NTUsMHgwYywweDVjLDB4ZWMsMHhjMCwweDIyLDB4NGIsMHhhMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDY0LDB4MjAsMHg3ZCwweDRkLDB4YTgsMHg5NiwweDFhLDB4NjQsMHgzOCwweDkzLDB4Y2QsMHhlYywweDczLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NWQsMHhmOSwweDg5LDB4ODgsMHgyNCwweDNkLDB4NDgsMHhmZiwweDNiLDB4ODcsMHg2MiwweGQwLDB4ODQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhlYSwweGZmLDB4MzksMHhiNSwweDI3LDB4NzAsMHhlYSwweDRhLDB4YjIsMHgyZSwweDlkLDB4ZjEsMHg3YyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDIzLDB4ZWMsMHhmNCwweDVlLDB4ZWEsMHg2MSwweDNkLDB4ZTUsMHhkOCwweDBkLDB4ZjksMHg1OSwweDZkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MjgsMHgwMCwweGViLDB4Y2IsMHhjOSwweDU1LDB4MDAsMHg3MiwweDMwLDB4MWYsMHg2NSwweDlkLDB4ZDYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxNywweDU4LDB4NWYsMHhhNiwweDRhLDB4YTAsMHhkZCwweGUxLDB4NzYsMHhmMiwweGVmLDB4MjEsMHg5ZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDg0LDB4ZmMsMHhhYSwweDViLDB4NTIsMHg2ZSwweGMxLDB4YTIsMHhiOSwweGJkLDB4YjksMHhmNCwweDllLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NDksMHg5MiwweGYyLDB4YWYsMHg1NywweDg2LDB4ZjIsMHhlZiwweDcwLDB4YmYsMHg1MSwweDQwLDB4ZmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhiZiwweDU2LDB4NTEsMHhlOCwweDJjLDB4YTIsMHg0ZiwweGY4LDB4YTQsMHhkNywweDM2LDB4MTgsMHg4NSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGNlLDB4MDksMHgwZCwweGJjLDB4OGQsMHg2NSwweDVlLDB4OGEsMHgxZCwweDk4LDB4YjAsMHg0ZCwweDlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YzEsMHhjZiwweDgyLDB4ZTEsMHhiNywweDQzLDB4NWQsMHg1YSwweDcyLDB4Y2QsMHg1NSwweGQyLDB4ZmYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhiMSwweGI0LDB4NzgsMHhiZiwweGExLDB4N2QsMHhhYywweGQ5LDB4MWIsMHhjNCwweGZhLDB4MzksMHgzNCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDkyLDB4MDksMHhmOSwweDA4LDB4MmEsMHg2YiwweDlkLDB4MTQsMHg1NiwweDEyLDB4NGMsMHhlOSwweGE2LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MjksMHhjMSwweGYzLDB4YTksMHgwYiwweGZjLDB4MzEsMHg3NSwweDU4LDB4NzQsMHgyYSwweDg4LDB4YWYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhlZSwweGM5LDB4YTQsMHhjZCwweDE1LDB4ZGMsMHgxYiwweDhkLDB4NjQsMHhjMSwweDM2LDB4MTcsMHhjNCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDhkLDB4NWUsMHg5OSwweDdhLDB4NWIsMHg5ZiwweDM5LDB4ZDAsMHgwMCwweDZlLDB4ZjldKSxcbiAgICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDAwLDB4MTEsMHgwMSwweDAwLDB4MDFdKV07XG4gIHZhciBSU0FzZWNNUElzdHJzID0gW1xuICAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDcsMHhmZSwweDIzLDB4ZmYsMHhjZSwweDQ1LDB4NmMsMHg2MCwweDY1LDB4NDAsMHg2ZSwweGFlLDB4MzUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxMCwweDU2LDB4NjAsMHhlZSwweGFiLDB4ZmEsMHgxMCwweDQyLDB4YmEsMHhjNywweDA0LDB4YWYsMHg2MyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGNkLDB4M2YsMHg2MiwweGNhLDB4NGIsMHhmYSwweGUxLDB4YTksMHg3MCwweGNkLDB4MzQsMHg4YiwweGM4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MGUsMHhlNCwweGM0LDB4YmEsMHg4MywweDE3LDB4NWYsMHhhNCwweGI4LDB4ZWEsMHg2MCwweGMyLDB4NGQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg5YSwweGYyLDB4YTksMHgwMywweGViLDB4ZjYsMHhhYSwweGMyLDB4YjgsMHg4YiwweDQzLDB4MTIsMHhlOSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGY3LDB4ODgsMHhkMiwweDVhLDB4YTYsMHhhYSwweDIzLDB4NzEsMHgzMSwweDc0LDB4ZGIsMHgxOSwweDIwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MTUsMHg0MSwweDFiLDB4NDMsMHg2OCwweDYyLDB4ZDgsMHhjMCwweDkzLDB4OTEsMHhlOCwweGZjLDB4YjEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhhOSwweDlhLDB4NTIsMHg2YywweGUwLDB4YmYsMHg0MywweDAxLDB4YTgsMHgzNywweDE0LDB4MjgsMHhiZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDBiLDB4MTUsMHg1NiwweDNlLDB4YTUsMHg3OSwweGEwLDB4YzQsMHg0MiwweDg4LDB4ZWUsMHhlYiwweDFiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZjQsMHg3YSwweDRhLDB4NTgsMHgzMSwweDU4LDB4ODEsMHhkMiwweDNlLDB4ZGUsMHgwNywweDY0LDB4OTIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhmMCwweDYwLDB4ZDMsMHg5YSwweDI5LDB4Y2EsMHhjNiwweDY3LDB4NzUsMHgwNywweGNhLDB4OTIsMHgzOSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDU2LDB4ZjYsMHgxMSwweDg0LDB4YmEsMHg2ZCwweDRiLDB4ZTYsMHg2ZiwweDY2LDB4YzIsMHgxNywweGViLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NDYsMHg2OSwweDFjLDB4YmIsMHhkZiwweGMwLDB4MzgsMHgwMCwweGQ2LDB4MDEsMHhlNiwweDcwLDB4OWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0YiwweDliLDB4NzAsMHhlZCwweDVjLDB4YjgsMHhjZiwweGU4LDB4NjgsMHg3MSwweGJlLDB4MjQsMHg2ZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGIxLDB4YTMsMHgxMywweGNjLDB4ZjEsMHhiYywweDY3LDB4ZGMsMHhlMCwweDY5LDB4MDksMHg4MiwweDNjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4M2IsMHgwZiwweDE0LDB4OTgsMHg0OCwweDMwLDB4YjIsMHg3MCwweGM2LDB4OWUsMHhmYSwweDQ2LDB4OGYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhmMSwweGMwLDB4NjUsMHg4ZSwweGM2LDB4YWUsMHhkYywweDQ3LDB4OTEsMHgxMywweDFlLDB4ZDYsMHg0YSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGYyLDB4YWQsMHhkYSwweGMyLDB4YzcsMHgzOSwweDc4LDB4OTksMHhkZSwweDU3LDB4MTQsMHg0NSwweDdmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MzIsMHgzOCwweGEzLDB4NDQsMHgwZiwweGU3LDB4MzksMHg0YywweDZmLDB4MGYsMHgzMiwweDdlLDB4ZjEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg1YywweDg0LDB4OTcsMHhkZCwweGEwLDB4MGMsMHg4NywweDY2LDB4N2QsMHg3NSwweDc5XSksXG4gICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwNCwweDAwLDB4YzIsMHhiYywweDcxLDB4ZjcsMHg0MSwweDRhLDB4MDksMHg2NiwweDcwLDB4MDIsMHg2OCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDhiLDB4ZWIsMHhlMiwweDM0LDB4ZDEsMHgxMiwweDgzLDB4OTMsMHg3NSwweGU5LDB4NzEsMHgzMiwweGUyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZWQsMHgxOCwweDZmLDB4OGUsMHgzYSwweGZmLDB4MjIsMHg3MCwweDI4LDB4MDEsMHhiZiwweDRhLDB4MzksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0MSwweGJiLDB4M2MsMHg0YSwweGJjLDB4YjgsMHgxMywweGZjLDB4MTQsMHhmNiwweDcxLDB4YTEsMHg0NCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDFjLDB4MDIsMHhhMSwweDczLDB4ODEsMHhjYywweGEwLDB4MzUsMHgwMiwweDNlLDB4OTcsMHhiNSwweGM0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4OTQsMHgzMywweGYxLDB4ZDEsMHhkZiwweDE0LDB4M2YsMHhmYiwweDhmLDB4YjksMHg3NSwweDcwLDB4ZGMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg3NCwweDNmLDB4MDcsMHgzNSwweDhmLDB4NTMsMHhhYSwweGIyLDB4ZDYsMHg4OCwweDUxLDB4NzEsMHg0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDAxLDB4MjQsMHhlYywweDdkLDB4Y2EsMHhmNiwweGEyLDB4YjMsMHhiYiwweGFkLDB4MmUsMHg2MCwweGZiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MWMsMHhlZSwweDQ5LDB4ZDAsMHg0ZSwweDVjLDB4ZTMsMHgxZiwweDg4LDB4NDgsMHhlNCwweDY4LDB4MTQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgzZCwweDcxLDB4YmEsMHhkNywweDRkLDB4MzUsMHgxMCwweDg2LDB4MzcsMHg2MiwweGUwLDB4YTUsMHgwYl0pLFxuICAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDQsMHgwMCwweGUyLDB4MzgsMHhmOSwweGM4LDB4M2MsMHhkMSwweGNmLDB4NjIsMHg5MywweGMzLDB4NzcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg3NiwweDk3LDB4NDQsMHhlOCwweGM4LDB4Y2EsMHg5MywweDlhLDB4ZWYsMHhmMCwweDYzLDB4NzYsMHgyNSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDNiLDB4MWMsMHg0NiwweGZmLDB4OTAsMHgxMywweDkxLDB4MTUsMHg5NywweDdlLDB4ODgsMHg5NSwweGQ0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4N2YsMHgyZiwweDUyLDB4NmUsMHgwZCwweDU1LDB4NTUsMHgyZSwweGYxLDB4NTgsMHg1YywweDdlLDB4NTYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhkNCwweDQ4LDB4YWEsMHhkYiwweDhjLDB4NDQsMHg0ZCwweDg0LDB4NjksMHgzMywweDg3LDB4MDcsMHhiMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDdlLDB4ZjUsMHhhMCwweDYwLDB4ZmIsMHg3MywweDU5LDB4NDYsMHgyOSwweGNiLDB4MWUsMHgzZiwweDdjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MmYsMHhhNiwweDUzLDB4ZTMsMHg4YywweGVmLDB4ZDUsMHhlYiwweGJiLDB4YzgsMHg5YSwweDhlLDB4NjYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0YSwweDQ3LDB4MmYsMHhlMSwweGJhLDB4NWUsMHgzMiwweGQ0LDB4NTIsMHgwNCwweDg4LDB4OWQsMHg2MyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDNlLDB4YmEsMHg3MSwweDJkLDB4ZjcsMHg2MSwweGQ1LDB4ZmMsMHgyNiwweGJmLDB4ZDgsMHg2MCwweDkyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4N2IsMHg5NCwweGY4LDB4NmYsMHgzZCwweDk3LDB4MGIsMHgwYywweDUyLDB4OGMsMHhiMywweGI2LDB4OGJdKSxcbiAgICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDA0LDB4MDAsMHhiNywweGM1LDB4NGQsMHg2ZSwweDJmLDB4ZGQsMHhlZiwweGVjLDB4MDcsMHg3MCwweGEyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4N2MsMHgxYywweDlkLDB4OGUsMHg2NiwweDYwLDB4N2MsMHg2MSwweDFlLDB4NDUsMHhlOSwweGRjLDB4ODIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgyZiwweGM1LDB4N2UsMHgxYSwweGM2LDB4ZDAsMHg5MiwweGM1LDB4MjIsMHg5YiwweDlhLDB4ZmIsMHg3MyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDk1LDB4OTksMHhmMiwweDdjLDB4ZGIsMHgyYSwweDkzLDB4N2IsMHg1YSwweDI5LDB4NzMsMHgyNCwweDE2LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NDEsMHg0OSwweGI1LDB4ZjIsMHg1ZiwweGJlLDB4ZTcsMHg2NCwweDRkLDB4ZGEsMHg1MiwweDllLDB4YzEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg0MSwweDQwLDB4NWUsMHgwMywweDkyLDB4OGQsMHgzOSwweDk1LDB4MWYsMHg2OCwweDlmLDB4MDAsMHgyZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDBjLDB4NmYsMHhjZiwweGQ5LDB4NmQsMHg2OCwweGY3LDB4MDAsMHg0ZiwweDBlLDB4YzgsMHgwYiwweGZhLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NTEsMHhlMCwweDIyLDB4ZjAsMHhmZiwweGE3LDB4NDIsMHhkNCwweGRlLDB4MGIsMHg0NywweDhmLDB4MmIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhmNSwweDRkLDB4MDQsMHgzMiwweDkxLDB4ODksMHg0YiwweDBlLDB4MDUsMHg4ZCwweDcwLDB4ZjksMHhiYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGU3LDB4ZDYsMHg3NiwweGVhLDB4MGUsMHgxYSwweDkwLDB4MzAsMHhmNSwweDk4LDB4MDEsMHhjNSwweDczXSldO1xuICBcbiAgdmFyIERTQXB1Yk1QSXN0cnMgPSBbXG4gICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDA4LDB4MDAsMHhhOCwweDg1LDB4NWMsMHgyOCwweDA1LDB4OTQsMHgwMywweGJlLDB4MDcsMHg2YywweDEzLDB4M2UsMHg2NSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4ZmIsMHhiNSwweGUxLDB4OTksMHg3YywweGZhLDB4ODQsMHhlMywweGFjLDB4NDcsMHhhNSwweGM0LDB4NDYsMHhkOCwweDVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHg0NCwweGU5LDB4YzEsMHg2YiwweDY5LDB4ZjcsMHgxMCwweDc2LDB4NDksMHhhNywweDI1LDB4ODUsMHhmNCwweDFiLDB4ZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGM2LDB4NjAsMHhjNCwweDViLDB4YWEsMHhkNCwweDg3LDB4ZDYsMHg4ZiwweDkyLDB4NTYsMHg3ZCwweDU1LDB4M2YsMHg0NSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4YWUsMHgxMiwweDczLDB4ZGEsMHgyOSwweDhjLDB4YmEsMHgzMiwweGNjLDB4ZDcsMHhhNCwweGQwLDB4MjQsMHhiMCwweDdjLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhkOCwweDBjLDB4M2EsMHg5MSwweDZmLDB4OTgsMHg0MCwweDljLDB4OWEsMHhhOCwweGNjLDB4MjgsMHgyNywweDk1LDB4MGIsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGUxLDB4NWIsMHhiOSwweDNiLDB4MWMsMHgxYywweGQyLDB4ZWMsMHhhYiwweDA3LDB4MjUsMHg4ZCwweDdhLDB4MmEsMHgyYixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MTYsMHgxNCwweGU4LDB4ZGEsMHg3MSwweGQyLDB4YWIsMHhiYSwweDg1LDB4MTQsMHgwZCwweGM1LDB4ZTAsMHg4OCwweGViLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhhNSwweGUyLDB4ZDUsMHg0OCwweDNkLDB4NzQsMHgwYywweDQxLDB4ZWIsMHhmZCwweGI2LDB4NGUsMHhmOSwweDJjLDB4ODIsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDE3LDB4ZGQsMHg2NCwweDFlLDB4MTksMHgzOSwweGEzLDB4N2YsMHhmOSwweDAwLDB4Y2QsMHg5YiwweGRhLDB4MmUsMHhiZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4NzEsMHgxMiwweGRmLDB4MGQsMHg3YywweDBhLDB4NmIsMHgyZCwweDIxLDB4M2IsMHg5YywweDY2LDB4OTMsMHg0YSwweDFlLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHg5MCwweDc5LDB4ZDMsMHg1YSwweDViLDB4ZTUsMHhiOSwweDk0LDB4MWIsMHhlNiwweDQ3LDB4OTksMHgwNiwweDk4LDB4ZDgsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDJhLDB4ZTUsMHhlMiwweGE2LDB4OTUsMHg2YSwweDA3LDB4YzgsMHhhYywweDdjLDB4ZTksMHhmYywweGEyLDB4NmEsMHgxNixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MmMsMHg5NCwweDk4LDB4YmQsMHg5MSwweDBhLDB4N2MsMHg3YywweDJjLDB4YjksMHg3ZSwweGEyLDB4NTEsMHg4YiwweDQ1LFxuICAgICAgICAgICAgICAgICAgICAgICAgMHgxZCwweDQ2LDB4MzQsMHhhOCwweDUyLDB4MmIsMHhkZCwweGQ5LDB4YTgsMHhiYywweDQ2LDB4NzgsMHg2NiwweGUxLDB4NzIsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDExLDB4ZjEsMHhjYiwweDFhLDB4YjYsMHg0ZSwweDA1LDB4NTQsMHhmNywweGU5LDB4YmUsMHg0YywweDI1LDB4NTksMHgwOCxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4OWYsMHhmOCwweGVhLDB4MjUsMHg5NywweDMzLDB4ZDYsMHhjOSwweDBmLDB4NTksMHgwZSwweGZkLDB4OWYsMHhkYywweGUyLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhjMCwweGNmLDB4MmZdKSxcbiAgICAgIHV0aWwuYmluMnN0cihbMHgwMSwweDAwLDB4ZTEsMHg3MiwweDJjLDB4ZDAsMHhiYiwweDFhLDB4NGYsMHhiNiwweGI2LDB4OTUsMHg3NywweDcxLDB4MmUsXG4gICAgICAgICAgICAgICAgICAgIDB4MDEsMHg0OCwweDNlLDB4MzUsMHg1NCwweDY0LDB4MmIsMHhlZCwweDQwLDB4NWYsMHg2NSwweDBjLDB4NTcsMHgyOCwweDVmLFxuICAgICAgICAgICAgICAgICAgICAweGZkLDB4ZmQsMHhmZiwweGQ3XSksXG4gICAgICB1dGlsLmJpbjJzdHIoWzB4MDcsMHhmZiwweDVkLDB4OWYsMHhjNCwweGI1LDB4NjMsMHgyNSwweDlkLDB4NzIsMHg4OCwweGU1LDB4NTMsMHg0NiwweDk4LFxuICAgICAgICAgICAgICAgICAgICAweGUzLDB4ZTksMHg2MiwweGNiLDB4MGMsMHhhMSwweGI3LDB4NzUsMHg5ZiwweDE4LDB4NDEsMHg5NCwweDMyLDB4MjgsMHgyOSxcbiAgICAgICAgICAgICAgICAgICAgMHg2ZCwweDY5LDB4ZTAsMHgzZiwweDdkLDB4N2IsMHgyYiwweDA2LDB4NWEsMHgzMywweDVjLDB4ZDQsMHgzNiwweDMxLDB4MDksXG4gICAgICAgICAgICAgICAgICAgIDB4NTQsMHg4NSwweDlkLDB4YjgsMHgyMCwweGZlLDB4ZGEsMHhmYywweGNkLDB4MWYsMHhiMSwweDJjLDB4MTUsMHgwOCwweDlkLFxuICAgICAgICAgICAgICAgICAgICAweDMyLDB4NTMsMHgyZiwweGMxLDB4NDIsMHgyMiwweDY5LDB4ZmYsMHg2NywweDJlLDB4MzksMHg5NywweDUwLDB4NjYsMHgzOSxcbiAgICAgICAgICAgICAgICAgICAgMHhkYSwweGNmLDB4ZmQsMHg2NCwweDZmLDB4OTEsMHgwNSwweDY0LDB4MzcsMHhjNSwweDA3LDB4MjQsMHhhYSwweDQwLDB4YTAsXG4gICAgICAgICAgICAgICAgICAgIDB4NzUsMHg4MiwweDFkLDB4OTcsMHg5NiwweDEyLDB4ZjEsMHhiZCwweDllLDB4MDksMHgyNiwweDNjLDB4OTcsMHg1ZCwweDU3LFxuICAgICAgICAgICAgICAgICAgICAweGI4LDB4NWMsMHg3ZCwweDg5LDB4MDMsMHg4MiwweGNkLDB4NDAsMHhlNSwweDAzLDB4ZTYsMHg0YSwweGZiLDB4YmMsMHhkMixcbiAgICAgICAgICAgICAgICAgICAgMHhlZiwweDdhLDB4ODksMHgwMiwweDA4LDB4YzgsMHg1MiwweGZhLDB4OTcsMHg3NCwweDY2LDB4MzIsMHhhZSwweGE2LDB4NTIsXG4gICAgICAgICAgICAgICAgICAgIDB4NGIsMHhlZiwweDVmLDB4Y2UsMHg5MSwweDIzLDB4M2YsMHhhYiwweDlkLDB4NjIsMHgyMSwweGVmLDB4NDgsMHg2ZCwweDA3LFxuICAgICAgICAgICAgICAgICAgICAweDVhLDB4YmEsMHhkZiwweDAwLDB4OTEsMHg1NCwweGVhLDB4NWMsMHhmYSwweDRiLDB4MTYsMHgyOCwweDFhLDB4Y2UsMHg0OCxcbiAgICAgICAgICAgICAgICAgICAgMHhiNywweDVjLDB4NTAsMHhhNSwweDU5LDB4YTQsMHhiNCwweGFmLDB4MWYsMHhlYiwweDhkLDB4NTgsMHgzZiwweDBhLDB4YTUsXG4gICAgICAgICAgICAgICAgICAgIDB4OTcsMHgyYiwweDUxLDB4NTYsMHhlOCwweDg4LDB4ZjYsMHgwNywweGJjLDB4ZGYsMHhmYSwweDJiLDB4N2IsMHg4OCwweGUwLFxuICAgICAgICAgICAgICAgICAgICAweDQ2LDB4YzgsMHg3YSwweDNlLDB4ZDgsMHg4MCwweGRiLDB4NGQsMHg4NywweDYxLDB4NGYsMHg2NCwweGNkLDB4ZWIsMHhlOCxcbiAgICAgICAgICAgICAgICAgICAgMHgwZCwweDg2LDB4MTYsMHhjYywweGRkLDB4NmMsMHg3NiwweDY2LDB4YzEsMHg3MywweGI3LDB4MDgsMHg5OCwweDg5LDB4MmYsXG4gICAgICAgICAgICAgICAgICAgIDB4NjcsMHg2OSwweGQxLDB4ZmMsMHg5NywweDRkLDB4YTIsMHhjZSwweGFkLDB4YmIsMHg2ZiwweGFiLDB4YTUsMHhkNiwweDE4LFxuICAgICAgICAgICAgICAgICAgICAweGIzLDB4MWEsMHg5NiwweDAyLDB4YmMsMHgzMSwweDQyLDB4YTIsMHhhZCwweDc3LDB4ZTgsMHhlMiwweDRjLDB4OTksMHhmOSxcbiAgICAgICAgICAgICAgICAgICAgMHhkZCwweGJlLDB4Y2RdKSxcbiAgICAgIHV0aWwuYmluMnN0cihbMHgwNywweGZmLDB4NWQsMHhmZSwweDljLDB4OTgsMHhlZiwweDNhLDB4YTYsMHg0OSwweGYwLDB4MTAsMHg2NywweDc5LDB4MmEsXG4gICAgICAgICAgICAgICAgICAgIDB4OWQsMHg3OSwweDQzLDB4MDYsMHhhNCwweGE4LDB4NmIsMHgxYSwweDZkLDB4MWYsMHg3NywweDZlLDB4MDAsMHgzMSwweGI5LFxuICAgICAgICAgICAgICAgICAgICAweGVkLDB4YzksMHg2NiwweGZmLDB4ZjEsMHgyMSwweDMyLDB4ZmEsMHg2MiwweDQzLDB4Y2QsMHg5NywweGQzLDB4M2QsMHhhZixcbiAgICAgICAgICAgICAgICAgICAgMHhiNCwweDI5LDB4MjksMHgyNiwweDRlLDB4MWMsMHhhMCwweGFkLDB4MWMsMHgwNywweDI4LDB4M2YsMHhlNSwweDQzLDB4MTAsXG4gICAgICAgICAgICAgICAgICAgIDB4YmEsMHhiNCwweDA4LDB4ZTAsMHhkYywweGEyLDB4YzMsMHg1YiwweDFmLDB4YmQsMHg5NCwweGM3LDB4NDMsMHhlNSwweGYyLFxuICAgICAgICAgICAgICAgICAgICAweDE3LDB4MzAsMHg1NCwweDdmLDB4MTQsMHhiZSwweGY0LDB4YmQsMHg5MSwweDNiLDB4ZTQsMHgzNiwweGE0LDB4NTAsMHg1YixcbiAgICAgICAgICAgICAgICAgICAgMHgzNywweDg5LDB4NWUsMHhjYywweGM3LDB4NzQsMHg1NCwweDMyLDB4MjAsMHgwOSwweDYzLDB4OTgsMHhiNywweGQ5LDB4YWYsXG4gICAgICAgICAgICAgICAgICAgIDB4N2YsMHhiMCwweDZjLDB4MjcsMHg0MywweGZlLDB4NTIsMHhlNiwweDFhLDB4ODgsMHg1OSwweDI1LDB4ZmMsMHhlYiwweDQzLFxuICAgICAgICAgICAgICAgICAgICAweDUwLDB4YzcsMHg2NSwweDQzLDB4YzEsMHg4NiwweDczLDB4NTgsMHg1MywweDNhLDB4Y2YsMHg3YSwweGEzLDB4MWQsMHg1NixcbiAgICAgICAgICAgICAgICAgICAgMHhjOCwweDRhLDB4ODAsMHg3MCwweGI3LDB4YmYsMHhmMiwweGEzLDB4ZWMsMHhlOCwweDc3LDB4MDUsMHgzMywweDA5LDB4OWQsXG4gICAgICAgICAgICAgICAgICAgIDB4YWEsMHhjYSwweGEwLDB4ZTEsMHg2NCwweDY0LDB4NmYsMHg3NiwweDk5LDB4NDEsMHg3NSwweDc4LDB4OTAsMHhmNiwweGU3LFxuICAgICAgICAgICAgICAgICAgICAweDIzLDB4ZTYsMHhlYywweDUwLDB4ZTUsMHg5OSwweGE4LDB4M2UsMHgxYSwweDRiLDB4YzksMHg4OCwweDU4LDB4NjYsMHhhZSxcbiAgICAgICAgICAgICAgICAgICAgMHgxYSwweDUzLDB4NWUsMHhlNCwweGI3LDB4ODYsMHhjZiwweGE2LDB4ZTUsMHhhZCwweGI0LDB4ODAsMHhhMCwweGYxLDB4MGQsXG4gICAgICAgICAgICAgICAgICAgIDB4OTYsMHhiOCwweDQxLDB4ZDAsMHgwNywweDlhLDB4MjEsMHg4ZCwweDUwLDB4N2YsMHg0ZiwweDczLDB4MTMsMHhhMiwweGUyLFxuICAgICAgICAgICAgICAgICAgICAweDAyLDB4MDcsMHhjMywweGEzLDB4MGYsMHgwOSwweDE4LDB4N2YsMHhmNywweDZiLDB4OTAsMHg3MCwweGMwLDB4ZjksMHgwYyxcbiAgICAgICAgICAgICAgICAgICAgMHg2NywweDhkLDB4OWQsMHgxNCwweGI2LDB4OWQsMHgzMiwweDgyLDB4ZDAsMHhiNSwweGM2LDB4NTcsMHhmMCwweDkxLDB4ZDksXG4gICAgICAgICAgICAgICAgICAgIDB4YzMsMHgyNiwweGFlLDB4OWYsMHhhOSwweDY3LDB4NDksMHg5NiwweDVjLDB4MDcsMHgzZSwweDQ3LDB4NWMsMHhlZCwweDYwLFxuICAgICAgICAgICAgICAgICAgICAweDA3LDB4YWMsMHg2YV0pXTtcbiAgdmFyIERTQXNlY01QSXN0cnMgPSBbdXRpbC5iaW4yc3RyKFsweDAxLDB4MDAsMHg5YiwweDU4LDB4YTgsMHhmNCwweDA0LDB4YjEsMHhkNSwweDE0LDB4MDksMHhlMSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZTEsMHhhMSwweDhhLDB4MGIsMHhhMywweGMzLDB4YTMsMHg2NiwweGFhLDB4MjcsMHg5OSwweDUwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxYywweDRkLDB4YmEsMHgyNCwweGVlLDB4ZGYsMHhkZiwweGI4LDB4OGUsMHg4ZV0pXTtcbiAgICAgICAgICAgIFxuICB2YXIgRWxnYW1hbHB1Yk1QSXN0cnMgPSBcbiAgICAgICAgICBbdXRpbC5iaW4yc3RyKFsweDA4LDB4MDAsMHhlYSwweGNjLDB4YmUsMHhlMiwweGU0LDB4NWEsMHg1MSwweDE4LDB4OTMsMHhhMSwweDEyLDB4MmYsXG4gICAgICAgICAgICAgICAgICAgICAweDAwLDB4OTksMHg0MiwweGQ4LDB4NWMsMHgxYywweDJmLDB4YjYsMHgzYywweGQ5LDB4OTQsMHg2MSwweGI0LDB4NTUsXG4gICAgICAgICAgICAgICAgICAgICAweDhkLDB4NGUsMHg3MywweGU2LDB4NjksMHhiYywweDFkLDB4MzMsMHhlMywweDJkLDB4OTEsMHgyMywweDY5LDB4OTUsXG4gICAgICAgICAgICAgICAgICAgICAweDk4LDB4ZDcsMHgxOCwweDVhLDB4YWYsMHhhNywweDkzLDB4YzYsMHgwNSwweDkzLDB4M2EsMHhjNywweGVhLDB4ZDAsXG4gICAgICAgICAgICAgICAgICAgICAweGIxLDB4YTksMHhjNywweGFiLDB4NDEsMHg4OSwweGM4LDB4MzgsMHg5OSwweGRjLDB4MWEsMHg1NywweDM1LDB4MWEsXG4gICAgICAgICAgICAgICAgICAgICAweDI3LDB4NjIsMHg0MCwweDcxLDB4OWYsMHgzNiwweDFjLDB4NmQsMHgxOCwweDFjLDB4OTMsMHhmNywweGJhLDB4MzUsXG4gICAgICAgICAgICAgICAgICAgICAweDA2LDB4ZWQsMHgzMCwweGI4LDB4ZDksMHg4YSwweDdjLDB4MDMsMHhhZiwweGJhLDB4NDAsMHgxZiwweDYyLDB4ZjEsXG4gICAgICAgICAgICAgICAgICAgICAweDZkLDB4ODcsMHgyYywweGE2LDB4MmUsMHg0NiwweGIwLDB4YWEsMHhiYywweGJjLDB4OTMsMHhmYSwweDliLDB4NDcsXG4gICAgICAgICAgICAgICAgICAgICAweDNmLDB4NzAsMHgxZiwweDJhLDB4YzIsMHg2NiwweDljLDB4N2MsMHg2OSwweGUwLDB4MmIsMHgwNSwweGVlLDB4YjcsXG4gICAgICAgICAgICAgICAgICAgICAweGE3LDB4N2YsMHhmMywweDIxLDB4NDgsMHg4NSwweGMyLDB4OTUsMHg1ZiwweDZmLDB4MWUsMHhiMywweDliLDB4OTcsXG4gICAgICAgICAgICAgICAgICAgICAweGY4LDB4MTQsMHhjMywweGZmLDB4NGQsMHg5NywweDI1LDB4MjksMHg5NCwweDQxLDB4NGIsMHg5MCwweGQ4LDB4YmEsXG4gICAgICAgICAgICAgICAgICAgICAweDcxLDB4NDUsMHg0YiwweDFlLDB4MmYsMHhjYSwweDgyLDB4NWYsMHg1NiwweDc3LDB4ZTksMHhkMywweDg4LDB4NWQsXG4gICAgICAgICAgICAgICAgICAgICAweDhiLDB4ZWMsMHg5MiwweDhiLDB4OGEsMHgyMywweDg4LDB4MDUsMHhmOCwweDJjLDB4YTgsMHhmMSwweDcwLDB4NzYsXG4gICAgICAgICAgICAgICAgICAgICAweGU3LDB4YmYsMHg3NSwweGE4LDB4MzEsMHgxNCwweDhlLDB4NzYsMHhjOCwweDAxLDB4YTYsMHgyNSwweDI3LDB4NDksXG4gICAgICAgICAgICAgICAgICAgICAweGFmLDB4ZGMsMHhmNCwweGY2LDB4ZjQsMHhjZSwweDkwLDB4ODQsMHgxNSwweDJiLDB4NGQsMHhiMywweGNjLDB4NzcsXG4gICAgICAgICAgICAgICAgICAgICAweGRiLDB4NjUsMHg3MSwweDc1LDB4ZDMsMHgwMCwweDFkLDB4MjIsMHhjNSwweDQyLDB4MmYsMHg1MSwweGZhLDB4N2IsXG4gICAgICAgICAgICAgICAgICAgICAweGViLDB4NmUsMHgwMywweGQ5LDB4NDEsMHhkZCwweDJkLDB4MWEsMHhkZCwweDA3LDB4NzQsMHg4YiwweGI3LDB4YTIsXG4gICAgICAgICAgICAgICAgICAgICAweGZhLDB4YjIsMHg1OSwweDBlLDB4MGUsMHg5NCwweDdjLDB4MDAsMHhhZCwweDk1LDB4MjMsMHg0MiwweDkxLDB4MTgsXG4gICAgICAgICAgICAgICAgICAgICAweDRjLDB4OTcsMHhmMSwweDI3LDB4NjIsMHg3N10pLFxuICAgICAgIHV0aWwuYmluMnN0cihbMHgwMCwweDAzLDB4MDVdKSxcbiAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDcsMHhmZiwweDU3LDB4MTksMHg3NiwweGZjLDB4MDksMHg2YSwweDdhLDB4ZjcsMHhiYSwweGIyLDB4NDIsMHhiZixcbiAgICAgICAgICAgICAgICAgICAgIDB4Y2QsMHgyYiwweGMxLDB4MWEsMHg3OSwweDI1LDB4OGMsMHhhZCwweGY0LDB4M2EsMHgwYSwweDdhLDB4OWIsMHg0YyxcbiAgICAgICAgICAgICAgICAgICAgIDB4NDYsMHgzYywweGUwLDB4NGYsMHhjYywweDZlLDB4ZTUsMHg3YSwweDMzLDB4M2EsMHg0ZSwweDgwLDB4Y2IsMHhkMyxcbiAgICAgICAgICAgICAgICAgICAgIDB4NjIsMHhkNywweDhmLDB4ZTIsMHhjOCwweGIwLDB4ZDAsMHhjYiwweDQ5LDB4YzksMHg5ZSwweDJkLDB4OTcsMHgxNixcbiAgICAgICAgICAgICAgICAgICAgIDB4M2EsMHg3ZCwweGIxLDB4ZTEsMHhkMywweGQ5LDB4ZDcsMHgzZiwweDIwLDB4NjAsMHhlMywweDNlLDB4NzcsMHhlYSxcbiAgICAgICAgICAgICAgICAgICAgIDB4MGMsMHhlNCwweDdiLDB4ZjAsMHgzOSwweDFhLDB4MGQsMHhkOSwweDhmLDB4NzMsMHhkMiwweDUxLDB4YjgsMHgwYyxcbiAgICAgICAgICAgICAgICAgICAgIDB4MGUsMHgxNSwweDFlLDB4YWQsMHg3YywweGQ4LDB4OWQsMHg3NCwweDZlLDB4YTIsMHgxNywweDZiLDB4NTgsMHgxNCxcbiAgICAgICAgICAgICAgICAgICAgIDB4MmIsMHhiNywweGFkLDB4OGEsMHhkNywweDY2LDB4YzAsMHhkZiwweGVhLDB4MmQsMHhmYywweGM0LDB4NmUsMHg2OCxcbiAgICAgICAgICAgICAgICAgICAgIDB4YjYsMHg0YywweDlhLDB4MTYsMHhhNCwweDNkLDB4YzIsMHgyNiwweDBjLDB4YjcsMHhkNCwweDEzLDB4N2IsMHgyMixcbiAgICAgICAgICAgICAgICAgICAgIDB4ZmQsMHg4NCwweGQ3LDB4MGYsMHhkYywweDQyLDB4NzUsMHgwNSwweDg1LDB4MjksMHgwMCwweDMxLDB4MWQsMHhlYyxcbiAgICAgICAgICAgICAgICAgICAgIDB4NGUsMHgyMiwweDhiLDB4ZjYsMHgzNywweDgzLDB4NDUsMHhlNSwweGIzLDB4MzEsMHg2MSwweDJjLDB4MDIsMHhhMSxcbiAgICAgICAgICAgICAgICAgICAgIDB4YzYsMHg5ZCwweGVhLDB4YmEsMHgzZCwweDhhLDB4YWIsMHgwZiwweDYxLDB4NWUsMHgxNCwweDY0LDB4NjksMHgxZSxcbiAgICAgICAgICAgICAgICAgICAgIDB4YTAsMHgxNSwweDQ4LDB4ODYsMHhlNSwweDExLDB4MDYsMHhlOCwweGRlLDB4MzQsMHhjNywweGE3LDB4M2QsMHgzNSxcbiAgICAgICAgICAgICAgICAgICAgIDB4ZDEsMHg3NiwweGMyLDB4YmUsMHgwMSwweDgyLDB4NjEsMHg4ZCwweGU3LDB4N2UsMHgyOCwweDFkLDB4NGUsMHg4YyxcbiAgICAgICAgICAgICAgICAgICAgIDB4YjksMHhlOCwweDdlLDB4YTQsMHg1ZiwweGE2LDB4M2EsMHg5ZSwweDVkLDB4YWMsMHhmMywweDYwLDB4MjIsMHgxNCxcbiAgICAgICAgICAgICAgICAgICAgIDB4ZDUsMHhkNSwweGJlLDB4MWYsMHhmMCwweDE5LDB4ZTYsMHg4MSwweGZkLDB4NWQsMHhlMSwweGY4LDB4NzYsMHg1ZixcbiAgICAgICAgICAgICAgICAgICAgIDB4ZTMsMHhkYSwweGJhLDB4MTksMHhmMywweGNiLDB4MTAsMHhhMCwweDZiLDB4ZDAsMHgyZCwweGJlLDB4NDAsMHg0MixcbiAgICAgICAgICAgICAgICAgICAgIDB4N2IsMHg5YiwweDE1LDB4YTQsMHgyZCwweGVjLDB4Y2YsMHgwOSwweGQ2LDB4ZTMsMHg5MiwweGMzLDB4OGQsMHg2NSxcbiAgICAgICAgICAgICAgICAgICAgIDB4NmIsMHg2MCwweDk3LDB4ZGEsMHg2YiwweGNhXSldO1xuXG4gIHZhciBFbGdhbWFsc2VjTVBJc3RycyA9IFtcbiAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDEsMHg1MiwweDAyLDB4ODAsMHg4NywweGY2LDB4ZTQsMHg0OSwweGQ3LDB4MmUsMHgzZSwweGZlLDB4NjAsMHhiOSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YTMsMHgyYSwweGYwLDB4NjcsMHg1OCwweGU5LDB4ZjYsMHg0NywweDgzLDB4ZGUsMHg3ZSwweGZiLDB4YmIsMHhiZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZGYsMHg0OCwweDEyLDB4MWIsMHgwNiwweDdkLDB4MTMsMHhiYywweDNiLDB4NDksMHhmOSwweDg2LDB4ZDQsMHg1MyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZWQsMHgyZCwweDY4XSldO1xuXG4gIHZhciBSU0FwdWJNUElzID0gW107XG4gIHZhciBpO1xuICBmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7XG4gICAgUlNBcHViTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIFJTQXB1Yk1QSXNbaV0ucmVhZChSU0FwdWJNUElzdHJzW2ldKTtcbiAgfVxuXG4gIHZhciBSU0FzZWNNUElzID0gW107XG4gIGZvciAoaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICBSU0FzZWNNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgUlNBc2VjTVBJc1tpXS5yZWFkKFJTQXNlY01QSXN0cnNbaV0pO1xuICB9XG4gICAgXG4gIHZhciBEU0FzZWNNUElzID0gW107XG4gIGZvciAoaSA9IDA7IGkgPCAxOyBpKyspIHtcbiAgICBEU0FzZWNNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRFNBc2VjTVBJc1tpXS5yZWFkKERTQXNlY01QSXN0cnNbaV0pO1xuICB9XG4gICAgXG4gIHZhciBEU0FwdWJNUElzID0gW107XG4gIGZvciAoaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICBEU0FwdWJNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRFNBcHViTVBJc1tpXS5yZWFkKERTQXB1Yk1QSXN0cnNbaV0pO1xuICB9XG4gIHZhciBFbGdhbWFsc2VjTVBJcyA9IFtdO1xuICBmb3IgKGkgPSAwOyBpIDwgMTsgaSsrKSB7XG4gICAgRWxnYW1hbHNlY01QSXNbaV0gPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgICBFbGdhbWFsc2VjTVBJc1tpXS5yZWFkKEVsZ2FtYWxzZWNNUElzdHJzW2ldKTtcbiAgfVxuICAgIFxuICB2YXIgRWxnYW1hbHB1Yk1QSXMgPSBbXTtcbiAgZm9yIChpID0gMDsgaSA8IDM7IGkrKykge1xuICAgIEVsZ2FtYWxwdWJNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRWxnYW1hbHB1Yk1QSXNbaV0ucmVhZChFbGdhbWFscHViTVBJc3Ryc1tpXSk7XG4gIH1cblxuICAvL09yaWdpbmFsbHkgd2UgcGFzc2VkIHB1YmxpYyBhbmQgc2VjcmV0IE1QSSBzZXBhcmF0ZWx5LCBub3cgdGhleSBhcmUgam9pbmVkLiBJcyB0aGlzIHdoYXQgd2Ugd2FudCB0byBkbyBsb25nIHRlcm0/XG4gIC8vIFJTQVxuICB2YXIgUlNBc2lnbmVkRGF0YSA9IG9wZW5wZ3AuY3J5cHRvLnNpZ25hdHVyZS5zaWduKDIsIDEsIFJTQXB1Yk1QSXMuY29uY2F0KFJTQXNlY01QSXMpLCBcImZvb2JhclwiKTtcbiAgdmFyIFJTQXNpZ25lZERhdGFNUEkgPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgUlNBc2lnbmVkRGF0YU1QSS5yZWFkKFJTQXNpZ25lZERhdGEpO1xuICByZXN1bHRbMF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIFJTQSBTaWduIGFuZCBWZXJpZnlcIixcbiAgICAgIG9wZW5wZ3AuY3J5cHRvLnNpZ25hdHVyZS52ZXJpZnkoMSwgMiwgW1JTQXNpZ25lZERhdGFNUEldLCBSU0FwdWJNUElzLCBcImZvb2JhclwiKSk7XG5cbiAgLy8gRFNBIFxuICB2YXIgRFNBc2lnbmVkRGF0YSA9IG9wZW5wZ3AuY3J5cHRvLnNpZ25hdHVyZS5zaWduKDIsIDE3LCBEU0FwdWJNUElzLmNvbmNhdChEU0FzZWNNUElzKSwgXCJmb29iYXJcIik7XG4gIFxuICB2YXIgRFNBbXNnTVBJcyA9IFtdO1xuICAgIERTQW1zZ01QSXNbMF0gPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgICBEU0Ftc2dNUElzWzFdID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRFNBbXNnTVBJc1swXS5yZWFkKERTQXNpZ25lZERhdGEuc3Vic3RyaW5nKDAsMzQpKTtcbiAgICBEU0Ftc2dNUElzWzFdLnJlYWQoRFNBc2lnbmVkRGF0YS5zdWJzdHJpbmcoMzQsNjgpKTtcbiAgcmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBEU0EgU2lnbiBhbmQgVmVyaWZ5XCIsXG4gICAgICBvcGVucGdwLmNyeXB0by5zaWduYXR1cmUudmVyaWZ5KDE3LCAyLCBEU0Ftc2dNUElzLCBEU0FwdWJNUElzLCBcImZvb2JhclwiKSk7XG4gIFxuICB2YXIgc3ltbUFsZ28gPSBcImFlczI1NlwiOyAvLyBBRVMyNTZcbiAgdmFyIHN5bW1LZXkgPSBvcGVucGdwLmNyeXB0by5nZW5lcmF0ZVNlc3Npb25LZXkoc3ltbUFsZ28pO1xuICB2YXIgc3ltbWVuY0RhdGFPQ0ZCID0gb3BlbnBncC5jcnlwdG8uY2ZiLmVuY3J5cHQob3BlbnBncC5jcnlwdG8uZ2V0UHJlZml4UmFuZG9tKHN5bW1BbGdvKSwgc3ltbUFsZ28sIFwiZm9vYmFyZm9vYmFyMTIzNDU2Nzg5MFwiLCBzeW1tS2V5LCB0cnVlKTtcbiAgdmFyIHN5bW1lbmNEYXRhQ0ZCICA9IG9wZW5wZ3AuY3J5cHRvLmNmYi5lbmNyeXB0KG9wZW5wZ3AuY3J5cHRvLmdldFByZWZpeFJhbmRvbShzeW1tQWxnbyksIHN5bW1BbGdvLCBcImZvb2JhcmZvb2JhcjEyMzQ1Njc4OTBcIiwgc3ltbUtleSwgZmFsc2UpO1xuICBcbiAgcmVzdWx0WzJdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBzeW1tZXRyaWMgZW5jcnlwdCBhbmQgZGVjcnlwdCB3aXRoIE9wZW5QR1AgQ0ZCIHJlc3luY1wiLFxuICAgICAgb3BlbnBncC5jcnlwdG8uY2ZiLmRlY3J5cHQoc3ltbUFsZ28sc3ltbUtleSxzeW1tZW5jRGF0YU9DRkIsdHJ1ZSkgPT0gXCJmb29iYXJmb29iYXIxMjM0NTY3ODkwXCIpO1xuICByZXN1bHRbM10gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIHN5bW1ldHJpYyBlbmNyeXB0IGFuZCBkZWNyeXB0IHdpdGhvdXQgT3BlblBHUCBDRkIgcmVzeW5jICh1c2VkIGluIG1vZGlmaWNhdGlvbiBkZXRlY3Rpb24gY29kZSBcXFwiTURDXFxcIiBwYWNrZXRzKVwiLFxuICAgICAgb3BlbnBncC5jcnlwdG8uY2ZiLmRlY3J5cHQoc3ltbUFsZ28sc3ltbUtleSxzeW1tZW5jRGF0YUNGQixmYWxzZSkgPT0gXCJmb29iYXJmb29iYXIxMjM0NTY3ODkwXCIpO1xuICBcbiAgdmFyIFJTQVVuZW5jcnlwdGVkRGF0YSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICBSU0FVbmVuY3J5cHRlZERhdGEuZnJvbUJ5dGVzKG9wZW5wZ3AuY3J5cHRvLnBrY3MxLmVtZS5lbmNvZGUoc3ltbUtleSwgUlNBcHViTVBJc1swXS5ieXRlTGVuZ3RoKCkpKTtcbiAgdmFyIFJTQUVuY3J5cHRlZERhdGEgPSBvcGVucGdwLmNyeXB0by5wdWJsaWNLZXlFbmNyeXB0KFwicnNhX2VuY3J5cHRfc2lnblwiLCBSU0FwdWJNUElzLCBSU0FVbmVuY3J5cHRlZERhdGEpO1xuXG4gIHJlc3VsdFs0XSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgYXN5bW1ldHJpYyBlbmNyeXB0IGFuZCBkZWNyeXB0IHVzaW5nIFJTQSB3aXRoIGVtZV9wa2NzMSBwYWRkaW5nXCIsXG4gICAgICBvcGVucGdwLmNyeXB0by5wa2NzMS5lbWUuZGVjb2RlKG9wZW5wZ3AuY3J5cHRvLnB1YmxpY0tleURlY3J5cHQoXCJyc2FfZW5jcnlwdF9zaWduXCIsIFJTQXB1Yk1QSXMuY29uY2F0KFJTQXNlY01QSXMpLCBSU0FFbmNyeXB0ZWREYXRhKS53cml0ZSgpLnN1YnN0cmluZygyKSwgUlNBcHViTVBJc1swXS5ieXRlTGVuZ3RoKCkpID09IHN5bW1LZXkpO1xuXG4gIHZhciBFbGdhbWFsVW5lbmNyeXB0ZWREYXRhID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gIEVsZ2FtYWxVbmVuY3J5cHRlZERhdGEuZnJvbUJ5dGVzKG9wZW5wZ3AuY3J5cHRvLnBrY3MxLmVtZS5lbmNvZGUoc3ltbUtleSwgRWxnYW1hbHB1Yk1QSXNbMF0uYnl0ZUxlbmd0aCgpKSk7XG4gIHZhciBFbGdhbWFsRW5jcnlwdGVkRGF0YSA9IG9wZW5wZ3AuY3J5cHRvLnB1YmxpY0tleUVuY3J5cHQoXCJlbGdhbWFsXCIsIEVsZ2FtYWxwdWJNUElzLCBFbGdhbWFsVW5lbmNyeXB0ZWREYXRhKTtcblxuICByZXN1bHRbNV0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIGFzeW1tZXRyaWMgZW5jcnlwdCBhbmQgZGVjcnlwdCB1c2luZyBFbGdhbWFsIHdpdGggZW1lX3BrY3MxIHBhZGRpbmdcIixcbiAgICAgIG9wZW5wZ3AuY3J5cHRvLnBrY3MxLmVtZS5kZWNvZGUob3BlbnBncC5jcnlwdG8ucHVibGljS2V5RGVjcnlwdChcImVsZ2FtYWxcIiwgRWxnYW1hbHB1Yk1QSXMuY29uY2F0KEVsZ2FtYWxzZWNNUElzKSwgRWxnYW1hbEVuY3J5cHRlZERhdGEpLndyaXRlKCkuc3Vic3RyaW5nKDIpLCBFbGdhbWFscHViTVBJc1swXS5ieXRlTGVuZ3RoKCkpID09IHN5bW1LZXkpO1xuXG4gIHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vdW5pdC5qcycpO1xuXG51bml0LnJlZ2lzdGVyKFwiVGVzdGluZyBvZiBiaW5hcnkgc2lnbmF0dXJlIGNoZWNraW5nXCIsIGZ1bmN0aW9uKCkge1xuICB2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLycpO1xuICB2YXIga2V5cmluZyA9IHJlcXVpcmUoJy4uLy4uL3NyYy9rZXlyaW5nLmpzJyk7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIHByaXZfa2V5ID0gb3BlbnBncC5rZXkucmVhZEFybW9yZWQoW1xuICAgICAgICAnLS0tLS1CRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAgICdWZXJzaW9uOiBHbnVQRyB2MS40LjExIChHTlUvTGludXgpJyxcbiAgICAgICAgJycsXG4gICAgICAgICdsUUhoQkZFUm5yTVJCQURtTTBoSWZrSTN5b3NqZ2JXbzl2MExucjNDQ0UrOEtzTXN6Z1ZTK2hCdTBYZkdyYUttJyxcbiAgICAgICAgJ2l2Y0EyYWFKaW1IcVZZT1A3Z0Vud0ZBeEhCQnBlVEpjdTV3ekNGeUp3RVlxVmVTM25uYUloQlBwbFNGMTREdWYnLFxuICAgICAgICAnaTZiQjlSVjdLeFZBZzZhdW5tTTJ0QXV0cUMrYTB5MnJEYWY3amtKb1o5Z1dKZTJ6SSt2cmFENmZpd0NneHZIbycsXG4gICAgICAgICczSWdVTEI5UnFJcXBMb01nWGZjakMrY0QvMWplSmxLUm0rbjcxcnlZd1QvRUNLc3NwRno3UzM2ejZxM1h5UzhRJyxcbiAgICAgICAgJ1FmcnNVejJwMWZiRmljdkp3SU9KOEIyMEovTjIvbml0NFAwZ0JVVFV4djNRRWE3WENNLzU2L3hyR2t5QnpzY1cnLFxuICAgICAgICAnQXpCb3kvQUs5SzdHTjZ6MTNSb3p1QVM2MEYxeE83TVFjNllpMlZVM2VBU0RRRUtpeUwvVWJmL3MvcmtaK3NHaicsXG4gICAgICAgICd5Sml6QkFDdHdDYlF6QSt6OVhCWk5VYXQ1TlBnY1p6NVFlaDFud0Y5TnhucjZweUJ2N3RrckxoLzNneFJHSHFHJyxcbiAgICAgICAgJzA2M2RNYlVrOHBtVWNKekJVeVJzTmlJUERvRVVzTGpZNXptWlptcC93YUFocFJFc25LMjlXTENicUxkcFVvcnMnLFxuICAgICAgICAnYzFKSkJzT2JrQTFJTThUWlk4WVVtdnNNRXZCTENDYW51S3BjbFpaWHFlUkFlT0hKMHY0REF3SzhXZnVUZTVCKycsXG4gICAgICAgICdNMkJPT2VaYk44QnBmaUExbC8vZk1NSExSUzNVdmJMQnY0UDErNFN5dmh5WVRSN003NlEweFBjMDNNRk9XSEwrJyxcbiAgICAgICAgJ1M5VnVtYlFXVkdWemRESWdQSFJsYzNReVFIUmxjM1F1WTI5dFBvaGlCQk1SQWdBaUJRSlJFWjZ6QWhzREJnc0onLFxuICAgICAgICAnQ0FjREFnWVZDQUlKQ2dzRUZnSURBUUllQVFJWGdBQUtDUkFSSjVRRHl4YWUrTVhOQUtDeldTRFIzdE1yVHJEYicsXG4gICAgICAgICdUQXJpNzNOMVhiM2oxQUNmU2w5eStTQWFoMnE3R3ZtaVIxKzYrL2VrcUpHZEFWZ0VVUkdlc3hBRUFObHBNWmpXJyxcbiAgICAgICAgJzMzak14bEtIRGR5UkZYdEtPcThScmVYaHEwMHBsb3JIYmd6OXpGRVdtNFZGNTMrRS9LR25tSEd5WTVDeThUS3knLFxuICAgICAgICAnWmphdWVaWjlYdUcwaHVaZzVJZjY4aXJGZk5adHhkQTI2anY4Ly9QZFowVWorWDZKM1JWYTJwZU1MRERzd1RZTCcsXG4gICAgICAgICdPTDFaTzFmeGR0REQ0MGZkQWlJWjFReWp3RUcwQVB0ejQxRWZBQU1GQkFDNS9kdGdCQlB0SGU4VWpEQmFVZTRuJyxcbiAgICAgICAgJ056SHVVQkJwNlhFK0g3ZXFITkZDdVpBSjd5cUpMR1ZITklhUVI0MTljTnkwOC9PTy8rWVVRN3JnNzhMeGpGaXYnLFxuICAgICAgICAnQ0g3SXpoZlUrNnl2RUxTYmdSTWljWTZFbkFQMkdUK2IxK010Rk5hM2xCR3RCSGNKbGE1MmMyclRBSHRoWVpXaycsXG4gICAgICAgICdmVDVSNURuSnVRMmNKSEJNUzlIV3lQNERBd0s4V2Z1VGU1QitNMkM3YS9ZSlNVdjZTZXhkR0NhaWFUY0FtNmcvJyxcbiAgICAgICAgJ1B2QTZody9GTHpJRVA2N1FjUVNTVG1oZnRRSXduZGR0NFM0TXlKSkgzVTRmSmFGZllRMXpDbmlZSm9oSkJCZ1InLFxuICAgICAgICAnQWdBSkJRSlJFWjZ6QWhzTUFBb0pFQkVubEFQTEZwNzRRYk1BbjNWNDg1N3h3bk85Lyt2eklWbkw5M1czazAvOCcsXG4gICAgICAgICdBS0M4b21ZUFBvbU4xRS9VSkZmWGRMRElNaTVMb0E9PScsXG4gICAgICAgICc9TFNyVycsXG4gICAgICAgICctLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLSdcbiAgICAgIF0uam9pbihcIlxcblwiKSkucGFja2V0cztcbiAgdmFyIHB1Yl9rZXkgPSBvcGVucGdwLmtleS5yZWFkQXJtb3JlZChcbiAgICAgIFsgJy0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAgICdWZXJzaW9uOiBHbnVQRyB2MS40LjExIChHTlUvTGludXgpJyxcbiAgICAgICAgJycsXG4gICAgICAgICdtUUdpQkZFUmx3NFJCQUQ2Qm1jZjJ3MWR0VW10Q0xrZHhlcVpMQXJrM3ZZb1FBamRpYnhBM2dYVnl1cjdmc1diJyxcbiAgICAgICAgJ3JvMGpWYkJIcU9DdEM2akR4RTJsNTJOUDkrdFRsV2VWTWFxcU52VUU0N0xTYVBxMkRHSThXeDFSajZiRjNtVHMnLFxuICAgICAgICAnb2JZRXdoR2JHaC9NaEpuTUU5QUhPRGFydms4QVpiem8wK2sxRXdyQldGNmRUVUJQZnFPN3JHVTJld0NnODBXVicsXG4gICAgICAgICd4NXB0M2V2ajhyUkszalE4U01LVE5Sc0QvMVBoVGR4ZFpUZFhBUkFGemNXMVZhYXJ1V1cwUnIxK1hIS0t3REN6JyxcbiAgICAgICAgJ2k3SEU3NlNPOXFqblFmWkNaRzc1Q2RReEkwaDhHRmVOM3pzRHFtaG9iMmlTejJhSjFrcnRqTStpWjFGQkZkNTcnLFxuICAgICAgICAnT3FDVjZ3bWs1SVQwUkJOMTJaek1TMTlZdnpOL09OWEhybVRabEtFeGQ5TWg5UktMZVZOdytiZjZKc0tRRXpjWScsXG4gICAgICAgICdKekZrQkFDWDlYK2hEWWNoTy8yaGlUd3g0aU9POUZoc3VoN2VJV3VtQjNndCthVXBtMWpyU2Jhcy9RTFR5bW1rJyxcbiAgICAgICAgJ3VadVFWWEk0TnRubHZ6bE5nV3Y0TDVzNVJVNVdxTkdHN1dTYUtOZGNydkpaUkMyZGdiVUp0MDRKNUNLcldwNlInLFxuICAgICAgICAnYUlZYWwvODFVdDE3NzhsVTAxUEV0NTYzVGNRblVCbG5qVTVPUjI1S2hmU2VONUNaWTdRVVZHVnpkQ0E4ZEdWeicsXG4gICAgICAgICdkRUIwWlhOMExtTnZiVDZJWWdRVEVRSUFJZ1VDVVJHWERnSWJBd1lMQ1FnSEF3SUdGUWdDQ1FvTEJCWUNBd0VDJyxcbiAgICAgICAgJ0hnRUNGNEFBQ2drUWlrRGxaSy9VdkxTc3BnQ2ZjTmFPcFRnMVcydWNSMUp3QmJCR3ZhRVJmdU1BblJndDMvcnMnLFxuICAgICAgICAnRXBscUVha01ja0N0aWtFbnB4WWUnLFxuICAgICAgICAnPWIyTG4nLFxuICAgICAgICAnLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLSdcbiAgICAgIF0uam9pbihcIlxcblwiKSkucGFja2V0cztcbiAgdmFyIG1zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChbXG4gICAgICAgICctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS0nLFxuICAgICAgICAnVmVyc2lvbjogR251UEcgdjEuNC4xMSAoR05VL0xpbnV4KScsXG4gICAgICAgICcnLFxuICAgICAgICAnaFFFT0ExTjRPQ1NTakVDQkVBUC9kaURKQ1FuNGU4ODE5M1BncWhiZkFrb2hrOVJRMHYwTVBuWHBKYkNSVEhLTycsXG4gICAgICAgICc4cjlueGlBci9UUXY0Wk9pbmdYZEFwMkpaRW9FOXBYeFozcjFVV2V3MDRjenhtZ0o4RlAxenRaWVdWRkFXRlZpJyxcbiAgICAgICAgJ1RqOTMwVEJEN0wxZlkvTUQ0Zks2eGpFRzd6NUdUOGs0dG40bUxtL1BwV01iYXJJZ2xmTW9wVHkxTS9weTJjSUQnLFxuICAgICAgICAnLzJTajdJa2gzVUZpRyt6bTRzVmlZYzVyb05iTXk4aXhlb0tpeHhpOTlNeDhJTmEyY3hOZnFiYWJqYmxGeWMwWicsXG4gICAgICAgICdCd21iSWMrWmlZMm1lUk5JNXkvdGswZ1JEN2hUODRJWEdHbDYvbUgwMGJzWC9ra1dkS0dlVHZ6OHM1RzhSREhhJyxcbiAgICAgICAgJ1phNEhnTGJYSXRrWC9RYXJ2UlM5a3ZrRDAxdWpIZmorMVp2Z21PQnR0TmZQMHA4QlFMSUlDcXZnMWVZRDlhUEInLFxuICAgICAgICAnK0d0T1oyRjMrazVWeUJMNXlJbi9zNjVTQmpOTzhGcXMzYUwweCtwN3MxY2ZVeng4SjhhOG5XcHFxL3FJUUlxZycsXG4gICAgICAgICdaSkg2TVpSS3VRd3Njd0g2Tldnc1NWd2NuVkNBWG5ZT3BiSHhGUStqN1JiRi8rdWl1cVUrREZIL1JkNXBpazhiJyxcbiAgICAgICAgJzBEcW5wMHlmZWZya2pRMG51dnViZ0I2UnY4OW1IcG52dUpmRkpSSW5wZzRsckh3THZSd2RwTjJIRG96RkhjS0snLFxuICAgICAgICAnYU9VPScsXG4gICAgICAgICc9NGlHdCcsXG4gICAgICAgICctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJ1xuICAgICAgXS5qb2luKFwiXFxuXCIpKS5wYWNrZXRzO1xuICAvL1RPRE8gbmVlZCBib3RoP1xuICBwcml2X2tleVswXS5kZWNyeXB0KFwiYWJjZFwiKTtcbiAgcHJpdl9rZXlbM10uZGVjcnlwdChcImFiY2RcIik7XG4gIG1zZ1swXS5kZWNyeXB0KHByaXZfa2V5WzNdKTtcbiAgbXNnWzFdLmRlY3J5cHQobXNnWzBdLnNlc3Npb25LZXlBbGdvcml0aG0sIG1zZ1swXS5zZXNzaW9uS2V5KTtcbiAgbXNnWzFdLnBhY2tldHNbMl0udmVyaWZ5KHB1Yl9rZXlbMF0sIG1zZ1sxXS5wYWNrZXRzWzFdKTtcbiAgcmVzdWx0WzBdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBzaWduYXR1cmUgY2hlY2tpbmcgb24gQ0FTVDUtZW5jaXBoZXJlZCBtZXNzYWdlXCIsXG4gICAgICAgICAgbXNnWzFdLnBhY2tldHNbMl0udmVyaWZpZWQgPT09IHRydWUpO1xuXG4gIC8vIGV4ZXJjaXNlcyB0aGUgR251UEcgczJrIHR5cGUgMTAwMSBleHRlbnNpb246XG4gIC8vIHRoZSBzZWNyZXRzIG9uIHRoZSBwcmltYXJ5IGtleSBoYXZlIGJlZW4gc3RyaXBwZWQuXG4gIHZhciBwcml2X2tleV9nbnVwZ19leHQgPSBvcGVucGdwLmtleS5yZWFkQXJtb3JlZChbXG4gICAgICAgICctLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICAgJ1ZlcnNpb246IEdudVBHIHYxLjQuMTEgKEdOVS9MaW51eCknLFxuICAgICAgICAnJyxcbiAgICAgICAgJ2xRR3FCRkVSbnJNUkJBRG1NMGhJZmtJM3lvc2pnYldvOXYwTG5yM0NDRSs4S3NNc3pnVlMraEJ1MFhmR3JhS20nLFxuICAgICAgICAnaXZjQTJhYUppbUhxVllPUDdnRW53RkF4SEJCcGVUSmN1NXd6Q0Z5SndFWXFWZVMzbm5hSWhCUHBsU0YxNER1ZicsXG4gICAgICAgICdpNmJCOVJWN0t4VkFnNmF1bm1NMnRBdXRxQythMHkyckRhZjdqa0pvWjlnV0plMnpJK3ZyYUQ2Zml3Q2d4dkhvJyxcbiAgICAgICAgJzNJZ1VMQjlScUlxcExvTWdYZmNqQytjRC8xamVKbEtSbStuNzFyeVl3VC9FQ0tzc3BGejdTMzZ6NnEzWHlTOFEnLFxuICAgICAgICAnUWZyc1V6MnAxZmJGaWN2SndJT0o4QjIwSi9OMi9uaXQ0UDBnQlVUVXh2M1FFYTdYQ00vNTYveHJHa3lCenNjVycsXG4gICAgICAgICdBekJveS9BSzlLN0dONnoxM1JvenVBUzYwRjF4TzdNUWM2WWkyVlUzZUFTRFFFS2l5TC9VYmYvcy9ya1orc0dqJyxcbiAgICAgICAgJ3lKaXpCQUN0d0NiUXpBK3o5WEJaTlVhdDVOUGdjWno1UWVoMW53RjlOeG5yNnB5QnY3dGtyTGgvM2d4UkdIcUcnLFxuICAgICAgICAnMDYzZE1iVWs4cG1VY0p6QlV5UnNOaUlQRG9FVXNMalk1em1aWm1wL3dhQWhwUkVzbksyOVdMQ2JxTGRwVW9ycycsXG4gICAgICAgICdjMUpKQnNPYmtBMUlNOFRaWThZVW12c01FdkJMQ0NhbnVLcGNsWlpYcWVSQWVPSEowdjREWlFKSFRsVUJ0QlpVJyxcbiAgICAgICAgJ1pYTjBNaUE4ZEdWemRESkFkR1Z6ZEM1amIyMCtpR0lFRXhFQ0FDSUZBbEVSbnJNQ0d3TUdDd2tJQndNQ0JoVUknLFxuICAgICAgICAnQWdrS0N3UVdBZ01CQWg0QkFoZUFBQW9KRUJFbmxBUExGcDc0eGMwQW9MTlpJTkhlMHl0T3NOdE1DdUx2YzNWZCcsXG4gICAgICAgICd2ZVBVQUo5S1gzTDVJQnFIYXJzYSthSkhYN3I3OTZTb2taMEJXQVJSRVo2ekVBUUEyV2t4bU5iZmVNekdVb2NOJyxcbiAgICAgICAgJzNKRVZlMG82cnhHdDVlR3JUU21XaXNkdURQM01VUmFiaFVYbmY0VDhvYWVZY2JKamtMTHhNckptTnE1NWxuMWUnLFxuICAgICAgICAnNGJTRzVtRGtoL3J5S3NWODFtM0YwRGJxTy96Lzg5MW5SU1A1Zm9uZEZWcmFsNHdzTU96Qk5nczR2Vms3Vi9GMicsXG4gICAgICAgICcwTVBqUjkwQ0loblZES1BBUWJRQSszUGpVUjhBQXdVRUFMbjkyMkFFRSswZDd4U01NRnBSN2ljM01lNVFFR25wJyxcbiAgICAgICAgJ2NUNGZ0Nm9jMFVLNWtBbnZLb2tzWlVjMGhwQkhqWDF3M0xUejg0Ny81aFJEdXVEdnd2R01XSzhJZnNqT0Y5VDcnLFxuICAgICAgICAncks4UXRKdUJFeUp4am9TY0EvWVpQNXZYNHkwVTFyZVVFYTBFZHdtVnJuWnphdE1BZTJGaGxhUjlQbEhrT2NtNScsXG4gICAgICAgICdEWndrY0V4TDBkYkkvZ01EQXJ4Wis1TjdrSDR6WUx0cjlnbEpTL3BKN0YwWUpxSnBOd0NicUQ4KzhEcUhEOFV2JyxcbiAgICAgICAgJ01nUS9ydEJ4QkpKT2FGKzFBakNkMTIzaExneklra2ZkVGg4bG9WOWhEWE1LZUpnbWlFa0VHQkVDQUFrRkFsRVInLFxuICAgICAgICAnbnJNQ0d3d0FDZ2tRRVNlVUE4c1dudmhCc3dDZmRYanpudkhDYzczLzYvTWhXY3YzZGJlVFQvd0FvTHlpWmc4KycsXG4gICAgICAgICdpWTNVVDlRa1Y5ZDBzTWd5TGt1ZycsXG4gICAgICAgICc9R1FzWScsXG4gICAgICAgICctLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLScsXG4gICAgICBdLmpvaW4oXCJcXG5cIikpLnBhY2tldHM7XG4gIHByaXZfa2V5X2dudXBnX2V4dFszXS5kZWNyeXB0KFwiYWJjZFwiKTtcbiAgbXNnWzBdLmRlY3J5cHQocHJpdl9rZXlfZ251cGdfZXh0WzNdKTtcbiAgbXNnWzFdLmRlY3J5cHQobXNnWzBdLnNlc3Npb25LZXlBbGdvcml0aG0sIG1zZ1swXS5zZXNzaW9uS2V5KTtcbiAgbXNnWzFdLnBhY2tldHNbMl0udmVyaWZ5KHB1Yl9rZXlbMF0sIG1zZ1sxXS5wYWNrZXRzWzFdKTtcbiAgcmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBHbnVQRyBzdHJpcHBlZC1rZXkgZXh0ZW5zaW9uc1wiLFxuICAgICAgICAgIG1zZ1sxXS5wYWNrZXRzWzJdLnZlcmlmaWVkID09PSB0cnVlKTtcblxuICAvLyBFeGVyY2lzZXMgdGhlIGFiaWxpdHkgb2Ygb3BlbnBncF9rZXlyaW5nLmdldFB1YmxpY0tleXNGb3JLZXlJZCB0byByZXR1cm4gc3Via2V5c1xuICBrZXlyaW5nLmluaXQoKTtcbiAga2V5cmluZy5pbXBvcnRQYWNrZXRsaXN0KFtcbiAgICAgICAgJy0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAgICdWZXJzaW9uOiBHbnVQRyB2MS40LjExIChHTlUvTGludXgpJyxcbiAgICAgICAgJycsXG4gICAgICAgICdtUUdpQkZFUnZJNFJCQUQwTS9IR2dsQ3RWTlhQRjcyZWhUOHJpQVhybDByU2VjNFJKQzYxQmgrVUFPaHhuNStVJyxcbiAgICAgICAgJ2ZEZ29zNXAxU3BJelltbitNODdKb1NTVkxBamZha0ZrMGdIZ1I5STNidTdTSXdxM0Jpa2sxVnczZ08reURTTzYnLFxuICAgICAgICAnVEtwTFVGR1lEaUJTU0UxTUdkeEJhZFdMRTFobFJmNUIyeDYyZ25HbWpTcFNWYmx5MzNQRmtvRG1yd0NnOXJBcCcsXG4gICAgICAgICdSbW5jbkY5R2hXak9MRmtFb1F3OVl4OEVBT3N4dnE4SWc1WjFnaytaS2ZEWmVmdHBIUmUzRmRyUnRibmh4dllZJyxcbiAgICAgICAgJzd6K3c5dXoxRXBvWlV3RFI1RzRYM2hUd0pRN2xYbUlPc2tnLytlUk1MRUFxRVk3Yi83dFc2UmFVSjJkNkVoc2knLFxuICAgICAgICAnZE9TODlmSXhFbHdqQU9uVk9NNVMyNGYwRkRRVFR0bzdRQk9veGNOVGZrRUpDSFhTbHBvT1VtR0FQODVmWGgzbCcsXG4gICAgICAgICd5UFRHQkFDSmZLYzc2VW4zVVdDMXNXSVJEeFlpeWgzWnBaeU5Fc2tvVjZFU1c4akVJMVJuTW52NVRyZkdKSDVLJyxcbiAgICAgICAgJ0U4aldYN1RUbm9GeVBKdEJUamx1Y0F0a1FhUzRCYjdkZzFMTGphMTd6QXFLTkdPSksyYjlmYjJaK2xuVGpQaVknLFxuICAgICAgICAnaTdEUEgxWEhuZmFFZXhqbGgvVTdtWWE1UnJ3SXBoUnhOaThnQ3V4djg3NFpNbWhFbjdRV1ZHVnpkRE1nUEhSbCcsXG4gICAgICAgICdjM1F6UUhSbGMzUXVZMjl0UG9oaUJCTVJBZ0FpQlFKUkVieU9BaHNEQmdzSkNBY0RBZ1lWQ0FJSkNnc0VGZ0lEJyxcbiAgICAgICAgJ0FRSWVBUUlYZ0FBS0NSQzB1OE8wTW9hMkpZeHlBSjlPaTJVbGNVVDBWSk5nd2p5bC9WRjlYY2pmOWdDZUpQdnknLFxuICAgICAgICAnZy9mcDRFQVU4TUpJYU4yeU1JOHBMRlM1QWFJRVVSRzhuaEVFQUtWZ2VORHVZRFB1Zkx1SjBHckpWL0NiWEVqaicsXG4gICAgICAgICdhRVBBMGlUVXFWMG5UQ1BkQWZRL25tRTNnaDVVbE5Nci96U0hKK2M0RlFoWWRMcnpSR0RPU3pWK21mUEhIM3QrJyxcbiAgICAgICAgJ1lWeCt3YXQwQll3QUJwSEF0c0l1TElWbzJSUXFZWllIODV0YXR3QmttNzFISFQzam1sRUF2cjZORkgzOCt2M3MnLFxuICAgICAgICAnM3c0V2wwL3NkSHlhZWlTWEFLQ3hKNFgxZU9kTjdMMXJyYkpvelEvZ0RDRnVWUVAvZGNWNktzc3M4QXc0NDNqRycsXG4gICAgICAgICdBWUJMSFdoNm80R2hBWTYvaDFraWpGMHhEK3VjK3RObVRRblFpMXRFT29UZUlaTVhuU1J3dGs4WEV1SmtrYkFQJyxcbiAgICAgICAgJyt1eXZNZ3lWM3dyazl6a2FUQWluN25yakFFUnhlekZPZEJFT3RuQjFDb3ZKeHRNbitSUnhhTUVHcEM0R25FVHknLFxuICAgICAgICAnTjUrNkZrTHVMY05YaUNRUDc1YWp6T0FOMWFJRC9qdU5qVU5wQmJOcGZxQlY3ajFLK0tuMG45SFlUeVFsOWdoeScsXG4gICAgICAgICcwMjYrLzRjOGFnMkhWK2JnM0JEN2MyVlRWdTl4Qk9ESHNmdTBxOFFsL1FCOVc4dG1ZdWdVNkRlWE1IYWVXUFVIJyxcbiAgICAgICAgJ3BoOThndU05a0YyeUhJaVJCdkFkNWk3d09qd24rSS9JcjZuQlIyeXhKM3AzMUNEVW5VbGJqVFBZZzdtdFF2SFcnLFxuICAgICAgICAnRVkyQ3A0U1dpSkVFR0JFQ0FBa0ZBbEVSdko0Q0d3SUFVZ2tRdEx2RHRES0d0aVZISUFRWkVRSUFCZ1VDVVJHOCcsXG4gICAgICAgICduZ0FLQ1JBTWlNZVIyOTZZMlNqeUFKOVYzd1JKSjJTemF6cWFsNGtoV0dmTHU1UjYvd0NmUVFJUkQyNHlWZHo4JyxcbiAgICAgICAgJzJhKzJlQ3J3eUFMVDJHQWloQUNmUzBuV00zYTBndElUcW5ncEpzUndzK0VwK2VJQW4xNXFEMml0dXR4TmI4TkknLFxuICAgICAgICAnYlIyZ0JCNVFtVkozJyxcbiAgICAgICAgJz1wR0E2JyxcbiAgICAgICAgJy0tLS0tRU5EIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0nXG4gICAgICAgIF0uam9pbihcIlxcblwiKSk7XG5cbiAgdmFyIG1zZzIgPSBvcGVucGdwLm1lc3NhZ2UucmVhZEFybW9yZWQoW1xuICAgICAgICAnLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tJyxcbiAgICAgICAgJ1ZlcnNpb246IEdudVBHIHYxLjQuMTEgKEdOVS9MaW51eCknLFxuICAgICAgICAnJyxcbiAgICAgICAgJ2tBMERBQUlSRElqSGtkdmVtTmtCckIxaUIyWnZieTUwZUhSUkViejNWRVZUVkNCRVFWUkJJREV5TXpRMU5vaEcnLFxuICAgICAgICAnQkFBUkFnQUdCUUpSRWJ6M0FBb0pFQXlJeDVIYjNwaloyVGNBbjMyTHBERXVIZTlRclNSbHl2U3VSRUtOT0Z3eicsXG4gICAgICAgICdBSjl6aDR6c0s0R0lQdUV1ODFZUE5tSHNqdTdEWWc9PScsXG4gICAgICAgICc9V2FTeCcsXG4gICAgICAgICctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJ1xuICAgICAgICBdLmpvaW4oXCJcXG5cIikpLnBhY2tldHM7XG4gIHZhciBwYWNrZXRsaXN0cyA9IGtleXJpbmcuZ2V0UGFja2V0bGlzdHNGb3JLZXlJZChtc2cyWzBdLnNpZ25pbmdLZXlJZC53cml0ZSgpKTtcbiAgdmFyIHB1YktleSA9IHBhY2tldGxpc3RzWzBdO1xuICBtc2cyWzJdLnZlcmlmeShwdWJLZXlbM10sIG1zZzJbMV0pO1xuICByZXN1bHRbMl0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIGtleXJpbmcgcHVibGljIHN1YmtleSBzdXBwb3J0XCIsXG4gICAgICAgICAgcGFja2V0bGlzdHMgIT09IG51bGwgJiYgXG4gICAgICAgICAgcGFja2V0bGlzdHMubGVuZ3RoID09IDEgJiYgXG4gICAgICAgICAgbXNnMlsyXS52ZXJpZmllZCk7XG4gIHJldHVybiByZXN1bHQ7XG59KTtcblxuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJLZXkgZ2VuZXJhdGlvbi9lbmNyeXB0aW9uL2RlY3J5cHRpb25cIiwgZnVuY3Rpb24oKSB7XG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vJyk7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIHRlc3RIZWxwZXIgPSBmdW5jdGlvbihwYXNzcGhyYXNlLCB1c2VyaWQsIG1lc3NhZ2UpIHtcbiAgICB2YXIga2V5ID0gb3BlbnBncC5nZW5lcmF0ZUtleVBhaXIob3BlbnBncC5lbnVtcy5wdWJsaWNLZXkucnNhX2VuY3J5cHRfc2lnbiwgNTEyLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlcmlkLCBtZXNzYWdlLCBwYXNzcGhyYXNlKTtcblxuICAgIHZhciBpbmZvID0gJ1xcbnBhc3NwaHJhc2U6ICcgKyBwYXNzcGhyYXNlICsgJ1xcbidcbiAgICAgICAgKyAndXNlcmlkOiAnICsgdXNlcmlkICsgJ1xcbidcbiAgICAgICAgKyAnbWVzc2FnZTogJyArIG1lc3NhZ2U7XG5cbiAgICB2YXIgcHJpdktleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKGtleSk7XG5cbiAgICB2YXIgZW5jcnlwdGVkID0gb3BlbnBncC5lbmNyeXB0TWVzc2FnZShbcHJpdktleV0sIG1lc3NhZ2UpO1xuXG4gICAgdmFyIG1zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChlbmNyeXB0ZWQpO1xuXG4gICAgcHJpdktleS51bmxvY2socGFzc3BocmFzZSk7XG5cbiAgICB0cnkge1xuICAgICAgdmFyIGRlY3J5cHRlZCA9IG9wZW5wZ3AuZGVjcnlwdE1lc3NhZ2UocHJpdktleSwgbXNnKTtcbiAgICAgIHJldHVybiBuZXcgdW5pdC5yZXN1bHQobWVzc2FnZSArICcgPT0gJyArIGRlY3J5cHRlZCArIGluZm8sIG1lc3NhZ2UgPT0gZGVjcnlwdGVkKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gbmV3IHVuaXQucmVzdWx0KFwiRXhjZXB0aW9uIG9uIGRlY3J5cHQgb2YgcHJpdmF0ZSBrZXkgcGFja2V0IVwiICsgaW5mbywgZmFsc2UpO1xuICAgIH1cblxuICB9O1xuXG4gIHJlc3VsdC5wdXNoKHRlc3RIZWxwZXIoJ3Bhc3N3b3JkJywgJ1Rlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPicsICdoZWxsbyB3b3JsZCcpKTtcbiAgcmVzdWx0LnB1c2godGVzdEhlbHBlcign4peP4peP4peP4pePJywgJ+KZlOKZlOKZlOKZlCA8dGVzdEBleGFtcGxlLmNvbT4nLCAnxYLDpMOzxIcnKSk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuXG51bml0LnJlZ2lzdGVyKFwiRW5jcnlwdGlvbi9kZWNyeXB0aW9uXCIsIGZ1bmN0aW9uKCkge1xuICB2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLycpO1xuXG4gIHZhciByZXN1bHQgPSBbXTtcblxuICB2YXIgcHViX2tleSA9IFxuICAgICBbJy0tLS0tQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAnVmVyc2lvbjogR251UEcgdjIuMC4xOSAoR05VL0xpbnV4KScsXG4gICAgICAnVHlwZTogUlNBL1JTQScsXG4gICAgICAnJyxcbiAgICAgICdtSTBFVW1FdlRnRUVBTnlXdFFRTU95YlE5Smx0RHFtYVgwV25OUEplTElMSU0zNnN3NnpMMG5mVFE1elhTUzMrJyxcbiAgICAgICdmSUY2UDI5bEpGeHBibFdrMDJQU0lENXpYL0RZVTkvempNMnhQTzhPYTR4bzBjVlRPVExqKytSaTVtdHIvL2Y1JyxcbiAgICAgICdHTHNJWHhGckJKaEQvZ2hGc0wzT3AwR1hPZUxKOUE1YnNPbjh0aDd4Nkp1Y05LdWFSQjZiUWJTUEFCRUJBQUcwJyxcbiAgICAgICdKRlJsYzNRZ1RXTlVaWE4wYVc1bmRHOXVJRHgwWlhOMFFHVjRZVzF3YkdVdVkyOXRQb2k1QkJNQkFnQWpCUUpTJyxcbiAgICAgICdZUzlPQWhzdkJ3c0pDQWNEQWdFR0ZRZ0NDUW9MQkJZQ0F3RUNIZ0VDRjRBQUNna1FTbU5oT2sxdVFKUXdEQVA2JyxcbiAgICAgICdBZ3JUeXFrUmxKVnF6MnBiNDZUZmJETTJUREY3bzlDQm5CeklHb3hCaGxSd3BxQUx6N3oya3hCRG13cFFhK2tpJyxcbiAgICAgICdCcTNqWk4vVW9zWTl5OGJod01BbG5yRFk5alAxZ2RDbytIMHNENDhDZFh5YmJsTndhWXB3cUM4VlNwRGRUbmRmJyxcbiAgICAgICc5ajJ3RS93ZWloR3AvREFkeS8ya3lCQ2FpT1kxc2poVWZKMUdvZ0Y0OXJDNGpRUlNZUzlPQVFRQTZSL1B0QkZhJyxcbiAgICAgICdKYVQ0anExMHlxQVNrNHNxd1ZNc2M2SGNpZk01bFNkeHpFeEZQNzRuYVVNTXlFc0tIUDUzUXhURjBHcnF1c2FnJyxcbiAgICAgICdRZy9adGdUMENOMUhVTTE1Mnk3QUNPZHAxZ2lLanBNek9UUUNscUNvY2x5dldPRkIrTC9Td0dFSUpmN0xTQ0VyJyxcbiAgICAgICd3b0J1SmlmSmM4eEFWcjBYWDBKdGhvVyt1UDkxZVRRM1hwc0FFUUVBQVlrQlBRUVlBUUlBQ1FVQ1VtRXZUZ0liJyxcbiAgICAgICdMZ0NvQ1JCS1kyRTZUVzVBbEowZ0JCa0JBZ0FHQlFKU1lTOU9BQW9KRU9DRTkwUnNJQ3lYdXFJRUFObW1pUkNBJyxcbiAgICAgICdTRjdZSzdQdkZraWVKTnd6ZUswVjNGMmxHWCt1dTZZM1EvWnhkdHdjNHhSK21lL0NTQm1zVVJ5WFRPMjlPV2hQJyxcbiAgICAgICdHTHN6UEg5elNKVTlCZERpNnYweU5wcm1GUFgvMU5nMEFibi9zQ2t3ZXR2anhDMVlJdlRMRnd0VUwvN3Y2TlMyJyxcbiAgICAgICdiWnBzVXhSVGc5K2NTck1XV1NOamlZOXFVS2FqbTF0dXpQRFpYQVVFQU1ObUFOM3hYTi9Lanl2ajJPSzJjazBYJyxcbiAgICAgICdXNzQ4c2wvdGMzcWlLUE1KKzBBa01GN1BqaG1oOW54cUU5K1FDRWw3cWluRnFxQkxqdXpnVWhCVTRRbHdYMUdEJyxcbiAgICAgICdBdE5UcTZpaExNRDV2MWQ4MlpDN3ROYXRkbERNR1duSWR2RU1DdjJHWmN1SXFEUTlyWFdzNDllN3RxMU5uY0xZJyxcbiAgICAgICdoejN0WWpLaG9GVEtFSXEzeTNQcCcsXG4gICAgICAnPWgvYVgnLFxuICAgICAgJy0tLS0tRU5EIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0nXS5qb2luKCdcXG4nKTtcblxuICB2YXIgcHJpdl9rZXkgPVxuICAgICAgWyctLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpJyxcbiAgICAgICdUeXBlOiBSU0EvUlNBJyxcbiAgICAgICdQd2Q6IGhlbGxvIHdvcmxkJyxcbiAgICAgICcnLFxuICAgICAgJ2xRSCtCRkpoTDA0QkJBRGNsclVFRERzbTBQU1piUTZwbWw5RnB6VHlYaXlDeUROK3JNT3N5OUozMDBPYzEwa3QnLFxuICAgICAgJy9ueUJlajl2WlNSY2FXNVZwTk5qMGlBK2MxL3cyRlBmODR6TnNUenZEbXVNYU5IRlV6a3k0L3ZrWXVacmEvLzMnLFxuICAgICAgJytSaTdDRjhSYXdTWVEvNElSYkM5enFkQmx6bml5ZlFPVzdEcC9MWWU4ZWlibkRTcm1rUWVtMEcwandBUkFRQUInLFxuICAgICAgJy9nTURBdTdMLy9jekJwRTQwcDFacU84SzNrN1VlamVtanNRcWM3a09xbmxEWWQxWjYvM05FQS9VTTMwU2lpcHInLFxuICAgICAgJ0tqZElGWTUraHAwaGNzNkVpaU5xMFBEZm0vVzJqKzdIZnJaNWtwZVFWeERlazRpcmV6WVpybDdKUzJ4ZXphTHYnLFxuICAgICAgJ2swRnYvNmZ4YXNuRnRqT002UWJzdHU2N3M1R3BsOXkwNlp4YlAzVnBUNjIrWGVpYm4vc3dXcmZpSmp1R0VFaE0nLFxuICAgICAgJ2JnbnNNcEh0ekF6L0w4eTZLU3pWaUcvMDVoQmFxcnZrMy9HZUVBNm5FK28wKzBhNnIwTFlMVGVtbXE2RmJhQTEnLFxuICAgICAgJ1BIbyt4N2s3b0ZjQkZVVWVTemd4NzhHY2t1UHdxcjJtTmZlRitJdVNSbnJscFpsM2tjYkhBU1BBT2ZFa3lNWFMnLFxuICAgICAgJ3NXR0U3Z3JDQWpieVF5TTNPRVhUU3lxbmVodkdTLzFSZEI2a0REeEd3Z0UvUUZid055RWg2SzRlYWFBVGhXMmonLFxuICAgICAgJ0lFRUkwV0VuUmtQaTlmWHl4aEZzQ0xTSTFYaHFUYXE3aUROcUpUeEUrQVgyYjladVpYQXhJM1RjLzcrK3ZFeUwnLFxuICAgICAgJzNwMThOL01CMmt0MVdiMWF6bVhXTDJFS2xUMUJaNXlEYUp1QlE4QmhwaE0zdENSVVpYTjBJRTFqVkdWemRHbHUnLFxuICAgICAgJ1ozUnZiaUE4ZEdWemRFQmxlR0Z0Y0d4bExtTnZiVDZJdVFRVEFRSUFJd1VDVW1FdlRnSWJMd2NMQ1FnSEF3SUInLFxuICAgICAgJ0JoVUlBZ2tLQ3dRV0FnTUJBaDRCQWhlQUFBb0pFRXBqWVRwTmJrQ1VNQXdEK2dJSzA4cXBFWlNWYXM5cVcrT2snLFxuICAgICAgJzMyd3pOa3d4ZTZQUWdad2N5QnFNUVlaVWNLYWdDOCs4OXBNUVE1c0tVR3ZwSWdhdDQyVGYxS0xHUGN2RzRjREEnLFxuICAgICAgJ0paNncyUFl6OVlIUXFQaDlMQStQQW5WOG0yNVRjR21LY0tndkZVcVEzVTUzWC9ZOXNCUDhIb29ScWZ3d0hjdjknLFxuICAgICAgJ3BNZ1Ftb2ptTmJJNFZIeWRScUlCZVBhd25RSCtCRkpoTDA0QkJBRHBIOCswRVZvbHBQaU9yWFRLb0JLVGl5ckInLFxuICAgICAgJ1V5eHpvZHlKOHptVkozSE1URVUvdmlkcFF3eklTd29jL25kREZNWFFhdXE2eHFCQ0Q5bTJCUFFJM1VkUXpYbmInLFxuICAgICAgJ0xzQUk1Mm5XQ0lxT2t6TTVOQUtXb0toeVhLOVk0VUg0djlMQVlRZ2wvc3RJSVN2Q2dHNG1KOGx6ekVCV3ZSZGYnLFxuICAgICAgJ1FtMkdoYjY0LzNWNU5EZGVtd0FSQVFBQi9nTURBdTdMLy9jekJwRTQwaVBjcEx6TDdHd0JiV0ZoU1dnU0x5NTMnLFxuICAgICAgJ01kOTlLeHczY0FwV0NvazJFOFI5LzRWUzA0OTB4S1pJYTV5MkkvSzh0aFZocWs5Nlo4S2J0N01STUMxV0xIZ0MnLFxuICAgICAgJ3FKdmtlUUNJNlByRk0wUFVJUExIQVF0REpZS3RhTFh4WXVleGNBZEt6WmozRkhkdExOV0Nvb0s2bjN2SmxMMWMnLFxuICAgICAgJ1dqWmNISjFQSDdVU2xqMWp1cDRYZnhzYnppdXlzUlVTeVhram45MkdaTG0rNjR2Q0lpd2hxQVlvaXpGMk5ISEcnLFxuICAgICAgJ2hSVE40Z1F6eHJ4Z2tlVmNobCthZzdEa1FVREFOSUlWSStBNjNKZUxKZ1dKaUgxZmJZbHdFU0J5SFcrekJGTnQnLFxuICAgICAgJ3FTdGpmSU9oanJmTkljM1J2c2dnYkRkV1FMY2J4bUxaajRzQjB5ZFBTZ1JLb2FVZFJISlkwUzR2cDlvdUtPdGwnLFxuICAgICAgJzJhdS9QMUJQM2JoRDBmRFhsOTFvZWhlWXRoK01TbXNKRkRnL3ZaSnpDSmhGYVE5ZHArMkVuak41YXVOQ05iYUknLFxuICAgICAgJ2JlRkpSSEZmOWNoYThwM2hoK0FLNTROUkNUKytCMk1YWWYrVFB3cVg4OGpZTUJ2OGtrOHZZVWdvODEyOHIxelEnLFxuICAgICAgJ0V6anZpUUU5QkJnQkFnQUpCUUpTWVM5T0Foc3VBS2dKRUVwallUcE5ia0NVblNBRUdRRUNBQVlGQWxKaEwwNEEnLFxuICAgICAgJ0Nna1E0SVQzUkd3Z0xKZTZvZ1FBMmFhSkVJQklYdGdycys4V1NKNGszRE40clJYY1hhVVpmNjY3cGpkRDluRjInLFxuICAgICAgJzNCempGSDZaNzhKSUdheFJISmRNN2IwNWFFOFl1ek04ZjNOSWxUMEYwT0xxL1RJMm11WVU5Zi9VMkRRQnVmK3cnLFxuICAgICAgJ0tUQjYyK1BFTFZnaTlNc1hDMVF2L3UvbzFMWnRtbXhURkZPRDM1eEtzeFpaSTJPSmoycFFwcU9iVzI3TThObGMnLFxuICAgICAgJ0JRUUF3MllBM2ZGYzM4cVBLK1BZNHJaeVRSZGJ2anl5WCsxemVxSW84d243UUNRd1hzK09HYUgyZkdvVDM1QUknLFxuICAgICAgJ1NYdXFLY1dxb0V1TzdPQlNFRlRoQ1hCZlVZTUMwMU9ycUtFc3dQbS9WM3paa0x1MDFxMTJVTXdaYWNoMjhRd0snLFxuICAgICAgJy9ZWmx5NGlvTkQydGRhemoxN3UyclUyZHd0aUhQZTFpTXFHZ1ZNb1FpcmZMYytrPScsXG4gICAgICAnPWx3NWUnLFxuICAgICAgJy0tLS0tRU5EIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgdmFyIHBsYWludGV4dCA9ICdzaG9ydCBtZXNzYWdlXFxubmV4dCBsaW5lXFxu7ZWc6rWt7Ja0L+yhsOyEoOunkCc7XG5cbiAgdmFyIGtleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHB1Yl9rZXkpO1xuXG4gIHZhciBlbmNyeXB0ZWQgPSBvcGVucGdwLmVuY3J5cHRNZXNzYWdlKFtrZXldLCBwbGFpbnRleHQpO1xuXG4gIHZhciBtZXNzYWdlID0gb3BlbnBncC5tZXNzYWdlLnJlYWRBcm1vcmVkKGVuY3J5cHRlZCk7XG5cbiAgdmFyIHByaXZLZXkgPSBvcGVucGdwLmtleS5yZWFkQXJtb3JlZChwcml2X2tleSk7XG5cbiAgcHJpdktleS51bmxvY2soJ2hlbGxvIHdvcmxkJyk7XG5cbiAgdmFyIGRlY3J5cHRlZCA9IG9wZW5wZ3AuZGVjcnlwdE1lc3NhZ2UocHJpdktleSwgbWVzc2FnZSk7XG5cbiAgcmVzdWx0WzBdID0gbmV3IHVuaXQucmVzdWx0KCdFbmNyeXB0IHBsYWluIHRleHQgYW5kIGFmdGVyd2FyZHMgZGVjcnlwdCBsZWFkcyB0byBzYW1lIHJlc3VsdCcsIHBsYWludGV4dCA9PSBkZWNyeXB0ZWQpO1xuXG4gIHJldHVybiByZXN1bHQ7XG5cbn0pO1xuIiwiXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vdW5pdC5qcycpO1xuXG5yZXF1aXJlKCcuL2NyeXB0by9oYXNoL3NoYS5qcycpO1xucmVxdWlyZSgnLi9jcnlwdG8vaGFzaC9tZDUuanMnKTtcbnJlcXVpcmUoJy4vY3J5cHRvL2hhc2gvcmlwZW1kLmpzJyk7XG5cbnJlcXVpcmUoJy4vY3J5cHRvL2NpcGhlci9hZXMuanMnKTtcbnJlcXVpcmUoJy4vY3J5cHRvL2NpcGhlci9ibG93ZmlzaC5qcycpO1xucmVxdWlyZSgnLi9jcnlwdG8vY2lwaGVyL2Nhc3Q1LmpzJyk7XG5yZXF1aXJlKCcuL2NyeXB0by9jaXBoZXIvZGVzLmpzJyk7XG5yZXF1aXJlKCcuL2NyeXB0by9jaXBoZXIvdHdvZmlzaC5qcycpO1xuXG5yZXF1aXJlKCcuL2NyeXB0by9vcGVucGdwLmNyeXB0by5qcycpO1xucmVxdWlyZSgnLi9jcnlwdG8vb3BlbnBncC5zaWdjaGVjay5qcycpO1xuXG5yZXF1aXJlKCcuL2dlbmVyYWwvb3BlbnBncC5iYXNpYy5qcycpO1xuIiwidmFyIHByb2Nlc3M9cmVxdWlyZShcIl9fYnJvd3NlcmlmeV9wcm9jZXNzXCIpO1xubW9kdWxlLmV4cG9ydHMgPSB7XG5cdHRlc3RzOiBbXSxcblx0cmVnaXN0ZXI6IGZ1bmN0aW9uKHN0cl90aXRsZSwgZnVuY19ydW50ZXN0KSB7XG5cdFx0dGhpcy50ZXN0cy5wdXNoKHsgdGl0bGU6IHN0cl90aXRsZSwgcnVuOiBmdW5jX3J1bnRlc3QgfSk7XG5cdH0sXG5cdFxuXHRydW46IGZ1bmN0aW9uKCkge1xuXHRcdHZhciB0ZXN0ID0gdGhpcy50ZXN0cy5zaGlmdCgpO1xuXG5cdFx0dmFyIHJlc3VsdCA9IHtcblx0XHRcdHRpdGxlOiB0ZXN0LnRpdGxlXG5cdFx0fTtcblxuXG5cdFx0cmVzdWx0LnRlc3RzID0gdGVzdC5ydW4oKTtcblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0cnVuX2FsbDogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIHBhc3NlZCA9IHRydWU7XG5cblx0XHR3aGlsZSh0aGlzLnRlc3RzLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciByZXN1bHQgPSB0aGlzLnJ1bigpO1xuXG5cdFx0XHRjb25zb2xlLmxvZygnVGVzdDogJyArIHJlc3VsdC50aXRsZSk7XG5cblx0XHRcdGZvcih2YXIgaSBpbiByZXN1bHQudGVzdHMpIHtcblxuXHRcdFx0XHR2YXIgcmVzID0gcmVzdWx0LnRlc3RzW2ldLnJlc3VsdCA/XG5cdFx0XHRcdFx0J1NVQ0NFU1MnIDogJ0ZBSUxFRCc7XG5cblx0XHRcdFx0Y29uc29sZS5sb2cocmVzdWx0LnRlc3RzW2ldLmRlc2NyaXB0aW9uICsgJyAnICsgcmVzKTtcblxuXHRcdFx0XHRwYXNzZWQgPSBwYXNzZWQgJiYgcmVzdWx0LnRlc3RzW2ldLnJlc3VsdDtcblx0XHRcdH1cdFx0XHRcdFxuXHRcdH1cblxuXHRcdGlmKCFwYXNzZWQpIHByb2Nlc3MuZXhpdCgxKTtcblx0fSxcblx0XHRcblx0cmVzdWx0OiBmdW5jdGlvbihzdHJfZGVzY3JpcHRpb24sIGJvb2xlYW5fcmVzdWx0KSB7XG5cdFx0dGhpcy5kZXNjcmlwdGlvbiA9IHN0cl9kZXNjcmlwdGlvbjtcblx0XHR0aGlzLnJlc3VsdCA9IGJvb2xlYW5fcmVzdWx0O1xuXHR9XG59XG5cbiJdfQ==
;