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 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 . You should have received a copy of the Apache License along with JSXCompressor. If not, see . */ /** * @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]+"
"); 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("
len:" + len + " treepos:" + treepos); if (len == 17) { //war 17 return -1; } treepos++; len++; tmp = IsPat(); if (debug) document.write("
IsPat " + tmp); if (tmp >= 0) { curplace.b0 = tmp; /* leaf cell for 0-bit */ if (debug) document.write("
b0 " + curplace.b0); } else { /* Not a Leaf cell */ curplace.b0 = 0x8000; if (debug) document.write("
b0 " + curplace.b0); if (Rec()) return -1; } tmp = IsPat(); if (tmp >= 0) { curplace.b1 = tmp; /* leaf cell for 1-bit */ if (debug) document.write("
b1 " + curplace.b1); curplace.jump = null; /* Just for the display routine */ } else { /* Not a Leaf cell */ curplace.b1 = 0x8000; if (debug) document.write("
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("
createtree
"); 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('
Tree: ' + Places.length); for (var a = 0; a < 32; a++) { document.write("Places[" + a + "].b0=" + Places[a].b0 + "
"); document.write("Places[" + a + "].b1=" + Places[a].b1 + "
"); } } /*if(show) { var tmp; for(tmp=currentTree;tmpjump?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:'�'); } 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:'�'); } 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("
param: "+literalCodes+" "+distCodes+" "+lenCodes+"
"); for (j = 0; j < 19; j++) { ll[j] = 0; } // Get the decode tree code lengths //document.write("
"); for (j = 0; j < lenCodes; j++) { ll[border[j]] = readBits(3); //document.write(ll[border[j]]+" "); } //fprintf(errfp, "\n"); //document.write('
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("
distanceTree"); for (var a = 0; a < distanceTree.length; a++) { document.write("
" + 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('
tree created'); //read in literal and distance code lengths n = literalCodes + distCodes; i = 0; var z = -1; if (debug) document.write("
n=" + n + " bits: " + bits + "
"); while (i < n) { z++; j = DecodeValue(distanceTree); if (debug) document.write("
" + z + " i:" + i + " decode: " + j + " bits " + bits + "
"); 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; jliteralTree"); 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"); } */ //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<>= 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 "data" containing the bytes. */ function dearmor(text) { text = text.replace(/\r/g, ''); var type = get_type(text); if (type != 2) { var splittedtext = text.split('-----'); var result = { data: base64.decode( splittedtext[2] .split('\n\n')[1] .split("\n=")[0] .replace(/\n- /g, "\n")), type: type }; if (verifyCheckSum(result.data, splittedtext[2] .split('\n\n')[1] .split("\n=")[1] .split('\n')[0])) return result; 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(result.data)) + "'"; return false; } } else { var splittedtext = text.split('-----'); var result = { text: splittedtext[2] .replace(/\n- /g, "\n") .split("\n\n")[1], data: base64.decode(splittedtext[4] .split("\n\n")[1] .split("\n=")[0]), type: type }; if (verifyCheckSum(result.data, 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 body * @param {Integer} partindex * @param {Integer} parttotal * @returns {String} Armored text */ function armor(messagetype, body, 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(body); result += "\r\n=" + getCheckSum(body) + "\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(body); result += "\r\n=" + getCheckSum(body) + "\r\n"; result += "-----END PGP MESSAGE, PART " + partindex + "-----\r\n"; break; case enums.armor.signed: result += "\r\n-----BEGIN PGP SIGNED MESSAGE-----\r\n"; result += "Hash: " + body.hash + "\r\n\r\n"; result += body.text.replace(/\n-/g, "\n- -"); result += "\r\n-----BEGIN PGP SIGNATURE-----\r\n"; result += armor_addheader(); result += base64.encode(body.data); result += "\r\n=" + getCheckSum(body.data) + "\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(body); result += "\r\n=" + getCheckSum(body) + "\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(body); result += "\r\n=" + getCheckSum(body) + "\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(body); result += "\r\n=" + getCheckSum(body) + "\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, key_expiration_time: 9, placeholder_backwards_compatibility: 10, preferred_symmetric_algorithms: 11, revocation_key: 12, issuer: 16, notation_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 }, keyFlags: { // 0x01 - This key may be used to certify other keys. certify_keys: 1, // 0x02 - This key may be used to sign data. sign_data: 2, // 0x04 - This key may be used to encrypt communications. encrypt_communication: 4, // 0x08 - This key may be used to encrypt storage. encrypt_storage: 8, // 0x10 - The private component of this key may have been split // by a secret-sharing mechanism. split_private_key: 16, // 0x20 - This key may be used for authentication. authentication: 32, // 0x80 - The private component of this key may be in the // possession of more than one person. shared_private_key: 128 }, 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(); /** * 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; } function findKey(keys, keyIds) { 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])) { return keys[i]; } } } return null; } /** * Returns first public key packet for given array of key IDs * @param {[keyid]} keyIds * @return {public_subkey|packet_public_key|null} */ this.getPublicKeyPacket = function(keyIds) { var keys = this.packets.filterByTag(enums.packet.public_key, enums.packet.public_subkey); return findKey(keys, keyIds); } /** * Returns first private key packet for given array of key IDs * @param {[keyid]} keyIds * @return {secret_subkey|packet_secret_key|null} */ this.getPrivateKeyPacket = function(keyIds) { var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey); return findKey(keys, keyIds); } /** * 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 key as public key * @return {key} public key */ this.toPublic = function() { for (var i = 0; i < this.packets.length; i++) { if (this.packets[i].tag == enums.packet.secret_key) { var bytes = this.packets[i].writePublicKey(); var pubKeyPacket = new packet.public_key(); pubKeyPacket.read(bytes); this.packets[i] = pubKeyPacket; } if (this.packets[i].tag == enums.packet.secret_subkey) { var bytes = this.packets[i].writePublicKey(); var pubSubkeyPacket = new packet.public_subkey(); pubSubkeyPacket.read(bytes); this.packets[i] = pubSubkeyPacket; } } return this; } /** * Returns ASCII armored text of key * @return {String} ASCII armor */ this.armor = function() { var type = this.isPublic() ? enums.armor.public_key : enums.armor.private_key; return armor.encode(type, this.packets.write()); } /** * 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 {Boolean} true if all key and subkey packets decrypted successfully */ this.decrypt = function(passphrase) { var keys = this.packets.filterByTag(enums.packet.secret_key, enums.packet.secret_subkey); for (var i = 0; i < keys.length; i++) { var success = keys[i].decrypt(passphrase); if (!success) return false; } return true; } /** * Decrypts specific key packets by key ID * @param {[keyid]} keyIds * @param {String} passphrase * @return {Boolean} true if all key packets decrypted successfully */ this.decryptKeyPacket = function(keyIds, passphrase) { //TODO return value 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])) { var success = keys[i].decrypt(passphrase); if (!success) return false; } } } return true; } // 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).data; 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, '')).data; 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'); var util = require('./util'); /** * @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 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; } /** * Returns the key IDs of the keys that signed the message * @return {[keyId]} array of keyid objects */ this.getSigningKeyIds = function() { var keyIds = []; var msg = this.unwrapCompressed(); // search for one pass signatures var onePassSigList = msg.packets.filterByTag(enums.packet.one_pass_signature); onePassSigList.forEach(function(packet) { keyIds.push(packet.signingKeyId); }); // if nothing found look for signature packets if (!keyIds.length) { var signatureList = msg.packets.filterByTag(enums.packet.signature); signatureList.forEach(function(packet) { keyIds.push(packet.issuerKeyId); }); } return keyIds; } /** * Decrypt the message * @param {key} privateKey private key with decrypted secret data * @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); if (!privateKeyPacket.isDecrypted) throw new Error('Private key is not decrypted.'); 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.getLiteralData = function() { var literal = this.packets.findPacket(enums.packet.literal); return literal && literal.data || null; } /** * Get literal data as text * @return {String|null} literal body of the message interpreted as text */ this.getText = function() { var literal = this.packets.findPacket(enums.packet.literal); if (literal) { var data = literal.data; if (literal.format == enums.read(enums.literal, enums.literal.binary) || literal.format == enums.read(enums.literal, enums.literal.text)) { // text in a literal packet with format 'binary' or 'text' could be utf8, therefore decode data = util.decode_utf8(data); } return data; } else { return 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); } /** * Sign the message (the literal data packet of the message) * @param {[key]} privateKey private keys with decrypted secret key data for signing * @return {message} new message with signed content */ this.sign = function(privateKeys) { var packetlist = new packet.list(); var literalDataPacket = this.packets.findPacket(enums.packet.literal); if (!literalDataPacket) throw new Error('No literal data packet to sign.'); var literalFormat = enums.write(enums.literal, literalDataPacket.format); var signatureType = literalFormat == enums.literal.binary ? enums.signature.binary : enums.signature.text; for (var i = 0; i < privateKeys.length; i++) { var onePassSig = new packet.one_pass_signature(); onePassSig.type = signatureType; //TODO get preferred hashg algo from key signature onePassSig.hashAlgorithm = config.prefer_hash_algorithm; var signingKeyPacket = privateKeys[i].getSigningKeyPacket(); onePassSig.publicKeyAlgorithm = signingKeyPacket.algorithm; onePassSig.signingKeyId = signingKeyPacket.getKeyId(); packetlist.push(onePassSig); } packetlist.push(literalDataPacket); for (var i = privateKeys.length - 1; i >= 0; i--) { var signaturePacket = new packet.signature(); signaturePacket.signatureType = signatureType; signaturePacket.hashAlgorithm = config.prefer_hash_algorithm; signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm; if (!signingKeyPacket.isDecrypted) throw new Error('Private key is not decrypted.'); signaturePacket.sign(signingKeyPacket, literalDataPacket); packetlist.push(signaturePacket); } return new message(packetlist); } /** * Verify message signatures * @param {[key]} publicKeys public keys to verify signatures * @return {[{'keyid': keyid, 'valid': Boolean}]} list of signer's keyid and validity of signature */ this.verify = function(publicKeys) { var result = []; var msg = this.unwrapCompressed(); var literalDataList = msg.packets.filterByTag(enums.packet.literal); if (literalDataList.length !== 1) throw new Error('Can only verify message with one literal data packet.'); var signatureList = msg.packets.filterByTag(enums.packet.signature); publicKeys.forEach(function(pubKey) { for (var i = 0; i < signatureList.length; i++) { var publicKeyPacket = pubKey.getPublicKeyPacket([signatureList[i].issuerKeyId]); if (publicKeyPacket) { var verifiedSig = {}; verifiedSig.keyid = signatureList[i].issuerKeyId; verifiedSig.status = signatureList[i].verify(publicKeyPacket, literalDataList[0]); result.push(verifiedSig); break; } } }); return result; } /** * Unwrap compressed message * @return {message} message Content of compressed message */ this.unwrapCompressed = function() { var compressed = this.packets.filterByTag(enums.packet.compressed); if (compressed.length) { return new message(compressed[0].packets); } else { return this; } } /** * Returns ASCII armored text of message * @return {String} ASCII armor */ this.armor = function() { return armor.encode(enums.armor.message, this.packets.write()); } /** * 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).data; 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,"./util":56}],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 text 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; } /** * Signs message text and encrypts it * @param {[key]} publicKeys array of keys, used to encrypt the message * @param {key} privateKey private key with decrypted secret key data for signing * @param {String} text message as native JavaScript string * @return {String} encrypted ASCII armored message */ function signAndEncryptMessage(publicKeys, privateKey, text) { var msg = message.fromText(text); msg = msg.sign([privateKey]); msg = msg.encrypt(publicKeys); var armored = armor.encode(enums.armor.message, msg.packets.write()); return armored; } /** * Decrypts message * @param {key} privateKey private key with decrypted secret key data * @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.getText(); } /** * Decrypts message and verifies signatures * @param {key} privateKey private key with decrypted secret key data * @param {[key]} publicKeys public keys to verify signatures * @param {message} message the message object with signed and encrypted data * @return {{'text': String, signatures: [{'keyid': keyid, 'status': Boolean}]}} * decrypted message as as native JavaScript string * with verified signatures or null if no literal data found */ function decryptAndVerifyMessage(privateKey, publicKeys, message) { var result = {}; message = message.decrypt(privateKey); result.text = message.getText(); if (result.text) { result.signatures = message.verify(publicKeys); return result; } return null; } 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 * " * @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.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.keyFlags = [enums.keyFlags.certify_keys | enums.keyFlags.sign_data]; 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.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.keyFlags = [enums.keyFlags.encrypt_communication | enums.keyFlags.encrypt_storage]; subkeySignaturePacket.sign(secretKeyPacket, 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.signAndEncryptMessage = signAndEncryptMessage; this.decryptAndVerifyMessage = decryptAndVerifyMessage 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 * @return {packet_one_pass_signature} 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 * @return {String} a string representation of a one-pass signature packet */ this.write = function() { var result = ""; result += String.fromCharCode(3); result += String.fromCharCode(enums.write(enums.signature, this.type)); result += String.fromCharCode(enums.write(enums.hash, this.hashAlgorithm)); result += String.fromCharCode(enums.write(enums.publicKey, this.publicKeyAlgorithm)); result += this.signingKeyId.write(); result += String.fromCharCode(this.flags); 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 = 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 {packet|null} */ 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<num> * @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) return 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 */ 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. var parsedMPI = parse_cleartext_mpi('mod', bytes.substr(1), this.algorithm); if (parsedMPI instanceof Error) throw parsedMPI; this.mpi = this.mpi.concat(parsedMPI); this.isDecrypted = true; } }; /** Creates an OpenPGP key packet for the given key. * @return {String} A string of bytes containing the secret key OpenPGP packet */ 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 or MPI already * decrypted; false if not */ this.decrypt = function(passphrase) { if (this.isDecrypted) return true; 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'; var parsedMPI = parse_cleartext_mpi(hash, cleartext, this.algorithm); if (parsedMPI instanceof Error) return false; this.mpi = this.mpi.concat(parsedMPI); this.isDecrypted = true; return true; }; this.generate = function(bits) { 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'), type_keyid = require('../type/keyid.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.version = null; this.signatureType = null; this.hashAlgorithm = null; this.publicKeyAlgorithm = null; this.signatureData = null; this.signedHashValue = null; this.mpi = null; this.created = new Date(); 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 = new type_keyid(); this.notation = null; 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.features = 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; this.version = bytes[i++].charCodeAt(); // switch on version (3 and 4) switch (this.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(sigpos, i); // Eight-octet Key ID of signer. this.issuerKeyId.read(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) { // Two-octet scalar octet count for following subpacket data. var subpacket_length = util.readNumber( bytes.substr(0, 2)); var i = 2; // 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; this.read_sub_packet(bytes.substr(i, len.len)); i += len.len; } return i; } // hashed subpackets 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); // unhashed subpackets 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); this.issuerKeyId = key.getKeyId(); // Add hashed subpackets result += this.write_all_sub_packets(); 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 string of bytes with all subpacket data * @return {String} a string-representation of a all subpacket data */ this.write_all_sub_packets = function() { var sub = enums.signatureSubpacket; var result = ''; var bytes = ''; if (this.created !== null) { result += write_sub_packet(sub.signature_creation_time, util.writeDate(this.created)); } if (this.signatureExpirationTime !== null) { result += write_sub_packet(sub.signature_expiration_time, util.writeDate(this.signatureExpirationTime)); } if (this.exportable !== null) { result += write_sub_packet(sub.exportable_certification, String.fromCharCode(this.exportable ? 1 : 0)); } if (this.trustLevel !== null) { bytes = String.fromCharCode(this.trustLevel) + String.fromCharCode(this.trustAmount); result += write_sub_packet(sub.trust_signature, bytes); } if (this.regularExpression !== null) { result += write_sub_packet(sub.regular_expression, this.regularExpression); } if (this.revocable !== null) { result += write_sub_packet(sub.revocable, String.fromCharCode(this.revocable ? 1 : 0)); } if (this.keyExpirationTime !== null) { result += write_sub_packet(sub.key_expiration_time, util.writeDate(this.keyExpirationTime)); } if (this.preferredSymmetricAlgorithms !== null) { bytes = util.bin2str(this.preferredSymmetricAlgorithms); result += write_sub_packet(sub.preferred_symmetric_algorithms, bytes); } if (this.revocationKeyClass !== null) { bytes = String.fromCharCode(this.revocationKeyClass); bytes += String.fromCharCode(this.revocationKeyAlgorithm); bytes += this.revocationKeyFingerprint; result += write_sub_packet(sub.revocation_key, bytes); } if (!this.issuerKeyId.isNull()) { result += write_sub_packet(sub.issuer, this.issuerKeyId.write()); } if (this.notation !== null) { for (var name in this.notation) { if (this.notation.hasOwnProperty(name)) { var value = this.notation[name]; bytes = String.fromCharCode(0x80); bytes += String.fromCharCode(0); bytes += String.fromCharCode(0); bytes += String.fromCharCode(0); // 2 octets of name length bytes += util.writeNumber(name.length, 2); // 2 octets of value length bytes += util.writeNumber(value.length, 2); bytes += name + value; result += write_sub_packet(sub.notation_data, bytes); } } } if (this.preferredHashAlgorithms !== null) { bytes = util.bin2str(this.preferredHashAlgorithms); result += write_sub_packet(sub.preferred_hash_algorithms, bytes); } if (this.preferredCompressionAlgorithms !== null) { bytes = util.bin2str(this.preferredCompressionAlgorithms); result += write_sub_packet(sub.preferred_hash_algorithms, bytes); } if (this.keyServerPreferences !== null) { bytes = util.bin2str(this.keyServerPreferences); result += write_sub_packet(sub.key_server_preferences, bytes); } if (this.preferredKeyServer !== null) { result += write_sub_packet(sub.preferred_key_server, this.preferredKeyServer); } if (this.isPrimaryUserID !== null) { result += write_sub_packet(sub.primary_user_id, String.fromCharCode(this.isPrimaryUserID ? 1 : 0)); } if (this.policyURI !== null) { result += write_sub_packet(sub.policy_uri, this.policyURI); } if (this.keyFlags !== null) { bytes = util.bin2str(this.keyFlags); result += write_sub_packet(sub.key_flags, bytes); } if (this.signersUserId !== null) { result += write_sub_packet(sub.signers_user_id, this.signersUserId); } if (this.reasonForRevocationFlag !== null) { bytes = String.fromCharCode(this.reasonForRevocationFlag); bytes += this.reasonForRevocationString; result += write_sub_packet(sub.reason_for_revocation, bytes); } if (this.features !== null) { bytes = util.bin2str(this.features); result += write_sub_packet(sub.features, bytes); } if (this.signatureTargetPublicKeyAlgorithm !== null) { bytes = String.fromCharCode(this.signatureTargetPublicKeyAlgorithm); bytes += String.fromCharCode(this.signatureTargetHashAlgorithm); bytes += this.signatureTargetHash; result += write_sub_packet(sub.signature_target, bytes); } if (this.embeddedSignature !== null) { result += write_sub_packet(sub.embedded_signature, this.embeddedSignature.write()); } result = util.writeNumber(result.length, 2) + result; return result; }; /** * 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.read(bytes.substr(mypos)); 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.readNumber(bytes.substr(mypos, 2)); mypos += 2 var n = util.readNumber(bytes.substr(mypos, 2)); mypos += 2 var name = bytes.substr(mypos, m), value = bytes.substr(mypos + m, n); this.notation = this.notation || {}; 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: // conversion to CRLF line endings done in literal data packet case t.text: return data.getBytes(); 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.third_party: throw new Error('Not implemented'); break; default: throw new Error('Unknown signature type.') } } this.calculateTrailer = function() { // calculating the trailer var trailer = ''; // V3 signatures don't have a trailer if (this.version == 3) return 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|Object} data data which on the signature applies * @param {public_subkey|packet_public_key} 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/keyid.js":53,"../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 */ 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 > 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 config = require('../config'); 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. * @param {String} str String of the debug message */ this.print_debug = function(str) { if (config.debug) { console.log(str); } }; /** * Helper function to print a debug message. Debug * messages are only printed if * openpgp.config.debug is set to true. * Different than print_debug because will call hexstrdump iff necessary. * @param {String} str String of the debug message */ this.print_debug_hexstr_dump = function(str, strToHex) { if (config.debug) { str = str + this.hexstrdump(strToHex); console.log(str); } }; /** * Helper function to print an error message. * @param {String} str String of the error message */ this.print_error = function(str) { if (config.debug) throw str; console.log(str); }; /** * Helper function to print an info message. * @param {String} str String of the info message */ this.print_info = function(str) { if (config.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(); },{"../config":3}],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":72}],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":72}],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":72}],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":72}],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":72}],62:[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":72}],63:[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":72}],64:[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":72}],65:[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":72}],66:[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, 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); var keyids = msg.getEncryptionKeyIds(); privKey.decryptKeyPacket(keyids, 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 ', 'hello world')); result.push(testHelper('●●●●', '♔♔♔♔ ', 'łäóć')); return result; }); unit.register("Message 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); // get key IDs the message is encrypted for var keyids = message.getEncryptionKeyIds(); // decrypt only required key packets var success = privKey.decryptKeyPacket(keyids, 'hello what?') result.push(new unit.result('Decrypting key packet with wrong password returns false', !success)); var decrypted, error; try { decrypted = openpgp.decryptMessage(privKey, message); } catch (e) { error = e; } result.push(new unit.result('Calling decryptMessage with not decrypted key packet leads to exception: \'' + (error || '') + '\'', error)); success = privKey.decryptKeyPacket(keyids, 'hello world'); result.push(new unit.result('Decrypting key packet with correct password returns true', success)); decrypted = openpgp.decryptMessage(privKey, message); result.push(new unit.result('Encrypt plain text and afterwards decrypt leads to same result', plaintext == decrypted)); return result; }); },{"../../":28,"../unit.js":72}],67:[function(require,module,exports){ var unit = require('../unit.js'); unit.register("Keyring testing", function() { var openpgp = require('../../'); var keyring = require('../../src/keyring.js'); var result = []; // 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":72}],68:[function(require,module,exports){ var unit = require('../unit.js'); unit.register("Packet testing", function() { var openpgp = require('../../'); var armored_key = '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'lQH+BFF79J8BBADDhRUOMUSGdYM1Kq9J/vVS3qLfaZHweycAKm9SnpLGLJE+Qbki\n' + 'JRXLAhxZ+HgVThR9VXs8wbPR2UXnDhMJGe+VcMA0jiwIOEAF0y9M3ZQsPFWguej2\n' + '1ZycgOwxYHehbKdPqRK+nFgFbhvg6f6x2Gt+a0ZbvivGL1BqSSGsL+dchQARAQAB\n' + '/gMDAijatUNeUFZSyfg16x343/1Jo6u07LVTdH6Bcbx4yBQjEHvlgb6m1eqEIbZ1\n' + 'holVzt0fSKTzmlxltDaOwFLf7i42lqNoWyfaqFrOblJ5Ays7Q+6xiJTBROG9po+j\n' + 'Z2AE+hkBIwKghB645OikchR4sn9Ej3ipea5v9+a7YimHlVmIiqgLDygQvXkzXVaf\n' + 'Zi1P2wB7eU6If2xeeX5GSR8rWo+I7ujns0W8S9PxBHlH3n1oXUmFWsWLZCY/qpkD\n' + 'I/FroBhXxBVRpQhQmdsWPUdcgmQTEj8jnP++lwSQexfgk2QboAW7ODUA8Cl9oy87\n' + 'Uor5schwwdD3oRoLGcJZfR6Dyu9dCYdQSDWj+IQs95hJQfHNcfj7XFtTyOi7Kxx0\n' + 'Jxio9De84QnxNAoNYuLtwkaRgkUVKVph2nYWJfAJunuMMosM2WdcidHJ5d6RIdxB\n' + 'U6o3T+d8BPXuRQEZH9+FkDkb4ihakKO3+Zcon85e1ZUUtB1QYXRyaWNrIDxwYXRy\n' + 'aWNrQGV4YW1wbGUuY29tPoi5BBMBAgAjBQJRe/SfAhsDBwsJCAcDAgEGFQgCCQoL\n' + 'BBYCAwECHgECF4AACgkQObliSdM/GEJbjgP/ffei4lU6fXp8Qu0ubNHh4A6swkTO\n' + 'b3suuBELE4A2/pK5YnW5yByFFSi4kq8bJp5O6p9ydXpOA38t3aQ8wrbo0yDvGekr\n' + '1S1HWOLgCaY7rEDQubuCOHd2R81/VQOJyG3zgX4KFIgkVyV9BZXUpz4PXuhMORmv\n' + '81uzej9r7BYkJ6GdAf4EUXv0nwEEAKbO02jtGEHet2fQfkAYyO+789sTxyfrUy5y\n' + 'SAf5n3GgkuiHz8dFevhgqYyMK0OYEOCZqdd1lRBjL6Us7PxTljHc2jtGhoAgE4aZ\n' + 'LKarI3j+5Oofcaq0+S0bhqiQ5hl6C4SkdYOEeJ0Hlq2008n0pJIlU4E5yIu0oNvb\n' + '4+4owTpRABEBAAH+AwMCKNq1Q15QVlLJyeuGBEA+7nXS3aSy6mE4lR5f3Ml5NRqt\n' + 'jm6Q+UUI69DzhLGX4jHRxna6NMP74S3CghOz9eChMndkfWLC/c11h1npzLci+AwJ\n' + '45xMbw/OW5PLlaxdtkg/SnsHpFGCAuTUWY87kuWoG0HSVMn9Clm+67rdicOW6L5a\n' + 'ChfyWcVZ+Hvwjx8YM0/j11If7oUkCZEstSUeJYOI10JQLhNLpDdkB89vXhAMaCuU\n' + 'Ijhdq0vvJi6JruKQGPK+jajJ4MMannpQtKAvt8aifqpdovYy8w4yh2pGkadFvrsZ\n' + 'mxpjqmmawab6zlOW5WrLxQVL1cQRdrIQ7jYtuLApGWkPfytSCBZ20pSyWnmkxd4X\n' + 'OIms6BjqrP9LxBEXsPBwdUA5Iranr+UBIPDxQrTp5k0DJhXBCpJ1k3ZT+2dxiRS2\n' + 'sk83w2VUBnXdYWZx0YlMqr3bDT6J5fO+8V8pbgY5BkHRCFMacFx45km/fvmInwQY\n' + 'AQIACQUCUXv0nwIbDAAKCRA5uWJJ0z8YQqb3A/97njLl33OQYXVp9OTk/VgE6O+w\n' + 'oSYa+6xMOzsk7tluLIRQtnIprga/e8vEZXGTomV2a77HBksg+YjlTh/l8oMuaoxG\n' + 'QNkMpoRJKPip29RTW4gLdnoJVekZ/awkBN2S3NMArOZGca8U+M1IuV7OyVchSVSl\n' + 'YRlci72GHhlyos8YHA==\n' + '=KXkj\n' + '-----END PGP PRIVATE KEY BLOCK-----'; var tests = [function() { var message = new openpgp.packet.list(); var literal = new openpgp.packet.literal(); literal.set('Hello world', 'utf8'); var enc = new openpgp.packet.symmetrically_encrypted(); message.push(enc); enc.packets.push(literal); var key = '12345678901234567890123456789012', algo = 'aes256'; enc.encrypt(algo, key); var msg2 = new openpgp.packet.list(); msg2.read(message.write()); msg2[0].decrypt(algo, key); return new unit.result('Symmetrically encrypted packet', msg2[0].packets[0].data == literal.data); }, function() { var key = '12345678901234567890123456789012', algo = 'aes256'; var literal = new openpgp.packet.literal(), enc = new openpgp.packet.sym_encrypted_integrity_protected(), msg = new openpgp.packet.list(); msg.push(enc); literal.set('Hello world!', 'utf8'); enc.packets.push(literal); enc.encrypt(algo, key); var msg2 = new openpgp.packet.list(); msg2.read(msg.write()); msg2[0].decrypt(algo, key); return new unit.result('Sym. encrypted integrity protected packet', msg2[0].packets[0].data == literal.data); }, function() { var msg = '-----BEGIN PGP MESSAGE-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'jA0ECQMCpo7I8WqsebTJ0koBmm6/oqdHXJU9aPe+Po+nk/k4/PZrLmlXwz2lhqBg\n' + 'GAlY9rxVStLBrg0Hn+5gkhyHI9B85rM1BEYXQ8pP5CSFuTwbJ3O2s67dzQ==\n' + '=VZ0/\n' + '-----END PGP MESSAGE-----'; var msgbytes = openpgp.armor.decode(msg).data; var parsed = new openpgp.packet.list(); parsed.read(msgbytes); parsed[0].decrypt('test'); var key = parsed[0].sessionKey; parsed[1].decrypt(parsed[0].sessionKeyAlgorithm, key); var compressed = parsed[1].packets[0]; var result = compressed.packets[0].data; return new unit.result('Sym encrypted session key with a compressed packet', result == 'Hello world!\n'); }, function() { var rsa = new openpgp.crypto.publicKey.rsa(), mpi = rsa.generate(512, "10001") var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u]; mpi = mpi.map(function(k) { var mpi = new openpgp.mpi(); mpi.fromBigInteger(k); return mpi; }); var enc = new openpgp.packet.public_key_encrypted_session_key(), msg = new openpgp.packet.list(), msg2 = new openpgp.packet.list(); enc.sessionKey = '12345678901234567890123456789012'; enc.publicKeyAlgorithm = 'rsa_encrypt'; enc.sessionKeyAlgorithm = 'aes256'; enc.publicKeyId.bytes = '12345678'; enc.encrypt({ mpi: mpi }); msg.push(enc); msg2.read(msg.write()); msg2[0].decrypt({ mpi: mpi }); return new unit.result('Public key encrypted symmetric key packet', msg2[0].sessionKey == enc.sessionKey && msg2[0].sessionKeyAlgorithm == enc.sessionKeyAlgorithm); }, function() { var armored_key = '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'lQHYBFF33iMBBAC9YfOYahJlWrVj2J1TjQiZLunWljI4G9e6ARTyD99nfOkV3swh\n' + '0WaOse4Utj7BfTqdYcoezhCaQpuExUupKWZqmduBcwSmEBfNu1XyKcxlDQuuk0Vk\n' + 'viGC3kFRce/cJaKVFSRU8V5zPgt6KQNv/wNz7ydEisaSoNbk51vQt5oGfwARAQAB\n' + 'AAP5AVL8xWMuKgLj9g7/wftMH+jO7vhAxje2W3Y+8r8TnOSn0536lQvzl/eQyeLC\n' + 'VK2k3+7+trgO7I4KuXCXZqgAbEi3niDYXDaCJ+8gdR9qvPM2gi9NM71TGXZvGE0w\n' + 'X8gIZfqLTQWKm9TIS/3tdrth4nwhiye0ASychOboIiN6VIECAMbCQ4/noxGV6yTK\n' + 'VezsGSz+iCMxz2lV270/Ac2C5WPk+OlxXloxUXeEkGIr6Xkmhhpceed2KL41UC8Y\n' + 'w5ttGIECAPPsahniKGyqp9CHy6W0B83yhhcIbmLlaVG2ftKyUEDxIggzOlXuVrue\n' + 'z9XRd6wFqwDd1QMFW0uUyHPDCIFPnv8CAJaDFSZutuWdWMt15NZXjfgRgfJuDrtv\n' + 'E7yFY/p0el8lCihOT8WoHbTn1PbCYMzNBc0IhHaZKAtA2pjkE+wzz9ClP7QbR2Vv\n' + 'cmdlIDxnZW9yZ2VAZXhhbXBsZS5jb20+iLkEEwECACMFAlF33iMCGwMHCwkIBwMC\n' + 'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRBcqs36fwJCXRbvA/9LPiK6WFKcFoNBnLEJ\n' + 'mS/CNkL8yTpkslpCP6+TwJMc8uXqwYl9/PW2+CwmzZjs6JsvTzMcR/ZbfZJuSW6Y\n' + 'EsLNejsSpgcY9aiewGtE+53e5oKYnlmVMTWOPywciIgMvXlzdGhxcwqJ8u0hT+ug\n' + '9CjcAfuX9yw85LwXtdGwNh7J8Q==\n' + '=lKiS\n' + '-----END PGP PRIVATE KEY BLOCK-----'; key = new openpgp.packet.list(); key.read(openpgp.armor.decode(armored_key).data); key = key[0]; var enc = new openpgp.packet.public_key_encrypted_session_key(), secret = '12345678901234567890123456789012'; enc.sessionKey = secret; enc.publicKeyAlgorithm = 'rsa_encrypt'; enc.sessionKeyAlgorithm = 'aes256'; enc.publicKeyId.bytes = '12345678'; enc.encrypt(key); enc.decrypt(key); return new unit.result('Secret key packet (reading, unencrpted)', enc.sessionKey == secret); }, function() { var armored_key = '-----BEGIN PGP PRIVATE KEY BLOCK-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'lQHYBFF6gtkBBADKUOWZK6/V75MNwBS+hLYicoS0Sojbo3qWXXpS7eM+uhiDm4bP\n' + 'DNjdNVA0R+TCjvhWbc3W6cvdHYTmHRMhTIOefncZRt3OwF7AvVk53fKKPiNNv5C9\n' + 'IK8bcDhAknSOg1TXRSpXLHtYy36A6iDgffNSjoCOVaeKpuRDMA37PvJWFQARAQAB\n' + 'AAP+KxHbOwcrnPPuXppCYEew3Xb7LMWESpvMFFgsmxx1COzFnLjek1P1E+yOWT7n\n' + '4opcsEuaazLk+TrYSMOuR6O6DgGg5c+ctVPU+NGNNCiiTkOzuD+8ow8NgsoINOxi\n' + '481qLK0NYpc5sEg394J3fRuzpfEi6DTS/RzCN7YDiGFccNECAM71NuaAzH5LrZ+B\n' + '4Okwy9CQQbgoYrdaia24CjEaUODaROnyNsvOb0ydEebVAbGzrsBr6LrisTidyZsG\n' + 't2T+L7ECAPpCFzZIwwk6giZ10HmXEhXZLXYmdhQD/1fwegpTrEciMA6MCcdkcCyO\n' + '2/J+S+NXM62ykMGDhg2cjhU1rj/uaaUCAJfCjkwpxMsDKHYDFDXyjJFy2vEmA3s8\n' + 'cnmAUDF1caPyEcPEZmYJRE+KdroOD6IGhzp7oA34Ef3D6HOCovH9YaCgbbQbSm9o\n' + 'bm55IDxqb2hubnlAZXhhbXBsZS5jb20+iLkEEwECACMFAlF6gtkCGwMHCwkIBwMC\n' + 'AQYVCAIJCgsEFgIDAQIeAQIXgAAKCRA6HTM8yP08keZgA/4vL273zrqnmOrqmo/K\n' + 'UxQgD0vMhM58d25UjGYI6LAZkAls/k4FvFt5GUHVWJR3HBRuuNlB7UndH/uYlU7j\n' + 'm/bQLiP4uvFQuRGuG76f0O5t/KyeUdzrpNiJpe8tYDAnoPxUzENYsIv0fm2ZISo1\n' + 'QnnXX2WuVZGMZH1YhQoakZxbnp0B2ARReoLZAQQAvQvPp2MLu9vnRvZ3Py559kQf\n' + '0Z5AnEXVokALTn5A2m51dLekQ9T3Rhz8p9I6C/XjVQwBkp1USOaDUz+L7lsbNdY4\n' + 'YbUi3eIA5RImVXeTIrD1hE4CllDNKmqT5wFN07eEu7QhDEuYioO+4gtjjhUDYeIA\n' + 'dCVtVO//q8rP8ukZEc8AEQEAAQAD/RHlttyNe3RnDr/AoKx6HXDLpUmGlm5VDDMm\n' + 'pgth14j2cSdCJYqIdHqOTvsiY31zY3jPQKzdOTgHnsI4X2qK9InbwXepSBkaOJzY\n' + 'iNhifPSUs9qoNawDqbFJ8PMXd4QQGgM93w+tudKC650Zuq7M7eWSdQg0u9aoLY97\n' + 'MpKx3DUFAgDA/RgoO8xYMgkKN1tuKWa61qesLdJRAZI/3cnvtsmmEBt9tdbcDoBz\n' + 'gOIAAvUFgipuP6dBWLyf2NRNRVVQdNTlAgD6xS7S87g3kTa3GLcEI2cveaP1WWNK\n' + 'rKFnVWsjBKArKFzMQ5N6FMnFD4T96i3sYlACE5UjH90SpOgBKOpdKzSjAf9nghrw\n' + 'kbFbF708ZIpVEwxvp/JoSutYUQ4v01MImnCGqzDVuSef3eutLLu4ZG7kLekxNauV\n' + '8tGFwxsdtv30RL/3nW+InwQYAQIACQUCUXqC2QIbDAAKCRA6HTM8yP08kRXjBACu\n' + 'RtEwjU+p6qqm3pmh7xz1CzhQN1F7VOj9dFUeECJJ1iv8J71w5UINH0otIceeBeWy\n' + 'NLA/QvK8+4/b9QW+S8aDZyeZpYg37gBwdTNGNT7TsEAxz9SUbx9uRja0wNmtb5xW\n' + 'mG+VE8CBXNkp8JTWx05AHwtK3baWlHWwpwnRlbU94Q==\n' + '=FSwA\n' + '-----END PGP PRIVATE KEY BLOCK-----'; var armored_msg = '-----BEGIN PGP MESSAGE-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'hIwDFYET+7bfx/ABA/95Uc9942Tg8oqpO0vEu2eSKwPALM3a0DrVdAiFOIK/dJmZ\n' + 'YrtPRw3EEwHZjl6CO9RD+95iE27tPbsICw1K43gofSV/wWsPO6vvs3eftQYHSxxa\n' + 'IQbTPImiRaJ73Mf7iM3CNtQM4iUBsx1HnUGl+rtD0nz3fLm6i3CjwiNQWW42I9JH\n' + 'AWv8EvvpxZ8X2ClFfSW3UVBoROHe9CAWHM/40nGutAZK8MIgmUI4xqkLFBbqqTyx\n' + '/cDSC4Q+sv65UX4urbfc7uJuk1Cpj54=\n' + '=iSaK\n' + '-----END PGP MESSAGE-----'; var key = new openpgp.packet.list(); key.read(openpgp.armor.decode(armored_key).data); key = key[3]; var msg = new openpgp.packet.list(); msg.read(openpgp.armor.decode(armored_msg).data); msg[0].decrypt(key); msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); var text = msg[1].packets[0].packets[0].data; return new unit.result('Public key encrypted packet (reading, GPG)', text == 'Hello world!'); }, function() { var passphrase = 'hello', algo = 'aes256'; var literal = new openpgp.packet.literal(), key_enc = new openpgp.packet.sym_encrypted_session_key(), enc = new openpgp.packet.sym_encrypted_integrity_protected(), msg = new openpgp.packet.list(); msg.push(key_enc); msg.push(enc); key_enc.sessionKeyAlgorithm = algo; key_enc.decrypt(passphrase); var key = key_enc.sessionKey; literal.set('Hello world!', 'utf8'); enc.packets.push(literal); enc.encrypt(algo, key); var msg2 = new openpgp.packet.list(); msg2.read(msg.write()); msg2[0].decrypt(passphrase); var key2 = msg2[0].sessionKey; msg2[1].decrypt(msg2[0].sessionKeyAlgorithm, key2); return new unit.result('Sym encrypted session key reading/writing', msg2[1].packets[0].data == literal.data); }, function() { var armored_msg = '-----BEGIN PGP MESSAGE-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'hIwD95D9aHS5fxEBA/98CwH54XZmwobOmHUcvWcDDQysBEC4uf7wASiGcRbejDaO\n' + 'aJqcrK/3k8sBQMO7yOhvrCRqqpGDqnmx7IaaKLnZS7nYAZoHEsK9UyG0hDa8Cfbo\n' + 'CP4xZVcgIvIfAW/in1LeT2td0QcQNbeewBmPea+vQEEvRgIP10tlE7MK8Ay48dJH\n' + 'AagMgNYg7MBUjpuOCVrjM1pWja8uzbULfYhTq3IJ8H3QhbdT+k9khY9f0aJPEeYi\n' + 'dVv6DK9uviMGc/DsVCw5K8lQRLlkcHc=\n' + '=pR+C\n' + '-----END PGP MESSAGE-----'; var key = new openpgp.packet.list(); key.read(openpgp.armor.decode(armored_key).data); key = key[3]; key.decrypt('test'); var msg = new openpgp.packet.list(); msg.read(openpgp.armor.decode(armored_msg).data); msg[0].decrypt(key); msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); var text = msg[1].packets[0].packets[0].data; return new unit.result('Secret key encryption/decryption test', text == 'Hello world!'); }, function() { var key = new openpgp.packet.list(); key.read(openpgp.armor.decode(armored_key).data); var verified = key[2].verify(key[0], { userid: key[1], key: key[0] }); verified = verified && key[4].verify(key[0], { key: key[0], bind: key[3], }) return new unit.result('Secret key reading with signature verification.', verified == true); }, function() { var armored_msg = '-----BEGIN PGP MESSAGE-----\n' + 'Version: GnuPG v2.0.19 (GNU/Linux)\n' + '\n' + 'hIwD95D9aHS5fxEBA/4/X4myvH+jB1HYNeZvdK+WsBNDMfLsBGOf205Rxr3vSob/\n' + 'A09boj8/9lFaipqu+AEdQKEjCB8sZ+OY0WiQPEPpuhG+mVqDqEiPFkdpcqNtS0VV\n' + 'pwqplHo6QnH2MHfxprZHYuwcEC9ynJCxJ6kSCD8Xs99h+PjxNNw7NhMjkF+N69LA\n' + 'NwGPtbLx2/r2nR4gO8gV92A2RQCOwPP7ZV+6fXgWIs+mhyCHFP3xUP5DaFCNM8mo\n' + 'PN97i659ucxF6IbOoK56FEaUbOPTD6xdyhWamxKfMsIb0UJgVUNhGaq+VlvOJxaB\n' + 'iRcnY5UxsypKgtqfcKIseb21MIo4vcNdogyxBIDlAO472Zfxn0udzr6W2aQ77+NK\n' + 'FE1O0kCXS+DTFOYYVD7X8rXGSglQsdXJmHd89sdYFQkO7D7bOLdRJuXgdgH2czCs\n' + 'UBGuHZzsGbTdyKvpVBuS3rnyHHBk6oCnsm1Nl7eLs64VkZUxjEUbq5pb4dlr1pw2\n' + 'ztpmpAnRcmM=\n' + '=htrB\n' + '-----END PGP MESSAGE-----' var key = new openpgp.packet.list(); key.read(openpgp.armor.decode(armored_key).data); key[3].decrypt('test') var msg = new openpgp.packet.list(); msg.read(openpgp.armor.decode(armored_msg).data); msg[0].decrypt(key[3]); msg[1].decrypt(msg[0].sessionKeyAlgorithm, msg[0].sessionKey); var payload = msg[1].packets[0].packets var verified = payload[2].verify(key[0], payload[1]); return new unit.result('Reading a signed, encrypted message.', verified == true); }, function() { var key = new openpgp.packet.list(); key.push(new openpgp.packet.secret_key); var rsa = new openpgp.crypto.publicKey.rsa(), mpi = rsa.generate(512, "10001") var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u]; mpi = mpi.map(function(k) { var mpi = new openpgp.mpi(); mpi.fromBigInteger(k); return mpi; }); key[0].mpi = mpi; key[0].encrypt('hello'); var raw = key.write(); var key2 = new openpgp.packet.list(); key2.read(raw); key2[0].decrypt('hello'); return new unit.result('Writing and encryptio of a secret key packet.', key[0].mpi.toString() == key2[0].mpi.toString()); }, function() { var key = new openpgp.packet.secret_key(); var rsa = new openpgp.crypto.publicKey.rsa, mpi = rsa.generate(512, "10001") var mpi = [mpi.n, mpi.ee, mpi.d, mpi.p, mpi.q, mpi.u]; mpi = mpi.map(function(k) { var mpi = new openpgp.mpi(); mpi.fromBigInteger(k); return mpi; }); key.mpi = mpi; var signed = new openpgp.packet.list(), literal = new openpgp.packet.literal(), signature = new openpgp.packet.signature(); literal.set('Hello world', 'utf8'); signature.hashAlgorithm = 'sha256'; signature.publicKeyAlgorithm = 'rsa_sign'; signature.signatureType = 'binary'; signature.sign(key, literal); signed.push(literal); signed.push(signature); var raw = signed.write(); var signed2 = new openpgp.packet.list(); signed2.read(raw); var verified = signed2[1].verify(key, signed2[0]); return new unit.result('Writing and verification of a signature packet.', verified == true); }]; tests.reverse(); var results = []; for(var i in tests) { results.push(tests[i]()); } return results; }); },{"../../":28,"../unit.js":72}],69:[function(require,module,exports){ var unit = require('../unit.js'); unit.register("Signature testing", function() { var openpgp = require('../../'); var priv_key_arm1 = [ '-----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"); var pub_key_arm1 = [ '-----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"); var msg_arm1 = [ '-----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"); var priv_key_arm2 = ['-----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 pub_key_arm2 = ['-----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 pub_key_arm3 = ['-----BEGIN PGP PUBLIC KEY BLOCK-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'mQENBFKV0FUBCACtZliApy01KBGbGNB36YGH4lpr+5KoqF1I8A5IT0YeNjyGisOk', 'WsDsUzOqaNvgzQ82I3MY/jQV5rLBhH/6LiRmCA16WkKcqBrHfNGIxJ+Q+ofVBHUb', 'aS9ClXYI88j747QgWzirnLuEA0GfilRZcewII1pDA/G7+m1HwV4qHsPataYLeboq', 'hPA3h1EVVQFMAcwlqjOuS8+weHQRfNVRGQdRMm6H7166PseDVRUHdkJpVaKFhptg', 'rDoNI0lO+UujdqeF1o5tVZ0j/s7RbyBvdLTXNuBbcpq93ceSWuJPZmi1XztQXKYe', 'y0f+ltgVtZDEc7TGV5WDX9erRECCcA3+s7J3ABEBAAG0G0pTIENyeXB0byA8ZGlm', 'ZmllQGhvbWUub3JnPokBPwQTAQIAKQUCUpXQVQIbAwUJCWYBgAcLCQgHAwIBBhUI', 'AgkKCwQWAgMBAh4BAheAAAoJENvyI+hwU030yRAIAKX/mGEgi/miqasbbQoyK/CS', 'a7sRxgZwOWQLdi2xxpE5V4W4HJIDNLJs5vGpRN4mmcNK2fmJAh74w0PskmVgJEhP', 'dFJ14UC3fFPq5nbqkBl7hU0tDP5jZxo9ruQZfDOWpHKxOCz5guYJ0CW97bz4fChZ', 'NFDyfU7VsJQwRIoViVcMCipP0fVZQkIhhwpzQpmVmN8E0a6jWezTZv1YpMdlzbEf', 'H79l3StaOh9/Un9CkIyqEWdYiKvIYms9nENyehN7r/OKYN3SW+qlt5GaL+ws+N1w', '6kEZjPFwnsr+Y4A3oHcAwXq7nfOz71USojSmmo8pgdN8je16CP98vw3/k6TncLS5', 'AQ0EUpXQVQEIAMEjHMeqg7B04FliUFWr/8C6sJDb492MlGAWgghIbnuJfXAnUGdN', 'oAzn0S+n93Y/qHbW6YcjHD4/G+kK3MuxthAFqcVjdHZQXK0rkhXO/u1co7v1cdtk', 'OTEcyOpyLXolM/1S2UYImhrml7YulTHMnWVja7xu6QIRso+7HBFT/u9D47L/xXrX', 'MzXFVZfBtVY+yoeTrOY3OX9cBMOAu0kuN9eT18Yv2yi6XMzP3iONVHtl6HfFrAA7', 'kAtx4ne0jgAPWZ+a8hMy59on2ZFs/AvSpJtSc1kw/vMTWkyVP1Ky20vAPHQ6Ej5q', '1NGJ/JbcFgolvEeI/3uDueLjj4SdSIbLOXMAEQEAAYkBJQQYAQIADwUCUpXQVQIb', 'DAUJCWYBgAAKCRDb8iPocFNN9NLkB/wO4iRxia0zf4Kw2RLVZG8qcuo3Bw9UTXYY', 'lI0AutoLNnSURMLLCq6rcJ0BCXGj/2iZ0NBxZq3t5vbRh6uUv+hpiSxK1nF7AheN', '4aAAzhbWx0UDTF04ebG/neE4uDklRIJLhif6+Bwu+EUeTlGbDj7fqGSsNe8g92w7', '1e41rF/9CMoOswrKgIjXAou3aexogWcHvKY2D+1q9exORe1rIa1+sUGl5PG2wsEs', 'znN6qtN5gMlGY1ofWDY+I02gO4qzaZ/FxRZfittCw7v5dmQYKot9qRi2Kx3Fvw+h', 'ivFBpC4TWgppFBnJJnAsFXZJQcejMW4nEmOViRQXY8N8PepQmgsu', '=ummy', '-----END PGP PUBLIC KEY BLOCK-----'].join('\n'); var tests = [function() { var priv_key = openpgp.key.readArmored(priv_key_arm1).packets; var pub_key = openpgp.key.readArmored(pub_key_arm1).packets; var msg = openpgp.message.readArmored(msg_arm1).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]); return new unit.result("Testing signature checking on CAST5-enciphered message", msg[1].packets[2].verified === true); }, function() { // 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; var pub_key = openpgp.key.readArmored(pub_key_arm1).packets; var msg = openpgp.message.readArmored(msg_arm1).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]); return new unit.result("Testing GnuPG stripped-key extensions", msg[1].packets[2].verified === true); }, function() { var signedArmor = ['-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'owGbwMvMwMT4oOW7S46CznTGNeZJLCWpFSVBU3ZGF2fkF5Uo5KYWFyemp3LlAUUV', 'cjLzUrneTp3zauvaN9O26L9ZuOFNy4LXyydwcXXMYWFgZGJgY2UCaWXg4hSAmblK', 'nPmfsXYxd58Ka9eVrEnSpzilr520fXBrJsf2P/oTqzTj3hzyLG0o3TTzxFfrtOXf', 'cw6U57n3/Z4X0pEZ68C5/o/6NpPICD7fuEOz3936raZ6wXGzueY8pfPnVjY0ajAc', 'PtJzvvqj+ubYaT1sK9wWhd9lL3/V+9Zuua9QjOWC22buchsCroh8fLoZAA==', '=VH8F', '-----END PGP MESSAGE-----'].join('\n'); var sMsg = openpgp.message.readArmored(signedArmor).packets; var pub_key = openpgp.key.readArmored(pub_key_arm2).packets; sMsg[0].packets[2].verify(pub_key[3], sMsg[0].packets[1]); return new unit.result("Verify V4 signature. Hash: SHA1. PK: RSA. Signature Type: 0x00 (binary document)", sMsg[0].packets[2].verified); }, function() { var signedArmor = ['-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'owGbwMvMyMj4oOW7S46CznTG09YlLCWpFSVBU47xFGfkF5Uo5KYWFyemp/Jy5QGF', 'FXIy84DMt1PnvNq69s20LfpvFm5407Lg9fIJvFy8XJ0MU5lZGUFa4eYxxiQz/6+/', 'aFt4/6+e76O6s1afLi65emmK9xsdh7Mr60UnT2UN0LwocWnT7t/nOMJubnypvzTu', 'aPJyvm9TTpobW/O+P1n2THLS4UCvWt12Oa2lJ04GLwk/bDF1u+8ZpfPCpsxLVzcs', 'ZGtbq/f23XxV/jkL47hr3s3Ic4yoZTW4oZO27GYf37TPp9L3VboCAA==', '=pa6B', '-----END PGP MESSAGE-----'].join('\n'); var sMsg = openpgp.message.readArmored(signedArmor).packets; var pub_key = openpgp.key.readArmored(pub_key_arm2).packets; sMsg[0].packets[2].verify(pub_key[3], sMsg[0].packets[1]); return new unit.result("Verify V3 signature. Hash: MD5. PK: RSA. Signature Type: 0x01 (text document)", sMsg[0].packets[2].verified); }, function() { var msg_armor = ['-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'hIwD4IT3RGwgLJcBBADEBdm+GEW7IV1K/Bykg0nB0WYO08ai7/8/+Y/O9xu6RiU0', 'q7/jWuKms7kSjw9gxMCjf2dGnAuT4Cg505Kj5WfeBuHh618ovO8qo4h0qHyp1/y3', 'o1P0IXPAb+LGJOeO7DyM9Xp2AOBiIKOVWzFTg+MBZOc+XZEVx3FioHfm9SSDudLA', 'WAEkDakCG6MRFj/7SmOiV8mQKH+YPMKT69eDZW7hjINabrpM2pdRU7c9lC7CMUBx', 'Vj7wZsQBMASSC8f2rhpGA2iKvYMsmW3g9R1xkvj1MXWftSPUS4jeNTAgEwvvF6Af', 'cP+OYSXKlTbwfEr73ES2O3/IFE9sHRjPqWaxWuv4DDQ5YfIxE54C1aE8Aq5/QaIH', 'v38TUSia0yEMCc/tJd58DikkT07AF162tcx9Ro0ZjhudyuvUyXIfPfxA+XWR2pdz', 'ifxyV4zia9RvaCUY8vXGM+gQJ3NNXx2LkZA3kWUEyxFVL1Vl/XUQY0M6U+uccSk4', 'eMXm6eyEWDcj0lBRckqKoKo1w/uan11jPuHsnRz6jO9DsuKEz79UDgI=', '=cFi7', '-----END PGP MESSAGE-----'].join('\n'); var plaintext = 'short message\nnext line\n한국어/조선말'; var esMsg = openpgp.message.readArmored(msg_armor); var pubKey = openpgp.key.readArmored(pub_key_arm2); var privKey = openpgp.key.readArmored(priv_key_arm2); var keyids = esMsg.getEncryptionKeyIds(); privKey.decryptKeyPacket(keyids, 'hello world'); var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], esMsg); var verified = decrypted.text == plaintext && decrypted.signatures[0].status; return new unit.result("Verify signature of signed and encrypted message from GPG2 with openpgp.decryptAndVerifyMessage", verified); }, function() { var msg_armor = ['-----BEGIN PGP MESSAGE-----', 'Version: Encryption Desktop 10.3.0 (Build 9307)', 'Charset: utf-8', '', 'qANQR1DBjAPghPdEbCAslwED/2S4oNvCjO5TdLUMMUuVOQc8fi6c5XIBu7Y09fEX', 'Jm/UrkDHVgmPojLGBDF0CYENNZOVrNfpahY7A3r4HPzGucBzCO1uxuUIKjhtNAAM', 'mjD939ernjooOZrM6xDuRaX8adG0LSxpNaVJGxXd/EdlmKDJbYDI6aJ5INrUxzAR', 'DAqw0sBSAXgRWgiH6IIiAo5y5WFEDEN9sGStaEQT2wd32kX73M4iZuMt/GM2agiB', 'sWb7yLcNHiJ/3OnTfDg9+T543kFq9FlwFbwqygO/wm9e/kgMBq0ZsFOfV+GRtXep', '3qNbJsmzGvdqiUHb/+hkdE191jaSVcO/zaMW4N0Vc1IwIEhZ8I9+9bKwusdVhHT5', 'MySnhIogv+0Ilag/aY+UiCt+Zcie69T7Eix48fC/VVW5w3INf1T2CMmDm5ZLZFRN', 'oyqzb9Vsgu1gS7SCb6qTbnbV9PlSyU4wJB6siX8hz/U0urokT5se3uYRjiV0KbkA', 'zl1/r/wCrmwX4Gl9VN9+33cQgYZAlJLsRw8N82GhbVweZS8qwv24GQ==', '=nx90', '-----END PGP MESSAGE-----'].join('\n'); var plaintext = 'short message\nnext line\n한국어/조선말\n\n'; var esMsg = openpgp.message.readArmored(msg_armor); var pubKey = openpgp.key.readArmored(pub_key_arm2); var privKey = openpgp.key.readArmored(priv_key_arm2); var keyids = esMsg.getEncryptionKeyIds(); privKey.decryptKeyPacket(keyids, 'hello world'); var decrypted = openpgp.decryptAndVerifyMessage(privKey, [pubKey], esMsg); var verified = decrypted.text == plaintext && decrypted.signatures[0].status; return new unit.result("Verify signature of signed and encrypted message from PGP 10.3.0 with openpgp.decryptAndVerifyMessage", verified); }, function() { var msg_armor = ['-----BEGIN PGP MESSAGE-----', 'Version: GnuPG v2.0.19 (GNU/Linux)', '', 'owGbwMvMwMF4+5Pyi4Jg3y8ME8DcBy3fXXIUdKYzrjFNYilJrSgJmsXDXJyRX1Si', 'kJtaXJyYnsqVBxRVyMnMS+V6O3XOq61r30zbov9m4YY3LQteL5/QMYeFgZGDgY2V', 'CaSRgYtTAGZiYxYLwySbQk07ptZel6gmjrKyBWsyWdkOG3oscLBdIpXXfDdb6fNv', '8ULN5L1ed+xNo79P2dBotWud6vn7e9dtLJ7o12PunnvEz8gyyvP4/As/los0xsnZ', 'H+8ublrhvGtLxJUZuUKZO6QdHq2Nepuw8OrfiMXPBDQXXpV2q11Ze+rD3lndgv/C', 'bJQNOhll0J0H839jFvt/16m20h/ZmDoWqJywapnypjdIjcXr+7rJFess40yenV7Q', '2LSu/EX6Aq29x+dv+GPUMfuhTNE3viWWUR4PD6T7XfmdViUwmSf8fkRNUn/t3a2n', 'cq46Xr36seCor/OLp0atSZwHrjx2SU5zPLheZn+zw/0d1/YZnD7AEeP9s/Cuycyv', 'CZ5HZNKufvB8fsh+dfdSXW0GfqkPfxk36Vw8ufpjaoZDyt2nxxg/6D4KS3UvZzv3', 'axdLZ9yd0OJNZv4P501If24W4vTGz6nI7Ser8Yd2PiOvE5MWMT0wLZQ+zPX1sv0/', 's8PvkyWmVM0O0fB/ZSHovHNNPffDg/rWhzOmXQ9/7vTn477F+aWm5sYzJ75/BQA=', '=+L0S', '-----END PGP MESSAGE-----'].join('\n'); var plaintext = 'short message\nnext line\n한국어/조선말'; var sMsg = openpgp.message.readArmored(msg_armor); var pubKey2 = openpgp.key.readArmored(pub_key_arm2); var pubKey3 = openpgp.key.readArmored(pub_key_arm3); var keyids = sMsg.getSigningKeyIds(); var verified = pubKey2.getPublicKeyPacket(keyids) && pubKey3.getPublicKeyPacket(keyids); verified = verified && sMsg.getText() == plaintext; var verifiedSig = sMsg.verify([pubKey2, pubKey3]); verified = verified && verifiedSig[0].status && verifiedSig[1].status; return new unit.result("Verify signed message with two one pass signatures", verified); }]; var results = []; for(var i in tests) { results.push(tests[i]()); } return results; }); },{"../../":28,"../unit.js":72}],"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/crypto.js'); require('./general/basic.js'); require('./general/keyring.js'); require('./general/packet.js'); require('./general/signature.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/crypto.js":62,"./crypto/hash/md5.js":63,"./crypto/hash/ripemd.js":64,"./crypto/hash/sha.js":65,"./general/basic.js":66,"./general/keyring.js":67,"./general/packet.js":68,"./general/signature.js":69,"./unit.js":72}],72:[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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlcyI6WyIvaG9tZS90b2Jlcm5kby9kZXYvbm9kZS9saWIvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2luc2VydC1tb2R1bGUtZ2xvYmFscy9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY29tcHJlc3Npb24vanhnLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY29uZmlnL2NvbmZpZy5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9jZmIuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vY2lwaGVyL2Flcy5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9jaXBoZXIvYmxvd2Zpc2guanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vY2lwaGVyL2Nhc3Q1LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2NpcGhlci9kZXMuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vY2lwaGVyL2luZGV4LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2NpcGhlci90d29maXNoLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2NyeXB0by5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9oYXNoL2luZGV4LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2hhc2gvbWQ1LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL2hhc2gvcmlwZS1tZC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9oYXNoL3NoYS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9pbmRleC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9wa2NzMS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9wdWJsaWNfa2V5L2RzYS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9wdWJsaWNfa2V5L2VsZ2FtYWwuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcHVibGljX2tleS9pbmRleC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2NyeXB0by9wdWJsaWNfa2V5L2pzYm4uanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcHVibGljX2tleS9yc2EuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9jcnlwdG8vcmFuZG9tLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvY3J5cHRvL3NpZ25hdHVyZS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2VuY29kaW5nL2FybW9yLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvZW5jb2RpbmcvYmFzZTY0LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvZW51bXMuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9pbmRleC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2tleS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL2tleXJpbmcuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9tZXNzYWdlLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvb3BlbnBncC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9hbGxfcGFja2V0cy5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9jb21wcmVzc2VkLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L2luZGV4LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L2xpdGVyYWwuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvbWFya2VyLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L29uZV9wYXNzX3NpZ25hdHVyZS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9wYWNrZXQuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvcGFja2V0bGlzdC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9wdWJsaWNfa2V5LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L3B1YmxpY19rZXlfZW5jcnlwdGVkX3Nlc3Npb25fa2V5LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L3B1YmxpY19zdWJrZXkuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvc2VjcmV0X2tleS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9zZWNyZXRfc3Via2V5LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvcGFja2V0L3NpZ25hdHVyZS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9zeW1fZW5jcnlwdGVkX2ludGVncml0eV9wcm90ZWN0ZWQuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy9wYWNrZXQvc3ltX2VuY3J5cHRlZF9zZXNzaW9uX2tleS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC9zeW1tZXRyaWNhbGx5X2VuY3J5cHRlZC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC90cnVzdC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC91c2VyX2F0dHJpYnV0ZS5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3BhY2tldC91c2VyaWQuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy90eXBlL2tleWlkLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC9zcmMvdHlwZS9tcGkuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3NyYy90eXBlL3Myay5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvc3JjL3V0aWwvdXRpbC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9jcnlwdG8vY2lwaGVyL2Flcy5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9jcnlwdG8vY2lwaGVyL2Jsb3dmaXNoLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L2NyeXB0by9jaXBoZXIvY2FzdDUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL2NpcGhlci9kZXMuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL2NpcGhlci90d29maXNoLmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L2NyeXB0by9jcnlwdG8uanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvY3J5cHRvL2hhc2gvbWQ1LmpzIiwiL2hvbWUvdG9iZXJuZG8vZGV2L29wZW5wZ3Bqcy1kZXZlbC90ZXN0L2NyeXB0by9oYXNoL3JpcGVtZC5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9jcnlwdG8vaGFzaC9zaGEuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvZ2VuZXJhbC9iYXNpYy5qcyIsIi9ob21lL3RvYmVybmRvL2Rldi9vcGVucGdwanMtZGV2ZWwvdGVzdC9nZW5lcmFsL2tleXJpbmcuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvZ2VuZXJhbC9wYWNrZXQuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvZ2VuZXJhbC9zaWduYXR1cmUuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvdGVzdC1hbGwuanMiLCIvaG9tZS90b2Jlcm5kby9kZXYvb3BlbnBncGpzLWRldmVsL3Rlc3QvdW5pdC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0dkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNVpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNWxCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMVhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25TQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1bENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6cURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdlRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNtQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRUE7QUFDQTtBQUNBO0FBQ0E7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0tBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblhBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuUG9zdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIGlmIChldi5zb3VyY2UgPT09IHdpbmRvdyAmJiBldi5kYXRhID09PSAncHJvY2Vzcy10aWNrJykge1xuICAgICAgICAgICAgICAgIGV2LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGlmIChxdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmbiA9IHF1ZXVlLnNoaWZ0KCk7XG4gICAgICAgICAgICAgICAgICAgIGZuKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB0cnVlKTtcblxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgICAgIHF1ZXVlLnB1c2goZm4pO1xuICAgICAgICAgICAgd2luZG93LnBvc3RNZXNzYWdlKCdwcm9jZXNzLXRpY2snLCAnKicpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICBzZXRUaW1lb3V0KGZuLCAwKTtcbiAgICB9O1xufSkoKTtcblxucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG4iLCJKWEcgPSB7XG4gIGV4aXN0czogKGZ1bmN0aW9uKHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBmdW5jdGlvbih2KSB7XG4gICAgICByZXR1cm4gISh2ID09PSB1bmRlZmluZWQgfHwgdiA9PT0gbnVsbCk7XG4gICAgfVxuICB9KSgpXG59O1xuSlhHLmRlY29tcHJlc3MgPSBmdW5jdGlvbihzdHIpIHtcbiAgcmV0dXJuIHVuZXNjYXBlKChuZXcgSlhHLlV0aWwuVW56aXAoSlhHLlV0aWwuQmFzZTY0LmRlY29kZUFzQXJyYXkoc3RyKSkpLnVuemlwKClbMF1bMF0pO1xufTtcbi8qXG4gICAgQ29weXJpZ2h0IDIwMDgtMjAxMlxuICAgICAgICBNYXR0aGlhcyBFaG1hbm4sXG4gICAgICAgIE1pY2hhZWwgR2VyaGFldXNlcixcbiAgICAgICAgQ2Fyc3RlbiBNaWxsZXIsXG4gICAgICAgIEJpYW5jYSBWYWxlbnRpbixcbiAgICAgICAgQWxmcmVkIFdhc3Nlcm1hbm4sXG4gICAgICAgIFBldGVyIFdpbGZhaHJ0XG5cbiAgICBUaGlzIGZpbGUgaXMgcGFydCBvZiBKU1hHcmFwaC5cbiAgICBcbiAgICBEdWFsIGxpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSBWZXJzaW9uIDIuMCwgb3IgTEdQTCBWZXJzaW9uIDMgbGljZW5zZXMuXG5cbiAgICBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAgICBhbG9uZyB3aXRoIEpTWENvbXByZXNzb3IuICBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4uXG4gICAgXG4gICAgWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgQXBhY2hlIExpY2Vuc2UgYWxvbmcgd2l0aCBKU1hDb21wcmVzc29yLiAgXG4gICAgSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy8+LlxuXG4qL1xuXG4vKipcbiAqIEBjbGFzcyBVdGlsIGNsYXNzXG4gKiBAY2xhc3NkZXNjIFV0aWxpdGllcyBmb3IgdW5jb21wcmVzc2luZyBhbmQgYmFzZTY0IGRlY29kaW5nXG4gKiBDbGFzcyBmb3IgZ3VuemlwcGluZywgdW56aXBwaW5nIGFuZCBiYXNlNjQgZGVjb2Rpbmcgb2YgZmlsZXMuXG4gKiBJdCBpcyB1c2VkIGZvciByZWFkaW5nIEdFT05FeFQsIEdlb2dlYnJhIGFuZCBJbnRlcmdlbyBmaWxlcy5cbiAqXG4gKiBPbmx5IEh1ZmZtYW4gY29kZXMgYXJlIGRlY29kZWQgaW4gZ3VuemlwLlxuICogVGhlIGNvZGUgaXMgYmFzZWQgb24gdGhlIHNvdXJjZSBjb2RlIGZvciBndW56aXAuYyBieSBQYXNpIE9qYWxhIFxuICoge0BsaW5rIGh0dHA6Ly93d3cuY3MudHV0LmZpL35hbGJlcnQvRGV2L2d1bnppcC9ndW56aXAuY31cbiAqIHtAbGluayBodHRwOi8vd3d3LmNzLnR1dC5maS9+YWxiZXJ0fVxuICovXG5KWEcuVXRpbCA9IHt9O1xuXG4vKipcbiAqIFVuemlwIHppcCBmaWxlc1xuICovXG5KWEcuVXRpbC5VbnppcCA9IGZ1bmN0aW9uKGJhcnJheSkge1xuICB2YXIgb3V0cHV0QXJyID0gW10sXG4gICAgb3V0cHV0ID0gXCJcIixcbiAgICBkZWJ1ZyA9IGZhbHNlLFxuICAgIGdwZmxhZ3MsXG4gICAgZmlsZXMgPSAwLFxuICAgIHVuemlwcGVkID0gW10sXG4gICAgY3JjLFxuICAgIGJ1ZjMyayA9IG5ldyBBcnJheSgzMjc2OCksXG4gICAgYklkeCA9IDAsXG4gICAgbW9kZVpJUCA9IGZhbHNlLFxuXG4gICAgQ1JDLCBTSVpFLFxuXG4gICAgYml0UmV2ZXJzZSA9IFtcbiAgICAgICAgMHgwMCwgMHg4MCwgMHg0MCwgMHhjMCwgMHgyMCwgMHhhMCwgMHg2MCwgMHhlMCxcbiAgICAgICAgMHgxMCwgMHg5MCwgMHg1MCwgMHhkMCwgMHgzMCwgMHhiMCwgMHg3MCwgMHhmMCxcbiAgICAgICAgMHgwOCwgMHg4OCwgMHg0OCwgMHhjOCwgMHgyOCwgMHhhOCwgMHg2OCwgMHhlOCxcbiAgICAgICAgMHgxOCwgMHg5OCwgMHg1OCwgMHhkOCwgMHgzOCwgMHhiOCwgMHg3OCwgMHhmOCxcbiAgICAgICAgMHgwNCwgMHg4NCwgMHg0NCwgMHhjNCwgMHgyNCwgMHhhNCwgMHg2NCwgMHhlNCxcbiAgICAgICAgMHgxNCwgMHg5NCwgMHg1NCwgMHhkNCwgMHgzNCwgMHhiNCwgMHg3NCwgMHhmNCxcbiAgICAgICAgMHgwYywgMHg4YywgMHg0YywgMHhjYywgMHgyYywgMHhhYywgMHg2YywgMHhlYyxcbiAgICAgICAgMHgxYywgMHg5YywgMHg1YywgMHhkYywgMHgzYywgMHhiYywgMHg3YywgMHhmYyxcbiAgICAgICAgMHgwMiwgMHg4MiwgMHg0MiwgMHhjMiwgMHgyMiwgMHhhMiwgMHg2MiwgMHhlMixcbiAgICAgICAgMHgxMiwgMHg5MiwgMHg1MiwgMHhkMiwgMHgzMiwgMHhiMiwgMHg3MiwgMHhmMixcbiAgICAgICAgMHgwYSwgMHg4YSwgMHg0YSwgMHhjYSwgMHgyYSwgMHhhYSwgMHg2YSwgMHhlYSxcbiAgICAgICAgMHgxYSwgMHg5YSwgMHg1YSwgMHhkYSwgMHgzYSwgMHhiYSwgMHg3YSwgMHhmYSxcbiAgICAgICAgMHgwNiwgMHg4NiwgMHg0NiwgMHhjNiwgMHgyNiwgMHhhNiwgMHg2NiwgMHhlNixcbiAgICAgICAgMHgxNiwgMHg5NiwgMHg1NiwgMHhkNiwgMHgzNiwgMHhiNiwgMHg3NiwgMHhmNixcbiAgICAgICAgMHgwZSwgMHg4ZSwgMHg0ZSwgMHhjZSwgMHgyZSwgMHhhZSwgMHg2ZSwgMHhlZSxcbiAgICAgICAgMHgxZSwgMHg5ZSwgMHg1ZSwgMHhkZSwgMHgzZSwgMHhiZSwgMHg3ZSwgMHhmZSxcbiAgICAgICAgMHgwMSwgMHg4MSwgMHg0MSwgMHhjMSwgMHgyMSwgMHhhMSwgMHg2MSwgMHhlMSxcbiAgICAgICAgMHgxMSwgMHg5MSwgMHg1MSwgMHhkMSwgMHgzMSwgMHhiMSwgMHg3MSwgMHhmMSxcbiAgICAgICAgMHgwOSwgMHg4OSwgMHg0OSwgMHhjOSwgMHgyOSwgMHhhOSwgMHg2OSwgMHhlOSxcbiAgICAgICAgMHgxOSwgMHg5OSwgMHg1OSwgMHhkOSwgMHgzOSwgMHhiOSwgMHg3OSwgMHhmOSxcbiAgICAgICAgMHgwNSwgMHg4NSwgMHg0NSwgMHhjNSwgMHgyNSwgMHhhNSwgMHg2NSwgMHhlNSxcbiAgICAgICAgMHgxNSwgMHg5NSwgMHg1NSwgMHhkNSwgMHgzNSwgMHhiNSwgMHg3NSwgMHhmNSxcbiAgICAgICAgMHgwZCwgMHg4ZCwgMHg0ZCwgMHhjZCwgMHgyZCwgMHhhZCwgMHg2ZCwgMHhlZCxcbiAgICAgICAgMHgxZCwgMHg5ZCwgMHg1ZCwgMHhkZCwgMHgzZCwgMHhiZCwgMHg3ZCwgMHhmZCxcbiAgICAgICAgMHgwMywgMHg4MywgMHg0MywgMHhjMywgMHgyMywgMHhhMywgMHg2MywgMHhlMyxcbiAgICAgICAgMHgxMywgMHg5MywgMHg1MywgMHhkMywgMHgzMywgMHhiMywgMHg3MywgMHhmMyxcbiAgICAgICAgMHgwYiwgMHg4YiwgMHg0YiwgMHhjYiwgMHgyYiwgMHhhYiwgMHg2YiwgMHhlYixcbiAgICAgICAgMHgxYiwgMHg5YiwgMHg1YiwgMHhkYiwgMHgzYiwgMHhiYiwgMHg3YiwgMHhmYixcbiAgICAgICAgMHgwNywgMHg4NywgMHg0NywgMHhjNywgMHgyNywgMHhhNywgMHg2NywgMHhlNyxcbiAgICAgICAgMHgxNywgMHg5NywgMHg1NywgMHhkNywgMHgzNywgMHhiNywgMHg3NywgMHhmNyxcbiAgICAgICAgMHgwZiwgMHg4ZiwgMHg0ZiwgMHhjZiwgMHgyZiwgMHhhZiwgMHg2ZiwgMHhlZixcbiAgICAgICAgMHgxZiwgMHg5ZiwgMHg1ZiwgMHhkZiwgMHgzZiwgMHhiZiwgMHg3ZiwgMHhmZlxuICAgIF0sXG5cbiAgICBjcGxlbnMgPSBbXG4gICAgICAgIDMsIDQsIDUsIDYsIDcsIDgsIDksIDEwLCAxMSwgMTMsIDE1LCAxNywgMTksIDIzLCAyNywgMzEsXG4gICAgICAgIDM1LCA0MywgNTEsIDU5LCA2NywgODMsIDk5LCAxMTUsIDEzMSwgMTYzLCAxOTUsIDIyNywgMjU4LCAwLCAwXG4gICAgXSxcblxuICAgIGNwbGV4dCA9IFtcbiAgICAgICAgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMSwgMSwgMSwgMiwgMiwgMiwgMixcbiAgICAgICAgMywgMywgMywgMywgNCwgNCwgNCwgNCwgNSwgNSwgNSwgNSwgMCwgOTksIDk5XG4gICAgXSxcbiAgICAvKiA5OT09aW52YWxpZCAqL1xuXG4gICAgY3BkaXN0ID0gW1xuICAgICAgICAweDAwMDEsIDB4MDAwMiwgMHgwMDAzLCAweDAwMDQsIDB4MDAwNSwgMHgwMDA3LCAweDAwMDksIDB4MDAwZCxcbiAgICAgICAgMHgwMDExLCAweDAwMTksIDB4MDAyMSwgMHgwMDMxLCAweDAwNDEsIDB4MDA2MSwgMHgwMDgxLCAweDAwYzEsXG4gICAgICAgIDB4MDEwMSwgMHgwMTgxLCAweDAyMDEsIDB4MDMwMSwgMHgwNDAxLCAweDA2MDEsIDB4MDgwMSwgMHgwYzAxLFxuICAgICAgICAweDEwMDEsIDB4MTgwMSwgMHgyMDAxLCAweDMwMDEsIDB4NDAwMSwgMHg2MDAxXG4gICAgXSxcblxuICAgIGNwZGV4dCA9IFtcbiAgICAgICAgMCwgMCwgMCwgMCwgMSwgMSwgMiwgMixcbiAgICAgICAgMywgMywgNCwgNCwgNSwgNSwgNiwgNixcbiAgICAgICAgNywgNywgOCwgOCwgOSwgOSwgMTAsIDEwLFxuICAgICAgICAxMSwgMTEsIDEyLCAxMiwgMTMsIDEzXG4gICAgXSxcblxuICAgIGJvcmRlciA9IFsxNiwgMTcsIDE4LCAwLCA4LCA3LCA5LCA2LCAxMCwgNSwgMTEsIDQsIDEyLCAzLCAxMywgMiwgMTQsIDEsIDE1XSxcblxuICAgIGJBID0gYmFycmF5LFxuXG4gICAgYnl0ZXBvcyA9IDAsXG4gICAgYml0cG9zID0gMCxcbiAgICBiYiA9IDEsXG4gICAgYml0cyA9IDAsXG5cbiAgICBOQU1FTUFYID0gMjU2LFxuXG4gICAgbmFtZUJ1ZiA9IFtdLFxuXG4gICAgZmlsZW91dDtcblxuICBmdW5jdGlvbiByZWFkQnl0ZSgpIHtcbiAgICBiaXRzICs9IDg7XG4gICAgaWYgKGJ5dGVwb3MgPCBiQS5sZW5ndGgpIHtcbiAgICAgIC8vaWYgKGRlYnVnKVxuICAgICAgLy8gICAgZG9jdW1lbnQud3JpdGUoYnl0ZXBvcytcIjogXCIrYkFbYnl0ZXBvc10rXCI8YnI+XCIpO1xuICAgICAgcmV0dXJuIGJBW2J5dGVwb3MrK107XG4gICAgfSBlbHNlXG4gICAgICByZXR1cm4gLTE7XG4gIH07XG5cbiAgZnVuY3Rpb24gYnl0ZUFsaWduKCkge1xuICAgIGJiID0gMTtcbiAgfTtcblxuICBmdW5jdGlvbiByZWFkQml0KCkge1xuICAgIHZhciBjYXJyeTtcbiAgICBiaXRzKys7XG4gICAgY2FycnkgPSAoYmIgJiAxKTtcbiAgICBiYiA+Pj0gMTtcbiAgICBpZiAoYmIgPT0gMCkge1xuICAgICAgYmIgPSByZWFkQnl0ZSgpO1xuICAgICAgY2FycnkgPSAoYmIgJiAxKTtcbiAgICAgIGJiID0gKGJiID4+IDEpIHwgMHg4MDtcbiAgICB9XG4gICAgcmV0dXJuIGNhcnJ5O1xuICB9O1xuXG4gIGZ1bmN0aW9uIHJlYWRCaXRzKGEpIHtcbiAgICB2YXIgcmVzID0gMCxcbiAgICAgIGkgPSBhO1xuXG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgcmVzID0gKHJlcyA8PCAxKSB8IHJlYWRCaXQoKTtcbiAgICB9XG4gICAgaWYgKGEpIHtcbiAgICAgIHJlcyA9IGJpdFJldmVyc2VbcmVzXSA+PiAoOCAtIGEpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGZsdXNoQnVmZmVyKCkge1xuICAgIC8vZG9jdW1lbnQud3JpdGUoJ0ZMVVNIQlVGRkVSOicrYnVmMzJrKTtcbiAgICBiSWR4ID0gMDtcbiAgfTtcblxuICBmdW5jdGlvbiBhZGRCdWZmZXIoYSkge1xuICAgIFNJWkUrKztcbiAgICAvL0NSQz11cGRjcmMoYSxjcmMpO1xuICAgIGJ1ZjMya1tiSWR4KytdID0gYTtcbiAgICBvdXRwdXRBcnIucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGEpKTtcbiAgICAvL291dHB1dCs9U3RyaW5nLmZyb21DaGFyQ29kZShhKTtcbiAgICBpZiAoYklkeCA9PSAweDgwMDApIHtcbiAgICAgIC8vZG9jdW1lbnQud3JpdGUoJ0FEREJVRkZFUjonK2J1ZjMyayk7XG4gICAgICBiSWR4ID0gMDtcbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gSHVmTm9kZSgpIHtcbiAgICB0aGlzLmIwID0gMDtcbiAgICB0aGlzLmIxID0gMDtcbiAgICB0aGlzLmp1bXAgPSBudWxsO1xuICAgIHRoaXMuanVtcHBvcyA9IC0xO1xuICB9O1xuXG4gIHZhciBMSVRFUkFMUyA9IDI4ODtcblxuICB2YXIgbGl0ZXJhbFRyZWUgPSBuZXcgQXJyYXkoTElURVJBTFMpO1xuICB2YXIgZGlzdGFuY2VUcmVlID0gbmV3IEFycmF5KDMyKTtcbiAgdmFyIHRyZWVwb3MgPSAwO1xuICB2YXIgUGxhY2VzID0gbnVsbDtcbiAgdmFyIFBsYWNlczIgPSBudWxsO1xuXG4gIHZhciBpbXBEaXN0YW5jZVRyZWUgPSBuZXcgQXJyYXkoNjQpO1xuICB2YXIgaW1wTGVuZ3RoVHJlZSA9IG5ldyBBcnJheSg2NCk7XG5cbiAgdmFyIGxlbiA9IDA7XG4gIHZhciBmcG9zID0gbmV3IEFycmF5KDE3KTtcbiAgZnBvc1swXSA9IDA7XG4gIHZhciBmbGVucztcbiAgdmFyIGZtYXg7XG5cbiAgZnVuY3Rpb24gSXNQYXQoKSB7XG4gICAgd2hpbGUgKDEpIHtcbiAgICAgIGlmIChmcG9zW2xlbl0gPj0gZm1heClcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgaWYgKGZsZW5zW2Zwb3NbbGVuXV0gPT0gbGVuKVxuICAgICAgICByZXR1cm4gZnBvc1tsZW5dKys7XG4gICAgICBmcG9zW2xlbl0rKztcbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gUmVjKCkge1xuICAgIHZhciBjdXJwbGFjZSA9IFBsYWNlc1t0cmVlcG9zXTtcbiAgICB2YXIgdG1wO1xuICAgIGlmIChkZWJ1ZylcbiAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPmxlbjpcIiArIGxlbiArIFwiIHRyZWVwb3M6XCIgKyB0cmVlcG9zKTtcbiAgICBpZiAobGVuID09IDE3KSB7IC8vd2FyIDE3XG4gICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIHRyZWVwb3MrKztcbiAgICBsZW4rKztcblxuICAgIHRtcCA9IElzUGF0KCk7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+SXNQYXQgXCIgKyB0bXApO1xuICAgIGlmICh0bXAgPj0gMCkge1xuICAgICAgY3VycGxhY2UuYjAgPSB0bXA7IC8qIGxlYWYgY2VsbCBmb3IgMC1iaXQgKi9cbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgZG9jdW1lbnQud3JpdGUoXCI8YnI+YjAgXCIgKyBjdXJwbGFjZS5iMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIE5vdCBhIExlYWYgY2VsbCAqL1xuICAgICAgY3VycGxhY2UuYjAgPSAweDgwMDA7XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPmIwIFwiICsgY3VycGxhY2UuYjApO1xuICAgICAgaWYgKFJlYygpKVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIHRtcCA9IElzUGF0KCk7XG4gICAgaWYgKHRtcCA+PSAwKSB7XG4gICAgICBjdXJwbGFjZS5iMSA9IHRtcDsgLyogbGVhZiBjZWxsIGZvciAxLWJpdCAqL1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBkb2N1bWVudC53cml0ZShcIjxicj5iMSBcIiArIGN1cnBsYWNlLmIxKTtcbiAgICAgIGN1cnBsYWNlLmp1bXAgPSBudWxsOyAvKiBKdXN0IGZvciB0aGUgZGlzcGxheSByb3V0aW5lICovXG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIE5vdCBhIExlYWYgY2VsbCAqL1xuICAgICAgY3VycGxhY2UuYjEgPSAweDgwMDA7XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPmIxIFwiICsgY3VycGxhY2UuYjEpO1xuICAgICAgY3VycGxhY2UuanVtcCA9IFBsYWNlc1t0cmVlcG9zXTtcbiAgICAgIGN1cnBsYWNlLmp1bXBwb3MgPSB0cmVlcG9zO1xuICAgICAgaWYgKFJlYygpKVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGxlbi0tO1xuICAgIHJldHVybiAwO1xuICB9O1xuXG4gIGZ1bmN0aW9uIENyZWF0ZVRyZWUoY3VycmVudFRyZWUsIG51bXZhbCwgbGVuZ3Rocywgc2hvdykge1xuICAgIHZhciBpO1xuICAgIC8qIENyZWF0ZSB0aGUgSHVmZm1hbiBkZWNvZGUgdHJlZS90YWJsZSAqL1xuICAgIC8vZG9jdW1lbnQud3JpdGUoXCI8YnI+Y3JlYXRldHJlZTxicj5cIik7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgZG9jdW1lbnQud3JpdGUoXCJjdXJyZW50VHJlZSBcIiArIGN1cnJlbnRUcmVlICsgXCIgbnVtdmFsIFwiICsgbnVtdmFsICsgXCIgbGVuZ3RocyBcIiArIGxlbmd0aHMgKyBcIiBzaG93IFwiICsgc2hvdyk7XG4gICAgUGxhY2VzID0gY3VycmVudFRyZWU7XG4gICAgdHJlZXBvcyA9IDA7XG4gICAgZmxlbnMgPSBsZW5ndGhzO1xuICAgIGZtYXggPSBudW12YWw7XG4gICAgZm9yIChpID0gMDsgaSA8IDE3OyBpKyspXG4gICAgICBmcG9zW2ldID0gMDtcbiAgICBsZW4gPSAwO1xuICAgIGlmIChSZWMoKSkge1xuICAgICAgLy9mcHJpbnRmKHN0ZGVyciwgXCJpbnZhbGlkIGh1ZmZtYW4gdHJlZVxcblwiKTtcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgYWxlcnQoXCJpbnZhbGlkIGh1ZmZtYW4gdHJlZVxcblwiKTtcbiAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgaWYgKGRlYnVnKSB7XG4gICAgICBkb2N1bWVudC53cml0ZSgnPGJyPlRyZWU6ICcgKyBQbGFjZXMubGVuZ3RoKTtcbiAgICAgIGZvciAodmFyIGEgPSAwOyBhIDwgMzI7IGErKykge1xuICAgICAgICBkb2N1bWVudC53cml0ZShcIlBsYWNlc1tcIiArIGEgKyBcIl0uYjA9XCIgKyBQbGFjZXNbYV0uYjAgKyBcIjxicj5cIik7XG4gICAgICAgIGRvY3VtZW50LndyaXRlKFwiUGxhY2VzW1wiICsgYSArIFwiXS5iMT1cIiArIFBsYWNlc1thXS5iMSArIFwiPGJyPlwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKmlmKHNob3cpIHtcbiAgICAgICAgICAgIHZhciB0bXA7XG4gICAgICAgICAgICBmb3IodG1wPWN1cnJlbnRUcmVlO3RtcDxQbGFjZXM7dG1wKyspIHtcbiAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91dCwgXCIweCUwM3ggIDB4JTAzeCAoMHglMDR4KVwiLHRtcC1jdXJyZW50VHJlZSwgdG1wLT5qdW1wP3RtcC0+anVtcC1jdXJyZW50VHJlZTowLCh0bXAtPmp1bXA/dG1wLT5qdW1wLWN1cnJlbnRUcmVlOjApKjYrMHhjZjApO1xuICAgICAgICAgICAgICAgIGlmKCEodG1wLmIwICYgMHg4MDAwKSkge1xuICAgICAgICAgICAgICAgICAgICAvL2ZwcmludGYoc3Rkb3V0LCBcIiAgMHglMDN4ICglYylcIiwgdG1wLT5iMCwodG1wLT5iMDwyNTYgJiYgaXNwcmludCh0bXAtPmIwKSk/dG1wLT5iMDon77+9Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmKCEodG1wLmIxICYgMHg4MDAwKSkge1xuICAgICAgICAgICAgICAgICAgICBpZigodG1wLmIwICYgMHg4MDAwKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGZwcmludGYoc3Rkb3V0LCBcIiAgICAgICAgICAgXCIpO1xuICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91dCwgXCIgIDB4JTAzeCAoJWMpXCIsIHRtcC0+YjEsKHRtcC0+YjE8MjU2ICYmIGlzcHJpbnQodG1wLT5iMSkpP3RtcC0+YjE6J++/vScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmcHJpbnRmKHN0ZG91dCwgXCJcXG5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0qL1xuICAgIHJldHVybiAwO1xuICB9O1xuXG4gIGZ1bmN0aW9uIERlY29kZVZhbHVlKGN1cnJlbnRUcmVlKSB7XG4gICAgdmFyIGxlbiwgaSxcbiAgICAgIHh0cmVlcG9zID0gMCxcbiAgICAgIFggPSBjdXJyZW50VHJlZVt4dHJlZXBvc10sXG4gICAgICBiO1xuXG4gICAgLyogZGVjb2RlIG9uZSBzeW1ib2wgb2YgdGhlIGRhdGEgKi9cbiAgICB3aGlsZSAoMSkge1xuICAgICAgYiA9IHJlYWRCaXQoKTtcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgZG9jdW1lbnQud3JpdGUoXCJiPVwiICsgYik7XG4gICAgICBpZiAoYikge1xuICAgICAgICBpZiAoIShYLmIxICYgMHg4MDAwKSkge1xuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwicmV0MVwiKTtcbiAgICAgICAgICByZXR1cm4gWC5iMTsgLyogSWYgbGVhZiBub2RlLCByZXR1cm4gZGF0YSAqL1xuICAgICAgICB9XG4gICAgICAgIFggPSBYLmp1bXA7XG4gICAgICAgIGxlbiA9IGN1cnJlbnRUcmVlLmxlbmd0aDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgaWYgKGN1cnJlbnRUcmVlW2ldID09PSBYKSB7XG4gICAgICAgICAgICB4dHJlZXBvcyA9IGk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy94dHJlZXBvcysrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCEoWC5iMCAmIDB4ODAwMCkpIHtcbiAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBkb2N1bWVudC53cml0ZShcInJldDJcIik7XG4gICAgICAgICAgcmV0dXJuIFguYjA7IC8qIElmIGxlYWYgbm9kZSwgcmV0dXJuIGRhdGEgKi9cbiAgICAgICAgfVxuICAgICAgICAvL1grKzsgLy8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz9cbiAgICAgICAgeHRyZWVwb3MrKztcbiAgICAgICAgWCA9IGN1cnJlbnRUcmVlW3h0cmVlcG9zXTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGRlYnVnKVxuICAgICAgZG9jdW1lbnQud3JpdGUoXCJyZXQzXCIpO1xuICAgIHJldHVybiAtMTtcbiAgfTtcblxuICBmdW5jdGlvbiBEZWZsYXRlTG9vcCgpIHtcbiAgICB2YXIgbGFzdCwgYywgdHlwZSwgaSwgbGVuO1xuXG4gICAgZG8ge1xuICAgICAgLyppZigobGFzdCA9IHJlYWRCaXQoKSkpe1xuICAgICAgICAgICAgZnByaW50ZihlcnJmcCwgXCJMYXN0IEJsb2NrOiBcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmcHJpbnRmKGVycmZwLCBcIk5vdCBMYXN0IEJsb2NrOiBcIik7XG4gICAgICAgIH0qL1xuICAgICAgbGFzdCA9IHJlYWRCaXQoKTtcbiAgICAgIHR5cGUgPSByZWFkQml0cygyKTtcbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgICAgYWxlcnQoXCJTdG9yZWRcXG5cIik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBhbGVydChcIkZpeGVkIEh1ZmZtYW4gY29kZXNcXG5cIik7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBhbGVydChcIkR5bmFtaWMgSHVmZm1hbiBjb2Rlc1xcblwiKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGFsZXJ0KFwiUmVzZXJ2ZWQgYmxvY2sgdHlwZSEhXFxuXCIpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGFsZXJ0KFwiVW5leHBlY3RlZCB2YWx1ZSAlZCFcXG5cIiwgdHlwZSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlID09IDApIHtcbiAgICAgICAgdmFyIGJsb2NrTGVuLCBjU3VtO1xuXG4gICAgICAgIC8vIFN0b3JlZCBcbiAgICAgICAgYnl0ZUFsaWduKCk7XG4gICAgICAgIGJsb2NrTGVuID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgYmxvY2tMZW4gfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG5cbiAgICAgICAgY1N1bSA9IHJlYWRCeXRlKCk7XG4gICAgICAgIGNTdW0gfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG5cbiAgICAgICAgaWYgKCgoYmxvY2tMZW4gXiB+Y1N1bSkgJiAweGZmZmYpKSB7XG4gICAgICAgICAgZG9jdW1lbnQud3JpdGUoXCJCbG9ja0xlbiBjaGVja3N1bSBtaXNtYXRjaFxcblwiKTtcbiAgICAgICAgfVxuICAgICAgICB3aGlsZSAoYmxvY2tMZW4tLSkge1xuICAgICAgICAgIGMgPSByZWFkQnl0ZSgpO1xuICAgICAgICAgIGFkZEJ1ZmZlcihjKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlID09IDEpIHtcbiAgICAgICAgdmFyIGo7XG5cbiAgICAgICAgLyogRml4ZWQgSHVmZm1hbiB0YWJsZXMgLS0gZml4ZWQgZGVjb2RlIHJvdXRpbmUgKi9cbiAgICAgICAgd2hpbGUgKDEpIHtcbiAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgIDI1NiAgICAwMDAwMDAwICAgICAgICAwXG4gICAgICAgICAgICAgICAgOiAgIDogICAgIDpcbiAgICAgICAgICAgICAgICAyNzkgICAgMDAxMDExMSAgICAgICAgMjNcbiAgICAgICAgICAgICAgICAwICAgMDAxMTAwMDAgICAgNDhcbiAgICAgICAgICAgICAgICA6ICAgIDogICAgICA6XG4gICAgICAgICAgICAgICAgMTQzICAgIDEwMTExMTExICAgIDE5MVxuICAgICAgICAgICAgICAgIDI4MCAxMTAwMDAwMCAgICAxOTJcbiAgICAgICAgICAgICAgICA6ICAgIDogICAgICA6XG4gICAgICAgICAgICAgICAgMjg3IDExMDAwMTExICAgIDE5OVxuICAgICAgICAgICAgICAgIDE0NCAgICAxMTAwMTAwMDAgICAgNDAwXG4gICAgICAgICAgICAgICAgOiAgICA6ICAgICAgIDpcbiAgICAgICAgICAgICAgICAyNTUgICAgMTExMTExMTExICAgIDUxMVxuICAgIFxuICAgICAgICAgICAgICAgIE5vdGUgdGhlIGJpdCBvcmRlciFcbiAgICAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgaiA9IChiaXRSZXZlcnNlW3JlYWRCaXRzKDcpXSA+PiAxKTtcbiAgICAgICAgICBpZiAoaiA+IDIzKSB7XG4gICAgICAgICAgICBqID0gKGogPDwgMSkgfCByZWFkQml0KCk7IC8qIDQ4Li4yNTUgKi9cblxuICAgICAgICAgICAgaWYgKGogPiAxOTkpIHsgLyogMjAwLi4yNTUgKi9cbiAgICAgICAgICAgICAgaiAtPSAxMjg7IC8qICA3Mi4uMTI3ICovXG4gICAgICAgICAgICAgIGogPSAoaiA8PCAxKSB8IHJlYWRCaXQoKTsgLyogMTQ0Li4yNTUgPDwgKi9cbiAgICAgICAgICAgIH0gZWxzZSB7IC8qICA0OC4uMTk5ICovXG4gICAgICAgICAgICAgIGogLT0gNDg7IC8qICAgMC4uMTUxICovXG4gICAgICAgICAgICAgIGlmIChqID4gMTQzKSB7XG4gICAgICAgICAgICAgICAgaiA9IGogKyAxMzY7IC8qIDI4MC4uMjg3IDw8ICovXG4gICAgICAgICAgICAgICAgLyogICAwLi4xNDMgPDwgKi9cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7IC8qICAgMC4uMjMgKi9cbiAgICAgICAgICAgIGogKz0gMjU2OyAvKiAyNTYuLjI3OSA8PCAqL1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaiA8IDI1Nikge1xuICAgICAgICAgICAgYWRkQnVmZmVyKGopO1xuICAgICAgICAgICAgLy9kb2N1bWVudC53cml0ZShcIm91dDpcIitTdHJpbmcuZnJvbUNoYXJDb2RlKGopKTtcbiAgICAgICAgICAgIC8qZnByaW50ZihlcnJmcCwgXCJAJWQgJTAyeFxcblwiLCBTSVpFLCBqKTsqL1xuICAgICAgICAgIH0gZWxzZSBpZiAoaiA9PSAyNTYpIHtcbiAgICAgICAgICAgIC8qIEVPRiAqL1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBsZW4sIGRpc3Q7XG5cbiAgICAgICAgICAgIGogLT0gMjU2ICsgMTsgLyogYnl0ZXMgKyBFT0YgKi9cbiAgICAgICAgICAgIGxlbiA9IHJlYWRCaXRzKGNwbGV4dFtqXSkgKyBjcGxlbnNbal07XG5cbiAgICAgICAgICAgIGogPSBiaXRSZXZlcnNlW3JlYWRCaXRzKDUpXSA+PiAzO1xuICAgICAgICAgICAgaWYgKGNwZGV4dFtqXSA+IDgpIHtcbiAgICAgICAgICAgICAgZGlzdCA9IHJlYWRCaXRzKDgpO1xuICAgICAgICAgICAgICBkaXN0IHw9IChyZWFkQml0cyhjcGRleHRbal0gLSA4KSA8PCA4KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGRpc3QgPSByZWFkQml0cyhjcGRleHRbal0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGlzdCArPSBjcGRpc3Rbal07XG5cbiAgICAgICAgICAgIC8qZnByaW50ZihlcnJmcCwgXCJAJWQgKGwlMDJ4LGQlMDR4KVxcblwiLCBTSVpFLCBsZW4sIGRpc3QpOyovXG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbGVuOyBqKyspIHtcbiAgICAgICAgICAgICAgdmFyIGMgPSBidWYzMmtbKGJJZHggLSBkaXN0KSAmIDB4N2ZmZl07XG4gICAgICAgICAgICAgIGFkZEJ1ZmZlcihjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gd2hpbGVcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PSAyKSB7XG4gICAgICAgIHZhciBqLCBuLCBsaXRlcmFsQ29kZXMsIGRpc3RDb2RlcywgbGVuQ29kZXM7XG4gICAgICAgIHZhciBsbCA9IG5ldyBBcnJheSgyODggKyAzMik7IC8vIFwic3RhdGljXCIganVzdCB0byBwcmVzZXJ2ZSBzdGFja1xuXG4gICAgICAgIC8vIER5bmFtaWMgSHVmZm1hbiB0YWJsZXMgXG5cbiAgICAgICAgbGl0ZXJhbENvZGVzID0gMjU3ICsgcmVhZEJpdHMoNSk7XG4gICAgICAgIGRpc3RDb2RlcyA9IDEgKyByZWFkQml0cyg1KTtcbiAgICAgICAgbGVuQ29kZXMgPSA0ICsgcmVhZEJpdHMoNCk7XG4gICAgICAgIC8vZG9jdW1lbnQud3JpdGUoXCI8YnI+cGFyYW06IFwiK2xpdGVyYWxDb2RlcytcIiBcIitkaXN0Q29kZXMrXCIgXCIrbGVuQ29kZXMrXCI8YnI+XCIpO1xuICAgICAgICBmb3IgKGogPSAwOyBqIDwgMTk7IGorKykge1xuICAgICAgICAgIGxsW2pdID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCB0aGUgZGVjb2RlIHRyZWUgY29kZSBsZW5ndGhzXG5cbiAgICAgICAgLy9kb2N1bWVudC53cml0ZShcIjxicj5cIik7XG4gICAgICAgIGZvciAoaiA9IDA7IGogPCBsZW5Db2RlczsgaisrKSB7XG4gICAgICAgICAgbGxbYm9yZGVyW2pdXSA9IHJlYWRCaXRzKDMpO1xuICAgICAgICAgIC8vZG9jdW1lbnQud3JpdGUobGxbYm9yZGVyW2pdXStcIiBcIik7XG4gICAgICAgIH1cbiAgICAgICAgLy9mcHJpbnRmKGVycmZwLCBcIlxcblwiKTtcbiAgICAgICAgLy9kb2N1bWVudC53cml0ZSgnPGJyPmxsOicrbGwpO1xuICAgICAgICBsZW4gPSBkaXN0YW5jZVRyZWUubGVuZ3RoO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICAgICAgZGlzdGFuY2VUcmVlW2ldID0gbmV3IEh1Zk5vZGUoKTtcbiAgICAgICAgaWYgKENyZWF0ZVRyZWUoZGlzdGFuY2VUcmVlLCAxOSwgbGwsIDApKSB7XG4gICAgICAgICAgZmx1c2hCdWZmZXIoKTtcbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGVidWcpIHtcbiAgICAgICAgICBkb2N1bWVudC53cml0ZShcIjxicj5kaXN0YW5jZVRyZWVcIik7XG4gICAgICAgICAgZm9yICh2YXIgYSA9IDA7IGEgPCBkaXN0YW5jZVRyZWUubGVuZ3RoOyBhKyspIHtcbiAgICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPlwiICsgZGlzdGFuY2VUcmVlW2FdLmIwICsgXCIgXCIgKyBkaXN0YW5jZVRyZWVbYV0uYjEgKyBcIiBcIiArIGRpc3RhbmNlVHJlZVthXS5qdW1wICsgXCIgXCIgK1xuICAgICAgICAgICAgICBkaXN0YW5jZVRyZWVbYV0uanVtcHBvcyk7XG4gICAgICAgICAgICAvKmlmIChkaXN0YW5jZVRyZWVbYV0uanVtcHBvcyE9LTEpXG4gICAgICAgICAgICAgICAgICAgIFx0ZG9jdW1lbnQud3JpdGUoXCIgXCIrZGlzdGFuY2VUcmVlW2FdLmp1bXAuYjArXCIgXCIrZGlzdGFuY2VUcmVlW2FdLmp1bXAuYjEpO1xuICAgICAgICAgICAgICAgIFx0Ki9cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy9kb2N1bWVudC53cml0ZSgnPEJSPnRyZWUgY3JlYXRlZCcpO1xuXG4gICAgICAgIC8vcmVhZCBpbiBsaXRlcmFsIGFuZCBkaXN0YW5jZSBjb2RlIGxlbmd0aHNcbiAgICAgICAgbiA9IGxpdGVyYWxDb2RlcyArIGRpc3RDb2RlcztcbiAgICAgICAgaSA9IDA7XG4gICAgICAgIHZhciB6ID0gLTE7XG4gICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICBkb2N1bWVudC53cml0ZShcIjxicj5uPVwiICsgbiArIFwiIGJpdHM6IFwiICsgYml0cyArIFwiPGJyPlwiKTtcbiAgICAgICAgd2hpbGUgKGkgPCBuKSB7XG4gICAgICAgICAgeisrO1xuICAgICAgICAgIGogPSBEZWNvZGVWYWx1ZShkaXN0YW5jZVRyZWUpO1xuICAgICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICAgIGRvY3VtZW50LndyaXRlKFwiPGJyPlwiICsgeiArIFwiIGk6XCIgKyBpICsgXCIgZGVjb2RlOiBcIiArIGogKyBcIiAgICBiaXRzIFwiICsgYml0cyArIFwiPGJyPlwiKTtcbiAgICAgICAgICBpZiAoaiA8IDE2KSB7IC8vIGxlbmd0aCBvZiBjb2RlIGluIGJpdHMgKDAuLjE1KVxuICAgICAgICAgICAgbGxbaSsrXSA9IGo7XG4gICAgICAgICAgfSBlbHNlIGlmIChqID09IDE2KSB7IC8vIHJlcGVhdCBsYXN0IGxlbmd0aCAzIHRvIDYgdGltZXMgXG4gICAgICAgICAgICB2YXIgbDtcbiAgICAgICAgICAgIGogPSAzICsgcmVhZEJpdHMoMik7XG4gICAgICAgICAgICBpZiAoaSArIGogPiBuKSB7XG4gICAgICAgICAgICAgIGZsdXNoQnVmZmVyKCk7XG4gICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbCA9IGkgPyBsbFtpIC0gMV0gOiAwO1xuICAgICAgICAgICAgd2hpbGUgKGotLSkge1xuICAgICAgICAgICAgICBsbFtpKytdID0gbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGogPT0gMTcpIHsgLy8gMyB0byAxMCB6ZXJvIGxlbmd0aCBjb2Rlc1xuICAgICAgICAgICAgICBqID0gMyArIHJlYWRCaXRzKDMpO1xuICAgICAgICAgICAgfSBlbHNlIHsgLy8gaiA9PSAxODogMTEgdG8gMTM4IHplcm8gbGVuZ3RoIGNvZGVzIFxuICAgICAgICAgICAgICBqID0gMTEgKyByZWFkQml0cyg3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChpICsgaiA+IG4pIHtcbiAgICAgICAgICAgICAgZmx1c2hCdWZmZXIoKTtcbiAgICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aGlsZSAoai0tKSB7XG4gICAgICAgICAgICAgIGxsW2krK10gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKmZvcihqPTA7IGo8bGl0ZXJhbENvZGVzK2Rpc3RDb2RlczsgaisrKSB7XG4gICAgICAgICAgICAgICAgLy9mcHJpbnRmKGVycmZwLCBcIiVkIFwiLCBsbFtqXSk7XG4gICAgICAgICAgICAgICAgaWYgKChqJjcpPT03KVxuICAgICAgICAgICAgICAgICAgICBmcHJpbnRmKGVycmZwLCBcIlxcblwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZwcmludGYoZXJyZnAsIFwiXFxuXCIpOyovXG4gICAgICAgIC8vIENhbiBvdmVyd3JpdGUgdHJlZSBkZWNvZGUgdHJlZSBhcyBpdCBpcyBub3QgdXNlZCBhbnltb3JlXG4gICAgICAgIGxlbiA9IGxpdGVyYWxUcmVlLmxlbmd0aDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKVxuICAgICAgICAgIGxpdGVyYWxUcmVlW2ldID0gbmV3IEh1Zk5vZGUoKTtcbiAgICAgICAgaWYgKENyZWF0ZVRyZWUobGl0ZXJhbFRyZWUsIGxpdGVyYWxDb2RlcywgbGwsIDApKSB7XG4gICAgICAgICAgZmx1c2hCdWZmZXIoKTtcbiAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuICAgICAgICBsZW4gPSBsaXRlcmFsVHJlZS5sZW5ndGg7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgICAgICBkaXN0YW5jZVRyZWVbaV0gPSBuZXcgSHVmTm9kZSgpO1xuICAgICAgICB2YXIgbGwyID0gbmV3IEFycmF5KCk7XG4gICAgICAgIGZvciAoaSA9IGxpdGVyYWxDb2RlczsgaSA8IGxsLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgbGwyW2kgLSBsaXRlcmFsQ29kZXNdID0gbGxbaV07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKENyZWF0ZVRyZWUoZGlzdGFuY2VUcmVlLCBkaXN0Q29kZXMsIGxsMiwgMCkpIHtcbiAgICAgICAgICBmbHVzaEJ1ZmZlcigpO1xuICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICBkb2N1bWVudC53cml0ZShcIjxicj5saXRlcmFsVHJlZVwiKTtcbiAgICAgICAgb3V0ZXI6IHdoaWxlICgxKSB7XG4gICAgICAgICAgaiA9IERlY29kZVZhbHVlKGxpdGVyYWxUcmVlKTtcbiAgICAgICAgICBpZiAoaiA+PSAyNTYpIHsgLy8gSW4gQzY0OiBpZiBjYXJyeSBzZXRcbiAgICAgICAgICAgIHZhciBsZW4sIGRpc3Q7XG4gICAgICAgICAgICBqIC09IDI1NjtcbiAgICAgICAgICAgIGlmIChqID09IDApIHtcbiAgICAgICAgICAgICAgLy8gRU9GXG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgai0tO1xuICAgICAgICAgICAgbGVuID0gcmVhZEJpdHMoY3BsZXh0W2pdKSArIGNwbGVuc1tqXTtcblxuICAgICAgICAgICAgaiA9IERlY29kZVZhbHVlKGRpc3RhbmNlVHJlZSk7XG4gICAgICAgICAgICBpZiAoY3BkZXh0W2pdID4gOCkge1xuICAgICAgICAgICAgICBkaXN0ID0gcmVhZEJpdHMoOCk7XG4gICAgICAgICAgICAgIGRpc3QgfD0gKHJlYWRCaXRzKGNwZGV4dFtqXSAtIDgpIDw8IDgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgZGlzdCA9IHJlYWRCaXRzKGNwZGV4dFtqXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkaXN0ICs9IGNwZGlzdFtqXTtcbiAgICAgICAgICAgIHdoaWxlIChsZW4tLSkge1xuICAgICAgICAgICAgICBpZiAoYklkeCAtIGRpc3QgPCAwKSB7XG4gICAgICAgICAgICAgICAgYnJlYWsgb3V0ZXI7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdmFyIGMgPSBidWYzMmtbKGJJZHggLSBkaXN0KSAmIDB4N2ZmZl07XG4gICAgICAgICAgICAgIGFkZEJ1ZmZlcihjKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWRkQnVmZmVyKGopO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gd2hpbGUgKCFsYXN0KTtcbiAgICBmbHVzaEJ1ZmZlcigpO1xuXG4gICAgYnl0ZUFsaWduKCk7XG4gICAgcmV0dXJuIDA7XG4gIH07XG5cbiAgSlhHLlV0aWwuVW56aXAucHJvdG90eXBlLnVuemlwRmlsZSA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgaTtcbiAgICB0aGlzLnVuemlwKCk7XG4gICAgLy9hbGVydCh1bnppcHBlZFswXVsxXSk7XG4gICAgZm9yIChpID0gMDsgaSA8IHVuemlwcGVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodW56aXBwZWRbaV1bMV0gPT0gbmFtZSkge1xuICAgICAgICByZXR1cm4gdW56aXBwZWRbaV1bMF07XG4gICAgICB9XG4gICAgfVxuXG4gIH07XG5cbiAgSlhHLlV0aWwuVW56aXAucHJvdG90eXBlLmRlZmxhdGUgPSBmdW5jdGlvbigpIHtcbiAgICBvdXRwdXRBcnIgPSBbXTtcbiAgICB2YXIgdG1wID0gW107XG4gICAgbW9kZVpJUCA9IGZhbHNlO1xuICAgIERlZmxhdGVMb29wKCk7XG4gICAgaWYgKGRlYnVnKVxuICAgICAgYWxlcnQob3V0cHV0QXJyLmpvaW4oJycpKTtcbiAgICB1bnppcHBlZFtmaWxlc10gPSBuZXcgQXJyYXkoMik7XG4gICAgdW56aXBwZWRbZmlsZXNdWzBdID0gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgIHVuemlwcGVkW2ZpbGVzXVsxXSA9IFwiREVGTEFURVwiO1xuICAgIGZpbGVzKys7XG4gICAgcmV0dXJuIHVuemlwcGVkO1xuICB9XG5cbiAgSlhHLlV0aWwuVW56aXAucHJvdG90eXBlLnVuemlwID0gZnVuY3Rpb24oKSB7XG4gICAgLy9jb252ZXJ0VG9CeXRlQXJyYXkoaW5wdXQpO1xuICAgIGlmIChkZWJ1ZylcbiAgICAgIGFsZXJ0KGJBKTtcbiAgICAvKmZvciAoaT0wO2k8YkEubGVuZ3RoKjg7aSsrKXtcblx0XHRkb2N1bWVudC53cml0ZShyZWFkQml0KCkpO1xuXHRcdGlmICgoaSsxKSU4PT0wKVxuXHRcdFx0ZG9jdW1lbnQud3JpdGUoXCIgXCIpO1xuXHR9Ki9cbiAgICAvKmZvciAoaT0wO2k8YkEubGVuZ3RoO2krKyl7XG5cdFx0ZG9jdW1lbnQud3JpdGUocmVhZEJ5dGUoKStcIiBcIik7XG5cdFx0aWYgKChpKzEpJTg9PTApXG5cdFx0XHRkb2N1bWVudC53cml0ZShcIiBcIik7XG5cdH1cblx0Zm9yIChpPTA7aTxiQS5sZW5ndGg7aSsrKXtcblx0XHRkb2N1bWVudC53cml0ZShiQVtpXStcIiBcIik7XG5cdFx0aWYgKChpKzEpJTE2PT0wKVxuXHRcdFx0ZG9jdW1lbnQud3JpdGUoXCI8YnI+XCIpO1xuXHR9XHRcblx0Ki9cbiAgICAvL2FsZXJ0KGJBKTtcbiAgICBuZXh0RmlsZSgpO1xuICAgIHJldHVybiB1bnppcHBlZDtcbiAgfTtcblxuICBmdW5jdGlvbiBuZXh0RmlsZSgpIHtcbiAgICBpZiAoZGVidWcpXG4gICAgICBhbGVydChcIk5FWFRGSUxFXCIpO1xuICAgIG91dHB1dEFyciA9IFtdO1xuICAgIHZhciB0bXAgPSBbXTtcbiAgICBtb2RlWklQID0gZmFsc2U7XG4gICAgdG1wWzBdID0gcmVhZEJ5dGUoKTtcbiAgICB0bXBbMV0gPSByZWFkQnl0ZSgpO1xuICAgIGlmIChkZWJ1ZylcbiAgICAgIGFsZXJ0KFwidHlwZTogXCIgKyB0bXBbMF0gKyBcIiBcIiArIHRtcFsxXSk7XG4gICAgaWYgKHRtcFswXSA9PSBwYXJzZUludChcIjc4XCIsIDE2KSAmJiB0bXBbMV0gPT0gcGFyc2VJbnQoXCJkYVwiLCAxNikpIHsgLy9HWklQXG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KFwiR0VPTkV4VC1HWklQXCIpO1xuICAgICAgRGVmbGF0ZUxvb3AoKTtcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgYWxlcnQob3V0cHV0QXJyLmpvaW4oJycpKTtcbiAgICAgIHVuemlwcGVkW2ZpbGVzXSA9IG5ldyBBcnJheSgyKTtcbiAgICAgIHVuemlwcGVkW2ZpbGVzXVswXSA9IG91dHB1dEFyci5qb2luKCcnKTtcbiAgICAgIHVuemlwcGVkW2ZpbGVzXVsxXSA9IFwiZ2VvbmV4dC5neHRcIjtcbiAgICAgIGZpbGVzKys7XG4gICAgfVxuICAgIGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI3OFwiLCAxNikgJiYgdG1wWzFdID09IHBhcnNlSW50KFwiOWNcIiwgMTYpKSB7IC8vWkxJQlxuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChcIlpMSUJcIik7XG4gICAgICBEZWZsYXRlTG9vcCgpO1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdID0gbmV3IEFycmF5KDIpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdWzBdID0gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdWzFdID0gXCJaTElCXCI7XG4gICAgICBmaWxlcysrO1xuICAgIH1cbiAgICBpZiAodG1wWzBdID09IHBhcnNlSW50KFwiMWZcIiwgMTYpICYmIHRtcFsxXSA9PSBwYXJzZUludChcIjhiXCIsIDE2KSkgeyAvL0daSVBcbiAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgYWxlcnQoXCJHWklQXCIpO1xuICAgICAgLy9EZWZsYXRlTG9vcCgpO1xuICAgICAgc2tpcGRpcigpO1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdID0gbmV3IEFycmF5KDIpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdWzBdID0gb3V0cHV0QXJyLmpvaW4oJycpO1xuICAgICAgdW56aXBwZWRbZmlsZXNdWzFdID0gXCJmaWxlXCI7XG4gICAgICBmaWxlcysrO1xuICAgIH1cbiAgICBpZiAodG1wWzBdID09IHBhcnNlSW50KFwiNTBcIiwgMTYpICYmIHRtcFsxXSA9PSBwYXJzZUludChcIjRiXCIsIDE2KSkgeyAvL1pJUFxuICAgICAgbW9kZVpJUCA9IHRydWU7XG4gICAgICB0bXBbMl0gPSByZWFkQnl0ZSgpO1xuICAgICAgdG1wWzNdID0gcmVhZEJ5dGUoKTtcbiAgICAgIGlmICh0bXBbMl0gPT0gcGFyc2VJbnQoXCIzXCIsIDE2KSAmJiB0bXBbM10gPT0gcGFyc2VJbnQoXCI0XCIsIDE2KSkge1xuICAgICAgICAvL01PREVfWklQXG4gICAgICAgIHRtcFswXSA9IHJlYWRCeXRlKCk7XG4gICAgICAgIHRtcFsxXSA9IHJlYWRCeXRlKCk7XG4gICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICBhbGVydChcIlpJUC1WZXJzaW9uOiBcIiArIHRtcFsxXSArIFwiIFwiICsgdG1wWzBdIC8gMTAgKyBcIi5cIiArIHRtcFswXSAlIDEwKTtcblxuICAgICAgICBncGZsYWdzID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgZ3BmbGFncyB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgIGFsZXJ0KFwiZ3BmbGFnczogXCIgKyBncGZsYWdzKTtcblxuICAgICAgICB2YXIgbWV0aG9kID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgbWV0aG9kIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgYWxlcnQoXCJtZXRob2Q6IFwiICsgbWV0aG9kKTtcblxuICAgICAgICByZWFkQnl0ZSgpO1xuICAgICAgICByZWFkQnl0ZSgpO1xuICAgICAgICByZWFkQnl0ZSgpO1xuICAgICAgICByZWFkQnl0ZSgpO1xuXG4gICAgICAgIHZhciBjcmMgPSByZWFkQnl0ZSgpO1xuICAgICAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCAxNik7XG4gICAgICAgIGNyYyB8PSAocmVhZEJ5dGUoKSA8PCAyNCk7XG5cbiAgICAgICAgdmFyIGNvbXBTaXplID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgY29tcFNpemUgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgICAgIGNvbXBTaXplIHw9IChyZWFkQnl0ZSgpIDw8IDE2KTtcbiAgICAgICAgY29tcFNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuXG4gICAgICAgIHZhciBzaXplID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgc2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICAgICAgc2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCAxNik7XG4gICAgICAgIHNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuXG4gICAgICAgIGlmIChkZWJ1ZylcbiAgICAgICAgICBhbGVydChcImxvY2FsIENSQzogXCIgKyBjcmMgKyBcIlxcbmxvY2FsIFNpemU6IFwiICsgc2l6ZSArIFwiXFxubG9jYWwgQ29tcFNpemU6IFwiICsgY29tcFNpemUpO1xuXG4gICAgICAgIHZhciBmaWxlbGVuID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgZmlsZWxlbiB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcblxuICAgICAgICB2YXIgZXh0cmFsZW4gPSByZWFkQnl0ZSgpO1xuICAgICAgICBleHRyYWxlbiB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcblxuICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgYWxlcnQoXCJmaWxlbGVuIFwiICsgZmlsZWxlbik7XG4gICAgICAgIGkgPSAwO1xuICAgICAgICBuYW1lQnVmID0gW107XG4gICAgICAgIHdoaWxlIChmaWxlbGVuLS0pIHtcbiAgICAgICAgICB2YXIgYyA9IHJlYWRCeXRlKCk7XG4gICAgICAgICAgaWYgKGMgPT0gXCIvXCIgfCBjID09IFwiOlwiKSB7XG4gICAgICAgICAgICBpID0gMDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGkgPCBOQU1FTUFYIC0gMSlcbiAgICAgICAgICAgIG5hbWVCdWZbaSsrXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlYnVnKVxuICAgICAgICAgIGFsZXJ0KFwibmFtZUJ1ZjogXCIgKyBuYW1lQnVmKTtcblxuICAgICAgICAvL25hbWVCdWZbaV0gPSBcIlxcMFwiO1xuICAgICAgICBpZiAoIWZpbGVvdXQpXG4gICAgICAgICAgZmlsZW91dCA9IG5hbWVCdWY7XG5cbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICB3aGlsZSAoaSA8IGV4dHJhbGVuKSB7XG4gICAgICAgICAgYyA9IHJlYWRCeXRlKCk7XG4gICAgICAgICAgaSsrO1xuICAgICAgICB9XG5cbiAgICAgICAgQ1JDID0gMHhmZmZmZmZmZjtcbiAgICAgICAgU0laRSA9IDA7XG5cbiAgICAgICAgaWYgKHNpemUgPSAwICYmIGZpbGVPdXQuY2hhckF0KGZpbGVvdXQubGVuZ3RoIC0gMSkgPT0gXCIvXCIpIHtcbiAgICAgICAgICAvL3NraXBkaXJcbiAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBhbGVydChcInNraXBkaXJcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGhvZCA9PSA4KSB7XG4gICAgICAgICAgRGVmbGF0ZUxvb3AoKTtcbiAgICAgICAgICBpZiAoZGVidWcpXG4gICAgICAgICAgICBhbGVydChvdXRwdXRBcnIuam9pbignJykpO1xuICAgICAgICAgIHVuemlwcGVkW2ZpbGVzXSA9IG5ldyBBcnJheSgyKTtcbiAgICAgICAgICB1bnppcHBlZFtmaWxlc11bMF0gPSBvdXRwdXRBcnIuam9pbignJyk7XG4gICAgICAgICAgdW56aXBwZWRbZmlsZXNdWzFdID0gbmFtZUJ1Zi5qb2luKCcnKTtcbiAgICAgICAgICBmaWxlcysrO1xuICAgICAgICAgIC8vcmV0dXJuIG91dHB1dEFyci5qb2luKCcnKTtcbiAgICAgICAgfVxuICAgICAgICBza2lwZGlyKCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIHNraXBkaXIoKSB7XG4gICAgdmFyIGNyYyxcbiAgICAgIHRtcCA9IFtdLFxuICAgICAgY29tcFNpemUsIHNpemUsIG9zLCBpLCBjO1xuXG4gICAgaWYgKChncGZsYWdzICYgOCkpIHtcbiAgICAgIHRtcFswXSA9IHJlYWRCeXRlKCk7XG4gICAgICB0bXBbMV0gPSByZWFkQnl0ZSgpO1xuICAgICAgdG1wWzJdID0gcmVhZEJ5dGUoKTtcbiAgICAgIHRtcFszXSA9IHJlYWRCeXRlKCk7XG5cbiAgICAgIGlmICh0bXBbMF0gPT0gcGFyc2VJbnQoXCI1MFwiLCAxNikgJiZcbiAgICAgICAgdG1wWzFdID09IHBhcnNlSW50KFwiNGJcIiwgMTYpICYmXG4gICAgICAgIHRtcFsyXSA9PSBwYXJzZUludChcIjA3XCIsIDE2KSAmJlxuICAgICAgICB0bXBbM10gPT0gcGFyc2VJbnQoXCIwOFwiLCAxNikpIHtcbiAgICAgICAgY3JjID0gcmVhZEJ5dGUoKTtcbiAgICAgICAgY3JjIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuICAgICAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgMTYpO1xuICAgICAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3JjID0gdG1wWzBdIHwgKHRtcFsxXSA8PCA4KSB8ICh0bXBbMl0gPDwgMTYpIHwgKHRtcFszXSA8PCAyNCk7XG4gICAgICB9XG5cbiAgICAgIGNvbXBTaXplID0gcmVhZEJ5dGUoKTtcbiAgICAgIGNvbXBTaXplIHw9IChyZWFkQnl0ZSgpIDw8IDgpO1xuICAgICAgY29tcFNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMTYpO1xuICAgICAgY29tcFNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuXG4gICAgICBzaXplID0gcmVhZEJ5dGUoKTtcbiAgICAgIHNpemUgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgICBzaXplIHw9IChyZWFkQnl0ZSgpIDw8IDE2KTtcbiAgICAgIHNpemUgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuXG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KFwiQ1JDOlwiKTtcbiAgICB9XG5cbiAgICBpZiAobW9kZVpJUClcbiAgICAgIG5leHRGaWxlKCk7XG5cbiAgICB0bXBbMF0gPSByZWFkQnl0ZSgpO1xuICAgIGlmICh0bXBbMF0gIT0gOCkge1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChcIlVua25vd24gY29tcHJlc3Npb24gbWV0aG9kIVwiKTtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGdwZmxhZ3MgPSByZWFkQnl0ZSgpO1xuICAgIGlmIChkZWJ1Zykge1xuICAgICAgaWYgKChncGZsYWdzICYgfihwYXJzZUludChcIjFmXCIsIDE2KSkpKVxuICAgICAgICBhbGVydChcIlVua25vd24gZmxhZ3Mgc2V0IVwiKTtcbiAgICB9XG5cbiAgICByZWFkQnl0ZSgpO1xuICAgIHJlYWRCeXRlKCk7XG4gICAgcmVhZEJ5dGUoKTtcbiAgICByZWFkQnl0ZSgpO1xuXG4gICAgcmVhZEJ5dGUoKTtcbiAgICBvcyA9IHJlYWRCeXRlKCk7XG5cbiAgICBpZiAoKGdwZmxhZ3MgJiA0KSkge1xuICAgICAgdG1wWzBdID0gcmVhZEJ5dGUoKTtcbiAgICAgIHRtcFsyXSA9IHJlYWRCeXRlKCk7XG4gICAgICBsZW4gPSB0bXBbMF0gKyAyNTYgKiB0bXBbMV07XG4gICAgICBpZiAoZGVidWcpXG4gICAgICAgIGFsZXJ0KFwiRXh0cmEgZmllbGQgc2l6ZTogXCIgKyBsZW4pO1xuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKVxuICAgICAgICByZWFkQnl0ZSgpO1xuICAgIH1cblxuICAgIGlmICgoZ3BmbGFncyAmIDgpKSB7XG4gICAgICBpID0gMDtcbiAgICAgIG5hbWVCdWYgPSBbXTtcbiAgICAgIHdoaWxlIChjID0gcmVhZEJ5dGUoKSkge1xuICAgICAgICBpZiAoYyA9PSBcIjdcIiB8fCBjID09IFwiOlwiKVxuICAgICAgICAgIGkgPSAwO1xuICAgICAgICBpZiAoaSA8IE5BTUVNQVggLSAxKVxuICAgICAgICAgIG5hbWVCdWZbaSsrXSA9IGM7XG4gICAgICB9XG4gICAgICAvL25hbWVCdWZbaV0gPSBcIlxcMFwiO1xuICAgICAgaWYgKGRlYnVnKVxuICAgICAgICBhbGVydChcIm9yaWdpbmFsIGZpbGUgbmFtZTogXCIgKyBuYW1lQnVmKTtcbiAgICB9XG5cbiAgICBpZiAoKGdwZmxhZ3MgJiAxNikpIHtcbiAgICAgIHdoaWxlIChjID0gcmVhZEJ5dGUoKSkge1xuICAgICAgICAvL0ZJTEUgQ09NTUVOVFxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICgoZ3BmbGFncyAmIDIpKSB7XG4gICAgICByZWFkQnl0ZSgpO1xuICAgICAgcmVhZEJ5dGUoKTtcbiAgICB9XG5cbiAgICBEZWZsYXRlTG9vcCgpO1xuXG4gICAgY3JjID0gcmVhZEJ5dGUoKTtcbiAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgOCk7XG4gICAgY3JjIHw9IChyZWFkQnl0ZSgpIDw8IDE2KTtcbiAgICBjcmMgfD0gKHJlYWRCeXRlKCkgPDwgMjQpO1xuXG4gICAgc2l6ZSA9IHJlYWRCeXRlKCk7XG4gICAgc2l6ZSB8PSAocmVhZEJ5dGUoKSA8PCA4KTtcbiAgICBzaXplIHw9IChyZWFkQnl0ZSgpIDw8IDE2KTtcbiAgICBzaXplIHw9IChyZWFkQnl0ZSgpIDw8IDI0KTtcblxuICAgIGlmIChtb2RlWklQKVxuICAgICAgbmV4dEZpbGUoKTtcblxuICB9O1xuXG59O1xuXG4vKipcbiAqICBCYXNlNjQgZW5jb2RpbmcgLyBkZWNvZGluZ1xuICogIHtAbGluayBodHRwOi8vd3d3LndlYnRvb2xraXQuaW5mby99XG4gKi9cbkpYRy5VdGlsLkJhc2U2NCA9IHtcblxuICAvLyBwcml2YXRlIHByb3BlcnR5XG4gIF9rZXlTdHI6IFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLz1cIixcblxuICAvLyBwdWJsaWMgbWV0aG9kIGZvciBlbmNvZGluZ1xuICBlbmNvZGU6IGZ1bmN0aW9uKGlucHV0KSB7XG4gICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgY2hyMSwgY2hyMiwgY2hyMywgZW5jMSwgZW5jMiwgZW5jMywgZW5jNCxcbiAgICAgIGkgPSAwO1xuXG4gICAgaW5wdXQgPSBKWEcuVXRpbC5CYXNlNjQuX3V0ZjhfZW5jb2RlKGlucHV0KTtcblxuICAgIHdoaWxlIChpIDwgaW5wdXQubGVuZ3RoKSB7XG5cbiAgICAgIGNocjEgPSBpbnB1dC5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICBjaHIyID0gaW5wdXQuY2hhckNvZGVBdChpKyspO1xuICAgICAgY2hyMyA9IGlucHV0LmNoYXJDb2RlQXQoaSsrKTtcblxuICAgICAgZW5jMSA9IGNocjEgPj4gMjtcbiAgICAgIGVuYzIgPSAoKGNocjEgJiAzKSA8PCA0KSB8IChjaHIyID4+IDQpO1xuICAgICAgZW5jMyA9ICgoY2hyMiAmIDE1KSA8PCAyKSB8IChjaHIzID4+IDYpO1xuICAgICAgZW5jNCA9IGNocjMgJiA2MztcblxuICAgICAgaWYgKGlzTmFOKGNocjIpKSB7XG4gICAgICAgIGVuYzMgPSBlbmM0ID0gNjQ7XG4gICAgICB9IGVsc2UgaWYgKGlzTmFOKGNocjMpKSB7XG4gICAgICAgIGVuYzQgPSA2NDtcbiAgICAgIH1cblxuICAgICAgb3V0cHV0LnB1c2goW3RoaXMuX2tleVN0ci5jaGFyQXQoZW5jMSksXG4gICAgICAgICAgdGhpcy5fa2V5U3RyLmNoYXJBdChlbmMyKSxcbiAgICAgICAgICB0aGlzLl9rZXlTdHIuY2hhckF0KGVuYzMpLFxuICAgICAgICAgIHRoaXMuX2tleVN0ci5jaGFyQXQoZW5jNClcbiAgICAgIF0uam9pbignJykpO1xuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXQuam9pbignJyk7XG4gIH0sXG5cbiAgLy8gcHVibGljIG1ldGhvZCBmb3IgZGVjb2RpbmdcbiAgZGVjb2RlOiBmdW5jdGlvbihpbnB1dCwgdXRmOCkge1xuICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgIGNocjEsIGNocjIsIGNocjMsXG4gICAgICBlbmMxLCBlbmMyLCBlbmMzLCBlbmM0LFxuICAgICAgaSA9IDA7XG5cbiAgICBpbnB1dCA9IGlucHV0LnJlcGxhY2UoL1teQS1aYS16MC05XFwrXFwvXFw9XS9nLCBcIlwiKTtcblxuICAgIHdoaWxlIChpIDwgaW5wdXQubGVuZ3RoKSB7XG5cbiAgICAgIGVuYzEgPSB0aGlzLl9rZXlTdHIuaW5kZXhPZihpbnB1dC5jaGFyQXQoaSsrKSk7XG4gICAgICBlbmMyID0gdGhpcy5fa2V5U3RyLmluZGV4T2YoaW5wdXQuY2hhckF0KGkrKykpO1xuICAgICAgZW5jMyA9IHRoaXMuX2tleVN0ci5pbmRleE9mKGlucHV0LmNoYXJBdChpKyspKTtcbiAgICAgIGVuYzQgPSB0aGlzLl9rZXlTdHIuaW5kZXhPZihpbnB1dC5jaGFyQXQoaSsrKSk7XG5cbiAgICAgIGNocjEgPSAoZW5jMSA8PCAyKSB8IChlbmMyID4+IDQpO1xuICAgICAgY2hyMiA9ICgoZW5jMiAmIDE1KSA8PCA0KSB8IChlbmMzID4+IDIpO1xuICAgICAgY2hyMyA9ICgoZW5jMyAmIDMpIDw8IDYpIHwgZW5jNDtcblxuICAgICAgb3V0cHV0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaHIxKSk7XG5cbiAgICAgIGlmIChlbmMzICE9IDY0KSB7XG4gICAgICAgIG91dHB1dC5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2hyMikpO1xuICAgICAgfVxuICAgICAgaWYgKGVuYzQgIT0gNjQpIHtcbiAgICAgICAgb3V0cHV0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaHIzKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgb3V0cHV0ID0gb3V0cHV0LmpvaW4oJycpO1xuXG4gICAgaWYgKHV0ZjgpIHtcbiAgICAgIG91dHB1dCA9IEpYRy5VdGlsLkJhc2U2NC5fdXRmOF9kZWNvZGUob3V0cHV0KTtcbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dDtcblxuICB9LFxuXG4gIC8vIHByaXZhdGUgbWV0aG9kIGZvciBVVEYtOCBlbmNvZGluZ1xuICBfdXRmOF9lbmNvZGU6IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHN0cmluZyA9IHN0cmluZy5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIik7XG4gICAgdmFyIHV0ZnRleHQgPSBcIlwiO1xuXG4gICAgZm9yICh2YXIgbiA9IDA7IG4gPCBzdHJpbmcubGVuZ3RoOyBuKyspIHtcblxuICAgICAgdmFyIGMgPSBzdHJpbmcuY2hhckNvZGVBdChuKTtcblxuICAgICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgICAgdXRmdGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGMpO1xuICAgICAgfSBlbHNlIGlmICgoYyA+IDEyNykgJiYgKGMgPCAyMDQ4KSkge1xuICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgPj4gNikgfCAxOTIpO1xuICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgJiA2MykgfCAxMjgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmdGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChjID4+IDEyKSB8IDIyNCk7XG4gICAgICAgIHV0ZnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMgPj4gNikgJiA2MykgfCAxMjgpO1xuICAgICAgICB1dGZ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgJiA2MykgfCAxMjgpO1xuICAgICAgfVxuXG4gICAgfVxuXG4gICAgcmV0dXJuIHV0ZnRleHQ7XG4gIH0sXG5cbiAgLy8gcHJpdmF0ZSBtZXRob2QgZm9yIFVURi04IGRlY29kaW5nXG4gIF91dGY4X2RlY29kZTogZnVuY3Rpb24odXRmdGV4dCkge1xuICAgIHZhciBzdHJpbmcgPSBbXSxcbiAgICAgIGkgPSAwLFxuICAgICAgYyA9IDAsXG4gICAgICBjMiA9IDAsXG4gICAgICBjMyA9IDA7XG5cbiAgICB3aGlsZSAoaSA8IHV0ZnRleHQubGVuZ3RoKSB7XG4gICAgICBjID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgICAgc3RyaW5nLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjKSk7XG4gICAgICAgIGkrKztcbiAgICAgIH0gZWxzZSBpZiAoKGMgPiAxOTEpICYmIChjIDwgMjI0KSkge1xuICAgICAgICBjMiA9IHV0ZnRleHQuY2hhckNvZGVBdChpICsgMSk7XG4gICAgICAgIHN0cmluZy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoKChjICYgMzEpIDw8IDYpIHwgKGMyICYgNjMpKSk7XG4gICAgICAgIGkgKz0gMjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGMyID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkgKyAxKTtcbiAgICAgICAgYzMgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSArIDIpO1xuICAgICAgICBzdHJpbmcucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKCgoYyAmIDE1KSA8PCAxMikgfCAoKGMyICYgNjMpIDw8IDYpIHwgKGMzICYgNjMpKSk7XG4gICAgICAgIGkgKz0gMztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0cmluZy5qb2luKCcnKTtcbiAgfSxcblxuICBfZGVzdHJpcDogZnVuY3Rpb24oc3RyaXBwZWQsIHdyYXApIHtcbiAgICB2YXIgbGluZXMgPSBbXSxcbiAgICAgIGxpbmVubywgaSxcbiAgICAgIGRlc3RyaXBwZWQgPSBbXTtcblxuICAgIGlmICh3cmFwID09IG51bGwpXG4gICAgICB3cmFwID0gNzY7XG5cbiAgICBzdHJpcHBlZC5yZXBsYWNlKC8gL2csIFwiXCIpO1xuICAgIGxpbmVubyA9IHN0cmlwcGVkLmxlbmd0aCAvIHdyYXA7XG4gICAgZm9yIChpID0gMDsgaSA8IGxpbmVubzsgaSsrKVxuICAgICAgbGluZXNbaV0gPSBzdHJpcHBlZC5zdWJzdHIoaSAqIHdyYXAsIHdyYXApO1xuICAgIGlmIChsaW5lbm8gIT0gc3RyaXBwZWQubGVuZ3RoIC8gd3JhcClcbiAgICAgIGxpbmVzW2xpbmVzLmxlbmd0aF0gPSBzdHJpcHBlZC5zdWJzdHIobGluZW5vICogd3JhcCwgc3RyaXBwZWQubGVuZ3RoIC0gKGxpbmVubyAqIHdyYXApKTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKylcbiAgICAgIGRlc3RyaXBwZWQucHVzaChsaW5lc1tpXSk7XG4gICAgcmV0dXJuIGRlc3RyaXBwZWQuam9pbignXFxuJyk7XG4gIH0sXG5cbiAgZGVjb2RlQXNBcnJheTogZnVuY3Rpb24oaW5wdXQpIHtcbiAgICB2YXIgZGVjID0gdGhpcy5kZWNvZGUoaW5wdXQpLFxuICAgICAgYXIgPSBbXSxcbiAgICAgIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IGRlYy5sZW5ndGg7IGkrKykge1xuICAgICAgYXJbaV0gPSBkZWMuY2hhckNvZGVBdChpKTtcbiAgICB9XG4gICAgcmV0dXJuIGFyO1xuICB9LFxuXG4gIGRlY29kZUdFT05FeFQ6IGZ1bmN0aW9uKGlucHV0KSB7XG4gICAgcmV0dXJuIGRlY29kZUFzQXJyYXkoZGVzdHJpcChpbnB1dCksIGZhbHNlKTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5KWEcuVXRpbC5hc2NpaUNoYXJDb2RlQXQgPSBmdW5jdGlvbihzdHIsIGkpIHtcbiAgdmFyIGMgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgaWYgKGMgPiAyNTUpIHtcbiAgICBzd2l0Y2ggKGMpIHtcbiAgICAgIGNhc2UgODM2NDpcbiAgICAgICAgYyA9IDEyODtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMTg6XG4gICAgICAgIGMgPSAxMzA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA0MDI6XG4gICAgICAgIGMgPSAxMzE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjIyOlxuICAgICAgICBjID0gMTMyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIzMDpcbiAgICAgICAgYyA9IDEzMztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMjQ6XG4gICAgICAgIGMgPSAxMzQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjI1OlxuICAgICAgICBjID0gMTM1O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNzEwOlxuICAgICAgICBjID0gMTM2O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODI0MDpcbiAgICAgICAgYyA9IDEzNztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM1MjpcbiAgICAgICAgYyA9IDEzODtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyNDk6XG4gICAgICAgIGMgPSAxMzk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzMzg6XG4gICAgICAgIGMgPSAxNDA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzODE6XG4gICAgICAgIGMgPSAxNDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjE2OlxuICAgICAgICBjID0gMTQ1O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIxNzpcbiAgICAgICAgYyA9IDE0NjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMjA6XG4gICAgICAgIGMgPSAxNDc7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjIxOlxuICAgICAgICBjID0gMTQ4O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODIyNjpcbiAgICAgICAgYyA9IDE0OTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyMTE6XG4gICAgICAgIGMgPSAxNTA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MjEyOlxuICAgICAgICBjID0gMTUxO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNzMyOlxuICAgICAgICBjID0gMTUyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgODQ4MjpcbiAgICAgICAgYyA9IDE1MztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM1MzpcbiAgICAgICAgYyA9IDE1NDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDgyNTA6XG4gICAgICAgIGMgPSAxNTU7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzMzk6XG4gICAgICAgIGMgPSAxNTY7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzODI6XG4gICAgICAgIGMgPSAxNTg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzNzY6XG4gICAgICAgIGMgPSAxNTk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBjO1xufTtcblxuLyoqXG4gKiBEZWNvZGluZyBzdHJpbmcgaW50byB1dGYtOFxuICogQHBhcmFtIHtTdHJpbmd9IHN0cmluZyB0byBkZWNvZGVcbiAqIEByZXR1cm4ge1N0cmluZ30gdXRmOCBkZWNvZGVkIHN0cmluZ1xuICovXG5KWEcuVXRpbC51dGY4RGVjb2RlID0gZnVuY3Rpb24odXRmdGV4dCkge1xuICB2YXIgc3RyaW5nID0gW107XG4gIHZhciBpID0gMDtcbiAgdmFyIGMgPSAwLFxuICAgIGMxID0gMCxcbiAgICBjMiA9IDAsXG4gICAgYzM7XG4gIGlmICghSlhHLmV4aXN0cyh1dGZ0ZXh0KSkgcmV0dXJuICcnO1xuXG4gIHdoaWxlIChpIDwgdXRmdGV4dC5sZW5ndGgpIHtcbiAgICBjID0gdXRmdGV4dC5jaGFyQ29kZUF0KGkpO1xuXG4gICAgaWYgKGMgPCAxMjgpIHtcbiAgICAgIHN0cmluZy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYykpO1xuICAgICAgaSsrO1xuICAgIH0gZWxzZSBpZiAoKGMgPiAxOTEpICYmIChjIDwgMjI0KSkge1xuICAgICAgYzIgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgc3RyaW5nLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMgJiAzMSkgPDwgNikgfCAoYzIgJiA2MykpKTtcbiAgICAgIGkgKz0gMjtcbiAgICB9IGVsc2Uge1xuICAgICAgYzIgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgYzMgPSB1dGZ0ZXh0LmNoYXJDb2RlQXQoaSArIDIpO1xuICAgICAgc3RyaW5nLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMgJiAxNSkgPDwgMTIpIHwgKChjMiAmIDYzKSA8PCA2KSB8IChjMyAmIDYzKSkpO1xuICAgICAgaSArPSAzO1xuICAgIH1cbiAgfTtcbiAgcmV0dXJuIHN0cmluZy5qb2luKCcnKTtcbn07XG5cbi8qKlxuICogR2VuZXJhdGUgYSByYW5kb20gdXVpZC5cbiAqIGh0dHA6Ly93d3cuYnJvb2ZhLmNvbVxuICogbWFpbHRvOnJvYmVydEBicm9vZmEuY29tXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwIFJvYmVydCBLaWVmZmVyXG4gKiBEdWFsIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgYW5kIEdQTCBsaWNlbnNlcy5cbiAqXG4gKiBFWEFNUExFUzpcbiAqICAgPj4+IE1hdGgudXVpZCgpXG4gKiAgIFwiOTIzMjlEMzktNkY1Qy00NTIwLUFCRkMtQUFCNjQ1NDRFMTcyXCJcbiAqL1xuSlhHLlV0aWwuZ2VuVVVJRCA9IGZ1bmN0aW9uKCkge1xuICAvLyBQcml2YXRlIGFycmF5IG9mIGNoYXJzIHRvIHVzZVxuICB2YXIgY2hhcnMgPSAnMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXonLnNwbGl0KCcnKSxcbiAgICB1dWlkID0gbmV3IEFycmF5KDM2KSxcbiAgICBybmQgPSAwLFxuICAgIHI7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAzNjsgaSsrKSB7XG4gICAgaWYgKGkgPT0gOCB8fCBpID09IDEzIHx8IGkgPT0gMTggfHwgaSA9PSAyMykge1xuICAgICAgdXVpZFtpXSA9ICctJztcbiAgICB9IGVsc2UgaWYgKGkgPT0gMTQpIHtcbiAgICAgIHV1aWRbaV0gPSAnNCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChybmQgPD0gMHgwMikgcm5kID0gMHgyMDAwMDAwICsgKE1hdGgucmFuZG9tKCkgKiAweDEwMDAwMDApIHwgMDtcbiAgICAgIHIgPSBybmQgJiAweGY7XG4gICAgICBybmQgPSBybmQgPj4gNDtcbiAgICAgIHV1aWRbaV0gPSBjaGFyc1soaSA9PSAxOSkgPyAociAmIDB4MykgfCAweDggOiByXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdXVpZC5qb2luKCcnKTtcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBKWEc7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy9cbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy9cbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpO1xuXG4vKipcbiAqXG4gKiBUaGlzIG9iamVjdCBjb250YWlucyBjb25maWd1cmF0aW9uIHZhbHVlcyBhbmQgaW1wbGVtZW50c1xuICogc3RvcmluZyBhbmQgcmV0cmlldmluZyBjb25maWd1cmF0aW9uIHRoZW0gZnJvbSBIVE1MNSBsb2NhbCBzdG9yYWdlLlxuICpcbiAqIFRoaXMgb2JqZWN0IGNhbiBiZSBhY2Nlc3NlZCBhZnRlciBjYWxsaW5nIG9wZW5wZ3AuaW5pdCgpXG4gKiB1c2luZyBvcGVucGdwLmNvbmZpZ1xuICogU3RvcmVkIGNvbmZpZyBwYXJhbWV0ZXJzIGNhbiBiZSBhY2Nlc3NlZCB1c2luZ1xuICogb3BlbnBncC5jb25maWcuY29uZmlnXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIEdQRzRCcm93c2VycyBjb25maWcgb2JqZWN0XG4gKi9cbnZhciBjb25maWcgPSBmdW5jdGlvbigpIHtcbiAgLyoqXG4gICAqIEBwcm9wZXJ0eSB7SW50ZWdlcn0gcHJlZmVyX2hhc2hfYWxnb3JpdGhtXG4gICAqIEBwcm9wZXJ0eSB7SW50ZWdlcn0gZW5jcnlwdGlvbl9jaXBoZXJcbiAgICogQHByb3BlcnR5IHtJbnRlZ2VyfSBjb21wcmVzc2lvblxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IHNob3dfdmVyc2lvblxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IHNob3dfY29tbWVudFxuICAgKiBAcHJvcGVydHkge0Jvb2xlYW59IGludGVncml0eV9wcm90ZWN0XG4gICAqIEBwcm9wZXJ0eSB7U3RyaW5nfSBrZXlzZXJ2ZXJcbiAgICovXG4gIHRoaXMucHJlZmVyX2hhc2hfYWxnb3JpdGhtID0gZW51bXMuaGFzaC5zaGEyNTY7XG4gIHRoaXMuZW5jcnlwdGlvbl9jaXBoZXIgPSBlbnVtcy5zeW1tZXRyaWMuYWVzMjU2O1xuICB0aGlzLmNvbXByZXNzaW9uID0gZW51bXMuY29tcHJlc3Npb24uemlwO1xuICB0aGlzLnNob3dfdmVyc2lvbiA9IHRydWU7XG4gIHRoaXMuc2hvd19jb21tZW50ID0gdHJ1ZTtcbiAgdGhpcy5pbnRlZ3JpdHlfcHJvdGVjdCA9IHRydWU7XG4gIHRoaXMua2V5c2VydmVyID0gXCJrZXlzZXJ2ZXIubGludXguaXRcIjsgLy8gXCJwZ3AubWl0LmVkdToxMTM3MVwiXG5cbiAgdGhpcy52ZXJzaW9uc3RyaW5nID0gXCJPcGVuUEdQLmpzIFZFUlNJT05cIjtcbiAgdGhpcy5jb21tZW50c3RyaW5nID0gXCJodHRwOi8vb3BlbnBncGpzLm9yZ1wiO1xuXG4gIC8qKlxuICAgKiBJZiBlbmFibGVkLCBkZWJ1ZyBtZXNzYWdlcyB3aWxsIGJlIHByaW50ZWRcbiAgICovXG4gIHRoaXMuZGVidWcgPSBmYWxzZTtcblxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgY29uZmlnKCk7XG4iLCIvLyBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkggXG5cbi8vIG1vZGlmaWVkIHZlcnNpb24gb2YgaHR0cDovL3d3dy5oYW5ld2luLm5ldC9lbmNyeXB0L1BHZGVjb2RlLmpzOlxuXG4vKiBPcGVuUEdQIGVuY3J5cHRpb24gdXNpbmcgUlNBL0FFU1xuICogQ29weXJpZ2h0IDIwMDUtMjAwNiBIZXJiZXJ0IEhhbmV3aW5rZWwsIHd3dy5oYW5lV0lOLmRlXG4gKiB2ZXJzaW9uIDIuMCwgY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxuXG4gKiBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkIGFzLWlzLCB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4gIFxuICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgZGlzdHJpYnV0ZSBvciBzZWxsIHRoaXMgc29mdHdhcmUsIHdpdGggb3JcbiAqIHdpdGhvdXQgZmVlLCBmb3IgYW55IHB1cnBvc2UgYW5kIGJ5IGFueSBpbmRpdmlkdWFsIG9yIG9yZ2FuaXphdGlvbiwgaXMgaGVyZWJ5XG4gKiBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBhcmFncmFwaCBhcHBlYXIgXG4gKiBpbiBhbGwgY29waWVzLiBEaXN0cmlidXRpb24gYXMgYSBwYXJ0IG9mIGFuIGFwcGxpY2F0aW9uIG9yIGJpbmFyeSBtdXN0XG4gKiBpbmNsdWRlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlclxuICogbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGFwcGxpY2F0aW9uIG9yIGRpc3RyaWJ1dGlvbi5cbiAqL1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgY2lwaGVyID0gcmVxdWlyZSgnLi9jaXBoZXInKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgLyoqXG4gICAqIEFuIGFycmF5IG9mIGJ5dGVzLCB0aGF0IGlzIGludGVnZXJzIHdpdGggdmFsdWVzIGZyb20gMCB0byAyNTVcbiAgICogQHR5cGVkZWYgeyhBcnJheXxVaW50OEFycmF5KX0gb3BlbnBncF9ieXRlX2FycmF5XG4gICAqL1xuXG4gIC8qKlxuICAgKiBCbG9jayBjaXBoZXIgZnVuY3Rpb25cbiAgICogQGNhbGxiYWNrIG9wZW5wZ3BfY2lwaGVyX2Jsb2NrX2ZuXG4gICAqIEBwYXJhbSB7b3BlbnBncF9ieXRlX2FycmF5fSBibG9jayBBIGJsb2NrIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyBvblxuICAgKiBAcGFyYW0ge29wZW5wZ3BfYnl0ZV9hcnJheX0ga2V5IHRvIHVzZSBpbiBlbmNyeXB0aW9uL2RlY3J5cHRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9ieXRlX2FycmF5fSBFbmNyeXB0ZWQvZGVjcnlwdGVkIGJsb2NrXG4gICAqL1xuXG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLyoqXG4gICAqIFRoaXMgZnVuY3Rpb24gZW5jcnlwdHMgYSBnaXZlbiB3aXRoIHRoZSBzcGVjaWZpZWQgcHJlZml4cmFuZG9tIFxuICAgKiB1c2luZyB0aGUgc3BlY2lmaWVkIGJsb2NrY2lwaGVyIHRvIGVuY3J5cHQgYSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcmVmaXhyYW5kb20gcmFuZG9tIGJ5dGVzIG9mIGJsb2NrX3NpemUgbGVuZ3RoIHByb3ZpZGVkIFxuICAgKiAgYXMgYSBzdHJpbmcgdG8gYmUgdXNlZCBpbiBwcmVmaXhpbmcgdGhlIGRhdGFcbiAgICogQHBhcmFtIHtvcGVucGdwX2NpcGhlcl9ibG9ja19mbn0gYmxvY2tjaXBoZXJmbiB0aGUgYWxnb3JpdGhtIGVuY3J5cHQgZnVuY3Rpb24gdG8gZW5jcnlwdFxuICAgKiAgZGF0YSBpbiBvbmUgYmxvY2tfc2l6ZSBlbmNyeXB0aW9uLiBcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBibG9ja19zaXplIHRoZSBibG9jayBzaXplIGluIGJ5dGVzIG9mIHRoZSBhbGdvcml0aG0gdXNlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcGxhaW50ZXh0IGRhdGEgdG8gYmUgZW5jcnlwdGVkIHByb3ZpZGVkIGFzIGEgc3RyaW5nXG4gICAqIEBwYXJhbSB7b3BlbnBncF9ieXRlX2FycmF5fSBrZXkga2V5IHRvIGJlIHVzZWQgdG8gZW5jcnlwdCB0aGUgZGF0YS4gVGhpcyB3aWxsIGJlIHBhc3NlZCB0byB0aGUgXG4gICAqICBibG9ja2NpcGhlcmZuXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gcmVzeW5jIGEgYm9vbGVhbiB2YWx1ZSBzcGVjaWZ5aW5nIGlmIGEgcmVzeW5jIG9mIHRoZSBcbiAgICogIElWIHNob3VsZCBiZSB1c2VkIG9yIG5vdC4gVGhlIGVuY3J5cHRlZGRhdGFwYWNrZXQgdXNlcyB0aGUgXG4gICAqICBcIm9sZFwiIHN0eWxlIHdpdGggYSByZXN5bmMuIEVuY3J5cHRpb24gd2l0aGluIGFuIFxuICAgKiAgZW5jcnlwdGVkaW50ZWdyaXR5cHJvdGVjdGVkZGF0YSBwYWNrZXQgaXMgbm90IHJlc3luY2luZyB0aGUgSVYuXG4gICAqIEByZXR1cm4ge1N0cmluZ30gYSBzdHJpbmcgd2l0aCB0aGUgZW5jcnlwdGVkIGRhdGFcbiAgICovXG4gIGVuY3J5cHQ6IGZ1bmN0aW9uKHByZWZpeHJhbmRvbSwgY2lwaGVyZm4sIHBsYWludGV4dCwga2V5LCByZXN5bmMpIHtcbiAgICBjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG4gICAgdmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cbiAgICB2YXIgRlIgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG4gICAgdmFyIEZSRSA9IG5ldyBBcnJheShibG9ja19zaXplKTtcblxuICAgIHByZWZpeHJhbmRvbSA9IHByZWZpeHJhbmRvbSArIHByZWZpeHJhbmRvbS5jaGFyQXQoYmxvY2tfc2l6ZSAtIDIpICsgcHJlZml4cmFuZG9tLmNoYXJBdChibG9ja19zaXplIC0gMSk7XG4gICAgdXRpbC5wcmludF9kZWJ1ZyhcInByZWZpeHJhbmRvbTpcIiArIHV0aWwuaGV4c3RyZHVtcChwcmVmaXhyYW5kb20pKTtcbiAgICB2YXIgY2lwaGVydGV4dCA9IFwiXCI7XG4gICAgLy8gMS4gIFRoZSBmZWVkYmFjayByZWdpc3RlciAoRlIpIGlzIHNldCB0byB0aGUgSVYsIHdoaWNoIGlzIGFsbCB6ZXJvcy5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgRlJbaV0gPSAwO1xuXG4gICAgLy8gMi4gIEZSIGlzIGVuY3J5cHRlZCB0byBwcm9kdWNlIEZSRSAoRlIgRW5jcnlwdGVkKS4gIFRoaXMgaXMgdGhlXG4gICAgLy8gICAgIGVuY3J5cHRpb24gb2YgYW4gYWxsLXplcm8gdmFsdWUuXG4gICAgRlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG4gICAgLy8gMy4gIEZSRSBpcyB4b3JlZCB3aXRoIHRoZSBmaXJzdCBCUyBvY3RldHMgb2YgcmFuZG9tIGRhdGEgcHJlZml4ZWQgdG9cbiAgICAvLyAgICAgdGhlIHBsYWludGV4dCB0byBwcm9kdWNlIENbMV0gdGhyb3VnaCBDW0JTXSwgdGhlIGZpcnN0IEJTIG9jdGV0c1xuICAgIC8vICAgICBvZiBjaXBoZXJ0ZXh0LlxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBjaXBoZXJ0ZXh0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFW2ldIF4gcHJlZml4cmFuZG9tLmNoYXJDb2RlQXQoaSkpO1xuXG4gICAgLy8gNC4gIEZSIGlzIGxvYWRlZCB3aXRoIENbMV0gdGhyb3VnaCBDW0JTXS5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgRlJbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSk7XG5cbiAgICAvLyA1LiAgRlIgaXMgZW5jcnlwdGVkIHRvIHByb2R1Y2UgRlJFLCB0aGUgZW5jcnlwdGlvbiBvZiB0aGUgZmlyc3QgQlNcbiAgICAvLyBcdCAgIG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LlxuICAgIEZSRSA9IGNpcGhlcmZuLmVuY3J5cHQoRlIpO1xuXG4gICAgLy8gNi4gIFRoZSBsZWZ0IHR3byBvY3RldHMgb2YgRlJFIGdldCB4b3JlZCB3aXRoIHRoZSBuZXh0IHR3byBvY3RldHMgb2ZcbiAgICAvLyAgICAgZGF0YSB0aGF0IHdlcmUgcHJlZml4ZWQgdG8gdGhlIHBsYWludGV4dC4gIFRoaXMgcHJvZHVjZXMgQ1tCUysxXVxuICAgIC8vICAgICBhbmQgQ1tCUysyXSwgdGhlIG5leHQgdHdvIG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LlxuICAgIGNpcGhlcnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbMF0gXiBwcmVmaXhyYW5kb20uY2hhckNvZGVBdChibG9ja19zaXplKSk7XG4gICAgY2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVsxXSBeIHByZWZpeHJhbmRvbS5jaGFyQ29kZUF0KGJsb2NrX3NpemUgKyAxKSk7XG5cbiAgICBpZiAocmVzeW5jKSB7XG4gICAgICAvLyA3LiAgKFRoZSByZXN5bmMgc3RlcCkgRlIgaXMgbG9hZGVkIHdpdGggQzMtQzEwLlxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkgKyAyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIEZSW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkpO1xuICAgIH1cbiAgICAvLyA4LiAgRlIgaXMgZW5jcnlwdGVkIHRvIHByb2R1Y2UgRlJFLlxuICAgIEZSRSA9IGNpcGhlcmZuLmVuY3J5cHQoRlIsIGtleSk7XG5cbiAgICBpZiAocmVzeW5jKSB7XG4gICAgICAvLyA5LiAgRlJFIGlzIHhvcmVkIHdpdGggdGhlIGZpcnN0IDggb2N0ZXRzIG9mIHRoZSBnaXZlbiBwbGFpbnRleHQsIG5vd1xuICAgICAgLy9cdCAgIHRoYXQgd2UgaGF2ZSBmaW5pc2hlZCBlbmNyeXB0aW5nIHRoZSAxMCBvY3RldHMgb2YgcHJlZml4ZWQgZGF0YS5cbiAgICAgIC8vIFx0ICAgVGhpcyBwcm9kdWNlcyBDMTEtQzE4LCB0aGUgbmV4dCA4IG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LlxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspXG4gICAgICAgIGNpcGhlcnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwbGFpbnRleHQuY2hhckNvZGVBdChpKSk7XG4gICAgICBmb3IgKG4gPSBibG9ja19zaXplICsgMjsgbiA8IHBsYWludGV4dC5sZW5ndGg7IG4gKz0gYmxvY2tfc2l6ZSkge1xuICAgICAgICAvLyAxMC4gRlIgaXMgbG9hZGVkIHdpdGggQzExLUMxOFxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgRlJbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQobiArIGkpO1xuXG4gICAgICAgIC8vIDExLiBGUiBpcyBlbmNyeXB0ZWQgdG8gcHJvZHVjZSBGUkUuXG4gICAgICAgIEZSRSA9IGNpcGhlcmZuLmVuY3J5cHQoRlIpO1xuXG4gICAgICAgIC8vIDEyLiBGUkUgaXMgeG9yZWQgd2l0aCB0aGUgbmV4dCA4IG9jdGV0cyBvZiBwbGFpbnRleHQsIHRvIHByb2R1Y2UgdGhlXG4gICAgICAgIC8vIG5leHQgOCBvY3RldHMgb2YgY2lwaGVydGV4dC4gIFRoZXNlIGFyZSBsb2FkZWQgaW50byBGUiBhbmQgdGhlXG4gICAgICAgIC8vIHByb2Nlc3MgaXMgcmVwZWF0ZWQgdW50aWwgdGhlIHBsYWludGV4dCBpcyB1c2VkIHVwLlxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgY2lwaGVydGV4dCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKEZSRVtpXSBeIHBsYWludGV4dC5jaGFyQ29kZUF0KChuIC0gMikgK1xuICAgICAgICAgICAgaSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBwbGFpbnRleHQgPSBcIiAgXCIgKyBwbGFpbnRleHQ7XG4gICAgICAvLyA5LiAgRlJFIGlzIHhvcmVkIHdpdGggdGhlIGZpcnN0IDggb2N0ZXRzIG9mIHRoZSBnaXZlbiBwbGFpbnRleHQsIG5vd1xuICAgICAgLy9cdCAgIHRoYXQgd2UgaGF2ZSBmaW5pc2hlZCBlbmNyeXB0aW5nIHRoZSAxMCBvY3RldHMgb2YgcHJlZml4ZWQgZGF0YS5cbiAgICAgIC8vIFx0ICAgVGhpcyBwcm9kdWNlcyBDMTEtQzE4LCB0aGUgbmV4dCA4IG9jdGV0cyBvZiBjaXBoZXJ0ZXh0LlxuICAgICAgZm9yICh2YXIgaSA9IDI7IGkgPCBibG9ja19zaXplOyBpKyspIGNpcGhlcnRleHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwbGFpbnRleHQuY2hhckNvZGVBdChpKSk7XG4gICAgICB2YXIgdGVtcENpcGhlcnRleHQgPSBjaXBoZXJ0ZXh0LnN1YnN0cmluZygwLCAyICogYmxvY2tfc2l6ZSkuc3BsaXQoJycpO1xuICAgICAgdmFyIHRlbXBDaXBoZXJ0ZXh0U3RyaW5nID0gY2lwaGVydGV4dC5zdWJzdHJpbmcoYmxvY2tfc2l6ZSk7XG4gICAgICBmb3IgKG4gPSBibG9ja19zaXplOyBuIDwgcGxhaW50ZXh0Lmxlbmd0aDsgbiArPSBibG9ja19zaXplKSB7XG4gICAgICAgIC8vIDEwLiBGUiBpcyBsb2FkZWQgd2l0aCBDMTEtQzE4XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBGUltpXSA9IHRlbXBDaXBoZXJ0ZXh0U3RyaW5nLmNoYXJDb2RlQXQoaSk7XG4gICAgICAgIHRlbXBDaXBoZXJ0ZXh0U3RyaW5nID0gJyc7XG5cbiAgICAgICAgLy8gMTEuIEZSIGlzIGVuY3J5cHRlZCB0byBwcm9kdWNlIEZSRS5cbiAgICAgICAgRlJFID0gY2lwaGVyZm4uZW5jcnlwdChGUik7XG5cbiAgICAgICAgLy8gMTIuIEZSRSBpcyB4b3JlZCB3aXRoIHRoZSBuZXh0IDggb2N0ZXRzIG9mIHBsYWludGV4dCwgdG8gcHJvZHVjZSB0aGVcbiAgICAgICAgLy8gICAgIG5leHQgOCBvY3RldHMgb2YgY2lwaGVydGV4dC4gIFRoZXNlIGFyZSBsb2FkZWQgaW50byBGUiBhbmQgdGhlXG4gICAgICAgIC8vICAgICBwcm9jZXNzIGlzIHJlcGVhdGVkIHVudGlsIHRoZSBwbGFpbnRleHQgaXMgdXNlZCB1cC5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIHtcbiAgICAgICAgICB0ZW1wQ2lwaGVydGV4dC5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoRlJFW2ldIF4gcGxhaW50ZXh0LmNoYXJDb2RlQXQobiArIGkpKSk7XG4gICAgICAgICAgdGVtcENpcGhlcnRleHRTdHJpbmcgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShGUkVbaV0gXiBwbGFpbnRleHQuY2hhckNvZGVBdChuICsgaSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBjaXBoZXJ0ZXh0ID0gdGVtcENpcGhlcnRleHQuam9pbignJyk7XG5cbiAgICB9XG5cbiAgICBjaXBoZXJ0ZXh0ID0gY2lwaGVydGV4dC5zdWJzdHJpbmcoMCwgcGxhaW50ZXh0Lmxlbmd0aCArIDIgKyBibG9ja19zaXplKTtcblxuICAgIHJldHVybiBjaXBoZXJ0ZXh0O1xuICB9LFxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyB0aGUgcHJlZml4ZWQgZGF0YSBmb3IgdGhlIE1vZGlmaWNhdGlvbiBEZXRlY3Rpb24gQ29kZSAoTURDKSBjb21wdXRhdGlvblxuICAgKiBAcGFyYW0ge29wZW5wZ3BfYmxvY2tfY2lwaGVyX2ZufSBjaXBoZXJmbi5lbmNyeXB0IENpcGhlciBmdW5jdGlvbiB0byB1c2VcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBibG9ja19zaXplIEJsb2Nrc2l6ZSBvZiB0aGUgYWxnb3JpdGhtXG4gICAqIEBwYXJhbSB7b3BlbnBncF9ieXRlX2FycmF5fSBrZXkgVGhlIGtleSBmb3IgZW5jcnlwdGlvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gY2lwaGVydGV4dCBUaGUgZW5jcnlwdGVkIGRhdGFcbiAgICogQHJldHVybiB7U3RyaW5nfSBwbGFpbnRleHQgRGF0YSBvZiBEKGNpcGhlcnRleHQpIHdpdGggYmxvY2tzaXplIGxlbmd0aCArMlxuICAgKi9cbiAgbWRjOiBmdW5jdGlvbihjaXBoZXJmbiwga2V5LCBjaXBoZXJ0ZXh0KSB7XG4gICAgY2lwaGVyZm4gPSBuZXcgY2lwaGVyW2NpcGhlcmZuXShrZXkpO1xuICAgIHZhciBibG9ja19zaXplID0gY2lwaGVyZm4uYmxvY2tTaXplO1xuXG4gICAgdmFyIGlibG9jayA9IG5ldyBBcnJheShibG9ja19zaXplKTtcbiAgICB2YXIgYWJsb2NrID0gbmV3IEFycmF5KGJsb2NrX3NpemUpO1xuICAgIHZhciBpO1xuXG5cbiAgICAvLyBpbml0aWFsaXNhdGlvbiB2ZWN0b3JcbiAgICBmb3IgKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSAwO1xuXG4gICAgaWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChpYmxvY2spO1xuICAgIGZvciAoaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIHtcbiAgICAgIGFibG9ja1tpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgIGlibG9ja1tpXSBePSBhYmxvY2tbaV07XG4gICAgfVxuXG4gICAgYWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChhYmxvY2spO1xuXG4gICAgcmV0dXJuIHV0aWwuYmluMnN0cihpYmxvY2spICtcbiAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUoYWJsb2NrWzBdIF4gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGJsb2NrX3NpemUpKSArXG4gICAgICBTdHJpbmcuZnJvbUNoYXJDb2RlKGFibG9ja1sxXSBeIGNpcGhlcnRleHQuY2hhckNvZGVBdChibG9ja19zaXplICsgMSkpO1xuICB9LFxuICAvKipcbiAgICogVGhpcyBmdW5jdGlvbiBkZWNyeXB0cyBhIGdpdmVuIHBsYWludGV4dCB1c2luZyB0aGUgc3BlY2lmaWVkXG4gICAqIGJsb2NrY2lwaGVyIHRvIGRlY3J5cHQgYSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7b3BlbnBncF9jaXBoZXJfYmxvY2tfZm59IGJsb2NrY2lwaGVyZm4gVGhlIGFsZ29yaXRobSBfZW5jcnlwdF8gZnVuY3Rpb24gdG8gZW5jcnlwdFxuICAgKiAgZGF0YSBpbiBvbmUgYmxvY2tfc2l6ZSBlbmNyeXB0aW9uLlxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGJsb2NrX3NpemUgdGhlIGJsb2NrIHNpemUgaW4gYnl0ZXMgb2YgdGhlIGFsZ29yaXRobSB1c2VkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwbGFpbnRleHQgY2lwaGVydGV4dCB0byBiZSBkZWNyeXB0ZWQgcHJvdmlkZWQgYXMgYSBzdHJpbmdcbiAgICogQHBhcmFtIHtvcGVucGdwX2J5dGVfYXJyYXl9IGtleSBrZXkgdG8gYmUgdXNlZCB0byBkZWNyeXB0IHRoZSBjaXBoZXJ0ZXh0LiBUaGlzIHdpbGwgYmUgcGFzc2VkIHRvIHRoZSBcbiAgICogIGJsb2NrY2lwaGVyZm5cbiAgICogQHBhcmFtIHtCb29sZWFufSByZXN5bmMgYSBib29sZWFuIHZhbHVlIHNwZWNpZnlpbmcgaWYgYSByZXN5bmMgb2YgdGhlIFxuICAgKiAgSVYgc2hvdWxkIGJlIHVzZWQgb3Igbm90LiBUaGUgZW5jcnlwdGVkZGF0YXBhY2tldCB1c2VzIHRoZSBcbiAgICogIFwib2xkXCIgc3R5bGUgd2l0aCBhIHJlc3luYy4gRGVjcnlwdGlvbiB3aXRoaW4gYW4gXG4gICAqICBlbmNyeXB0ZWRpbnRlZ3JpdHlwcm90ZWN0ZWRkYXRhIHBhY2tldCBpcyBub3QgcmVzeW5jaW5nIHRoZSBJVi5cbiAgICogQHJldHVybiB7U3RyaW5nfSBhIHN0cmluZyB3aXRoIHRoZSBwbGFpbnRleHQgZGF0YVxuICAgKi9cblxuICBkZWNyeXB0OiBmdW5jdGlvbihjaXBoZXJmbiwga2V5LCBjaXBoZXJ0ZXh0LCByZXN5bmMpIHtcbiAgICBjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG4gICAgdmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cbiAgICB2YXIgaWJsb2NrID0gbmV3IEFycmF5KGJsb2NrX3NpemUpO1xuICAgIHZhciBhYmxvY2sgPSBuZXcgQXJyYXkoYmxvY2tfc2l6ZSk7XG4gICAgdmFyIGksIG4gPSAnJztcbiAgICB2YXIgdGV4dCA9IFtdO1xuXG4gICAgLy8gaW5pdGlhbGlzYXRpb24gdmVjdG9yXG4gICAgZm9yIChpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgaWJsb2NrW2ldID0gMDtcblxuICAgIGlibG9jayA9IGNpcGhlcmZuLmVuY3J5cHQoaWJsb2NrLCBrZXkpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBibG9ja19zaXplOyBpKyspIHtcbiAgICAgIGFibG9ja1tpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChpKTtcbiAgICAgIGlibG9ja1tpXSBePSBhYmxvY2tbaV07XG4gICAgfVxuXG4gICAgYWJsb2NrID0gY2lwaGVyZm4uZW5jcnlwdChhYmxvY2ssIGtleSk7XG5cbiAgICAvLyB0ZXN0IGNoZWNrIG9jdGV0c1xuICAgIGlmIChpYmxvY2tbYmxvY2tfc2l6ZSAtIDJdICE9IChhYmxvY2tbMF0gXiBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoYmxvY2tfc2l6ZSkpIHx8IGlibG9ja1tibG9ja19zaXplIC0gMV0gIT0gKGFibG9ja1tcbiAgICAgIDFdIF4gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGJsb2NrX3NpemUgKyAxKSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBkYXRhLicpO1xuICAgIH1cblxuICAgIC8qICBSRkM0ODgwOiBUYWcgMTggYW5kIFJlc3luYzpcblx0XHQgKiAgWy4uLl0gVW5saWtlIHRoZSBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIFBhY2tldCwgbm9cblx0XHQgKiAgc3BlY2lhbCBDRkIgcmVzeW5jaHJvbml6YXRpb24gaXMgZG9uZSBhZnRlciBlbmNyeXB0aW5nIHRoaXMgcHJlZml4XG5cdFx0ICogIGRhdGEuICBTZWUgXCJPcGVuUEdQIENGQiBNb2RlXCIgYmVsb3cgZm9yIG1vcmUgZGV0YWlscy5cblxuXHRcdCAqL1xuXG4gICAgaWYgKHJlc3luYykge1xuICAgICAgZm9yIChpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgaWJsb2NrW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KGkgKyAyKTtcbiAgICAgIGZvciAobiA9IGJsb2NrX3NpemUgKyAyOyBuIDwgY2lwaGVydGV4dC5sZW5ndGg7IG4gKz0gYmxvY2tfc2l6ZSkge1xuICAgICAgICBhYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGlibG9jayk7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGJsb2NrX3NpemUgJiYgaSArIG4gPCBjaXBoZXJ0ZXh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWJsb2NrW2ldID0gY2lwaGVydGV4dC5jaGFyQ29kZUF0KG4gKyBpKTtcbiAgICAgICAgICB0ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShhYmxvY2tbaV0gXiBpYmxvY2tbaV0pKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgYmxvY2tfc2l6ZTsgaSsrKSBpYmxvY2tbaV0gPSBjaXBoZXJ0ZXh0LmNoYXJDb2RlQXQoaSk7XG4gICAgICBmb3IgKG4gPSBibG9ja19zaXplOyBuIDwgY2lwaGVydGV4dC5sZW5ndGg7IG4gKz0gYmxvY2tfc2l6ZSkge1xuICAgICAgICBhYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KGlibG9jayk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBibG9ja19zaXplICYmIGkgKyBuIDwgY2lwaGVydGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGlibG9ja1tpXSA9IGNpcGhlcnRleHQuY2hhckNvZGVBdChuICsgaSk7XG4gICAgICAgICAgdGV4dC5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoYWJsb2NrW2ldIF4gaWJsb2NrW2ldKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbiA9IHJlc3luYyA/IDAgOiAyO1xuXG4gICAgdGV4dCA9IHRleHQuam9pbignJyk7XG5cbiAgICB0ZXh0ID0gdGV4dC5zdWJzdHJpbmcobiwgY2lwaGVydGV4dC5sZW5ndGggLSBibG9ja19zaXplIC0gMiArIG4pO1xuXG5cbiAgICByZXR1cm4gdGV4dDtcbiAgfSxcblxuXG4gIG5vcm1hbEVuY3J5cHQ6IGZ1bmN0aW9uKGNpcGhlcmZuLCBrZXksIHBsYWludGV4dCwgaXYpIHtcbiAgICBjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG4gICAgdmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cbiAgICB2YXIgYmxvY2tpID0gXCJcIjtcbiAgICB2YXIgYmxvY2tjID0gXCJcIjtcbiAgICB2YXIgcG9zID0gMDtcbiAgICB2YXIgY3lwaGVydGV4dCA9IFtdO1xuICAgIHZhciB0ZW1wQmxvY2sgPSBbXTtcbiAgICBibG9ja2MgPSBpdi5zdWJzdHJpbmcoMCwgYmxvY2tfc2l6ZSk7XG4gICAgd2hpbGUgKHBsYWludGV4dC5sZW5ndGggPiBibG9ja19zaXplICogcG9zKSB7XG4gICAgICB2YXIgZW5jYmxvY2sgPSBjaXBoZXJmbi5lbmNyeXB0KHV0aWwuc3RyMmJpbihibG9ja2MpKTtcbiAgICAgIGJsb2NraSA9IHBsYWludGV4dC5zdWJzdHJpbmcoKHBvcyAqIGJsb2NrX3NpemUpLCAocG9zICogYmxvY2tfc2l6ZSkgKyBibG9ja19zaXplKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tpLmxlbmd0aDsgaSsrKVxuICAgICAgICB0ZW1wQmxvY2sucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGJsb2NraS5jaGFyQ29kZUF0KGkpIF4gZW5jYmxvY2tbaV0pKTtcbiAgICAgIGJsb2NrYyA9IHRlbXBCbG9jay5qb2luKCcnKTtcbiAgICAgIHRlbXBCbG9jayA9IFtdO1xuICAgICAgY3lwaGVydGV4dC5wdXNoKGJsb2NrYyk7XG4gICAgICBwb3MrKztcbiAgICB9XG4gICAgcmV0dXJuIGN5cGhlcnRleHQuam9pbignJyk7XG4gIH0sXG5cbiAgbm9ybWFsRGVjcnlwdDogZnVuY3Rpb24oY2lwaGVyZm4sIGtleSwgY2lwaGVydGV4dCwgaXYpIHtcbiAgICBjaXBoZXJmbiA9IG5ldyBjaXBoZXJbY2lwaGVyZm5dKGtleSk7XG4gICAgdmFyIGJsb2NrX3NpemUgPSBjaXBoZXJmbi5ibG9ja1NpemU7XG5cbiAgICB2YXIgYmxvY2twID0gXCJcIjtcbiAgICB2YXIgcG9zID0gMDtcbiAgICB2YXIgcGxhaW50ZXh0ID0gW107XG4gICAgdmFyIG9mZnNldCA9IDA7XG4gICAgaWYgKGl2ID09IG51bGwpXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2NrX3NpemU7IGkrKykgYmxvY2twICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCk7XG4gICAgZWxzZVxuICAgICAgYmxvY2twID0gaXYuc3Vic3RyaW5nKDAsIGJsb2NrX3NpemUpO1xuICAgIHdoaWxlIChjaXBoZXJ0ZXh0Lmxlbmd0aCA+IChibG9ja19zaXplICogcG9zKSkge1xuICAgICAgdmFyIGRlY2Jsb2NrID0gY2lwaGVyZm4uZW5jcnlwdCh1dGlsLnN0cjJiaW4oYmxvY2twKSk7XG4gICAgICBibG9ja3AgPSBjaXBoZXJ0ZXh0LnN1YnN0cmluZygocG9zICogKGJsb2NrX3NpemUpKSArIG9mZnNldCwgKHBvcyAqIChibG9ja19zaXplKSkgKyAoYmxvY2tfc2l6ZSkgKyBvZmZzZXQpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBibG9ja3AubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcGxhaW50ZXh0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShibG9ja3AuY2hhckNvZGVBdChpKSBeIGRlY2Jsb2NrW2ldKSk7XG4gICAgICB9XG4gICAgICBwb3MrKztcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhaW50ZXh0LmpvaW4oJycpO1xuICB9XG59XG4iLCIvKiBSaWpuZGFlbCAoQUVTKSBFbmNyeXB0aW9uXG4gKiBDb3B5cmlnaHQgMjAwNSBIZXJiZXJ0IEhhbmV3aW5rZWwsIHd3dy5oYW5lV0lOLmRlXG4gKiB2ZXJzaW9uIDEuMSwgY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxuXG4gKiBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkIGFzLWlzLCB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4gIFxuICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgZGlzdHJpYnV0ZSBvciBzZWxsIHRoaXMgc29mdHdhcmUsIHdpdGggb3JcbiAqIHdpdGhvdXQgZmVlLCBmb3IgYW55IHB1cnBvc2UgYW5kIGJ5IGFueSBpbmRpdmlkdWFsIG9yIG9yZ2FuaXphdGlvbiwgaXMgaGVyZWJ5XG4gKiBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBhcmFncmFwaCBhcHBlYXIgXG4gKiBpbiBhbGwgY29waWVzLiBEaXN0cmlidXRpb24gYXMgYSBwYXJ0IG9mIGFuIGFwcGxpY2F0aW9uIG9yIGJpbmFyeSBtdXN0XG4gKiBpbmNsdWRlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlclxuICogbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGFwcGxpY2F0aW9uIG9yIGRpc3RyaWJ1dGlvbi5cbiAqL1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gVGhlIHJvdW5kIGNvbnN0YW50cyB1c2VkIGluIHN1YmtleSBleHBhbnNpb25cbnZhciBSY29uID0gW1xuICAgIDB4MDEsIDB4MDIsIDB4MDQsIDB4MDgsIDB4MTAsIDB4MjAsIDB4NDAsIDB4ODAsIDB4MWIsIDB4MzYsIDB4NmMsIDB4ZDgsXG4gICAgMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCxcbiAgICAweGIzLCAweDdkLCAweGZhLCAweGVmLCAweGM1LCAweDkxXG5dO1xuXG4vLyBQcmVjb21wdXRlZCBsb29rdXAgdGFibGUgZm9yIHRoZSBTQm94XG52YXIgUyA9IFtcbiAgICA5OSwgMTI0LCAxMTksIDEyMywgMjQyLCAxMDcsIDExMSwgMTk3LCA0OCwgMSwgMTAzLCA0MywgMjU0LCAyMTUsIDE3MSxcbiAgICAxMTgsIDIwMiwgMTMwLCAyMDEsIDEyNSwgMjUwLCA4OSwgNzEsIDI0MCwgMTczLCAyMTIsIDE2MiwgMTc1LCAxNTYsIDE2NCxcbiAgICAxMTQsIDE5MiwgMTgzLCAyNTMsIDE0NywgMzgsIDU0LCA2MywgMjQ3LCAyMDQsIDUyLCAxNjUsIDIyOSwgMjQxLCAxMTMsXG4gICAgMjE2LCA0OSwgMjEsIDQsIDE5OSwgMzUsIDE5NSwgMjQsIDE1MCwgNSwgMTU0LCA3LCAxOCwgMTI4LCAyMjYsXG4gICAgMjM1LCAzOSwgMTc4LCAxMTcsIDksIDEzMSwgNDQsIDI2LCAyNywgMTEwLCA5MCwgMTYwLCA4MiwgNTksIDIxNCxcbiAgICAxNzksIDQxLCAyMjcsIDQ3LCAxMzIsIDgzLCAyMDksIDAsIDIzNywgMzIsIDI1MiwgMTc3LCA5MSwgMTA2LCAyMDMsXG4gICAgMTkwLCA1NywgNzQsIDc2LCA4OCwgMjA3LCAyMDgsIDIzOSwgMTcwLCAyNTEsIDY3LCA3NywgNTEsIDEzMywgNjksXG4gICAgMjQ5LCAyLCAxMjcsIDgwLCA2MCwgMTU5LCAxNjgsIDgxLCAxNjMsIDY0LCAxNDMsIDE0NiwgMTU3LCA1NiwgMjQ1LFxuICAgIDE4OCwgMTgyLCAyMTgsIDMzLCAxNiwgMjU1LCAyNDMsIDIxMCwgMjA1LCAxMiwgMTksIDIzNiwgOTUsIDE1MSwgNjgsXG4gICAgMjMsIDE5NiwgMTY3LCAxMjYsIDYxLCAxMDAsIDkzLCAyNSwgMTE1LCA5NiwgMTI5LCA3OSwgMjIwLCAzNCwgNDIsXG4gICAgMTQ0LCAxMzYsIDcwLCAyMzgsIDE4NCwgMjAsIDIyMiwgOTQsIDExLCAyMTksIDIyNCwgNTAsIDU4LCAxMCwgNzMsXG4gICAgNiwgMzYsIDkyLCAxOTQsIDIxMSwgMTcyLCA5OCwgMTQ1LCAxNDksIDIyOCwgMTIxLCAyMzEsIDIwMCwgNTUsIDEwOSxcbiAgICAxNDEsIDIxMywgNzgsIDE2OSwgMTA4LCA4NiwgMjQ0LCAyMzQsIDEwMSwgMTIyLCAxNzQsIDgsIDE4NiwgMTIwLCAzNyxcbiAgICA0NiwgMjgsIDE2NiwgMTgwLCAxOTgsIDIzMiwgMjIxLCAxMTYsIDMxLCA3NSwgMTg5LCAxMzksIDEzOCwgMTEyLCA2MixcbiAgICAxODEsIDEwMiwgNzIsIDMsIDI0NiwgMTQsIDk3LCA1MywgODcsIDE4NSwgMTM0LCAxOTMsIDI5LCAxNTgsIDIyNSxcbiAgICAyNDgsIDE1MiwgMTcsIDEwNSwgMjE3LCAxNDIsIDE0OCwgMTU1LCAzMCwgMTM1LCAyMzMsIDIwNiwgODUsIDQwLCAyMjMsXG4gICAgMTQwLCAxNjEsIDEzNywgMTMsIDE5MSwgMjMwLCA2NiwgMTA0LCA2NSwgMTUzLCA0NSwgMTUsIDE3NiwgODQsIDE4NyxcbiAgICAyMlxuXTtcblxudmFyIFQxID0gW1xuICAgIDB4YTU2MzYzYzYsIDB4ODQ3YzdjZjgsIDB4OTk3Nzc3ZWUsIDB4OGQ3YjdiZjYsXG4gICAgMHgwZGYyZjJmZiwgMHhiZDZiNmJkNiwgMHhiMTZmNmZkZSwgMHg1NGM1YzU5MSxcbiAgICAweDUwMzAzMDYwLCAweDAzMDEwMTAyLCAweGE5Njc2N2NlLCAweDdkMmIyYjU2LFxuICAgIDB4MTlmZWZlZTcsIDB4NjJkN2Q3YjUsIDB4ZTZhYmFiNGQsIDB4OWE3Njc2ZWMsXG4gICAgMHg0NWNhY2E4ZiwgMHg5ZDgyODIxZiwgMHg0MGM5Yzk4OSwgMHg4NzdkN2RmYSxcbiAgICAweDE1ZmFmYWVmLCAweGViNTk1OWIyLCAweGM5NDc0NzhlLCAweDBiZjBmMGZiLFxuICAgIDB4ZWNhZGFkNDEsIDB4NjdkNGQ0YjMsIDB4ZmRhMmEyNWYsIDB4ZWFhZmFmNDUsXG4gICAgMHhiZjljOWMyMywgMHhmN2E0YTQ1MywgMHg5NjcyNzJlNCwgMHg1YmMwYzA5YixcbiAgICAweGMyYjdiNzc1LCAweDFjZmRmZGUxLCAweGFlOTM5MzNkLCAweDZhMjYyNjRjLFxuICAgIDB4NWEzNjM2NmMsIDB4NDEzZjNmN2UsIDB4MDJmN2Y3ZjUsIDB4NGZjY2NjODMsXG4gICAgMHg1YzM0MzQ2OCwgMHhmNGE1YTU1MSwgMHgzNGU1ZTVkMSwgMHgwOGYxZjFmOSxcbiAgICAweDkzNzE3MWUyLCAweDczZDhkOGFiLCAweDUzMzEzMTYyLCAweDNmMTUxNTJhLFxuICAgIDB4MGMwNDA0MDgsIDB4NTJjN2M3OTUsIDB4NjUyMzIzNDYsIDB4NWVjM2MzOWQsXG4gICAgMHgyODE4MTgzMCwgMHhhMTk2OTYzNywgMHgwZjA1MDUwYSwgMHhiNTlhOWEyZixcbiAgICAweDA5MDcwNzBlLCAweDM2MTIxMjI0LCAweDliODA4MDFiLCAweDNkZTJlMmRmLFxuICAgIDB4MjZlYmViY2QsIDB4NjkyNzI3NGUsIDB4Y2RiMmIyN2YsIDB4OWY3NTc1ZWEsXG4gICAgMHgxYjA5MDkxMiwgMHg5ZTgzODMxZCwgMHg3NDJjMmM1OCwgMHgyZTFhMWEzNCxcbiAgICAweDJkMWIxYjM2LCAweGIyNmU2ZWRjLCAweGVlNWE1YWI0LCAweGZiYTBhMDViLFxuICAgIDB4ZjY1MjUyYTQsIDB4NGQzYjNiNzYsIDB4NjFkNmQ2YjcsIDB4Y2ViM2IzN2QsXG4gICAgMHg3YjI5Mjk1MiwgMHgzZWUzZTNkZCwgMHg3MTJmMmY1ZSwgMHg5Nzg0ODQxMyxcbiAgICAweGY1NTM1M2E2LCAweDY4ZDFkMWI5LCAweDAwMDAwMDAwLCAweDJjZWRlZGMxLFxuICAgIDB4NjAyMDIwNDAsIDB4MWZmY2ZjZTMsIDB4YzhiMWIxNzksIDB4ZWQ1YjViYjYsXG4gICAgMHhiZTZhNmFkNCwgMHg0NmNiY2I4ZCwgMHhkOWJlYmU2NywgMHg0YjM5Mzk3MixcbiAgICAweGRlNGE0YTk0LCAweGQ0NGM0Yzk4LCAweGU4NTg1OGIwLCAweDRhY2ZjZjg1LFxuICAgIDB4NmJkMGQwYmIsIDB4MmFlZmVmYzUsIDB4ZTVhYWFhNGYsIDB4MTZmYmZiZWQsXG4gICAgMHhjNTQzNDM4NiwgMHhkNzRkNGQ5YSwgMHg1NTMzMzM2NiwgMHg5NDg1ODUxMSxcbiAgICAweGNmNDU0NThhLCAweDEwZjlmOWU5LCAweDA2MDIwMjA0LCAweDgxN2Y3ZmZlLFxuICAgIDB4ZjA1MDUwYTAsIDB4NDQzYzNjNzgsIDB4YmE5ZjlmMjUsIDB4ZTNhOGE4NGIsXG4gICAgMHhmMzUxNTFhMiwgMHhmZWEzYTM1ZCwgMHhjMDQwNDA4MCwgMHg4YThmOGYwNSxcbiAgICAweGFkOTI5MjNmLCAweGJjOWQ5ZDIxLCAweDQ4MzgzODcwLCAweDA0ZjVmNWYxLFxuICAgIDB4ZGZiY2JjNjMsIDB4YzFiNmI2NzcsIDB4NzVkYWRhYWYsIDB4NjMyMTIxNDIsXG4gICAgMHgzMDEwMTAyMCwgMHgxYWZmZmZlNSwgMHgwZWYzZjNmZCwgMHg2ZGQyZDJiZixcbiAgICAweDRjY2RjZDgxLCAweDE0MGMwYzE4LCAweDM1MTMxMzI2LCAweDJmZWNlY2MzLFxuICAgIDB4ZTE1ZjVmYmUsIDB4YTI5Nzk3MzUsIDB4Y2M0NDQ0ODgsIDB4MzkxNzE3MmUsXG4gICAgMHg1N2M0YzQ5MywgMHhmMmE3YTc1NSwgMHg4MjdlN2VmYywgMHg0NzNkM2Q3YSxcbiAgICAweGFjNjQ2NGM4LCAweGU3NWQ1ZGJhLCAweDJiMTkxOTMyLCAweDk1NzM3M2U2LFxuICAgIDB4YTA2MDYwYzAsIDB4OTg4MTgxMTksIDB4ZDE0ZjRmOWUsIDB4N2ZkY2RjYTMsXG4gICAgMHg2NjIyMjI0NCwgMHg3ZTJhMmE1NCwgMHhhYjkwOTAzYiwgMHg4Mzg4ODgwYixcbiAgICAweGNhNDY0NjhjLCAweDI5ZWVlZWM3LCAweGQzYjhiODZiLCAweDNjMTQxNDI4LFxuICAgIDB4NzlkZWRlYTcsIDB4ZTI1ZTVlYmMsIDB4MWQwYjBiMTYsIDB4NzZkYmRiYWQsXG4gICAgMHgzYmUwZTBkYiwgMHg1NjMyMzI2NCwgMHg0ZTNhM2E3NCwgMHgxZTBhMGExNCxcbiAgICAweGRiNDk0OTkyLCAweDBhMDYwNjBjLCAweDZjMjQyNDQ4LCAweGU0NWM1Y2I4LFxuICAgIDB4NWRjMmMyOWYsIDB4NmVkM2QzYmQsIDB4ZWZhY2FjNDMsIDB4YTY2MjYyYzQsXG4gICAgMHhhODkxOTEzOSwgMHhhNDk1OTUzMSwgMHgzN2U0ZTRkMywgMHg4Yjc5NzlmMixcbiAgICAweDMyZTdlN2Q1LCAweDQzYzhjODhiLCAweDU5MzczNzZlLCAweGI3NmQ2ZGRhLFxuICAgIDB4OGM4ZDhkMDEsIDB4NjRkNWQ1YjEsIDB4ZDI0ZTRlOWMsIDB4ZTBhOWE5NDksXG4gICAgMHhiNDZjNmNkOCwgMHhmYTU2NTZhYywgMHgwN2Y0ZjRmMywgMHgyNWVhZWFjZixcbiAgICAweGFmNjU2NWNhLCAweDhlN2E3YWY0LCAweGU5YWVhZTQ3LCAweDE4MDgwODEwLFxuICAgIDB4ZDViYWJhNmYsIDB4ODg3ODc4ZjAsIDB4NmYyNTI1NGEsIDB4NzIyZTJlNWMsXG4gICAgMHgyNDFjMWMzOCwgMHhmMWE2YTY1NywgMHhjN2I0YjQ3MywgMHg1MWM2YzY5NyxcbiAgICAweDIzZThlOGNiLCAweDdjZGRkZGExLCAweDljNzQ3NGU4LCAweDIxMWYxZjNlLFxuICAgIDB4ZGQ0YjRiOTYsIDB4ZGNiZGJkNjEsIDB4ODY4YjhiMGQsIDB4ODU4YThhMGYsXG4gICAgMHg5MDcwNzBlMCwgMHg0MjNlM2U3YywgMHhjNGI1YjU3MSwgMHhhYTY2NjZjYyxcbiAgICAweGQ4NDg0ODkwLCAweDA1MDMwMzA2LCAweDAxZjZmNmY3LCAweDEyMGUwZTFjLFxuICAgIDB4YTM2MTYxYzIsIDB4NWYzNTM1NmEsIDB4Zjk1NzU3YWUsIDB4ZDBiOWI5NjksXG4gICAgMHg5MTg2ODYxNywgMHg1OGMxYzE5OSwgMHgyNzFkMWQzYSwgMHhiOTllOWUyNyxcbiAgICAweDM4ZTFlMWQ5LCAweDEzZjhmOGViLCAweGIzOTg5ODJiLCAweDMzMTExMTIyLFxuICAgIDB4YmI2OTY5ZDIsIDB4NzBkOWQ5YTksIDB4ODk4ZThlMDcsIDB4YTc5NDk0MzMsXG4gICAgMHhiNjliOWIyZCwgMHgyMjFlMWUzYywgMHg5Mjg3ODcxNSwgMHgyMGU5ZTljOSxcbiAgICAweDQ5Y2VjZTg3LCAweGZmNTU1NWFhLCAweDc4MjgyODUwLCAweDdhZGZkZmE1LFxuICAgIDB4OGY4YzhjMDMsIDB4ZjhhMWExNTksIDB4ODA4OTg5MDksIDB4MTcwZDBkMWEsXG4gICAgMHhkYWJmYmY2NSwgMHgzMWU2ZTZkNywgMHhjNjQyNDI4NCwgMHhiODY4NjhkMCxcbiAgICAweGMzNDE0MTgyLCAweGIwOTk5OTI5LCAweDc3MmQyZDVhLCAweDExMGYwZjFlLFxuICAgIDB4Y2JiMGIwN2IsIDB4ZmM1NDU0YTgsIDB4ZDZiYmJiNmQsIDB4M2ExNjE2MmNcbl07XG5cbnZhciBUMiA9IFtcbiAgICAweDYzNjNjNmE1LCAweDdjN2NmODg0LCAweDc3NzdlZTk5LCAweDdiN2JmNjhkLFxuICAgIDB4ZjJmMmZmMGQsIDB4NmI2YmQ2YmQsIDB4NmY2ZmRlYjEsIDB4YzVjNTkxNTQsXG4gICAgMHgzMDMwNjA1MCwgMHgwMTAxMDIwMywgMHg2NzY3Y2VhOSwgMHgyYjJiNTY3ZCxcbiAgICAweGZlZmVlNzE5LCAweGQ3ZDdiNTYyLCAweGFiYWI0ZGU2LCAweDc2NzZlYzlhLFxuICAgIDB4Y2FjYThmNDUsIDB4ODI4MjFmOWQsIDB4YzljOTg5NDAsIDB4N2Q3ZGZhODcsXG4gICAgMHhmYWZhZWYxNSwgMHg1OTU5YjJlYiwgMHg0NzQ3OGVjOSwgMHhmMGYwZmIwYixcbiAgICAweGFkYWQ0MWVjLCAweGQ0ZDRiMzY3LCAweGEyYTI1ZmZkLCAweGFmYWY0NWVhLFxuICAgIDB4OWM5YzIzYmYsIDB4YTRhNDUzZjcsIDB4NzI3MmU0OTYsIDB4YzBjMDliNWIsXG4gICAgMHhiN2I3NzVjMiwgMHhmZGZkZTExYywgMHg5MzkzM2RhZSwgMHgyNjI2NGM2YSxcbiAgICAweDM2MzY2YzVhLCAweDNmM2Y3ZTQxLCAweGY3ZjdmNTAyLCAweGNjY2M4MzRmLFxuICAgIDB4MzQzNDY4NWMsIDB4YTVhNTUxZjQsIDB4ZTVlNWQxMzQsIDB4ZjFmMWY5MDgsXG4gICAgMHg3MTcxZTI5MywgMHhkOGQ4YWI3MywgMHgzMTMxNjI1MywgMHgxNTE1MmEzZixcbiAgICAweDA0MDQwODBjLCAweGM3Yzc5NTUyLCAweDIzMjM0NjY1LCAweGMzYzM5ZDVlLFxuICAgIDB4MTgxODMwMjgsIDB4OTY5NjM3YTEsIDB4MDUwNTBhMGYsIDB4OWE5YTJmYjUsXG4gICAgMHgwNzA3MGUwOSwgMHgxMjEyMjQzNiwgMHg4MDgwMWI5YiwgMHhlMmUyZGYzZCxcbiAgICAweGViZWJjZDI2LCAweDI3Mjc0ZTY5LCAweGIyYjI3ZmNkLCAweDc1NzVlYTlmLFxuICAgIDB4MDkwOTEyMWIsIDB4ODM4MzFkOWUsIDB4MmMyYzU4NzQsIDB4MWExYTM0MmUsXG4gICAgMHgxYjFiMzYyZCwgMHg2ZTZlZGNiMiwgMHg1YTVhYjRlZSwgMHhhMGEwNWJmYixcbiAgICAweDUyNTJhNGY2LCAweDNiM2I3NjRkLCAweGQ2ZDZiNzYxLCAweGIzYjM3ZGNlLFxuICAgIDB4MjkyOTUyN2IsIDB4ZTNlM2RkM2UsIDB4MmYyZjVlNzEsIDB4ODQ4NDEzOTcsXG4gICAgMHg1MzUzYTZmNSwgMHhkMWQxYjk2OCwgMHgwMDAwMDAwMCwgMHhlZGVkYzEyYyxcbiAgICAweDIwMjA0MDYwLCAweGZjZmNlMzFmLCAweGIxYjE3OWM4LCAweDViNWJiNmVkLFxuICAgIDB4NmE2YWQ0YmUsIDB4Y2JjYjhkNDYsIDB4YmViZTY3ZDksIDB4MzkzOTcyNGIsXG4gICAgMHg0YTRhOTRkZSwgMHg0YzRjOThkNCwgMHg1ODU4YjBlOCwgMHhjZmNmODU0YSxcbiAgICAweGQwZDBiYjZiLCAweGVmZWZjNTJhLCAweGFhYWE0ZmU1LCAweGZiZmJlZDE2LFxuICAgIDB4NDM0Mzg2YzUsIDB4NGQ0ZDlhZDcsIDB4MzMzMzY2NTUsIDB4ODU4NTExOTQsXG4gICAgMHg0NTQ1OGFjZiwgMHhmOWY5ZTkxMCwgMHgwMjAyMDQwNiwgMHg3ZjdmZmU4MSxcbiAgICAweDUwNTBhMGYwLCAweDNjM2M3ODQ0LCAweDlmOWYyNWJhLCAweGE4YTg0YmUzLFxuICAgIDB4NTE1MWEyZjMsIDB4YTNhMzVkZmUsIDB4NDA0MDgwYzAsIDB4OGY4ZjA1OGEsXG4gICAgMHg5MjkyM2ZhZCwgMHg5ZDlkMjFiYywgMHgzODM4NzA0OCwgMHhmNWY1ZjEwNCxcbiAgICAweGJjYmM2M2RmLCAweGI2YjY3N2MxLCAweGRhZGFhZjc1LCAweDIxMjE0MjYzLFxuICAgIDB4MTAxMDIwMzAsIDB4ZmZmZmU1MWEsIDB4ZjNmM2ZkMGUsIDB4ZDJkMmJmNmQsXG4gICAgMHhjZGNkODE0YywgMHgwYzBjMTgxNCwgMHgxMzEzMjYzNSwgMHhlY2VjYzMyZixcbiAgICAweDVmNWZiZWUxLCAweDk3OTczNWEyLCAweDQ0NDQ4OGNjLCAweDE3MTcyZTM5LFxuICAgIDB4YzRjNDkzNTcsIDB4YTdhNzU1ZjIsIDB4N2U3ZWZjODIsIDB4M2QzZDdhNDcsXG4gICAgMHg2NDY0YzhhYywgMHg1ZDVkYmFlNywgMHgxOTE5MzIyYiwgMHg3MzczZTY5NSxcbiAgICAweDYwNjBjMGEwLCAweDgxODExOTk4LCAweDRmNGY5ZWQxLCAweGRjZGNhMzdmLFxuICAgIDB4MjIyMjQ0NjYsIDB4MmEyYTU0N2UsIDB4OTA5MDNiYWIsIDB4ODg4ODBiODMsXG4gICAgMHg0NjQ2OGNjYSwgMHhlZWVlYzcyOSwgMHhiOGI4NmJkMywgMHgxNDE0MjgzYyxcbiAgICAweGRlZGVhNzc5LCAweDVlNWViY2UyLCAweDBiMGIxNjFkLCAweGRiZGJhZDc2LFxuICAgIDB4ZTBlMGRiM2IsIDB4MzIzMjY0NTYsIDB4M2EzYTc0NGUsIDB4MGEwYTE0MWUsXG4gICAgMHg0OTQ5OTJkYiwgMHgwNjA2MGMwYSwgMHgyNDI0NDg2YywgMHg1YzVjYjhlNCxcbiAgICAweGMyYzI5ZjVkLCAweGQzZDNiZDZlLCAweGFjYWM0M2VmLCAweDYyNjJjNGE2LFxuICAgIDB4OTE5MTM5YTgsIDB4OTU5NTMxYTQsIDB4ZTRlNGQzMzcsIDB4Nzk3OWYyOGIsXG4gICAgMHhlN2U3ZDUzMiwgMHhjOGM4OGI0MywgMHgzNzM3NmU1OSwgMHg2ZDZkZGFiNyxcbiAgICAweDhkOGQwMThjLCAweGQ1ZDViMTY0LCAweDRlNGU5Y2QyLCAweGE5YTk0OWUwLFxuICAgIDB4NmM2Y2Q4YjQsIDB4NTY1NmFjZmEsIDB4ZjRmNGYzMDcsIDB4ZWFlYWNmMjUsXG4gICAgMHg2NTY1Y2FhZiwgMHg3YTdhZjQ4ZSwgMHhhZWFlNDdlOSwgMHgwODA4MTAxOCxcbiAgICAweGJhYmE2ZmQ1LCAweDc4NzhmMDg4LCAweDI1MjU0YTZmLCAweDJlMmU1YzcyLFxuICAgIDB4MWMxYzM4MjQsIDB4YTZhNjU3ZjEsIDB4YjRiNDczYzcsIDB4YzZjNjk3NTEsXG4gICAgMHhlOGU4Y2IyMywgMHhkZGRkYTE3YywgMHg3NDc0ZTg5YywgMHgxZjFmM2UyMSxcbiAgICAweDRiNGI5NmRkLCAweGJkYmQ2MWRjLCAweDhiOGIwZDg2LCAweDhhOGEwZjg1LFxuICAgIDB4NzA3MGUwOTAsIDB4M2UzZTdjNDIsIDB4YjViNTcxYzQsIDB4NjY2NmNjYWEsXG4gICAgMHg0ODQ4OTBkOCwgMHgwMzAzMDYwNSwgMHhmNmY2ZjcwMSwgMHgwZTBlMWMxMixcbiAgICAweDYxNjFjMmEzLCAweDM1MzU2YTVmLCAweDU3NTdhZWY5LCAweGI5Yjk2OWQwLFxuICAgIDB4ODY4NjE3OTEsIDB4YzFjMTk5NTgsIDB4MWQxZDNhMjcsIDB4OWU5ZTI3YjksXG4gICAgMHhlMWUxZDkzOCwgMHhmOGY4ZWIxMywgMHg5ODk4MmJiMywgMHgxMTExMjIzMyxcbiAgICAweDY5NjlkMmJiLCAweGQ5ZDlhOTcwLCAweDhlOGUwNzg5LCAweDk0OTQzM2E3LFxuICAgIDB4OWI5YjJkYjYsIDB4MWUxZTNjMjIsIDB4ODc4NzE1OTIsIDB4ZTllOWM5MjAsXG4gICAgMHhjZWNlODc0OSwgMHg1NTU1YWFmZiwgMHgyODI4NTA3OCwgMHhkZmRmYTU3YSxcbiAgICAweDhjOGMwMzhmLCAweGExYTE1OWY4LCAweDg5ODkwOTgwLCAweDBkMGQxYTE3LFxuICAgIDB4YmZiZjY1ZGEsIDB4ZTZlNmQ3MzEsIDB4NDI0Mjg0YzYsIDB4Njg2OGQwYjgsXG4gICAgMHg0MTQxODJjMywgMHg5OTk5MjliMCwgMHgyZDJkNWE3NywgMHgwZjBmMWUxMSxcbiAgICAweGIwYjA3YmNiLCAweDU0NTRhOGZjLCAweGJiYmI2ZGQ2LCAweDE2MTYyYzNhXG5dO1xuXG52YXIgVDMgPSBbXG4gICAgMHg2M2M2YTU2MywgMHg3Y2Y4ODQ3YywgMHg3N2VlOTk3NywgMHg3YmY2OGQ3YixcbiAgICAweGYyZmYwZGYyLCAweDZiZDZiZDZiLCAweDZmZGViMTZmLCAweGM1OTE1NGM1LFxuICAgIDB4MzA2MDUwMzAsIDB4MDEwMjAzMDEsIDB4NjdjZWE5NjcsIDB4MmI1NjdkMmIsXG4gICAgMHhmZWU3MTlmZSwgMHhkN2I1NjJkNywgMHhhYjRkZTZhYiwgMHg3NmVjOWE3NixcbiAgICAweGNhOGY0NWNhLCAweDgyMWY5ZDgyLCAweGM5ODk0MGM5LCAweDdkZmE4NzdkLFxuICAgIDB4ZmFlZjE1ZmEsIDB4NTliMmViNTksIDB4NDc4ZWM5NDcsIDB4ZjBmYjBiZjAsXG4gICAgMHhhZDQxZWNhZCwgMHhkNGIzNjdkNCwgMHhhMjVmZmRhMiwgMHhhZjQ1ZWFhZixcbiAgICAweDljMjNiZjljLCAweGE0NTNmN2E0LCAweDcyZTQ5NjcyLCAweGMwOWI1YmMwLFxuICAgIDB4Yjc3NWMyYjcsIDB4ZmRlMTFjZmQsIDB4OTMzZGFlOTMsIDB4MjY0YzZhMjYsXG4gICAgMHgzNjZjNWEzNiwgMHgzZjdlNDEzZiwgMHhmN2Y1MDJmNywgMHhjYzgzNGZjYyxcbiAgICAweDM0Njg1YzM0LCAweGE1NTFmNGE1LCAweGU1ZDEzNGU1LCAweGYxZjkwOGYxLFxuICAgIDB4NzFlMjkzNzEsIDB4ZDhhYjczZDgsIDB4MzE2MjUzMzEsIDB4MTUyYTNmMTUsXG4gICAgMHgwNDA4MGMwNCwgMHhjNzk1NTJjNywgMHgyMzQ2NjUyMywgMHhjMzlkNWVjMyxcbiAgICAweDE4MzAyODE4LCAweDk2MzdhMTk2LCAweDA1MGEwZjA1LCAweDlhMmZiNTlhLFxuICAgIDB4MDcwZTA5MDcsIDB4MTIyNDM2MTIsIDB4ODAxYjliODAsIDB4ZTJkZjNkZTIsXG4gICAgMHhlYmNkMjZlYiwgMHgyNzRlNjkyNywgMHhiMjdmY2RiMiwgMHg3NWVhOWY3NSxcbiAgICAweDA5MTIxYjA5LCAweDgzMWQ5ZTgzLCAweDJjNTg3NDJjLCAweDFhMzQyZTFhLFxuICAgIDB4MWIzNjJkMWIsIDB4NmVkY2IyNmUsIDB4NWFiNGVlNWEsIDB4YTA1YmZiYTAsXG4gICAgMHg1MmE0ZjY1MiwgMHgzYjc2NGQzYiwgMHhkNmI3NjFkNiwgMHhiMzdkY2ViMyxcbiAgICAweDI5NTI3YjI5LCAweGUzZGQzZWUzLCAweDJmNWU3MTJmLCAweDg0MTM5Nzg0LFxuICAgIDB4NTNhNmY1NTMsIDB4ZDFiOTY4ZDEsIDB4MDAwMDAwMDAsIDB4ZWRjMTJjZWQsXG4gICAgMHgyMDQwNjAyMCwgMHhmY2UzMWZmYywgMHhiMTc5YzhiMSwgMHg1YmI2ZWQ1YixcbiAgICAweDZhZDRiZTZhLCAweGNiOGQ0NmNiLCAweGJlNjdkOWJlLCAweDM5NzI0YjM5LFxuICAgIDB4NGE5NGRlNGEsIDB4NGM5OGQ0NGMsIDB4NThiMGU4NTgsIDB4Y2Y4NTRhY2YsXG4gICAgMHhkMGJiNmJkMCwgMHhlZmM1MmFlZiwgMHhhYTRmZTVhYSwgMHhmYmVkMTZmYixcbiAgICAweDQzODZjNTQzLCAweDRkOWFkNzRkLCAweDMzNjY1NTMzLCAweDg1MTE5NDg1LFxuICAgIDB4NDU4YWNmNDUsIDB4ZjllOTEwZjksIDB4MDIwNDA2MDIsIDB4N2ZmZTgxN2YsXG4gICAgMHg1MGEwZjA1MCwgMHgzYzc4NDQzYywgMHg5ZjI1YmE5ZiwgMHhhODRiZTNhOCxcbiAgICAweDUxYTJmMzUxLCAweGEzNWRmZWEzLCAweDQwODBjMDQwLCAweDhmMDU4YThmLFxuICAgIDB4OTIzZmFkOTIsIDB4OWQyMWJjOWQsIDB4Mzg3MDQ4MzgsIDB4ZjVmMTA0ZjUsXG4gICAgMHhiYzYzZGZiYywgMHhiNjc3YzFiNiwgMHhkYWFmNzVkYSwgMHgyMTQyNjMyMSxcbiAgICAweDEwMjAzMDEwLCAweGZmZTUxYWZmLCAweGYzZmQwZWYzLCAweGQyYmY2ZGQyLFxuICAgIDB4Y2Q4MTRjY2QsIDB4MGMxODE0MGMsIDB4MTMyNjM1MTMsIDB4ZWNjMzJmZWMsXG4gICAgMHg1ZmJlZTE1ZiwgMHg5NzM1YTI5NywgMHg0NDg4Y2M0NCwgMHgxNzJlMzkxNyxcbiAgICAweGM0OTM1N2M0LCAweGE3NTVmMmE3LCAweDdlZmM4MjdlLCAweDNkN2E0NzNkLFxuICAgIDB4NjRjOGFjNjQsIDB4NWRiYWU3NWQsIDB4MTkzMjJiMTksIDB4NzNlNjk1NzMsXG4gICAgMHg2MGMwYTA2MCwgMHg4MTE5OTg4MSwgMHg0ZjllZDE0ZiwgMHhkY2EzN2ZkYyxcbiAgICAweDIyNDQ2NjIyLCAweDJhNTQ3ZTJhLCAweDkwM2JhYjkwLCAweDg4MGI4Mzg4LFxuICAgIDB4NDY4Y2NhNDYsIDB4ZWVjNzI5ZWUsIDB4Yjg2YmQzYjgsIDB4MTQyODNjMTQsXG4gICAgMHhkZWE3NzlkZSwgMHg1ZWJjZTI1ZSwgMHgwYjE2MWQwYiwgMHhkYmFkNzZkYixcbiAgICAweGUwZGIzYmUwLCAweDMyNjQ1NjMyLCAweDNhNzQ0ZTNhLCAweDBhMTQxZTBhLFxuICAgIDB4NDk5MmRiNDksIDB4MDYwYzBhMDYsIDB4MjQ0ODZjMjQsIDB4NWNiOGU0NWMsXG4gICAgMHhjMjlmNWRjMiwgMHhkM2JkNmVkMywgMHhhYzQzZWZhYywgMHg2MmM0YTY2MixcbiAgICAweDkxMzlhODkxLCAweDk1MzFhNDk1LCAweGU0ZDMzN2U0LCAweDc5ZjI4Yjc5LFxuICAgIDB4ZTdkNTMyZTcsIDB4Yzg4YjQzYzgsIDB4Mzc2ZTU5MzcsIDB4NmRkYWI3NmQsXG4gICAgMHg4ZDAxOGM4ZCwgMHhkNWIxNjRkNSwgMHg0ZTljZDI0ZSwgMHhhOTQ5ZTBhOSxcbiAgICAweDZjZDhiNDZjLCAweDU2YWNmYTU2LCAweGY0ZjMwN2Y0LCAweGVhY2YyNWVhLFxuICAgIDB4NjVjYWFmNjUsIDB4N2FmNDhlN2EsIDB4YWU0N2U5YWUsIDB4MDgxMDE4MDgsXG4gICAgMHhiYTZmZDViYSwgMHg3OGYwODg3OCwgMHgyNTRhNmYyNSwgMHgyZTVjNzIyZSxcbiAgICAweDFjMzgyNDFjLCAweGE2NTdmMWE2LCAweGI0NzNjN2I0LCAweGM2OTc1MWM2LFxuICAgIDB4ZThjYjIzZTgsIDB4ZGRhMTdjZGQsIDB4NzRlODljNzQsIDB4MWYzZTIxMWYsXG4gICAgMHg0Yjk2ZGQ0YiwgMHhiZDYxZGNiZCwgMHg4YjBkODY4YiwgMHg4YTBmODU4YSxcbiAgICAweDcwZTA5MDcwLCAweDNlN2M0MjNlLCAweGI1NzFjNGI1LCAweDY2Y2NhYTY2LFxuICAgIDB4NDg5MGQ4NDgsIDB4MDMwNjA1MDMsIDB4ZjZmNzAxZjYsIDB4MGUxYzEyMGUsXG4gICAgMHg2MWMyYTM2MSwgMHgzNTZhNWYzNSwgMHg1N2FlZjk1NywgMHhiOTY5ZDBiOSxcbiAgICAweDg2MTc5MTg2LCAweGMxOTk1OGMxLCAweDFkM2EyNzFkLCAweDllMjdiOTllLFxuICAgIDB4ZTFkOTM4ZTEsIDB4ZjhlYjEzZjgsIDB4OTgyYmIzOTgsIDB4MTEyMjMzMTEsXG4gICAgMHg2OWQyYmI2OSwgMHhkOWE5NzBkOSwgMHg4ZTA3ODk4ZSwgMHg5NDMzYTc5NCxcbiAgICAweDliMmRiNjliLCAweDFlM2MyMjFlLCAweDg3MTU5Mjg3LCAweGU5YzkyMGU5LFxuICAgIDB4Y2U4NzQ5Y2UsIDB4NTVhYWZmNTUsIDB4Mjg1MDc4MjgsIDB4ZGZhNTdhZGYsXG4gICAgMHg4YzAzOGY4YywgMHhhMTU5ZjhhMSwgMHg4OTA5ODA4OSwgMHgwZDFhMTcwZCxcbiAgICAweGJmNjVkYWJmLCAweGU2ZDczMWU2LCAweDQyODRjNjQyLCAweDY4ZDBiODY4LFxuICAgIDB4NDE4MmMzNDEsIDB4OTkyOWIwOTksIDB4MmQ1YTc3MmQsIDB4MGYxZTExMGYsXG4gICAgMHhiMDdiY2JiMCwgMHg1NGE4ZmM1NCwgMHhiYjZkZDZiYiwgMHgxNjJjM2ExNlxuXTtcblxudmFyIFQ0ID0gW1xuICAgIDB4YzZhNTYzNjMsIDB4Zjg4NDdjN2MsIDB4ZWU5OTc3NzcsIDB4ZjY4ZDdiN2IsXG4gICAgMHhmZjBkZjJmMiwgMHhkNmJkNmI2YiwgMHhkZWIxNmY2ZiwgMHg5MTU0YzVjNSxcbiAgICAweDYwNTAzMDMwLCAweDAyMDMwMTAxLCAweGNlYTk2NzY3LCAweDU2N2QyYjJiLFxuICAgIDB4ZTcxOWZlZmUsIDB4YjU2MmQ3ZDcsIDB4NGRlNmFiYWIsIDB4ZWM5YTc2NzYsXG4gICAgMHg4ZjQ1Y2FjYSwgMHgxZjlkODI4MiwgMHg4OTQwYzljOSwgMHhmYTg3N2Q3ZCxcbiAgICAweGVmMTVmYWZhLCAweGIyZWI1OTU5LCAweDhlYzk0NzQ3LCAweGZiMGJmMGYwLFxuICAgIDB4NDFlY2FkYWQsIDB4YjM2N2Q0ZDQsIDB4NWZmZGEyYTIsIDB4NDVlYWFmYWYsXG4gICAgMHgyM2JmOWM5YywgMHg1M2Y3YTRhNCwgMHhlNDk2NzI3MiwgMHg5YjViYzBjMCxcbiAgICAweDc1YzJiN2I3LCAweGUxMWNmZGZkLCAweDNkYWU5MzkzLCAweDRjNmEyNjI2LFxuICAgIDB4NmM1YTM2MzYsIDB4N2U0MTNmM2YsIDB4ZjUwMmY3ZjcsIDB4ODM0ZmNjY2MsXG4gICAgMHg2ODVjMzQzNCwgMHg1MWY0YTVhNSwgMHhkMTM0ZTVlNSwgMHhmOTA4ZjFmMSxcbiAgICAweGUyOTM3MTcxLCAweGFiNzNkOGQ4LCAweDYyNTMzMTMxLCAweDJhM2YxNTE1LFxuICAgIDB4MDgwYzA0MDQsIDB4OTU1MmM3YzcsIDB4NDY2NTIzMjMsIDB4OWQ1ZWMzYzMsXG4gICAgMHgzMDI4MTgxOCwgMHgzN2ExOTY5NiwgMHgwYTBmMDUwNSwgMHgyZmI1OWE5YSxcbiAgICAweDBlMDkwNzA3LCAweDI0MzYxMjEyLCAweDFiOWI4MDgwLCAweGRmM2RlMmUyLFxuICAgIDB4Y2QyNmViZWIsIDB4NGU2OTI3MjcsIDB4N2ZjZGIyYjIsIDB4ZWE5Zjc1NzUsXG4gICAgMHgxMjFiMDkwOSwgMHgxZDllODM4MywgMHg1ODc0MmMyYywgMHgzNDJlMWExYSxcbiAgICAweDM2MmQxYjFiLCAweGRjYjI2ZTZlLCAweGI0ZWU1YTVhLCAweDViZmJhMGEwLFxuICAgIDB4YTRmNjUyNTIsIDB4NzY0ZDNiM2IsIDB4Yjc2MWQ2ZDYsIDB4N2RjZWIzYjMsXG4gICAgMHg1MjdiMjkyOSwgMHhkZDNlZTNlMywgMHg1ZTcxMmYyZiwgMHgxMzk3ODQ4NCxcbiAgICAweGE2ZjU1MzUzLCAweGI5NjhkMWQxLCAweDAwMDAwMDAwLCAweGMxMmNlZGVkLFxuICAgIDB4NDA2MDIwMjAsIDB4ZTMxZmZjZmMsIDB4NzljOGIxYjEsIDB4YjZlZDViNWIsXG4gICAgMHhkNGJlNmE2YSwgMHg4ZDQ2Y2JjYiwgMHg2N2Q5YmViZSwgMHg3MjRiMzkzOSxcbiAgICAweDk0ZGU0YTRhLCAweDk4ZDQ0YzRjLCAweGIwZTg1ODU4LCAweDg1NGFjZmNmLFxuICAgIDB4YmI2YmQwZDAsIDB4YzUyYWVmZWYsIDB4NGZlNWFhYWEsIDB4ZWQxNmZiZmIsXG4gICAgMHg4NmM1NDM0MywgMHg5YWQ3NGQ0ZCwgMHg2NjU1MzMzMywgMHgxMTk0ODU4NSxcbiAgICAweDhhY2Y0NTQ1LCAweGU5MTBmOWY5LCAweDA0MDYwMjAyLCAweGZlODE3ZjdmLFxuICAgIDB4YTBmMDUwNTAsIDB4Nzg0NDNjM2MsIDB4MjViYTlmOWYsIDB4NGJlM2E4YTgsXG4gICAgMHhhMmYzNTE1MSwgMHg1ZGZlYTNhMywgMHg4MGMwNDA0MCwgMHgwNThhOGY4ZixcbiAgICAweDNmYWQ5MjkyLCAweDIxYmM5ZDlkLCAweDcwNDgzODM4LCAweGYxMDRmNWY1LFxuICAgIDB4NjNkZmJjYmMsIDB4NzdjMWI2YjYsIDB4YWY3NWRhZGEsIDB4NDI2MzIxMjEsXG4gICAgMHgyMDMwMTAxMCwgMHhlNTFhZmZmZiwgMHhmZDBlZjNmMywgMHhiZjZkZDJkMixcbiAgICAweDgxNGNjZGNkLCAweDE4MTQwYzBjLCAweDI2MzUxMzEzLCAweGMzMmZlY2VjLFxuICAgIDB4YmVlMTVmNWYsIDB4MzVhMjk3OTcsIDB4ODhjYzQ0NDQsIDB4MmUzOTE3MTcsXG4gICAgMHg5MzU3YzRjNCwgMHg1NWYyYTdhNywgMHhmYzgyN2U3ZSwgMHg3YTQ3M2QzZCxcbiAgICAweGM4YWM2NDY0LCAweGJhZTc1ZDVkLCAweDMyMmIxOTE5LCAweGU2OTU3MzczLFxuICAgIDB4YzBhMDYwNjAsIDB4MTk5ODgxODEsIDB4OWVkMTRmNGYsIDB4YTM3ZmRjZGMsXG4gICAgMHg0NDY2MjIyMiwgMHg1NDdlMmEyYSwgMHgzYmFiOTA5MCwgMHgwYjgzODg4OCxcbiAgICAweDhjY2E0NjQ2LCAweGM3MjllZWVlLCAweDZiZDNiOGI4LCAweDI4M2MxNDE0LFxuICAgIDB4YTc3OWRlZGUsIDB4YmNlMjVlNWUsIDB4MTYxZDBiMGIsIDB4YWQ3NmRiZGIsXG4gICAgMHhkYjNiZTBlMCwgMHg2NDU2MzIzMiwgMHg3NDRlM2EzYSwgMHgxNDFlMGEwYSxcbiAgICAweDkyZGI0OTQ5LCAweDBjMGEwNjA2LCAweDQ4NmMyNDI0LCAweGI4ZTQ1YzVjLFxuICAgIDB4OWY1ZGMyYzIsIDB4YmQ2ZWQzZDMsIDB4NDNlZmFjYWMsIDB4YzRhNjYyNjIsXG4gICAgMHgzOWE4OTE5MSwgMHgzMWE0OTU5NSwgMHhkMzM3ZTRlNCwgMHhmMjhiNzk3OSxcbiAgICAweGQ1MzJlN2U3LCAweDhiNDNjOGM4LCAweDZlNTkzNzM3LCAweGRhYjc2ZDZkLFxuICAgIDB4MDE4YzhkOGQsIDB4YjE2NGQ1ZDUsIDB4OWNkMjRlNGUsIDB4NDllMGE5YTksXG4gICAgMHhkOGI0NmM2YywgMHhhY2ZhNTY1NiwgMHhmMzA3ZjRmNCwgMHhjZjI1ZWFlYSxcbiAgICAweGNhYWY2NTY1LCAweGY0OGU3YTdhLCAweDQ3ZTlhZWFlLCAweDEwMTgwODA4LFxuICAgIDB4NmZkNWJhYmEsIDB4ZjA4ODc4NzgsIDB4NGE2ZjI1MjUsIDB4NWM3MjJlMmUsXG4gICAgMHgzODI0MWMxYywgMHg1N2YxYTZhNiwgMHg3M2M3YjRiNCwgMHg5NzUxYzZjNixcbiAgICAweGNiMjNlOGU4LCAweGExN2NkZGRkLCAweGU4OWM3NDc0LCAweDNlMjExZjFmLFxuICAgIDB4OTZkZDRiNGIsIDB4NjFkY2JkYmQsIDB4MGQ4NjhiOGIsIDB4MGY4NThhOGEsXG4gICAgMHhlMDkwNzA3MCwgMHg3YzQyM2UzZSwgMHg3MWM0YjViNSwgMHhjY2FhNjY2NixcbiAgICAweDkwZDg0ODQ4LCAweDA2MDUwMzAzLCAweGY3MDFmNmY2LCAweDFjMTIwZTBlLFxuICAgIDB4YzJhMzYxNjEsIDB4NmE1ZjM1MzUsIDB4YWVmOTU3NTcsIDB4NjlkMGI5YjksXG4gICAgMHgxNzkxODY4NiwgMHg5OTU4YzFjMSwgMHgzYTI3MWQxZCwgMHgyN2I5OWU5ZSxcbiAgICAweGQ5MzhlMWUxLCAweGViMTNmOGY4LCAweDJiYjM5ODk4LCAweDIyMzMxMTExLFxuICAgIDB4ZDJiYjY5NjksIDB4YTk3MGQ5ZDksIDB4MDc4OThlOGUsIDB4MzNhNzk0OTQsXG4gICAgMHgyZGI2OWI5YiwgMHgzYzIyMWUxZSwgMHgxNTkyODc4NywgMHhjOTIwZTllOSxcbiAgICAweDg3NDljZWNlLCAweGFhZmY1NTU1LCAweDUwNzgyODI4LCAweGE1N2FkZmRmLFxuICAgIDB4MDM4ZjhjOGMsIDB4NTlmOGExYTEsIDB4MDk4MDg5ODksIDB4MWExNzBkMGQsXG4gICAgMHg2NWRhYmZiZiwgMHhkNzMxZTZlNiwgMHg4NGM2NDI0MiwgMHhkMGI4Njg2OCxcbiAgICAweDgyYzM0MTQxLCAweDI5YjA5OTk5LCAweDVhNzcyZDJkLCAweDFlMTEwZjBmLFxuICAgIDB4N2JjYmIwYjAsIDB4YThmYzU0NTQsIDB4NmRkNmJiYmIsIDB4MmMzYTE2MTZcbl07XG5cbmZ1bmN0aW9uIEIwKHgpIHtcbiAgcmV0dXJuICh4ICYgMjU1KTtcbn1cblxuZnVuY3Rpb24gQjEoeCkge1xuICByZXR1cm4gKCh4ID4+IDgpICYgMjU1KTtcbn1cblxuZnVuY3Rpb24gQjIoeCkge1xuICByZXR1cm4gKCh4ID4+IDE2KSAmIDI1NSk7XG59XG5cbmZ1bmN0aW9uIEIzKHgpIHtcbiAgcmV0dXJuICgoeCA+PiAyNCkgJiAyNTUpO1xufVxuXG5mdW5jdGlvbiBGMSh4MCwgeDEsIHgyLCB4Mykge1xuICByZXR1cm4gQjEoVDFbeDAgJiAyNTVdKSB8IChCMShUMVsoeDEgPj4gOCkgJiAyNTVdKSA8PCA4KSB8IChCMShUMVsoeDIgPj4gMTYpICYgMjU1XSkgPDwgMTYpIHwgKEIxKFQxW3gzID4+PiAyNF0pIDw8XG4gICAgMjQpO1xufVxuXG5mdW5jdGlvbiBwYWNrQnl0ZXMob2N0ZXRzKSB7XG4gIHZhciBpLCBqO1xuICB2YXIgbGVuID0gb2N0ZXRzLmxlbmd0aDtcbiAgdmFyIGIgPSBuZXcgQXJyYXkobGVuIC8gNCk7XG5cbiAgaWYgKCFvY3RldHMgfHwgbGVuICUgNCkgcmV0dXJuO1xuXG4gIGZvciAoaSA9IDAsIGogPSAwOyBqIDwgbGVuOyBqICs9IDQpXG4gICAgYltpKytdID0gb2N0ZXRzW2pdIHwgKG9jdGV0c1tqICsgMV0gPDwgOCkgfCAob2N0ZXRzW2ogKyAyXSA8PCAxNikgfCAob2N0ZXRzW2ogKyAzXSA8PCAyNCk7XG5cbiAgcmV0dXJuIGI7XG59XG5cbmZ1bmN0aW9uIHVucGFja0J5dGVzKHBhY2tlZCkge1xuICB2YXIgajtcbiAgdmFyIGkgPSAwLFxuICAgIGwgPSBwYWNrZWQubGVuZ3RoO1xuICB2YXIgciA9IG5ldyBBcnJheShsICogNCk7XG5cbiAgZm9yIChqID0gMDsgaiA8IGw7IGorKykge1xuICAgIHJbaSsrXSA9IEIwKHBhY2tlZFtqXSk7XG4gICAgcltpKytdID0gQjEocGFja2VkW2pdKTtcbiAgICByW2krK10gPSBCMihwYWNrZWRbal0pO1xuICAgIHJbaSsrXSA9IEIzKHBhY2tlZFtqXSk7XG4gIH1cbiAgcmV0dXJuIHI7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG52YXIgbWF4a2MgPSA4O1xudmFyIG1heHJrID0gMTQ7XG5cbmZ1bmN0aW9uIGtleUV4cGFuc2lvbihrZXkpIHtcbiAgdmFyIGtjLCBpLCBqLCByLCB0O1xuICB2YXIgcm91bmRzO1xuICB2YXIga2V5U2NoZWQgPSBuZXcgQXJyYXkobWF4cmsgKyAxKTtcbiAgdmFyIGtleWxlbiA9IGtleS5sZW5ndGg7XG4gIHZhciBrID0gbmV3IEFycmF5KG1heGtjKTtcbiAgdmFyIHRrID0gbmV3IEFycmF5KG1heGtjKTtcbiAgdmFyIHJjb25wb2ludGVyID0gMDtcblxuICBpZiAoa2V5bGVuID09IDE2KSB7XG4gICAgcm91bmRzID0gMTA7XG4gICAga2MgPSA0O1xuICB9IGVsc2UgaWYgKGtleWxlbiA9PSAyNCkge1xuICAgIHJvdW5kcyA9IDEyO1xuICAgIGtjID0gNjtcbiAgfSBlbHNlIGlmIChrZXlsZW4gPT0gMzIpIHtcbiAgICByb3VuZHMgPSAxNDtcbiAgICBrYyA9IDg7XG4gIH0gZWxzZSB7XG4gICAgdXRpbC5wcmludF9lcnJvcignYWVzLmpzOiBJbnZhbGlkIGtleS1sZW5ndGggZm9yIEFFUyBrZXk6JyArIGtleWxlbik7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgZm9yIChpID0gMDsgaSA8IG1heHJrICsgMTsgaSsrKSBrZXlTY2hlZFtpXSA9IG5ldyBBcnJheSg0KTtcblxuICBmb3IgKGkgPSAwLCBqID0gMDsgaiA8IGtleWxlbjsgaisrLCBpICs9IDQpXG4gICAga1tqXSA9IGtleS5jaGFyQ29kZUF0KGkpIHwgKGtleS5jaGFyQ29kZUF0KGkgKyAxKSA8PCA4KSB8IChrZXkuY2hhckNvZGVBdChpICsgMikgPDwgMTYpIHwgKGtleS5jaGFyQ29kZUF0KGkgKyAzKSA8PFxuICAgICAgMjQpO1xuXG4gIGZvciAoaiA9IGtjIC0gMTsgaiA+PSAwOyBqLS0pIHRrW2pdID0ga1tqXTtcblxuICByID0gMDtcbiAgdCA9IDA7XG4gIGZvciAoaiA9IDA7XG4gIChqIDwga2MpICYmIChyIDwgcm91bmRzICsgMSk7KSB7XG4gICAgZm9yICg7XG4gICAgKGogPCBrYykgJiYgKHQgPCA0KTsgaisrLCB0KyspIHtcbiAgICAgIGtleVNjaGVkW3JdW3RdID0gdGtbal07XG4gICAgfVxuICAgIGlmICh0ID09IDQpIHtcbiAgICAgIHIrKztcbiAgICAgIHQgPSAwO1xuICAgIH1cbiAgfVxuXG4gIHdoaWxlIChyIDwgcm91bmRzICsgMSkge1xuICAgIHZhciB0ZW1wID0gdGtba2MgLSAxXTtcblxuICAgIHRrWzBdIF49IFNbQjEodGVtcCldIHwgKFNbQjIodGVtcCldIDw8IDgpIHwgKFNbQjModGVtcCldIDw8IDE2KSB8IChTW0IwKHRlbXApXSA8PCAyNCk7XG4gICAgdGtbMF0gXj0gUmNvbltyY29ucG9pbnRlcisrXTtcblxuICAgIGlmIChrYyAhPSA4KSB7XG4gICAgICBmb3IgKGogPSAxOyBqIDwga2M7IGorKykgdGtbal0gXj0gdGtbaiAtIDFdO1xuICAgIH0gZWxzZSB7XG4gICAgICBmb3IgKGogPSAxOyBqIDwga2MgLyAyOyBqKyspIHRrW2pdIF49IHRrW2ogLSAxXTtcblxuICAgICAgdGVtcCA9IHRrW2tjIC8gMiAtIDFdO1xuICAgICAgdGtba2MgLyAyXSBePSBTW0IwKHRlbXApXSB8IChTW0IxKHRlbXApXSA8PCA4KSB8IChTW0IyKHRlbXApXSA8PCAxNikgfCAoU1tCMyh0ZW1wKV0gPDwgMjQpO1xuXG4gICAgICBmb3IgKGogPSBrYyAvIDIgKyAxOyBqIDwga2M7IGorKykgdGtbal0gXj0gdGtbaiAtIDFdO1xuICAgIH1cblxuICAgIGZvciAoaiA9IDA7XG4gICAgKGogPCBrYykgJiYgKHIgPCByb3VuZHMgKyAxKTspIHtcbiAgICAgIGZvciAoO1xuICAgICAgKGogPCBrYykgJiYgKHQgPCA0KTsgaisrLCB0KyspIHtcbiAgICAgICAga2V5U2NoZWRbcl1bdF0gPSB0a1tqXTtcbiAgICAgIH1cbiAgICAgIGlmICh0ID09IDQpIHtcbiAgICAgICAgcisrO1xuICAgICAgICB0ID0gMDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdGhpcy5yb3VuZHMgPSByb3VuZHM7XG4gIHRoaXMucmsgPSBrZXlTY2hlZDtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbmZ1bmN0aW9uIEFFU2VuY3J5cHQoYmxvY2ssIGN0eCkge1xuICB2YXIgcjtcbiAgdmFyIHQwLCB0MSwgdDIsIHQzO1xuXG4gIHZhciBiID0gcGFja0J5dGVzKGJsb2NrKTtcbiAgdmFyIHJvdW5kcyA9IGN0eC5yb3VuZHM7XG4gIHZhciBiMCA9IGJbMF07XG4gIHZhciBiMSA9IGJbMV07XG4gIHZhciBiMiA9IGJbMl07XG4gIHZhciBiMyA9IGJbM107XG5cbiAgZm9yIChyID0gMDsgciA8IHJvdW5kcyAtIDE7IHIrKykge1xuICAgIHQwID0gYjAgXiBjdHgucmtbcl1bMF07XG4gICAgdDEgPSBiMSBeIGN0eC5ya1tyXVsxXTtcbiAgICB0MiA9IGIyIF4gY3R4LnJrW3JdWzJdO1xuICAgIHQzID0gYjMgXiBjdHgucmtbcl1bM107XG5cbiAgICBiMCA9IFQxW3QwICYgMjU1XSBeIFQyWyh0MSA+PiA4KSAmIDI1NV0gXiBUM1sodDIgPj4gMTYpICYgMjU1XSBeIFQ0W3QzID4+PiAyNF07XG4gICAgYjEgPSBUMVt0MSAmIDI1NV0gXiBUMlsodDIgPj4gOCkgJiAyNTVdIF4gVDNbKHQzID4+IDE2KSAmIDI1NV0gXiBUNFt0MCA+Pj4gMjRdO1xuICAgIGIyID0gVDFbdDIgJiAyNTVdIF4gVDJbKHQzID4+IDgpICYgMjU1XSBeIFQzWyh0MCA+PiAxNikgJiAyNTVdIF4gVDRbdDEgPj4+IDI0XTtcbiAgICBiMyA9IFQxW3QzICYgMjU1XSBeIFQyWyh0MCA+PiA4KSAmIDI1NV0gXiBUM1sodDEgPj4gMTYpICYgMjU1XSBeIFQ0W3QyID4+PiAyNF07XG4gIH1cblxuICAvLyBsYXN0IHJvdW5kIGlzIHNwZWNpYWxcbiAgciA9IHJvdW5kcyAtIDE7XG5cbiAgdDAgPSBiMCBeIGN0eC5ya1tyXVswXTtcbiAgdDEgPSBiMSBeIGN0eC5ya1tyXVsxXTtcbiAgdDIgPSBiMiBeIGN0eC5ya1tyXVsyXTtcbiAgdDMgPSBiMyBeIGN0eC5ya1tyXVszXTtcblxuICBiWzBdID0gRjEodDAsIHQxLCB0MiwgdDMpIF4gY3R4LnJrW3JvdW5kc11bMF07XG4gIGJbMV0gPSBGMSh0MSwgdDIsIHQzLCB0MCkgXiBjdHgucmtbcm91bmRzXVsxXTtcbiAgYlsyXSA9IEYxKHQyLCB0MywgdDAsIHQxKSBeIGN0eC5ya1tyb3VuZHNdWzJdO1xuICBiWzNdID0gRjEodDMsIHQwLCB0MSwgdDIpIF4gY3R4LnJrW3JvdW5kc11bM107XG5cbiAgcmV0dXJuIHVucGFja0J5dGVzKGIpO1xufVxuXG5mdW5jdGlvbiBtYWtlQ2xhc3MobGVuZ3RoKSB7XG5cbiAgdmFyIGMgPSBmdW5jdGlvbihrZXkpIHtcbiAgICB0aGlzLmtleSA9IGtleUV4cGFuc2lvbihrZXkpO1xuXG4gICAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oYmxvY2spIHtcbiAgICAgIHJldHVybiBBRVNlbmNyeXB0KGJsb2NrLCB0aGlzLmtleSk7XG4gICAgfVxuICB9XG5cbiAgYy5ibG9ja1NpemUgPSBjLnByb3RvdHlwZS5ibG9ja1NpemUgPSAxNjtcbiAgYy5rZXlTaXplID0gYy5wcm90b3R5cGUua2V5U2l6ZSA9IGxlbmd0aCAvIDg7XG5cbiAgcmV0dXJuIGM7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge31cblxudmFyIHR5cGVzID0gWzEyOCwgMTkyLCAyNTZdO1xuXG5mb3IgKHZhciBpIGluIHR5cGVzKSB7XG4gIG1vZHVsZS5leHBvcnRzW3R5cGVzW2ldXSA9IG1ha2VDbGFzcyh0eXBlc1tpXSk7XG59XG4iLCIvKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkggXG4gKiBcbiAqIE9yaWdpbmFsbHkgd3JpdHRlbiBieSBua2xlaW4gc29mdHdhcmUgKG5rbGVpbi5jb20pXG4gKi9cblxuLyogXG4gKiBKYXZhc2NyaXB0IGltcGxlbWVudGF0aW9uIGJhc2VkIG9uIEJydWNlIFNjaG5laWVyJ3MgcmVmZXJlbmNlIGltcGxlbWVudGF0aW9uLlxuICpcbiAqXG4gKiBUaGUgY29uc3RydWN0b3IgZG9lc24ndCBkbyBtdWNoIG9mIGFueXRoaW5nLiAgSXQncyBqdXN0IGhlcmVcbiAqIHNvIHdlIGNhbiBzdGFydCBkZWZpbmluZyBwcm9wZXJ0aWVzIGFuZCBtZXRob2RzIGFuZCBzdWNoLlxuICovXG5mdW5jdGlvbiBCbG93ZmlzaCgpIHt9O1xuXG4vKlxuICogRGVjbGFyZSB0aGUgYmxvY2sgc2l6ZSBzbyB0aGF0IHByb3RvY29scyBrbm93IHdoYXQgc2l6ZVxuICogSW5pdGlhbGl6YXRpb24gVmVjdG9yIChJVikgdGhleSB3aWxsIG5lZWQuXG4gKi9cbkJsb3dmaXNoLnByb3RvdHlwZS5CTE9DS1NJWkUgPSA4O1xuXG4vKlxuICogVGhlc2UgYXJlIHRoZSBkZWZhdWx0IFNCT1hFUy5cbiAqL1xuQmxvd2Zpc2gucHJvdG90eXBlLlNCT1hFUyA9IFtcbiAgW1xuICAgICAgMHhkMTMxMGJhNiwgMHg5OGRmYjVhYywgMHgyZmZkNzJkYiwgMHhkMDFhZGZiNywgMHhiOGUxYWZlZCwgMHg2YTI2N2U5NixcbiAgICAgIDB4YmE3YzkwNDUsIDB4ZjEyYzdmOTksIDB4MjRhMTk5NDcsIDB4YjM5MTZjZjcsIDB4MDgwMWYyZTIsIDB4ODU4ZWZjMTYsXG4gICAgICAweDYzNjkyMGQ4LCAweDcxNTc0ZTY5LCAweGE0NThmZWEzLCAweGY0OTMzZDdlLCAweDBkOTU3NDhmLCAweDcyOGViNjU4LFxuICAgICAgMHg3MThiY2Q1OCwgMHg4MjE1NGFlZSwgMHg3YjU0YTQxZCwgMHhjMjVhNTliNSwgMHg5YzMwZDUzOSwgMHgyYWYyNjAxMyxcbiAgICAgIDB4YzVkMWIwMjMsIDB4Mjg2MDg1ZjAsIDB4Y2E0MTc5MTgsIDB4YjhkYjM4ZWYsIDB4OGU3OWRjYjAsIDB4NjAzYTE4MGUsXG4gICAgICAweDZjOWUwZThiLCAweGIwMWU4YTNlLCAweGQ3MTU3N2MxLCAweGJkMzE0YjI3LCAweDc4YWYyZmRhLCAweDU1NjA1YzYwLFxuICAgICAgMHhlNjU1MjVmMywgMHhhYTU1YWI5NCwgMHg1NzQ4OTg2MiwgMHg2M2U4MTQ0MCwgMHg1NWNhMzk2YSwgMHgyYWFiMTBiNixcbiAgICAgIDB4YjRjYzVjMzQsIDB4MTE0MWU4Y2UsIDB4YTE1NDg2YWYsIDB4N2M3MmU5OTMsIDB4YjNlZTE0MTEsIDB4NjM2ZmJjMmEsXG4gICAgICAweDJiYTljNTVkLCAweDc0MTgzMWY2LCAweGNlNWMzZTE2LCAweDliODc5MzFlLCAweGFmZDZiYTMzLCAweDZjMjRjZjVjLFxuICAgICAgMHg3YTMyNTM4MSwgMHgyODk1ODY3NywgMHgzYjhmNDg5OCwgMHg2YjRiYjlhZiwgMHhjNGJmZTgxYiwgMHg2NjI4MjE5MyxcbiAgICAgIDB4NjFkODA5Y2MsIDB4ZmIyMWE5OTEsIDB4NDg3Y2FjNjAsIDB4NWRlYzgwMzIsIDB4ZWY4NDVkNWQsIDB4ZTk4NTc1YjEsXG4gICAgICAweGRjMjYyMzAyLCAweGViNjUxYjg4LCAweDIzODkzZTgxLCAweGQzOTZhY2M1LCAweDBmNmQ2ZmYzLCAweDgzZjQ0MjM5LFxuICAgICAgMHgyZTBiNDQ4MiwgMHhhNDg0MjAwNCwgMHg2OWM4ZjA0YSwgMHg5ZTFmOWI1ZSwgMHgyMWM2Njg0MiwgMHhmNmU5NmM5YSxcbiAgICAgIDB4NjcwYzljNjEsIDB4YWJkMzg4ZjAsIDB4NmE1MWEwZDIsIDB4ZDg1NDJmNjgsIDB4OTYwZmE3MjgsIDB4YWI1MTMzYTMsXG4gICAgICAweDZlZWYwYjZjLCAweDEzN2EzYmU0LCAweGJhM2JmMDUwLCAweDdlZmIyYTk4LCAweGExZjE2NTFkLCAweDM5YWYwMTc2LFxuICAgICAgMHg2NmNhNTkzZSwgMHg4MjQzMGU4OCwgMHg4Y2VlODYxOSwgMHg0NTZmOWZiNCwgMHg3ZDg0YTVjMywgMHgzYjhiNWViZSxcbiAgICAgIDB4ZTA2Zjc1ZDgsIDB4ODVjMTIwNzMsIDB4NDAxYTQ0OWYsIDB4NTZjMTZhYTYsIDB4NGVkM2FhNjIsIDB4MzYzZjc3MDYsXG4gICAgICAweDFiZmVkZjcyLCAweDQyOWIwMjNkLCAweDM3ZDBkNzI0LCAweGQwMGExMjQ4LCAweGRiMGZlYWQzLCAweDQ5ZjFjMDliLFxuICAgICAgMHgwNzUzNzJjOSwgMHg4MDk5MWI3YiwgMHgyNWQ0NzlkOCwgMHhmNmU4ZGVmNywgMHhlM2ZlNTAxYSwgMHhiNjc5NGMzYixcbiAgICAgIDB4OTc2Y2UwYmQsIDB4MDRjMDA2YmEsIDB4YzFhOTRmYjYsIDB4NDA5ZjYwYzQsIDB4NWU1YzllYzIsIDB4MTk2YTI0NjMsXG4gICAgICAweDY4ZmI2ZmFmLCAweDNlNmM1M2I1LCAweDEzMzliMmViLCAweDNiNTJlYzZmLCAweDZkZmM1MTFmLCAweDliMzA5NTJjLFxuICAgICAgMHhjYzgxNDU0NCwgMHhhZjVlYmQwOSwgMHhiZWUzZDAwNCwgMHhkZTMzNGFmZCwgMHg2NjBmMjgwNywgMHgxOTJlNGJiMyxcbiAgICAgIDB4YzBjYmE4NTcsIDB4NDVjODc0MGYsIDB4ZDIwYjVmMzksIDB4YjlkM2ZiZGIsIDB4NTU3OWMwYmQsIDB4MWE2MDMyMGEsXG4gICAgICAweGQ2YTEwMGM2LCAweDQwMmM3Mjc5LCAweDY3OWYyNWZlLCAweGZiMWZhM2NjLCAweDhlYTVlOWY4LCAweGRiMzIyMmY4LFxuICAgICAgMHgzYzc1MTZkZiwgMHhmZDYxNmIxNSwgMHgyZjUwMWVjOCwgMHhhZDA1NTJhYiwgMHgzMjNkYjVmYSwgMHhmZDIzODc2MCxcbiAgICAgIDB4NTMzMTdiNDgsIDB4M2UwMGRmODIsIDB4OWU1YzU3YmIsIDB4Y2E2ZjhjYTAsIDB4MWE4NzU2MmUsIDB4ZGYxNzY5ZGIsXG4gICAgICAweGQ1NDJhOGY2LCAweDI4N2VmZmMzLCAweGFjNjczMmM2LCAweDhjNGY1NTczLCAweDY5NWIyN2IwLCAweGJiY2E1OGM4LFxuICAgICAgMHhlMWZmYTM1ZCwgMHhiOGYwMTFhMCwgMHgxMGZhM2Q5OCwgMHhmZDIxODNiOCwgMHg0YWZjYjU2YywgMHgyZGQxZDM1YixcbiAgICAgIDB4OWE1M2U0NzksIDB4YjZmODQ1NjUsIDB4ZDI4ZTQ5YmMsIDB4NGJmYjk3OTAsIDB4ZTFkZGYyZGEsIDB4YTRjYjdlMzMsXG4gICAgICAweDYyZmIxMzQxLCAweGNlZTRjNmU4LCAweGVmMjBjYWRhLCAweDM2Nzc0YzAxLCAweGQwN2U5ZWZlLCAweDJiZjExZmI0LFxuICAgICAgMHg5NWRiZGE0ZCwgMHhhZTkwOTE5OCwgMHhlYWFkOGU3MSwgMHg2YjkzZDVhMCwgMHhkMDhlZDFkMCwgMHhhZmM3MjVlMCxcbiAgICAgIDB4OGUzYzViMmYsIDB4OGU3NTk0YjcsIDB4OGZmNmUyZmIsIDB4ZjIxMjJiNjQsIDB4ODg4OGI4MTIsIDB4OTAwZGYwMWMsXG4gICAgICAweDRmYWQ1ZWEwLCAweDY4OGZjMzFjLCAweGQxY2ZmMTkxLCAweGIzYThjMWFkLCAweDJmMmYyMjE4LCAweGJlMGUxNzc3LFxuICAgICAgMHhlYTc1MmRmZSwgMHg4YjAyMWZhMSwgMHhlNWEwY2MwZiwgMHhiNTZmNzRlOCwgMHgxOGFjZjNkNiwgMHhjZTg5ZTI5OSxcbiAgICAgIDB4YjRhODRmZTAsIDB4ZmQxM2UwYjcsIDB4N2NjNDNiODEsIDB4ZDJhZGE4ZDksIDB4MTY1ZmEyNjYsIDB4ODA5NTc3MDUsXG4gICAgICAweDkzY2M3MzE0LCAweDIxMWExNDc3LCAweGU2YWQyMDY1LCAweDc3YjVmYTg2LCAweGM3NTQ0MmY1LCAweGZiOWQzNWNmLFxuICAgICAgMHhlYmNkYWYwYywgMHg3YjNlODlhMCwgMHhkNjQxMWJkMywgMHhhZTFlN2U0OSwgMHgwMDI1MGUyZCwgMHgyMDcxYjM1ZSxcbiAgICAgIDB4MjI2ODAwYmIsIDB4NTdiOGUwYWYsIDB4MjQ2NDM2OWIsIDB4ZjAwOWI5MWUsIDB4NTU2MzkxMWQsIDB4NTlkZmE2YWEsXG4gICAgICAweDc4YzE0Mzg5LCAweGQ5NWE1MzdmLCAweDIwN2Q1YmEyLCAweDAyZTViOWM1LCAweDgzMjYwMzc2LCAweDYyOTVjZmE5LFxuICAgICAgMHgxMWM4MTk2OCwgMHg0ZTczNGE0MSwgMHhiMzQ3MmRjYSwgMHg3YjE0YTk0YSwgMHgxYjUxMDA1MiwgMHg5YTUzMjkxNSxcbiAgICAgIDB4ZDYwZjU3M2YsIDB4YmM5YmM2ZTQsIDB4MmI2MGE0NzYsIDB4ODFlNjc0MDAsIDB4MDhiYTZmYjUsIDB4NTcxYmU5MWYsXG4gICAgICAweGYyOTZlYzZiLCAweDJhMGRkOTE1LCAweGI2NjM2NTIxLCAweGU3YjlmOWI2LCAweGZmMzQwNTJlLCAweGM1ODU1NjY0LFxuICAgICAgMHg1M2IwMmQ1ZCwgMHhhOTlmOGZhMSwgMHgwOGJhNDc5OSwgMHg2ZTg1MDc2YVxuICBdLFxuICBbXG4gICAgICAweDRiN2E3MGU5LCAweGI1YjMyOTQ0LCAweGRiNzUwOTJlLCAweGM0MTkyNjIzLCAweGFkNmVhNmIwLCAweDQ5YTdkZjdkLFxuICAgICAgMHg5Y2VlNjBiOCwgMHg4ZmVkYjI2NiwgMHhlY2FhOGM3MSwgMHg2OTlhMTdmZiwgMHg1NjY0NTI2YywgMHhjMmIxOWVlMSxcbiAgICAgIDB4MTkzNjAyYTUsIDB4NzUwOTRjMjksIDB4YTA1OTEzNDAsIDB4ZTQxODNhM2UsIDB4M2Y1NDk4OWEsIDB4NWI0MjlkNjUsXG4gICAgICAweDZiOGZlNGQ2LCAweDk5ZjczZmQ2LCAweGExZDI5YzA3LCAweGVmZTgzMGY1LCAweDRkMmQzOGU2LCAweGYwMjU1ZGMxLFxuICAgICAgMHg0Y2RkMjA4NiwgMHg4NDcwZWIyNiwgMHg2MzgyZTljNiwgMHgwMjFlY2M1ZSwgMHgwOTY4NmIzZiwgMHgzZWJhZWZjOSxcbiAgICAgIDB4M2M5NzE4MTQsIDB4NmI2YTcwYTEsIDB4Njg3ZjM1ODQsIDB4NTJhMGUyODYsIDB4Yjc5YzUzMDUsIDB4YWE1MDA3MzcsXG4gICAgICAweDNlMDc4NDFjLCAweDdmZGVhZTVjLCAweDhlN2Q0NGVjLCAweDU3MTZmMmI4LCAweGIwM2FkYTM3LCAweGYwNTAwYzBkLFxuICAgICAgMHhmMDFjMWYwNCwgMHgwMjAwYjNmZiwgMHhhZTBjZjUxYSwgMHgzY2I1NzRiMiwgMHgyNTgzN2E1OCwgMHhkYzA5MjFiZCxcbiAgICAgIDB4ZDE5MTEzZjksIDB4N2NhOTJmZjYsIDB4OTQzMjQ3NzMsIDB4MjJmNTQ3MDEsIDB4M2FlNWU1ODEsIDB4MzdjMmRhZGMsXG4gICAgICAweGM4YjU3NjM0LCAweDlhZjNkZGE3LCAweGE5NDQ2MTQ2LCAweDBmZDAwMzBlLCAweGVjYzhjNzNlLCAweGE0NzUxZTQxLFxuICAgICAgMHhlMjM4Y2Q5OSwgMHgzYmVhMGUyZiwgMHgzMjgwYmJhMSwgMHgxODNlYjMzMSwgMHg0ZTU0OGIzOCwgMHg0ZjZkYjkwOCxcbiAgICAgIDB4NmY0MjBkMDMsIDB4ZjYwYTA0YmYsIDB4MmNiODEyOTAsIDB4MjQ5NzdjNzksIDB4NTY3OWIwNzIsIDB4YmNhZjg5YWYsXG4gICAgICAweGRlOWE3NzFmLCAweGQ5OTMwODEwLCAweGIzOGJhZTEyLCAweGRjY2YzZjJlLCAweDU1MTI3MjFmLCAweDJlNmI3MTI0LFxuICAgICAgMHg1MDFhZGRlNiwgMHg5Zjg0Y2Q4NywgMHg3YTU4NDcxOCwgMHg3NDA4ZGExNywgMHhiYzlmOWFiYywgMHhlOTRiN2Q4YyxcbiAgICAgIDB4ZWM3YWVjM2EsIDB4ZGI4NTFkZmEsIDB4NjMwOTQzNjYsIDB4YzQ2NGMzZDIsIDB4ZWYxYzE4NDcsIDB4MzIxNWQ5MDgsXG4gICAgICAweGRkNDMzYjM3LCAweDI0YzJiYTE2LCAweDEyYTE0ZDQzLCAweDJhNjVjNDUxLCAweDUwOTQwMDAyLCAweDEzM2FlNGRkLFxuICAgICAgMHg3MWRmZjg5ZSwgMHgxMDMxNGU1NSwgMHg4MWFjNzdkNiwgMHg1ZjExMTk5YiwgMHgwNDM1NTZmMSwgMHhkN2EzYzc2YixcbiAgICAgIDB4M2MxMTE4M2IsIDB4NTkyNGE1MDksIDB4ZjI4ZmU2ZWQsIDB4OTdmMWZiZmEsIDB4OWViYWJmMmMsIDB4MWUxNTNjNmUsXG4gICAgICAweDg2ZTM0NTcwLCAweGVhZTk2ZmIxLCAweDg2MGU1ZTBhLCAweDVhM2UyYWIzLCAweDc3MWZlNzFjLCAweDRlM2QwNmZhLFxuICAgICAgMHgyOTY1ZGNiOSwgMHg5OWU3MWQwZiwgMHg4MDNlODlkNiwgMHg1MjY2YzgyNSwgMHgyZTRjYzk3OCwgMHg5YzEwYjM2YSxcbiAgICAgIDB4YzYxNTBlYmEsIDB4OTRlMmVhNzgsIDB4YTVmYzNjNTMsIDB4MWUwYTJkZjQsIDB4ZjJmNzRlYTcsIDB4MzYxZDJiM2QsXG4gICAgICAweDE5MzkyNjBmLCAweDE5YzI3OTYwLCAweDUyMjNhNzA4LCAweGY3MTMxMmI2LCAweGViYWRmZTZlLCAweGVhYzMxZjY2LFxuICAgICAgMHhlM2JjNDU5NSwgMHhhNjdiYzg4MywgMHhiMTdmMzdkMSwgMHgwMThjZmYyOCwgMHhjMzMyZGRlZiwgMHhiZTZjNWFhNSxcbiAgICAgIDB4NjU1ODIxODUsIDB4NjhhYjk4MDIsIDB4ZWVjZWE1MGYsIDB4ZGIyZjk1M2IsIDB4MmFlZjdkYWQsIDB4NWI2ZTJmODQsXG4gICAgICAweDE1MjFiNjI4LCAweDI5MDc2MTcwLCAweGVjZGQ0Nzc1LCAweDYxOWYxNTEwLCAweDEzY2NhODMwLCAweGViNjFiZDk2LFxuICAgICAgMHgwMzM0ZmUxZSwgMHhhYTAzNjNjZiwgMHhiNTczNWM5MCwgMHg0YzcwYTIzOSwgMHhkNTllOWUwYiwgMHhjYmFhZGUxNCxcbiAgICAgIDB4ZWVjYzg2YmMsIDB4NjA2MjJjYTcsIDB4OWNhYjVjYWIsIDB4YjJmMzg0NmUsIDB4NjQ4YjFlYWYsIDB4MTliZGYwY2EsXG4gICAgICAweGEwMjM2OWI5LCAweDY1NWFiYjUwLCAweDQwNjg1YTMyLCAweDNjMmFiNGIzLCAweDMxOWVlOWQ1LCAweGMwMjFiOGY3LFxuICAgICAgMHg5YjU0MGIxOSwgMHg4NzVmYTA5OSwgMHg5NWY3OTk3ZSwgMHg2MjNkN2RhOCwgMHhmODM3ODg5YSwgMHg5N2UzMmQ3NyxcbiAgICAgIDB4MTFlZDkzNWYsIDB4MTY2ODEyODEsIDB4MGUzNTg4MjksIDB4YzdlNjFmZDYsIDB4OTZkZWRmYTEsIDB4Nzg1OGJhOTksXG4gICAgICAweDU3ZjU4NGE1LCAweDFiMjI3MjYzLCAweDliODNjM2ZmLCAweDFhYzI0Njk2LCAweGNkYjMwYWViLCAweDUzMmUzMDU0LFxuICAgICAgMHg4ZmQ5NDhlNCwgMHg2ZGJjMzEyOCwgMHg1OGViZjJlZiwgMHgzNGM2ZmZlYSwgMHhmZTI4ZWQ2MSwgMHhlZTdjM2M3MyxcbiAgICAgIDB4NWQ0YTE0ZDksIDB4ZTg2NGI3ZTMsIDB4NDIxMDVkMTQsIDB4MjAzZTEzZTAsIDB4NDVlZWUyYjYsIDB4YTNhYWFiZWEsXG4gICAgICAweGRiNmM0ZjE1LCAweGZhY2I0ZmQwLCAweGM3NDJmNDQyLCAweGVmNmFiYmI1LCAweDY1NGYzYjFkLCAweDQxY2QyMTA1LFxuICAgICAgMHhkODFlNzk5ZSwgMHg4Njg1NGRjNywgMHhlNDRiNDc2YSwgMHgzZDgxNjI1MCwgMHhjZjYyYTFmMiwgMHg1YjhkMjY0NixcbiAgICAgIDB4ZmM4ODgzYTAsIDB4YzFjN2I2YTMsIDB4N2YxNTI0YzMsIDB4NjljYjc0OTIsIDB4NDc4NDhhMGIsIDB4NTY5MmIyODUsXG4gICAgICAweDA5NWJiZjAwLCAweGFkMTk0ODlkLCAweDE0NjJiMTc0LCAweDIzODIwZTAwLCAweDU4NDI4ZDJhLCAweDBjNTVmNWVhLFxuICAgICAgMHgxZGFkZjQzZSwgMHgyMzNmNzA2MSwgMHgzMzcyZjA5MiwgMHg4ZDkzN2U0MSwgMHhkNjVmZWNmMSwgMHg2YzIyM2JkYixcbiAgICAgIDB4N2NkZTM3NTksIDB4Y2JlZTc0NjAsIDB4NDA4NWYyYTcsIDB4Y2U3NzMyNmUsIDB4YTYwNzgwODQsIDB4MTlmODUwOWUsXG4gICAgICAweGU4ZWZkODU1LCAweDYxZDk5NzM1LCAweGE5NjlhN2FhLCAweGM1MGMwNmMyLCAweDVhMDRhYmZjLCAweDgwMGJjYWRjLFxuICAgICAgMHg5ZTQ0N2EyZSwgMHhjMzQ1MzQ4NCwgMHhmZGQ1NjcwNSwgMHgwZTFlOWVjOSwgMHhkYjczZGJkMywgMHgxMDU1ODhjZCxcbiAgICAgIDB4Njc1ZmRhNzksIDB4ZTM2NzQzNDAsIDB4YzVjNDM0NjUsIDB4NzEzZTM4ZDgsIDB4M2QyOGY4OWUsIDB4ZjE2ZGZmMjAsXG4gICAgICAweDE1M2UyMWU3LCAweDhmYjAzZDRhLCAweGU2ZTM5ZjJiLCAweGRiODNhZGY3XG4gIF0sXG4gIFtcbiAgICAgIDB4ZTkzZDVhNjgsIDB4OTQ4MTQwZjcsIDB4ZjY0YzI2MWMsIDB4OTQ2OTI5MzQsIDB4NDExNTIwZjcsIDB4NzYwMmQ0ZjcsXG4gICAgICAweGJjZjQ2YjJlLCAweGQ0YTIwMDY4LCAweGQ0MDgyNDcxLCAweDMzMjBmNDZhLCAweDQzYjdkNGI3LCAweDUwMDA2MWFmLFxuICAgICAgMHgxZTM5ZjYyZSwgMHg5NzI0NDU0NiwgMHgxNDIxNGY3NCwgMHhiZjhiODg0MCwgMHg0ZDk1ZmMxZCwgMHg5NmI1OTFhZixcbiAgICAgIDB4NzBmNGRkZDMsIDB4NjZhMDJmNDUsIDB4YmZiYzA5ZWMsIDB4MDNiZDk3ODUsIDB4N2ZhYzZkZDAsIDB4MzFjYjg1MDQsXG4gICAgICAweDk2ZWIyN2IzLCAweDU1ZmQzOTQxLCAweGRhMjU0N2U2LCAweGFiY2EwYTlhLCAweDI4NTA3ODI1LCAweDUzMDQyOWY0LFxuICAgICAgMHgwYTJjODZkYSwgMHhlOWI2NmRmYiwgMHg2OGRjMTQ2MiwgMHhkNzQ4NjkwMCwgMHg2ODBlYzBhNCwgMHgyN2ExOGRlZSxcbiAgICAgIDB4NGYzZmZlYTIsIDB4ZTg4N2FkOGMsIDB4YjU4Y2UwMDYsIDB4N2FmNGQ2YjYsIDB4YWFjZTFlN2MsIDB4ZDMzNzVmZWMsXG4gICAgICAweGNlNzhhMzk5LCAweDQwNmIyYTQyLCAweDIwZmU5ZTM1LCAweGQ5ZjM4NWI5LCAweGVlMzlkN2FiLCAweDNiMTI0ZThiLFxuICAgICAgMHgxZGM5ZmFmNywgMHg0YjZkMTg1NiwgMHgyNmEzNjYzMSwgMHhlYWUzOTdiMiwgMHgzYTZlZmE3NCwgMHhkZDViNDMzMixcbiAgICAgIDB4Njg0MWU3ZjcsIDB4Y2E3ODIwZmIsIDB4ZmIwYWY1NGUsIDB4ZDhmZWIzOTcsIDB4NDU0MDU2YWMsIDB4YmE0ODk1MjcsXG4gICAgICAweDU1NTMzYTNhLCAweDIwODM4ZDg3LCAweGZlNmJhOWI3LCAweGQwOTY5NTRiLCAweDU1YTg2N2JjLCAweGExMTU5YTU4LFxuICAgICAgMHhjY2E5Mjk2MywgMHg5OWUxZGIzMywgMHhhNjJhNGE1NiwgMHgzZjMxMjVmOSwgMHg1ZWY0N2UxYywgMHg5MDI5MzE3YyxcbiAgICAgIDB4ZmRmOGU4MDIsIDB4MDQyNzJmNzAsIDB4ODBiYjE1NWMsIDB4MDUyODJjZTMsIDB4OTVjMTE1NDgsIDB4ZTRjNjZkMjIsXG4gICAgICAweDQ4YzExMzNmLCAweGM3MGY4NmRjLCAweDA3ZjljOWVlLCAweDQxMDQxZjBmLCAweDQwNDc3OWE0LCAweDVkODg2ZTE3LFxuICAgICAgMHgzMjVmNTFlYiwgMHhkNTliYzBkMSwgMHhmMmJjYzE4ZiwgMHg0MTExMzU2NCwgMHgyNTdiNzgzNCwgMHg2MDJhOWM2MCxcbiAgICAgIDB4ZGZmOGU4YTMsIDB4MWY2MzZjMWIsIDB4MGUxMmI0YzIsIDB4MDJlMTMyOWUsIDB4YWY2NjRmZDEsIDB4Y2FkMTgxMTUsXG4gICAgICAweDZiMjM5NWUwLCAweDMzM2U5MmUxLCAweDNiMjQwYjYyLCAweGVlYmViOTIyLCAweDg1YjJhMjBlLCAweGU2YmEwZDk5LFxuICAgICAgMHhkZTcyMGM4YywgMHgyZGEyZjcyOCwgMHhkMDEyNzg0NSwgMHg5NWI3OTRmZCwgMHg2NDdkMDg2MiwgMHhlN2NjZjVmMCxcbiAgICAgIDB4NTQ0OWEzNmYsIDB4ODc3ZDQ4ZmEsIDB4YzM5ZGZkMjcsIDB4ZjMzZThkMWUsIDB4MGE0NzYzNDEsIDB4OTkyZWZmNzQsXG4gICAgICAweDNhNmY2ZWFiLCAweGY0ZjhmZDM3LCAweGE4MTJkYzYwLCAweGExZWJkZGY4LCAweDk5MWJlMTRjLCAweGRiNmU2YjBkLFxuICAgICAgMHhjNjdiNTUxMCwgMHg2ZDY3MmMzNywgMHgyNzY1ZDQzYiwgMHhkY2QwZTgwNCwgMHhmMTI5MGRjNywgMHhjYzAwZmZhMyxcbiAgICAgIDB4YjUzOTBmOTIsIDB4NjkwZmVkMGIsIDB4NjY3YjlmZmIsIDB4Y2VkYjdkOWMsIDB4YTA5MWNmMGIsIDB4ZDkxNTVlYTMsXG4gICAgICAweGJiMTMyZjg4LCAweDUxNWJhZDI0LCAweDdiOTQ3OWJmLCAweDc2M2JkNmViLCAweDM3MzkyZWIzLCAweGNjMTE1OTc5LFxuICAgICAgMHg4MDI2ZTI5NywgMHhmNDJlMzEyZCwgMHg2ODQyYWRhNywgMHhjNjZhMmIzYiwgMHgxMjc1NGNjYywgMHg3ODJlZjExYyxcbiAgICAgIDB4NmExMjQyMzcsIDB4Yjc5MjUxZTcsIDB4MDZhMWJiZTYsIDB4NGJmYjYzNTAsIDB4MWE2YjEwMTgsIDB4MTFjYWVkZmEsXG4gICAgICAweDNkMjViZGQ4LCAweGUyZTFjM2M5LCAweDQ0NDIxNjU5LCAweDBhMTIxMzg2LCAweGQ5MGNlYzZlLCAweGQ1YWJlYTJhLFxuICAgICAgMHg2NGFmNjc0ZSwgMHhkYTg2YTg1ZiwgMHhiZWJmZTk4OCwgMHg2NGU0YzNmZSwgMHg5ZGJjODA1NywgMHhmMGY3YzA4NixcbiAgICAgIDB4NjA3ODdiZjgsIDB4NjAwMzYwNGQsIDB4ZDFmZDgzNDYsIDB4ZjYzODFmYjAsIDB4Nzc0NWFlMDQsIDB4ZDczNmZjY2MsXG4gICAgICAweDgzNDI2YjMzLCAweGYwMWVhYjcxLCAweGIwODA0MTg3LCAweDNjMDA1ZTVmLCAweDc3YTA1N2JlLCAweGJkZThhZTI0LFxuICAgICAgMHg1NTQ2NDI5OSwgMHhiZjU4MmU2MSwgMHg0ZTU4ZjQ4ZiwgMHhmMmRkZmRhMiwgMHhmNDc0ZWYzOCwgMHg4Nzg5YmRjMixcbiAgICAgIDB4NTM2NmY5YzMsIDB4YzhiMzhlNzQsIDB4YjQ3NWYyNTUsIDB4NDZmY2Q5YjksIDB4N2FlYjI2NjEsIDB4OGIxZGRmODQsXG4gICAgICAweDg0NmEwZTc5LCAweDkxNWY5NWUyLCAweDQ2NmU1OThlLCAweDIwYjQ1NzcwLCAweDhjZDU1NTkxLCAweGM5MDJkZTRjLFxuICAgICAgMHhiOTBiYWNlMSwgMHhiYjgyMDVkMCwgMHgxMWE4NjI0OCwgMHg3NTc0YTk5ZSwgMHhiNzdmMTliNiwgMHhlMGE5ZGMwOSxcbiAgICAgIDB4NjYyZDA5YTEsIDB4YzQzMjQ2MzMsIDB4ZTg1YTFmMDIsIDB4MDlmMGJlOGMsIDB4NGE5OWEwMjUsIDB4MWQ2ZWZlMTAsXG4gICAgICAweDFhYjkzZDFkLCAweDBiYTVhNGRmLCAweGExODZmMjBmLCAweDI4NjhmMTY5LCAweGRjYjdkYTgzLCAweDU3MzkwNmZlLFxuICAgICAgMHhhMWUyY2U5YiwgMHg0ZmNkN2Y1MiwgMHg1MDExNWUwMSwgMHhhNzA2ODNmYSwgMHhhMDAyYjVjNCwgMHgwZGU2ZDAyNyxcbiAgICAgIDB4OWFmODhjMjcsIDB4NzczZjg2NDEsIDB4YzM2MDRjMDYsIDB4NjFhODA2YjUsIDB4ZjAxNzdhMjgsIDB4YzBmNTg2ZTAsXG4gICAgICAweDAwNjA1OGFhLCAweDMwZGM3ZDYyLCAweDExZTY5ZWQ3LCAweDIzMzhlYTYzLCAweDUzYzJkZDk0LCAweGMyYzIxNjM0LFxuICAgICAgMHhiYmNiZWU1NiwgMHg5MGJjYjZkZSwgMHhlYmZjN2RhMSwgMHhjZTU5MWQ3NiwgMHg2ZjA1ZTQwOSwgMHg0YjdjMDE4OCxcbiAgICAgIDB4Mzk3MjBhM2QsIDB4N2M5MjdjMjQsIDB4ODZlMzcyNWYsIDB4NzI0ZDlkYjksIDB4MWFjMTViYjQsIDB4ZDM5ZWI4ZmMsXG4gICAgICAweGVkNTQ1NTc4LCAweDA4ZmNhNWI1LCAweGQ4M2Q3Y2QzLCAweDRkYWQwZmM0LCAweDFlNTBlZjVlLCAweGIxNjFlNmY4LFxuICAgICAgMHhhMjg1MTRkOSwgMHg2YzUxMTMzYywgMHg2ZmQ1YzdlNywgMHg1NmUxNGVjNCwgMHgzNjJhYmZjZSwgMHhkZGM2YzgzNyxcbiAgICAgIDB4ZDc5YTMyMzQsIDB4OTI2MzgyMTIsIDB4NjcwZWZhOGUsIDB4NDA2MDAwZTBcbiAgXSxcbiAgW1xuICAgICAgMHgzYTM5Y2UzNywgMHhkM2ZhZjVjZiwgMHhhYmMyNzczNywgMHg1YWM1MmQxYiwgMHg1Y2IwNjc5ZSwgMHg0ZmEzMzc0MixcbiAgICAgIDB4ZDM4MjI3NDAsIDB4OTliYzliYmUsIDB4ZDUxMThlOWQsIDB4YmYwZjczMTUsIDB4ZDYyZDFjN2UsIDB4YzcwMGM0N2IsXG4gICAgICAweGI3OGMxYjZiLCAweDIxYTE5MDQ1LCAweGIyNmViMWJlLCAweDZhMzY2ZWI0LCAweDU3NDhhYjJmLCAweGJjOTQ2ZTc5LFxuICAgICAgMHhjNmEzNzZkMiwgMHg2NTQ5YzJjOCwgMHg1MzBmZjhlZSwgMHg0NjhkZGU3ZCwgMHhkNTczMGExZCwgMHg0Y2QwNGRjNixcbiAgICAgIDB4MjkzOWJiZGIsIDB4YTliYTQ2NTAsIDB4YWM5NTI2ZTgsIDB4YmU1ZWUzMDQsIDB4YTFmYWQ1ZjAsIDB4NmEyZDUxOWEsXG4gICAgICAweDYzZWY4Y2UyLCAweDlhODZlZTIyLCAweGMwODljMmI4LCAweDQzMjQyZWY2LCAweGE1MWUwM2FhLCAweDljZjJkMGE0LFxuICAgICAgMHg4M2MwNjFiYSwgMHg5YmU5NmE0ZCwgMHg4ZmU1MTU1MCwgMHhiYTY0NWJkNiwgMHgyODI2YTJmOSwgMHhhNzNhM2FlMSxcbiAgICAgIDB4NGJhOTk1ODYsIDB4ZWY1NTYyZTksIDB4YzcyZmVmZDMsIDB4Zjc1MmY3ZGEsIDB4M2YwNDZmNjksIDB4NzdmYTBhNTksXG4gICAgICAweDgwZTRhOTE1LCAweDg3YjA4NjAxLCAweDliMDllNmFkLCAweDNiM2VlNTkzLCAweGU5OTBmZDVhLCAweDllMzRkNzk3LFxuICAgICAgMHgyY2YwYjdkOSwgMHgwMjJiOGI1MSwgMHg5NmQ1YWMzYSwgMHgwMTdkYTY3ZCwgMHhkMWNmM2VkNiwgMHg3YzdkMmQyOCxcbiAgICAgIDB4MWY5ZjI1Y2YsIDB4YWRmMmI4OWIsIDB4NWFkNmI0NzIsIDB4NWE4OGY1NGMsIDB4ZTAyOWFjNzEsIDB4ZTAxOWE1ZTYsXG4gICAgICAweDQ3YjBhY2ZkLCAweGVkOTNmYTliLCAweGU4ZDNjNDhkLCAweDI4M2I1N2NjLCAweGY4ZDU2NjI5LCAweDc5MTMyZTI4LFxuICAgICAgMHg3ODVmMDE5MSwgMHhlZDc1NjA1NSwgMHhmNzk2MGU0NCwgMHhlM2QzNWU4YywgMHgxNTA1NmRkNCwgMHg4OGY0NmRiYSxcbiAgICAgIDB4MDNhMTYxMjUsIDB4MDU2NGYwYmQsIDB4YzNlYjllMTUsIDB4M2M5MDU3YTIsIDB4OTcyNzFhZWMsIDB4YTkzYTA3MmEsXG4gICAgICAweDFiM2Y2ZDliLCAweDFlNjMyMWY1LCAweGY1OWM2NmZiLCAweDI2ZGNmMzE5LCAweDc1MzNkOTI4LCAweGIxNTVmZGY1LFxuICAgICAgMHgwMzU2MzQ4MiwgMHg4YWJhM2NiYiwgMHgyODUxNzcxMSwgMHhjMjBhZDlmOCwgMHhhYmNjNTE2NywgMHhjY2FkOTI1ZixcbiAgICAgIDB4NGRlODE3NTEsIDB4MzgzMGRjOGUsIDB4Mzc5ZDU4NjIsIDB4OTMyMGY5OTEsIDB4ZWE3YTkwYzIsIDB4ZmIzZTdiY2UsXG4gICAgICAweDUxMjFjZTY0LCAweDc3NGZiZTMyLCAweGE4YjZlMzdlLCAweGMzMjkzZDQ2LCAweDQ4ZGU1MzY5LCAweDY0MTNlNjgwLFxuICAgICAgMHhhMmFlMDgxMCwgMHhkZDZkYjIyNCwgMHg2OTg1MmRmZCwgMHgwOTA3MjE2NiwgMHhiMzlhNDYwYSwgMHg2NDQ1YzBkZCxcbiAgICAgIDB4NTg2Y2RlY2YsIDB4MWMyMGM4YWUsIDB4NWJiZWY3ZGQsIDB4MWI1ODhkNDAsIDB4Y2NkMjAxN2YsIDB4NmJiNGUzYmIsXG4gICAgICAweGRkYTI2YTdlLCAweDNhNTlmZjQ1LCAweDNlMzUwYTQ0LCAweGJjYjRjZGQ1LCAweDcyZWFjZWE4LCAweGZhNjQ4NGJiLFxuICAgICAgMHg4ZDY2MTJhZSwgMHhiZjNjNmY0NywgMHhkMjliZTQ2MywgMHg1NDJmNWQ5ZSwgMHhhZWMyNzcxYiwgMHhmNjRlNjM3MCxcbiAgICAgIDB4NzQwZTBkOGQsIDB4ZTc1YjEzNTcsIDB4Zjg3MjE2NzEsIDB4YWY1MzdkNWQsIDB4NDA0MGNiMDgsIDB4NGViNGUyY2MsXG4gICAgICAweDM0ZDI0NjZhLCAweDAxMTVhZjg0LCAweGUxYjAwNDI4LCAweDk1OTgzYTFkLCAweDA2Yjg5ZmI0LCAweGNlNmVhMDQ4LFxuICAgICAgMHg2ZjNmM2I4MiwgMHgzNTIwYWI4MiwgMHgwMTFhMWQ0YiwgMHgyNzcyMjdmOCwgMHg2MTE1NjBiMSwgMHhlNzkzM2ZkYyxcbiAgICAgIDB4YmIzYTc5MmIsIDB4MzQ0NTI1YmQsIDB4YTA4ODM5ZTEsIDB4NTFjZTc5NGIsIDB4MmYzMmM5YjcsIDB4YTAxZmJhYzksXG4gICAgICAweGUwMWNjODdlLCAweGJjYzdkMWY2LCAweGNmMDExMWMzLCAweGExZThhYWM3LCAweDFhOTA4NzQ5LCAweGQ0NGZiZDlhLFxuICAgICAgMHhkMGRhZGVjYiwgMHhkNTBhZGEzOCwgMHgwMzM5YzMyYSwgMHhjNjkxMzY2NywgMHg4ZGY5MzE3YywgMHhlMGIxMmI0ZixcbiAgICAgIDB4Zjc5ZTU5YjcsIDB4NDNmNWJiM2EsIDB4ZjJkNTE5ZmYsIDB4MjdkOTQ1OWMsIDB4YmY5NzIyMmMsIDB4MTVlNmZjMmEsXG4gICAgICAweDBmOTFmYzcxLCAweDliOTQxNTI1LCAweGZhZTU5MzYxLCAweGNlYjY5Y2ViLCAweGMyYTg2NDU5LCAweDEyYmFhOGQxLFxuICAgICAgMHhiNmMxMDc1ZSwgMHhlMzA1NmEwYywgMHgxMGQyNTA2NSwgMHhjYjAzYTQ0MiwgMHhlMGVjNmUwZSwgMHgxNjk4ZGIzYixcbiAgICAgIDB4NGM5OGEwYmUsIDB4MzI3OGU5NjQsIDB4OWYxZjk1MzIsIDB4ZTBkMzkyZGYsIDB4ZDNhMDM0MmIsIDB4ODk3MWYyMWUsXG4gICAgICAweDFiMGE3NDQxLCAweDRiYTMzNDhjLCAweGM1YmU3MTIwLCAweGMzNzYzMmQ4LCAweGRmMzU5ZjhkLCAweDliOTkyZjJlLFxuICAgICAgMHhlNjBiNmY0NywgMHgwZmUzZjExZCwgMHhlNTRjZGE1NCwgMHgxZWRhZDg5MSwgMHhjZTYyNzljZiwgMHhjZDNlN2U2ZixcbiAgICAgIDB4MTYxOGIxNjYsIDB4ZmQyYzFkMDUsIDB4ODQ4ZmQyYzUsIDB4ZjZmYjIyOTksIDB4ZjUyM2YzNTcsIDB4YTYzMjc2MjMsXG4gICAgICAweDkzYTgzNTMxLCAweDU2Y2NjZDAyLCAweGFjZjA4MTYyLCAweDVhNzVlYmI1LCAweDZlMTYzNjk3LCAweDg4ZDI3M2NjLFxuICAgICAgMHhkZTk2NjI5MiwgMHg4MWI5NDlkMCwgMHg0YzUwOTAxYiwgMHg3MWM2NTYxNCwgMHhlNmM2YzdiZCwgMHgzMjdhMTQwYSxcbiAgICAgIDB4NDVlMWQwMDYsIDB4YzNmMjdiOWEsIDB4YzlhYTUzZmQsIDB4NjJhODBmMDAsIDB4YmIyNWJmZTIsIDB4MzViZGQyZjYsXG4gICAgICAweDcxMTI2OTA1LCAweGIyMDQwMjIyLCAweGI2Y2JjZjdjLCAweGNkNzY5YzJiLCAweDUzMTEzZWMwLCAweDE2NDBlM2QzLFxuICAgICAgMHgzOGFiYmQ2MCwgMHgyNTQ3YWRmMCwgMHhiYTM4MjA5YywgMHhmNzQ2Y2U3NiwgMHg3N2FmYTFjNSwgMHgyMDc1NjA2MCxcbiAgICAgIDB4ODVjYmZlNGUsIDB4OGFlODhkZDgsIDB4N2FhYWY5YjAsIDB4NGNmOWFhN2UsIDB4MTk0OGMyNWMsIDB4MDJmYjhhOGMsXG4gICAgICAweDAxYzM2YWU0LCAweGQ2ZWJlMWY5LCAweDkwZDRmODY5LCAweGE2NWNkZWEwLCAweDNmMDkyNTJkLCAweGMyMDhlNjlmLFxuICAgICAgMHhiNzRlNjEzMiwgMHhjZTc3ZTI1YiwgMHg1NzhmZGZlMywgMHgzYWMzNzJlNlxuICBdXG5dO1xuXG4vLypcbi8vKiBUaGlzIGlzIHRoZSBkZWZhdWx0IFBBUlJBWVxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuUEFSUkFZID0gW1xuICAgIDB4MjQzZjZhODgsIDB4ODVhMzA4ZDMsIDB4MTMxOThhMmUsIDB4MDM3MDczNDQsIDB4YTQwOTM4MjIsIDB4Mjk5ZjMxZDAsXG4gICAgMHgwODJlZmE5OCwgMHhlYzRlNmM4OSwgMHg0NTI4MjFlNiwgMHgzOGQwMTM3NywgMHhiZTU0NjZjZiwgMHgzNGU5MGM2YyxcbiAgICAweGMwYWMyOWI3LCAweGM5N2M1MGRkLCAweDNmODRkNWI1LCAweGI1NDcwOTE3LCAweDkyMTZkNWQ5LCAweDg5NzlmYjFiXG5dO1xuXG4vLypcbi8vKiBUaGlzIGlzIHRoZSBudW1iZXIgb2Ygcm91bmRzIHRoZSBjaXBoZXIgd2lsbCBnb1xuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuTk4gPSAxNjtcblxuLy8qXG4vLyogVGhpcyBmdW5jdGlvbiBpcyBuZWVkZWQgdG8gZ2V0IHJpZCBvZiBwcm9ibGVtc1xuLy8qIHdpdGggdGhlIGhpZ2gtYml0IGdldHRpbmcgc2V0LiAgSWYgd2UgZG9uJ3QgZG9cbi8vKiB0aGlzLCB0aGVuIHNvbWV0aW1lcyAoIGFhICYgMHgwMEZGRkZGRkZGICkgaXMgbm90XG4vLyogZXF1YWwgdG8gKCBiYiAmIDB4MDBGRkZGRkZGRiApIGV2ZW4gd2hlbiB0aGV5XG4vLyogYWdyZWUgYml0LWZvci1iaXQgZm9yIHRoZSBmaXJzdCAzMiBiaXRzLlxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuX2NsZWFuID0gZnVuY3Rpb24oeHgpIHtcbiAgaWYgKHh4IDwgMCkge1xuICAgIHZhciB5eSA9IHh4ICYgMHg3RkZGRkZGRjtcbiAgICB4eCA9IHl5ICsgMHg4MDAwMDAwMDtcbiAgfVxuICByZXR1cm4geHg7XG59O1xuXG4vLypcbi8vKiBUaGlzIGlzIHRoZSBtaXhpbmcgZnVuY3Rpb24gdGhhdCB1c2VzIHRoZSBzYm94ZXNcbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLl9GID0gZnVuY3Rpb24oeHgpIHtcbiAgdmFyIGFhO1xuICB2YXIgYmI7XG4gIHZhciBjYztcbiAgdmFyIGRkO1xuICB2YXIgeXk7XG5cbiAgZGQgPSB4eCAmIDB4MDBGRjtcbiAgeHggPj4+PSA4O1xuICBjYyA9IHh4ICYgMHgwMEZGO1xuICB4eCA+Pj49IDg7XG4gIGJiID0geHggJiAweDAwRkY7XG4gIHh4ID4+Pj0gODtcbiAgYWEgPSB4eCAmIDB4MDBGRjtcblxuICB5eSA9IHRoaXMuc2JveGVzWzBdW2FhXSArIHRoaXMuc2JveGVzWzFdW2JiXTtcbiAgeXkgPSB5eSBeIHRoaXMuc2JveGVzWzJdW2NjXTtcbiAgeXkgPSB5eSArIHRoaXMuc2JveGVzWzNdW2RkXTtcblxuICByZXR1cm4geXk7XG59O1xuXG4vLypcbi8vKiBUaGlzIG1ldGhvZCB0YWtlcyBhbiBhcnJheSB3aXRoIHR3byB2YWx1ZXMsIGxlZnQgYW5kIHJpZ2h0XG4vLyogYW5kIGRvZXMgTk4gcm91bmRzIG9mIEJsb3dmaXNoIG9uIHRoZW0uXG4vLypcbkJsb3dmaXNoLnByb3RvdHlwZS5fZW5jcnlwdF9ibG9jayA9IGZ1bmN0aW9uKHZhbHMpIHtcbiAgdmFyIGRhdGFMID0gdmFsc1swXTtcbiAgdmFyIGRhdGFSID0gdmFsc1sxXTtcblxuICB2YXIgaWk7XG5cbiAgZm9yIChpaSA9IDA7IGlpIDwgdGhpcy5OTjsgKytpaSkge1xuICAgIGRhdGFMID0gZGF0YUwgXiB0aGlzLnBhcnJheVtpaV07XG4gICAgZGF0YVIgPSB0aGlzLl9GKGRhdGFMKSBeIGRhdGFSO1xuXG4gICAgdmFyIHRtcCA9IGRhdGFMO1xuICAgIGRhdGFMID0gZGF0YVI7XG4gICAgZGF0YVIgPSB0bXA7XG4gIH1cblxuICBkYXRhTCA9IGRhdGFMIF4gdGhpcy5wYXJyYXlbdGhpcy5OTiArIDBdO1xuICBkYXRhUiA9IGRhdGFSIF4gdGhpcy5wYXJyYXlbdGhpcy5OTiArIDFdO1xuXG4gIHZhbHNbMF0gPSB0aGlzLl9jbGVhbihkYXRhUik7XG4gIHZhbHNbMV0gPSB0aGlzLl9jbGVhbihkYXRhTCk7XG59O1xuXG4vLypcbi8vKiBUaGlzIG1ldGhvZCB0YWtlcyBhIHZlY3RvciBvZiBudW1iZXJzIGFuZCB0dXJucyB0aGVtXG4vLyogaW50byBsb25nIHdvcmRzIHNvIHRoYXQgdGhleSBjYW4gYmUgcHJvY2Vzc2VkIGJ5IHRoZVxuLy8qIHJlYWwgYWxnb3JpdGhtLlxuLy8qXG4vLyogTWF5YmUgSSBzaG91bGQgbWFrZSB0aGUgcmVhbCBhbGdvcml0aG0gYWJvdmUgdGFrZSBhIHZlY3RvclxuLy8qIGluc3RlYWQuICBUaGF0IHdpbGwgaW52b2x2ZSBtb3JlIGxvb3BpbmcsIGJ1dCBpdCB3b24ndCByZXF1aXJlXG4vLyogdGhlIEYoKSBtZXRob2QgdG8gZGVjb25zdHJ1Y3QgdGhlIHZlY3Rvci5cbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLmVuY3J5cHRfYmxvY2sgPSBmdW5jdGlvbih2ZWN0b3IpIHtcbiAgdmFyIGlpO1xuICB2YXIgdmFscyA9IFswLCAwXTtcbiAgdmFyIG9mZiA9IHRoaXMuQkxPQ0tTSVpFIC8gMjtcbiAgZm9yIChpaSA9IDA7IGlpIDwgdGhpcy5CTE9DS1NJWkUgLyAyOyArK2lpKSB7XG4gICAgdmFsc1swXSA9ICh2YWxzWzBdIDw8IDgpIHwgKHZlY3RvcltpaSArIDBdICYgMHgwMEZGKTtcbiAgICB2YWxzWzFdID0gKHZhbHNbMV0gPDwgOCkgfCAodmVjdG9yW2lpICsgb2ZmXSAmIDB4MDBGRik7XG4gIH1cblxuICB0aGlzLl9lbmNyeXB0X2Jsb2NrKHZhbHMpO1xuXG4gIHZhciByZXQgPSBbXTtcbiAgZm9yIChpaSA9IDA7IGlpIDwgdGhpcy5CTE9DS1NJWkUgLyAyOyArK2lpKSB7XG4gICAgcmV0W2lpICsgMF0gPSAodmFsc1swXSA+Pj4gKDI0IC0gOCAqIChpaSkpICYgMHgwMEZGKTtcbiAgICByZXRbaWkgKyBvZmZdID0gKHZhbHNbMV0gPj4+ICgyNCAtIDggKiAoaWkpKSAmIDB4MDBGRik7XG4gICAgLy8gdmFsc1sgMCBdID0gKCB2YWxzWyAwIF0gPj4+IDggKTtcbiAgICAvLyB2YWxzWyAxIF0gPSAoIHZhbHNbIDEgXSA+Pj4gOCApO1xuICB9XG5cbiAgcmV0dXJuIHJldDtcbn07XG5cbi8vKlxuLy8qIFRoaXMgbWV0aG9kIHRha2VzIGFuIGFycmF5IHdpdGggdHdvIHZhbHVlcywgbGVmdCBhbmQgcmlnaHRcbi8vKiBhbmQgdW5kb2VzIE5OIHJvdW5kcyBvZiBCbG93ZmlzaCBvbiB0aGVtLlxuLy8qXG5CbG93ZmlzaC5wcm90b3R5cGUuX2RlY3J5cHRfYmxvY2sgPSBmdW5jdGlvbih2YWxzKSB7XG4gIHZhciBkYXRhTCA9IHZhbHNbMF07XG4gIHZhciBkYXRhUiA9IHZhbHNbMV07XG5cbiAgdmFyIGlpO1xuXG4gIGZvciAoaWkgPSB0aGlzLk5OICsgMTsgaWkgPiAxOyAtLWlpKSB7XG4gICAgZGF0YUwgPSBkYXRhTCBeIHRoaXMucGFycmF5W2lpXTtcbiAgICBkYXRhUiA9IHRoaXMuX0YoZGF0YUwpIF4gZGF0YVI7XG5cbiAgICB2YXIgdG1wID0gZGF0YUw7XG4gICAgZGF0YUwgPSBkYXRhUjtcbiAgICBkYXRhUiA9IHRtcDtcbiAgfVxuXG4gIGRhdGFMID0gZGF0YUwgXiB0aGlzLnBhcnJheVsxXTtcbiAgZGF0YVIgPSBkYXRhUiBeIHRoaXMucGFycmF5WzBdO1xuXG4gIHZhbHNbMF0gPSB0aGlzLl9jbGVhbihkYXRhUik7XG4gIHZhbHNbMV0gPSB0aGlzLl9jbGVhbihkYXRhTCk7XG59O1xuXG4vLypcbi8vKiBUaGlzIG1ldGhvZCB0YWtlcyBhIGtleSBhcnJheSBhbmQgaW5pdGlhbGl6ZXMgdGhlXG4vLyogc2JveGVzIGFuZCBwYXJyYXkgZm9yIHRoaXMgZW5jcnlwdGlvbi5cbi8vKlxuQmxvd2Zpc2gucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbihrZXkpIHtcbiAgdmFyIGlpO1xuICB2YXIgamogPSAwO1xuXG4gIHRoaXMucGFycmF5ID0gW107XG4gIGZvciAoaWkgPSAwOyBpaSA8IHRoaXMuTk4gKyAyOyArK2lpKSB7XG4gICAgdmFyIGRhdGEgPSAweDAwMDAwMDAwO1xuICAgIHZhciBraztcbiAgICBmb3IgKGtrID0gMDsga2sgPCA0OyArK2trKSB7XG4gICAgICBkYXRhID0gKGRhdGEgPDwgOCkgfCAoa2V5W2pqXSAmIDB4MDBGRik7XG4gICAgICBpZiAoKytqaiA+PSBrZXkubGVuZ3RoKSB7XG4gICAgICAgIGpqID0gMDtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5wYXJyYXlbaWldID0gdGhpcy5QQVJSQVlbaWldIF4gZGF0YTtcbiAgfVxuXG4gIHRoaXMuc2JveGVzID0gW107XG4gIGZvciAoaWkgPSAwOyBpaSA8IDQ7ICsraWkpIHtcbiAgICB0aGlzLnNib3hlc1tpaV0gPSBbXTtcbiAgICBmb3IgKGpqID0gMDsgamogPCAyNTY7ICsramopIHtcbiAgICAgIHRoaXMuc2JveGVzW2lpXVtqal0gPSB0aGlzLlNCT1hFU1tpaV1bampdO1xuICAgIH1cbiAgfVxuXG4gIHZhciB2YWxzID0gWzB4MDAwMDAwMDAsIDB4MDAwMDAwMDBdO1xuXG4gIGZvciAoaWkgPSAwOyBpaSA8IHRoaXMuTk4gKyAyOyBpaSArPSAyKSB7XG4gICAgdGhpcy5fZW5jcnlwdF9ibG9jayh2YWxzKTtcbiAgICB0aGlzLnBhcnJheVtpaSArIDBdID0gdmFsc1swXTtcbiAgICB0aGlzLnBhcnJheVtpaSArIDFdID0gdmFsc1sxXTtcbiAgfVxuXG4gIGZvciAoaWkgPSAwOyBpaSA8IDQ7ICsraWkpIHtcbiAgICBmb3IgKGpqID0gMDsgamogPCAyNTY7IGpqICs9IDIpIHtcbiAgICAgIHRoaXMuX2VuY3J5cHRfYmxvY2sodmFscyk7XG4gICAgICB0aGlzLnNib3hlc1tpaV1bamogKyAwXSA9IHZhbHNbMF07XG4gICAgICB0aGlzLnNib3hlc1tpaV1bamogKyAxXSA9IHZhbHNbMV07XG4gICAgfVxuICB9XG59O1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuLy8gYWRkZWQgYnkgUmVjdXJpdHkgTGFic1xuXG5mdW5jdGlvbiBCRmVuY3J5cHQoYmxvY2ssIGtleSkge1xuICB2YXIgYmYgPSBuZXcgQmxvd2Zpc2goKTtcbiAgYmYuaW5pdCh1dGlsLnN0cjJiaW4oa2V5KSk7XG4gIHJldHVybiBiZi5lbmNyeXB0X2Jsb2NrKGJsb2NrKTtcbn1cblxuZnVuY3Rpb24gQkYoa2V5KSB7XG4gIHRoaXMuYmYgPSBuZXcgQmxvd2Zpc2goKTtcbiAgdGhpcy5iZi5pbml0KHV0aWwuc3RyMmJpbihrZXkpKTtcblxuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihibG9jaykge1xuICAgIHJldHVybiB0aGlzLmJmLmVuY3J5cHRfYmxvY2soYmxvY2spO1xuICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBCRjtcbm1vZHVsZS5leHBvcnRzLmtleVNpemUgPSBCRi5wcm90b3R5cGUua2V5U2l6ZSA9IDE2O1xubW9kdWxlLmV4cG9ydHMuYmxvY2tTaXplID0gQkYucHJvdG90eXBlLmJsb2NrU2l6ZSA9IDE2O1xuIiwiLy8gVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYSBCU0Qtc3R5bGVcbi8vIGxpY2Vuc2UgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZS5cblxuLy8gQ29weXJpZ2h0IDIwMTAgcGphY29ic0B4ZWVrci5jb20gLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG4vLyBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkhcblxuLy8gZml4ZWQvbW9kaWZpZWQgYnkgSGVyYmVydCBIYW5ld2lua2VsLCB3d3cuaGFuZVdJTi5kZVxuLy8gY2hlY2sgd3d3LmhhbmVXSU4uZGUgZm9yIHRoZSBsYXRlc3QgdmVyc2lvblxuXG4vLyBjYXN0NS5qcyBpcyBhIEphdmFzY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgQ0FTVC0xMjgsIGFzIGRlZmluZWQgaW4gUkZDIDIxNDQuXG4vLyBDQVNULTEyOCBpcyBhIGNvbW1vbiBPcGVuUEdQIGNpcGhlci5cblxuXG4vLyBDQVNUNSBjb25zdHJ1Y3RvclxuXG5cblxuZnVuY3Rpb24gb3BlbnBncF9zeW1lbmNfY2FzdDUoKSB7XG4gIHRoaXMuQmxvY2tTaXplID0gODtcbiAgdGhpcy5LZXlTaXplID0gMTY7XG5cbiAgdGhpcy5zZXRLZXkgPSBmdW5jdGlvbihrZXkpIHtcbiAgICB0aGlzLm1hc2tpbmcgPSBuZXcgQXJyYXkoMTYpO1xuICAgIHRoaXMucm90YXRlID0gbmV3IEFycmF5KDE2KTtcblxuICAgIHRoaXMucmVzZXQoKTtcblxuICAgIGlmIChrZXkubGVuZ3RoID09IHRoaXMuS2V5U2l6ZSkge1xuICAgICAgdGhpcy5rZXlTY2hlZHVsZShrZXkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1dGlsLnByaW50X2Vycm9yKCdjYXN0NS5qczogQ0FTVC0xMjg6IGtleXMgbXVzdCBiZSAxNiBieXRlcycpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICB0aGlzLnJlc2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICB0aGlzLm1hc2tpbmdbaV0gPSAwO1xuICAgICAgdGhpcy5yb3RhdGVbaV0gPSAwO1xuICAgIH1cbiAgfTtcblxuICB0aGlzLmdldEJsb2NrU2l6ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBCbG9ja1NpemU7XG4gIH07XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oc3JjKSB7XG4gICAgdmFyIGRzdCA9IG5ldyBBcnJheShzcmMubGVuZ3RoKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3JjLmxlbmd0aDsgaSArPSA4KSB7XG4gICAgICB2YXIgbCA9IHNyY1tpXSA8PCAyNCB8IHNyY1tpICsgMV0gPDwgMTYgfCBzcmNbaSArIDJdIDw8IDggfCBzcmNbaSArIDNdO1xuICAgICAgdmFyIHIgPSBzcmNbaSArIDRdIDw8IDI0IHwgc3JjW2kgKyA1XSA8PCAxNiB8IHNyY1tpICsgNl0gPDwgOCB8IHNyY1tpICsgN107XG4gICAgICB2YXIgdDtcblxuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1swXSwgdGhpcy5yb3RhdGVbMF0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjIociwgdGhpcy5tYXNraW5nWzFdLCB0aGlzLnJvdGF0ZVsxXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMyhyLCB0aGlzLm1hc2tpbmdbMl0sIHRoaXMucm90YXRlWzJdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1szXSwgdGhpcy5yb3RhdGVbM10pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbNF0sIHRoaXMucm90YXRlWzRdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1s1XSwgdGhpcy5yb3RhdGVbNV0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzZdLCB0aGlzLnJvdGF0ZVs2XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbN10sIHRoaXMucm90YXRlWzddKTtcbiAgICAgIGwgPSB0O1xuXG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzhdLCB0aGlzLnJvdGF0ZVs4XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbOV0sIHRoaXMucm90YXRlWzldKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1sxMF0sIHRoaXMucm90YXRlWzEwXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMyhyLCB0aGlzLm1hc2tpbmdbMTFdLCB0aGlzLnJvdGF0ZVsxMV0pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbMTJdLCB0aGlzLnJvdGF0ZVsxMl0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjIociwgdGhpcy5tYXNraW5nWzEzXSwgdGhpcy5yb3RhdGVbMTNdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1sxNF0sIHRoaXMucm90YXRlWzE0XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbMTVdLCB0aGlzLnJvdGF0ZVsxNV0pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIGRzdFtpXSA9IChyID4+PiAyNCkgJiAyNTU7XG4gICAgICBkc3RbaSArIDFdID0gKHIgPj4+IDE2KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgMl0gPSAociA+Pj4gOCkgJiAyNTU7XG4gICAgICBkc3RbaSArIDNdID0gciAmIDI1NTtcbiAgICAgIGRzdFtpICsgNF0gPSAobCA+Pj4gMjQpICYgMjU1O1xuICAgICAgZHN0W2kgKyA1XSA9IChsID4+PiAxNikgJiAyNTU7XG4gICAgICBkc3RbaSArIDZdID0gKGwgPj4+IDgpICYgMjU1O1xuICAgICAgZHN0W2kgKyA3XSA9IGwgJiAyNTU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRzdDtcbiAgfTtcblxuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihzcmMpIHtcbiAgICB2YXIgZHN0ID0gbmV3IEFycmF5KHNyYy5sZW5ndGgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzcmMubGVuZ3RoOyBpICs9IDgpIHtcbiAgICAgIHZhciBsID0gc3JjW2ldIDw8IDI0IHwgc3JjW2kgKyAxXSA8PCAxNiB8IHNyY1tpICsgMl0gPDwgOCB8IHNyY1tpICsgM107XG4gICAgICB2YXIgciA9IHNyY1tpICsgNF0gPDwgMjQgfCBzcmNbaSArIDVdIDw8IDE2IHwgc3JjW2kgKyA2XSA8PCA4IHwgc3JjW2kgKyA3XTtcbiAgICAgIHZhciB0O1xuXG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzE1XSwgdGhpcy5yb3RhdGVbMTVdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1sxNF0sIHRoaXMucm90YXRlWzE0XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbMTNdLCB0aGlzLnJvdGF0ZVsxM10pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzEyXSwgdGhpcy5yb3RhdGVbMTJdKTtcbiAgICAgIGwgPSB0O1xuXG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzExXSwgdGhpcy5yb3RhdGVbMTFdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1sxMF0sIHRoaXMucm90YXRlWzEwXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMShyLCB0aGlzLm1hc2tpbmdbOV0sIHRoaXMucm90YXRlWzldKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYzKHIsIHRoaXMubWFza2luZ1s4XSwgdGhpcy5yb3RhdGVbOF0pO1xuICAgICAgbCA9IHQ7XG5cbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbN10sIHRoaXMucm90YXRlWzddKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYxKHIsIHRoaXMubWFza2luZ1s2XSwgdGhpcy5yb3RhdGVbNl0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjMociwgdGhpcy5tYXNraW5nWzVdLCB0aGlzLnJvdGF0ZVs1XSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMihyLCB0aGlzLm1hc2tpbmdbNF0sIHRoaXMucm90YXRlWzRdKTtcbiAgICAgIGwgPSB0O1xuXG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzNdLCB0aGlzLnJvdGF0ZVszXSk7XG4gICAgICBsID0gdDtcbiAgICAgIHQgPSByO1xuICAgICAgciA9IGwgXiBmMyhyLCB0aGlzLm1hc2tpbmdbMl0sIHRoaXMucm90YXRlWzJdKTtcbiAgICAgIGwgPSB0O1xuICAgICAgdCA9IHI7XG4gICAgICByID0gbCBeIGYyKHIsIHRoaXMubWFza2luZ1sxXSwgdGhpcy5yb3RhdGVbMV0pO1xuICAgICAgbCA9IHQ7XG4gICAgICB0ID0gcjtcbiAgICAgIHIgPSBsIF4gZjEociwgdGhpcy5tYXNraW5nWzBdLCB0aGlzLnJvdGF0ZVswXSk7XG4gICAgICBsID0gdDtcblxuICAgICAgZHN0W2ldID0gKHIgPj4+IDI0KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgMV0gPSAociA+Pj4gMTYpICYgMjU1O1xuICAgICAgZHN0W2kgKyAyXSA9IChyID4+PiA4KSAmIDI1NTtcbiAgICAgIGRzdFtpICsgM10gPSByICYgMjU1O1xuICAgICAgZHN0W2kgKyA0XSA9IChsID4+PiAyNCkgJiAyNTU7XG4gICAgICBkc3RbaSArIDVdID0gKGwgPj4gMTYpICYgMjU1O1xuICAgICAgZHN0W2kgKyA2XSA9IChsID4+IDgpICYgMjU1O1xuICAgICAgZHN0W2kgKyA3XSA9IGwgJiAyNTU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRzdDtcbiAgfTtcbiAgdmFyIHNjaGVkdWxlQSA9IG5ldyBBcnJheSg0KTtcblxuICBzY2hlZHVsZUFbMF0gPSBuZXcgQXJyYXkoNCk7XG4gIHNjaGVkdWxlQVswXVswXSA9IG5ldyBBcnJheSg0LCAwLCAweGQsIDB4ZiwgMHhjLCAweGUsIDB4OCk7XG4gIHNjaGVkdWxlQVswXVsxXSA9IG5ldyBBcnJheSg1LCAyLCAxNiArIDAsIDE2ICsgMiwgMTYgKyAxLCAxNiArIDMsIDB4YSk7XG4gIHNjaGVkdWxlQVswXVsyXSA9IG5ldyBBcnJheSg2LCAzLCAxNiArIDcsIDE2ICsgNiwgMTYgKyA1LCAxNiArIDQsIDkpO1xuICBzY2hlZHVsZUFbMF1bM10gPSBuZXcgQXJyYXkoNywgMSwgMTYgKyAweGEsIDE2ICsgOSwgMTYgKyAweGIsIDE2ICsgOCwgMHhiKTtcblxuICBzY2hlZHVsZUFbMV0gPSBuZXcgQXJyYXkoNCk7XG4gIHNjaGVkdWxlQVsxXVswXSA9IG5ldyBBcnJheSgwLCA2LCAxNiArIDUsIDE2ICsgNywgMTYgKyA0LCAxNiArIDYsIDE2ICsgMCk7XG4gIHNjaGVkdWxlQVsxXVsxXSA9IG5ldyBBcnJheSgxLCA0LCAwLCAyLCAxLCAzLCAxNiArIDIpO1xuICBzY2hlZHVsZUFbMV1bMl0gPSBuZXcgQXJyYXkoMiwgNSwgNywgNiwgNSwgNCwgMTYgKyAxKTtcbiAgc2NoZWR1bGVBWzFdWzNdID0gbmV3IEFycmF5KDMsIDcsIDB4YSwgOSwgMHhiLCA4LCAxNiArIDMpO1xuXG4gIHNjaGVkdWxlQVsyXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVBWzJdWzBdID0gbmV3IEFycmF5KDQsIDAsIDB4ZCwgMHhmLCAweGMsIDB4ZSwgOCk7XG4gIHNjaGVkdWxlQVsyXVsxXSA9IG5ldyBBcnJheSg1LCAyLCAxNiArIDAsIDE2ICsgMiwgMTYgKyAxLCAxNiArIDMsIDB4YSk7XG4gIHNjaGVkdWxlQVsyXVsyXSA9IG5ldyBBcnJheSg2LCAzLCAxNiArIDcsIDE2ICsgNiwgMTYgKyA1LCAxNiArIDQsIDkpO1xuICBzY2hlZHVsZUFbMl1bM10gPSBuZXcgQXJyYXkoNywgMSwgMTYgKyAweGEsIDE2ICsgOSwgMTYgKyAweGIsIDE2ICsgOCwgMHhiKTtcblxuXG4gIHNjaGVkdWxlQVszXSA9IG5ldyBBcnJheSg0KTtcbiAgc2NoZWR1bGVBWzNdWzBdID0gbmV3IEFycmF5KDAsIDYsIDE2ICsgNSwgMTYgKyA3LCAxNiArIDQsIDE2ICsgNiwgMTYgKyAwKTtcbiAgc2NoZWR1bGVBWzNdWzFdID0gbmV3IEFycmF5KDEsIDQsIDAsIDIsIDEsIDMsIDE2ICsgMik7XG4gIHNjaGVkdWxlQVszXVsyXSA9IG5ldyBBcnJheSgyLCA1LCA3LCA2LCA1LCA0LCAxNiArIDEpO1xuICBzY2hlZHVsZUFbM11bM10gPSBuZXcgQXJyYXkoMywgNywgMHhhLCA5LCAweGIsIDgsIDE2ICsgMyk7XG5cbiAgdmFyIHNjaGVkdWxlQiA9IG5ldyBBcnJheSg0KTtcblxuICBzY2hlZHVsZUJbMF0gPSBuZXcgQXJyYXkoNCk7XG4gIHNjaGVkdWxlQlswXVswXSA9IG5ldyBBcnJheSgxNiArIDgsIDE2ICsgOSwgMTYgKyA3LCAxNiArIDYsIDE2ICsgMik7XG4gIHNjaGVkdWxlQlswXVsxXSA9IG5ldyBBcnJheSgxNiArIDB4YSwgMTYgKyAweGIsIDE2ICsgNSwgMTYgKyA0LCAxNiArIDYpO1xuICBzY2hlZHVsZUJbMF1bMl0gPSBuZXcgQXJyYXkoMTYgKyAweGMsIDE2ICsgMHhkLCAxNiArIDMsIDE2ICsgMiwgMTYgKyA5KTtcbiAgc2NoZWR1bGVCWzBdWzNdID0gbmV3IEFycmF5KDE2ICsgMHhlLCAxNiArIDB4ZiwgMTYgKyAxLCAxNiArIDAsIDE2ICsgMHhjKTtcblxuICBzY2hlZHVsZUJbMV0gPSBuZXcgQXJyYXkoNCk7XG4gIHNjaGVkdWxlQlsxXVswXSA9IG5ldyBBcnJheSgzLCAyLCAweGMsIDB4ZCwgOCk7XG4gIHNjaGVkdWxlQlsxXVsxXSA9IG5ldyBBcnJheSgxLCAwLCAweGUsIDB4ZiwgMHhkKTtcbiAgc2NoZWR1bGVCWzFdWzJdID0gbmV3IEFycmF5KDcsIDYsIDgsIDksIDMpO1xuICBzY2hlZHVsZUJbMV1bM10gPSBuZXcgQXJyYXkoNSwgNCwgMHhhLCAweGIsIDcpO1xuXG5cbiAgc2NoZWR1bGVCWzJdID0gbmV3IEFycmF5KDQpO1xuICBzY2hlZHVsZUJbMl1bMF0gPSBuZXcgQXJyYXkoMTYgKyAzLCAxNiArIDIsIDE2ICsgMHhjLCAxNiArIDB4ZCwgMTYgKyA5KTtcbiAgc2NoZWR1bGVCWzJdWzFdID0gbmV3IEFycmF5KDE2ICsgMSwgMTYgKyAwLCAxNiArIDB4ZSwgMTYgKyAweGYsIDE2ICsgMHhjKTtcbiAgc2NoZWR1bGVCWzJdWzJdID0gbmV3IEFycmF5KDE2ICsgNywgMTYgKyA2LCAxNiArIDgsIDE2ICsgOSwgMTYgKyAyKTtcbiAgc2NoZWR1bGVCWzJdWzNdID0gbmV3IEFycmF5KDE2ICsgNSwgMTYgKyA0LCAxNiArIDB4YSwgMTYgKyAweGIsIDE2ICsgNik7XG5cblxuICBzY2hlZHVsZUJbM10gPSBuZXcgQXJyYXkoNCk7XG4gIHNjaGVkdWxlQlszXVswXSA9IG5ldyBBcnJheSg4LCA5LCA3LCA2LCAzKTtcbiAgc2NoZWR1bGVCWzNdWzFdID0gbmV3IEFycmF5KDB4YSwgMHhiLCA1LCA0LCA3KTtcbiAgc2NoZWR1bGVCWzNdWzJdID0gbmV3IEFycmF5KDB4YywgMHhkLCAzLCAyLCA4KTtcbiAgc2NoZWR1bGVCWzNdWzNdID0gbmV3IEFycmF5KDB4ZSwgMHhmLCAxLCAwLCAweGQpO1xuXG4gIC8vIGNoYW5nZWQgJ2luJyB0byAnaW5uJyAoaW4gamF2YXNjcmlwdCAnaW4nIGlzIGEgcmVzZXJ2ZWQgd29yZClcbiAgdGhpcy5rZXlTY2hlZHVsZSA9IGZ1bmN0aW9uKGlubikge1xuICAgIHZhciB0ID0gbmV3IEFycmF5KDgpO1xuICAgIHZhciBrID0gbmV3IEFycmF5KDMyKTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgICB2YXIgaiA9IGkgKiA0O1xuICAgICAgdFtpXSA9IGlubltqXSA8PCAyNCB8IGlubltqICsgMV0gPDwgMTYgfCBpbm5baiArIDJdIDw8IDggfCBpbm5baiArIDNdO1xuICAgIH1cblxuICAgIHZhciB4ID0gWzYsIDcsIDQsIDVdO1xuICAgIHZhciBraSA9IDA7XG5cbiAgICBmb3IgKHZhciBoYWxmID0gMDsgaGFsZiA8IDI7IGhhbGYrKykge1xuICAgICAgZm9yICh2YXIgcm91bmQgPSAwOyByb3VuZCA8IDQ7IHJvdW5kKyspIHtcbiAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCA0OyBqKyspIHtcbiAgICAgICAgICB2YXIgYSA9IHNjaGVkdWxlQVtyb3VuZF1bal07XG4gICAgICAgICAgdmFyIHcgPSB0W2FbMV1dO1xuXG4gICAgICAgICAgdyBePSBzQm94WzRdWyh0W2FbMl0gPj4+IDJdID4+PiAoMjQgLSA4ICogKGFbMl0gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94WzVdWyh0W2FbM10gPj4+IDJdID4+PiAoMjQgLSA4ICogKGFbM10gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94WzZdWyh0W2FbNF0gPj4+IDJdID4+PiAoMjQgLSA4ICogKGFbNF0gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94WzddWyh0W2FbNV0gPj4+IDJdID4+PiAoMjQgLSA4ICogKGFbNV0gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdyBePSBzQm94W3hbal1dWyh0W2FbNl0gPj4+IDJdID4+PiAoMjQgLSA4ICogKGFbNl0gJiAzKSkpICYgMHhmZl07XG4gICAgICAgICAgdFthWzBdXSA9IHc7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDQ7IGorKykge1xuICAgICAgICAgIHZhciBiID0gc2NoZWR1bGVCW3JvdW5kXVtqXTtcbiAgICAgICAgICB2YXIgdyA9IHNCb3hbNF1bKHRbYlswXSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYlswXSAmIDMpKSkgJiAweGZmXTtcblxuICAgICAgICAgIHcgXj0gc0JveFs1XVsodFtiWzFdID4+PiAyXSA+Pj4gKDI0IC0gOCAqIChiWzFdICYgMykpKSAmIDB4ZmZdO1xuICAgICAgICAgIHcgXj0gc0JveFs2XVsodFtiWzJdID4+PiAyXSA+Pj4gKDI0IC0gOCAqIChiWzJdICYgMykpKSAmIDB4ZmZdO1xuICAgICAgICAgIHcgXj0gc0JveFs3XVsodFtiWzNdID4+PiAyXSA+Pj4gKDI0IC0gOCAqIChiWzNdICYgMykpKSAmIDB4ZmZdO1xuICAgICAgICAgIHcgXj0gc0JveFs0ICsgal1bKHRbYls0XSA+Pj4gMl0gPj4+ICgyNCAtIDggKiAoYls0XSAmIDMpKSkgJiAweGZmXTtcbiAgICAgICAgICBrW2tpXSA9IHc7XG4gICAgICAgICAga2krKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgdGhpcy5tYXNraW5nW2ldID0ga1tpXTtcbiAgICAgIHRoaXMucm90YXRlW2ldID0ga1sxNiArIGldICYgMHgxZjtcbiAgICB9XG4gIH07XG5cbiAgLy8gVGhlc2UgYXJlIHRoZSB0aHJlZSAnZicgZnVuY3Rpb25zLiBTZWUgUkZDIDIxNDQsIHNlY3Rpb24gMi4yLlxuXG4gIGZ1bmN0aW9uIGYxKGQsIG0sIHIpIHtcbiAgICB2YXIgdCA9IG0gKyBkO1xuICAgIHZhciBJID0gKHQgPDwgcikgfCAodCA+Pj4gKDMyIC0gcikpO1xuICAgIHJldHVybiAoKHNCb3hbMF1bSSA+Pj4gMjRdIF4gc0JveFsxXVsoSSA+Pj4gMTYpICYgMjU1XSkgLSBzQm94WzJdWyhJID4+PiA4KSAmIDI1NV0pICsgc0JveFszXVtJICYgMjU1XTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGYyKGQsIG0sIHIpIHtcbiAgICB2YXIgdCA9IG0gXiBkO1xuICAgIHZhciBJID0gKHQgPDwgcikgfCAodCA+Pj4gKDMyIC0gcikpO1xuICAgIHJldHVybiAoKHNCb3hbMF1bSSA+Pj4gMjRdIC0gc0JveFsxXVsoSSA+Pj4gMTYpICYgMjU1XSkgKyBzQm94WzJdWyhJID4+PiA4KSAmIDI1NV0pIF4gc0JveFszXVtJICYgMjU1XTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGYzKGQsIG0sIHIpIHtcbiAgICB2YXIgdCA9IG0gLSBkO1xuICAgIHZhciBJID0gKHQgPDwgcikgfCAodCA+Pj4gKDMyIC0gcikpO1xuICAgIHJldHVybiAoKHNCb3hbMF1bSSA+Pj4gMjRdICsgc0JveFsxXVsoSSA+Pj4gMTYpICYgMjU1XSkgXiBzQm94WzJdWyhJID4+PiA4KSAmIDI1NV0pIC0gc0JveFszXVtJICYgMjU1XTtcbiAgfVxuXG4gIHZhciBzQm94ID0gbmV3IEFycmF5KDgpO1xuICBzQm94WzBdID0gbmV3IEFycmF5KFxuICAgIDB4MzBmYjQwZDQsIDB4OWZhMGZmMGIsIDB4NmJlY2NkMmYsIDB4M2YyNThjN2EsIDB4MWUyMTNmMmYsIDB4OWMwMDRkZDMsIDB4NjAwM2U1NDAsIDB4Y2Y5ZmM5NDksXG4gICAgMHhiZmQ0YWYyNywgMHg4OGJiYmRiNSwgMHhlMjAzNDA5MCwgMHg5OGQwOTY3NSwgMHg2ZTYzYTBlMCwgMHgxNWMzNjFkMiwgMHhjMmU3NjYxZCwgMHgyMmQ0ZmY4ZSxcbiAgICAweDI4NjgzYjZmLCAweGMwN2ZkMDU5LCAweGZmMjM3OWM4LCAweDc3NWY1MGUyLCAweDQzYzM0MGQzLCAweGRmMmY4NjU2LCAweDg4N2NhNDFhLCAweGEyZDJiZDJkLFxuICAgIDB4YTFjOWUwZDYsIDB4MzQ2YzQ4MTksIDB4NjFiNzZkODcsIDB4MjI1NDBmMmYsIDB4MmFiZTMyZTEsIDB4YWE1NDE2NmIsIDB4MjI1NjhlM2EsIDB4YTJkMzQxZDAsXG4gICAgMHg2NmRiNDBjOCwgMHhhNzg0MzkyZiwgMHgwMDRkZmYyZiwgMHgyZGI5ZDJkZSwgMHg5Nzk0M2ZhYywgMHg0YTk3YzFkOCwgMHg1Mjc2NDRiNywgMHhiNWY0MzdhNyxcbiAgICAweGI4MmNiYWVmLCAweGQ3NTFkMTU5LCAweDZmZjdmMGVkLCAweDVhMDk3YTFmLCAweDgyN2I2OGQwLCAweDkwZWNmNTJlLCAweDIyYjBjMDU0LCAweGJjOGU1OTM1LFxuICAgIDB4NGI2ZDJmN2YsIDB4NTBiYjY0YTIsIDB4ZDI2NjQ5MTAsIDB4YmVlNTgxMmQsIDB4YjczMzIyOTAsIDB4ZTkzYjE1OWYsIDB4YjQ4ZWU0MTEsIDB4NGJmZjM0NWQsXG4gICAgMHhmZDQ1YzI0MCwgMHhhZDMxOTczZiwgMHhjNGY2ZDAyZSwgMHg1NWZjODE2NSwgMHhkNWIxY2FhZCwgMHhhMWFjMmRhZSwgMHhhMmQ0Yjc2ZCwgMHhjMTliMGM1MCxcbiAgICAweDg4MjI0MGYyLCAweDBjNmU0ZjM4LCAweGE0ZTRiZmQ3LCAweDRmNWJhMjcyLCAweDU2NGMxZDJmLCAweGM1OWM1MzE5LCAweGI5NDllMzU0LCAweGIwNDY2OWZlLFxuICAgIDB4YjFiNmFiOGEsIDB4YzcxMzU4ZGQsIDB4NjM4NWM1NDUsIDB4MTEwZjkzNWQsIDB4NTc1MzhhZDUsIDB4NmEzOTA0OTMsIDB4ZTYzZDM3ZTAsIDB4MmE1NGY2YjMsXG4gICAgMHgzYTc4N2Q1ZiwgMHg2Mjc2YTBiNSwgMHgxOWE2ZmNkZiwgMHg3YTQyMjA2YSwgMHgyOWY5ZDRkNSwgMHhmNjFiMTg5MSwgMHhiYjcyMjc1ZSwgMHhhYTUwODE2NyxcbiAgICAweDM4OTAxMDkxLCAweGM2YjUwNWViLCAweDg0YzdjYjhjLCAweDJhZDc1YTBmLCAweDg3NGExNDI3LCAweGEyZDE5MzZiLCAweDJhZDI4NmFmLCAweGFhNTZkMjkxLFxuICAgIDB4ZDc4OTQzNjAsIDB4NDI1Yzc1MGQsIDB4OTNiMzllMjYsIDB4MTg3MTg0YzksIDB4NmMwMGIzMmQsIDB4NzNlMmJiMTQsIDB4YTBiZWJjM2MsIDB4NTQ2MjM3NzksXG4gICAgMHg2NDQ1OWVhYiwgMHgzZjMyOGI4MiwgMHg3NzE4Y2Y4MiwgMHg1OWEyY2VhNiwgMHgwNGVlMDAyZSwgMHg4OWZlNzhlNiwgMHgzZmFiMDk1MCwgMHgzMjVmZjZjMixcbiAgICAweDgxMzgzZjA1LCAweDY5NjNjNWM4LCAweDc2Y2I1YWQ2LCAweGQ0OTk3NGM5LCAweGNhMTgwZGNmLCAweDM4MDc4MmQ1LCAweGM3ZmE1Y2Y2LCAweDhhYzMxNTExLFxuICAgIDB4MzVlNzllMTMsIDB4NDdkYTkxZDAsIDB4ZjQwZjkwODYsIDB4YTdlMjQxOWUsIDB4MzEzNjYyNDEsIDB4MDUxZWY0OTUsIDB4YWE1NzNiMDQsIDB4NGE4MDVkOGQsXG4gICAgMHg1NDgzMDBkMCwgMHgwMDMyMmEzYywgMHhiZjY0Y2RkZiwgMHhiYTU3YTY4ZSwgMHg3NWM2MzcyYiwgMHg1MGFmZDM0MSwgMHhhN2MxMzI3NSwgMHg5MTVhMGJmNSxcbiAgICAweDZiNTRiZmFiLCAweDJiMGIxNDI2LCAweGFiNGNjOWQ3LCAweDQ0OWNjZDgyLCAweGY3ZmJmMjY1LCAweGFiODVjNWYzLCAweDFiNTVkYjk0LCAweGFhZDRlMzI0LFxuICAgIDB4Y2ZhNGJkM2YsIDB4MmRlYWEzZTIsIDB4OWUyMDRkMDIsIDB4YzhiZDI1YWMsIDB4ZWFkZjU1YjMsIDB4ZDViZDllOTgsIDB4ZTMxMjMxYjIsIDB4MmFkNWFkNmMsXG4gICAgMHg5NTQzMjlkZSwgMHhhZGJlNDUyOCwgMHhkODcxMGY2OSwgMHhhYTUxYzkwZiwgMHhhYTc4NmJmNiwgMHgyMjUxM2YxZSwgMHhhYTUxYTc5YiwgMHgyYWQzNDRjYyxcbiAgICAweDdiNWE0MWYwLCAweGQzN2NmYmFkLCAweDFiMDY5NTA1LCAweDQxZWNlNDkxLCAweGI0YzMzMmU2LCAweDAzMjI2OGQ0LCAweGM5NjAwYWNjLCAweGNlMzg3ZTZkLFxuICAgIDB4YmY2YmIxNmMsIDB4NmE3MGZiNzgsIDB4MGQwM2Q5YzksIDB4ZDRkZjM5ZGUsIDB4ZTAxMDYzZGEsIDB4NDczNmY0NjQsIDB4NWFkMzI4ZDgsIDB4YjM0N2NjOTYsXG4gICAgMHg3NWJiMGZjMywgMHg5ODUxMWJmYiwgMHg0ZmZiY2MzNSwgMHhiNThiY2Y2YSwgMHhlMTFmMGFiYywgMHhiZmM1ZmU0YSwgMHhhNzBhZWMxMCwgMHhhYzM5NTcwYSxcbiAgICAweDNmMDQ0NDJmLCAweDYxODhiMTUzLCAweGUwMzk3YTJlLCAweDU3MjdjYjc5LCAweDljZWI0MThmLCAweDFjYWNkNjhkLCAweDJhZDM3Yzk2LCAweDAxNzVjYjlkLFxuICAgIDB4YzY5ZGZmMDksIDB4Yzc1YjY1ZjAsIDB4ZDlkYjQwZDgsIDB4ZWMwZTc3NzksIDB4NDc0NGVhZDQsIDB4YjExYzMyNzQsIDB4ZGQyNGNiOWUsIDB4N2UxYzU0YmQsXG4gICAgMHhmMDExNDRmOSwgMHhkMjI0MGViMSwgMHg5Njc1YjNmZCwgMHhhM2FjMzc1NSwgMHhkNDdjMjdhZiwgMHg1MWM4NWY0ZCwgMHg1NjkwNzU5NiwgMHhhNWJiMTVlNixcbiAgICAweDU4MDMwNGYwLCAweGNhMDQyY2YxLCAweDAxMWEzN2VhLCAweDhkYmZhYWRiLCAweDM1YmEzZTRhLCAweDM1MjZmZmEwLCAweGMzN2I0ZDA5LCAweGJjMzA2ZWQ5LFxuICAgIDB4OThhNTI2NjYsIDB4NTY0OGY3MjUsIDB4ZmY1ZTU2OWQsIDB4MGNlZDYzZDAsIDB4N2M2M2IyY2YsIDB4NzAwYjQ1ZTEsIDB4ZDVlYTUwZjEsIDB4ODVhOTI4NzIsXG4gICAgMHhhZjFmYmRhNywgMHhkNDIzNDg3MCwgMHhhNzg3MGJmMywgMHgyZDNiNGQ3OSwgMHg0MmUwNDE5OCwgMHgwY2QwZWRlNywgMHgyNjQ3MGRiOCwgMHhmODgxODE0YyxcbiAgICAweDQ3NGQ2YWQ3LCAweDdjMGM1ZTVjLCAweGQxMjMxOTU5LCAweDM4MWI3Mjk4LCAweGY1ZDJmNGRiLCAweGFiODM4NjUzLCAweDZlMmYxZTIzLCAweDgzNzE5YzllLFxuICAgIDB4YmQ5MWUwNDYsIDB4OWE1NjQ1NmUsIDB4ZGMzOTIwMGMsIDB4MjBjOGM1NzEsIDB4OTYyYmRhMWMsIDB4ZTFlNjk2ZmYsIDB4YjE0MWFiMDgsIDB4N2NjYTg5YjksXG4gICAgMHgxYTY5ZTc4MywgMHgwMmNjNDg0MywgMHhhMmY3YzU3OSwgMHg0MjllZjQ3ZCwgMHg0MjdiMTY5YywgMHg1YWM5ZjA0OSwgMHhkZDhmMGYwMCwgMHg1YzgxNjViZik7XG5cbiAgc0JveFsxXSA9IG5ldyBBcnJheShcbiAgICAweDFmMjAxMDk0LCAweGVmMGJhNzViLCAweDY5ZTNjZjdlLCAweDM5M2Y0MzgwLCAweGZlNjFjZjdhLCAweGVlYzUyMDdhLCAweDU1ODg5Yzk0LCAweDcyZmMwNjUxLFxuICAgIDB4YWRhN2VmNzksIDB4NGUxZDcyMzUsIDB4ZDU1YTYzY2UsIDB4ZGUwNDM2YmEsIDB4OTljNDMwZWYsIDB4NWYwYzA3OTQsIDB4MThkY2RiN2QsIDB4YTFkNmVmZjMsXG4gICAgMHhhMGI1MmY3YiwgMHg1OWU4MzYwNSwgMHhlZTE1YjA5NCwgMHhlOWZmZDkwOSwgMHhkYzQ0MDA4NiwgMHhlZjk0NDQ1OSwgMHhiYTgzY2NiMywgMHhlMGMzY2RmYixcbiAgICAweGQxZGE0MTgxLCAweDNiMDkyYWIxLCAweGY5OTdmMWMxLCAweGE1ZTZjZjdiLCAweDAxNDIwZGRiLCAweGU0ZTdlZjViLCAweDI1YTFmZjQxLCAweGUxODBmODA2LFxuICAgIDB4MWZjNDEwODAsIDB4MTc5YmVlN2EsIDB4ZDM3YWM2YTksIDB4ZmU1ODMwYTQsIDB4OThkZThiN2YsIDB4NzdlODNmNGUsIDB4Nzk5MjkyNjksIDB4MjRmYTlmN2IsXG4gICAgMHhlMTEzYzg1YiwgMHhhY2M0MDA4MywgMHhkNzUwMzUyNSwgMHhmN2VhNjE1ZiwgMHg2MjE0MzE1NCwgMHgwZDU1NGI2MywgMHg1ZDY4MTEyMSwgMHhjODY2YzM1OSxcbiAgICAweDNkNjNjZjczLCAweGNlZTIzNGMwLCAweGQ0ZDg3ZTg3LCAweDVjNjcyYjIxLCAweDA3MWY2MTgxLCAweDM5Zjc2MjdmLCAweDM2MWUzMDg0LCAweGU0ZWI1NzNiLFxuICAgIDB4NjAyZjY0YTQsIDB4ZDYzYWNkOWMsIDB4MWJiYzQ2MzUsIDB4OWU4MTAzMmQsIDB4MjcwMWY1MGMsIDB4OTk4NDdhYjQsIDB4YTBlM2RmNzksIDB4YmE2Y2YzOGMsXG4gICAgMHgxMDg0MzA5NCwgMHgyNTM3YTk1ZSwgMHhmNDZmNmZmZSwgMHhhMWZmM2IxZiwgMHgyMDhjZmI2YSwgMHg4ZjQ1OGM3NCwgMHhkOWUwYTIyNywgMHg0ZWM3M2EzNCxcbiAgICAweGZjODg0ZjY5LCAweDNlNGRlOGRmLCAweGVmMGUwMDg4LCAweDM1NTk2NDhkLCAweDhhNDUzODhjLCAweDFkODA0MzY2LCAweDcyMWQ5YmZkLCAweGE1ODY4NGJiLFxuICAgIDB4ZTgyNTYzMzMsIDB4ODQ0ZTgyMTIsIDB4MTI4ZDgwOTgsIDB4ZmVkMzNmYjQsIDB4Y2UyODBhZTEsIDB4MjdlMTliYTUsIDB4ZDVhNmMyNTIsIDB4ZTQ5NzU0YmQsXG4gICAgMHhjNWQ2NTVkZCwgMHhlYjY2NzA2NCwgMHg3Nzg0MGI0ZCwgMHhhMWI2YTgwMSwgMHg4NGRiMjZhOSwgMHhlMGI1NjcxNCwgMHgyMWYwNDNiNywgMHhlNWQwNTg2MCxcbiAgICAweDU0ZjAzMDg0LCAweDA2NmZmNDcyLCAweGEzMWFhMTUzLCAweGRhZGM0NzU1LCAweGI1NjI1ZGJmLCAweDY4NTYxYmU2LCAweDgzY2E2Yjk0LCAweDJkNmVkMjNiLFxuICAgIDB4ZWNjZjAxZGIsIDB4YTZkM2QwYmEsIDB4YjY4MDNkNWMsIDB4YWY3N2E3MDksIDB4MzNiNGEzNGMsIDB4Mzk3YmM4ZDYsIDB4NWVlMjJiOTUsIDB4NWYwZTUzMDQsXG4gICAgMHg4MWVkNmY2MSwgMHgyMGU3NDM2NCwgMHhiNDVlMTM3OCwgMHhkZTE4NjM5YiwgMHg4ODFjYTEyMiwgMHhiOTY3MjZkMSwgMHg4MDQ5YTdlOCwgMHgyMmI3ZGE3YixcbiAgICAweDVlNTUyZDI1LCAweDUyNzJkMjM3LCAweDc5ZDI5NTFjLCAweGM2MGQ4OTRjLCAweDQ4OGNiNDAyLCAweDFiYTRmZTViLCAweGE0YjA5ZjZiLCAweDFjYTgxNWNmLFxuICAgIDB4YTIwYzMwMDUsIDB4ODg3MWRmNjMsIDB4YjlkZTJmY2IsIDB4MGNjNmM5ZTksIDB4MGJlZWZmNTMsIDB4ZTMyMTQ1MTcsIDB4YjQ1NDI4MzUsIDB4OWY2MzI5M2MsXG4gICAgMHhlZTQxZTcyOSwgMHg2ZTFkMmQ3YywgMHg1MDA0NTI4NiwgMHgxZTY2ODVmMywgMHhmMzM0MDFjNiwgMHgzMGEyMmM5NSwgMHgzMWE3MDg1MCwgMHg2MDkzMGYxMyxcbiAgICAweDczZjk4NDE3LCAweGExMjY5ODU5LCAweGVjNjQ1YzQ0LCAweDUyYzg3N2E5LCAweGNkZmYzM2E2LCAweGEwMmIxNzQxLCAweDdjYmFkOWEyLCAweDIxODAwMzZmLFxuICAgIDB4NTBkOTljMDgsIDB4Y2IzZjQ4NjEsIDB4YzI2YmQ3NjUsIDB4NjRhM2Y2YWIsIDB4ODAzNDI2NzYsIDB4MjVhNzVlN2IsIDB4ZTRlNmQxZmMsIDB4MjBjNzEwZTYsXG4gICAgMHhjZGYwYjY4MCwgMHgxNzg0NGQzYiwgMHgzMWVlZjg0ZCwgMHg3ZTA4MjRlNCwgMHgyY2NiNDllYiwgMHg4NDZhM2JhZSwgMHg4ZmY3Nzg4OCwgMHhlZTVkNjBmNixcbiAgICAweDdhZjc1NjczLCAweDJmZGQ1Y2RiLCAweGExMTYzMWMxLCAweDMwZjY2ZjQzLCAweGIzZmFlYzU0LCAweDE1N2ZkN2ZhLCAweGVmODU3OWNjLCAweGQxNTJkZTU4LFxuICAgIDB4ZGIyZmZkNWUsIDB4OGYzMmNlMTksIDB4MzA2YWY5N2EsIDB4MDJmMDNlZjgsIDB4OTkzMTlhZDUsIDB4YzI0MmZhMGYsIDB4YTdlM2ViYjAsIDB4YzY4ZTQ5MDYsXG4gICAgMHhiOGRhMjMwYywgMHg4MDgyMzAyOCwgMHhkY2RlZjNjOCwgMHhkMzVmYjE3MSwgMHgwODhhMWJjOCwgMHhiZWMwYzU2MCwgMHg2MWEzYzllOCwgMHhiY2E4ZjU0ZCxcbiAgICAweGM3MmZlZmZhLCAweDIyODIyZTk5LCAweDgyYzU3MGI0LCAweGQ4ZDk0ZTg5LCAweDhiMWMzNGJjLCAweDMwMWUxNmU2LCAweDI3M2JlOTc5LCAweGIwZmZlYWE2LFxuICAgIDB4NjFkOWI4YzYsIDB4MDBiMjQ4NjksIDB4YjdmZmNlM2YsIDB4MDhkYzI4M2IsIDB4NDNkYWY2NWEsIDB4ZjdlMTk3OTgsIDB4NzYxOWI3MmYsIDB4OGYxYzliYTQsXG4gICAgMHhkYzg2MzdhMCwgMHgxNmE3ZDNiMSwgMHg5ZmMzOTNiNywgMHhhNzEzNmVlYiwgMHhjNmJjYzYzZSwgMHgxYTUxMzc0MiwgMHhlZjY4MjhiYywgMHg1MjAzNjVkNixcbiAgICAweDJkNmE3N2FiLCAweDM1MjdlZDRiLCAweDgyMWZkMjE2LCAweDA5NWM2ZTJlLCAweGRiOTJmMmZiLCAweDVlZWEyOWNiLCAweDE0NTg5MmY1LCAweDkxNTg0ZjdmLFxuICAgIDB4NTQ4MzY5N2IsIDB4MjY2N2E4Y2MsIDB4ODUxOTYwNDgsIDB4OGM0YmFjZWEsIDB4ODMzODYwZDQsIDB4MGQyM2UwZjksIDB4NmMzODdlOGEsIDB4MGFlNmQyNDksXG4gICAgMHhiMjg0NjAwYywgMHhkODM1NzMxZCwgMHhkY2IxYzY0NywgMHhhYzRjNTZlYSwgMHgzZWJkODFiMywgMHgyMzBlYWJiMCwgMHg2NDM4YmM4NywgMHhmMGI1YjFmYSxcbiAgICAweDhmNWVhMmIzLCAweGZjMTg0NjQyLCAweDBhMDM2YjdhLCAweDRmYjA4OWJkLCAweDY0OWRhNTg5LCAweGEzNDU0MTVlLCAweDVjMDM4MzIzLCAweDNlNWQzYmI5LFxuICAgIDB4NDNkNzk1NzIsIDB4N2U2ZGQwN2MsIDB4MDZkZmRmMWUsIDB4NmM2Y2M0ZWYsIDB4NzE2MGE1MzksIDB4NzNiZmJlNzAsIDB4ODM4Nzc2MDUsIDB4NDUyM2VjZjEpO1xuXG4gIHNCb3hbMl0gPSBuZXcgQXJyYXkoXG4gICAgMHg4ZGVmYzI0MCwgMHgyNWZhNWQ5ZiwgMHhlYjkwM2RiZiwgMHhlODEwYzkwNywgMHg0NzYwN2ZmZiwgMHgzNjlmZTQ0YiwgMHg4YzFmYzY0NCwgMHhhZWNlY2E5MCxcbiAgICAweGJlYjFmOWJmLCAweGVlZmJjYWVhLCAweGU4Y2YxOTUwLCAweDUxZGYwN2FlLCAweDkyMGU4ODA2LCAweGYwYWQwNTQ4LCAweGUxM2M4ZDgzLCAweDkyNzAxMGQ1LFxuICAgIDB4MTExMDdkOWYsIDB4MDc2NDdkYjksIDB4YjJlM2U0ZDQsIDB4M2Q0ZjI4NWUsIDB4YjlhZmE4MjAsIDB4ZmFkZTgyZTAsIDB4YTA2NzI2OGIsIDB4ODI3Mjc5MmUsXG4gICAgMHg1NTNmYjJjMCwgMHg0ODlhZTIyYiwgMHhkNGVmOTc5NCwgMHgxMjVlM2ZiYywgMHgyMWZmZmNlZSwgMHg4MjViMWJmZCwgMHg5MjU1YzVlZCwgMHgxMjU3YTI0MCxcbiAgICAweDRlMWE4MzAyLCAweGJhZTA3ZmZmLCAweDUyODI0NmU3LCAweDhlNTcxNDBlLCAweDMzNzNmN2JmLCAweDhjOWY4MTg4LCAweGE2ZmM0ZWU4LCAweGM5ODJiNWE1LFxuICAgIDB4YThjMDFkYjcsIDB4NTc5ZmMyNjQsIDB4NjcwOTRmMzEsIDB4ZjJiZDNmNWYsIDB4NDBmZmY3YzEsIDB4MWZiNzhkZmMsIDB4OGU2YmQyYzEsIDB4NDM3YmU1OWIsXG4gICAgMHg5OWIwM2RiZiwgMHhiNWRiYzY0YiwgMHg2MzhkYzBlNiwgMHg1NTgxOWQ5OSwgMHhhMTk3YzgxYywgMHg0YTAxMmQ2ZSwgMHhjNTg4NGEyOCwgMHhjY2MzNmY3MSxcbiAgICAweGI4NDNjMjEzLCAweDZjMDc0M2YxLCAweDgzMDk4OTNjLCAweDBmZWRkZDVmLCAweDJmN2ZlODUwLCAweGQ3YzA3ZjdlLCAweDAyNTA3ZmJmLCAweDVhZmI5YTA0LFxuICAgIDB4YTc0N2QyZDAsIDB4MTY1MTE5MmUsIDB4YWY3MGJmM2UsIDB4NThjMzEzODAsIDB4NWY5ODMwMmUsIDB4NzI3Y2MzYzQsIDB4MGEwZmI0MDIsIDB4MGY3ZmVmODIsXG4gICAgMHg4Yzk2ZmRhZCwgMHg1ZDJjMmFhZSwgMHg4ZWU5OWE0OSwgMHg1MGRhODhiOCwgMHg4NDI3ZjRhMCwgMHgxZWFjNTc5MCwgMHg3OTZmYjQ0OSwgMHg4MjUyZGMxNSxcbiAgICAweGVmYmQ3ZDliLCAweGE2NzI1OTdkLCAweGFkYTg0MGQ4LCAweDQ1ZjU0NTA0LCAweGZhNWQ3NDAzLCAweGU4M2VjMzA1LCAweDRmOTE3NTFhLCAweDkyNTY2OWMyLFxuICAgIDB4MjNlZmU5NDEsIDB4YTkwM2YxMmUsIDB4NjAyNzBkZjIsIDB4MDI3NmU0YjYsIDB4OTRmZDY1NzQsIDB4OTI3OTg1YjIsIDB4ODI3NmRiY2IsIDB4MDI3NzgxNzYsXG4gICAgMHhmOGFmOTE4ZCwgMHg0ZTQ4Zjc5ZSwgMHg4ZjYxNmRkZiwgMHhlMjlkODQwZSwgMHg4NDJmN2Q4MywgMHgzNDBjZTVjOCwgMHg5NmJiYjY4MiwgMHg5M2I0YjE0OCxcbiAgICAweGVmMzAzY2FiLCAweDk4NGZhZjI4LCAweDc3OWZhZjliLCAweDkyZGM1NjBkLCAweDIyNGQxZTIwLCAweDg0MzdhYTg4LCAweDdkMjlkYzk2LCAweDI3NTZkM2RjLFxuICAgIDB4OGI5MDdjZWUsIDB4YjUxZmQyNDAsIDB4ZTdjMDdjZTMsIDB4ZTU2NmI0YTEsIDB4YzNlOTYxNWUsIDB4M2NmODIwOWQsIDB4NjA5NGQxZTMsIDB4Y2Q5Y2EzNDEsXG4gICAgMHg1Yzc2NDYwZSwgMHgwMGVhOTgzYiwgMHhkNGQ2Nzg4MSwgMHhmZDQ3NTcyYywgMHhmNzZjZWRkOSwgMHhiZGE4MjI5YywgMHgxMjdkYWRhYSwgMHg0MzhhMDc0ZSxcbiAgICAweDFmOTdjMDkwLCAweDA4MWJkYjhhLCAweDkzYTA3ZWJlLCAweGI5MzhjYTE1LCAweDk3YjAzY2ZmLCAweDNkYzJjMGY4LCAweDhkMWFiMmVjLCAweDY0MzgwZTUxLFxuICAgIDB4NjhjYzdiZmIsIDB4ZDkwZjI3ODgsIDB4MTI0OTAxODEsIDB4NWRlNWZmZDQsIDB4ZGQ3ZWY4NmEsIDB4NzZhMmUyMTQsIDB4YjlhNDAzNjgsIDB4OTI1ZDk1OGYsXG4gICAgMHg0YjM5ZmZmYSwgMHhiYTM5YWVlOSwgMHhhNGZmZDMwYiwgMHhmYWY3OTMzYiwgMHg2ZDQ5ODYyMywgMHgxOTNjYmNmYSwgMHgyNzYyNzU0NSwgMHg4MjVjZjQ3YSxcbiAgICAweDYxYmQ4YmEwLCAweGQxMWU0MmQxLCAweGNlYWQwNGY0LCAweDEyN2VhMzkyLCAweDEwNDI4ZGI3LCAweDgyNzJhOTcyLCAweDkyNzBjNGE4LCAweDEyN2RlNTBiLFxuICAgIDB4Mjg1YmExYzgsIDB4M2M2MmY0NGYsIDB4MzVjMGVhYTUsIDB4ZTgwNWQyMzEsIDB4NDI4OTI5ZmIsIDB4YjRmY2RmODIsIDB4NGZiNjZhNTMsIDB4MGU3ZGMxNWIsXG4gICAgMHgxZjA4MWZhYiwgMHgxMDg2MThhZSwgMHhmY2ZkMDg2ZCwgMHhmOWZmMjg4OSwgMHg2OTRiY2MxMSwgMHgyMzZhNWNhZSwgMHgxMmRlY2E0ZCwgMHgyYzNmOGNjNSxcbiAgICAweGQyZDAyZGZlLCAweGY4ZWY1ODk2LCAweGU0Y2Y1MmRhLCAweDk1MTU1YjY3LCAweDQ5NGE0ODhjLCAweGI5YjZhODBjLCAweDVjOGY4MmJjLCAweDg5ZDM2YjQ1LFxuICAgIDB4M2E2MDk0MzcsIDB4ZWMwMGM5YTksIDB4NDQ3MTUyNTMsIDB4MGE4NzRiNDksIDB4ZDc3M2JjNDAsIDB4N2MzNDY3MWMsIDB4MDI3MTdlZjYsIDB4NGZlYjU1MzYsXG4gICAgMHhhMmQwMmZmZiwgMHhkMmJmNjBjNCwgMHhkNDNmMDNjMCwgMHg1MGI0ZWY2ZCwgMHgwNzQ3OGNkMSwgMHgwMDZlMTg4OCwgMHhhMmU1M2Y1NSwgMHhiOWU2ZDRiYyxcbiAgICAweGEyMDQ4MDE2LCAweDk3NTczODMzLCAweGQ3MjA3ZDY3LCAweGRlMGY4ZjNkLCAweDcyZjg3YjMzLCAweGFiY2M0ZjMzLCAweDc2ODhjNTVkLCAweDdiMDBhNmIwLFxuICAgIDB4OTQ3YjAwMDEsIDB4NTcwMDc1ZDIsIDB4ZjliYjg4ZjgsIDB4ODk0MjAxOWUsIDB4NDI2NGE1ZmYsIDB4ODU2MzAyZTAsIDB4NzJkYmQ5MmIsIDB4ZWU5NzFiNjksXG4gICAgMHg2ZWEyMmZkZSwgMHg1ZjA4YWUyYiwgMHhhZjdhNjE2ZCwgMHhlNWM5ODc2NywgMHhjZjFmZWJkMiwgMHg2MWVmYzhjMiwgMHhmMWFjMjU3MSwgMHhjYzgyMzljMixcbiAgICAweDY3MjE0Y2I4LCAweGIxZTU4M2QxLCAweGI3ZGMzZTYyLCAweDdmMTBiZGNlLCAweGY5MGE1YzM4LCAweDBmZjA0NDNkLCAweDYwNmU2ZGM2LCAweDYwNTQzYTQ5LFxuICAgIDB4NTcyN2MxNDgsIDB4MmJlOThhMWQsIDB4OGFiNDE3MzgsIDB4MjBlMWJlMjQsIDB4YWY5NmRhMGYsIDB4Njg0NTg0MjUsIDB4OTk4MzNiZTUsIDB4NjAwZDQ1N2QsXG4gICAgMHgyODJmOTM1MCwgMHg4MzM0YjM2MiwgMHhkOTFkMTEyMCwgMHgyYjZkOGRhMCwgMHg2NDJiMWUzMSwgMHg5YzMwNWEwMCwgMHg1MmJjZTY4OCwgMHgxYjAzNTg4YSxcbiAgICAweGY3YmFlZmQ1LCAweDQxNDJlZDljLCAweGE0MzE1YzExLCAweDgzMzIzZWM1LCAweGRmZWY0NjM2LCAweGExMzNjNTAxLCAweGU5ZDM1MzFjLCAweGVlMzUzNzgzKTtcblxuICBzQm94WzNdID0gbmV3IEFycmF5KFxuICAgIDB4OWRiMzA0MjAsIDB4MWZiNmU5ZGUsIDB4YTdiZTdiZWYsIDB4ZDI3M2EyOTgsIDB4NGE0ZjdiZGIsIDB4NjRhZDhjNTcsIDB4ODU1MTA0NDMsIDB4ZmEwMjBlZDEsXG4gICAgMHg3ZTI4N2FmZiwgMHhlNjBmYjY2MywgMHgwOTVmMzVhMSwgMHg3OWViZjEyMCwgMHhmZDA1OWQ0MywgMHg2NDk3YjdiMSwgMHhmMzY0MWY2MywgMHgyNDFlNGFkZixcbiAgICAweDI4MTQ3ZjVmLCAweDRmYTJiOGNkLCAweGM5NDMwMDQwLCAweDBjYzMyMjIwLCAweGZkZDMwYjMwLCAweGMwYTUzNzRmLCAweDFkMmQwMGQ5LCAweDI0MTQ3YjE1LFxuICAgIDB4ZWU0ZDExMWEsIDB4MGZjYTUxNjcsIDB4NzFmZjkwNGMsIDB4MmQxOTVmZmUsIDB4MWEwNTY0NWYsIDB4MGMxM2ZlZmUsIDB4MDgxYjA4Y2EsIDB4MDUxNzAxMjEsXG4gICAgMHg4MDUzMDEwMCwgMHhlODNlNWVmZSwgMHhhYzlhZjRmOCwgMHg3ZmU3MjcwMSwgMHhkMmI4ZWU1ZiwgMHgwNmRmNDI2MSwgMHhiYjllOWI4YSwgMHg3MjkzZWEyNSxcbiAgICAweGNlODRmZmRmLCAweGY1NzE4ODAxLCAweDNkZDY0YjA0LCAweGEyNmYyNjNiLCAweDdlZDQ4NDAwLCAweDU0N2VlYmU2LCAweDQ0NmQ0Y2EwLCAweDZjZjNkNmY1LFxuICAgIDB4MjY0OWFiZGYsIDB4YWVhMGM3ZjUsIDB4MzYzMzhjYzEsIDB4NTAzZjdlOTMsIDB4ZDM3NzIwNjEsIDB4MTFiNjM4ZTEsIDB4NzI1MDBlMDMsIDB4ZjgwZWIyYmIsXG4gICAgMHhhYmUwNTAyZSwgMHhlYzhkNzdkZSwgMHg1Nzk3MWU4MSwgMHhlMTRmNjc0NiwgMHhjOTMzNTQwMCwgMHg2OTIwMzE4ZiwgMHgwODFkYmI5OSwgMHhmZmMzMDRhNSxcbiAgICAweDRkMzUxODA1LCAweDdmM2Q1Y2UzLCAweGE2Yzg2NmM2LCAweDVkNWJjY2E5LCAweGRhZWM2ZmVhLCAweDlmOTI2ZjkxLCAweDlmNDYyMjJmLCAweDM5OTE0NjdkLFxuICAgIDB4YTViZjZkOGUsIDB4MTE0M2M0NGYsIDB4NDM5NTgzMDIsIDB4ZDAyMTRlZWIsIDB4MDIyMDgzYjgsIDB4M2ZiNjE4MGMsIDB4MThmODkzMWUsIDB4MjgxNjU4ZTYsXG4gICAgMHgyNjQ4NmUzZSwgMHg4YmQ3OGE3MCwgMHg3NDc3ZTRjMSwgMHhiNTA2ZTA3YywgMHhmMzJkMGEyNSwgMHg3OTA5OGIwMiwgMHhlNGVhYmI4MSwgMHgyODEyM2IyMyxcbiAgICAweDY5ZGVhZDM4LCAweDE1NzRjYTE2LCAweGRmODcxYjYyLCAweDIxMWM0MGI3LCAweGE1MWE5ZWY5LCAweDAwMTQzNzdiLCAweDA0MWU4YWM4LCAweDA5MTE0MDAzLFxuICAgIDB4YmQ1OWU0ZDIsIDB4ZTNkMTU2ZDUsIDB4NGZlODc2ZDUsIDB4MmY5MWEzNDAsIDB4NTU3YmU4ZGUsIDB4MDBlYWU0YTcsIDB4MGNlNWMyZWMsIDB4NGRiNGJiYTYsXG4gICAgMHhlNzU2YmRmZiwgMHhkZDMzNjlhYywgMHhlYzE3YjAzNSwgMHgwNjU3MjMyNywgMHg5OWFmYzhiMCwgMHg1NmM4YzM5MSwgMHg2YjY1ODExYywgMHg1ZTE0NjExOSxcbiAgICAweDZlODVjYjc1LCAweGJlMDdjMDAyLCAweGMyMzI1NTc3LCAweDg5M2ZmNGVjLCAweDViYmZjOTJkLCAweGQwZWMzYjI1LCAweGI3ODAxYWI3LCAweDhkNmQzYjI0LFxuICAgIDB4MjBjNzYzZWYsIDB4YzM2NmE1ZmMsIDB4OWMzODI4ODAsIDB4MGFjZTMyMDUsIDB4YWFjOTU0OGEsIDB4ZWNhMWQ3YzcsIDB4MDQxYWZhMzIsIDB4MWQxNjYyNWEsXG4gICAgMHg2NzAxOTAyYywgMHg5Yjc1N2E1NCwgMHgzMWQ0NzdmNywgMHg5MTI2YjAzMSwgMHgzNmNjNmZkYiwgMHhjNzBiOGI0NiwgMHhkOWU2NmE0OCwgMHg1NmU1NWE3OSxcbiAgICAweDAyNmE0Y2ViLCAweDUyNDM3ZWZmLCAweDJmOGY3NmI0LCAweDBkZjk4MGE1LCAweDg2NzRjZGUzLCAweGVkZGEwNGViLCAweDE3YTliZTA0LCAweDJjMThmNGRmLFxuICAgIDB4Yjc3NDdmOWQsIDB4YWIyYWY3YjQsIDB4ZWZjMzRkMjAsIDB4MmUwOTZiN2MsIDB4MTc0MWEyNTQsIDB4ZTViNmEwMzUsIDB4MjEzZDQyZjYsIDB4MmMxYzdjMjYsXG4gICAgMHg2MWMyZjUwZiwgMHg2NTUyZGFmOSwgMHhkMmMyMzFmOCwgMHgyNTEzMGY2OSwgMHhkODE2N2ZhMiwgMHgwNDE4ZjJjOCwgMHgwMDFhOTZhNiwgMHgwZDE1MjZhYixcbiAgICAweDYzMzE1YzIxLCAweDVlMGE3MmVjLCAweDQ5YmFmZWZkLCAweDE4NzkwOGQ5LCAweDhkMGRiZDg2LCAweDMxMTE3MGE3LCAweDNlOWI2NDBjLCAweGNjM2UxMGQ3LFxuICAgIDB4ZDVjYWQzYjYsIDB4MGNhZWMzODgsIDB4ZjczMDAxZTEsIDB4NmM3MjhhZmYsIDB4NzFlYWUyYTEsIDB4MWY5YWYzNmUsIDB4Y2ZjYmQxMmYsIDB4YzFkZTg0MTcsXG4gICAgMHhhYzA3YmU2YiwgMHhjYjQ0YTFkOCwgMHg4YjliMGY1NiwgMHgwMTM5ODhjMywgMHhiMWM1MmZjYSwgMHhiNGJlMzFjZCwgMHhkODc4MjgwNiwgMHgxMmEzYTRlMixcbiAgICAweDZmN2RlNTMyLCAweDU4ZmQ3ZWI2LCAweGQwMWVlOTAwLCAweDI0YWRmZmMyLCAweGY0OTkwZmM1LCAweDk3MTFhYWM1LCAweDAwMWQ3Yjk1LCAweDgyZTVlN2QyLFxuICAgIDB4MTA5ODczZjYsIDB4MDA2MTMwOTYsIDB4YzMyZDk1MjEsIDB4YWRhMTIxZmYsIDB4Mjk5MDg0MTUsIDB4N2ZiYjk3N2YsIDB4YWY5ZWIzZGIsIDB4MjljOWVkMmEsXG4gICAgMHg1Y2UyYTQ2NSwgMHhhNzMwZjMyYywgMHhkMGFhM2ZlOCwgMHg4YTVjYzA5MSwgMHhkNDllMmNlNywgMHgwY2U0NTRhOSwgMHhkNjBhY2Q4NiwgMHgwMTVmMTkxOSxcbiAgICAweDc3MDc5MTAzLCAweGRlYTAzYWY2LCAweDc4YTg1NjVlLCAweGRlZTM1NmRmLCAweDIxZjA1Y2JlLCAweDhiNzVlMzg3LCAweGIzYzUwNjUxLCAweGI4YTVjM2VmLFxuICAgIDB4ZDhlZWI2ZDIsIDB4ZTUyM2JlNzcsIDB4YzIxNTQ1MjksIDB4MmY2OWVmZGYsIDB4YWZlNjdhZmIsIDB4ZjQ3MGM0YjIsIDB4ZjNlMGViNWIsIDB4ZDZjYzk4NzYsXG4gICAgMHgzOWU0NDYwYywgMHgxZmRhODUzOCwgMHgxOTg3ODMyZiwgMHhjYTAwNzM2NywgMHhhOTkxNDRmOCwgMHgyOTZiMjk5ZSwgMHg0OTJmYzI5NSwgMHg5MjY2YmVhYixcbiAgICAweGI1Njc2ZTY5LCAweDliZDNkZGRhLCAweGRmN2UwNTJmLCAweGRiMjU3MDFjLCAweDFiNWU1MWVlLCAweGY2NTMyNGU2LCAweDZhZmNlMzZjLCAweDAzMTZjYzA0LFxuICAgIDB4ODY0NDIxM2UsIDB4YjdkYzU5ZDAsIDB4Nzk2NTI5MWYsIDB4Y2NkNmZkNDMsIDB4NDE4MjM5NzksIDB4OTMyYmNkZjYsIDB4YjY1N2MzNGQsIDB4NGVkZmQyODIsXG4gICAgMHg3YWU1MjkwYywgMHgzY2I5NTM2YiwgMHg4NTFlMjBmZSwgMHg5ODMzNTU3ZSwgMHgxM2VjZjBiMCwgMHhkM2ZmYjM3MiwgMHgzZjg1YzVjMSwgMHgwYWVmN2VkMik7XG5cbiAgc0JveFs0XSA9IG5ldyBBcnJheShcbiAgICAweDdlYzkwYzA0LCAweDJjNmU3NGI5LCAweDliMGU2NmRmLCAweGE2MzM3OTExLCAweGI4NmE3ZmZmLCAweDFkZDM1OGY1LCAweDQ0ZGQ5ZDQ0LCAweDE3MzExNjdmLFxuICAgIDB4MDhmYmYxZmEsIDB4ZTdmNTExY2MsIDB4ZDIwNTFiMDAsIDB4NzM1YWJhMDAsIDB4MmFiNzIyZDgsIDB4Mzg2MzgxY2IsIDB4YWNmNjI0M2EsIDB4NjliZWZkN2EsXG4gICAgMHhlNmEyZTc3ZiwgMHhmMGM3MjBjZCwgMHhjNDQ5NDgxNiwgMHhjY2Y1YzE4MCwgMHgzODg1MTY0MCwgMHgxNWIwYTg0OCwgMHhlNjhiMThjYiwgMHg0Y2FhZGVmZixcbiAgICAweDVmNDgwYTAxLCAweDA0MTJiMmFhLCAweDI1OTgxNGZjLCAweDQxZDBlZmUyLCAweDRlNDBiNDhkLCAweDI0OGViNmZiLCAweDhkYmExY2ZlLCAweDQxYTk5YjAyLFxuICAgIDB4MWE1NTBhMDQsIDB4YmE4ZjY1Y2IsIDB4NzI1MWY0ZTcsIDB4OTVhNTE3MjUsIDB4YzEwNmVjZDcsIDB4OTdhNTk4MGEsIDB4YzUzOWI5YWEsIDB4NGQ3OWZlNmEsXG4gICAgMHhmMmYzZjc2MywgMHg2OGFmODA0MCwgMHhlZDBjOWU1NiwgMHgxMWI0OTU4YiwgMHhlMWViNWE4OCwgMHg4NzA5ZTZiMCwgMHhkN2UwNzE1NiwgMHg0ZTI5ZmVhNyxcbiAgICAweDYzNjZlNTJkLCAweDAyZDFjMDAwLCAweGM0YWM4ZTA1LCAweDkzNzdmNTcxLCAweDBjMDUzNzJhLCAweDU3ODUzNWYyLCAweDIyNjFiZTAyLCAweGQ2NDJhMGM5LFxuICAgIDB4ZGYxM2EyODAsIDB4NzRiNTViZDIsIDB4NjgyMTk5YzAsIDB4ZDQyMWU1ZWMsIDB4NTNmYjNjZTgsIDB4YzhhZGVkYjMsIDB4MjhhODdmYzksIDB4M2Q5NTk5ODEsXG4gICAgMHg1YzFmZjkwMCwgMHhmZTM4ZDM5OSwgMHgwYzRlZmYwYiwgMHgwNjI0MDdlYSwgMHhhYTJmNGZiMSwgMHg0ZmI5Njk3NiwgMHg5MGM3OTUwNSwgMHhiMGE4YTc3NCxcbiAgICAweGVmNTVhMWZmLCAweGU1OWNhMmMyLCAweGE2YjYyZDI3LCAweGU2NmE0MjYzLCAweGRmNjUwMDFmLCAweDBlYzUwOTY2LCAweGRmZGQ1NWJjLCAweDI5ZGUwNjU1LFxuICAgIDB4OTExZTczOWEsIDB4MTdhZjg5NzUsIDB4MzJjNzkxMWMsIDB4ODlmODk0NjgsIDB4MGQwMWU5ODAsIDB4NTI0NzU1ZjQsIDB4MDNiNjNjYzksIDB4MGNjODQ0YjIsXG4gICAgMHhiY2YzZjBhYSwgMHg4N2FjMzZlOSwgMHhlNTNhNzQyNiwgMHgwMWIzZDgyYiwgMHgxYTllNzQ0OSwgMHg2NGVlMmQ3ZSwgMHhjZGRiYjFkYSwgMHgwMWM5NDkxMCxcbiAgICAweGI4NjhiZjgwLCAweDBkMjZmM2ZkLCAweDkzNDJlZGU3LCAweDA0YTVjMjg0LCAweDYzNjczN2I2LCAweDUwZjViNjE2LCAweGYyNDc2NmUzLCAweDhlY2EzNmMxLFxuICAgIDB4MTM2ZTA1ZGIsIDB4ZmVmMTgzOTEsIDB4ZmI4ODdhMzcsIDB4ZDZlN2Y3ZDQsIDB4YzdmYjdkYzksIDB4MzA2M2ZjZGYsIDB4YjZmNTg5ZGUsIDB4ZWMyOTQxZGEsXG4gICAgMHgyNmU0NjY5NSwgMHhiNzU2NjQxOSwgMHhmNjU0ZWZjNSwgMHhkMDhkNThiNywgMHg0ODkyNTQwMSwgMHhjMWJhY2I3ZiwgMHhlNWZmNTUwZiwgMHhiNjA4MzA0OSxcbiAgICAweDViYjVkMGU4LCAweDg3ZDcyZTVhLCAweGFiNmE2ZWUxLCAweDIyM2E2NmNlLCAweGM2MmJmM2NkLCAweDllMDg4NWY5LCAweDY4Y2IzZTQ3LCAweDA4NmMwMTBmLFxuICAgIDB4YTIxZGU4MjAsIDB4ZDE4YjY5ZGUsIDB4ZjNmNjU3NzcsIDB4ZmEwMmMzZjYsIDB4NDA3ZWRhYzMsIDB4Y2JiM2Q1NTAsIDB4MTc5MzA4NGQsIDB4YjBkNzBlYmEsXG4gICAgMHgwYWIzNzhkNSwgMHhkOTUxZmIwYywgMHhkZWQ3ZGE1NiwgMHg0MTI0YmJlNCwgMHg5NGNhMGI1NiwgMHgwZjU3NTVkMSwgMHhlMGUxZTU2ZSwgMHg2MTg0YjViZSxcbiAgICAweDU4MGEyNDlmLCAweDk0Zjc0YmMwLCAweGUzMjc4ODhlLCAweDlmN2I1NTYxLCAweGMzZGMwMjgwLCAweDA1Njg3NzE1LCAweDY0NmM2YmQ3LCAweDQ0OTA0ZGIzLFxuICAgIDB4NjZiNGYwYTMsIDB4YzBmMTY0OGEsIDB4Njk3ZWQ1YWYsIDB4NDllOTJmZjYsIDB4MzA5ZTM3NGYsIDB4MmNiNjM1NmEsIDB4ODU4MDg1NzMsIDB4NDk5MWY4NDAsXG4gICAgMHg3NmYwYWUwMiwgMHgwODNiZTg0ZCwgMHgyODQyMWM5YSwgMHg0NDQ4OTQwNiwgMHg3MzZlNGNiOCwgMHhjMTA5MjkxMCwgMHg4YmM5NWZjNiwgMHg3ZDg2OWNmNCxcbiAgICAweDEzNGY2MTZmLCAweDJlNzcxMThkLCAweGIzMWIyYmUxLCAweGFhOTBiNDcyLCAweDNjYTVkNzE3LCAweDdkMTYxYmJhLCAweDljYWQ5MDEwLCAweGFmNDYyYmEyLFxuICAgIDB4OWZlNDU5ZDIsIDB4NDVkMzQ1NTksIDB4ZDlmMmRhMTMsIDB4ZGJjNjU0ODcsIDB4ZjNlNGY5NGUsIDB4MTc2ZDQ4NmYsIDB4MDk3YzEzZWEsIDB4NjMxZGE1YzcsXG4gICAgMHg0NDVmNzM4MiwgMHgxNzU2ODNmNCwgMHhjZGM2NmE5NywgMHg3MGJlMDI4OCwgMHhiM2NkY2Y3MiwgMHg2ZTVkZDJmMywgMHgyMDkzNjA3OSwgMHg0NTliODBhNSxcbiAgICAweGJlNjBlMmRiLCAweGE5YzIzMTAxLCAweGViYTUzMTVjLCAweDIyNGU0MmYyLCAweDFjNWMxNTcyLCAweGY2NzIxYjJjLCAweDFhZDJmZmYzLCAweDhjMjU0MDRlLFxuICAgIDB4MzI0ZWQ3MmYsIDB4NDA2N2I3ZmQsIDB4MDUyMzEzOGUsIDB4NWNhM2JjNzgsIDB4ZGMwZmQ2NmUsIDB4NzU5MjIyODMsIDB4Nzg0ZDZiMTcsIDB4NThlYmIxNmUsXG4gICAgMHg0NDA5NGY4NSwgMHgzZjQ4MWQ4NywgMHhmY2ZlYWU3YiwgMHg3N2I1ZmY3NiwgMHg4YzIzMDJiZiwgMHhhYWY0NzU1NiwgMHg1ZjQ2YjAyYSwgMHgyYjA5MjgwMSxcbiAgICAweDNkMzhmNWY3LCAweDBjYTgxZjM2LCAweDUyYWY0YThhLCAweDY2ZDVlN2MwLCAweGRmM2IwODc0LCAweDk1MDU1MTEwLCAweDFiNWFkN2E4LCAweGY2MWVkNWFkLFxuICAgIDB4NmNmNmU0NzksIDB4MjA3NTgxODQsIDB4ZDBjZWZhNjUsIDB4ODhmN2JlNTgsIDB4NGEwNDY4MjYsIDB4MGZmNmY4ZjMsIDB4YTA5YzdmNzAsIDB4NTM0NmFiYTAsXG4gICAgMHg1Y2U5NmMyOCwgMHhlMTc2ZWRhMywgMHg2YmFjMzA3ZiwgMHgzNzY4MjlkMiwgMHg4NTM2MGZhOSwgMHgxN2UzZmUyYSwgMHgyNGI3OTc2NywgMHhmNWE5NmIyMCxcbiAgICAweGQ2Y2QyNTk1LCAweDY4ZmYxZWJmLCAweDc1NTU0NDJjLCAweGYxOWYwNmJlLCAweGY5ZTA2NTlhLCAweGVlYjk0OTFkLCAweDM0MDEwNzE4LCAweGJiMzBjYWI4LFxuICAgIDB4ZTgyMmZlMTUsIDB4ODg1NzA5ODMsIDB4NzUwZTYyNDksIDB4ZGE2MjdlNTUsIDB4NWU3NmZmYTgsIDB4YjE1MzQ1NDYsIDB4NmQ0N2RlMDgsIDB4ZWZlOWU3ZDQpO1xuXG4gIHNCb3hbNV0gPSBuZXcgQXJyYXkoXG4gICAgMHhmNmZhOGY5ZCwgMHgyY2FjNmNlMSwgMHg0Y2EzNDg2NywgMHhlMjMzN2Y3YywgMHg5NWRiMDhlNywgMHgwMTY4NDNiNCwgMHhlY2VkNWNiYywgMHgzMjU1NTNhYyxcbiAgICAweGJmOWYwOTYwLCAweGRmYTFlMmVkLCAweDgzZjA1NzlkLCAweDYzZWQ4NmI5LCAweDFhYjZhNmI4LCAweGRlNWViZTM5LCAweGYzOGZmNzMyLCAweDg5ODliMTM4LFxuICAgIDB4MzNmMTQ5NjEsIDB4YzAxOTM3YmQsIDB4ZjUwNmM2ZGEsIDB4ZTQ2MjVlN2UsIDB4YTMwOGVhOTksIDB4NGUyM2UzM2MsIDB4NzljYmQ3Y2MsIDB4NDhhMTQzNjcsXG4gICAgMHhhMzE0OTYxOSwgMHhmZWM5NGJkNSwgMHhhMTE0MTc0YSwgMHhlYWEwMTg2NiwgMHhhMDg0ZGIyZCwgMHgwOWE4NDg2ZiwgMHhhODg4NjE0YSwgMHgyOTAwYWY5OCxcbiAgICAweDAxNjY1OTkxLCAweGUxOTkyODYzLCAweGM4ZjMwYzYwLCAweDJlNzhlZjNjLCAweGQwZDUxOTMyLCAweGNmMGZlYzE0LCAweGY3Y2EwN2QyLCAweGQwYTgyMDcyLFxuICAgIDB4ZmQ0MTE5N2UsIDB4OTMwNWE2YjAsIDB4ZTg2YmUzZGEsIDB4NzRiZWQzY2QsIDB4MzcyZGE1M2MsIDB4NGM3ZjQ0NDgsIDB4ZGFiNWQ0NDAsIDB4NmRiYTBlYzMsXG4gICAgMHgwODM5MTlhNywgMHg5ZmJhZWVkOSwgMHg0OWRiY2ZiMCwgMHg0ZTY3MGM1MywgMHg1YzNkOWMwMSwgMHg2NGJkYjk0MSwgMHgyYzBlNjM2YSwgMHhiYTdkZDljZCxcbiAgICAweGVhNmY3Mzg4LCAweGU3MGJjNzYyLCAweDM1ZjI5YWRiLCAweDVjNGNkZDhkLCAweGYwZDQ4ZDhjLCAweGI4ODE1M2UyLCAweDA4YTE5ODY2LCAweDFhZTJlYWM4LFxuICAgIDB4Mjg0Y2FmODksIDB4YWE5MjgyMjMsIDB4OTMzNGJlNTMsIDB4M2IzYTIxYmYsIDB4MTY0MzRiZTMsIDB4OWFlYTM5MDYsIDB4ZWZlOGMzNmUsIDB4Zjg5MGNkZDksXG4gICAgMHg4MDIyNmRhZSwgMHhjMzQwYTRhMywgMHhkZjdlOWMwOSwgMHhhNjk0YTgwNywgMHg1YjdjNWVjYywgMHgyMjFkYjNhNiwgMHg5YTY5YTAyZiwgMHg2ODgxOGE1NCxcbiAgICAweGNlYjIyOTZmLCAweDUzYzA4NDNhLCAweGZlODkzNjU1LCAweDI1YmZlNjhhLCAweGI0NjI4YWJjLCAweGNmMjIyZWJmLCAweDI1YWM2ZjQ4LCAweGE5YTk5Mzg3LFxuICAgIDB4NTNiZGRiNjUsIDB4ZTc2ZmZiZTcsIDB4ZTk2N2ZkNzgsIDB4MGJhOTM1NjMsIDB4OGUzNDJiYzEsIDB4ZThhMTFiZTksIDB4NDk4MDc0MGQsIDB4YzgwODdkZmMsXG4gICAgMHg4ZGU0YmY5OSwgMHhhMTExMDFhMCwgMHg3ZmQzNzk3NSwgMHhkYTVhMjZjMCwgMHhlODFmOTk0ZiwgMHg5NTI4Y2Q4OSwgMHhmZDMzOWZlZCwgMHhiODc4MzRiZixcbiAgICAweDVmMDQ0NTZkLCAweDIyMjU4Njk4LCAweGM5YzRjODNiLCAweDJkYzE1NmJlLCAweDRmNjI4ZGFhLCAweDU3ZjU1ZWM1LCAweGUyMjIwYWJlLCAweGQyOTE2ZWJmLFxuICAgIDB4NGVjNzViOTUsIDB4MjRmMmMzYzAsIDB4NDJkMTVkOTksIDB4Y2QwZDdmYTAsIDB4N2I2ZTI3ZmYsIDB4YThkYzhhZjAsIDB4NzM0NWMxMDYsIDB4ZjQxZTIzMmYsXG4gICAgMHgzNTE2MjM4NiwgMHhlNmVhODkyNiwgMHgzMzMzYjA5NCwgMHgxNTdlYzZmMiwgMHgzNzJiNzRhZiwgMHg2OTI1NzNlNCwgMHhlOWE5ZDg0OCwgMHhmMzE2MDI4OSxcbiAgICAweDNhNjJlZjFkLCAweGE3ODdlMjM4LCAweGYzYTVmNjc2LCAweDc0MzY0ODUzLCAweDIwOTUxMDYzLCAweDQ1NzY2OThkLCAweGI2ZmFkNDA3LCAweDU5MmFmOTUwLFxuICAgIDB4MzZmNzM1MjMsIDB4NGNmYjZlODcsIDB4N2RhNGNlYzAsIDB4NmMxNTJkYWEsIDB4Y2IwMzk2YTgsIDB4YzUwZGZlNWQsIDB4ZmNkNzA3YWIsIDB4MDkyMWM0MmYsXG4gICAgMHg4OWRmZjBiYiwgMHg1ZmUyYmU3OCwgMHg0NDhmNGYzMywgMHg3NTQ2MTNjOSwgMHgyYjA1ZDA4ZCwgMHg0OGI5ZDU4NSwgMHhkYzA0OTQ0MSwgMHhjODA5OGY5YixcbiAgICAweDdkZWRlNzg2LCAweGMzOWEzMzczLCAweDQyNDEwMDA1LCAweDZhMDkxNzUxLCAweDBlZjNjOGE2LCAweDg5MDA3MmQ2LCAweDI4MjA3NjgyLCAweGE5YTlmN2JlLFxuICAgIDB4YmYzMjY3OWQsIDB4ZDQ1YjViNzUsIDB4YjM1M2ZkMDAsIDB4Y2JiMGUzNTgsIDB4ODMwZjIyMGEsIDB4MWY4ZmIyMTQsIDB4ZDM3MmNmMDgsIDB4Y2MzYzRhMTMsXG4gICAgMHg4Y2Y2MzE2NiwgMHgwNjFjODdiZSwgMHg4OGM5OGY4OCwgMHg2MDYyZTM5NywgMHg0N2NmOGU3YSwgMHhiNmM4NTI4MywgMHgzY2MyYWNmYiwgMHgzZmMwNjk3NixcbiAgICAweDRlOGYwMjUyLCAweDY0ZDgzMTRkLCAweGRhMzg3MGUzLCAweDFlNjY1NDU5LCAweGMxMDkwOGYwLCAweDUxMzAyMWE1LCAweDZjNWI2OGI3LCAweDgyMmY4YWEwLFxuICAgIDB4MzAwN2NkM2UsIDB4NzQ3MTllZWYsIDB4ZGM4NzI2ODEsIDB4MDczMzQwZDQsIDB4N2U0MzJmZDksIDB4MGM1ZWMyNDEsIDB4ODgwOTI4NmMsIDB4ZjU5MmQ4OTEsXG4gICAgMHgwOGE5MzBmNiwgMHg5NTdlZjMwNSwgMHhiN2ZiZmZiZCwgMHhjMjY2ZTk2ZiwgMHg2ZmU0YWM5OCwgMHhiMTczZWNjMCwgMHhiYzYwYjQyYSwgMHg5NTM0OThkYSxcbiAgICAweGZiYTFhZTEyLCAweDJkNGJkNzM2LCAweDBmMjVmYWFiLCAweGE0ZjNmY2ViLCAweGUyOTY5MTIzLCAweDI1N2YwYzNkLCAweDkzNDhhZjQ5LCAweDM2MTQwMGJjLFxuICAgIDB4ZTg4MTZmNGEsIDB4MzgxNGYyMDAsIDB4YTNmOTQwNDMsIDB4OWM3YTU0YzIsIDB4YmM3MDRmNTcsIDB4ZGE0MWU3ZjksIDB4YzI1YWQzM2EsIDB4NTRmNGEwODQsXG4gICAgMHhiMTdmNTUwNSwgMHg1OTM1N2NiZSwgMHhlZGJkMTVjOCwgMHg3Zjk3YzVhYiwgMHhiYTVhYzdiNSwgMHhiNmY2ZGVhZiwgMHgzYTQ3OWMzYSwgMHg1MzAyZGEyNSxcbiAgICAweDY1M2Q3ZTZhLCAweDU0MjY4ZDQ5LCAweDUxYTQ3N2VhLCAweDUwMTdkNTViLCAweGQ3ZDI1ZDg4LCAweDQ0MTM2Yzc2LCAweDA0MDRhOGM4LCAweGI4ZTVhMTIxLFxuICAgIDB4YjgxYTkyOGEsIDB4NjBlZDU4NjksIDB4OTdjNTViOTYsIDB4ZWFlYzk5MWIsIDB4Mjk5MzU5MTMsIDB4MDFmZGI3ZjEsIDB4MDg4ZThkZmEsIDB4OWFiNmY2ZjUsXG4gICAgMHgzYjRjYmY5ZiwgMHg0YTVkZTNhYiwgMHhlNjA1MWQzNSwgMHhhMGUxZDg1NSwgMHhkMzZiNGNmMSwgMHhmNTQ0ZWRlYiwgMHhiMGU5MzUyNCwgMHhiZWJiOGZiZCxcbiAgICAweGEyZDc2MmNmLCAweDQ5YzkyZjU0LCAweDM4YjVmMzMxLCAweDcxMjhhNDU0LCAweDQ4MzkyOTA1LCAweGE2NWIxZGI4LCAweDg1MWM5N2JkLCAweGQ2NzVjZjJmKTtcblxuICBzQm94WzZdID0gbmV3IEFycmF5KFxuICAgIDB4ODVlMDQwMTksIDB4MzMyYmY1NjcsIDB4NjYyZGJmZmYsIDB4Y2ZjNjU2OTMsIDB4MmE4ZDdmNmYsIDB4YWI5YmM5MTIsIDB4ZGU2MDA4YTEsIDB4MjAyOGRhMWYsXG4gICAgMHgwMjI3YmNlNywgMHg0ZDY0MjkxNiwgMHgxOGZhYzMwMCwgMHg1MGYxOGI4MiwgMHgyY2IyY2IxMSwgMHhiMjMyZTc1YywgMHg0YjM2OTVmMiwgMHhiMjg3MDdkZSxcbiAgICAweGEwNWZiY2Y2LCAweGNkNDE4MWU5LCAweGUxNTAyMTBjLCAweGUyNGVmMWJkLCAweGIxNjhjMzgxLCAweGZkZTRlNzg5LCAweDVjNzliMGQ4LCAweDFlOGJmZDQzLFxuICAgIDB4NGQ0OTUwMDEsIDB4MzhiZTQzNDEsIDB4OTEzY2VlMWQsIDB4OTJhNzljM2YsIDB4MDg5NzY2YmUsIDB4YmFlZWFkZjQsIDB4MTI4NmJlY2YsIDB4YjZlYWNiMTksXG4gICAgMHgyNjYwYzIwMCwgMHg3NTY1YmRlNCwgMHg2NDI0MWY3YSwgMHg4MjQ4ZGNhOSwgMHhjM2IzYWQ2NiwgMHgyODEzNjA4NiwgMHgwYmQ4ZGZhOCwgMHgzNTZkMWNmMixcbiAgICAweDEwNzc4OWJlLCAweGIzYjJlOWNlLCAweDA1MDJhYThmLCAweDBiYzAzNTFlLCAweDE2NmJmNTJhLCAweGViMTJmZjgyLCAweGUzNDg2OTExLCAweGQzNGQ3NTE2LFxuICAgIDB4NGU3YjNhZmYsIDB4NWY0MzY3MWIsIDB4OWNmNmUwMzcsIDB4NDk4MWFjODMsIDB4MzM0MjY2Y2UsIDB4OGM5MzQxYjcsIDB4ZDBkODU0YzAsIDB4Y2IzYTZjODgsXG4gICAgMHg0N2JjMjgyOSwgMHg0NzI1YmEzNywgMHhhNjZhZDIyYiwgMHg3YWQ2MWYxZSwgMHgwYzVjYmFmYSwgMHg0NDM3ZjEwNywgMHhiNmU3OTk2MiwgMHg0MmQyZDgxNixcbiAgICAweDBhOTYxMjg4LCAweGUxYTVjMDZlLCAweDEzNzQ5ZTY3LCAweDcyZmMwODFhLCAweGIxZDEzOWY3LCAweGY5NTgzNzQ1LCAweGNmMTlkZjU4LCAweGJlYzNmNzU2LFxuICAgIDB4YzA2ZWJhMzAsIDB4MDcyMTFiMjQsIDB4NDVjMjg4MjksIDB4Yzk1ZTMxN2YsIDB4YmM4ZWM1MTEsIDB4MzhiYzQ2ZTksIDB4YzZlNmZhMTQsIDB4YmFlODU4NGEsXG4gICAgMHhhZDRlYmM0NiwgMHg0NjhmNTA4YiwgMHg3ODI5NDM1ZiwgMHhmMTI0MTgzYiwgMHg4MjFkYmE5ZiwgMHhhZmY2MGZmNCwgMHhlYTJjNGU2ZCwgMHgxNmUzOTI2NCxcbiAgICAweDkyNTQ0YThiLCAweDAwOWI0ZmMzLCAweGFiYTY4Y2VkLCAweDlhYzk2Zjc4LCAweDA2YTViNzlhLCAweGIyODU2ZTZlLCAweDFhZWMzY2E5LCAweGJlODM4Njg4LFxuICAgIDB4MGUwODA0ZTksIDB4NTVmMWJlNTYsIDB4ZTdlNTM2M2IsIDB4YjNhMWYyNWQsIDB4ZjdkZWJiODUsIDB4NjFmZTAzM2MsIDB4MTY3NDYyMzMsIDB4M2MwMzRjMjgsXG4gICAgMHhkYTZkMGM3NCwgMHg3OWFhYzU2YywgMHgzY2U0ZTFhZCwgMHg1MWYwYzgwMiwgMHg5OGY4ZjM1YSwgMHgxNjI2YTQ5ZiwgMHhlZWQ4MmIyOSwgMHgxZDM4MmZlMyxcbiAgICAweDBjNGZiOTlhLCAweGJiMzI1Nzc4LCAweDNlYzZkOTdiLCAweDZlNzdhNmE5LCAweGNiNjU4YjVjLCAweGQ0NTIzMGM3LCAweDJiZDE0MDhiLCAweDYwYzAzZWI3LFxuICAgIDB4YjkwNjhkNzgsIDB4YTMzNzU0ZjQsIDB4ZjQzMGM4N2QsIDB4YzhhNzEzMDIsIDB4Yjk2ZDhjMzIsIDB4ZWJkNGU3YmUsIDB4YmU4YjlkMmQsIDB4Nzk3OWZiMDYsXG4gICAgMHhlNzIyNTMwOCwgMHg4Yjc1Y2Y3NywgMHgxMWVmOGRhNCwgMHhlMDgzYzg1OCwgMHg4ZDZiNzg2ZiwgMHg1YTYzMTdhNiwgMHhmYTVjZjdhMCwgMHg1ZGRhMDAzMyxcbiAgICAweGYyOGViZmIwLCAweGY1YjljMzEwLCAweGEwZWFjMjgwLCAweDA4Yjk3NjdhLCAweGEzZDlkMmIwLCAweDc5ZDM0MjE3LCAweDAyMWE3MThkLCAweDlhYzYzMzZhLFxuICAgIDB4MjcxMWZkNjAsIDB4NDM4MDUwZTMsIDB4MDY5OTA4YTgsIDB4M2Q3ZmVkYzQsIDB4ODI2ZDJiZWYsIDB4NGVlYjg0NzYsIDB4NDg4ZGNmMjUsIDB4MzZjOWQ1NjYsXG4gICAgMHgyOGU3NGU0MSwgMHhjMjYxMGFjYSwgMHgzZDQ5YTljZiwgMHhiYWUzYjlkZiwgMHhiNjVmOGRlNiwgMHg5MmFlYWY2NCwgMHgzYWM3ZDVlNiwgMHg5ZWE4MDUwOSxcbiAgICAweGYyMmIwMTdkLCAweGE0MTczZjcwLCAweGRkMWUxNmMzLCAweDE1ZTBkN2Y5LCAweDUwYjFiODg3LCAweDJiOWY0ZmQ1LCAweDYyNWFiYTgyLCAweDZhMDE3OTYyLFxuICAgIDB4MmVjMDFiOWMsIDB4MTU0ODhhYTksIDB4ZDcxNmU3NDAsIDB4NDAwNTVhMmMsIDB4OTNkMjlhMjIsIDB4ZTMyZGJmOWEsIDB4MDU4NzQ1YjksIDB4MzQ1M2RjMWUsXG4gICAgMHhkNjk5Mjk2ZSwgMHg0OTZjZmY2ZiwgMHgxYzlmNDk4NiwgMHhkZmUyZWQwNywgMHhiODcyNDJkMSwgMHgxOWRlN2VhZSwgMHgwNTNlNTYxYSwgMHgxNWFkNmY4YyxcbiAgICAweDY2NjI2YzFjLCAweDcxNTRjMjRjLCAweGVhMDgyYjJhLCAweDkzZWIyOTM5LCAweDE3ZGNiMGYwLCAweDU4ZDRmMmFlLCAweDllYTI5NGZiLCAweDUyY2Y1NjRjLFxuICAgIDB4OTg4M2ZlNjYsIDB4MmVjNDA1ODEsIDB4NzYzOTUzYzMsIDB4MDFkNjY5MmUsIDB4ZDNhMGMxMDgsIDB4YTFlNzE2MGUsIDB4ZTRmMmRmYTYsIDB4NjkzZWQyODUsXG4gICAgMHg3NDkwNDY5OCwgMHg0YzJiMGVkZCwgMHg0Zjc1NzY1NiwgMHg1ZDM5MzM3OCwgMHhhMTMyMjM0ZiwgMHgzZDMyMWM1ZCwgMHhjM2Y1ZTE5NCwgMHg0YjI2OTMwMSxcbiAgICAweGM3OWYwMjJmLCAweDNjOTk3ZTdlLCAweDVlNGY5NTA0LCAweDNmZmFmYmJkLCAweDc2ZjdhZDBlLCAweDI5NjY5M2Y0LCAweDNkMWZjZTZmLCAweGM2MWU0NWJlLFxuICAgIDB4ZDNiNWFiMzQsIDB4ZjcyYmY5YjcsIDB4MWIwNDM0YzAsIDB4NGU3MmI1NjcsIDB4NTU5MmEzM2QsIDB4YjUyMjkzMDEsIDB4Y2ZkMmE4N2YsIDB4NjBhZWI3NjcsXG4gICAgMHgxODE0Mzg2YiwgMHgzMGJjYzMzZCwgMHgzOGEwYzA3ZCwgMHhmZDE2MDZmMiwgMHhjMzYzNTE5YiwgMHg1ODlkZDM5MCwgMHg1NDc5ZjhlNiwgMHgxY2I4ZDY0NyxcbiAgICAweDk3ZmQ2MWE5LCAweGVhNzc1OWY0LCAweDJkNTc1MzlkLCAweDU2OWE1OGNmLCAweGU4NGU2M2FkLCAweDQ2MmUxYjc4LCAweDY1ODBmODdlLCAweGYzODE3OTE0LFxuICAgIDB4OTFkYTU1ZjQsIDB4NDBhMjMwZjMsIDB4ZDE5ODhmMzUsIDB4YjZlMzE4ZDIsIDB4M2ZmYTUwYmMsIDB4M2Q0MGYwMjEsIDB4YzNjMGJkYWUsIDB4NDk1OGMyNGMsXG4gICAgMHg1MThmMzZiMiwgMHg4NGIxZDM3MCwgMHgwZmVkY2U4MywgMHg4NzhkZGFkYSwgMHhmMmEyNzljNywgMHg5NGUwMWJlOCwgMHg5MDcxNmY0YiwgMHg5NTRiOGFhMyk7XG5cbiAgc0JveFs3XSA9IG5ldyBBcnJheShcbiAgICAweGUyMTYzMDBkLCAweGJiZGRmZmZjLCAweGE3ZWJkYWJkLCAweDM1NjQ4MDk1LCAweDc3ODlmOGI3LCAweGU2YzExMjFiLCAweDBlMjQxNjAwLCAweDA1MmNlOGI1LFxuICAgIDB4MTFhOWNmYjAsIDB4ZTU5NTJmMTEsIDB4ZWNlNzk5MGEsIDB4OTM4NmQxNzQsIDB4MmE0MjkzMWMsIDB4NzZlMzgxMTEsIDB4YjEyZGVmM2EsIDB4MzdkZGRkZmMsXG4gICAgMHhkZTlhZGViMSwgMHgwYTBjYzMyYywgMHhiZTE5NzAyOSwgMHg4NGEwMDk0MCwgMHhiYjI0M2EwZiwgMHhiNGQxMzdjZiwgMHhiNDRlNzlmMCwgMHgwNDllZWRmZCxcbiAgICAweDBiMTVhMTVkLCAweDQ4MGQzMTY4LCAweDhiYmJkZTVhLCAweDY2OWRlZDQyLCAweGM3ZWNlODMxLCAweDNmOGY5NWU3LCAweDcyZGYxOTFiLCAweDc1ODAzMzBkLFxuICAgIDB4OTQwNzQyNTEsIDB4NWM3ZGNkZmEsIDB4YWJiZTZkNjMsIDB4YWE0MDIxNjQsIDB4YjMwMWQ0MGEsIDB4MDJlN2QxY2EsIDB4NTM1NzFkYWUsIDB4N2EzMTgyYTIsXG4gICAgMHgxMmE4ZGRlYywgMHhmZGFhMzM1ZCwgMHgxNzZmNDNlOCwgMHg3MWZiNDZkNCwgMHgzODEyOTAyMiwgMHhjZTk0OWFkNCwgMHhiODQ3NjlhZCwgMHg5NjViZDg2MixcbiAgICAweDgyZjNkMDU1LCAweDY2ZmI5NzY3LCAweDE1YjgwYjRlLCAweDFkNWI0N2EwLCAweDRjZmRlMDZmLCAweGMyOGVjNGI4LCAweDU3ZTg3MjZlLCAweDY0N2E3OGZjLFxuICAgIDB4OTk4NjVkNDQsIDB4NjA4YmQ1OTMsIDB4NmMyMDBlMDMsIDB4MzlkYzVmZjYsIDB4NWQwYjAwYTMsIDB4YWU2M2FmZjIsIDB4N2U4YmQ2MzIsIDB4NzAxMDhjMGMsXG4gICAgMHhiYmQzNTA0OSwgMHgyOTk4ZGYwNCwgMHg5ODBjZjQyYSwgMHg5YjZkZjQ5MSwgMHg5ZTdlZGQ1MywgMHgwNjkxODU0OCwgMHg1OGNiN2UwNywgMHgzYjc0ZWYyZSxcbiAgICAweDUyMmZmZmIxLCAweGQyNDcwOGNjLCAweDFjN2UyN2NkLCAweGE0ZWIyMTViLCAweDNjZjFkMmUyLCAweDE5YjQ3YTM4LCAweDQyNGY3NjE4LCAweDM1ODU2MDM5LFxuICAgIDB4OWQxN2RlZTcsIDB4MjdlYjM1ZTYsIDB4YzlhZmY2N2IsIDB4MzZiYWY1YjgsIDB4MDljNDY3Y2QsIDB4YzE4OTEwYjEsIDB4ZTExZGJmN2IsIDB4MDZjZDFhZjgsXG4gICAgMHg3MTcwYzYwOCwgMHgyZDVlMzM1NCwgMHhkNGRlNDk1YSwgMHg2NGM2ZDAwNiwgMHhiY2MwYzYyYywgMHgzZGQwMGRiMywgMHg3MDhmOGYzNCwgMHg3N2Q1MWI0MixcbiAgICAweDI2NGY2MjBmLCAweDI0YjhkMmJmLCAweDE1YzFiNzllLCAweDQ2YTUyNTY0LCAweGY4ZDdlNTRlLCAweDNlMzc4MTYwLCAweDc4OTVjZGE1LCAweDg1OWMxNWE1LFxuICAgIDB4ZTY0NTk3ODgsIDB4YzM3YmM3NWYsIDB4ZGIwN2JhMGMsIDB4MDY3NmEzYWIsIDB4N2YyMjliMWUsIDB4MzE4NDJlN2IsIDB4MjQyNTlmZDcsIDB4ZjhiZWY0NzIsXG4gICAgMHg4MzVmZmNiOCwgMHg2ZGY0YzFmMiwgMHg5NmY1YjE5NSwgMHhmZDBhZjBmYywgMHhiMGZlMTM0YywgMHhlMjUwNmQzZCwgMHg0ZjliMTJlYSwgMHhmMjE1ZjIyNSxcbiAgICAweGEyMjM3MzZmLCAweDlmYjRjNDI4LCAweDI1ZDA0OTc5LCAweDM0YzcxM2Y4LCAweGM0NjE4MTg3LCAweGVhN2E2ZTk4LCAweDdjZDE2ZWZjLCAweDE0MzY4NzZjLFxuICAgIDB4ZjE1NDQxMDcsIDB4YmVkZWVlMTQsIDB4NTZlOWFmMjcsIDB4YTA0YWE0NDEsIDB4M2NmN2M4OTksIDB4OTJlY2JhZTYsIDB4ZGQ2NzAxNmQsIDB4MTUxNjgyZWIsXG4gICAgMHhhODQyZWVkZiwgMHhmZGJhNjBiNCwgMHhmMTkwN2I3NSwgMHgyMGUzMDMwZiwgMHgyNGQ4YzI5ZSwgMHhlMTM5NjczYiwgMHhlZmE2M2ZiOCwgMHg3MTg3MzA1NCxcbiAgICAweGI2ZjJjZjNiLCAweDlmMzI2NDQyLCAweGNiMTVhNGNjLCAweGIwMWE0NTA0LCAweGYxZTQ3ZDhkLCAweDg0NGExYmU1LCAweGJhZTdkZmRjLCAweDQyY2JkYTcwLFxuICAgIDB4Y2Q3ZGFlMGEsIDB4NTdlODViN2EsIDB4ZDUzZjVhZjYsIDB4MjBjZjRkOGMsIDB4Y2VhNGQ0MjgsIDB4NzlkMTMwYTQsIDB4MzQ4NmViZmIsIDB4MzNkM2NkZGMsXG4gICAgMHg3Nzg1M2I1MywgMHgzN2VmZmNiNSwgMHhjNTA2ODc3OCwgMHhlNTgwYjNlNiwgMHg0ZTY4YjhmNCwgMHhjNWM4YjM3ZSwgMHgwZDgwOWVhMiwgMHgzOThmZWI3YyxcbiAgICAweDEzMmE0Zjk0LCAweDQzYjc5NTBlLCAweDJmZWU3ZDFjLCAweDIyMzYxM2JkLCAweGRkMDZjYWEyLCAweDM3ZGY5MzJiLCAweGM0MjQ4Mjg5LCAweGFjZjNlYmMzLFxuICAgIDB4NTcxNWY2YjcsIDB4ZWYzNDc4ZGQsIDB4ZjI2NzYxNmYsIDB4YzE0OGNiZTQsIDB4OTA1MjgxNWUsIDB4NWU0MTBmYWIsIDB4YjQ4YTI0NjUsIDB4MmVkYTdmYTQsXG4gICAgMHhlODdiNDBlNCwgMHhlOThlYTA4NCwgMHg1ODg5ZTllMSwgMHhlZmQzOTBmYywgMHhkZDA3ZDM1YiwgMHhkYjQ4NTY5NCwgMHgzOGQ3ZTViMiwgMHg1NzcyMDEwMSxcbiAgICAweDczMGVkZWJjLCAweDViNjQzMTEzLCAweDk0OTE3ZTRmLCAweDUwM2MyZmJhLCAweDY0NmYxMjgyLCAweDc1MjNkMjRhLCAweGUwNzc5Njk1LCAweGY5YzE3YThmLFxuICAgIDB4N2E1YjIxMjEsIDB4ZDE4N2I4OTYsIDB4MjkyNjNhNGQsIDB4YmE1MTBjZGYsIDB4ODFmNDdjOWYsIDB4YWQxMTYzZWQsIDB4ZWE3YjU5NjUsIDB4MWEwMDcyNmUsXG4gICAgMHgxMTQwMzA5MiwgMHgwMGRhNmQ3NywgMHg0YTBjZGQ2MSwgMHhhZDFmNDYwMywgMHg2MDViZGZiMCwgMHg5ZWVkYzM2NCwgMHgyMmViZTZhOCwgMHhjZWU3ZDI4YSxcbiAgICAweGEwZTczNmEwLCAweDU1NjRhNmI5LCAweDEwODUzMjA5LCAweGM3ZWI4ZjM3LCAweDJkZTcwNWNhLCAweDg5NTE1NzBmLCAweGRmMDk4MjJiLCAweGJkNjkxYTZjLFxuICAgIDB4YWExMmU0ZjIsIDB4ODc0NTFjMGYsIDB4ZTBmNmEyN2EsIDB4M2FkYTQ4MTksIDB4NGNmMTc2NGYsIDB4MGQ3NzFjMmIsIDB4NjdjZGIxNTYsIDB4MzUwZDgzODQsXG4gICAgMHg1OTM4ZmEwZiwgMHg0MjM5OWVmMywgMHgzNjk5N2IwNywgMHgwZTg0MDkzZCwgMHg0YWE5M2U2MSwgMHg4MzYwZDg3YiwgMHgxZmE5OGIwYywgMHgxMTQ5MzgyYyxcbiAgICAweGU5NzYyNWE1LCAweDA2MTRkMWI3LCAweDBlMjUyNDRiLCAweDBjNzY4MzQ3LCAweDU4OWU4ZDgyLCAweDBkMjA1OWQxLCAweGE0NjZiYjFlLCAweGY4ZGEwYTgyLFxuICAgIDB4MDRmMTkxMzAsIDB4YmE2ZTRlYzAsIDB4OTkyNjUxNjQsIDB4MWVlNzIzMGQsIDB4NTBiMmFkODAsIDB4ZWFlZTY4MDEsIDB4OGRiMmEyODMsIDB4ZWE4YmY1OWUpO1xuXG59O1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uLy4uL3V0aWwnKTtcblxuZnVuY3Rpb24gY2FzdDUoa2V5KSB7XG4gIHRoaXMuY2FzdDUgPSBuZXcgb3BlbnBncF9zeW1lbmNfY2FzdDUoKTtcbiAgdGhpcy5jYXN0NS5zZXRLZXkodXRpbC5zdHIyYmluKGtleSkpO1xuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGJsb2NrKSB7XG4gICAgcmV0dXJuIHRoaXMuY2FzdDUuZW5jcnlwdChibG9jayk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjYXN0NTtcbm1vZHVsZS5leHBvcnRzLmJsb2NrU2l6ZSA9IGNhc3Q1LnByb3RvdHlwZS5ibG9ja1NpemUgPSA4O1xubW9kdWxlLmV4cG9ydHMua2V5U2l6ZSA9IGNhc3Q1LnByb3RvdHlwZS5rZXlTaXplID0gMTY7XG4iLCIvL1BhdWwgVGVybywgSnVseSAyMDAxXG4vL2h0dHA6Ly93d3cudGVyby5jby51ay9kZXMvXG4vL1xuLy9PcHRpbWlzZWQgZm9yIHBlcmZvcm1hbmNlIHdpdGggbGFyZ2UgYmxvY2tzIGJ5IE1pY2hhZWwgSGF5d29ydGgsIE5vdmVtYmVyIDIwMDFcbi8vaHR0cDovL3d3dy5uZXRkZWFsaW5nLmNvbVxuLy9cbi8vIE1vZGlmaWVkIGJ5IFJlY3VyaXR5IExhYnMgR21iSFxuXG4vL1RISVMgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORFxuLy9BTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEVcbi8vSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0Vcbi8vQVJFIERJU0NMQUlNRUQuICBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIE9SIENPTlRSSUJVVE9SUyBCRSBMSUFCTEVcbi8vRk9SIEFOWSBESVJFQ1QsIElORElSRUNULCBJTkNJREVOVEFMLCBTUEVDSUFMLCBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUxcbi8vREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFNcbi8vT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pXG4vL0hPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgV0hFVEhFUiBJTiBDT05UUkFDVCwgU1RSSUNUXG4vL0xJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVlcbi8vT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRlxuLy9TVUNIIERBTUFHRS5cblxuLy9kZXNcbi8vdGhpcyB0YWtlcyB0aGUga2V5LCB0aGUgbWVzc2FnZSwgYW5kIHdoZXRoZXIgdG8gZW5jcnlwdCBvciBkZWNyeXB0XG5cblxuXG5cbmZ1bmN0aW9uIGRlcyhrZXlzLCBtZXNzYWdlLCBlbmNyeXB0LCBtb2RlLCBpdiwgcGFkZGluZykge1xuICAvL2RlY2xhcmluZyB0aGlzIGxvY2FsbHkgc3BlZWRzIHRoaW5ncyB1cCBhIGJpdFxuICB2YXIgc3BmdW5jdGlvbjEgPSBuZXcgQXJyYXkoMHgxMDEwNDAwLCAwLCAweDEwMDAwLCAweDEwMTA0MDQsIDB4MTAxMDAwNCwgMHgxMDQwNCwgMHg0LCAweDEwMDAwLCAweDQwMCwgMHgxMDEwNDAwLFxuICAgIDB4MTAxMDQwNCwgMHg0MDAsIDB4MTAwMDQwNCwgMHgxMDEwMDA0LCAweDEwMDAwMDAsIDB4NCwgMHg0MDQsIDB4MTAwMDQwMCwgMHgxMDAwNDAwLCAweDEwNDAwLCAweDEwNDAwLCAweDEwMTAwMDAsXG4gICAgMHgxMDEwMDAwLCAweDEwMDA0MDQsIDB4MTAwMDQsIDB4MTAwMDAwNCwgMHgxMDAwMDA0LCAweDEwMDA0LCAwLCAweDQwNCwgMHgxMDQwNCwgMHgxMDAwMDAwLCAweDEwMDAwLCAweDEwMTA0MDQsIDB4NCxcbiAgICAweDEwMTAwMDAsIDB4MTAxMDQwMCwgMHgxMDAwMDAwLCAweDEwMDAwMDAsIDB4NDAwLCAweDEwMTAwMDQsIDB4MTAwMDAsIDB4MTA0MDAsIDB4MTAwMDAwNCwgMHg0MDAsIDB4NCwgMHgxMDAwNDA0LFxuICAgIDB4MTA0MDQsIDB4MTAxMDQwNCwgMHgxMDAwNCwgMHgxMDEwMDAwLCAweDEwMDA0MDQsIDB4MTAwMDAwNCwgMHg0MDQsIDB4MTA0MDQsIDB4MTAxMDQwMCwgMHg0MDQsIDB4MTAwMDQwMCxcbiAgICAweDEwMDA0MDAsIDAsIDB4MTAwMDQsIDB4MTA0MDAsIDAsIDB4MTAxMDAwNCk7XG4gIHZhciBzcGZ1bmN0aW9uMiA9IG5ldyBBcnJheSgtMHg3ZmVmN2ZlMCwgLTB4N2ZmZjgwMDAsIDB4ODAwMCwgMHgxMDgwMjAsIDB4MTAwMDAwLCAweDIwLCAtMHg3ZmVmZmZlMCwgLTB4N2ZmZjdmZTAsIC1cbiAgICAweDdmZmZmZmUwLCAtMHg3ZmVmN2ZlMCwgLTB4N2ZlZjgwMDAsIC0weDgwMDAwMDAwLCAtMHg3ZmZmODAwMCwgMHgxMDAwMDAsIDB4MjAsIC0weDdmZWZmZmUwLCAweDEwODAwMCwgMHgxMDAwMjAsIC1cbiAgICAweDdmZmY3ZmUwLCAwLCAtMHg4MDAwMDAwMCwgMHg4MDAwLCAweDEwODAyMCwgLTB4N2ZmMDAwMDAsIDB4MTAwMDIwLCAtMHg3ZmZmZmZlMCwgMCwgMHgxMDgwMDAsIDB4ODAyMCwgLTB4N2ZlZjgwMDAsIC1cbiAgICAweDdmZjAwMDAwLCAweDgwMjAsIDAsIDB4MTA4MDIwLCAtMHg3ZmVmZmZlMCwgMHgxMDAwMDAsIC0weDdmZmY3ZmUwLCAtMHg3ZmYwMDAwMCwgLTB4N2ZlZjgwMDAsIDB4ODAwMCwgLTB4N2ZmMDAwMDAsIC1cbiAgICAweDdmZmY4MDAwLCAweDIwLCAtMHg3ZmVmN2ZlMCwgMHgxMDgwMjAsIDB4MjAsIDB4ODAwMCwgLTB4ODAwMDAwMDAsIDB4ODAyMCwgLTB4N2ZlZjgwMDAsIDB4MTAwMDAwLCAtMHg3ZmZmZmZlMCxcbiAgICAweDEwMDAyMCwgLTB4N2ZmZjdmZTAsIC0weDdmZmZmZmUwLCAweDEwMDAyMCwgMHgxMDgwMDAsIDAsIC0weDdmZmY4MDAwLCAweDgwMjAsIC0weDgwMDAwMDAwLCAtMHg3ZmVmZmZlMCwgLVxuICAgIDB4N2ZlZjdmZTAsIDB4MTA4MDAwKTtcbiAgdmFyIHNwZnVuY3Rpb24zID0gbmV3IEFycmF5KDB4MjA4LCAweDgwMjAyMDAsIDAsIDB4ODAyMDAwOCwgMHg4MDAwMjAwLCAwLCAweDIwMjA4LCAweDgwMDAyMDAsIDB4MjAwMDgsIDB4ODAwMDAwOCxcbiAgICAweDgwMDAwMDgsIDB4MjAwMDAsIDB4ODAyMDIwOCwgMHgyMDAwOCwgMHg4MDIwMDAwLCAweDIwOCwgMHg4MDAwMDAwLCAweDgsIDB4ODAyMDIwMCwgMHgyMDAsIDB4MjAyMDAsIDB4ODAyMDAwMCxcbiAgICAweDgwMjAwMDgsIDB4MjAyMDgsIDB4ODAwMDIwOCwgMHgyMDIwMCwgMHgyMDAwMCwgMHg4MDAwMjA4LCAweDgsIDB4ODAyMDIwOCwgMHgyMDAsIDB4ODAwMDAwMCwgMHg4MDIwMjAwLCAweDgwMDAwMDAsXG4gICAgMHgyMDAwOCwgMHgyMDgsIDB4MjAwMDAsIDB4ODAyMDIwMCwgMHg4MDAwMjAwLCAwLCAweDIwMCwgMHgyMDAwOCwgMHg4MDIwMjA4LCAweDgwMDAyMDAsIDB4ODAwMDAwOCwgMHgyMDAsIDAsXG4gICAgMHg4MDIwMDA4LCAweDgwMDAyMDgsIDB4MjAwMDAsIDB4ODAwMDAwMCwgMHg4MDIwMjA4LCAweDgsIDB4MjAyMDgsIDB4MjAyMDAsIDB4ODAwMDAwOCwgMHg4MDIwMDAwLCAweDgwMDAyMDgsIDB4MjA4LFxuICAgIDB4ODAyMDAwMCwgMHgyMDIwOCwgMHg4LCAweDgwMjAwMDgsIDB4MjAyMDApO1xuICB2YXIgc3BmdW5jdGlvbjQgPSBuZXcgQXJyYXkoMHg4MDIwMDEsIDB4MjA4MSwgMHgyMDgxLCAweDgwLCAweDgwMjA4MCwgMHg4MDAwODEsIDB4ODAwMDAxLCAweDIwMDEsIDAsIDB4ODAyMDAwLFxuICAgIDB4ODAyMDAwLCAweDgwMjA4MSwgMHg4MSwgMCwgMHg4MDAwODAsIDB4ODAwMDAxLCAweDEsIDB4MjAwMCwgMHg4MDAwMDAsIDB4ODAyMDAxLCAweDgwLCAweDgwMDAwMCwgMHgyMDAxLCAweDIwODAsXG4gICAgMHg4MDAwODEsIDB4MSwgMHgyMDgwLCAweDgwMDA4MCwgMHgyMDAwLCAweDgwMjA4MCwgMHg4MDIwODEsIDB4ODEsIDB4ODAwMDgwLCAweDgwMDAwMSwgMHg4MDIwMDAsIDB4ODAyMDgxLCAweDgxLCAwLFxuICAgIDAsIDB4ODAyMDAwLCAweDIwODAsIDB4ODAwMDgwLCAweDgwMDA4MSwgMHgxLCAweDgwMjAwMSwgMHgyMDgxLCAweDIwODEsIDB4ODAsIDB4ODAyMDgxLCAweDgxLCAweDEsIDB4MjAwMCwgMHg4MDAwMDEsXG4gICAgMHgyMDAxLCAweDgwMjA4MCwgMHg4MDAwODEsIDB4MjAwMSwgMHgyMDgwLCAweDgwMDAwMCwgMHg4MDIwMDEsIDB4ODAsIDB4ODAwMDAwLCAweDIwMDAsIDB4ODAyMDgwKTtcbiAgdmFyIHNwZnVuY3Rpb241ID0gbmV3IEFycmF5KDB4MTAwLCAweDIwODAxMDAsIDB4MjA4MDAwMCwgMHg0MjAwMDEwMCwgMHg4MDAwMCwgMHgxMDAsIDB4NDAwMDAwMDAsIDB4MjA4MDAwMCxcbiAgICAweDQwMDgwMTAwLCAweDgwMDAwLCAweDIwMDAxMDAsIDB4NDAwODAxMDAsIDB4NDIwMDAxMDAsIDB4NDIwODAwMDAsIDB4ODAxMDAsIDB4NDAwMDAwMDAsIDB4MjAwMDAwMCwgMHg0MDA4MDAwMCxcbiAgICAweDQwMDgwMDAwLCAwLCAweDQwMDAwMTAwLCAweDQyMDgwMTAwLCAweDQyMDgwMTAwLCAweDIwMDAxMDAsIDB4NDIwODAwMDAsIDB4NDAwMDAxMDAsIDAsIDB4NDIwMDAwMDAsIDB4MjA4MDEwMCxcbiAgICAweDIwMDAwMDAsIDB4NDIwMDAwMDAsIDB4ODAxMDAsIDB4ODAwMDAsIDB4NDIwMDAxMDAsIDB4MTAwLCAweDIwMDAwMDAsIDB4NDAwMDAwMDAsIDB4MjA4MDAwMCwgMHg0MjAwMDEwMCxcbiAgICAweDQwMDgwMTAwLCAweDIwMDAxMDAsIDB4NDAwMDAwMDAsIDB4NDIwODAwMDAsIDB4MjA4MDEwMCwgMHg0MDA4MDEwMCwgMHgxMDAsIDB4MjAwMDAwMCwgMHg0MjA4MDAwMCwgMHg0MjA4MDEwMCxcbiAgICAweDgwMTAwLCAweDQyMDAwMDAwLCAweDQyMDgwMTAwLCAweDIwODAwMDAsIDAsIDB4NDAwODAwMDAsIDB4NDIwMDAwMDAsIDB4ODAxMDAsIDB4MjAwMDEwMCwgMHg0MDAwMDEwMCwgMHg4MDAwMCwgMCxcbiAgICAweDQwMDgwMDAwLCAweDIwODAxMDAsIDB4NDAwMDAxMDApO1xuICB2YXIgc3BmdW5jdGlvbjYgPSBuZXcgQXJyYXkoMHgyMDAwMDAxMCwgMHgyMDQwMDAwMCwgMHg0MDAwLCAweDIwNDA0MDEwLCAweDIwNDAwMDAwLCAweDEwLCAweDIwNDA0MDEwLCAweDQwMDAwMCxcbiAgICAweDIwMDA0MDAwLCAweDQwNDAxMCwgMHg0MDAwMDAsIDB4MjAwMDAwMTAsIDB4NDAwMDEwLCAweDIwMDA0MDAwLCAweDIwMDAwMDAwLCAweDQwMTAsIDAsIDB4NDAwMDEwLCAweDIwMDA0MDEwLFxuICAgIDB4NDAwMCwgMHg0MDQwMDAsIDB4MjAwMDQwMTAsIDB4MTAsIDB4MjA0MDAwMTAsIDB4MjA0MDAwMTAsIDAsIDB4NDA0MDEwLCAweDIwNDA0MDAwLCAweDQwMTAsIDB4NDA0MDAwLCAweDIwNDA0MDAwLFxuICAgIDB4MjAwMDAwMDAsIDB4MjAwMDQwMDAsIDB4MTAsIDB4MjA0MDAwMTAsIDB4NDA0MDAwLCAweDIwNDA0MDEwLCAweDQwMDAwMCwgMHg0MDEwLCAweDIwMDAwMDEwLCAweDQwMDAwMCwgMHgyMDAwNDAwMCxcbiAgICAweDIwMDAwMDAwLCAweDQwMTAsIDB4MjAwMDAwMTAsIDB4MjA0MDQwMTAsIDB4NDA0MDAwLCAweDIwNDAwMDAwLCAweDQwNDAxMCwgMHgyMDQwNDAwMCwgMCwgMHgyMDQwMDAxMCwgMHgxMCwgMHg0MDAwLFxuICAgIDB4MjA0MDAwMDAsIDB4NDA0MDEwLCAweDQwMDAsIDB4NDAwMDEwLCAweDIwMDA0MDEwLCAwLCAweDIwNDA0MDAwLCAweDIwMDAwMDAwLCAweDQwMDAxMCwgMHgyMDAwNDAxMCk7XG4gIHZhciBzcGZ1bmN0aW9uNyA9IG5ldyBBcnJheSgweDIwMDAwMCwgMHg0MjAwMDAyLCAweDQwMDA4MDIsIDAsIDB4ODAwLCAweDQwMDA4MDIsIDB4MjAwODAyLCAweDQyMDA4MDAsIDB4NDIwMDgwMixcbiAgICAweDIwMDAwMCwgMCwgMHg0MDAwMDAyLCAweDIsIDB4NDAwMDAwMCwgMHg0MjAwMDAyLCAweDgwMiwgMHg0MDAwODAwLCAweDIwMDgwMiwgMHgyMDAwMDIsIDB4NDAwMDgwMCwgMHg0MDAwMDAyLFxuICAgIDB4NDIwMDAwMCwgMHg0MjAwODAwLCAweDIwMDAwMiwgMHg0MjAwMDAwLCAweDgwMCwgMHg4MDIsIDB4NDIwMDgwMiwgMHgyMDA4MDAsIDB4MiwgMHg0MDAwMDAwLCAweDIwMDgwMCwgMHg0MDAwMDAwLFxuICAgIDB4MjAwODAwLCAweDIwMDAwMCwgMHg0MDAwODAyLCAweDQwMDA4MDIsIDB4NDIwMDAwMiwgMHg0MjAwMDAyLCAweDIsIDB4MjAwMDAyLCAweDQwMDAwMDAsIDB4NDAwMDgwMCwgMHgyMDAwMDAsXG4gICAgMHg0MjAwODAwLCAweDgwMiwgMHgyMDA4MDIsIDB4NDIwMDgwMCwgMHg4MDIsIDB4NDAwMDAwMiwgMHg0MjAwODAyLCAweDQyMDAwMDAsIDB4MjAwODAwLCAwLCAweDIsIDB4NDIwMDgwMiwgMCxcbiAgICAweDIwMDgwMiwgMHg0MjAwMDAwLCAweDgwMCwgMHg0MDAwMDAyLCAweDQwMDA4MDAsIDB4ODAwLCAweDIwMDAwMik7XG4gIHZhciBzcGZ1bmN0aW9uOCA9IG5ldyBBcnJheSgweDEwMDAxMDQwLCAweDEwMDAsIDB4NDAwMDAsIDB4MTAwNDEwNDAsIDB4MTAwMDAwMDAsIDB4MTAwMDEwNDAsIDB4NDAsIDB4MTAwMDAwMDAsXG4gICAgMHg0MDA0MCwgMHgxMDA0MDAwMCwgMHgxMDA0MTA0MCwgMHg0MTAwMCwgMHgxMDA0MTAwMCwgMHg0MTA0MCwgMHgxMDAwLCAweDQwLCAweDEwMDQwMDAwLCAweDEwMDAwMDQwLCAweDEwMDAxMDAwLFxuICAgIDB4MTA0MCwgMHg0MTAwMCwgMHg0MDA0MCwgMHgxMDA0MDA0MCwgMHgxMDA0MTAwMCwgMHgxMDQwLCAwLCAwLCAweDEwMDQwMDQwLCAweDEwMDAwMDQwLCAweDEwMDAxMDAwLCAweDQxMDQwLFxuICAgIDB4NDAwMDAsIDB4NDEwNDAsIDB4NDAwMDAsIDB4MTAwNDEwMDAsIDB4MTAwMCwgMHg0MCwgMHgxMDA0MDA0MCwgMHgxMDAwLCAweDQxMDQwLCAweDEwMDAxMDAwLCAweDQwLCAweDEwMDAwMDQwLFxuICAgIDB4MTAwNDAwMDAsIDB4MTAwNDAwNDAsIDB4MTAwMDAwMDAsIDB4NDAwMDAsIDB4MTAwMDEwNDAsIDAsIDB4MTAwNDEwNDAsIDB4NDAwNDAsIDB4MTAwMDAwNDAsIDB4MTAwNDAwMDAsIDB4MTAwMDEwMDAsXG4gICAgMHgxMDAwMTA0MCwgMCwgMHgxMDA0MTA0MCwgMHg0MTAwMCwgMHg0MTAwMCwgMHgxMDQwLCAweDEwNDAsIDB4NDAwNDAsIDB4MTAwMDAwMDAsIDB4MTAwNDEwMDApO1xuXG4gIC8vY3JlYXRlIHRoZSAxNiBvciA0OCBzdWJrZXlzIHdlIHdpbGwgbmVlZFxuICB2YXIgbSA9IDAsXG4gICAgaSwgaiwgdGVtcCwgdGVtcDIsIHJpZ2h0MSwgcmlnaHQyLCBsZWZ0LCByaWdodCwgbG9vcGluZztcbiAgdmFyIGNiY2xlZnQsIGNiY2xlZnQyLCBjYmNyaWdodCwgY2JjcmlnaHQyXG4gIHZhciBlbmRsb29wLCBsb29waW5jO1xuICB2YXIgbGVuID0gbWVzc2FnZS5sZW5ndGg7XG4gIHZhciBjaHVuayA9IDA7XG4gIC8vc2V0IHVwIHRoZSBsb29wcyBmb3Igc2luZ2xlIGFuZCB0cmlwbGUgZGVzXG4gIHZhciBpdGVyYXRpb25zID0ga2V5cy5sZW5ndGggPT0gMzIgPyAzIDogOTsgLy9zaW5nbGUgb3IgdHJpcGxlIGRlc1xuICBpZiAoaXRlcmF0aW9ucyA9PSAzKSB7XG4gICAgbG9vcGluZyA9IGVuY3J5cHQgPyBuZXcgQXJyYXkoMCwgMzIsIDIpIDogbmV3IEFycmF5KDMwLCAtMiwgLTIpO1xuICB9IGVsc2Uge1xuICAgIGxvb3BpbmcgPSBlbmNyeXB0ID8gbmV3IEFycmF5KDAsIDMyLCAyLCA2MiwgMzAsIC0yLCA2NCwgOTYsIDIpIDogbmV3IEFycmF5KDk0LCA2MiwgLTIsIDMyLCA2NCwgMiwgMzAsIC0yLCAtMik7XG4gIH1cblxuICAvL3BhZCB0aGUgbWVzc2FnZSBkZXBlbmRpbmcgb24gdGhlIHBhZGRpbmcgcGFyYW1ldGVyXG4gIC8vb25seSBhZGQgcGFkZGluZyBpZiBlbmNyeXB0aW5nIC0gbm90ZSB0aGF0IHlvdSBuZWVkIHRvIHVzZSB0aGUgc2FtZSBwYWRkaW5nIG9wdGlvbiBmb3IgYm90aCBlbmNyeXB0IGFuZCBkZWNyeXB0XG4gIGlmIChlbmNyeXB0KSB7XG4gICAgbWVzc2FnZSA9IGRlc19hZGRQYWRkaW5nKG1lc3NhZ2UsIHBhZGRpbmcpO1xuICAgIGxlbiA9IG1lc3NhZ2UubGVuZ3RoO1xuICB9XG5cbiAgLy9zdG9yZSB0aGUgcmVzdWx0IGhlcmVcbiAgcmVzdWx0ID0gXCJcIjtcbiAgdGVtcHJlc3VsdCA9IFwiXCI7XG5cbiAgaWYgKG1vZGUgPT0gMSkgeyAvL0NCQyBtb2RlXG4gICAgY2JjbGVmdCA9IChpdi5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKGl2LmNoYXJDb2RlQXQobSsrKSA8PCAxNikgfCAoaXYuY2hhckNvZGVBdChtKyspIDw8IDgpIHwgaXYuY2hhckNvZGVBdChtKyspO1xuICAgIGNiY3JpZ2h0ID0gKGl2LmNoYXJDb2RlQXQobSsrKSA8PCAyNCkgfCAoaXYuY2hhckNvZGVBdChtKyspIDw8IDE2KSB8IChpdi5jaGFyQ29kZUF0KG0rKykgPDwgOCkgfCBpdi5jaGFyQ29kZUF0KG0rKyk7XG4gICAgbSA9IDA7XG4gIH1cblxuICAvL2xvb3AgdGhyb3VnaCBlYWNoIDY0IGJpdCBjaHVuayBvZiB0aGUgbWVzc2FnZVxuICB3aGlsZSAobSA8IGxlbikge1xuICAgIGxlZnQgPSAobWVzc2FnZS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKG1lc3NhZ2UuY2hhckNvZGVBdChtKyspIDw8IDE2KSB8IChtZXNzYWdlLmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8IG1lc3NhZ2VcbiAgICAgIC5jaGFyQ29kZUF0KG0rKyk7XG4gICAgcmlnaHQgPSAobWVzc2FnZS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKG1lc3NhZ2UuY2hhckNvZGVBdChtKyspIDw8IDE2KSB8IChtZXNzYWdlLmNoYXJDb2RlQXQobSsrKSA8PCA4KSB8XG4gICAgICBtZXNzYWdlLmNoYXJDb2RlQXQobSsrKTtcblxuICAgIC8vZm9yIENpcGhlciBCbG9jayBDaGFpbmluZyBtb2RlLCB4b3IgdGhlIG1lc3NhZ2Ugd2l0aCB0aGUgcHJldmlvdXMgcmVzdWx0XG4gICAgaWYgKG1vZGUgPT0gMSkge1xuICAgICAgaWYgKGVuY3J5cHQpIHtcbiAgICAgICAgbGVmdCBePSBjYmNsZWZ0O1xuICAgICAgICByaWdodCBePSBjYmNyaWdodDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNiY2xlZnQyID0gY2JjbGVmdDtcbiAgICAgICAgY2JjcmlnaHQyID0gY2JjcmlnaHQ7XG4gICAgICAgIGNiY2xlZnQgPSBsZWZ0O1xuICAgICAgICBjYmNyaWdodCA9IHJpZ2h0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vZmlyc3QgZWFjaCA2NCBidXQgY2h1bmsgb2YgdGhlIG1lc3NhZ2UgbXVzdCBiZSBwZXJtdXRlZCBhY2NvcmRpbmcgdG8gSVBcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiA0KSBeIHJpZ2h0KSAmIDB4MGYwZjBmMGY7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDQpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDE2KSBeIHJpZ2h0KSAmIDB4MDAwMGZmZmY7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDE2KTtcbiAgICB0ZW1wID0gKChyaWdodCA+Pj4gMikgXiBsZWZ0KSAmIDB4MzMzMzMzMzM7XG4gICAgbGVmdCBePSB0ZW1wO1xuICAgIHJpZ2h0IF49ICh0ZW1wIDw8IDIpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiA4KSBeIGxlZnQpICYgMHgwMGZmMDBmZjtcbiAgICBsZWZ0IF49IHRlbXA7XG4gICAgcmlnaHQgXj0gKHRlbXAgPDwgOCk7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gMSkgXiByaWdodCkgJiAweDU1NTU1NTU1O1xuICAgIHJpZ2h0IF49IHRlbXA7XG4gICAgbGVmdCBePSAodGVtcCA8PCAxKTtcblxuICAgIGxlZnQgPSAoKGxlZnQgPDwgMSkgfCAobGVmdCA+Pj4gMzEpKTtcbiAgICByaWdodCA9ICgocmlnaHQgPDwgMSkgfCAocmlnaHQgPj4+IDMxKSk7XG5cbiAgICAvL2RvIHRoaXMgZWl0aGVyIDEgb3IgMyB0aW1lcyBmb3IgZWFjaCBjaHVuayBvZiB0aGUgbWVzc2FnZVxuICAgIGZvciAoaiA9IDA7IGogPCBpdGVyYXRpb25zOyBqICs9IDMpIHtcbiAgICAgIGVuZGxvb3AgPSBsb29waW5nW2ogKyAxXTtcbiAgICAgIGxvb3BpbmMgPSBsb29waW5nW2ogKyAyXTtcbiAgICAgIC8vbm93IGdvIHRocm91Z2ggYW5kIHBlcmZvcm0gdGhlIGVuY3J5cHRpb24gb3IgZGVjcnlwdGlvbiAgXG4gICAgICBmb3IgKGkgPSBsb29waW5nW2pdOyBpICE9IGVuZGxvb3A7IGkgKz0gbG9vcGluYykgeyAvL2ZvciBlZmZpY2llbmN5XG4gICAgICAgIHJpZ2h0MSA9IHJpZ2h0IF4ga2V5c1tpXTtcbiAgICAgICAgcmlnaHQyID0gKChyaWdodCA+Pj4gNCkgfCAocmlnaHQgPDwgMjgpKSBeIGtleXNbaSArIDFdO1xuICAgICAgICAvL3RoZSByZXN1bHQgaXMgYXR0YWluZWQgYnkgcGFzc2luZyB0aGVzZSBieXRlcyB0aHJvdWdoIHRoZSBTIHNlbGVjdGlvbiBmdW5jdGlvbnNcbiAgICAgICAgdGVtcCA9IGxlZnQ7XG4gICAgICAgIGxlZnQgPSByaWdodDtcbiAgICAgICAgcmlnaHQgPSB0ZW1wIF4gKHNwZnVuY3Rpb24yWyhyaWdodDEgPj4+IDI0KSAmIDB4M2ZdIHwgc3BmdW5jdGlvbjRbKHJpZ2h0MSA+Pj4gMTYpICYgMHgzZl0gfCBzcGZ1bmN0aW9uNlsocmlnaHQxID4+PlxuICAgICAgICAgIDgpICYgMHgzZl0gfCBzcGZ1bmN0aW9uOFtyaWdodDEgJiAweDNmXSB8IHNwZnVuY3Rpb24xWyhyaWdodDIgPj4+IDI0KSAmIDB4M2ZdIHwgc3BmdW5jdGlvbjNbKHJpZ2h0MiA+Pj4gMTYpICZcbiAgICAgICAgICAweDNmXSB8IHNwZnVuY3Rpb241WyhyaWdodDIgPj4+IDgpICYgMHgzZl0gfCBzcGZ1bmN0aW9uN1tyaWdodDIgJiAweDNmXSk7XG4gICAgICB9XG4gICAgICB0ZW1wID0gbGVmdDtcbiAgICAgIGxlZnQgPSByaWdodDtcbiAgICAgIHJpZ2h0ID0gdGVtcDsgLy91bnJldmVyc2UgbGVmdCBhbmQgcmlnaHRcbiAgICB9IC8vZm9yIGVpdGhlciAxIG9yIDMgaXRlcmF0aW9uc1xuXG4gICAgLy9tb3ZlIHRoZW4gZWFjaCBvbmUgYml0IHRvIHRoZSByaWdodFxuICAgIGxlZnQgPSAoKGxlZnQgPj4+IDEpIHwgKGxlZnQgPDwgMzEpKTtcbiAgICByaWdodCA9ICgocmlnaHQgPj4+IDEpIHwgKHJpZ2h0IDw8IDMxKSk7XG5cbiAgICAvL25vdyBwZXJmb3JtIElQLTEsIHdoaWNoIGlzIElQIGluIHRoZSBvcHBvc2l0ZSBkaXJlY3Rpb25cbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAxKSBeIHJpZ2h0KSAmIDB4NTU1NTU1NTU7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDEpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiA4KSBeIGxlZnQpICYgMHgwMGZmMDBmZjtcbiAgICBsZWZ0IF49IHRlbXA7XG4gICAgcmlnaHQgXj0gKHRlbXAgPDwgOCk7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IDIpIF4gbGVmdCkgJiAweDMzMzMzMzMzO1xuICAgIGxlZnQgXj0gdGVtcDtcbiAgICByaWdodCBePSAodGVtcCA8PCAyKTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAxNikgXiByaWdodCkgJiAweDAwMDBmZmZmO1xuICAgIHJpZ2h0IF49IHRlbXA7XG4gICAgbGVmdCBePSAodGVtcCA8PCAxNik7XG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gNCkgXiByaWdodCkgJiAweDBmMGYwZjBmO1xuICAgIHJpZ2h0IF49IHRlbXA7XG4gICAgbGVmdCBePSAodGVtcCA8PCA0KTtcblxuICAgIC8vZm9yIENpcGhlciBCbG9jayBDaGFpbmluZyBtb2RlLCB4b3IgdGhlIG1lc3NhZ2Ugd2l0aCB0aGUgcHJldmlvdXMgcmVzdWx0XG4gICAgaWYgKG1vZGUgPT0gMSkge1xuICAgICAgaWYgKGVuY3J5cHQpIHtcbiAgICAgICAgY2JjbGVmdCA9IGxlZnQ7XG4gICAgICAgIGNiY3JpZ2h0ID0gcmlnaHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZWZ0IF49IGNiY2xlZnQyO1xuICAgICAgICByaWdodCBePSBjYmNyaWdodDI7XG4gICAgICB9XG4gICAgfVxuICAgIHRlbXByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgobGVmdCA+Pj4gMjQpLCAoKGxlZnQgPj4+IDE2KSAmIDB4ZmYpLCAoKGxlZnQgPj4+IDgpICYgMHhmZiksIChsZWZ0ICYgMHhmZiksIChcbiAgICAgIHJpZ2h0ID4+PiAyNCksICgocmlnaHQgPj4+IDE2KSAmIDB4ZmYpLCAoKHJpZ2h0ID4+PiA4KSAmIDB4ZmYpLCAocmlnaHQgJiAweGZmKSk7XG5cbiAgICBjaHVuayArPSA4O1xuICAgIGlmIChjaHVuayA9PSA1MTIpIHtcbiAgICAgIHJlc3VsdCArPSB0ZW1wcmVzdWx0O1xuICAgICAgdGVtcHJlc3VsdCA9IFwiXCI7XG4gICAgICBjaHVuayA9IDA7XG4gICAgfVxuICB9IC8vZm9yIGV2ZXJ5IDggY2hhcmFjdGVycywgb3IgNjQgYml0cyBpbiB0aGUgbWVzc2FnZVxuXG4gIC8vcmV0dXJuIHRoZSByZXN1bHQgYXMgYW4gYXJyYXlcbiAgcmVzdWx0ICs9IHRlbXByZXN1bHQ7XG5cbiAgLy9vbmx5IHJlbW92ZSBwYWRkaW5nIGlmIGRlY3J5cHRpbmcgLSBub3RlIHRoYXQgeW91IG5lZWQgdG8gdXNlIHRoZSBzYW1lIHBhZGRpbmcgb3B0aW9uIGZvciBib3RoIGVuY3J5cHQgYW5kIGRlY3J5cHRcbiAgaWYgKCFlbmNyeXB0KSB7XG4gICAgcmVzdWx0ID0gZGVzX3JlbW92ZVBhZGRpbmcocmVzdWx0LCBwYWRkaW5nKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59IC8vZW5kIG9mIGRlc1xuXG5cblxuLy9kZXNfY3JlYXRlS2V5c1xuLy90aGlzIHRha2VzIGFzIGlucHV0IGEgNjQgYml0IGtleSAoZXZlbiB0aG91Z2ggb25seSA1NiBiaXRzIGFyZSB1c2VkKVxuLy9hcyBhbiBhcnJheSBvZiAyIGludGVnZXJzLCBhbmQgcmV0dXJucyAxNiA0OCBiaXQga2V5c1xuXG5mdW5jdGlvbiBkZXNfY3JlYXRlS2V5cyhrZXkpIHtcbiAgLy9kZWNsYXJpbmcgdGhpcyBsb2NhbGx5IHNwZWVkcyB0aGluZ3MgdXAgYSBiaXRcbiAgcGMyYnl0ZXMwID0gbmV3IEFycmF5KDAsIDB4NCwgMHgyMDAwMDAwMCwgMHgyMDAwMDAwNCwgMHgxMDAwMCwgMHgxMDAwNCwgMHgyMDAxMDAwMCwgMHgyMDAxMDAwNCwgMHgyMDAsIDB4MjA0LFxuICAgIDB4MjAwMDAyMDAsIDB4MjAwMDAyMDQsIDB4MTAyMDAsIDB4MTAyMDQsIDB4MjAwMTAyMDAsIDB4MjAwMTAyMDQpO1xuICBwYzJieXRlczEgPSBuZXcgQXJyYXkoMCwgMHgxLCAweDEwMDAwMCwgMHgxMDAwMDEsIDB4NDAwMDAwMCwgMHg0MDAwMDAxLCAweDQxMDAwMDAsIDB4NDEwMDAwMSwgMHgxMDAsIDB4MTAxLCAweDEwMDEwMCxcbiAgICAweDEwMDEwMSwgMHg0MDAwMTAwLCAweDQwMDAxMDEsIDB4NDEwMDEwMCwgMHg0MTAwMTAxKTtcbiAgcGMyYnl0ZXMyID0gbmV3IEFycmF5KDAsIDB4OCwgMHg4MDAsIDB4ODA4LCAweDEwMDAwMDAsIDB4MTAwMDAwOCwgMHgxMDAwODAwLCAweDEwMDA4MDgsIDAsIDB4OCwgMHg4MDAsIDB4ODA4LFxuICAgIDB4MTAwMDAwMCwgMHgxMDAwMDA4LCAweDEwMDA4MDAsIDB4MTAwMDgwOCk7XG4gIHBjMmJ5dGVzMyA9IG5ldyBBcnJheSgwLCAweDIwMDAwMCwgMHg4MDAwMDAwLCAweDgyMDAwMDAsIDB4MjAwMCwgMHgyMDIwMDAsIDB4ODAwMjAwMCwgMHg4MjAyMDAwLCAweDIwMDAwLCAweDIyMDAwMCxcbiAgICAweDgwMjAwMDAsIDB4ODIyMDAwMCwgMHgyMjAwMCwgMHgyMjIwMDAsIDB4ODAyMjAwMCwgMHg4MjIyMDAwKTtcbiAgcGMyYnl0ZXM0ID0gbmV3IEFycmF5KDAsIDB4NDAwMDAsIDB4MTAsIDB4NDAwMTAsIDAsIDB4NDAwMDAsIDB4MTAsIDB4NDAwMTAsIDB4MTAwMCwgMHg0MTAwMCwgMHgxMDEwLCAweDQxMDEwLCAweDEwMDAsXG4gICAgMHg0MTAwMCwgMHgxMDEwLCAweDQxMDEwKTtcbiAgcGMyYnl0ZXM1ID0gbmV3IEFycmF5KDAsIDB4NDAwLCAweDIwLCAweDQyMCwgMCwgMHg0MDAsIDB4MjAsIDB4NDIwLCAweDIwMDAwMDAsIDB4MjAwMDQwMCwgMHgyMDAwMDIwLCAweDIwMDA0MjAsXG4gICAgMHgyMDAwMDAwLCAweDIwMDA0MDAsIDB4MjAwMDAyMCwgMHgyMDAwNDIwKTtcbiAgcGMyYnl0ZXM2ID0gbmV3IEFycmF5KDAsIDB4MTAwMDAwMDAsIDB4ODAwMDAsIDB4MTAwODAwMDAsIDB4MiwgMHgxMDAwMDAwMiwgMHg4MDAwMiwgMHgxMDA4MDAwMiwgMCwgMHgxMDAwMDAwMCxcbiAgICAweDgwMDAwLCAweDEwMDgwMDAwLCAweDIsIDB4MTAwMDAwMDIsIDB4ODAwMDIsIDB4MTAwODAwMDIpO1xuICBwYzJieXRlczcgPSBuZXcgQXJyYXkoMCwgMHgxMDAwMCwgMHg4MDAsIDB4MTA4MDAsIDB4MjAwMDAwMDAsIDB4MjAwMTAwMDAsIDB4MjAwMDA4MDAsIDB4MjAwMTA4MDAsIDB4MjAwMDAsIDB4MzAwMDAsXG4gICAgMHgyMDgwMCwgMHgzMDgwMCwgMHgyMDAyMDAwMCwgMHgyMDAzMDAwMCwgMHgyMDAyMDgwMCwgMHgyMDAzMDgwMCk7XG4gIHBjMmJ5dGVzOCA9IG5ldyBBcnJheSgwLCAweDQwMDAwLCAwLCAweDQwMDAwLCAweDIsIDB4NDAwMDIsIDB4MiwgMHg0MDAwMiwgMHgyMDAwMDAwLCAweDIwNDAwMDAsIDB4MjAwMDAwMCwgMHgyMDQwMDAwLFxuICAgIDB4MjAwMDAwMiwgMHgyMDQwMDAyLCAweDIwMDAwMDIsIDB4MjA0MDAwMik7XG4gIHBjMmJ5dGVzOSA9IG5ldyBBcnJheSgwLCAweDEwMDAwMDAwLCAweDgsIDB4MTAwMDAwMDgsIDAsIDB4MTAwMDAwMDAsIDB4OCwgMHgxMDAwMDAwOCwgMHg0MDAsIDB4MTAwMDA0MDAsIDB4NDA4LFxuICAgIDB4MTAwMDA0MDgsIDB4NDAwLCAweDEwMDAwNDAwLCAweDQwOCwgMHgxMDAwMDQwOCk7XG4gIHBjMmJ5dGVzMTAgPSBuZXcgQXJyYXkoMCwgMHgyMCwgMCwgMHgyMCwgMHgxMDAwMDAsIDB4MTAwMDIwLCAweDEwMDAwMCwgMHgxMDAwMjAsIDB4MjAwMCwgMHgyMDIwLCAweDIwMDAsIDB4MjAyMCxcbiAgICAweDEwMjAwMCwgMHgxMDIwMjAsIDB4MTAyMDAwLCAweDEwMjAyMCk7XG4gIHBjMmJ5dGVzMTEgPSBuZXcgQXJyYXkoMCwgMHgxMDAwMDAwLCAweDIwMCwgMHgxMDAwMjAwLCAweDIwMDAwMCwgMHgxMjAwMDAwLCAweDIwMDIwMCwgMHgxMjAwMjAwLCAweDQwMDAwMDAsIDB4NTAwMDAwMCxcbiAgICAweDQwMDAyMDAsIDB4NTAwMDIwMCwgMHg0MjAwMDAwLCAweDUyMDAwMDAsIDB4NDIwMDIwMCwgMHg1MjAwMjAwKTtcbiAgcGMyYnl0ZXMxMiA9IG5ldyBBcnJheSgwLCAweDEwMDAsIDB4ODAwMDAwMCwgMHg4MDAxMDAwLCAweDgwMDAwLCAweDgxMDAwLCAweDgwODAwMDAsIDB4ODA4MTAwMCwgMHgxMCwgMHgxMDEwLFxuICAgIDB4ODAwMDAxMCwgMHg4MDAxMDEwLCAweDgwMDEwLCAweDgxMDEwLCAweDgwODAwMTAsIDB4ODA4MTAxMCk7XG4gIHBjMmJ5dGVzMTMgPSBuZXcgQXJyYXkoMCwgMHg0LCAweDEwMCwgMHgxMDQsIDAsIDB4NCwgMHgxMDAsIDB4MTA0LCAweDEsIDB4NSwgMHgxMDEsIDB4MTA1LCAweDEsIDB4NSwgMHgxMDEsIDB4MTA1KTtcblxuICAvL2hvdyBtYW55IGl0ZXJhdGlvbnMgKDEgZm9yIGRlcywgMyBmb3IgdHJpcGxlIGRlcylcbiAgdmFyIGl0ZXJhdGlvbnMgPSBrZXkubGVuZ3RoID4gOCA/IDMgOiAxOyAvL2NoYW5nZWQgYnkgUGF1bCAxNi82LzIwMDcgdG8gdXNlIFRyaXBsZSBERVMgZm9yIDkrIGJ5dGUga2V5c1xuICAvL3N0b3JlcyB0aGUgcmV0dXJuIGtleXNcbiAgdmFyIGtleXMgPSBuZXcgQXJyYXkoMzIgKiBpdGVyYXRpb25zKTtcbiAgLy9ub3cgZGVmaW5lIHRoZSBsZWZ0IHNoaWZ0cyB3aGljaCBuZWVkIHRvIGJlIGRvbmVcbiAgdmFyIHNoaWZ0cyA9IG5ldyBBcnJheSgwLCAwLCAxLCAxLCAxLCAxLCAxLCAxLCAwLCAxLCAxLCAxLCAxLCAxLCAxLCAwKTtcbiAgLy9vdGhlciB2YXJpYWJsZXNcbiAgdmFyIGxlZnR0ZW1wLCByaWdodHRlbXAsIG0gPSAwLFxuICAgIG4gPSAwLFxuICAgIHRlbXA7XG5cbiAgZm9yICh2YXIgaiA9IDA7IGogPCBpdGVyYXRpb25zOyBqKyspIHsgLy9laXRoZXIgMSBvciAzIGl0ZXJhdGlvbnNcbiAgICBsZWZ0ID0gKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgOCkgfCBrZXkuY2hhckNvZGVBdChtKyspO1xuICAgIHJpZ2h0ID0gKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMjQpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgMTYpIHwgKGtleS5jaGFyQ29kZUF0KG0rKykgPDwgOCkgfCBrZXkuY2hhckNvZGVBdChtKyspO1xuXG4gICAgdGVtcCA9ICgobGVmdCA+Pj4gNCkgXiByaWdodCkgJiAweDBmMGYwZjBmO1xuICAgIHJpZ2h0IF49IHRlbXA7XG4gICAgbGVmdCBePSAodGVtcCA8PCA0KTtcbiAgICB0ZW1wID0gKChyaWdodCA+Pj4gLTE2KSBeIGxlZnQpICYgMHgwMDAwZmZmZjtcbiAgICBsZWZ0IF49IHRlbXA7XG4gICAgcmlnaHQgXj0gKHRlbXAgPDwgLTE2KTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAyKSBeIHJpZ2h0KSAmIDB4MzMzMzMzMzM7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDIpO1xuICAgIHRlbXAgPSAoKHJpZ2h0ID4+PiAtMTYpIF4gbGVmdCkgJiAweDAwMDBmZmZmO1xuICAgIGxlZnQgXj0gdGVtcDtcbiAgICByaWdodCBePSAodGVtcCA8PCAtMTYpO1xuICAgIHRlbXAgPSAoKGxlZnQgPj4+IDEpIF4gcmlnaHQpICYgMHg1NTU1NTU1NTtcbiAgICByaWdodCBePSB0ZW1wO1xuICAgIGxlZnQgXj0gKHRlbXAgPDwgMSk7XG4gICAgdGVtcCA9ICgocmlnaHQgPj4+IDgpIF4gbGVmdCkgJiAweDAwZmYwMGZmO1xuICAgIGxlZnQgXj0gdGVtcDtcbiAgICByaWdodCBePSAodGVtcCA8PCA4KTtcbiAgICB0ZW1wID0gKChsZWZ0ID4+PiAxKSBeIHJpZ2h0KSAmIDB4NTU1NTU1NTU7XG4gICAgcmlnaHQgXj0gdGVtcDtcbiAgICBsZWZ0IF49ICh0ZW1wIDw8IDEpO1xuXG4gICAgLy90aGUgcmlnaHQgc2lkZSBuZWVkcyB0byBiZSBzaGlmdGVkIGFuZCB0byBnZXQgdGhlIGxhc3QgZm91ciBiaXRzIG9mIHRoZSBsZWZ0IHNpZGVcbiAgICB0ZW1wID0gKGxlZnQgPDwgOCkgfCAoKHJpZ2h0ID4+PiAyMCkgJiAweDAwMDAwMGYwKTtcbiAgICAvL2xlZnQgbmVlZHMgdG8gYmUgcHV0IHVwc2lkZSBkb3duXG4gICAgbGVmdCA9IChyaWdodCA8PCAyNCkgfCAoKHJpZ2h0IDw8IDgpICYgMHhmZjAwMDApIHwgKChyaWdodCA+Pj4gOCkgJiAweGZmMDApIHwgKChyaWdodCA+Pj4gMjQpICYgMHhmMCk7XG4gICAgcmlnaHQgPSB0ZW1wO1xuXG4gICAgLy9ub3cgZ28gdGhyb3VnaCBhbmQgcGVyZm9ybSB0aGVzZSBzaGlmdHMgb24gdGhlIGxlZnQgYW5kIHJpZ2h0IGtleXNcbiAgICBmb3IgKGkgPSAwOyBpIDwgc2hpZnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAvL3NoaWZ0IHRoZSBrZXlzIGVpdGhlciBvbmUgb3IgdHdvIGJpdHMgdG8gdGhlIGxlZnRcbiAgICAgIGlmIChzaGlmdHNbaV0pIHtcbiAgICAgICAgbGVmdCA9IChsZWZ0IDw8IDIpIHwgKGxlZnQgPj4+IDI2KTtcbiAgICAgICAgcmlnaHQgPSAocmlnaHQgPDwgMikgfCAocmlnaHQgPj4+IDI2KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxlZnQgPSAobGVmdCA8PCAxKSB8IChsZWZ0ID4+PiAyNyk7XG4gICAgICAgIHJpZ2h0ID0gKHJpZ2h0IDw8IDEpIHwgKHJpZ2h0ID4+PiAyNyk7XG4gICAgICB9XG4gICAgICBsZWZ0ICY9IC0weGY7XG4gICAgICByaWdodCAmPSAtMHhmO1xuXG4gICAgICAvL25vdyBhcHBseSBQQy0yLCBpbiBzdWNoIGEgd2F5IHRoYXQgRSBpcyBlYXNpZXIgd2hlbiBlbmNyeXB0aW5nIG9yIGRlY3J5cHRpbmdcbiAgICAgIC8vdGhpcyBjb252ZXJzaW9uIHdpbGwgbG9vayBsaWtlIFBDLTIgZXhjZXB0IG9ubHkgdGhlIGxhc3QgNiBiaXRzIG9mIGVhY2ggYnl0ZSBhcmUgdXNlZFxuICAgICAgLy9yYXRoZXIgdGhhbiA0OCBjb25zZWN1dGl2ZSBiaXRzIGFuZCB0aGUgb3JkZXIgb2YgbGluZXMgd2lsbCBiZSBhY2NvcmRpbmcgdG8gXG4gICAgICAvL2hvdyB0aGUgUyBzZWxlY3Rpb24gZnVuY3Rpb25zIHdpbGwgYmUgYXBwbGllZDogUzIsIFM0LCBTNiwgUzgsIFMxLCBTMywgUzUsIFM3XG4gICAgICBsZWZ0dGVtcCA9IHBjMmJ5dGVzMFtsZWZ0ID4+PiAyOF0gfCBwYzJieXRlczFbKGxlZnQgPj4+IDI0KSAmIDB4Zl0gfCBwYzJieXRlczJbKGxlZnQgPj4+IDIwKSAmIDB4Zl0gfCBwYzJieXRlczNbKFxuICAgICAgICBsZWZ0ID4+PiAxNikgJiAweGZdIHwgcGMyYnl0ZXM0WyhsZWZ0ID4+PiAxMikgJiAweGZdIHwgcGMyYnl0ZXM1WyhsZWZ0ID4+PiA4KSAmIDB4Zl0gfCBwYzJieXRlczZbKGxlZnQgPj4+IDQpICZcbiAgICAgICAgMHhmXTtcbiAgICAgIHJpZ2h0dGVtcCA9IHBjMmJ5dGVzN1tyaWdodCA+Pj4gMjhdIHwgcGMyYnl0ZXM4WyhyaWdodCA+Pj4gMjQpICYgMHhmXSB8IHBjMmJ5dGVzOVsocmlnaHQgPj4+IDIwKSAmIDB4Zl0gfFxuICAgICAgICBwYzJieXRlczEwWyhyaWdodCA+Pj4gMTYpICYgMHhmXSB8IHBjMmJ5dGVzMTFbKHJpZ2h0ID4+PiAxMikgJiAweGZdIHwgcGMyYnl0ZXMxMlsocmlnaHQgPj4+IDgpICYgMHhmXSB8XG4gICAgICAgIHBjMmJ5dGVzMTNbKHJpZ2h0ID4+PiA0KSAmIDB4Zl07XG4gICAgICB0ZW1wID0gKChyaWdodHRlbXAgPj4+IDE2KSBeIGxlZnR0ZW1wKSAmIDB4MDAwMGZmZmY7XG4gICAgICBrZXlzW24rK10gPSBsZWZ0dGVtcCBeIHRlbXA7XG4gICAgICBrZXlzW24rK10gPSByaWdodHRlbXAgXiAodGVtcCA8PCAxNik7XG4gICAgfVxuICB9IC8vZm9yIGVhY2ggaXRlcmF0aW9uc1xuICAvL3JldHVybiB0aGUga2V5cyB3ZSd2ZSBjcmVhdGVkXG4gIHJldHVybiBrZXlzO1xufSAvL2VuZCBvZiBkZXNfY3JlYXRlS2V5c1xuXG5cbmZ1bmN0aW9uIGRlc19hZGRQYWRkaW5nKG1lc3NhZ2UsIHBhZGRpbmcpIHtcbiAgdmFyIHBhZExlbmd0aCA9IDggLSAobWVzc2FnZS5sZW5ndGggJSA4KTtcbiAgaWYgKChwYWRkaW5nID09IDIpICYmIChwYWRMZW5ndGggPCA4KSkgeyAvL3BhZCB0aGUgbWVzc2FnZSB3aXRoIHNwYWNlc1xuICAgIG1lc3NhZ2UgKz0gXCIgICAgICAgIFwiLnN1YnN0cigwLCBwYWRMZW5ndGgpO1xuICB9IGVsc2UgaWYgKHBhZGRpbmcgPT0gMSkgeyAvL1BLQ1M3IHBhZGRpbmdcbiAgICBtZXNzYWdlICs9IFN0cmluZy5mcm9tQ2hhckNvZGUocGFkTGVuZ3RoLCBwYWRMZW5ndGgsIHBhZExlbmd0aCwgcGFkTGVuZ3RoLCBwYWRMZW5ndGgsIHBhZExlbmd0aCwgcGFkTGVuZ3RoLFxuICAgICAgcGFkTGVuZ3RoKS5zdWJzdHIoMCwgcGFkTGVuZ3RoKTtcbiAgfSBlbHNlIGlmICghcGFkZGluZyAmJiAocGFkTGVuZ3RoIDwgOCkpIHsgLy9wYWQgdGhlIG1lc3NhZ2Ugb3V0IHdpdGggbnVsbCBieXRlc1xuICAgIG1lc3NhZ2UgKz0gXCJcXDBcXDBcXDBcXDBcXDBcXDBcXDBcXDBcIi5zdWJzdHIoMCwgcGFkTGVuZ3RoKTtcbiAgfVxuICByZXR1cm4gbWVzc2FnZTtcbn1cblxuZnVuY3Rpb24gZGVzX3JlbW92ZVBhZGRpbmcobWVzc2FnZSwgcGFkZGluZykge1xuICBpZiAocGFkZGluZyA9PSAyKSB7IC8vIHNwYWNlIHBhZGRlZFxuICAgIG1lc3NhZ2UgPSBtZXNzYWdlLnJlcGxhY2UoLyAqJC9nLCBcIlwiKTtcbiAgfSBlbHNlIGlmIChwYWRkaW5nID09IDEpIHsgLy8gUEtDUzdcbiAgICB2YXIgcGFkQ291bnQgPSBtZXNzYWdlLmNoYXJDb2RlQXQobWVzc2FnZS5sZW5ndGggLSAxKTtcbiAgICBtZXNzYWdlID0gbWVzc2FnZS5zdWJzdHIoMCwgbWVzc2FnZS5sZW5ndGggLSBwYWRDb3VudCk7XG4gIH0gZWxzZSBpZiAoIXBhZGRpbmcpIHsgLy8gbnVsbCBwYWRkaW5nXG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UucmVwbGFjZSgvXFwwKiQvZywgXCJcIik7XG4gIH1cbiAgcmV0dXJuIG1lc3NhZ2U7XG59XG5cblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbi8vIGFkZGVkIGJ5IFJlY3VyaXR5IExhYnNcblxuZnVuY3Rpb24gRGVzKGtleSkge1xuICB0aGlzLmtleSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgdGhpcy5rZXkucHVzaChrZXkuc3Vic3RyKGkgKiA4LCA4KSk7XG4gIH1cblxuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihibG9jaykge1xuICAgIHJldHVybiB1dGlsLnN0cjJiaW4oZGVzKGRlc19jcmVhdGVLZXlzKHRoaXMua2V5WzJdKSxcbiAgICAgIGRlcyhkZXNfY3JlYXRlS2V5cyh0aGlzLmtleVsxXSksXG4gICAgICBkZXMoZGVzX2NyZWF0ZUtleXModGhpcy5rZXlbMF0pLFxuICAgICAgdXRpbC5iaW4yc3RyKGJsb2NrKSwgdHJ1ZSwgMCwgbnVsbCwgbnVsbCksXG4gICAgICBmYWxzZSwgMCwgbnVsbCwgbnVsbCksIHRydWUsIDAsIG51bGwsIG51bGwpKTtcbiAgfVxufVxuXG5EZXMua2V5U2l6ZSA9IERlcy5wcm90b3R5cGUua2V5U2l6ZSA9IDI0O1xuRGVzLmJsb2NrU2l6ZSA9IERlcy5wcm90b3R5cGUuYmxvY2tTaXplID0gODtcblxuLy8gVGhpcyBpcyBcIm9yaWdpbmFsXCIgREVTIC0gRGVzIGlzIGFjdHVhbGx5IFRyaXBsZSBERVMuXG4vLyBUaGlzIGlzIG9ubHkgZXhwb3J0ZWQgc28gd2UgY2FuIHVuaXQgdGVzdC5cblxuZnVuY3Rpb24gT3JpZ2luYWxEZXMoa2V5KSB7XG4gIHRoaXMua2V5ID0ga2V5O1xuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKGJsb2NrLCBwYWRkaW5nKSB7XG4gICAgdmFyIGtleXMgPSBkZXNfY3JlYXRlS2V5cyh0aGlzLmtleSk7XG4gICAgcmV0dXJuIHV0aWwuc3RyMmJpbihkZXMoa2V5cywgdXRpbC5iaW4yc3RyKGJsb2NrKSwgdHJ1ZSwgMCwgbnVsbCwgcGFkZGluZykpO1xuICB9XG5cbiAgdGhpcy5kZWNyeXB0ID0gZnVuY3Rpb24oYmxvY2ssIHBhZGRpbmcpIHtcbiAgICB2YXIga2V5cyA9IGRlc19jcmVhdGVLZXlzKHRoaXMua2V5KTtcbiAgICByZXR1cm4gdXRpbC5zdHIyYmluKGRlcyhrZXlzLCB1dGlsLmJpbjJzdHIoYmxvY2spLCBmYWxzZSwgMCwgbnVsbCwgcGFkZGluZykpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBkZXM6IERlcyxcbiAgb3JpZ2luYWxEZXM6IE9yaWdpbmFsRGVzXG59XG4iLCJ2YXIgZGVzTW9kdWxlID0gcmVxdWlyZSgnLi9kZXMuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGRlczogZGVzTW9kdWxlWydkZXMnXSxcbiAgb3JpZ2luYWxEZXM6IGRlc01vZHVsZVsnb3JpZ2luYWxEZXMnXSxcbiAgY2FzdDU6IHJlcXVpcmUoJy4vY2FzdDUuanMnKSxcbiAgdHdvZmlzaDogcmVxdWlyZSgnLi90d29maXNoLmpzJyksXG4gIGJsb3dmaXNoOiByZXF1aXJlKCcuL2Jsb3dmaXNoLmpzJylcbn1cblxudmFyIGFlcyA9IHJlcXVpcmUoJy4vYWVzLmpzJyk7XG5cbmZvciAodmFyIGkgaW4gYWVzKSB7XG4gIG1vZHVsZS5leHBvcnRzWydhZXMnICsgaV0gPSBhZXNbaV07XG59XG4iLCIvKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkggXG4gKiBcbiAqIENpcGhlci5qc1xuICogQSBibG9jay1jaXBoZXIgYWxnb3JpdGhtIGltcGxlbWVudGF0aW9uIG9uIEphdmFTY3JpcHRcbiAqIFNlZSBDaXBoZXIucmVhZG1lLnR4dCBmb3IgZnVydGhlciBpbmZvcm1hdGlvbi5cbiAqXG4gKiBDb3B5cmlnaHQoYykgMjAwOSBBdHN1c2hpIE9rYSBbIGh0dHA6Ly9va2EubnUvIF1cbiAqIFRoaXMgc2NyaXB0IGZpbGUgaXMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExHUExcbiAqXG4gKiBBQ0tOT1dMRURHTUVOVFxuICpcbiAqICAgICBUaGUgbWFpbiBzdWJyb3V0aW5lcyBhcmUgd3JpdHRlbiBieSBNaWNoaWVsIHZhbiBFdmVyZGluZ2VuLlxuICogXG4gKiAgICAgTWljaGllbCB2YW4gRXZlcmRpbmdlblxuICogICAgIGh0dHA6Ly9ob21lLnZlcnNhdGVsLm5sL01BdmFuRXZlcmRpbmdlbi9pbmRleC5odG1sXG4gKiBcbiAqICAgICBBbGwgcmlnaHRzIGZvciB0aGVzZSByb3V0aW5lcyBhcmUgcmVzZXJ2ZWQgdG8gTWljaGllbCB2YW4gRXZlcmRpbmdlbi5cbiAqXG4gKi9cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLy9NYXRoXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxudmFyIE1BWElOVCA9IDB4RkZGRkZGRkY7XG5cbmZ1bmN0aW9uIHJvdGIoYiwgbikge1xuICByZXR1cm4gKGIgPDwgbiB8IGIgPj4+ICg4IC0gbikpICYgMHhGRjtcbn1cblxuZnVuY3Rpb24gcm90dyh3LCBuKSB7XG4gIHJldHVybiAodyA8PCBuIHwgdyA+Pj4gKDMyIC0gbikpICYgTUFYSU5UO1xufVxuXG5mdW5jdGlvbiBnZXRXKGEsIGkpIHtcbiAgcmV0dXJuIGFbaV0gfCBhW2kgKyAxXSA8PCA4IHwgYVtpICsgMl0gPDwgMTYgfCBhW2kgKyAzXSA8PCAyNDtcbn1cblxuZnVuY3Rpb24gc2V0VyhhLCBpLCB3KSB7XG4gIGEuc3BsaWNlKGksIDQsIHcgJiAweEZGLCAodyA+Pj4gOCkgJiAweEZGLCAodyA+Pj4gMTYpICYgMHhGRiwgKHcgPj4+IDI0KSAmIDB4RkYpO1xufVxuXG5mdW5jdGlvbiBzZXRXSW52KGEsIGksIHcpIHtcbiAgYS5zcGxpY2UoaSwgNCwgKHcgPj4+IDI0KSAmIDB4RkYsICh3ID4+PiAxNikgJiAweEZGLCAodyA+Pj4gOCkgJiAweEZGLCB3ICYgMHhGRik7XG59XG5cbmZ1bmN0aW9uIGdldEIoeCwgbikge1xuICByZXR1cm4gKHggPj4+IChuICogOCkpICYgMHhGRjtcbn1cblxuZnVuY3Rpb24gZ2V0TnJCaXRzKGkpIHtcbiAgdmFyIG4gPSAwO1xuICB3aGlsZSAoaSA+IDApIHtcbiAgICBuKys7XG4gICAgaSA+Pj49IDE7XG4gIH1cbiAgcmV0dXJuIG47XG59XG5cbmZ1bmN0aW9uIGdldE1hc2sobikge1xuICByZXR1cm4gKDEgPDwgbikgLSAxO1xufVxuXG4vL2FkZGVkIDIwMDgvMTEvMTMgWFhYIE1VU1QgVVNFIE9ORS1XQVkgSEFTSCBGVU5DVElPTiBGT1IgU0VDVVJJVFkgUkVBU09OXG5cbmZ1bmN0aW9uIHJhbmRCeXRlKCkge1xuICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMjU2KTtcbn1cbi8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFR3b2Zpc2hcbi8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cblxuZnVuY3Rpb24gY3JlYXRlVHdvZmlzaCgpIHtcbiAgLy9cbiAgdmFyIGtleUJ5dGVzID0gbnVsbDtcbiAgdmFyIGRhdGFCeXRlcyA9IG51bGw7XG4gIHZhciBkYXRhT2Zmc2V0ID0gLTE7XG4gIC8vIHZhciBkYXRhTGVuZ3RoID0gLTE7XG4gIHZhciBhbGdvcml0aG1OYW1lID0gbnVsbDtcbiAgLy8gdmFyIGlkeDIgPSAtMTtcbiAgLy9cblxuICBhbGdvcml0aG1OYW1lID0gXCJ0d29maXNoXCI7XG5cbiAgdmFyIHRmc0tleSA9IFtdO1xuICB2YXIgdGZzTSA9IFtcbiAgICBbXSxcbiAgICBbXSxcbiAgICBbXSxcbiAgICBbXVxuICBdO1xuXG4gIGZ1bmN0aW9uIHRmc0luaXQoa2V5KSB7XG4gICAga2V5Qnl0ZXMgPSBrZXk7XG4gICAgdmFyIGksIGEsIGIsIGMsIGQsIG1lS2V5ID0gW10sXG4gICAgICBtb0tleSA9IFtdLFxuICAgICAgaW5LZXkgPSBbXTtcbiAgICB2YXIga0xlbjtcbiAgICB2YXIgc0tleSA9IFtdO1xuICAgIHZhciBmMDEsIGY1YiwgZmVmO1xuXG4gICAgdmFyIHEwID0gW1xuICAgICAgWzgsIDEsIDcsIDEzLCA2LCAxNSwgMywgMiwgMCwgMTEsIDUsIDksIDE0LCAxMiwgMTAsIDRdLFxuICAgICAgWzIsIDgsIDExLCAxMywgMTUsIDcsIDYsIDE0LCAzLCAxLCA5LCA0LCAwLCAxMCwgMTIsIDVdXG4gICAgXTtcbiAgICB2YXIgcTEgPSBbXG4gICAgICBbMTQsIDEyLCAxMSwgOCwgMSwgMiwgMywgNSwgMTUsIDQsIDEwLCA2LCA3LCAwLCA5LCAxM10sXG4gICAgICBbMSwgMTQsIDIsIDExLCA0LCAxMiwgMywgNywgNiwgMTMsIDEwLCA1LCAxNSwgOSwgMCwgOF1cbiAgICBdO1xuICAgIHZhciBxMiA9IFtcbiAgICAgIFsxMSwgMTAsIDUsIDE0LCA2LCAxMywgOSwgMCwgMTIsIDgsIDE1LCAzLCAyLCA0LCA3LCAxXSxcbiAgICAgIFs0LCAxMiwgNywgNSwgMSwgNiwgOSwgMTAsIDAsIDE0LCAxMywgOCwgMiwgMTEsIDMsIDE1XVxuICAgIF07XG4gICAgdmFyIHEzID0gW1xuICAgICAgWzEzLCA3LCAxNSwgNCwgMSwgMiwgNiwgMTQsIDksIDExLCAzLCAwLCA4LCA1LCAxMiwgMTBdLFxuICAgICAgWzExLCA5LCA1LCAxLCAxMiwgMywgMTMsIDE0LCA2LCA0LCA3LCAxNSwgMiwgMCwgOCwgMTBdXG4gICAgXTtcbiAgICB2YXIgcm9yNCA9IFswLCA4LCAxLCA5LCAyLCAxMCwgMywgMTEsIDQsIDEyLCA1LCAxMywgNiwgMTQsIDcsIDE1XTtcbiAgICB2YXIgYXNoeCA9IFswLCA5LCAyLCAxMSwgNCwgMTMsIDYsIDE1LCA4LCAxLCAxMCwgMywgMTIsIDUsIDE0LCA3XTtcbiAgICB2YXIgcSA9IFtcbiAgICAgIFtdLFxuICAgICAgW11cbiAgICBdO1xuICAgIHZhciBtID0gW1xuICAgICAgW10sXG4gICAgICBbXSxcbiAgICAgIFtdLFxuICAgICAgW11cbiAgICBdO1xuXG4gICAgZnVuY3Rpb24gZmZtNWIoeCkge1xuICAgICAgcmV0dXJuIHggXiAoeCA+PiAyKSBeIFswLCA5MCwgMTgwLCAyMzhdW3ggJiAzXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmZm1FZih4KSB7XG4gICAgICByZXR1cm4geCBeICh4ID4+IDEpIF4gKHggPj4gMikgXiBbMCwgMjM4LCAxODAsIDkwXVt4ICYgM107XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWRzUmVtKHAsIHEpIHtcbiAgICAgIHZhciBpLCB0LCB1O1xuICAgICAgZm9yIChpID0gMDsgaSA8IDg7IGkrKykge1xuICAgICAgICB0ID0gcSA+Pj4gMjQ7XG4gICAgICAgIHEgPSAoKHEgPDwgOCkgJiBNQVhJTlQpIHwgcCA+Pj4gMjQ7XG4gICAgICAgIHAgPSAocCA8PCA4KSAmIE1BWElOVDtcbiAgICAgICAgdSA9IHQgPDwgMTtcbiAgICAgICAgaWYgKHQgJiAxMjgpIHtcbiAgICAgICAgICB1IF49IDMzMztcbiAgICAgICAgfVxuICAgICAgICBxIF49IHQgXiAodSA8PCAxNik7XG4gICAgICAgIHUgXj0gdCA+Pj4gMTtcbiAgICAgICAgaWYgKHQgJiAxKSB7XG4gICAgICAgICAgdSBePSAxNjY7XG4gICAgICAgIH1cbiAgICAgICAgcSBePSB1IDw8IDI0IHwgdSA8PCA4O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHE7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcXAobiwgeCkge1xuICAgICAgdmFyIGEsIGIsIGMsIGQ7XG4gICAgICBhID0geCA+PiA0O1xuICAgICAgYiA9IHggJiAxNTtcbiAgICAgIGMgPSBxMFtuXVthIF4gYl07XG4gICAgICBkID0gcTFbbl1bcm9yNFtiXSBeIGFzaHhbYV1dO1xuICAgICAgcmV0dXJuIHEzW25dW3JvcjRbZF0gXiBhc2h4W2NdXSA8PCA0IHwgcTJbbl1bYyBeIGRdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhGdW4oeCwga2V5KSB7XG4gICAgICB2YXIgYSA9IGdldEIoeCwgMCksXG4gICAgICAgIGIgPSBnZXRCKHgsIDEpLFxuICAgICAgICBjID0gZ2V0Qih4LCAyKSxcbiAgICAgICAgZCA9IGdldEIoeCwgMyk7XG4gICAgICBzd2l0Y2ggKGtMZW4pIHtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIGEgPSBxWzFdW2FdIF4gZ2V0QihrZXlbM10sIDApO1xuICAgICAgICAgIGIgPSBxWzBdW2JdIF4gZ2V0QihrZXlbM10sIDEpO1xuICAgICAgICAgIGMgPSBxWzBdW2NdIF4gZ2V0QihrZXlbM10sIDIpO1xuICAgICAgICAgIGQgPSBxWzFdW2RdIF4gZ2V0QihrZXlbM10sIDMpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgYSA9IHFbMV1bYV0gXiBnZXRCKGtleVsyXSwgMCk7XG4gICAgICAgICAgYiA9IHFbMV1bYl0gXiBnZXRCKGtleVsyXSwgMSk7XG4gICAgICAgICAgYyA9IHFbMF1bY10gXiBnZXRCKGtleVsyXSwgMik7XG4gICAgICAgICAgZCA9IHFbMF1bZF0gXiBnZXRCKGtleVsyXSwgMyk7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBhID0gcVswXVtxWzBdW2FdIF4gZ2V0QihrZXlbMV0sIDApXSBeIGdldEIoa2V5WzBdLCAwKTtcbiAgICAgICAgICBiID0gcVswXVtxWzFdW2JdIF4gZ2V0QihrZXlbMV0sIDEpXSBeIGdldEIoa2V5WzBdLCAxKTtcbiAgICAgICAgICBjID0gcVsxXVtxWzBdW2NdIF4gZ2V0QihrZXlbMV0sIDIpXSBeIGdldEIoa2V5WzBdLCAyKTtcbiAgICAgICAgICBkID0gcVsxXVtxWzFdW2RdIF4gZ2V0QihrZXlbMV0sIDMpXSBeIGdldEIoa2V5WzBdLCAzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtWzBdW2FdIF4gbVsxXVtiXSBeIG1bMl1bY10gXiBtWzNdW2RdO1xuICAgIH1cblxuICAgIGtleUJ5dGVzID0ga2V5Qnl0ZXMuc2xpY2UoMCwgMzIpO1xuICAgIGkgPSBrZXlCeXRlcy5sZW5ndGg7XG4gICAgd2hpbGUgKGkgIT0gMTYgJiYgaSAhPSAyNCAmJiBpICE9IDMyKVxuICAgICAga2V5Qnl0ZXNbaSsrXSA9IDA7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwga2V5Qnl0ZXMubGVuZ3RoOyBpICs9IDQpIHtcbiAgICAgIGluS2V5W2kgPj4gMl0gPSBnZXRXKGtleUJ5dGVzLCBpKTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG4gICAgICBxWzBdW2ldID0gcXAoMCwgaSk7XG4gICAgICBxWzFdW2ldID0gcXAoMSwgaSk7XG4gICAgfVxuICAgIGZvciAoaSA9IDA7IGkgPCAyNTY7IGkrKykge1xuICAgICAgZjAxID0gcVsxXVtpXTtcbiAgICAgIGY1YiA9IGZmbTViKGYwMSk7XG4gICAgICBmZWYgPSBmZm1FZihmMDEpO1xuICAgICAgbVswXVtpXSA9IGYwMSArIChmNWIgPDwgOCkgKyAoZmVmIDw8IDE2KSArIChmZWYgPDwgMjQpO1xuICAgICAgbVsyXVtpXSA9IGY1YiArIChmZWYgPDwgOCkgKyAoZjAxIDw8IDE2KSArIChmZWYgPDwgMjQpO1xuICAgICAgZjAxID0gcVswXVtpXTtcbiAgICAgIGY1YiA9IGZmbTViKGYwMSk7XG4gICAgICBmZWYgPSBmZm1FZihmMDEpO1xuICAgICAgbVsxXVtpXSA9IGZlZiArIChmZWYgPDwgOCkgKyAoZjViIDw8IDE2KSArIChmMDEgPDwgMjQpO1xuICAgICAgbVszXVtpXSA9IGY1YiArIChmMDEgPDwgOCkgKyAoZmVmIDw8IDE2KSArIChmNWIgPDwgMjQpO1xuICAgIH1cblxuICAgIGtMZW4gPSBpbktleS5sZW5ndGggLyAyO1xuICAgIGZvciAoaSA9IDA7IGkgPCBrTGVuOyBpKyspIHtcbiAgICAgIGEgPSBpbktleVtpICsgaV07XG4gICAgICBtZUtleVtpXSA9IGE7XG4gICAgICBiID0gaW5LZXlbaSArIGkgKyAxXTtcbiAgICAgIG1vS2V5W2ldID0gYjtcbiAgICAgIHNLZXlba0xlbiAtIGkgLSAxXSA9IG1kc1JlbShhLCBiKTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IDQwOyBpICs9IDIpIHtcbiAgICAgIGEgPSAweDEwMTAxMDEgKiBpO1xuICAgICAgYiA9IGEgKyAweDEwMTAxMDE7XG4gICAgICBhID0gaEZ1bihhLCBtZUtleSk7XG4gICAgICBiID0gcm90dyhoRnVuKGIsIG1vS2V5KSwgOCk7XG4gICAgICB0ZnNLZXlbaV0gPSAoYSArIGIpICYgTUFYSU5UO1xuICAgICAgdGZzS2V5W2kgKyAxXSA9IHJvdHcoYSArIDIgKiBiLCA5KTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG4gICAgICBhID0gYiA9IGMgPSBkID0gaTtcbiAgICAgIHN3aXRjaCAoa0xlbikge1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgYSA9IHFbMV1bYV0gXiBnZXRCKHNLZXlbM10sIDApO1xuICAgICAgICAgIGIgPSBxWzBdW2JdIF4gZ2V0QihzS2V5WzNdLCAxKTtcbiAgICAgICAgICBjID0gcVswXVtjXSBeIGdldEIoc0tleVszXSwgMik7XG4gICAgICAgICAgZCA9IHFbMV1bZF0gXiBnZXRCKHNLZXlbM10sIDMpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgYSA9IHFbMV1bYV0gXiBnZXRCKHNLZXlbMl0sIDApO1xuICAgICAgICAgIGIgPSBxWzFdW2JdIF4gZ2V0QihzS2V5WzJdLCAxKTtcbiAgICAgICAgICBjID0gcVswXVtjXSBeIGdldEIoc0tleVsyXSwgMik7XG4gICAgICAgICAgZCA9IHFbMF1bZF0gXiBnZXRCKHNLZXlbMl0sIDMpO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgdGZzTVswXVtpXSA9IG1bMF1bcVswXVtxWzBdW2FdIF4gZ2V0QihzS2V5WzFdLCAwKV0gXiBnZXRCKHNLZXlbMF0sIDApXTtcbiAgICAgICAgICB0ZnNNWzFdW2ldID0gbVsxXVtxWzBdW3FbMV1bYl0gXiBnZXRCKHNLZXlbMV0sIDEpXSBeIGdldEIoc0tleVswXSwgMSldO1xuICAgICAgICAgIHRmc01bMl1baV0gPSBtWzJdW3FbMV1bcVswXVtjXSBeIGdldEIoc0tleVsxXSwgMildIF4gZ2V0QihzS2V5WzBdLCAyKV07XG4gICAgICAgICAgdGZzTVszXVtpXSA9IG1bM11bcVsxXVtxWzFdW2RdIF4gZ2V0QihzS2V5WzFdLCAzKV0gXiBnZXRCKHNLZXlbMF0sIDMpXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB0ZnNHMCh4KSB7XG4gICAgcmV0dXJuIHRmc01bMF1bZ2V0Qih4LCAwKV0gXiB0ZnNNWzFdW2dldEIoeCwgMSldIF4gdGZzTVsyXVtnZXRCKHgsIDIpXSBeIHRmc01bM11bZ2V0Qih4LCAzKV07XG4gIH1cblxuICBmdW5jdGlvbiB0ZnNHMSh4KSB7XG4gICAgcmV0dXJuIHRmc01bMF1bZ2V0Qih4LCAzKV0gXiB0ZnNNWzFdW2dldEIoeCwgMCldIF4gdGZzTVsyXVtnZXRCKHgsIDEpXSBeIHRmc01bM11bZ2V0Qih4LCAyKV07XG4gIH1cblxuICBmdW5jdGlvbiB0ZnNGcm5kKHIsIGJsaykge1xuICAgIHZhciBhID0gdGZzRzAoYmxrWzBdKTtcbiAgICB2YXIgYiA9IHRmc0cxKGJsa1sxXSk7XG4gICAgYmxrWzJdID0gcm90dyhibGtbMl0gXiAoYSArIGIgKyB0ZnNLZXlbNCAqIHIgKyA4XSkgJiBNQVhJTlQsIDMxKTtcbiAgICBibGtbM10gPSByb3R3KGJsa1szXSwgMSkgXiAoYSArIDIgKiBiICsgdGZzS2V5WzQgKiByICsgOV0pICYgTUFYSU5UO1xuICAgIGEgPSB0ZnNHMChibGtbMl0pO1xuICAgIGIgPSB0ZnNHMShibGtbM10pO1xuICAgIGJsa1swXSA9IHJvdHcoYmxrWzBdIF4gKGEgKyBiICsgdGZzS2V5WzQgKiByICsgMTBdKSAmIE1BWElOVCwgMzEpO1xuICAgIGJsa1sxXSA9IHJvdHcoYmxrWzFdLCAxKSBeIChhICsgMiAqIGIgKyB0ZnNLZXlbNCAqIHIgKyAxMV0pICYgTUFYSU5UO1xuICB9XG5cbiAgZnVuY3Rpb24gdGZzSXJuZChpLCBibGspIHtcbiAgICB2YXIgYSA9IHRmc0cwKGJsa1swXSk7XG4gICAgdmFyIGIgPSB0ZnNHMShibGtbMV0pO1xuICAgIGJsa1syXSA9IHJvdHcoYmxrWzJdLCAxKSBeIChhICsgYiArIHRmc0tleVs0ICogaSArIDEwXSkgJiBNQVhJTlQ7XG4gICAgYmxrWzNdID0gcm90dyhibGtbM10gXiAoYSArIDIgKiBiICsgdGZzS2V5WzQgKiBpICsgMTFdKSAmIE1BWElOVCwgMzEpO1xuICAgIGEgPSB0ZnNHMChibGtbMl0pO1xuICAgIGIgPSB0ZnNHMShibGtbM10pO1xuICAgIGJsa1swXSA9IHJvdHcoYmxrWzBdLCAxKSBeIChhICsgYiArIHRmc0tleVs0ICogaSArIDhdKSAmIE1BWElOVDtcbiAgICBibGtbMV0gPSByb3R3KGJsa1sxXSBeIChhICsgMiAqIGIgKyB0ZnNLZXlbNCAqIGkgKyA5XSkgJiBNQVhJTlQsIDMxKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRmc0Nsb3NlKCkge1xuICAgIHRmc0tleSA9IFtdO1xuICAgIHRmc00gPSBbXG4gICAgICBbXSxcbiAgICAgIFtdLFxuICAgICAgW10sXG4gICAgICBbXVxuICAgIF07XG4gIH1cblxuICBmdW5jdGlvbiB0ZnNFbmNyeXB0KGRhdGEsIG9mZnNldCkge1xuICAgIGRhdGFCeXRlcyA9IGRhdGE7XG4gICAgZGF0YU9mZnNldCA9IG9mZnNldDtcbiAgICB2YXIgYmxrID0gW2dldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0KSBeIHRmc0tleVswXSxcbiAgICAgICAgZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA0KSBeIHRmc0tleVsxXSxcbiAgICAgICAgZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA4KSBeIHRmc0tleVsyXSxcbiAgICAgICAgZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMikgXiB0ZnNLZXlbM11cbiAgICBdO1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgODsgaisrKSB7XG4gICAgICB0ZnNGcm5kKGosIGJsayk7XG4gICAgfVxuICAgIHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0LCBibGtbMl0gXiB0ZnNLZXlbNF0pO1xuICAgIHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0ICsgNCwgYmxrWzNdIF4gdGZzS2V5WzVdKTtcbiAgICBzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDgsIGJsa1swXSBeIHRmc0tleVs2XSk7XG4gICAgc2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMiwgYmxrWzFdIF4gdGZzS2V5WzddKTtcbiAgICBkYXRhT2Zmc2V0ICs9IDE2O1xuICAgIHJldHVybiBkYXRhQnl0ZXM7XG4gIH1cblxuICBmdW5jdGlvbiB0ZnNEZWNyeXB0KGRhdGEsIG9mZnNldCkge1xuICAgIGRhdGFCeXRlcyA9IGRhdGE7XG4gICAgZGF0YU9mZnNldCA9IG9mZnNldDtcbiAgICB2YXIgYmxrID0gW2dldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0KSBeIHRmc0tleVs0XSxcbiAgICAgICAgZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA0KSBeIHRmc0tleVs1XSxcbiAgICAgICAgZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA4KSBeIHRmc0tleVs2XSxcbiAgICAgICAgZ2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyAxMikgXiB0ZnNLZXlbN11cbiAgICBdO1xuICAgIGZvciAodmFyIGogPSA3OyBqID49IDA7IGotLSkge1xuICAgICAgdGZzSXJuZChqLCBibGspO1xuICAgIH1cbiAgICBzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCwgYmxrWzJdIF4gdGZzS2V5WzBdKTtcbiAgICBzZXRXKGRhdGFCeXRlcywgZGF0YU9mZnNldCArIDQsIGJsa1szXSBeIHRmc0tleVsxXSk7XG4gICAgc2V0VyhkYXRhQnl0ZXMsIGRhdGFPZmZzZXQgKyA4LCBibGtbMF0gXiB0ZnNLZXlbMl0pO1xuICAgIHNldFcoZGF0YUJ5dGVzLCBkYXRhT2Zmc2V0ICsgMTIsIGJsa1sxXSBeIHRmc0tleVszXSk7XG4gICAgZGF0YU9mZnNldCArPSAxNjtcbiAgfVxuXG4gIC8vIGFkZGVkIGJ5IFJlY3VyaXR5IExhYnNcblxuICBmdW5jdGlvbiB0ZnNGaW5hbCgpIHtcbiAgICByZXR1cm4gZGF0YUJ5dGVzO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBcInR3b2Zpc2hcIixcbiAgICBibG9ja3NpemU6IDEyOCAvIDgsXG4gICAgb3BlbjogdGZzSW5pdCxcbiAgICBjbG9zZTogdGZzQ2xvc2UsXG4gICAgZW5jcnlwdDogdGZzRW5jcnlwdCxcbiAgICBkZWNyeXB0OiB0ZnNEZWNyeXB0LFxuICAgIC8vIGFkZGVkIGJ5IFJlY3VyaXR5IExhYnNcbiAgICBmaW5hbGl6ZTogdGZzRmluYWxcbiAgfTtcbn1cblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbi8vIGFkZGVkIGJ5IFJlY3VyaXR5IExhYnNcblxuZnVuY3Rpb24gVEZlbmNyeXB0KGJsb2NrLCBrZXkpIHtcbiAgdmFyIGJsb2NrX2NvcHkgPSBbXS5jb25jYXQoYmxvY2spO1xuICB2YXIgdGYgPSBjcmVhdGVUd29maXNoKCk7XG4gIHRmLm9wZW4odXRpbC5zdHIyYmluKGtleSksIDApO1xuICB2YXIgcmVzdWx0ID0gdGYuZW5jcnlwdChibG9ja19jb3B5LCAwKTtcbiAgdGYuY2xvc2UoKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gVEYoa2V5KSB7XG4gIHRoaXMudGYgPSBjcmVhdGVUd29maXNoKCk7XG4gIHRoaXMudGYub3Blbih1dGlsLnN0cjJiaW4oa2V5KSwgMCk7XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oYmxvY2spIHtcbiAgICByZXR1cm4gdGhpcy50Zi5lbmNyeXB0KFtdLmNvbmNhdChibG9jayksIDApO1xuICB9XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBURjtcbm1vZHVsZS5leHBvcnRzLmtleVNpemUgPSBURi5wcm90b3R5cGUua2V5U2l6ZSA9IDMyO1xubW9kdWxlLmV4cG9ydHMuYmxvY2tTaXplID0gVEYucHJvdG90eXBlLmJsb2NrU2l6ZSA9IDE2O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0EgXG5cbi8vIFRoZSBHUEc0QnJvd3NlcnMgY3J5cHRvIGludGVyZmFjZVxuXG52YXIgcmFuZG9tID0gcmVxdWlyZSgnLi9yYW5kb20uanMnKSxcbiAgY2lwaGVyID0gcmVxdWlyZSgnLi9jaXBoZXInKSxcbiAgcHVibGljS2V5ID0gcmVxdWlyZSgnLi9wdWJsaWNfa2V5JyksXG4gIHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIC8qKlxuICAgKiBFbmNyeXB0cyBkYXRhIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHVibGljIGtleSBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBcbiAgICogYW5kIHRoZSBzcGVjaWZpZWQgYWxnb3JpdGhtLlxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gQWxnb3JpdGhtIHRvIGJlIHVzZWQgKFNlZSBSRkM0ODgwIDkuMSlcbiAgICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IHB1YmxpY01QSXMgQWxnb3JpdGhtIGRlcGVuZGVudCBtdWx0aXByZWNpc2lvbiBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGl9IGRhdGEgRGF0YSB0byBiZSBlbmNyeXB0ZWQgYXMgTVBJXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfdHlwZV9tcGlbXX0gaWYgUlNBIGFuIG9wZW5wZ3BfdHlwZV9tcGk7IFxuICAgKiBpZiBlbGdhbWFsIGVuY3J5cHRpb24gYW4gYXJyYXkgb2YgdHdvIG9wZW5wZ3BfdHlwZV9tcGkgaXMgcmV0dXJuZWQ7IG90aGVyd2lzZSBudWxsXG4gICAqL1xuICBwdWJsaWNLZXlFbmNyeXB0OiBmdW5jdGlvbihhbGdvLCBwdWJsaWNNUElzLCBkYXRhKSB7XG4gICAgdmFyIHJlc3VsdCA9IChmdW5jdGlvbigpIHtcbiAgICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgICBjYXNlICdyc2FfZW5jcnlwdCc6XG4gICAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgICAgICAgIHZhciByc2EgPSBuZXcgcHVibGljS2V5LnJzYSgpO1xuICAgICAgICAgIHZhciBuID0gcHVibGljTVBJc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgZSA9IHB1YmxpY01QSXNbMV0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIG0gPSBkYXRhLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHJldHVybiBbcnNhLmVuY3J5cHQobSwgZSwgbildO1xuXG4gICAgICAgIGNhc2UgJ2VsZ2FtYWwnOlxuICAgICAgICAgIHZhciBlbGdhbWFsID0gbmV3IHB1YmxpY0tleS5lbGdhbWFsKCk7XG4gICAgICAgICAgdmFyIHAgPSBwdWJsaWNNUElzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBnID0gcHVibGljTVBJc1sxXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgeSA9IHB1YmxpY01QSXNbMl0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIG0gPSBkYXRhLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHJldHVybiBlbGdhbWFsLmVuY3J5cHQobSwgZywgcCwgeSk7XG5cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgfSkoKTtcblxuICAgIHJldHVybiByZXN1bHQubWFwKGZ1bmN0aW9uKGJuKSB7XG4gICAgICB2YXIgbXBpID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgICBtcGkuZnJvbUJpZ0ludGVnZXIoYm4pO1xuICAgICAgcmV0dXJuIG1waTtcbiAgICB9KTtcbiAgfSxcblxuICAvKipcbiAgICogRGVjcnlwdHMgZGF0YSB1c2luZyB0aGUgc3BlY2lmaWVkIHB1YmxpYyBrZXkgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgb2YgdGhlIHByaXZhdGUga2V5LFxuICAgKiB0aGUgc3BlY2lmaWVkIHNlY3JldE1QSXMgb2YgdGhlIHByaXZhdGUga2V5IGFuZCB0aGUgc3BlY2lmaWVkIGFsZ29yaXRobS5cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEFsZ29yaXRobSB0byBiZSB1c2VkIChTZWUgUkZDNDg4MCA5LjEpXG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBwdWJsaWNNUElzIEFsZ29yaXRobSBkZXBlbmRlbnQgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgXG4gICAqIG9mIHRoZSBwdWJsaWMga2V5IHBhcnQgb2YgdGhlIHByaXZhdGUga2V5XG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waVtdfSBzZWNyZXRNUElzIEFsZ29yaXRobSBkZXBlbmRlbnQgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgXG4gICAqIG9mIHRoZSBwcml2YXRlIGtleSB1c2VkXG4gICAqIEBwYXJhbSB7b3BlbnBncF90eXBlX21waX0gZGF0YSBEYXRhIHRvIGJlIGVuY3J5cHRlZCBhcyBNUElcbiAgICogQHJldHVybiB7b3BlbnBncF90eXBlX21waX0gcmV0dXJucyBhIGJpZyBpbnRlZ2VyIGNvbnRhaW5pbmcgdGhlIGRlY3J5cHRlZCBkYXRhOyBvdGhlcndpc2UgbnVsbFxuICAgKi9cblxuICBwdWJsaWNLZXlEZWNyeXB0OiBmdW5jdGlvbihhbGdvLCBrZXlJbnRlZ2VycywgZGF0YUludGVnZXJzKSB7XG4gICAgdmFyIGJuID0gKGZ1bmN0aW9uKCkge1xuICAgICAgc3dpdGNoIChhbGdvKSB7XG4gICAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgICAgICBjYXNlICdyc2FfZW5jcnlwdCc6XG4gICAgICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICAgICAgLy8gMCBhbmQgMSBhcmUgdGhlIHB1YmxpYyBrZXkuXG4gICAgICAgICAgdmFyIGQgPSBrZXlJbnRlZ2Vyc1syXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgcCA9IGtleUludGVnZXJzWzNdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBxID0ga2V5SW50ZWdlcnNbNF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIHUgPSBrZXlJbnRlZ2Vyc1s1XS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgbSA9IGRhdGFJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICByZXR1cm4gcnNhLmRlY3J5cHQobSwgZCwgcCwgcSwgdSk7XG4gICAgICAgIGNhc2UgJ2VsZ2FtYWwnOlxuICAgICAgICAgIHZhciBlbGdhbWFsID0gbmV3IHB1YmxpY0tleS5lbGdhbWFsKCk7XG4gICAgICAgICAgdmFyIHggPSBrZXlJbnRlZ2Vyc1szXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgICB2YXIgYzEgPSBkYXRhSW50ZWdlcnNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgdmFyIGMyID0gZGF0YUludGVnZXJzWzFdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICAgIHZhciBwID0ga2V5SW50ZWdlcnNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgICAgcmV0dXJuIGVsZ2FtYWwuZGVjcnlwdChjMSwgYzIsIHAsIHgpO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICB2YXIgcmVzdWx0ID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgcmVzdWx0LmZyb21CaWdJbnRlZ2VyKGJuKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIC8qKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgaW50ZWdlcnMgY29tcHJpc2luZyB0aGUgcHJpdmF0ZSBrZXkgb2YgYW4gYWxnb3JpdGhtXG4gICAqIEBwYXJhbSB7b3BlbnBncC5wdWJsaWNrZXl9IGFsZ28gVGhlIHB1YmxpYyBrZXkgYWxnb3JpdGhtXG4gICAqIEByZXR1cm4ge0ludGVnZXJ9IFRoZSBudW1iZXIgb2YgaW50ZWdlcnMuXG4gICAqL1xuICBnZXRQcml2YXRlTXBpQ291bnQ6IGZ1bmN0aW9uKGFsZ28pIHtcbiAgICBzd2l0Y2ggKGFsZ28pIHtcbiAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0JzpcbiAgICAgIGNhc2UgJ3JzYV9lbmNyeXB0X3NpZ24nOlxuICAgICAgY2FzZSAncnNhX3NpZ24nOlxuICAgICAgICAvLyAgIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIFJTQSBzZWNyZXQga2V5czpcbiAgICAgICAgLy8gICAtIG11bHRpcHJlY2lzaW9uIGludGVnZXIgKE1QSSkgb2YgUlNBIHNlY3JldCBleHBvbmVudCBkLlxuICAgICAgICAvLyAgIC0gTVBJIG9mIFJTQSBzZWNyZXQgcHJpbWUgdmFsdWUgcC5cbiAgICAgICAgLy8gICAtIE1QSSBvZiBSU0Egc2VjcmV0IHByaW1lIHZhbHVlIHEgKHAgPCBxKS5cbiAgICAgICAgLy8gICAtIE1QSSBvZiB1LCB0aGUgbXVsdGlwbGljYXRpdmUgaW52ZXJzZSBvZiBwLCBtb2QgcS5cbiAgICAgICAgcmV0dXJuIDQ7XG4gICAgICBjYXNlICdlbGdhbWFsJzpcbiAgICAgICAgLy8gQWxnb3JpdGhtLVNwZWNpZmljIEZpZWxkcyBmb3IgRWxnYW1hbCBzZWNyZXQga2V5czpcbiAgICAgICAgLy8gICAtIE1QSSBvZiBFbGdhbWFsIHNlY3JldCBleHBvbmVudCB4LlxuICAgICAgICByZXR1cm4gMTtcbiAgICAgIGNhc2UgJ2RzYSc6XG4gICAgICAgIC8vIEFsZ29yaXRobS1TcGVjaWZpYyBGaWVsZHMgZm9yIERTQSBzZWNyZXQga2V5czpcbiAgICAgICAgLy8gICAtIE1QSSBvZiBEU0Egc2VjcmV0IGV4cG9uZW50IHguXG4gICAgICAgIHJldHVybiAxO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGFsZ29yaXRobScpO1xuICAgIH1cbiAgfSxcblxuICBnZXRQdWJsaWNNcGlDb3VudDogZnVuY3Rpb24oYWxnbykge1xuICAgIC8vIC0gQSBzZXJpZXMgb2YgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnMgY29tcHJpc2luZyB0aGUga2V5IG1hdGVyaWFsOlxuICAgIC8vICAgQWxnb3JpdGhtLVNwZWNpZmljIEZpZWxkcyBmb3IgUlNBIHB1YmxpYyBrZXlzOlxuICAgIC8vICAgICAgIC0gYSBtdWx0aXByZWNpc2lvbiBpbnRlZ2VyIChNUEkpIG9mIFJTQSBwdWJsaWMgbW9kdWx1cyBuO1xuICAgIC8vICAgICAgIC0gYW4gTVBJIG9mIFJTQSBwdWJsaWMgZW5jcnlwdGlvbiBleHBvbmVudCBlLlxuICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgICAgY2FzZSAncnNhX2VuY3J5cHRfc2lnbic6XG4gICAgICBjYXNlICdyc2Ffc2lnbic6XG4gICAgICAgIHJldHVybiAyO1xuXG4gICAgICAgIC8vICAgQWxnb3JpdGhtLVNwZWNpZmljIEZpZWxkcyBmb3IgRWxnYW1hbCBwdWJsaWMga2V5czpcbiAgICAgICAgLy8gICAgIC0gTVBJIG9mIEVsZ2FtYWwgcHJpbWUgcDtcbiAgICAgICAgLy8gICAgIC0gTVBJIG9mIEVsZ2FtYWwgZ3JvdXAgZ2VuZXJhdG9yIGc7XG4gICAgICAgIC8vICAgICAtIE1QSSBvZiBFbGdhbWFsIHB1YmxpYyBrZXkgdmFsdWUgeSAoPSBnKip4IG1vZCBwIHdoZXJlIHggIGlzIHNlY3JldCkuXG4gICAgICBjYXNlICdlbGdhbWFsJzpcbiAgICAgICAgcmV0dXJuIDM7XG5cbiAgICAgICAgLy8gICBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBEU0EgcHVibGljIGtleXM6XG4gICAgICAgIC8vICAgICAgIC0gTVBJIG9mIERTQSBwcmltZSBwO1xuICAgICAgICAvLyAgICAgICAtIE1QSSBvZiBEU0EgZ3JvdXAgb3JkZXIgcSAocSBpcyBhIHByaW1lIGRpdmlzb3Igb2YgcC0xKTtcbiAgICAgICAgLy8gICAgICAgLSBNUEkgb2YgRFNBIGdyb3VwIGdlbmVyYXRvciBnO1xuICAgICAgICAvLyAgICAgICAtIE1QSSBvZiBEU0EgcHVibGljLWtleSB2YWx1ZSB5ICg9IGcqKnggbW9kIHAgd2hlcmUgeCAgaXMgc2VjcmV0KS5cbiAgICAgIGNhc2UgJ2RzYSc6XG4gICAgICAgIHJldHVybiA0O1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gYWxnb3JpdGhtLicpO1xuICAgIH1cbiAgfSxcblxuICBnZW5lcmF0ZU1waTogZnVuY3Rpb24oYWxnbywgYml0cykge1xuICAgIHZhciByZXN1bHQgPSAoZnVuY3Rpb24oKSB7XG4gICAgICBzd2l0Y2ggKGFsZ28pIHtcbiAgICAgICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgICAgICBjYXNlICdyc2FfZW5jcnlwdF9zaWduJzpcbiAgICAgICAgY2FzZSAncnNhX3NpZ24nOlxuICAgICAgICAgIC8vcmVtZW1iZXIgXCJwdWJsaWNLZXlcIiByZWZlcnMgdG8gdGhlIGNyeXB0by9wdWJsaWNfa2V5IGRpclxuICAgICAgICAgIHZhciByc2EgPSBuZXcgcHVibGljS2V5LnJzYSgpO1xuICAgICAgICAgIHZhciBrZXlPYmplY3QgPSByc2EuZ2VuZXJhdGUoYml0cywgXCIxMDAwMVwiKTtcbiAgICAgICAgICB2YXIgb3V0cHV0ID0gW107XG4gICAgICAgICAgb3V0cHV0LnB1c2goa2V5T2JqZWN0Lm4pO1xuICAgICAgICAgIG91dHB1dC5wdXNoKGtleU9iamVjdC5lZSk7XG4gICAgICAgICAgb3V0cHV0LnB1c2goa2V5T2JqZWN0LmQpO1xuICAgICAgICAgIG91dHB1dC5wdXNoKGtleU9iamVjdC5wKTtcbiAgICAgICAgICBvdXRwdXQucHVzaChrZXlPYmplY3QucSk7XG4gICAgICAgICAgb3V0cHV0LnB1c2goa2V5T2JqZWN0LnUpO1xuICAgICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBhbGdvcml0aG0gZm9yIGtleSBnZW5lcmF0aW9uLicpO1xuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICByZXR1cm4gcmVzdWx0Lm1hcChmdW5jdGlvbihibikge1xuICAgICAgdmFyIG1waSA9IG5ldyB0eXBlX21waSgpO1xuICAgICAgbXBpLmZyb21CaWdJbnRlZ2VyKGJuKTtcbiAgICAgIHJldHVybiBtcGk7XG4gICAgfSk7XG4gIH0sXG5cblxuICAvKipcbiAgICogZ2VuZXJhdGUgcmFuZG9tIGJ5dGUgcHJlZml4IGFzIHN0cmluZyBmb3IgdGhlIHNwZWNpZmllZCBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEFsZ29yaXRobSB0byB1c2UgKHNlZSBSRkM0ODgwIDkuMilcbiAgICogQHJldHVybiB7U3RyaW5nfSBSYW5kb20gYnl0ZXMgd2l0aCBsZW5ndGggZXF1YWwgdG8gdGhlIGJsb2NrXG4gICAqIHNpemUgb2YgdGhlIGNpcGhlclxuICAgKi9cbiAgZ2V0UHJlZml4UmFuZG9tOiBmdW5jdGlvbihhbGdvKSB7XG4gICAgcmV0dXJuIHJhbmRvbS5nZXRSYW5kb21CeXRlcyhjaXBoZXJbYWxnb10uYmxvY2tTaXplKTtcbiAgfSxcblxuICAvKipcbiAgICogR2VuZXJhdGluZyBhIHNlc3Npb24ga2V5IGZvciB0aGUgc3BlY2lmaWVkIHN5bW1ldHJpYyBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEFsZ29yaXRobSB0byB1c2UgKHNlZSBSRkM0ODgwIDkuMilcbiAgICogQHJldHVybiB7U3RyaW5nfSBSYW5kb20gYnl0ZXMgYXMgYSBzdHJpbmcgdG8gYmUgdXNlZCBhcyBhIGtleVxuICAgKi9cbiAgZ2VuZXJhdGVTZXNzaW9uS2V5OiBmdW5jdGlvbihhbGdvKSB7XG4gICAgcmV0dXJuIHJhbmRvbS5nZXRSYW5kb21CeXRlcyhjaXBoZXJbYWxnb10ua2V5U2l6ZSk7XG4gIH0sXG5cbn07XG4iLCJ2YXIgc2hhID0gcmVxdWlyZSgnLi9zaGEuanMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIG1kNTogcmVxdWlyZSgnLi9tZDUuanMnKSxcbiAgc2hhMTogc2hhLnNoYTEsXG4gIHNoYTI1Njogc2hhLnNoYTI1NixcbiAgc2hhMjI0OiBzaGEuc2hhMjI0LFxuICBzaGEzODQ6IHNoYS5zaGEzODQsXG4gIHNoYTUxMjogc2hhLnNoYTUxMixcbiAgcmlwZW1kOiByZXF1aXJlKCcuL3JpcGUtbWQuanMnKSxcblxuICAvKipcbiAgICogQ3JlYXRlIGEgaGFzaCBvbiB0aGUgc3BlY2lmaWVkIGRhdGEgdXNpbmcgdGhlIHNwZWNpZmllZCBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEhhc2ggYWxnb3JpdGhtIHR5cGUgKHNlZSBSRkM0ODgwIDkuNClcbiAgICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBiZSBoYXNoZWRcbiAgICogQHJldHVybiB7U3RyaW5nfSBoYXNoIHZhbHVlXG4gICAqL1xuICBkaWdlc3Q6IGZ1bmN0aW9uKGFsZ28sIGRhdGEpIHtcbiAgICBzd2l0Y2ggKGFsZ28pIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgLy8gLSBNRDUgW0hBQ11cbiAgICAgICAgcmV0dXJuIHRoaXMubWQ1KGRhdGEpO1xuICAgICAgY2FzZSAyOlxuICAgICAgICAvLyAtIFNIQS0xIFtGSVBTMTgwXVxuICAgICAgICByZXR1cm4gdGhpcy5zaGExKGRhdGEpO1xuICAgICAgY2FzZSAzOlxuICAgICAgICAvLyAtIFJJUEUtTUQvMTYwIFtIQUNdXG4gICAgICAgIHJldHVybiB0aGlzLnJpcGVtZChkYXRhKTtcbiAgICAgIGNhc2UgODpcbiAgICAgICAgLy8gLSBTSEEyNTYgW0ZJUFMxODBdXG4gICAgICAgIHJldHVybiB0aGlzLnNoYTI1NihkYXRhKTtcbiAgICAgIGNhc2UgOTpcbiAgICAgICAgLy8gLSBTSEEzODQgW0ZJUFMxODBdXG4gICAgICAgIHJldHVybiB0aGlzLnNoYTM4NChkYXRhKTtcbiAgICAgIGNhc2UgMTA6XG4gICAgICAgIC8vIC0gU0hBNTEyIFtGSVBTMTgwXVxuICAgICAgICByZXR1cm4gdGhpcy5zaGE1MTIoZGF0YSk7XG4gICAgICBjYXNlIDExOlxuICAgICAgICAvLyAtIFNIQTIyNCBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIHRoaXMuc2hhMjI0KGRhdGEpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhhc2ggZnVuY3Rpb24uJyk7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBoYXNoIHNpemUgaW4gYnl0ZXMgb2YgdGhlIHNwZWNpZmllZCBoYXNoIGFsZ29yaXRobSB0eXBlXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gYWxnbyBIYXNoIGFsZ29yaXRobSB0eXBlIChTZWUgUkZDNDg4MCA5LjQpXG4gICAqIEByZXR1cm4ge0ludGVnZXJ9IFNpemUgaW4gYnl0ZXMgb2YgdGhlIHJlc3VsdGluZyBoYXNoXG4gICAqL1xuICBnZXRIYXNoQnl0ZUxlbmd0aDogZnVuY3Rpb24oYWxnbykge1xuICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgY2FzZSAxOlxuICAgICAgICAvLyAtIE1ENSBbSEFDXVxuICAgICAgICByZXR1cm4gMTY7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIC8vIC0gU0hBLTEgW0ZJUFMxODBdXG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vIC0gUklQRS1NRC8xNjAgW0hBQ11cbiAgICAgICAgcmV0dXJuIDIwO1xuICAgICAgY2FzZSA4OlxuICAgICAgICAvLyAtIFNIQTI1NiBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIDMyO1xuICAgICAgY2FzZSA5OlxuICAgICAgICAvLyAtIFNIQTM4NCBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIDQ4XG4gICAgICBjYXNlIDEwOlxuICAgICAgICAvLyAtIFNIQTUxMiBbRklQUzE4MF1cbiAgICAgICAgcmV0dXJuIDY0O1xuICAgICAgY2FzZSAxMTpcbiAgICAgICAgLy8gLSBTSEEyMjQgW0ZJUFMxODBdXG4gICAgICAgIHJldHVybiAyODtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoYXNoIGFsZ29yaXRobS4nKTtcbiAgICB9XG4gIH1cblxufVxuIiwiLyoqXG4gKiBBIGZhc3QgTUQ1IEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb25cbiAqIENvcHlyaWdodCAoYykgMjAxMiBKb3NlcGggTXllcnNcbiAqIGh0dHA6Ly93d3cubXllcnNkYWlseS5vcmcvam9zZXBoL2phdmFzY3JpcHQvbWQ1LXRleHQuaHRtbFxuICpcbiAqIFBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZCBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmVcbiAqIGFuZCBpdHMgZG9jdW1lbnRhdGlvbiBmb3IgYW55IHB1cnBvc2VzIGFuZCB3aXRob3V0XG4gKiBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQgcHJvdmlkZWQgdGhhdCB0aGlzIGNvcHlyaWdodCBub3RpY2VcbiAqIGFwcGVhcnMgaW4gYWxsIGNvcGllcy5cbiAqXG4gKiBPZiBjb3Vyc2UsIHRoaXMgc29mdCBpcyBwcm92aWRlZCBcImFzIGlzXCIgd2l0aG91dCBleHByZXNzIG9yIGltcGxpZWRcbiAqIHdhcnJhbnR5IG9mIGFueSBraW5kLlxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbC91dGlsLmpzJyk7XG5cbmZ1bmN0aW9uIE1ENShlbnRyZWUpIHtcbiAgdmFyIGhleCA9IG1kNShlbnRyZWUpO1xuICB2YXIgYmluID0gdXRpbC5oZXgyYmluKGhleCk7XG4gIHJldHVybiBiaW47XG59XG5cbmZ1bmN0aW9uIG1kNWN5Y2xlKHgsIGspIHtcbiAgdmFyIGEgPSB4WzBdLFxuICAgIGIgPSB4WzFdLFxuICAgIGMgPSB4WzJdLFxuICAgIGQgPSB4WzNdO1xuXG4gIGEgPSBmZihhLCBiLCBjLCBkLCBrWzBdLCA3LCAtNjgwODc2OTM2KTtcbiAgZCA9IGZmKGQsIGEsIGIsIGMsIGtbMV0sIDEyLCAtMzg5NTY0NTg2KTtcbiAgYyA9IGZmKGMsIGQsIGEsIGIsIGtbMl0sIDE3LCA2MDYxMDU4MTkpO1xuICBiID0gZmYoYiwgYywgZCwgYSwga1szXSwgMjIsIC0xMDQ0NTI1MzMwKTtcbiAgYSA9IGZmKGEsIGIsIGMsIGQsIGtbNF0sIDcsIC0xNzY0MTg4OTcpO1xuICBkID0gZmYoZCwgYSwgYiwgYywga1s1XSwgMTIsIDEyMDAwODA0MjYpO1xuICBjID0gZmYoYywgZCwgYSwgYiwga1s2XSwgMTcsIC0xNDczMjMxMzQxKTtcbiAgYiA9IGZmKGIsIGMsIGQsIGEsIGtbN10sIDIyLCAtNDU3MDU5ODMpO1xuICBhID0gZmYoYSwgYiwgYywgZCwga1s4XSwgNywgMTc3MDAzNTQxNik7XG4gIGQgPSBmZihkLCBhLCBiLCBjLCBrWzldLCAxMiwgLTE5NTg0MTQ0MTcpO1xuICBjID0gZmYoYywgZCwgYSwgYiwga1sxMF0sIDE3LCAtNDIwNjMpO1xuICBiID0gZmYoYiwgYywgZCwgYSwga1sxMV0sIDIyLCAtMTk5MDQwNDE2Mik7XG4gIGEgPSBmZihhLCBiLCBjLCBkLCBrWzEyXSwgNywgMTgwNDYwMzY4Mik7XG4gIGQgPSBmZihkLCBhLCBiLCBjLCBrWzEzXSwgMTIsIC00MDM0MTEwMSk7XG4gIGMgPSBmZihjLCBkLCBhLCBiLCBrWzE0XSwgMTcsIC0xNTAyMDAyMjkwKTtcbiAgYiA9IGZmKGIsIGMsIGQsIGEsIGtbMTVdLCAyMiwgMTIzNjUzNTMyOSk7XG5cbiAgYSA9IGdnKGEsIGIsIGMsIGQsIGtbMV0sIDUsIC0xNjU3OTY1MTApO1xuICBkID0gZ2coZCwgYSwgYiwgYywga1s2XSwgOSwgLTEwNjk1MDE2MzIpO1xuICBjID0gZ2coYywgZCwgYSwgYiwga1sxMV0sIDE0LCA2NDM3MTc3MTMpO1xuICBiID0gZ2coYiwgYywgZCwgYSwga1swXSwgMjAsIC0zNzM4OTczMDIpO1xuICBhID0gZ2coYSwgYiwgYywgZCwga1s1XSwgNSwgLTcwMTU1ODY5MSk7XG4gIGQgPSBnZyhkLCBhLCBiLCBjLCBrWzEwXSwgOSwgMzgwMTYwODMpO1xuICBjID0gZ2coYywgZCwgYSwgYiwga1sxNV0sIDE0LCAtNjYwNDc4MzM1KTtcbiAgYiA9IGdnKGIsIGMsIGQsIGEsIGtbNF0sIDIwLCAtNDA1NTM3ODQ4KTtcbiAgYSA9IGdnKGEsIGIsIGMsIGQsIGtbOV0sIDUsIDU2ODQ0NjQzOCk7XG4gIGQgPSBnZyhkLCBhLCBiLCBjLCBrWzE0XSwgOSwgLTEwMTk4MDM2OTApO1xuICBjID0gZ2coYywgZCwgYSwgYiwga1szXSwgMTQsIC0xODczNjM5NjEpO1xuICBiID0gZ2coYiwgYywgZCwgYSwga1s4XSwgMjAsIDExNjM1MzE1MDEpO1xuICBhID0gZ2coYSwgYiwgYywgZCwga1sxM10sIDUsIC0xNDQ0NjgxNDY3KTtcbiAgZCA9IGdnKGQsIGEsIGIsIGMsIGtbMl0sIDksIC01MTQwMzc4NCk7XG4gIGMgPSBnZyhjLCBkLCBhLCBiLCBrWzddLCAxNCwgMTczNTMyODQ3Myk7XG4gIGIgPSBnZyhiLCBjLCBkLCBhLCBrWzEyXSwgMjAsIC0xOTI2NjA3NzM0KTtcblxuICBhID0gaGgoYSwgYiwgYywgZCwga1s1XSwgNCwgLTM3ODU1OCk7XG4gIGQgPSBoaChkLCBhLCBiLCBjLCBrWzhdLCAxMSwgLTIwMjI1NzQ0NjMpO1xuICBjID0gaGgoYywgZCwgYSwgYiwga1sxMV0sIDE2LCAxODM5MDMwNTYyKTtcbiAgYiA9IGhoKGIsIGMsIGQsIGEsIGtbMTRdLCAyMywgLTM1MzA5NTU2KTtcbiAgYSA9IGhoKGEsIGIsIGMsIGQsIGtbMV0sIDQsIC0xNTMwOTkyMDYwKTtcbiAgZCA9IGhoKGQsIGEsIGIsIGMsIGtbNF0sIDExLCAxMjcyODkzMzUzKTtcbiAgYyA9IGhoKGMsIGQsIGEsIGIsIGtbN10sIDE2LCAtMTU1NDk3NjMyKTtcbiAgYiA9IGhoKGIsIGMsIGQsIGEsIGtbMTBdLCAyMywgLTEwOTQ3MzA2NDApO1xuICBhID0gaGgoYSwgYiwgYywgZCwga1sxM10sIDQsIDY4MTI3OTE3NCk7XG4gIGQgPSBoaChkLCBhLCBiLCBjLCBrWzBdLCAxMSwgLTM1ODUzNzIyMik7XG4gIGMgPSBoaChjLCBkLCBhLCBiLCBrWzNdLCAxNiwgLTcyMjUyMTk3OSk7XG4gIGIgPSBoaChiLCBjLCBkLCBhLCBrWzZdLCAyMywgNzYwMjkxODkpO1xuICBhID0gaGgoYSwgYiwgYywgZCwga1s5XSwgNCwgLTY0MDM2NDQ4Nyk7XG4gIGQgPSBoaChkLCBhLCBiLCBjLCBrWzEyXSwgMTEsIC00MjE4MTU4MzUpO1xuICBjID0gaGgoYywgZCwgYSwgYiwga1sxNV0sIDE2LCA1MzA3NDI1MjApO1xuICBiID0gaGgoYiwgYywgZCwgYSwga1syXSwgMjMsIC05OTUzMzg2NTEpO1xuXG4gIGEgPSBpaShhLCBiLCBjLCBkLCBrWzBdLCA2LCAtMTk4NjMwODQ0KTtcbiAgZCA9IGlpKGQsIGEsIGIsIGMsIGtbN10sIDEwLCAxMTI2ODkxNDE1KTtcbiAgYyA9IGlpKGMsIGQsIGEsIGIsIGtbMTRdLCAxNSwgLTE0MTYzNTQ5MDUpO1xuICBiID0gaWkoYiwgYywgZCwgYSwga1s1XSwgMjEsIC01NzQzNDA1NSk7XG4gIGEgPSBpaShhLCBiLCBjLCBkLCBrWzEyXSwgNiwgMTcwMDQ4NTU3MSk7XG4gIGQgPSBpaShkLCBhLCBiLCBjLCBrWzNdLCAxMCwgLTE4OTQ5ODY2MDYpO1xuICBjID0gaWkoYywgZCwgYSwgYiwga1sxMF0sIDE1LCAtMTA1MTUyMyk7XG4gIGIgPSBpaShiLCBjLCBkLCBhLCBrWzFdLCAyMSwgLTIwNTQ5MjI3OTkpO1xuICBhID0gaWkoYSwgYiwgYywgZCwga1s4XSwgNiwgMTg3MzMxMzM1OSk7XG4gIGQgPSBpaShkLCBhLCBiLCBjLCBrWzE1XSwgMTAsIC0zMDYxMTc0NCk7XG4gIGMgPSBpaShjLCBkLCBhLCBiLCBrWzZdLCAxNSwgLTE1NjAxOTgzODApO1xuICBiID0gaWkoYiwgYywgZCwgYSwga1sxM10sIDIxLCAxMzA5MTUxNjQ5KTtcbiAgYSA9IGlpKGEsIGIsIGMsIGQsIGtbNF0sIDYsIC0xNDU1MjMwNzApO1xuICBkID0gaWkoZCwgYSwgYiwgYywga1sxMV0sIDEwLCAtMTEyMDIxMDM3OSk7XG4gIGMgPSBpaShjLCBkLCBhLCBiLCBrWzJdLCAxNSwgNzE4Nzg3MjU5KTtcbiAgYiA9IGlpKGIsIGMsIGQsIGEsIGtbOV0sIDIxLCAtMzQzNDg1NTUxKTtcblxuICB4WzBdID0gYWRkMzIoYSwgeFswXSk7XG4gIHhbMV0gPSBhZGQzMihiLCB4WzFdKTtcbiAgeFsyXSA9IGFkZDMyKGMsIHhbMl0pO1xuICB4WzNdID0gYWRkMzIoZCwgeFszXSk7XG5cbn1cblxuZnVuY3Rpb24gY21uKHEsIGEsIGIsIHgsIHMsIHQpIHtcbiAgYSA9IGFkZDMyKGFkZDMyKGEsIHEpLCBhZGQzMih4LCB0KSk7XG4gIHJldHVybiBhZGQzMigoYSA8PCBzKSB8IChhID4+PiAoMzIgLSBzKSksIGIpO1xufVxuXG5mdW5jdGlvbiBmZihhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBjbW4oKGIgJiBjKSB8ICgofmIpICYgZCksIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBnZyhhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBjbW4oKGIgJiBkKSB8IChjICYgKH5kKSksIGEsIGIsIHgsIHMsIHQpO1xufVxuXG5mdW5jdGlvbiBoaChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG4gIHJldHVybiBjbW4oYiBeIGMgXiBkLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuZnVuY3Rpb24gaWkoYSwgYiwgYywgZCwgeCwgcywgdCkge1xuICByZXR1cm4gY21uKGMgXiAoYiB8ICh+ZCkpLCBhLCBiLCB4LCBzLCB0KTtcbn1cblxuZnVuY3Rpb24gbWQ1MShzKSB7XG4gIHR4dCA9ICcnO1xuICB2YXIgbiA9IHMubGVuZ3RoLFxuICAgIHN0YXRlID0gWzE3MzI1ODQxOTMsIC0yNzE3MzM4NzksIC0xNzMyNTg0MTk0LCAyNzE3MzM4NzhdLFxuICAgIGk7XG4gIGZvciAoaSA9IDY0OyBpIDw9IHMubGVuZ3RoOyBpICs9IDY0KSB7XG4gICAgbWQ1Y3ljbGUoc3RhdGUsIG1kNWJsayhzLnN1YnN0cmluZyhpIC0gNjQsIGkpKSk7XG4gIH1cbiAgcyA9IHMuc3Vic3RyaW5nKGkgLSA2NCk7XG4gIHZhciB0YWlsID0gWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDBdO1xuICBmb3IgKGkgPSAwOyBpIDwgcy5sZW5ndGg7IGkrKylcbiAgICB0YWlsW2kgPj4gMl0gfD0gcy5jaGFyQ29kZUF0KGkpIDw8ICgoaSAlIDQpIDw8IDMpO1xuICB0YWlsW2kgPj4gMl0gfD0gMHg4MCA8PCAoKGkgJSA0KSA8PCAzKTtcbiAgaWYgKGkgPiA1NSkge1xuICAgIG1kNWN5Y2xlKHN0YXRlLCB0YWlsKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTY7IGkrKykgdGFpbFtpXSA9IDA7XG4gIH1cbiAgdGFpbFsxNF0gPSBuICogODtcbiAgbWQ1Y3ljbGUoc3RhdGUsIHRhaWwpO1xuICByZXR1cm4gc3RhdGU7XG59XG5cbi8qIHRoZXJlIG5lZWRzIHRvIGJlIHN1cHBvcnQgZm9yIFVuaWNvZGUgaGVyZSxcbiAqIHVubGVzcyB3ZSBwcmV0ZW5kIHRoYXQgd2UgY2FuIHJlZGVmaW5lIHRoZSBNRC01XG4gKiBhbGdvcml0aG0gZm9yIG11bHRpLWJ5dGUgY2hhcmFjdGVycyAocGVyaGFwc1xuICogYnkgYWRkaW5nIGV2ZXJ5IGZvdXIgMTYtYml0IGNoYXJhY3RlcnMgYW5kXG4gKiBzaG9ydGVuaW5nIHRoZSBzdW0gdG8gMzIgYml0cykuIE90aGVyd2lzZVxuICogSSBzdWdnZXN0IHBlcmZvcm1pbmcgTUQtNSBhcyBpZiBldmVyeSBjaGFyYWN0ZXJcbiAqIHdhcyB0d28gYnl0ZXMtLWUuZy4sIDAwNDAgMDAyNSA9IEAlLS1idXQgdGhlblxuICogaG93IHdpbGwgYW4gb3JkaW5hcnkgTUQtNSBzdW0gYmUgbWF0Y2hlZD9cbiAqIFRoZXJlIGlzIG5vIHdheSB0byBzdGFuZGFyZGl6ZSB0ZXh0IHRvIHNvbWV0aGluZ1xuICogbGlrZSBVVEYtOCBiZWZvcmUgdHJhbnNmb3JtYXRpb247IHNwZWVkIGNvc3QgaXNcbiAqIHV0dGVybHkgcHJvaGliaXRpdmUuIFRoZSBKYXZhU2NyaXB0IHN0YW5kYXJkXG4gKiBpdHNlbGYgbmVlZHMgdG8gbG9vayBhdCB0aGlzOiBpdCBzaG91bGQgc3RhcnRcbiAqIHByb3ZpZGluZyBhY2Nlc3MgdG8gc3RyaW5ncyBhcyBwcmVmb3JtZWQgVVRGLThcbiAqIDgtYml0IHVuc2lnbmVkIHZhbHVlIGFycmF5cy5cbiAqL1xuZnVuY3Rpb24gbWQ1YmxrKHMpIHsgLyogSSBmaWd1cmVkIGdsb2JhbCB3YXMgZmFzdGVyLiAgICovXG4gIHZhciBtZDVibGtzID0gW10sXG4gICAgaTsgLyogQW5keSBLaW5nIHNhaWQgZG8gaXQgdGhpcyB3YXkuICovXG4gIGZvciAoaSA9IDA7IGkgPCA2NDsgaSArPSA0KSB7XG4gICAgbWQ1Ymxrc1tpID4+IDJdID0gcy5jaGFyQ29kZUF0KGkpICsgKHMuY2hhckNvZGVBdChpICsgMSkgPDwgOCkgKyAocy5jaGFyQ29kZUF0KGkgKyAyKSA8PCAxNikgKyAocy5jaGFyQ29kZUF0KGkgKyAzKSA8PFxuICAgICAgMjQpO1xuICB9XG4gIHJldHVybiBtZDVibGtzO1xufVxuXG52YXIgaGV4X2NociA9ICcwMTIzNDU2Nzg5YWJjZGVmJy5zcGxpdCgnJyk7XG5cbmZ1bmN0aW9uIHJoZXgobikge1xuICB2YXIgcyA9ICcnLFxuICAgIGogPSAwO1xuICBmb3IgKDsgaiA8IDQ7IGorKylcbiAgICBzICs9IGhleF9jaHJbKG4gPj4gKGogKiA4ICsgNCkpICYgMHgwRl0gKyBoZXhfY2hyWyhuID4+IChqICogOCkpICYgMHgwRl07XG4gIHJldHVybiBzO1xufVxuXG5mdW5jdGlvbiBoZXgoeCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHgubGVuZ3RoOyBpKyspXG4gICAgeFtpXSA9IHJoZXgoeFtpXSk7XG4gIHJldHVybiB4LmpvaW4oJycpO1xufVxuXG5mdW5jdGlvbiBtZDUocykge1xuICByZXR1cm4gaGV4KG1kNTEocykpO1xufVxuXG4vKiB0aGlzIGZ1bmN0aW9uIGlzIG11Y2ggZmFzdGVyLFxuc28gaWYgcG9zc2libGUgd2UgdXNlIGl0LiBTb21lIElFc1xuYXJlIHRoZSBvbmx5IG9uZXMgSSBrbm93IG9mIHRoYXRcbm5lZWQgdGhlIGlkaW90aWMgc2Vjb25kIGZ1bmN0aW9uLFxuZ2VuZXJhdGVkIGJ5IGFuIGlmIGNsYXVzZS4gICovXG5cbmZ1bmN0aW9uIGFkZDMyKGEsIGIpIHtcbiAgcmV0dXJuIChhICsgYikgJiAweEZGRkZGRkZGO1xufVxuXG5pZiAobWQ1KCdoZWxsbycpICE9ICc1ZDQxNDAyYWJjNGIyYTc2Yjk3MTlkOTExMDE3YzU5MicpIHtcbiAgZnVuY3Rpb24gYWRkMzIoeCwgeSkge1xuICAgIHZhciBsc3cgPSAoeCAmIDB4RkZGRikgKyAoeSAmIDB4RkZGRiksXG4gICAgICBtc3cgPSAoeCA+PiAxNikgKyAoeSA+PiAxNikgKyAobHN3ID4+IDE2KTtcbiAgICByZXR1cm4gKG1zdyA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IE1ENVxuIiwiLypcbiAqIENyeXB0b01YIFRvb2xzXG4gKiBDb3B5cmlnaHQgKEMpIDIwMDQgLSAyMDA2IERlcmVrIEJ1aXRlbmh1aXNcbiAqXG4gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZVxuICogYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uIDJcbiAqIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGVcbiAqIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2VcbiAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtOyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4gKiBGb3VuZGF0aW9uLCBJbmMuLCA1OSBUZW1wbGUgUGxhY2UgLSBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcsIFVTQS5cbiAqL1xuXG4vKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkhcbiAqL1xuXG52YXIgUk1Ec2l6ZSA9IDE2MDtcbnZhciBYID0gbmV3IEFycmF5KCk7XG5cbmZ1bmN0aW9uIFJPTCh4LCBuKSB7XG4gIHJldHVybiBuZXcgTnVtYmVyKCh4IDw8IG4pIHwgKHggPj4+ICgzMiAtIG4pKSk7XG59XG5cbmZ1bmN0aW9uIEYoeCwgeSwgeikge1xuICByZXR1cm4gbmV3IE51bWJlcih4IF4geSBeIHopO1xufVxuXG5mdW5jdGlvbiBHKHgsIHksIHopIHtcbiAgcmV0dXJuIG5ldyBOdW1iZXIoKHggJiB5KSB8ICh+eCAmIHopKTtcbn1cblxuZnVuY3Rpb24gSCh4LCB5LCB6KSB7XG4gIHJldHVybiBuZXcgTnVtYmVyKCh4IHwgfnkpIF4geik7XG59XG5cbmZ1bmN0aW9uIEkoeCwgeSwgeikge1xuICByZXR1cm4gbmV3IE51bWJlcigoeCAmIHopIHwgKHkgJiB+eikpO1xufVxuXG5mdW5jdGlvbiBKKHgsIHksIHopIHtcbiAgcmV0dXJuIG5ldyBOdW1iZXIoeCBeICh5IHwgfnopKTtcbn1cblxuZnVuY3Rpb24gbWl4T25lUm91bmQoYSwgYiwgYywgZCwgZSwgeCwgcywgcm91bmROdW1iZXIpIHtcbiAgc3dpdGNoIChyb3VuZE51bWJlcikge1xuICAgIGNhc2UgMDpcbiAgICAgIGEgKz0gRihiLCBjLCBkKSArIHggKyAweDAwMDAwMDAwO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAxOlxuICAgICAgYSArPSBHKGIsIGMsIGQpICsgeCArIDB4NWE4Mjc5OTk7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDI6XG4gICAgICBhICs9IEgoYiwgYywgZCkgKyB4ICsgMHg2ZWQ5ZWJhMTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMzpcbiAgICAgIGEgKz0gSShiLCBjLCBkKSArIHggKyAweDhmMWJiY2RjO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA0OlxuICAgICAgYSArPSBKKGIsIGMsIGQpICsgeCArIDB4YTk1M2ZkNGU7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDU6XG4gICAgICBhICs9IEooYiwgYywgZCkgKyB4ICsgMHg1MGEyOGJlNjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgNjpcbiAgICAgIGEgKz0gSShiLCBjLCBkKSArIHggKyAweDVjNGRkMTI0O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSA3OlxuICAgICAgYSArPSBIKGIsIGMsIGQpICsgeCArIDB4NmQ3MDNlZjM7XG4gICAgICBicmVhaztcbiAgICBjYXNlIDg6XG4gICAgICBhICs9IEcoYiwgYywgZCkgKyB4ICsgMHg3YTZkNzZlOTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgOTpcbiAgICAgIGEgKz0gRihiLCBjLCBkKSArIHggKyAweDAwMDAwMDAwO1xuICAgICAgYnJlYWs7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgZG9jdW1lbnQud3JpdGUoXCJCb2d1cyByb3VuZCBudW1iZXJcIik7XG4gICAgICBicmVhaztcbiAgfVxuXG4gIGEgPSBST0woYSwgcykgKyBlO1xuICBjID0gUk9MKGMsIDEwKTtcblxuICBhICY9IDB4ZmZmZmZmZmY7XG4gIGIgJj0gMHhmZmZmZmZmZjtcbiAgYyAmPSAweGZmZmZmZmZmO1xuICBkICY9IDB4ZmZmZmZmZmY7XG4gIGUgJj0gMHhmZmZmZmZmZjtcblxuICB2YXIgcmV0QmxvY2sgPSBuZXcgQXJyYXkoKTtcbiAgcmV0QmxvY2tbMF0gPSBhO1xuICByZXRCbG9ja1sxXSA9IGI7XG4gIHJldEJsb2NrWzJdID0gYztcbiAgcmV0QmxvY2tbM10gPSBkO1xuICByZXRCbG9ja1s0XSA9IGU7XG4gIHJldEJsb2NrWzVdID0geDtcbiAgcmV0QmxvY2tbNl0gPSBzO1xuXG4gIHJldHVybiByZXRCbG9jaztcbn1cblxuZnVuY3Rpb24gTURpbml0KE1EYnVmKSB7XG4gIE1EYnVmWzBdID0gMHg2NzQ1MjMwMTtcbiAgTURidWZbMV0gPSAweGVmY2RhYjg5O1xuICBNRGJ1ZlsyXSA9IDB4OThiYWRjZmU7XG4gIE1EYnVmWzNdID0gMHgxMDMyNTQ3NjtcbiAgTURidWZbNF0gPSAweGMzZDJlMWYwO1xufVxuXG52YXIgUk9McyA9IFtcbiAgWzExLCAxNCwgMTUsIDEyLCA1LCA4LCA3LCA5LCAxMSwgMTMsIDE0LCAxNSwgNiwgNywgOSwgOF0sXG4gIFs3LCA2LCA4LCAxMywgMTEsIDksIDcsIDE1LCA3LCAxMiwgMTUsIDksIDExLCA3LCAxMywgMTJdLFxuICBbMTEsIDEzLCA2LCA3LCAxNCwgOSwgMTMsIDE1LCAxNCwgOCwgMTMsIDYsIDUsIDEyLCA3LCA1XSxcbiAgWzExLCAxMiwgMTQsIDE1LCAxNCwgMTUsIDksIDgsIDksIDE0LCA1LCA2LCA4LCA2LCA1LCAxMl0sXG4gIFs5LCAxNSwgNSwgMTEsIDYsIDgsIDEzLCAxMiwgNSwgMTIsIDEzLCAxNCwgMTEsIDgsIDUsIDZdLFxuICBbOCwgOSwgOSwgMTEsIDEzLCAxNSwgMTUsIDUsIDcsIDcsIDgsIDExLCAxNCwgMTQsIDEyLCA2XSxcbiAgWzksIDEzLCAxNSwgNywgMTIsIDgsIDksIDExLCA3LCA3LCAxMiwgNywgNiwgMTUsIDEzLCAxMV0sXG4gIFs5LCA3LCAxNSwgMTEsIDgsIDYsIDYsIDE0LCAxMiwgMTMsIDUsIDE0LCAxMywgMTMsIDcsIDVdLFxuICBbMTUsIDUsIDgsIDExLCAxNCwgMTQsIDYsIDE0LCA2LCA5LCAxMiwgOSwgMTIsIDUsIDE1LCA4XSxcbiAgWzgsIDUsIDEyLCA5LCAxMiwgNSwgMTQsIDYsIDgsIDEzLCA2LCA1LCAxNSwgMTMsIDExLCAxMV1cbl07XG5cbnZhciBpbmRleGVzID0gW1xuICBbMCwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExLCAxMiwgMTMsIDE0LCAxNV0sXG4gIFs3LCA0LCAxMywgMSwgMTAsIDYsIDE1LCAzLCAxMiwgMCwgOSwgNSwgMiwgMTQsIDExLCA4XSxcbiAgWzMsIDEwLCAxNCwgNCwgOSwgMTUsIDgsIDEsIDIsIDcsIDAsIDYsIDEzLCAxMSwgNSwgMTJdLFxuICBbMSwgOSwgMTEsIDEwLCAwLCA4LCAxMiwgNCwgMTMsIDMsIDcsIDE1LCAxNCwgNSwgNiwgMl0sXG4gIFs0LCAwLCA1LCA5LCA3LCAxMiwgMiwgMTAsIDE0LCAxLCAzLCA4LCAxMSwgNiwgMTUsIDEzXSxcbiAgWzUsIDE0LCA3LCAwLCA5LCAyLCAxMSwgNCwgMTMsIDYsIDE1LCA4LCAxLCAxMCwgMywgMTJdLFxuICBbNiwgMTEsIDMsIDcsIDAsIDEzLCA1LCAxMCwgMTQsIDE1LCA4LCAxMiwgNCwgOSwgMSwgMl0sXG4gIFsxNSwgNSwgMSwgMywgNywgMTQsIDYsIDksIDExLCA4LCAxMiwgMiwgMTAsIDAsIDQsIDEzXSxcbiAgWzgsIDYsIDQsIDEsIDMsIDExLCAxNSwgMCwgNSwgMTIsIDIsIDEzLCA5LCA3LCAxMCwgMTRdLFxuICBbMTIsIDE1LCAxMCwgNCwgMSwgNSwgOCwgNywgNiwgMiwgMTMsIDE0LCAwLCAzLCA5LCAxMV1cbl07XG5cbmZ1bmN0aW9uIGNvbXByZXNzKE1EYnVmLCBYKSB7XG4gIGJsb2NrQSA9IG5ldyBBcnJheSgpO1xuICBibG9ja0IgPSBuZXcgQXJyYXkoKTtcblxuICB2YXIgcmV0QmxvY2s7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICBibG9ja0FbaV0gPSBuZXcgTnVtYmVyKE1EYnVmW2ldKTtcbiAgICBibG9ja0JbaV0gPSBuZXcgTnVtYmVyKE1EYnVmW2ldKTtcbiAgfVxuXG4gIHZhciBzdGVwID0gMDtcbiAgZm9yICh2YXIgaiA9IDA7IGogPCA1OyBqKyspIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgIHJldEJsb2NrID0gbWl4T25lUm91bmQoXG4gICAgICAgIGJsb2NrQVsoc3RlcCArIDApICUgNV0sXG4gICAgICAgIGJsb2NrQVsoc3RlcCArIDEpICUgNV0sXG4gICAgICAgIGJsb2NrQVsoc3RlcCArIDIpICUgNV0sXG4gICAgICAgIGJsb2NrQVsoc3RlcCArIDMpICUgNV0sXG4gICAgICAgIGJsb2NrQVsoc3RlcCArIDQpICUgNV0sXG4gICAgICAgIFhbaW5kZXhlc1tqXVtpXV0sXG4gICAgICAgIFJPTHNbal1baV0sXG4gICAgICAgIGopO1xuXG4gICAgICBibG9ja0FbKHN0ZXAgKyAwKSAlIDVdID0gcmV0QmxvY2tbMF07XG4gICAgICBibG9ja0FbKHN0ZXAgKyAxKSAlIDVdID0gcmV0QmxvY2tbMV07XG4gICAgICBibG9ja0FbKHN0ZXAgKyAyKSAlIDVdID0gcmV0QmxvY2tbMl07XG4gICAgICBibG9ja0FbKHN0ZXAgKyAzKSAlIDVdID0gcmV0QmxvY2tbM107XG4gICAgICBibG9ja0FbKHN0ZXAgKyA0KSAlIDVdID0gcmV0QmxvY2tbNF07XG5cbiAgICAgIHN0ZXAgKz0gNDtcbiAgICB9XG4gIH1cblxuICBzdGVwID0gMDtcbiAgZm9yICh2YXIgaiA9IDU7IGogPCAxMDsgaisrKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICByZXRCbG9jayA9IG1peE9uZVJvdW5kKFxuICAgICAgICBibG9ja0JbKHN0ZXAgKyAwKSAlIDVdLFxuICAgICAgICBibG9ja0JbKHN0ZXAgKyAxKSAlIDVdLFxuICAgICAgICBibG9ja0JbKHN0ZXAgKyAyKSAlIDVdLFxuICAgICAgICBibG9ja0JbKHN0ZXAgKyAzKSAlIDVdLFxuICAgICAgICBibG9ja0JbKHN0ZXAgKyA0KSAlIDVdLFxuICAgICAgICBYW2luZGV4ZXNbal1baV1dLFxuICAgICAgICBST0xzW2pdW2ldLFxuICAgICAgICBqKTtcblxuICAgICAgYmxvY2tCWyhzdGVwICsgMCkgJSA1XSA9IHJldEJsb2NrWzBdO1xuICAgICAgYmxvY2tCWyhzdGVwICsgMSkgJSA1XSA9IHJldEJsb2NrWzFdO1xuICAgICAgYmxvY2tCWyhzdGVwICsgMikgJSA1XSA9IHJldEJsb2NrWzJdO1xuICAgICAgYmxvY2tCWyhzdGVwICsgMykgJSA1XSA9IHJldEJsb2NrWzNdO1xuICAgICAgYmxvY2tCWyhzdGVwICsgNCkgJSA1XSA9IHJldEJsb2NrWzRdO1xuXG4gICAgICBzdGVwICs9IDQ7XG4gICAgfVxuICB9XG5cbiAgYmxvY2tCWzNdICs9IGJsb2NrQVsyXSArIE1EYnVmWzFdO1xuICBNRGJ1ZlsxXSA9IE1EYnVmWzJdICsgYmxvY2tBWzNdICsgYmxvY2tCWzRdO1xuICBNRGJ1ZlsyXSA9IE1EYnVmWzNdICsgYmxvY2tBWzRdICsgYmxvY2tCWzBdO1xuICBNRGJ1ZlszXSA9IE1EYnVmWzRdICsgYmxvY2tBWzBdICsgYmxvY2tCWzFdO1xuICBNRGJ1Zls0XSA9IE1EYnVmWzBdICsgYmxvY2tBWzFdICsgYmxvY2tCWzJdO1xuICBNRGJ1ZlswXSA9IGJsb2NrQlszXTtcbn1cblxuZnVuY3Rpb24gemVyb1goWCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICBYW2ldID0gMDtcbiAgfVxufVxuXG5mdW5jdGlvbiBNRGZpbmlzaChNRGJ1Ziwgc3RycHRyLCBsc3dsZW4sIG1zd2xlbikge1xuICB2YXIgWCA9IG5ldyBBcnJheSgxNik7XG4gIHplcm9YKFgpO1xuXG4gIHZhciBqID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAobHN3bGVuICYgNjMpOyBpKyspIHtcbiAgICBYW2kgPj4+IDJdIF49IChzdHJwdHIuY2hhckNvZGVBdChqKyspICYgMjU1KSA8PCAoOCAqIChpICYgMykpO1xuICB9XG5cbiAgWFsobHN3bGVuID4+PiAyKSAmIDE1XSBePSAxIDw8ICg4ICogKGxzd2xlbiAmIDMpICsgNyk7XG5cbiAgaWYgKChsc3dsZW4gJiA2MykgPiA1NSkge1xuICAgIGNvbXByZXNzKE1EYnVmLCBYKTtcbiAgICB2YXIgWCA9IG5ldyBBcnJheSgxNik7XG4gICAgemVyb1goWCk7XG4gIH1cblxuICBYWzE0XSA9IGxzd2xlbiA8PCAzO1xuICBYWzE1XSA9IChsc3dsZW4gPj4+IDI5KSB8IChtc3dsZW4gPDwgMyk7XG5cbiAgY29tcHJlc3MoTURidWYsIFgpO1xufVxuXG5mdW5jdGlvbiBCWVRFU19UT19EV09SRChmb3VyQ2hhcnMpIHtcbiAgdmFyIHRtcCA9IChmb3VyQ2hhcnMuY2hhckNvZGVBdCgzKSAmIDI1NSkgPDwgMjQ7XG4gIHRtcCB8PSAoZm91ckNoYXJzLmNoYXJDb2RlQXQoMikgJiAyNTUpIDw8IDE2O1xuICB0bXAgfD0gKGZvdXJDaGFycy5jaGFyQ29kZUF0KDEpICYgMjU1KSA8PCA4O1xuICB0bXAgfD0gKGZvdXJDaGFycy5jaGFyQ29kZUF0KDApICYgMjU1KTtcblxuICByZXR1cm4gdG1wO1xufVxuXG5mdW5jdGlvbiBSTUQobWVzc2FnZSkge1xuICB2YXIgTURidWYgPSBuZXcgQXJyYXkoUk1Ec2l6ZSAvIDMyKTtcbiAgdmFyIGhhc2hjb2RlID0gbmV3IEFycmF5KFJNRHNpemUgLyA4KTtcbiAgdmFyIGxlbmd0aDtcbiAgdmFyIG5ieXRlcztcblxuICBNRGluaXQoTURidWYpO1xuICBsZW5ndGggPSBtZXNzYWdlLmxlbmd0aDtcblxuICB2YXIgWCA9IG5ldyBBcnJheSgxNik7XG4gIHplcm9YKFgpO1xuXG4gIHZhciBqID0gMDtcbiAgZm9yICh2YXIgbmJ5dGVzID0gbGVuZ3RoOyBuYnl0ZXMgPiA2MzsgbmJ5dGVzIC09IDY0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG4gICAgICBYW2ldID0gQllURVNfVE9fRFdPUkQobWVzc2FnZS5zdWJzdHIoaiwgNCkpO1xuICAgICAgaiArPSA0O1xuICAgIH1cbiAgICBjb21wcmVzcyhNRGJ1ZiwgWCk7XG4gIH1cblxuICBNRGZpbmlzaChNRGJ1ZiwgbWVzc2FnZS5zdWJzdHIoaiksIGxlbmd0aCwgMCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBSTURzaXplIC8gODsgaSArPSA0KSB7XG4gICAgaGFzaGNvZGVbaV0gPSBNRGJ1ZltpID4+PiAyXSAmIDI1NTtcbiAgICBoYXNoY29kZVtpICsgMV0gPSAoTURidWZbaSA+Pj4gMl0gPj4+IDgpICYgMjU1O1xuICAgIGhhc2hjb2RlW2kgKyAyXSA9IChNRGJ1ZltpID4+PiAyXSA+Pj4gMTYpICYgMjU1O1xuICAgIGhhc2hjb2RlW2kgKyAzXSA9IChNRGJ1ZltpID4+PiAyXSA+Pj4gMjQpICYgMjU1O1xuICB9XG5cbiAgcmV0dXJuIGhhc2hjb2RlO1xufVxuXG5cbmZ1bmN0aW9uIFJNRHN0cmluZyhtZXNzYWdlKSB7XG4gIHZhciBoYXNoY29kZSA9IFJNRChtZXNzYWdlKTtcbiAgdmFyIHJldFN0cmluZyA9IFwiXCI7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBSTURzaXplIC8gODsgaSsrKSB7XG4gICAgcmV0U3RyaW5nICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoaGFzaGNvZGVbaV0pO1xuICB9XG5cbiAgcmV0dXJuIHJldFN0cmluZztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBSTURzdHJpbmc7XG4iLCIvKiBBIEphdmFTY3JpcHQgaW1wbGVtZW50YXRpb24gb2YgdGhlIFNIQSBmYW1pbHkgb2YgaGFzaGVzLCBhcyBkZWZpbmVkIGluIEZJUFMgXG4gKiBQVUIgMTgwLTIgYXMgd2VsbCBhcyB0aGUgY29ycmVzcG9uZGluZyBITUFDIGltcGxlbWVudGF0aW9uIGFzIGRlZmluZWQgaW5cbiAqIEZJUFMgUFVCIDE5OGFcbiAqXG4gKiBWZXJzaW9uIDEuMyBDb3B5cmlnaHQgQnJpYW4gVHVyZWsgMjAwOC0yMDEwXG4gKiBEaXN0cmlidXRlZCB1bmRlciB0aGUgQlNEIExpY2Vuc2VcbiAqIFNlZSBodHRwOi8vanNzaGEuc291cmNlZm9yZ2UubmV0LyBmb3IgbW9yZSBpbmZvcm1hdGlvblxuICpcbiAqIFNldmVyYWwgZnVuY3Rpb25zIHRha2VuIGZyb20gUGF1bCBKb2huc29uXG4gKi9cblxuLyogTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIXG4gKiBcbiAqIFRoaXMgY29kZSBoYXMgYmVlbiBzbGlnaHRseSBtb2RpZmllZCBkaXJlY3Qgc3RyaW5nIG91dHB1dDpcbiAqIC0gYmluMmJzdHIgaGFzIGJlZW4gYWRkZWRcbiAqIC0gZm9sbG93aW5nIHdyYXBwZXJzIG9mIHRoaXMgbGlicmFyeSBoYXZlIGJlZW4gYWRkZWQ6XG4gKiAgIC0gc3RyX3NoYTFcbiAqICAgLSBzdHJfc2hhMjU2XG4gKiAgIC0gc3RyX3NoYTIyNFxuICogICAtIHN0cl9zaGEzODRcbiAqICAgLSBzdHJfc2hhNTEyXG4gKi9cblxudmFyIGpzU0hBID0gKGZ1bmN0aW9uKCkge1xuXG4gIC8qXG4gICAqIENvbmZpZ3VyYWJsZSB2YXJpYWJsZXMuIERlZmF1bHRzIHR5cGljYWxseSB3b3JrXG4gICAqL1xuICAvKiBOdW1iZXIgb2YgQml0cyBQZXIgY2hhcmFjdGVyICg4IGZvciBBU0NJSSwgMTYgZm9yIFVuaWNvZGUpICovXG4gIHZhciBjaGFyU2l6ZSA9IDgsXG4gICAgLyogYmFzZS02NCBwYWQgY2hhcmFjdGVyLiBcIj1cIiBmb3Igc3RyaWN0IFJGQyBjb21wbGlhbmNlICovXG4gICAgYjY0cGFkID0gXCJcIixcbiAgICAvKiBoZXggb3V0cHV0IGZvcm1hdC4gMCAtIGxvd2VyY2FzZTsgMSAtIHVwcGVyY2FzZSAqL1xuICAgIGhleENhc2UgPSAwLFxuXG4gICAgLypcbiAgICAgKiBJbnRfNjQgaXMgYSBvYmplY3QgZm9yIDIgMzItYml0IG51bWJlcnMgZW11bGF0aW5nIGEgNjQtYml0IG51bWJlclxuICAgICAqXG4gICAgICogQGNvbnN0cnVjdG9yXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG1zaW50XzMyIFRoZSBtb3N0IHNpZ25pZmljYW50IDMyLWJpdHMgb2YgYSA2NC1iaXQgbnVtYmVyXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGxzaW50XzMyIFRoZSBsZWFzdCBzaWduaWZpY2FudCAzMi1iaXRzIG9mIGEgNjQtYml0IG51bWJlclxuICAgICAqL1xuICAgIEludF82NCA9IGZ1bmN0aW9uKG1zaW50XzMyLCBsc2ludF8zMikge1xuICAgICAgdGhpcy5oaWdoT3JkZXIgPSBtc2ludF8zMjtcbiAgICAgIHRoaXMubG93T3JkZXIgPSBsc2ludF8zMjtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGFuIGFycmF5IG9mIGJpZy1lbmRpYW4gd29yZHNcbiAgICAgKiBJZiBjaGFyU2l6ZSBpcyBBU0NJSSwgY2hhcmFjdGVycyA+MjU1IGhhdmUgdGhlaXIgaGktYnl0ZSBzaWxlbnRseVxuICAgICAqIGlnbm9yZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBiZSBjb252ZXJ0ZWQgdG8gYmluYXJ5IHJlcHJlc2VudGF0aW9uXG4gICAgICogQHJldHVybiBJbnRlZ2VyIGFycmF5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBzdHIyYmluYiA9IGZ1bmN0aW9uKHN0cikge1xuICAgICAgdmFyIGJpbiA9IFtdLFxuICAgICAgICBtYXNrID0gKDEgPDwgY2hhclNpemUpIC0gMSxcbiAgICAgICAgbGVuZ3RoID0gc3RyLmxlbmd0aCAqIGNoYXJTaXplLFxuICAgICAgICBpO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IGNoYXJTaXplKSB7XG4gICAgICAgIGJpbltpID4+IDVdIHw9IChzdHIuY2hhckNvZGVBdChpIC8gY2hhclNpemUpICYgbWFzaykgPDxcbiAgICAgICAgICAoMzIgLSBjaGFyU2l6ZSAtIChpICUgMzIpKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGJpbjtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGEgaGV4IHN0cmluZyB0byBhbiBhcnJheSBvZiBiaWctZW5kaWFuIHdvcmRzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBiZSBjb252ZXJ0ZWQgdG8gYmluYXJ5IHJlcHJlc2VudGF0aW9uXG4gICAgICogQHJldHVybiBJbnRlZ2VyIGFycmF5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBoZXgyYmluYiA9IGZ1bmN0aW9uKHN0cikge1xuICAgICAgdmFyIGJpbiA9IFtdLFxuICAgICAgICBsZW5ndGggPSBzdHIubGVuZ3RoLFxuICAgICAgICBpLCBudW07XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMikge1xuICAgICAgICBudW0gPSBwYXJzZUludChzdHIuc3Vic3RyKGksIDIpLCAxNik7XG4gICAgICAgIGlmICghaXNOYU4obnVtKSkge1xuICAgICAgICAgIGJpbltpID4+IDNdIHw9IG51bSA8PCAoMjQgLSAoNCAqIChpICUgOCkpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gXCJJTlZBTElEIEhFWCBTVFJJTkdcIjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gYmluO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYW4gYXJyYXkgb2YgYmlnLWVuZGlhbiB3b3JkcyB0byBhIGhleCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGJpbmFycmF5IEFycmF5IG9mIGludGVnZXJzIHRvIGJlIGNvbnZlcnRlZCB0byBoZXhpZGVjaW1hbFxuICAgICAqXHQgcmVwcmVzZW50YXRpb25cbiAgICAgKiBAcmV0dXJuIEhleGlkZWNpbWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYXJhbWV0ZXIgaW4gU3RyaW5nIGZvcm1cbiAgICAgKi9cbiAgICBiaW5iMmhleCA9IGZ1bmN0aW9uKGJpbmFycmF5KSB7XG4gICAgICB2YXIgaGV4X3RhYiA9IChoZXhDYXNlKSA/IFwiMDEyMzQ1Njc4OUFCQ0RFRlwiIDogXCIwMTIzNDU2Nzg5YWJjZGVmXCIsXG4gICAgICAgIHN0ciA9IFwiXCIsXG4gICAgICAgIGxlbmd0aCA9IGJpbmFycmF5Lmxlbmd0aCAqIDQsXG4gICAgICAgIGksIHNyY0J5dGU7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICBzcmNCeXRlID0gYmluYXJyYXlbaSA+PiAyXSA+PiAoKDMgLSAoaSAlIDQpKSAqIDgpO1xuICAgICAgICBzdHIgKz0gaGV4X3RhYi5jaGFyQXQoKHNyY0J5dGUgPj4gNCkgJiAweEYpICtcbiAgICAgICAgICBoZXhfdGFiLmNoYXJBdChzcmNCeXRlICYgMHhGKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHN0cjtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGJpZy1lbmRpYW4gd29yZHMgdG8gYSBiYXNlLTY0IHN0cmluZ1xuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBiaW5hcnJheSBBcnJheSBvZiBpbnRlZ2VycyB0byBiZSBjb252ZXJ0ZWQgdG8gYmFzZS02NFxuICAgICAqXHQgcmVwcmVzZW50YXRpb25cbiAgICAgKiBAcmV0dXJuIEJhc2UtNjQgZW5jb2RlZCByZXByZXNlbnRhdGlvbiBvZiB0aGUgcGFyYW1ldGVyIGluIFN0cmluZyBmb3JtXG4gICAgICovXG4gICAgYmluYjJiNjQgPSBmdW5jdGlvbihiaW5hcnJheSkge1xuICAgICAgdmFyIHRhYiA9IFwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elwiICtcbiAgICAgICAgXCIwMTIzNDU2Nzg5Ky9cIixcbiAgICAgICAgc3RyID0gXCJcIixcbiAgICAgICAgbGVuZ3RoID0gYmluYXJyYXkubGVuZ3RoICogNCxcbiAgICAgICAgaSwgaixcbiAgICAgICAgdHJpcGxldDtcblxuICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAzKSB7XG4gICAgICAgIHRyaXBsZXQgPSAoKChiaW5hcnJheVtpID4+IDJdID4+IDggKiAoMyAtIGkgJSA0KSkgJiAweEZGKSA8PCAxNikgfFxuICAgICAgICAgICgoKGJpbmFycmF5W2kgKyAxID4+IDJdID4+IDggKiAoMyAtIChpICsgMSkgJSA0KSkgJiAweEZGKSA8PCA4KSB8XG4gICAgICAgICAgKChiaW5hcnJheVtpICsgMiA+PiAyXSA+PiA4ICogKDMgLSAoaSArIDIpICUgNCkpICYgMHhGRik7XG4gICAgICAgIGZvciAoaiA9IDA7IGogPCA0OyBqICs9IDEpIHtcbiAgICAgICAgICBpZiAoaSAqIDggKyBqICogNiA8PSBiaW5hcnJheS5sZW5ndGggKiAzMikge1xuICAgICAgICAgICAgc3RyICs9IHRhYi5jaGFyQXQoKHRyaXBsZXQgPj4gNiAqICgzIC0gaikpICYgMHgzRik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0ciArPSBiNjRwYWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENvbnZlcnQgYW4gYXJyYXkgb2YgYmlnLWVuZGlhbiB3b3JkcyB0byBhIHN0cmluZ1xuICAgICAqL1xuICAgIGJpbmIyc3RyID0gZnVuY3Rpb24oYmluKSB7XG4gICAgICB2YXIgc3RyID0gXCJcIjtcbiAgICAgIHZhciBtYXNrID0gKDEgPDwgOCkgLSAxO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiaW4ubGVuZ3RoICogMzI7IGkgKz0gOClcbiAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKGJpbltpID4+IDVdID4+PiAoMjQgLSBpICUgMzIpKSAmIG1hc2spO1xuICAgICAgcmV0dXJuIHN0cjtcbiAgICB9LFxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiBjaXJjdWxhciByb3RhdGUgbGVmdFxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcbiAgICAgKiBAcmV0dXJuIFRoZSB4IHNoaWZ0ZWQgY2lyY3VsYXJseSBieSBuIGJpdHNcbiAgICAgKi9cbiAgICByb3RsXzMyID0gZnVuY3Rpb24oeCwgbikge1xuICAgICAgcmV0dXJuICh4IDw8IG4pIHwgKHggPj4+ICgzMiAtIG4pKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIGNpcmN1bGFyIHJvdGF0ZSByaWdodFxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcbiAgICAgKiBAcmV0dXJuIFRoZSB4IHNoaWZ0ZWQgY2lyY3VsYXJseSBieSBuIGJpdHNcbiAgICAgKi9cbiAgICByb3RyXzMyID0gZnVuY3Rpb24oeCwgbikge1xuICAgICAgcmV0dXJuICh4ID4+PiBuKSB8ICh4IDw8ICgzMiAtIG4pKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgNjQtYml0IGltcGxlbWVudGF0aW9uIG9mIGNpcmN1bGFyIHJvdGF0ZSByaWdodFxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbiBUaGUgbnVtYmVyIG9mIGJpdHMgdG8gc2hpZnRcbiAgICAgKiBAcmV0dXJuIFRoZSB4IHNoaWZ0ZWQgY2lyY3VsYXJseSBieSBuIGJpdHNcbiAgICAgKi9cbiAgICByb3RyXzY0ID0gZnVuY3Rpb24oeCwgbikge1xuICAgICAgaWYgKG4gPD0gMzIpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgICh4LmhpZ2hPcmRlciA+Pj4gbikgfCAoeC5sb3dPcmRlciA8PCAoMzIgLSBuKSksICh4Lmxvd09yZGVyID4+PiBuKSB8ICh4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgICh4Lmxvd09yZGVyID4+PiBuKSB8ICh4LmhpZ2hPcmRlciA8PCAoMzIgLSBuKSksICh4LmhpZ2hPcmRlciA+Pj4gbikgfCAoeC5sb3dPcmRlciA8PCAoMzIgLSBuKSkpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2Ygc2hpZnQgcmlnaHRcbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG4gVGhlIG51bWJlciBvZiBiaXRzIHRvIHNoaWZ0XG4gICAgICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGJ5IG4gYml0c1xuICAgICAqL1xuICAgIHNocl8zMiA9IGZ1bmN0aW9uKHgsIG4pIHtcbiAgICAgIHJldHVybiB4ID4+PiBuO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2Ygc2hpZnQgcmlnaHRcbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG4gVGhlIG51bWJlciBvZiBiaXRzIHRvIHNoaWZ0XG4gICAgICogQHJldHVybiBUaGUgeCBzaGlmdGVkIGJ5IG4gYml0c1xuICAgICAqL1xuICAgIHNocl82NCA9IGZ1bmN0aW9uKHgsIG4pIHtcbiAgICAgIGlmIChuIDw9IDMyKSB7XG4gICAgICAgIHJldHVybiBuZXcgSW50XzY0KFxuICAgICAgICAgIHguaGlnaE9yZGVyID4+PiBuLFxuICAgICAgICAgIHgubG93T3JkZXIgPj4+IG4gfCAoeC5oaWdoT3JkZXIgPDwgKDMyIC0gbikpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBuZXcgSW50XzY0KFxuICAgICAgICAgIDAsXG4gICAgICAgICAgeC5oaWdoT3JkZXIgPDwgKDMyIC0gbikpO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIFBhcml0eSBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgZmlyc3QgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geSBUaGUgc2Vjb25kIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHogVGhlIHRoaXJkIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIHBhcml0eV8zMiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICAgIHJldHVybiB4IF4geSBeIHo7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgQ2ggZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHkgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB6IFRoZSB0aGlyZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBjaF8zMiA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICAgIHJldHVybiAoeCAmIHkpIF4gKH54ICYgeik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgQ2ggZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHggVGhlIGZpcnN0IDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHkgVGhlIHNlY29uZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB6IFRoZSB0aGlyZCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBjaF82NCA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICAgIHJldHVybiBuZXcgSW50XzY0KFxuICAgICAgKHguaGlnaE9yZGVyICYgeS5oaWdoT3JkZXIpIF4gKH54LmhpZ2hPcmRlciAmIHouaGlnaE9yZGVyKSwgKHgubG93T3JkZXIgJiB5Lmxvd09yZGVyKSBeICh+eC5sb3dPcmRlciAmIHoubG93T3JkZXIpKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBNYWogZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHkgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB6IFRoZSB0aGlyZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBtYWpfMzIgPSBmdW5jdGlvbih4LCB5LCB6KSB7XG4gICAgICByZXR1cm4gKHggJiB5KSBeICh4ICYgeikgXiAoeSAmIHopO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIE1haiBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgZmlyc3QgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geSBUaGUgc2Vjb25kIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHBhcmFtIHtJbnRfNjR9IHogVGhlIHRoaXJkIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIG1hal82NCA9IGZ1bmN0aW9uKHgsIHksIHopIHtcbiAgICAgIHJldHVybiBuZXcgSW50XzY0KFxuICAgICAgKHguaGlnaE9yZGVyICYgeS5oaWdoT3JkZXIpIF5cbiAgICAgICAgKHguaGlnaE9yZGVyICYgei5oaWdoT3JkZXIpIF5cbiAgICAgICAgKHkuaGlnaE9yZGVyICYgei5oaWdoT3JkZXIpLCAoeC5sb3dPcmRlciAmIHkubG93T3JkZXIpIF5cbiAgICAgICAgKHgubG93T3JkZXIgJiB6Lmxvd09yZGVyKSBeXG4gICAgICAgICh5Lmxvd09yZGVyICYgei5sb3dPcmRlcikpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIFNpZ21hMCBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgc2lnbWEwXzMyID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHJvdHJfMzIoeCwgMikgXiByb3RyXzMyKHgsIDEzKSBeIHJvdHJfMzIoeCwgMjIpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIFNpZ21hMCBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgc2lnbWEwXzY0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgdmFyIHJvdHIyOCA9IHJvdHJfNjQoeCwgMjgpLFxuICAgICAgICByb3RyMzQgPSByb3RyXzY0KHgsIDM0KSxcbiAgICAgICAgcm90cjM5ID0gcm90cl82NCh4LCAzOSk7XG5cbiAgICAgIHJldHVybiBuZXcgSW50XzY0KFxuICAgICAgICByb3RyMjguaGlnaE9yZGVyIF4gcm90cjM0LmhpZ2hPcmRlciBeIHJvdHIzOS5oaWdoT3JkZXIsXG4gICAgICAgIHJvdHIyOC5sb3dPcmRlciBeIHJvdHIzNC5sb3dPcmRlciBeIHJvdHIzOS5sb3dPcmRlcik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDMyLWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgU2lnbWExIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSAzMi1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBzaWdtYTFfMzIgPSBmdW5jdGlvbih4KSB7XG4gICAgICByZXR1cm4gcm90cl8zMih4LCA2KSBeIHJvdHJfMzIoeCwgMTEpIF4gcm90cl8zMih4LCAyNSk7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgU2lnbWExIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBzaWdtYTFfNjQgPSBmdW5jdGlvbih4KSB7XG4gICAgICB2YXIgcm90cjE0ID0gcm90cl82NCh4LCAxNCksXG4gICAgICAgIHJvdHIxOCA9IHJvdHJfNjQoeCwgMTgpLFxuICAgICAgICByb3RyNDEgPSByb3RyXzY0KHgsIDQxKTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgIHJvdHIxNC5oaWdoT3JkZXIgXiByb3RyMTguaGlnaE9yZGVyIF4gcm90cjQxLmhpZ2hPcmRlcixcbiAgICAgICAgcm90cjE0Lmxvd09yZGVyIF4gcm90cjE4Lmxvd09yZGVyIF4gcm90cjQxLmxvd09yZGVyKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBUaGUgMzItYml0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBOSVNUIHNwZWNpZmllZCBHYW1tYTAgZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IHggVGhlIDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50XG4gICAgICogQHJldHVybiBUaGUgTklTVCBzcGVjaWZpZWQgb3V0cHV0IG9mIHRoZSBmdW5jdGlvblxuICAgICAqL1xuICAgIGdhbW1hMF8zMiA9IGZ1bmN0aW9uKHgpIHtcbiAgICAgIHJldHVybiByb3RyXzMyKHgsIDcpIF4gcm90cl8zMih4LCAxOCkgXiBzaHJfMzIoeCwgMyk7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogVGhlIDY0LWJpdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgTklTVCBzcGVjaWZpZWQgR2FtbWEwIGZ1bmN0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSA2NC1iaXQgaW50ZWdlciBhcmd1bWVudFxuICAgICAqIEByZXR1cm4gVGhlIE5JU1Qgc3BlY2lmaWVkIG91dHB1dCBvZiB0aGUgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBnYW1tYTBfNjQgPSBmdW5jdGlvbih4KSB7XG4gICAgICB2YXIgcm90cjEgPSByb3RyXzY0KHgsIDEpLFxuICAgICAgICByb3RyOCA9IHJvdHJfNjQoeCwgOCksXG4gICAgICAgIHNocjcgPSBzaHJfNjQoeCwgNyk7XG5cbiAgICAgIHJldHVybiBuZXcgSW50XzY0KFxuICAgICAgICByb3RyMS5oaWdoT3JkZXIgXiByb3RyOC5oaWdoT3JkZXIgXiBzaHI3LmhpZ2hPcmRlcixcbiAgICAgICAgcm90cjEubG93T3JkZXIgXiByb3RyOC5sb3dPcmRlciBeIHNocjcubG93T3JkZXIpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSAzMi1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIEdhbW1hMSBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge051bWJlcn0geCBUaGUgMzItYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgZ2FtbWExXzMyID0gZnVuY3Rpb24oeCkge1xuICAgICAgcmV0dXJuIHJvdHJfMzIoeCwgMTcpIF4gcm90cl8zMih4LCAxOSkgXiBzaHJfMzIoeCwgMTApO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIFRoZSA2NC1iaXQgaW1wbGVtZW50YXRpb24gb2YgdGhlIE5JU1Qgc3BlY2lmaWVkIEdhbW1hMSBmdW5jdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0geCBUaGUgNjQtYml0IGludGVnZXIgYXJndW1lbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBOSVNUIHNwZWNpZmllZCBvdXRwdXQgb2YgdGhlIGZ1bmN0aW9uXG4gICAgICovXG4gICAgZ2FtbWExXzY0ID0gZnVuY3Rpb24oeCkge1xuICAgICAgdmFyIHJvdHIxOSA9IHJvdHJfNjQoeCwgMTkpLFxuICAgICAgICByb3RyNjEgPSByb3RyXzY0KHgsIDYxKSxcbiAgICAgICAgc2hyNiA9IHNocl82NCh4LCA2KTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoXG4gICAgICAgIHJvdHIxOS5oaWdoT3JkZXIgXiByb3RyNjEuaGlnaE9yZGVyIF4gc2hyNi5oaWdoT3JkZXIsXG4gICAgICAgIHJvdHIxOS5sb3dPcmRlciBeIHJvdHI2MS5sb3dPcmRlciBeIHNocjYubG93T3JkZXIpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIEFkZCB0d28gMzItYml0IGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjMyLiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnNcbiAgICAgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB4IFRoZSBmaXJzdCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSB5IFRoZSBzZWNvbmQgMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcmV0dXJuIFRoZSBzdW0gb2YgeCArIHlcbiAgICAgKi9cbiAgICBzYWZlQWRkXzMyXzIgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgbHN3ID0gKHggJiAweEZGRkYpICsgKHkgJiAweEZGRkYpLFxuICAgICAgICBtc3cgPSAoeCA+Pj4gMTYpICsgKHkgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcblxuICAgICAgcmV0dXJuICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBBZGQgZm91ciAzMi1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeMzIuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuICAgICAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGEgVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGIgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSB0aGlyZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBkIFRoZSBmb3VydGggMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcmV0dXJuIFRoZSBzdW0gb2YgYSArIGIgKyBjICsgZFxuICAgICAqL1xuICAgIHNhZmVBZGRfMzJfNCA9IGZ1bmN0aW9uKGEsIGIsIGMsIGQpIHtcbiAgICAgIHZhciBsc3cgPSAoYSAmIDB4RkZGRikgKyAoYiAmIDB4RkZGRikgKyAoYyAmIDB4RkZGRikgKyAoZCAmIDB4RkZGRiksXG4gICAgICAgIG1zdyA9IChhID4+PiAxNikgKyAoYiA+Pj4gMTYpICsgKGMgPj4+IDE2KSArIChkID4+PiAxNikgK1xuICAgICAgICAgIChsc3cgPj4+IDE2KTtcblxuICAgICAgcmV0dXJuICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBBZGQgZml2ZSAzMi1iaXQgaW50ZWdlcnMsIHdyYXBwaW5nIGF0IDJeMzIuIFRoaXMgdXNlcyAxNi1iaXQgb3BlcmF0aW9uc1xuICAgICAqIGludGVybmFsbHkgdG8gd29yayBhcm91bmQgYnVncyBpbiBzb21lIEpTIGludGVycHJldGVycy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGEgVGhlIGZpcnN0IDMyLWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IGIgVGhlIHNlY29uZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBjIFRoZSB0aGlyZCAzMi1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBkIFRoZSBmb3VydGggMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gZSBUaGUgZmlmdGggMzItYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcmV0dXJuIFRoZSBzdW0gb2YgYSArIGIgKyBjICsgZCArIGVcbiAgICAgKi9cbiAgICBzYWZlQWRkXzMyXzUgPSBmdW5jdGlvbihhLCBiLCBjLCBkLCBlKSB7XG4gICAgICB2YXIgbHN3ID0gKGEgJiAweEZGRkYpICsgKGIgJiAweEZGRkYpICsgKGMgJiAweEZGRkYpICsgKGQgJiAweEZGRkYpICtcbiAgICAgICAgKGUgJiAweEZGRkYpLFxuICAgICAgICBtc3cgPSAoYSA+Pj4gMTYpICsgKGIgPj4+IDE2KSArIChjID4+PiAxNikgKyAoZCA+Pj4gMTYpICtcbiAgICAgICAgICAoZSA+Pj4gMTYpICsgKGxzdyA+Pj4gMTYpO1xuXG4gICAgICByZXR1cm4gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIEFkZCB0d28gNjQtYml0IGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjY0LiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnNcbiAgICAgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB4IFRoZSBmaXJzdCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSB5IFRoZSBzZWNvbmQgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcmV0dXJuIFRoZSBzdW0gb2YgeCArIHlcbiAgICAgKi9cbiAgICBzYWZlQWRkXzY0XzIgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB2YXIgbHN3LCBtc3csIGxvd09yZGVyLCBoaWdoT3JkZXI7XG5cbiAgICAgIGxzdyA9ICh4Lmxvd09yZGVyICYgMHhGRkZGKSArICh5Lmxvd09yZGVyICYgMHhGRkZGKTtcbiAgICAgIG1zdyA9ICh4Lmxvd09yZGVyID4+PiAxNikgKyAoeS5sb3dPcmRlciA+Pj4gMTYpICsgKGxzdyA+Pj4gMTYpO1xuICAgICAgbG93T3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cbiAgICAgIGxzdyA9ICh4LmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoeS5oaWdoT3JkZXIgJiAweEZGRkYpICsgKG1zdyA+Pj4gMTYpO1xuICAgICAgbXN3ID0gKHguaGlnaE9yZGVyID4+PiAxNikgKyAoeS5oaWdoT3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcbiAgICAgIGhpZ2hPcmRlciA9ICgobXN3ICYgMHhGRkZGKSA8PCAxNikgfCAobHN3ICYgMHhGRkZGKTtcblxuICAgICAgcmV0dXJuIG5ldyBJbnRfNjQoaGlnaE9yZGVyLCBsb3dPcmRlcik7XG4gICAgfSxcblxuICAgIC8qXG4gICAgICogQWRkIGZvdXIgNjQtYml0IGludGVnZXJzLCB3cmFwcGluZyBhdCAyXjY0LiBUaGlzIHVzZXMgMTYtYml0IG9wZXJhdGlvbnNcbiAgICAgKiBpbnRlcm5hbGx5IHRvIHdvcmsgYXJvdW5kIGJ1Z3MgaW4gc29tZSBKUyBpbnRlcnByZXRlcnMuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSB7SW50XzY0fSBhIFRoZSBmaXJzdCA2NC1iaXQgaW50ZWdlciBhcmd1bWVudCB0byBiZSBhZGRlZFxuICAgICAqIEBwYXJhbSB7SW50XzY0fSBiIFRoZSBzZWNvbmQgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gYyBUaGUgdGhpcmQgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gZCBUaGUgZm91dGggNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcmV0dXJuIFRoZSBzdW0gb2YgYSArIGIgKyBjICsgZFxuICAgICAqL1xuICAgIHNhZmVBZGRfNjRfNCA9IGZ1bmN0aW9uKGEsIGIsIGMsIGQpIHtcbiAgICAgIHZhciBsc3csIG1zdywgbG93T3JkZXIsIGhpZ2hPcmRlcjtcblxuICAgICAgbHN3ID0gKGEubG93T3JkZXIgJiAweEZGRkYpICsgKGIubG93T3JkZXIgJiAweEZGRkYpICtcbiAgICAgICAgKGMubG93T3JkZXIgJiAweEZGRkYpICsgKGQubG93T3JkZXIgJiAweEZGRkYpO1xuICAgICAgbXN3ID0gKGEubG93T3JkZXIgPj4+IDE2KSArIChiLmxvd09yZGVyID4+PiAxNikgK1xuICAgICAgICAoYy5sb3dPcmRlciA+Pj4gMTYpICsgKGQubG93T3JkZXIgPj4+IDE2KSArIChsc3cgPj4+IDE2KTtcbiAgICAgIGxvd09yZGVyID0gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXG4gICAgICBsc3cgPSAoYS5oaWdoT3JkZXIgJiAweEZGRkYpICsgKGIuaGlnaE9yZGVyICYgMHhGRkZGKSArXG4gICAgICAgIChjLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoZC5oaWdoT3JkZXIgJiAweEZGRkYpICsgKG1zdyA+Pj4gMTYpO1xuICAgICAgbXN3ID0gKGEuaGlnaE9yZGVyID4+PiAxNikgKyAoYi5oaWdoT3JkZXIgPj4+IDE2KSArXG4gICAgICAgIChjLmhpZ2hPcmRlciA+Pj4gMTYpICsgKGQuaGlnaE9yZGVyID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG4gICAgICBoaWdoT3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cbiAgICAgIHJldHVybiBuZXcgSW50XzY0KGhpZ2hPcmRlciwgbG93T3JkZXIpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIEFkZCBmaXZlIDY0LWJpdCBpbnRlZ2Vycywgd3JhcHBpbmcgYXQgMl42NC4gVGhpcyB1c2VzIDE2LWJpdCBvcGVyYXRpb25zXG4gICAgICogaW50ZXJuYWxseSB0byB3b3JrIGFyb3VuZCBidWdzIGluIHNvbWUgSlMgaW50ZXJwcmV0ZXJzLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gYSBUaGUgZmlyc3QgNjQtYml0IGludGVnZXIgYXJndW1lbnQgdG8gYmUgYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludF82NH0gYiBUaGUgc2Vjb25kIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IGMgVGhlIHRoaXJkIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IGQgVGhlIGZvdXRoIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHBhcmFtIHtJbnRfNjR9IGUgVGhlIGZvdXRoIDY0LWJpdCBpbnRlZ2VyIGFyZ3VtZW50IHRvIGJlIGFkZGVkXG4gICAgICogQHJldHVybiBUaGUgc3VtIG9mIGEgKyBiICsgYyArIGQgKyBlXG4gICAgICovXG4gICAgc2FmZUFkZF82NF81ID0gZnVuY3Rpb24oYSwgYiwgYywgZCwgZSkge1xuICAgICAgdmFyIGxzdywgbXN3LCBsb3dPcmRlciwgaGlnaE9yZGVyO1xuXG4gICAgICBsc3cgPSAoYS5sb3dPcmRlciAmIDB4RkZGRikgKyAoYi5sb3dPcmRlciAmIDB4RkZGRikgK1xuICAgICAgICAoYy5sb3dPcmRlciAmIDB4RkZGRikgKyAoZC5sb3dPcmRlciAmIDB4RkZGRikgK1xuICAgICAgICAoZS5sb3dPcmRlciAmIDB4RkZGRik7XG4gICAgICBtc3cgPSAoYS5sb3dPcmRlciA+Pj4gMTYpICsgKGIubG93T3JkZXIgPj4+IDE2KSArXG4gICAgICAgIChjLmxvd09yZGVyID4+PiAxNikgKyAoZC5sb3dPcmRlciA+Pj4gMTYpICsgKGUubG93T3JkZXIgPj4+IDE2KSArXG4gICAgICAgIChsc3cgPj4+IDE2KTtcbiAgICAgIGxvd09yZGVyID0gKChtc3cgJiAweEZGRkYpIDw8IDE2KSB8IChsc3cgJiAweEZGRkYpO1xuXG4gICAgICBsc3cgPSAoYS5oaWdoT3JkZXIgJiAweEZGRkYpICsgKGIuaGlnaE9yZGVyICYgMHhGRkZGKSArXG4gICAgICAgIChjLmhpZ2hPcmRlciAmIDB4RkZGRikgKyAoZC5oaWdoT3JkZXIgJiAweEZGRkYpICtcbiAgICAgICAgKGUuaGlnaE9yZGVyICYgMHhGRkZGKSArIChtc3cgPj4+IDE2KTtcbiAgICAgIG1zdyA9IChhLmhpZ2hPcmRlciA+Pj4gMTYpICsgKGIuaGlnaE9yZGVyID4+PiAxNikgK1xuICAgICAgICAoYy5oaWdoT3JkZXIgPj4+IDE2KSArIChkLmhpZ2hPcmRlciA+Pj4gMTYpICtcbiAgICAgICAgKGUuaGlnaE9yZGVyID4+PiAxNikgKyAobHN3ID4+PiAxNik7XG4gICAgICBoaWdoT3JkZXIgPSAoKG1zdyAmIDB4RkZGRikgPDwgMTYpIHwgKGxzdyAmIDB4RkZGRik7XG5cbiAgICAgIHJldHVybiBuZXcgSW50XzY0KGhpZ2hPcmRlciwgbG93T3JkZXIpO1xuICAgIH0sXG5cbiAgICAvKlxuICAgICAqIENhbGN1bGF0ZXMgdGhlIFNIQS0xIGhhc2ggb2YgdGhlIHN0cmluZyBzZXQgYXQgaW5zdGFudGlhdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBtZXNzYWdlIFRoZSBiaW5hcnkgYXJyYXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHN0cmluZyB0b1xuICAgICAqXHQgaGFzaFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBtZXNzYWdlTGVuIFRoZSBudW1iZXIgb2YgYml0cyBpbiB0aGUgbWVzc2FnZVxuICAgICAqIEByZXR1cm4gVGhlIGFycmF5IG9mIGludGVnZXJzIHJlcHJlc2VudGluZyB0aGUgU0hBLTEgaGFzaCBvZiBtZXNzYWdlXG4gICAgICovXG4gICAgY29yZVNIQTEgPSBmdW5jdGlvbihtZXNzYWdlLCBtZXNzYWdlTGVuKSB7XG4gICAgICB2YXIgVyA9IFtdLFxuICAgICAgICBhLCBiLCBjLCBkLCBlLCBULCBjaCA9IGNoXzMyLFxuICAgICAgICBwYXJpdHkgPSBwYXJpdHlfMzIsXG4gICAgICAgIG1haiA9IG1hal8zMixcbiAgICAgICAgcm90bCA9IHJvdGxfMzIsXG4gICAgICAgIHNhZmVBZGRfMiA9IHNhZmVBZGRfMzJfMixcbiAgICAgICAgaSwgdCxcbiAgICAgICAgc2FmZUFkZF81ID0gc2FmZUFkZF8zMl81LFxuICAgICAgICBhcHBlbmRlZE1lc3NhZ2VMZW5ndGgsXG4gICAgICAgIEggPSBbXG4gICAgICAgICAgICAweDY3NDUyMzAxLCAweGVmY2RhYjg5LCAweDk4YmFkY2ZlLCAweDEwMzI1NDc2LCAweGMzZDJlMWYwXG4gICAgICAgIF0sXG4gICAgICAgIEsgPSBbXG4gICAgICAgICAgICAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuICAgICAgICAgICAgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSxcbiAgICAgICAgICAgIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksIDB4NWE4Mjc5OTksXG4gICAgICAgICAgICAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LCAweDVhODI3OTk5LFxuICAgICAgICAgICAgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSwgMHg1YTgyNzk5OSxcbiAgICAgICAgICAgIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsXG4gICAgICAgICAgICAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuICAgICAgICAgICAgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSwgMHg2ZWQ5ZWJhMSxcbiAgICAgICAgICAgIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsIDB4NmVkOWViYTEsXG4gICAgICAgICAgICAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLCAweDZlZDllYmExLFxuICAgICAgICAgICAgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYyxcbiAgICAgICAgICAgIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsXG4gICAgICAgICAgICAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLCAweDhmMWJiY2RjLFxuICAgICAgICAgICAgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYywgMHg4ZjFiYmNkYyxcbiAgICAgICAgICAgIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsIDB4OGYxYmJjZGMsXG4gICAgICAgICAgICAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuICAgICAgICAgICAgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNixcbiAgICAgICAgICAgIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsIDB4Y2E2MmMxZDYsXG4gICAgICAgICAgICAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LCAweGNhNjJjMWQ2LFxuICAgICAgICAgICAgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNiwgMHhjYTYyYzFkNlxuICAgICAgICBdO1xuXG4gICAgICAvKiBBcHBlbmQgJzEnIGF0IHRoZSBlbmQgb2YgdGhlIGJpbmFyeSBzdHJpbmcgKi9cbiAgICAgIG1lc3NhZ2VbbWVzc2FnZUxlbiA+PiA1XSB8PSAweDgwIDw8ICgyNCAtIChtZXNzYWdlTGVuICUgMzIpKTtcbiAgICAgIC8qIEFwcGVuZCBsZW5ndGggb2YgYmluYXJ5IHN0cmluZyBpbiB0aGUgcG9zaXRpb24gc3VjaCB0aGF0IHRoZSBuZXdcblx0XHRsZW5ndGggaXMgYSBtdWx0aXBsZSBvZiA1MTIuICBMb2dpYyBkb2VzIG5vdCB3b3JrIGZvciBldmVuIG11bHRpcGxlc1xuXHRcdG9mIDUxMiBidXQgdGhlcmUgY2FuIG5ldmVyIGJlIGV2ZW4gbXVsdGlwbGVzIG9mIDUxMiAqL1xuICAgICAgbWVzc2FnZVsoKChtZXNzYWdlTGVuICsgNjUpID4+IDkpIDw8IDQpICsgMTVdID0gbWVzc2FnZUxlbjtcblxuICAgICAgYXBwZW5kZWRNZXNzYWdlTGVuZ3RoID0gbWVzc2FnZS5sZW5ndGg7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBhcHBlbmRlZE1lc3NhZ2VMZW5ndGg7IGkgKz0gMTYpIHtcbiAgICAgICAgYSA9IEhbMF07XG4gICAgICAgIGIgPSBIWzFdO1xuICAgICAgICBjID0gSFsyXTtcbiAgICAgICAgZCA9IEhbM107XG4gICAgICAgIGUgPSBIWzRdO1xuXG4gICAgICAgIGZvciAodCA9IDA7IHQgPCA4MDsgdCArPSAxKSB7XG4gICAgICAgICAgaWYgKHQgPCAxNikge1xuICAgICAgICAgICAgV1t0XSA9IG1lc3NhZ2VbdCArIGldO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBXW3RdID0gcm90bChXW3QgLSAzXSBeIFdbdCAtIDhdIF4gV1t0IC0gMTRdIF4gV1t0IC0gMTZdLCAxKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodCA8IDIwKSB7XG4gICAgICAgICAgICBUID0gc2FmZUFkZF81KHJvdGwoYSwgNSksIGNoKGIsIGMsIGQpLCBlLCBLW3RdLCBXW3RdKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHQgPCA0MCkge1xuICAgICAgICAgICAgVCA9IHNhZmVBZGRfNShyb3RsKGEsIDUpLCBwYXJpdHkoYiwgYywgZCksIGUsIEtbdF0sIFdbdF0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAodCA8IDYwKSB7XG4gICAgICAgICAgICBUID0gc2FmZUFkZF81KHJvdGwoYSwgNSksIG1haihiLCBjLCBkKSwgZSwgS1t0XSwgV1t0XSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFQgPSBzYWZlQWRkXzUocm90bChhLCA1KSwgcGFyaXR5KGIsIGMsIGQpLCBlLCBLW3RdLCBXW3RdKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBlID0gZDtcbiAgICAgICAgICBkID0gYztcbiAgICAgICAgICBjID0gcm90bChiLCAzMCk7XG4gICAgICAgICAgYiA9IGE7XG4gICAgICAgICAgYSA9IFQ7XG4gICAgICAgIH1cblxuICAgICAgICBIWzBdID0gc2FmZUFkZF8yKGEsIEhbMF0pO1xuICAgICAgICBIWzFdID0gc2FmZUFkZF8yKGIsIEhbMV0pO1xuICAgICAgICBIWzJdID0gc2FmZUFkZF8yKGMsIEhbMl0pO1xuICAgICAgICBIWzNdID0gc2FmZUFkZF8yKGQsIEhbM10pO1xuICAgICAgICBIWzRdID0gc2FmZUFkZF8yKGUsIEhbNF0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gSDtcbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSBkZXNpcmVkIFNIQS0yIGhhc2ggb2YgdGhlIHN0cmluZyBzZXQgYXQgaW5zdGFudGlhdGlvblxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBUaGUgYmluYXJ5IGFycmF5IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBzdHJpbmcgdG8gaGFzaFxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBUaGUgbnVtYmVyIG9mIGJpdHMgaW4gbWVzc2FnZVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB2YXJpYW50IFRoZSBkZXNpcmVkIFNIQS0yIHZhcmlhbnRcbiAgICAgKiBAcmV0dXJuIFRoZSBhcnJheSBvZiBpbnRlZ2VycyByZXByZXNlbnRpbmcgdGhlIFNIQS0yIGhhc2ggb2YgbWVzc2FnZVxuICAgICAqL1xuICAgIGNvcmVTSEEyID0gZnVuY3Rpb24obWVzc2FnZSwgbWVzc2FnZUxlbiwgdmFyaWFudCkge1xuICAgICAgdmFyIGEsIGIsIGMsIGQsIGUsIGYsIGcsIGgsIFQxLCBUMiwgSCwgbnVtUm91bmRzLCBsZW5ndGhQb3NpdGlvbiwgaSwgdCxcbiAgICAgICAgYmluYXJ5U3RyaW5nSW5jLCBiaW5hcnlTdHJpbmdNdWx0LCBzYWZlQWRkXzIsIHNhZmVBZGRfNCwgc2FmZUFkZF81LFxuICAgICAgICBnYW1tYTAsIGdhbW1hMSwgc2lnbWEwLCBzaWdtYTEsIGNoLCBtYWosIEludCwgSywgVyA9IFtdLFxuICAgICAgICBhcHBlbmRlZE1lc3NhZ2VMZW5ndGg7XG5cbiAgICAgIC8qIFNldCB1cCB0aGUgdmFyaW91cyBmdW5jdGlvbiBoYW5kbGVzIGFuZCB2YXJpYWJsZSBmb3IgdGhlIHNwZWNpZmljIFxuICAgICAgICogdmFyaWFudCAqL1xuICAgICAgaWYgKHZhcmlhbnQgPT09IFwiU0hBLTIyNFwiIHx8IHZhcmlhbnQgPT09IFwiU0hBLTI1NlwiKSB7XG4gICAgICAgIC8qIDMyLWJpdCB2YXJpYW50ICovXG4gICAgICAgIG51bVJvdW5kcyA9IDY0O1xuICAgICAgICBsZW5ndGhQb3NpdGlvbiA9ICgoKG1lc3NhZ2VMZW4gKyA2NSkgPj4gOSkgPDwgNCkgKyAxNTtcbiAgICAgICAgYmluYXJ5U3RyaW5nSW5jID0gMTY7XG4gICAgICAgIGJpbmFyeVN0cmluZ011bHQgPSAxO1xuICAgICAgICBJbnQgPSBOdW1iZXI7XG4gICAgICAgIHNhZmVBZGRfMiA9IHNhZmVBZGRfMzJfMjtcbiAgICAgICAgc2FmZUFkZF80ID0gc2FmZUFkZF8zMl80O1xuICAgICAgICBzYWZlQWRkXzUgPSBzYWZlQWRkXzMyXzU7XG4gICAgICAgIGdhbW1hMCA9IGdhbW1hMF8zMjtcbiAgICAgICAgZ2FtbWExID0gZ2FtbWExXzMyO1xuICAgICAgICBzaWdtYTAgPSBzaWdtYTBfMzI7XG4gICAgICAgIHNpZ21hMSA9IHNpZ21hMV8zMjtcbiAgICAgICAgbWFqID0gbWFqXzMyO1xuICAgICAgICBjaCA9IGNoXzMyO1xuICAgICAgICBLID0gW1xuICAgICAgICAgICAgMHg0MjhBMkY5OCwgMHg3MTM3NDQ5MSwgMHhCNUMwRkJDRiwgMHhFOUI1REJBNSxcbiAgICAgICAgICAgIDB4Mzk1NkMyNUIsIDB4NTlGMTExRjEsIDB4OTIzRjgyQTQsIDB4QUIxQzVFRDUsXG4gICAgICAgICAgICAweEQ4MDdBQTk4LCAweDEyODM1QjAxLCAweDI0MzE4NUJFLCAweDU1MEM3REMzLFxuICAgICAgICAgICAgMHg3MkJFNUQ3NCwgMHg4MERFQjFGRSwgMHg5QkRDMDZBNywgMHhDMTlCRjE3NCxcbiAgICAgICAgICAgIDB4RTQ5QjY5QzEsIDB4RUZCRTQ3ODYsIDB4MEZDMTlEQzYsIDB4MjQwQ0ExQ0MsXG4gICAgICAgICAgICAweDJERTkyQzZGLCAweDRBNzQ4NEFBLCAweDVDQjBBOURDLCAweDc2Rjk4OERBLFxuICAgICAgICAgICAgMHg5ODNFNTE1MiwgMHhBODMxQzY2RCwgMHhCMDAzMjdDOCwgMHhCRjU5N0ZDNyxcbiAgICAgICAgICAgIDB4QzZFMDBCRjMsIDB4RDVBNzkxNDcsIDB4MDZDQTYzNTEsIDB4MTQyOTI5NjcsXG4gICAgICAgICAgICAweDI3QjcwQTg1LCAweDJFMUIyMTM4LCAweDREMkM2REZDLCAweDUzMzgwRDEzLFxuICAgICAgICAgICAgMHg2NTBBNzM1NCwgMHg3NjZBMEFCQiwgMHg4MUMyQzkyRSwgMHg5MjcyMkM4NSxcbiAgICAgICAgICAgIDB4QTJCRkU4QTEsIDB4QTgxQTY2NEIsIDB4QzI0QjhCNzAsIDB4Qzc2QzUxQTMsXG4gICAgICAgICAgICAweEQxOTJFODE5LCAweEQ2OTkwNjI0LCAweEY0MEUzNTg1LCAweDEwNkFBMDcwLFxuICAgICAgICAgICAgMHgxOUE0QzExNiwgMHgxRTM3NkMwOCwgMHgyNzQ4Nzc0QywgMHgzNEIwQkNCNSxcbiAgICAgICAgICAgIDB4MzkxQzBDQjMsIDB4NEVEOEFBNEEsIDB4NUI5Q0NBNEYsIDB4NjgyRTZGRjMsXG4gICAgICAgICAgICAweDc0OEY4MkVFLCAweDc4QTU2MzZGLCAweDg0Qzg3ODE0LCAweDhDQzcwMjA4LFxuICAgICAgICAgICAgMHg5MEJFRkZGQSwgMHhBNDUwNkNFQiwgMHhCRUY5QTNGNywgMHhDNjcxNzhGMlxuICAgICAgICBdO1xuXG4gICAgICAgIGlmICh2YXJpYW50ID09PSBcIlNIQS0yMjRcIikge1xuICAgICAgICAgIEggPSBbXG4gICAgICAgICAgICAgIDB4YzEwNTllZDgsIDB4MzY3Y2Q1MDcsIDB4MzA3MGRkMTcsIDB4ZjcwZTU5MzksXG4gICAgICAgICAgICAgIDB4ZmZjMDBiMzEsIDB4Njg1ODE1MTEsIDB4NjRmOThmYTcsIDB4YmVmYTRmYTRcbiAgICAgICAgICBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIEggPSBbXG4gICAgICAgICAgICAgIDB4NkEwOUU2NjcsIDB4QkI2N0FFODUsIDB4M0M2RUYzNzIsIDB4QTU0RkY1M0EsXG4gICAgICAgICAgICAgIDB4NTEwRTUyN0YsIDB4OUIwNTY4OEMsIDB4MUY4M0Q5QUIsIDB4NUJFMENEMTlcbiAgICAgICAgICBdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHZhcmlhbnQgPT09IFwiU0hBLTM4NFwiIHx8IHZhcmlhbnQgPT09IFwiU0hBLTUxMlwiKSB7XG4gICAgICAgIC8qIDY0LWJpdCB2YXJpYW50ICovXG4gICAgICAgIG51bVJvdW5kcyA9IDgwO1xuICAgICAgICBsZW5ndGhQb3NpdGlvbiA9ICgoKG1lc3NhZ2VMZW4gKyAxMjgpID4+IDEwKSA8PCA1KSArIDMxO1xuICAgICAgICBiaW5hcnlTdHJpbmdJbmMgPSAzMjtcbiAgICAgICAgYmluYXJ5U3RyaW5nTXVsdCA9IDI7XG4gICAgICAgIEludCA9IEludF82NDtcbiAgICAgICAgc2FmZUFkZF8yID0gc2FmZUFkZF82NF8yO1xuICAgICAgICBzYWZlQWRkXzQgPSBzYWZlQWRkXzY0XzQ7XG4gICAgICAgIHNhZmVBZGRfNSA9IHNhZmVBZGRfNjRfNTtcbiAgICAgICAgZ2FtbWEwID0gZ2FtbWEwXzY0O1xuICAgICAgICBnYW1tYTEgPSBnYW1tYTFfNjQ7XG4gICAgICAgIHNpZ21hMCA9IHNpZ21hMF82NDtcbiAgICAgICAgc2lnbWExID0gc2lnbWExXzY0O1xuICAgICAgICBtYWogPSBtYWpfNjQ7XG4gICAgICAgIGNoID0gY2hfNjQ7XG5cbiAgICAgICAgSyA9IFtcbiAgICAgICAgICAgIG5ldyBJbnQoMHg0MjhhMmY5OCwgMHhkNzI4YWUyMiksIG5ldyBJbnQoMHg3MTM3NDQ5MSwgMHgyM2VmNjVjZCksXG4gICAgICAgICAgICBuZXcgSW50KDB4YjVjMGZiY2YsIDB4ZWM0ZDNiMmYpLCBuZXcgSW50KDB4ZTliNWRiYTUsIDB4ODE4OWRiYmMpLFxuICAgICAgICAgICAgbmV3IEludCgweDM5NTZjMjViLCAweGYzNDhiNTM4KSwgbmV3IEludCgweDU5ZjExMWYxLCAweGI2MDVkMDE5KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg5MjNmODJhNCwgMHhhZjE5NGY5YiksIG5ldyBJbnQoMHhhYjFjNWVkNSwgMHhkYTZkODExOCksXG4gICAgICAgICAgICBuZXcgSW50KDB4ZDgwN2FhOTgsIDB4YTMwMzAyNDIpLCBuZXcgSW50KDB4MTI4MzViMDEsIDB4NDU3MDZmYmUpLFxuICAgICAgICAgICAgbmV3IEludCgweDI0MzE4NWJlLCAweDRlZTRiMjhjKSwgbmV3IEludCgweDU1MGM3ZGMzLCAweGQ1ZmZiNGUyKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg3MmJlNWQ3NCwgMHhmMjdiODk2ZiksIG5ldyBJbnQoMHg4MGRlYjFmZSwgMHgzYjE2OTZiMSksXG4gICAgICAgICAgICBuZXcgSW50KDB4OWJkYzA2YTcsIDB4MjVjNzEyMzUpLCBuZXcgSW50KDB4YzE5YmYxNzQsIDB4Y2Y2OTI2OTQpLFxuICAgICAgICAgICAgbmV3IEludCgweGU0OWI2OWMxLCAweDllZjE0YWQyKSwgbmV3IEludCgweGVmYmU0Nzg2LCAweDM4NGYyNWUzKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgwZmMxOWRjNiwgMHg4YjhjZDViNSksIG5ldyBJbnQoMHgyNDBjYTFjYywgMHg3N2FjOWM2NSksXG4gICAgICAgICAgICBuZXcgSW50KDB4MmRlOTJjNmYsIDB4NTkyYjAyNzUpLCBuZXcgSW50KDB4NGE3NDg0YWEsIDB4NmVhNmU0ODMpLFxuICAgICAgICAgICAgbmV3IEludCgweDVjYjBhOWRjLCAweGJkNDFmYmQ0KSwgbmV3IEludCgweDc2Zjk4OGRhLCAweDgzMTE1M2I1KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg5ODNlNTE1MiwgMHhlZTY2ZGZhYiksIG5ldyBJbnQoMHhhODMxYzY2ZCwgMHgyZGI0MzIxMCksXG4gICAgICAgICAgICBuZXcgSW50KDB4YjAwMzI3YzgsIDB4OThmYjIxM2YpLCBuZXcgSW50KDB4YmY1OTdmYzcsIDB4YmVlZjBlZTQpLFxuICAgICAgICAgICAgbmV3IEludCgweGM2ZTAwYmYzLCAweDNkYTg4ZmMyKSwgbmV3IEludCgweGQ1YTc5MTQ3LCAweDkzMGFhNzI1KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgwNmNhNjM1MSwgMHhlMDAzODI2ZiksIG5ldyBJbnQoMHgxNDI5Mjk2NywgMHgwYTBlNmU3MCksXG4gICAgICAgICAgICBuZXcgSW50KDB4MjdiNzBhODUsIDB4NDZkMjJmZmMpLCBuZXcgSW50KDB4MmUxYjIxMzgsIDB4NWMyNmM5MjYpLFxuICAgICAgICAgICAgbmV3IEludCgweDRkMmM2ZGZjLCAweDVhYzQyYWVkKSwgbmV3IEludCgweDUzMzgwZDEzLCAweDlkOTViM2RmKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg2NTBhNzM1NCwgMHg4YmFmNjNkZSksIG5ldyBJbnQoMHg3NjZhMGFiYiwgMHgzYzc3YjJhOCksXG4gICAgICAgICAgICBuZXcgSW50KDB4ODFjMmM5MmUsIDB4NDdlZGFlZTYpLCBuZXcgSW50KDB4OTI3MjJjODUsIDB4MTQ4MjM1M2IpLFxuICAgICAgICAgICAgbmV3IEludCgweGEyYmZlOGExLCAweDRjZjEwMzY0KSwgbmV3IEludCgweGE4MWE2NjRiLCAweGJjNDIzMDAxKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhjMjRiOGI3MCwgMHhkMGY4OTc5MSksIG5ldyBJbnQoMHhjNzZjNTFhMywgMHgwNjU0YmUzMCksXG4gICAgICAgICAgICBuZXcgSW50KDB4ZDE5MmU4MTksIDB4ZDZlZjUyMTgpLCBuZXcgSW50KDB4ZDY5OTA2MjQsIDB4NTU2NWE5MTApLFxuICAgICAgICAgICAgbmV3IEludCgweGY0MGUzNTg1LCAweDU3NzEyMDJhKSwgbmV3IEludCgweDEwNmFhMDcwLCAweDMyYmJkMWI4KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgxOWE0YzExNiwgMHhiOGQyZDBjOCksIG5ldyBJbnQoMHgxZTM3NmMwOCwgMHg1MTQxYWI1MyksXG4gICAgICAgICAgICBuZXcgSW50KDB4Mjc0ODc3NGMsIDB4ZGY4ZWViOTkpLCBuZXcgSW50KDB4MzRiMGJjYjUsIDB4ZTE5YjQ4YTgpLFxuICAgICAgICAgICAgbmV3IEludCgweDM5MWMwY2IzLCAweGM1Yzk1YTYzKSwgbmV3IEludCgweDRlZDhhYTRhLCAweGUzNDE4YWNiKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg1YjljY2E0ZiwgMHg3NzYzZTM3MyksIG5ldyBJbnQoMHg2ODJlNmZmMywgMHhkNmIyYjhhMyksXG4gICAgICAgICAgICBuZXcgSW50KDB4NzQ4ZjgyZWUsIDB4NWRlZmIyZmMpLCBuZXcgSW50KDB4NzhhNTYzNmYsIDB4NDMxNzJmNjApLFxuICAgICAgICAgICAgbmV3IEludCgweDg0Yzg3ODE0LCAweGExZjBhYjcyKSwgbmV3IEludCgweDhjYzcwMjA4LCAweDFhNjQzOWVjKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg5MGJlZmZmYSwgMHgyMzYzMWUyOCksIG5ldyBJbnQoMHhhNDUwNmNlYiwgMHhkZTgyYmRlOSksXG4gICAgICAgICAgICBuZXcgSW50KDB4YmVmOWEzZjcsIDB4YjJjNjc5MTUpLCBuZXcgSW50KDB4YzY3MTc4ZjIsIDB4ZTM3MjUzMmIpLFxuICAgICAgICAgICAgbmV3IEludCgweGNhMjczZWNlLCAweGVhMjY2MTljKSwgbmV3IEludCgweGQxODZiOGM3LCAweDIxYzBjMjA3KSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHhlYWRhN2RkNiwgMHhjZGUwZWIxZSksIG5ldyBJbnQoMHhmNTdkNGY3ZiwgMHhlZTZlZDE3OCksXG4gICAgICAgICAgICBuZXcgSW50KDB4MDZmMDY3YWEsIDB4NzIxNzZmYmEpLCBuZXcgSW50KDB4MGE2MzdkYzUsIDB4YTJjODk4YTYpLFxuICAgICAgICAgICAgbmV3IEludCgweDExM2Y5ODA0LCAweGJlZjkwZGFlKSwgbmV3IEludCgweDFiNzEwYjM1LCAweDEzMWM0NzFiKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHgyOGRiNzdmNSwgMHgyMzA0N2Q4NCksIG5ldyBJbnQoMHgzMmNhYWI3YiwgMHg0MGM3MjQ5MyksXG4gICAgICAgICAgICBuZXcgSW50KDB4M2M5ZWJlMGEsIDB4MTVjOWJlYmMpLCBuZXcgSW50KDB4NDMxZDY3YzQsIDB4OWMxMDBkNGMpLFxuICAgICAgICAgICAgbmV3IEludCgweDRjYzVkNGJlLCAweGNiM2U0MmI2KSwgbmV3IEludCgweDU5N2YyOTljLCAweGZjNjU3ZTJhKSxcbiAgICAgICAgICAgIG5ldyBJbnQoMHg1ZmNiNmZhYiwgMHgzYWQ2ZmFlYyksIG5ldyBJbnQoMHg2YzQ0MTk4YywgMHg0YTQ3NTgxNylcbiAgICAgICAgXTtcblxuICAgICAgICBpZiAodmFyaWFudCA9PT0gXCJTSEEtMzg0XCIpIHtcbiAgICAgICAgICBIID0gW1xuICAgICAgICAgICAgICBuZXcgSW50KDB4Y2JiYjlkNWQsIDB4YzEwNTllZDgpLCBuZXcgSW50KDB4MDYyOWEyOTJhLCAweDM2N2NkNTA3KSxcbiAgICAgICAgICAgICAgbmV3IEludCgweDkxNTkwMTVhLCAweDMwNzBkZDE3KSwgbmV3IEludCgweDAxNTJmZWNkOCwgMHhmNzBlNTkzOSksXG4gICAgICAgICAgICAgIG5ldyBJbnQoMHg2NzMzMjY2NywgMHhmZmMwMGIzMSksIG5ldyBJbnQoMHg5OGViNDRhODcsIDB4Njg1ODE1MTEpLFxuICAgICAgICAgICAgICBuZXcgSW50KDB4ZGIwYzJlMGQsIDB4NjRmOThmYTcpLCBuZXcgSW50KDB4MDQ3YjU0ODFkLCAweGJlZmE0ZmE0KVxuICAgICAgICAgIF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgSCA9IFtcbiAgICAgICAgICAgICAgbmV3IEludCgweDZhMDllNjY3LCAweGYzYmNjOTA4KSwgbmV3IEludCgweGJiNjdhZTg1LCAweDg0Y2FhNzNiKSxcbiAgICAgICAgICAgICAgbmV3IEludCgweDNjNmVmMzcyLCAweGZlOTRmODJiKSwgbmV3IEludCgweGE1NGZmNTNhLCAweDVmMWQzNmYxKSxcbiAgICAgICAgICAgICAgbmV3IEludCgweDUxMGU1MjdmLCAweGFkZTY4MmQxKSwgbmV3IEludCgweDliMDU2ODhjLCAweDJiM2U2YzFmKSxcbiAgICAgICAgICAgICAgbmV3IEludCgweDFmODNkOWFiLCAweGZiNDFiZDZiKSwgbmV3IEludCgweDViZTBjZDE5LCAweDEzN2UyMTc5KVxuICAgICAgICAgIF07XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLyogQXBwZW5kICcxJyBhdCB0aGUgZW5kIG9mIHRoZSBiaW5hcnkgc3RyaW5nICovXG4gICAgICBtZXNzYWdlW21lc3NhZ2VMZW4gPj4gNV0gfD0gMHg4MCA8PCAoMjQgLSBtZXNzYWdlTGVuICUgMzIpO1xuICAgICAgLyogQXBwZW5kIGxlbmd0aCBvZiBiaW5hcnkgc3RyaW5nIGluIHRoZSBwb3NpdGlvbiBzdWNoIHRoYXQgdGhlIG5ld1xuICAgICAgICogbGVuZ3RoIGlzIGNvcnJlY3QgKi9cbiAgICAgIG1lc3NhZ2VbbGVuZ3RoUG9zaXRpb25dID0gbWVzc2FnZUxlbjtcblxuICAgICAgYXBwZW5kZWRNZXNzYWdlTGVuZ3RoID0gbWVzc2FnZS5sZW5ndGg7XG5cbiAgICAgIGZvciAoaSA9IDA7IGkgPCBhcHBlbmRlZE1lc3NhZ2VMZW5ndGg7IGkgKz0gYmluYXJ5U3RyaW5nSW5jKSB7XG4gICAgICAgIGEgPSBIWzBdO1xuICAgICAgICBiID0gSFsxXTtcbiAgICAgICAgYyA9IEhbMl07XG4gICAgICAgIGQgPSBIWzNdO1xuICAgICAgICBlID0gSFs0XTtcbiAgICAgICAgZiA9IEhbNV07XG4gICAgICAgIGcgPSBIWzZdO1xuICAgICAgICBoID0gSFs3XTtcblxuICAgICAgICBmb3IgKHQgPSAwOyB0IDwgbnVtUm91bmRzOyB0ICs9IDEpIHtcbiAgICAgICAgICBpZiAodCA8IDE2KSB7XG4gICAgICAgICAgICAvKiBCaXQgb2YgYSBoYWNrIC0gZm9yIDMyLWJpdCwgdGhlIHNlY29uZCB0ZXJtIGlzIGlnbm9yZWQgKi9cbiAgICAgICAgICAgIFdbdF0gPSBuZXcgSW50KG1lc3NhZ2VbdCAqIGJpbmFyeVN0cmluZ011bHQgKyBpXSxcbiAgICAgICAgICAgICAgbWVzc2FnZVt0ICogYmluYXJ5U3RyaW5nTXVsdCArIGkgKyAxXSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFdbdF0gPSBzYWZlQWRkXzQoXG4gICAgICAgICAgICAgIGdhbW1hMShXW3QgLSAyXSksIFdbdCAtIDddLFxuICAgICAgICAgICAgICBnYW1tYTAoV1t0IC0gMTVdKSwgV1t0IC0gMTZdKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBUMSA9IHNhZmVBZGRfNShoLCBzaWdtYTEoZSksIGNoKGUsIGYsIGcpLCBLW3RdLCBXW3RdKTtcbiAgICAgICAgICBUMiA9IHNhZmVBZGRfMihzaWdtYTAoYSksIG1haihhLCBiLCBjKSk7XG4gICAgICAgICAgaCA9IGc7XG4gICAgICAgICAgZyA9IGY7XG4gICAgICAgICAgZiA9IGU7XG4gICAgICAgICAgZSA9IHNhZmVBZGRfMihkLCBUMSk7XG4gICAgICAgICAgZCA9IGM7XG4gICAgICAgICAgYyA9IGI7XG4gICAgICAgICAgYiA9IGE7XG4gICAgICAgICAgYSA9IHNhZmVBZGRfMihUMSwgVDIpO1xuICAgICAgICB9XG5cbiAgICAgICAgSFswXSA9IHNhZmVBZGRfMihhLCBIWzBdKTtcbiAgICAgICAgSFsxXSA9IHNhZmVBZGRfMihiLCBIWzFdKTtcbiAgICAgICAgSFsyXSA9IHNhZmVBZGRfMihjLCBIWzJdKTtcbiAgICAgICAgSFszXSA9IHNhZmVBZGRfMihkLCBIWzNdKTtcbiAgICAgICAgSFs0XSA9IHNhZmVBZGRfMihlLCBIWzRdKTtcbiAgICAgICAgSFs1XSA9IHNhZmVBZGRfMihmLCBIWzVdKTtcbiAgICAgICAgSFs2XSA9IHNhZmVBZGRfMihnLCBIWzZdKTtcbiAgICAgICAgSFs3XSA9IHNhZmVBZGRfMihoLCBIWzddKTtcbiAgICAgIH1cblxuICAgICAgc3dpdGNoICh2YXJpYW50KSB7XG4gICAgICAgIGNhc2UgXCJTSEEtMjI0XCI6XG4gICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIEhbMF0sIEhbMV0sIEhbMl0sIEhbM10sXG4gICAgICAgICAgICBIWzRdLCBIWzVdLCBIWzZdXTtcbiAgICAgICAgY2FzZSBcIlNIQS0yNTZcIjpcbiAgICAgICAgICByZXR1cm4gSDtcbiAgICAgICAgY2FzZSBcIlNIQS0zODRcIjpcbiAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgSFswXS5oaWdoT3JkZXIsIEhbMF0ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzFdLmhpZ2hPcmRlciwgSFsxXS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbMl0uaGlnaE9yZGVyLCBIWzJdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFszXS5oaWdoT3JkZXIsIEhbM10ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzRdLmhpZ2hPcmRlciwgSFs0XS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbNV0uaGlnaE9yZGVyLCBIWzVdLmxvd09yZGVyXTtcbiAgICAgICAgY2FzZSBcIlNIQS01MTJcIjpcbiAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgSFswXS5oaWdoT3JkZXIsIEhbMF0ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzFdLmhpZ2hPcmRlciwgSFsxXS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbMl0uaGlnaE9yZGVyLCBIWzJdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFszXS5oaWdoT3JkZXIsIEhbM10ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzRdLmhpZ2hPcmRlciwgSFs0XS5sb3dPcmRlcixcbiAgICAgICAgICAgIEhbNV0uaGlnaE9yZGVyLCBIWzVdLmxvd09yZGVyLFxuICAgICAgICAgICAgSFs2XS5oaWdoT3JkZXIsIEhbNl0ubG93T3JkZXIsXG4gICAgICAgICAgICBIWzddLmhpZ2hPcmRlciwgSFs3XS5sb3dPcmRlcl07XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgLyogVGhpcyBzaG91bGQgbmV2ZXIgYmUgcmVhY2hlZCAqL1xuICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBqc1NIQSBpcyB0aGUgd29ya2hvcnNlIG9mIHRoZSBsaWJyYXJ5LiAgSW5zdGFudGlhdGUgaXQgd2l0aCB0aGUgc3RyaW5nIHRvXG4gICAgICogYmUgaGFzaGVkIGFzIHRoZSBwYXJhbWV0ZXJcbiAgICAgKlxuICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzcmNTdHJpbmcgVGhlIHN0cmluZyB0byBiZSBoYXNoZWRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXRGb3JtYXQgVGhlIGZvcm1hdCBvZiBzcmNTdHJpbmcsIEFTQ0lJIG9yIEhFWFxuICAgICAqL1xuICAgIGpzU0hBID0gZnVuY3Rpb24oc3JjU3RyaW5nLCBpbnB1dEZvcm1hdCkge1xuXG4gICAgICB0aGlzLnNoYTEgPSBudWxsO1xuICAgICAgdGhpcy5zaGEyMjQgPSBudWxsO1xuICAgICAgdGhpcy5zaGEyNTYgPSBudWxsO1xuICAgICAgdGhpcy5zaGEzODQgPSBudWxsO1xuICAgICAgdGhpcy5zaGE1MTIgPSBudWxsO1xuXG4gICAgICB0aGlzLnN0ckJpbkxlbiA9IG51bGw7XG4gICAgICB0aGlzLnN0clRvSGFzaCA9IG51bGw7XG5cbiAgICAgIC8qIENvbnZlcnQgdGhlIGlucHV0IHN0cmluZyBpbnRvIHRoZSBjb3JyZWN0IHR5cGUgKi9cbiAgICAgIGlmIChcIkhFWFwiID09PSBpbnB1dEZvcm1hdCkge1xuICAgICAgICBpZiAoMCAhPT0gKHNyY1N0cmluZy5sZW5ndGggJSAyKSkge1xuICAgICAgICAgIHJldHVybiBcIlRFWFQgTVVTVCBCRSBJTiBCWVRFIElOQ1JFTUVOVFNcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0ckJpbkxlbiA9IHNyY1N0cmluZy5sZW5ndGggKiA0O1xuICAgICAgICB0aGlzLnN0clRvSGFzaCA9IGhleDJiaW5iKHNyY1N0cmluZyk7XG4gICAgICB9IGVsc2UgaWYgKChcIkFTQ0lJXCIgPT09IGlucHV0Rm9ybWF0KSB8fFxuICAgICAgICAoJ3VuZGVmaW5lZCcgPT09IHR5cGVvZihpbnB1dEZvcm1hdCkpKSB7XG4gICAgICAgIHRoaXMuc3RyQmluTGVuID0gc3JjU3RyaW5nLmxlbmd0aCAqIGNoYXJTaXplO1xuICAgICAgICB0aGlzLnN0clRvSGFzaCA9IHN0cjJiaW5iKHNyY1N0cmluZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gXCJVTktOT1dOIFRFWFQgSU5QVVQgVFlQRVwiO1xuICAgICAgfVxuICAgIH07XG5cbiAganNTSEEucHJvdG90eXBlID0ge1xuICAgIC8qXG4gICAgICogUmV0dXJucyB0aGUgZGVzaXJlZCBTSEEgaGFzaCBvZiB0aGUgc3RyaW5nIHNwZWNpZmllZCBhdCBpbnN0YW50aWF0aW9uXG4gICAgICogdXNpbmcgdGhlIHNwZWNpZmllZCBwYXJhbWV0ZXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gdmFyaWFudCBUaGUgZGVzaXJlZCBTSEEgdmFyaWFudCAoU0hBLTEsIFNIQS0yMjQsXG4gICAgICpcdCBTSEEtMjU2LCBTSEEtMzg0LCBvciBTSEEtNTEyKVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBmb3JtYXQgVGhlIGRlc2lyZWQgb3V0cHV0IGZvcm1hdHRpbmcgKEI2NCBvciBIRVgpXG4gICAgICogQHJldHVybiBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBoYXNoIGluIHRoZSBmb3JtYXQgc3BlY2lmaWVkXG4gICAgICovXG4gICAgZ2V0SGFzaDogZnVuY3Rpb24odmFyaWFudCwgZm9ybWF0KSB7XG4gICAgICB2YXIgZm9ybWF0RnVuYyA9IG51bGwsXG4gICAgICAgIG1lc3NhZ2UgPSB0aGlzLnN0clRvSGFzaC5zbGljZSgpO1xuXG4gICAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgICBjYXNlIFwiSEVYXCI6XG4gICAgICAgICAgZm9ybWF0RnVuYyA9IGJpbmIyaGV4O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQjY0XCI6XG4gICAgICAgICAgZm9ybWF0RnVuYyA9IGJpbmIyYjY0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQVNDSUlcIjpcbiAgICAgICAgICBmb3JtYXRGdW5jID0gYmluYjJzdHI7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIFwiRk9STUFUIE5PVCBSRUNPR05JWkVEXCI7XG4gICAgICB9XG5cbiAgICAgIHN3aXRjaCAodmFyaWFudCkge1xuICAgICAgICBjYXNlIFwiU0hBLTFcIjpcbiAgICAgICAgICBpZiAobnVsbCA9PT0gdGhpcy5zaGExKSB7XG4gICAgICAgICAgICB0aGlzLnNoYTEgPSBjb3JlU0hBMShtZXNzYWdlLCB0aGlzLnN0ckJpbkxlbik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhMSk7XG4gICAgICAgIGNhc2UgXCJTSEEtMjI0XCI6XG4gICAgICAgICAgaWYgKG51bGwgPT09IHRoaXMuc2hhMjI0KSB7XG4gICAgICAgICAgICB0aGlzLnNoYTIyNCA9IGNvcmVTSEEyKG1lc3NhZ2UsIHRoaXMuc3RyQmluTGVuLCB2YXJpYW50KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmModGhpcy5zaGEyMjQpO1xuICAgICAgICBjYXNlIFwiU0hBLTI1NlwiOlxuICAgICAgICAgIGlmIChudWxsID09PSB0aGlzLnNoYTI1Nikge1xuICAgICAgICAgICAgdGhpcy5zaGEyNTYgPSBjb3JlU0hBMihtZXNzYWdlLCB0aGlzLnN0ckJpbkxlbiwgdmFyaWFudCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmb3JtYXRGdW5jKHRoaXMuc2hhMjU2KTtcbiAgICAgICAgY2FzZSBcIlNIQS0zODRcIjpcbiAgICAgICAgICBpZiAobnVsbCA9PT0gdGhpcy5zaGEzODQpIHtcbiAgICAgICAgICAgIHRoaXMuc2hhMzg0ID0gY29yZVNIQTIobWVzc2FnZSwgdGhpcy5zdHJCaW5MZW4sIHZhcmlhbnQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gZm9ybWF0RnVuYyh0aGlzLnNoYTM4NCk7XG4gICAgICAgIGNhc2UgXCJTSEEtNTEyXCI6XG4gICAgICAgICAgaWYgKG51bGwgPT09IHRoaXMuc2hhNTEyKSB7XG4gICAgICAgICAgICB0aGlzLnNoYTUxMiA9IGNvcmVTSEEyKG1lc3NhZ2UsIHRoaXMuc3RyQmluTGVuLCB2YXJpYW50KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmModGhpcy5zaGE1MTIpO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiBcIkhBU0ggTk9UIFJFQ09HTklaRURcIjtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgLypcbiAgICAgKiBSZXR1cm5zIHRoZSBkZXNpcmVkIEhNQUMgb2YgdGhlIHN0cmluZyBzcGVjaWZpZWQgYXQgaW5zdGFudGlhdGlvblxuICAgICAqIHVzaW5nIHRoZSBrZXkgYW5kIHZhcmlhbnQgcGFyYW0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5IFRoZSBrZXkgdXNlZCB0byBjYWxjdWxhdGUgdGhlIEhNQUNcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXRGb3JtYXQgVGhlIGZvcm1hdCBvZiBrZXksIEFTQ0lJIG9yIEhFWFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSB2YXJpYW50IFRoZSBkZXNpcmVkIFNIQSB2YXJpYW50IChTSEEtMSwgU0hBLTIyNCxcbiAgICAgKlx0IFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIpXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG91dHB1dEZvcm1hdCBUaGUgZGVzaXJlZCBvdXRwdXQgZm9ybWF0dGluZ1xuICAgICAqXHQgKEI2NCBvciBIRVgpXG4gICAgICogQHJldHVybiBUaGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBoYXNoIGluIHRoZSBmb3JtYXQgc3BlY2lmaWVkXG4gICAgICovXG4gICAgZ2V0SE1BQzogZnVuY3Rpb24oa2V5LCBpbnB1dEZvcm1hdCwgdmFyaWFudCwgb3V0cHV0Rm9ybWF0KSB7XG4gICAgICB2YXIgZm9ybWF0RnVuYywga2V5VG9Vc2UsIGJsb2NrQnl0ZVNpemUsIGJsb2NrQml0U2l6ZSwgaSxcbiAgICAgICAgcmV0VmFsLCBsYXN0QXJyYXlJbmRleCwga2V5QmluTGVuLCBoYXNoQml0U2l6ZSxcbiAgICAgICAga2V5V2l0aElQYWQgPSBbXSxcbiAgICAgICAga2V5V2l0aE9QYWQgPSBbXTtcblxuICAgICAgLyogVmFsaWRhdGUgdGhlIG91dHB1dCBmb3JtYXQgc2VsZWN0aW9uICovXG4gICAgICBzd2l0Y2ggKG91dHB1dEZvcm1hdCkge1xuICAgICAgICBjYXNlIFwiSEVYXCI6XG4gICAgICAgICAgZm9ybWF0RnVuYyA9IGJpbmIyaGV4O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQjY0XCI6XG4gICAgICAgICAgZm9ybWF0RnVuYyA9IGJpbmIyYjY0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQVNDSUlcIjpcbiAgICAgICAgICBmb3JtYXRGdW5jID0gYmluYjJzdHI7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIFwiRk9STUFUIE5PVCBSRUNPR05JWkVEXCI7XG4gICAgICB9XG5cbiAgICAgIC8qIFZhbGlkYXRlIHRoZSBoYXNoIHZhcmlhbnQgc2VsZWN0aW9uIGFuZCBzZXQgbmVlZGVkIHZhcmlhYmxlcyAqL1xuICAgICAgc3dpdGNoICh2YXJpYW50KSB7XG4gICAgICAgIGNhc2UgXCJTSEEtMVwiOlxuICAgICAgICAgIGJsb2NrQnl0ZVNpemUgPSA2NDtcbiAgICAgICAgICBoYXNoQml0U2l6ZSA9IDE2MDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcIlNIQS0yMjRcIjpcbiAgICAgICAgICBibG9ja0J5dGVTaXplID0gNjQ7XG4gICAgICAgICAgaGFzaEJpdFNpemUgPSAyMjQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJTSEEtMjU2XCI6XG4gICAgICAgICAgYmxvY2tCeXRlU2l6ZSA9IDY0O1xuICAgICAgICAgIGhhc2hCaXRTaXplID0gMjU2O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiU0hBLTM4NFwiOlxuICAgICAgICAgIGJsb2NrQnl0ZVNpemUgPSAxMjg7XG4gICAgICAgICAgaGFzaEJpdFNpemUgPSAzODQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJTSEEtNTEyXCI6XG4gICAgICAgICAgYmxvY2tCeXRlU2l6ZSA9IDEyODtcbiAgICAgICAgICBoYXNoQml0U2l6ZSA9IDUxMjtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gXCJIQVNIIE5PVCBSRUNPR05JWkVEXCI7XG4gICAgICB9XG5cbiAgICAgIC8qIFZhbGlkYXRlIGlucHV0IGZvcm1hdCBzZWxlY3Rpb24gKi9cbiAgICAgIGlmIChcIkhFWFwiID09PSBpbnB1dEZvcm1hdCkge1xuICAgICAgICAvKiBOaWJibGVzIG11c3QgY29tZSBpbiBwYWlycyAqL1xuICAgICAgICBpZiAoMCAhPT0gKGtleS5sZW5ndGggJSAyKSkge1xuICAgICAgICAgIHJldHVybiBcIktFWSBNVVNUIEJFIElOIEJZVEUgSU5DUkVNRU5UU1wiO1xuICAgICAgICB9XG4gICAgICAgIGtleVRvVXNlID0gaGV4MmJpbmIoa2V5KTtcbiAgICAgICAga2V5QmluTGVuID0ga2V5Lmxlbmd0aCAqIDQ7XG4gICAgICB9IGVsc2UgaWYgKFwiQVNDSUlcIiA9PT0gaW5wdXRGb3JtYXQpIHtcbiAgICAgICAga2V5VG9Vc2UgPSBzdHIyYmluYihrZXkpO1xuICAgICAgICBrZXlCaW5MZW4gPSBrZXkubGVuZ3RoICogY2hhclNpemU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gXCJVTktOT1dOIEtFWSBJTlBVVCBUWVBFXCI7XG4gICAgICB9XG5cbiAgICAgIC8qIFRoZXNlIGFyZSB1c2VkIG11bHRpcGxlIHRpbWVzLCBjYWxjdWxhdGUgYW5kIHN0b3JlIHRoZW0gKi9cbiAgICAgIGJsb2NrQml0U2l6ZSA9IGJsb2NrQnl0ZVNpemUgKiA4O1xuICAgICAgbGFzdEFycmF5SW5kZXggPSAoYmxvY2tCeXRlU2l6ZSAvIDQpIC0gMTtcblxuICAgICAgLyogRmlndXJlIG91dCB3aGF0IHRvIGRvIHdpdGggdGhlIGtleSBiYXNlZCBvbiBpdHMgc2l6ZSByZWxhdGl2ZSB0b1xuICAgICAgICogdGhlIGhhc2gncyBibG9jayBzaXplICovXG4gICAgICBpZiAoYmxvY2tCeXRlU2l6ZSA8IChrZXlCaW5MZW4gLyA4KSkge1xuICAgICAgICBpZiAoXCJTSEEtMVwiID09PSB2YXJpYW50KSB7XG4gICAgICAgICAga2V5VG9Vc2UgPSBjb3JlU0hBMShrZXlUb1VzZSwga2V5QmluTGVuKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXlUb1VzZSA9IGNvcmVTSEEyKGtleVRvVXNlLCBrZXlCaW5MZW4sIHZhcmlhbnQpO1xuICAgICAgICB9XG4gICAgICAgIC8qIEZvciBhbGwgdmFyaWFudHMsIHRoZSBibG9jayBzaXplIGlzIGJpZ2dlciB0aGFuIHRoZSBvdXRwdXRcbiAgICAgICAgICogc2l6ZSBzbyB0aGVyZSB3aWxsIG5ldmVyIGJlIGEgdXNlZnVsIGJ5dGUgYXQgdGhlIGVuZCBvZiB0aGVcbiAgICAgICAgICogc3RyaW5nICovXG4gICAgICAgIGtleVRvVXNlW2xhc3RBcnJheUluZGV4XSAmPSAweEZGRkZGRjAwO1xuICAgICAgfSBlbHNlIGlmIChibG9ja0J5dGVTaXplID4gKGtleUJpbkxlbiAvIDgpKSB7XG4gICAgICAgIC8qIElmIHRoZSBibG9ja0J5dGVTaXplIGlzIGdyZWF0ZXIgdGhhbiB0aGUga2V5IGxlbmd0aCwgdGhlcmVcbiAgICAgICAgICogd2lsbCBhbHdheXMgYmUgYXQgTEVBU1Qgb25lIFwidXNlbGVzc1wiIGJ5dGUgYXQgdGhlIGVuZCBvZiB0aGVcbiAgICAgICAgICogc3RyaW5nICovXG4gICAgICAgIGtleVRvVXNlW2xhc3RBcnJheUluZGV4XSAmPSAweEZGRkZGRjAwO1xuICAgICAgfVxuXG4gICAgICAvKiBDcmVhdGUgaXBhZCBhbmQgb3BhZCAqL1xuICAgICAgZm9yIChpID0gMDsgaSA8PSBsYXN0QXJyYXlJbmRleDsgaSArPSAxKSB7XG4gICAgICAgIGtleVdpdGhJUGFkW2ldID0ga2V5VG9Vc2VbaV0gXiAweDM2MzYzNjM2O1xuICAgICAgICBrZXlXaXRoT1BhZFtpXSA9IGtleVRvVXNlW2ldIF4gMHg1QzVDNUM1QztcbiAgICAgIH1cblxuICAgICAgLyogQ2FsY3VsYXRlIHRoZSBITUFDICovXG4gICAgICBpZiAoXCJTSEEtMVwiID09PSB2YXJpYW50KSB7XG4gICAgICAgIHJldFZhbCA9IGNvcmVTSEExKFxuICAgICAgICAgIGtleVdpdGhJUGFkLmNvbmNhdCh0aGlzLnN0clRvSGFzaCksXG4gICAgICAgICAgYmxvY2tCaXRTaXplICsgdGhpcy5zdHJCaW5MZW4pO1xuICAgICAgICByZXRWYWwgPSBjb3JlU0hBMShcbiAgICAgICAgICBrZXlXaXRoT1BhZC5jb25jYXQocmV0VmFsKSxcbiAgICAgICAgICBibG9ja0JpdFNpemUgKyBoYXNoQml0U2l6ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXRWYWwgPSBjb3JlU0hBMihcbiAgICAgICAgICBrZXlXaXRoSVBhZC5jb25jYXQodGhpcy5zdHJUb0hhc2gpLFxuICAgICAgICAgIGJsb2NrQml0U2l6ZSArIHRoaXMuc3RyQmluTGVuLCB2YXJpYW50KTtcbiAgICAgICAgcmV0VmFsID0gY29yZVNIQTIoXG4gICAgICAgICAga2V5V2l0aE9QYWQuY29uY2F0KHJldFZhbCksXG4gICAgICAgICAgYmxvY2tCaXRTaXplICsgaGFzaEJpdFNpemUsIHZhcmlhbnQpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gKGZvcm1hdEZ1bmMocmV0VmFsKSk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBqc1NIQTtcbn0oKSk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBzaGExOiBmdW5jdGlvbihzdHIpIHtcbiAgICB2YXIgc2hhT2JqID0gbmV3IGpzU0hBKHN0ciwgXCJBU0NJSVwiKTtcbiAgICByZXR1cm4gc2hhT2JqLmdldEhhc2goXCJTSEEtMVwiLCBcIkFTQ0lJXCIpO1xuICB9LFxuICBzaGEyMjQ6IGZ1bmN0aW9uKHN0cikge1xuICAgIHZhciBzaGFPYmogPSBuZXcganNTSEEoc3RyLCBcIkFTQ0lJXCIpO1xuICAgIHJldHVybiBzaGFPYmouZ2V0SGFzaChcIlNIQS0yMjRcIiwgXCJBU0NJSVwiKTtcbiAgfSxcbiAgc2hhMjU2OiBmdW5jdGlvbihzdHIpIHtcbiAgICB2YXIgc2hhT2JqID0gbmV3IGpzU0hBKHN0ciwgXCJBU0NJSVwiKTtcbiAgICByZXR1cm4gc2hhT2JqLmdldEhhc2goXCJTSEEtMjU2XCIsIFwiQVNDSUlcIik7XG4gIH0sXG4gIHNoYTM4NDogZnVuY3Rpb24oc3RyKSB7XG4gICAgdmFyIHNoYU9iaiA9IG5ldyBqc1NIQShzdHIsIFwiQVNDSUlcIik7XG4gICAgcmV0dXJuIHNoYU9iai5nZXRIYXNoKFwiU0hBLTM4NFwiLCBcIkFTQ0lJXCIpO1xuXG4gIH0sXG4gIHNoYTUxMjogZnVuY3Rpb24oc3RyKSB7XG4gICAgdmFyIHNoYU9iaiA9IG5ldyBqc1NIQShzdHIsIFwiQVNDSUlcIik7XG4gICAgcmV0dXJuIHNoYU9iai5nZXRIYXNoKFwiU0hBLTUxMlwiLCBcIkFTQ0lJXCIpO1xuICB9XG59XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcbiAgY2lwaGVyOiByZXF1aXJlKCcuL2NpcGhlcicpLFxuICBoYXNoOiByZXF1aXJlKCcuL2hhc2gnKSxcbiAgY2ZiOiByZXF1aXJlKCcuL2NmYi5qcycpLFxuICBwdWJsaWNLZXk6IHJlcXVpcmUoJy4vcHVibGljX2tleScpLFxuICBzaWduYXR1cmU6IHJlcXVpcmUoJy4vc2lnbmF0dXJlLmpzJyksXG4gIHJhbmRvbTogcmVxdWlyZSgnLi9yYW5kb20uanMnKSxcbiAgcGtjczE6IHJlcXVpcmUoJy4vcGtjczEuanMnKVxuXG59XG5cbnZhciBjcnlwdG8gPSByZXF1aXJlKCcuL2NyeXB0by5qcycpO1xuXG5mb3IgKHZhciBpIGluIGNyeXB0bylcbiAgbW9kdWxlLmV4cG9ydHNbaV0gPSBjcnlwdG9baV07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKipcbiAqIEFTTjEgb2JqZWN0IGlkZW50aWZpZXJzIGZvciBoYXNoZXMgKFNlZSBSRkM0ODgwIDUuMi4yKVxuICovXG5oYXNoX2hlYWRlcnMgPSBuZXcgQXJyYXkoKTtcbmhhc2hfaGVhZGVyc1sxXSA9IFsweDMwLCAweDIwLCAweDMwLCAweDBjLCAweDA2LCAweDA4LCAweDJhLCAweDg2LCAweDQ4LCAweDg2LCAweGY3LCAweDBkLCAweDAyLCAweDA1LCAweDA1LCAweDAwLCAweDA0LFxuICAgIDB4MTBcbl07XG5oYXNoX2hlYWRlcnNbM10gPSBbMHgzMCwgMHgyMSwgMHgzMCwgMHgwOSwgMHgwNiwgMHgwNSwgMHgyQiwgMHgyNCwgMHgwMywgMHgwMiwgMHgwMSwgMHgwNSwgMHgwMCwgMHgwNCwgMHgxNF07XG5oYXNoX2hlYWRlcnNbMl0gPSBbMHgzMCwgMHgyMSwgMHgzMCwgMHgwOSwgMHgwNiwgMHgwNSwgMHgyYiwgMHgwZSwgMHgwMywgMHgwMiwgMHgxYSwgMHgwNSwgMHgwMCwgMHgwNCwgMHgxNF07XG5oYXNoX2hlYWRlcnNbOF0gPSBbMHgzMCwgMHgzMSwgMHgzMCwgMHgwZCwgMHgwNiwgMHgwOSwgMHg2MCwgMHg4NiwgMHg0OCwgMHgwMSwgMHg2NSwgMHgwMywgMHgwNCwgMHgwMiwgMHgwMSwgMHgwNSwgMHgwMCxcbiAgICAweDA0LCAweDIwXG5dO1xuaGFzaF9oZWFkZXJzWzldID0gWzB4MzAsIDB4NDEsIDB4MzAsIDB4MGQsIDB4MDYsIDB4MDksIDB4NjAsIDB4ODYsIDB4NDgsIDB4MDEsIDB4NjUsIDB4MDMsIDB4MDQsIDB4MDIsIDB4MDIsIDB4MDUsIDB4MDAsXG4gICAgMHgwNCwgMHgzMFxuXTtcbmhhc2hfaGVhZGVyc1sxMF0gPSBbMHgzMCwgMHg1MSwgMHgzMCwgMHgwZCwgMHgwNiwgMHgwOSwgMHg2MCwgMHg4NiwgMHg0OCwgMHgwMSwgMHg2NSwgMHgwMywgMHgwNCwgMHgwMiwgMHgwMywgMHgwNSxcbiAgICAweDAwLCAweDA0LCAweDQwXG5dO1xuaGFzaF9oZWFkZXJzWzExXSA9IFsweDMwLCAweDMxLCAweDMwLCAweDBkLCAweDA2LCAweDA5LCAweDYwLCAweDg2LCAweDQ4LCAweDAxLCAweDY1LCAweDAzLCAweDA0LCAweDAyLCAweDA0LCAweDA1LFxuICAgIDB4MDAsIDB4MDQsIDB4MUNcbl07XG5cblxudmFyIGNyeXB0byA9IHJlcXVpcmUoJy4vY3J5cHRvLmpzJyksXG4gIHJhbmRvbSA9IHJlcXVpcmUoJy4vcmFuZG9tLmpzJyksXG4gIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG4gIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL3B1YmxpY19rZXkvanNibi5qcycpLFxuICBoYXNoID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBlbWU6IHtcbiAgICAvKipcbiAgICAgKiBjcmVhdGUgYSBFTUUtUEtDUzEtdjFfNSBwYWRkaW5nIChTZWUgUkZDNDg4MCAxMy4xLjEpXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgbWVzc2FnZSB0byBiZSBwYWRkZWRcbiAgICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBMZW5ndGggdG8gdGhlIHJlc3VsdGluZyBtZXNzYWdlXG4gICAgICogQHJldHVybiB7U3RyaW5nfSBFTUUtUEtDUzEgcGFkZGVkIG1lc3NhZ2VcbiAgICAgKi9cbiAgICBlbmNvZGU6IGZ1bmN0aW9uKG1lc3NhZ2UsIGxlbmd0aCkge1xuICAgICAgaWYgKG1lc3NhZ2UubGVuZ3RoID4gbGVuZ3RoIC0gMTEpXG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIHZhciByZXN1bHQgPSBcIlwiO1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCk7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgyKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoIC0gbWVzc2FnZS5sZW5ndGggLSAzOyBpKyspIHtcbiAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUocmFuZG9tLmdldFBzZXVkb1JhbmRvbSgxLCAyNTUpKTtcbiAgICAgIH1cbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuICAgICAgcmVzdWx0ICs9IG1lc3NhZ2U7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBkZWNvZGVzIGEgRU1FLVBLQ1MxLXYxXzUgcGFkZGluZyAoU2VlIFJGQzQ4ODAgMTMuMS4yKVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIEVNRS1QS0NTMSBwYWRkZWQgbWVzc2FnZVxuICAgICAqIEByZXR1cm4ge1N0cmluZ30gZGVjb2RlZCBtZXNzYWdlIFxuICAgICAqL1xuICAgIGRlY29kZTogZnVuY3Rpb24obWVzc2FnZSwgbGVuKSB7XG4gICAgICBpZiAobWVzc2FnZS5sZW5ndGggPCBsZW4pXG4gICAgICAgIG1lc3NhZ2UgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApICsgbWVzc2FnZTtcbiAgICAgIGlmIChtZXNzYWdlLmxlbmd0aCA8IDEyIHx8IG1lc3NhZ2UuY2hhckNvZGVBdCgwKSAhPSAwIHx8IG1lc3NhZ2UuY2hhckNvZGVBdCgxKSAhPSAyKVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB2YXIgaSA9IDI7XG4gICAgICB3aGlsZSAobWVzc2FnZS5jaGFyQ29kZUF0KGkpICE9IDAgJiYgbWVzc2FnZS5sZW5ndGggPiBpKVxuICAgICAgICBpKys7XG4gICAgICByZXR1cm4gbWVzc2FnZS5zdWJzdHJpbmcoaSArIDEsIG1lc3NhZ2UubGVuZ3RoKTtcbiAgICB9LFxuICB9LFxuXG4gIGVtc2E6IHtcblxuICAgIC8qKlxuICAgICAqIGNyZWF0ZSBhIEVNU0EtUEtDUzEtdjFfNSBwYWRkaW5nIChTZWUgUkZDNDg4MCAxMy4xLjMpXG4gICAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEhhc2ggYWxnb3JpdGhtIHR5cGUgdXNlZFxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIERhdGEgdG8gYmUgaGFzaGVkXG4gICAgICogQHBhcmFtIHtJbnRlZ2VyfSBrZXlsZW5ndGggS2V5IHNpemUgb2YgdGhlIHB1YmxpYyBtcGkgaW4gYnl0ZXNcbiAgICAgKiBAcmV0dXJucyB7U3RyaW5nfSBIYXNoY29kZSB3aXRoIHBrY3MxcGFkZGluZyBhcyBzdHJpbmdcbiAgICAgKi9cbiAgICBlbmNvZGU6IGZ1bmN0aW9uKGFsZ28sIGRhdGEsIGtleWxlbmd0aCkge1xuICAgICAgdmFyIGRhdGEyID0gXCJcIjtcbiAgICAgIGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHgwMCk7XG4gICAgICBkYXRhMiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4MDEpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAoa2V5bGVuZ3RoIC0gaGFzaF9oZWFkZXJzW2FsZ29dLmxlbmd0aCAtIDMgLVxuICAgICAgICBoYXNoLmdldEhhc2hCeXRlTGVuZ3RoKGFsZ28pKTsgaSsrKVxuXG4gICAgICAgIGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhmZik7XG5cbiAgICAgIGRhdGEyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHgwMCk7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaGFzaF9oZWFkZXJzW2FsZ29dLmxlbmd0aDsgaSsrKVxuICAgICAgICBkYXRhMiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGhhc2hfaGVhZGVyc1thbGdvXVtpXSk7XG5cbiAgICAgIGRhdGEyICs9IGhhc2guZGlnZXN0KGFsZ28sIGRhdGEpO1xuICAgICAgcmV0dXJuIG5ldyBCaWdJbnRlZ2VyKHV0aWwuaGV4c3RyZHVtcChkYXRhMiksIDE2KTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogZXh0cmFjdCB0aGUgaGFzaCBvdXQgb2YgYW4gRU1TQS1QS0NTMS12MS41IHBhZGRpbmcgKFNlZSBSRkM0ODgwIDEzLjEuMykgXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgSGFzaCBpbiBwa2NzMSBlbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSBoYXNoIGFzIHN0cmluZ1xuICAgICAqL1xuICAgIGRlY29kZTogZnVuY3Rpb24oYWxnbywgZGF0YSkge1xuICAgICAgdmFyIGkgPSAwO1xuICAgICAgaWYgKGRhdGEuY2hhckNvZGVBdCgwKSA9PSAwKSBpKys7XG4gICAgICBlbHNlIGlmIChkYXRhLmNoYXJDb2RlQXQoMCkgIT0gMSkgcmV0dXJuIC0xO1xuICAgICAgZWxzZSBpKys7XG5cbiAgICAgIHdoaWxlIChkYXRhLmNoYXJDb2RlQXQoaSkgPT0gMHhGRikgaSsrO1xuICAgICAgaWYgKGRhdGEuY2hhckNvZGVBdChpKyspICE9IDApIHJldHVybiAtMTtcbiAgICAgIHZhciBqID0gMDtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBoYXNoX2hlYWRlcnNbYWxnb10ubGVuZ3RoICYmIGogKyBpIDwgZGF0YS5sZW5ndGg7IGorKykge1xuICAgICAgICBpZiAoZGF0YS5jaGFyQ29kZUF0KGogKyBpKSAhPSBoYXNoX2hlYWRlcnNbYWxnb11bal0pIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIGkgKz0gajtcbiAgICAgIGlmIChkYXRhLnN1YnN0cmluZyhpKS5sZW5ndGggPCBoYXNoLmdldEhhc2hCeXRlTGVuZ3RoKGFsZ28pKSByZXR1cm4gLTE7XG4gICAgICByZXR1cm4gZGF0YS5zdWJzdHJpbmcoaSk7XG4gICAgfVxuICB9XG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuLy9cbi8vIEEgRGlnaXRhbCBzaWduYXR1cmUgYWxnb3JpdGhtIGltcGxlbWVudGF0aW9uXG5cbnZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnLi9qc2JuLmpzJyksXG4gIHJhbmRvbSA9IHJlcXVpcmUoJy4uL3JhbmRvbS5qcycpLFxuICBoYXNoTW9kdWxlID0gcmVxdWlyZSgnLi4vaGFzaCcpLFxuICB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG5mdW5jdGlvbiBEU0EoKSB7XG4gIC8vIHMxID0gKChnKipzKSBtb2QgcCkgbW9kIHFcbiAgLy8gczEgPSAoKHMqKi0xKSooc2hhLTEobSkrKHMxKngpIG1vZCBxKVxuICBmdW5jdGlvbiBzaWduKGhhc2hhbGdvLCBtLCBnLCBwLCBxLCB4KSB7XG4gICAgLy8gSWYgdGhlIG91dHB1dCBzaXplIG9mIHRoZSBjaG9zZW4gaGFzaCBpcyBsYXJnZXIgdGhhbiB0aGUgbnVtYmVyIG9mXG4gICAgLy8gYml0cyBvZiBxLCB0aGUgaGFzaCByZXN1bHQgaXMgdHJ1bmNhdGVkIHRvIGZpdCBieSB0YWtpbmcgdGhlIG51bWJlclxuICAgIC8vIG9mIGxlZnRtb3N0IGJpdHMgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBiaXRzIG9mIHEuICBUaGlzIChwb3NzaWJseVxuICAgIC8vIHRydW5jYXRlZCkgaGFzaCBmdW5jdGlvbiByZXN1bHQgaXMgdHJlYXRlZCBhcyBhIG51bWJlciBhbmQgdXNlZFxuICAgIC8vIGRpcmVjdGx5IGluIHRoZSBEU0Egc2lnbmF0dXJlIGFsZ29yaXRobS5cbiAgICB2YXIgaGFzaGVkX2RhdGEgPSB1dGlsLmdldExlZnROQml0cyhoYXNoTW9kdWxlLmRpZ2VzdChoYXNoYWxnbywgbSksIHEuYml0TGVuZ3RoKCkpO1xuICAgIHZhciBoYXNoID0gbmV3IEJpZ0ludGVnZXIodXRpbC5oZXhzdHJkdW1wKGhhc2hlZF9kYXRhKSwgMTYpO1xuICAgIHZhciBrID0gcmFuZG9tLmdldFJhbmRvbUJpZ0ludGVnZXJJblJhbmdlKEJpZ0ludGVnZXIuT05FLmFkZChCaWdJbnRlZ2VyLk9ORSksIHEuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpKTtcbiAgICB2YXIgczEgPSAoZy5tb2RQb3coaywgcCkpLm1vZChxKTtcbiAgICB2YXIgczIgPSAoay5tb2RJbnZlcnNlKHEpLm11bHRpcGx5KGhhc2guYWRkKHgubXVsdGlwbHkoczEpKSkpLm1vZChxKTtcbiAgICB2YXIgcmVzdWx0ID0gbmV3IEFycmF5KCk7XG4gICAgcmVzdWx0WzBdID0gczEudG9NUEkoKTtcbiAgICByZXN1bHRbMV0gPSBzMi50b01QSSgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBzZWxlY3RfaGFzaF9hbGdvcml0aG0ocSkge1xuICAgIHZhciB1c2Vyc2V0dGluZyA9IG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5wcmVmZXJfaGFzaF9hbGdvcml0aG07XG4gICAgLypcbiAgICAgKiAxMDI0LWJpdCBrZXksIDE2MC1iaXQgcSwgU0hBLTEsIFNIQS0yMjQsIFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIgaGFzaFxuICAgICAqIDIwNDgtYml0IGtleSwgMjI0LWJpdCBxLCBTSEEtMjI0LCBTSEEtMjU2LCBTSEEtMzg0LCBvciBTSEEtNTEyIGhhc2hcbiAgICAgKiAyMDQ4LWJpdCBrZXksIDI1Ni1iaXQgcSwgU0hBLTI1NiwgU0hBLTM4NCwgb3IgU0hBLTUxMiBoYXNoXG4gICAgICogMzA3Mi1iaXQga2V5LCAyNTYtYml0IHEsIFNIQS0yNTYsIFNIQS0zODQsIG9yIFNIQS01MTIgaGFzaFxuICAgICAqL1xuICAgIHN3aXRjaCAoTWF0aC5yb3VuZChxLmJpdExlbmd0aCgpIC8gOCkpIHtcbiAgICAgIGNhc2UgMjA6XG4gICAgICAgIC8vIDEwMjQgYml0XG4gICAgICAgIGlmICh1c2Vyc2V0dGluZyAhPSAyICYmXG4gICAgICAgICAgdXNlcnNldHRpbmcgPiAxMSAmJlxuICAgICAgICAgIHVzZXJzZXR0aW5nICE9IDEwICYmXG4gICAgICAgICAgdXNlcnNldHRpbmcgPCA4KVxuICAgICAgICAgIHJldHVybiAyOyAvLyBwcmVmZXIgc2hhMVxuICAgICAgICByZXR1cm4gdXNlcnNldHRpbmc7XG4gICAgICBjYXNlIDI4OlxuICAgICAgICAvLyAyMDQ4IGJpdFxuICAgICAgICBpZiAodXNlcnNldHRpbmcgPiAxMSAmJlxuICAgICAgICAgIHVzZXJzZXR0aW5nIDwgOClcbiAgICAgICAgICByZXR1cm4gMTE7XG4gICAgICAgIHJldHVybiB1c2Vyc2V0dGluZztcbiAgICAgIGNhc2UgMzI6XG4gICAgICAgIC8vIDQwOTYgYml0IC8vIHByZWZlciBzaGEyMjRcbiAgICAgICAgaWYgKHVzZXJzZXR0aW5nID4gMTAgJiZcbiAgICAgICAgICB1c2Vyc2V0dGluZyA8IDgpXG4gICAgICAgICAgcmV0dXJuIDg7IC8vIHByZWZlciBzaGEyNTZcbiAgICAgICAgcmV0dXJuIHVzZXJzZXR0aW5nO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdXRpbC5wcmludF9kZWJ1ZyhcIkRTQSBzZWxlY3QgaGFzaCBhbGdvcml0aG06IHJldHVybmluZyBudWxsIGZvciBhbiB1bmtub3duIGxlbmd0aCBvZiBxXCIpO1xuICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgIH1cbiAgfVxuICB0aGlzLnNlbGVjdF9oYXNoX2FsZ29yaXRobSA9IHNlbGVjdF9oYXNoX2FsZ29yaXRobTtcblxuICBmdW5jdGlvbiB2ZXJpZnkoaGFzaGFsZ28sIHMxLCBzMiwgbSwgcCwgcSwgZywgeSkge1xuICAgIHZhciBoYXNoZWRfZGF0YSA9IHV0aWwuZ2V0TGVmdE5CaXRzKGhhc2hNb2R1bGUuZGlnZXN0KGhhc2hhbGdvLCBtKSwgcS5iaXRMZW5ndGgoKSk7XG4gICAgdmFyIGhhc2ggPSBuZXcgQmlnSW50ZWdlcih1dGlsLmhleHN0cmR1bXAoaGFzaGVkX2RhdGEpLCAxNik7XG4gICAgaWYgKEJpZ0ludGVnZXIuWkVSTy5jb21wYXJlVG8oczEpID4gMCB8fFxuICAgICAgczEuY29tcGFyZVRvKHEpID4gMCB8fFxuICAgICAgQmlnSW50ZWdlci5aRVJPLmNvbXBhcmVUbyhzMikgPiAwIHx8XG4gICAgICBzMi5jb21wYXJlVG8ocSkgPiAwKSB7XG4gICAgICB1dGlsLnByaW50X2Vycm9yKFwiaW52YWxpZCBEU0EgU2lnbmF0dXJlXCIpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciB3ID0gczIubW9kSW52ZXJzZShxKTtcbiAgICB2YXIgdTEgPSBoYXNoLm11bHRpcGx5KHcpLm1vZChxKTtcbiAgICB2YXIgdTIgPSBzMS5tdWx0aXBseSh3KS5tb2QocSk7XG4gICAgcmV0dXJuIGcubW9kUG93KHUxLCBwKS5tdWx0aXBseSh5Lm1vZFBvdyh1MiwgcCkpLm1vZChwKS5tb2QocSk7XG4gIH1cblxuICAvKlxuXHQgKiB1bnVzZWQgY29kZS4gVGhpcyBjYW4gYmUgdXNlZCBhcyBhIHN0YXJ0IHRvIHdyaXRlIGEga2V5IGdlbmVyYXRvclxuXHQgKiBmdW5jdGlvbi5cblx0XG5cdGZ1bmN0aW9uIGdlbmVyYXRlS2V5KGJpdGNvdW50KSB7XG5cdCAgICB2YXIgcWkgPSBuZXcgQmlnSW50ZWdlcihiaXRjb3VudCwgcHJpbWVDZW50ZXJpZSk7XG5cdCAgICB2YXIgcGkgPSBnZW5lcmF0ZVAocSwgNTEyKTtcblx0ICAgIHZhciBnaSA9IGdlbmVyYXRlRyhwLCBxLCBiaXRjb3VudCk7XG5cdCAgICB2YXIgeGk7XG5cdCAgICBkbyB7XG5cdCAgICAgICAgeGkgPSBuZXcgQmlnSW50ZWdlcihxLmJpdENvdW50KCksIHJhbmQpO1xuXHQgICAgfSB3aGlsZSAoeC5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSAhPSAxICYmIHguY29tcGFyZVRvKHEpICE9IC0xKTtcblx0ICAgIHZhciB5aSA9IGcubW9kUG93KHgsIHApO1xuXHQgICAgcmV0dXJuIHt4OiB4aSwgcTogcWksIHA6IHBpLCBnOiBnaSwgeTogeWl9O1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2VuZXJhdGVQKHEsIGJpdGxlbmd0aCwgcmFuZG9tZm4pIHtcblx0ICAgIGlmIChiaXRsZW5ndGggJSA2NCAhPSAwKSB7XG5cdCAgICBcdHJldHVybiBmYWxzZTtcblx0ICAgIH1cblx0ICAgIHZhciBwVGVtcDtcblx0ICAgIHZhciBwVGVtcDI7XG5cdCAgICBkbyB7XG5cdCAgICAgICAgcFRlbXAgPSByYW5kb21mbihiaXRjb3VudCwgdHJ1ZSk7XG5cdCAgICAgICAgcFRlbXAyID0gcFRlbXAuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpO1xuXHQgICAgICAgIHBUZW1wID0gcFRlbXAuc3VidHJhY3QocFRlbXAyLnJlbWFpbmRlcihxKSk7XG5cdCAgICB9IHdoaWxlICghcFRlbXAuaXNQcm9iYWJsZVByaW1lKHByaW1lQ2VudGVyaWUpIHx8IHBUZW1wLmJpdExlbmd0aCgpICE9IGwpO1xuXHQgICAgcmV0dXJuIHBUZW1wO1xuXHR9XG5cdFxuXHRmdW5jdGlvbiBnZW5lcmF0ZUcocCwgcSwgYml0bGVuZ3RoLCByYW5kb21mbikge1xuXHQgICAgdmFyIGF1eCA9IHAuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpO1xuXHQgICAgdmFyIHBvdyA9IGF1eC5kaXZpZGUocSk7XG5cdCAgICB2YXIgZ1RlbXA7XG5cdCAgICBkbyB7XG5cdCAgICAgICAgZ1RlbXAgPSByYW5kb21mbihiaXRsZW5ndGgpO1xuXHQgICAgfSB3aGlsZSAoZ1RlbXAuY29tcGFyZVRvKGF1eCkgIT0gLTEgJiYgZ1RlbXAuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSAhPSAxKTtcblx0ICAgIHJldHVybiBnVGVtcC5tb2RQb3cocG93LCBwKTtcblx0fVxuXG5cdGZ1bmN0aW9uIGdlbmVyYXRlSyhxLCBiaXRsZW5ndGgsIHJhbmRvbWZuKSB7XG5cdCAgICB2YXIgdGVtcEs7XG5cdCAgICBkbyB7XG5cdCAgICAgICAgdGVtcEsgPSByYW5kb21mbihiaXRsZW5ndGgsIGZhbHNlKTtcblx0ICAgIH0gd2hpbGUgKHRlbXBLLmNvbXBhcmVUbyhxKSAhPSAtMSAmJiB0ZW1wSy5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSAhPSAxKTtcblx0ICAgIHJldHVybiB0ZW1wSztcblx0fVxuXG5cdGZ1bmN0aW9uIGdlbmVyYXRlUihxLHApIHtcblx0ICAgIGsgPSBnZW5lcmF0ZUsocSk7XG5cdCAgICB2YXIgciA9IGcubW9kUG93KGssIHApLm1vZChxKTtcblx0ICAgIHJldHVybiByO1xuXHR9XG5cblx0ZnVuY3Rpb24gZ2VuZXJhdGVTKGhhc2hmbixrLHIsbSxxLHgpIHtcbiAgICAgICAgdmFyIGhhc2ggPSBoYXNoZm4obSk7XG4gICAgICAgIHMgPSAoay5tb2RJbnZlcnNlKHEpLm11bHRpcGx5KGhhc2guYWRkKHgubXVsdGlwbHkocikpKSkubW9kKHEpO1xuXHQgICAgcmV0dXJuIHM7XG5cdH0gKi9cbiAgdGhpcy5zaWduID0gc2lnbjtcbiAgdGhpcy52ZXJpZnkgPSB2ZXJpZnk7XG4gIC8vIHRoaXMuZ2VuZXJhdGUgPSBnZW5lcmF0ZUtleTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBEU0E7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuLy9cbi8vIEVsR2FtYWwgaW1wbGVtZW50YXRpb25cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2pzYm4uanMnKSxcbiAgcmFuZG9tID0gcmVxdWlyZSgnLi4vcmFuZG9tLmpzJyksXG4gIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbmZ1bmN0aW9uIEVsZ2FtYWwoKSB7XG5cbiAgZnVuY3Rpb24gZW5jcnlwdChtLCBnLCBwLCB5KSB7XG4gICAgLy8gIGNob29zZSBrIGluIHsyLC4uLixwLTJ9XG4gICAgdmFyIHR3byA9IEJpZ0ludGVnZXIuT05FLmFkZChCaWdJbnRlZ2VyLk9ORSk7XG4gICAgdmFyIHBNaW51czIgPSBwLnN1YnRyYWN0KHR3byk7XG4gICAgdmFyIGsgPSByYW5kb20uZ2V0UmFuZG9tQmlnSW50ZWdlckluUmFuZ2UodHdvLCBwTWludXMyKTtcbiAgICBrID0gay5tb2QocE1pbnVzMikuYWRkKEJpZ0ludGVnZXIuT05FKTtcbiAgICB2YXIgYyA9IFtdO1xuICAgIGNbMF0gPSBnLm1vZFBvdyhrLCBwKTtcbiAgICBjWzFdID0geS5tb2RQb3coaywgcCkubXVsdGlwbHkobSkubW9kKHApO1xuICAgIHJldHVybiBjO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVjcnlwdChjMSwgYzIsIHAsIHgpIHtcbiAgICB1dGlsLnByaW50X2RlYnVnKFwiRWxnYW1hbCBEZWNyeXB0OlxcbmMxOlwiICsgdXRpbC5oZXhzdHJkdW1wKGMxLnRvTVBJKCkpICsgXCJcXG5cIiArXG4gICAgICBcImMyOlwiICsgdXRpbC5oZXhzdHJkdW1wKGMyLnRvTVBJKCkpICsgXCJcXG5cIiArXG4gICAgICBcInA6XCIgKyB1dGlsLmhleHN0cmR1bXAocC50b01QSSgpKSArIFwiXFxuXCIgK1xuICAgICAgXCJ4OlwiICsgdXRpbC5oZXhzdHJkdW1wKHgudG9NUEkoKSkpO1xuICAgIHJldHVybiAoYzEubW9kUG93KHgsIHApLm1vZEludmVyc2UocCkpLm11bHRpcGx5KGMyKS5tb2QocCk7XG4gICAgLy92YXIgYyA9IGMxLnBvdyh4KS5tb2RJbnZlcnNlKHApOyAvLyBjMF4tYSBtb2QgcFxuICAgIC8vcmV0dXJuIGMubXVsdGlwbHkoYzIpLm1vZChwKTtcbiAgfVxuXG4gIC8vIHNpZ25pbmcgYW5kIHNpZ25hdHVyZSB2ZXJpZmljYXRpb24gdXNpbmcgRWxnYW1hbCBpcyBub3QgcmVxdWlyZWQgYnkgT3BlblBHUC5cbiAgdGhpcy5lbmNyeXB0ID0gZW5jcnlwdDtcbiAgdGhpcy5kZWNyeXB0ID0gZGVjcnlwdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBFbGdhbWFsO1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIHJzYTogcmVxdWlyZSgnLi9yc2EuanMnKSxcbiAgZWxnYW1hbDogcmVxdWlyZSgnLi9lbGdhbWFsLmpzJyksXG4gIGRzYTogcmVxdWlyZSgnLi9kc2EuanMnKVxufVxuIiwiLypcbiAqIENvcHlyaWdodCAoYykgMjAwMy0yMDA1ICBUb20gV3UgKHRqd0Bjcy5TdGFuZm9yZC5FRFUpIFxuICogQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBNb2RpZmllZCBieSBSZWN1cml0eSBMYWJzIEdtYkggXG4gKiBcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZ1xuICogYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4gKiBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbiAqIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbiAqIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0b1xuICogcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvXG4gKiB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTLUlTXCIgQU5EIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIFxuICogRVhQUkVTUywgSU1QTElFRCBPUiBPVEhFUldJU0UsIElOQ0xVRElORyBXSVRIT1VUIExJTUlUQVRJT04sIEFOWSBcbiAqIFdBUlJBTlRZIE9GIE1FUkNIQU5UQUJJTElUWSBPUiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFxuICpcbiAqIElOIE5PIEVWRU5UIFNIQUxMIFRPTSBXVSBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBJTkNJREVOVEFMLFxuICogSU5ESVJFQ1QgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9GIEFOWSBLSU5ELCBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSXG4gKiBSRVNVTFRJTkcgRlJPTSBMT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIE9SIE5PVCBBRFZJU0VEIE9GXG4gKiBUSEUgUE9TU0lCSUxJVFkgT0YgREFNQUdFLCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIEFSSVNJTkcgT1VUXG4gKiBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFVTRSBPUiBQRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxuICpcbiAqIEluIGFkZGl0aW9uLCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbiBhcHBsaWVzOlxuICpcbiAqIEFsbCByZWRpc3RyaWJ1dGlvbnMgbXVzdCByZXRhaW4gYW4gaW50YWN0IGNvcHkgb2YgdGhpcyBjb3B5cmlnaHQgbm90aWNlXG4gKiBhbmQgZGlzY2xhaW1lci5cbiAqL1xuXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xuXG4vLyBCYXNpYyBKYXZhU2NyaXB0IEJOIGxpYnJhcnkgLSBzdWJzZXQgdXNlZnVsIGZvciBSU0EgZW5jcnlwdGlvbi5cblxuLy8gQml0cyBwZXIgZGlnaXRcbnZhciBkYml0cztcblxuLy8gSmF2YVNjcmlwdCBlbmdpbmUgYW5hbHlzaXNcbnZhciBjYW5hcnkgPSAweGRlYWRiZWVmY2FmZTtcbnZhciBqX2xtID0gKChjYW5hcnkgJiAweGZmZmZmZikgPT0gMHhlZmNhZmUpO1xuXG4vLyAocHVibGljKSBDb25zdHJ1Y3RvclxuXG5mdW5jdGlvbiBCaWdJbnRlZ2VyKGEsIGIsIGMpIHtcbiAgaWYgKGEgIT0gbnVsbClcbiAgICBpZiAoXCJudW1iZXJcIiA9PSB0eXBlb2YgYSkgdGhpcy5mcm9tTnVtYmVyKGEsIGIsIGMpO1xuICAgIGVsc2UgaWYgKGIgPT0gbnVsbCAmJiBcInN0cmluZ1wiICE9IHR5cGVvZiBhKSB0aGlzLmZyb21TdHJpbmcoYSwgMjU2KTtcbiAgZWxzZSB0aGlzLmZyb21TdHJpbmcoYSwgYik7XG59XG5cbi8vIHJldHVybiBuZXcsIHVuc2V0IEJpZ0ludGVnZXJcblxuZnVuY3Rpb24gbmJpKCkge1xuICByZXR1cm4gbmV3IEJpZ0ludGVnZXIobnVsbCk7XG59XG5cbi8vIGFtOiBDb21wdXRlIHdfaiArPSAoeCp0aGlzX2kpLCBwcm9wYWdhdGUgY2Fycmllcyxcbi8vIGMgaXMgaW5pdGlhbCBjYXJyeSwgcmV0dXJucyBmaW5hbCBjYXJyeS5cbi8vIGMgPCAzKmR2YWx1ZSwgeCA8IDIqZHZhbHVlLCB0aGlzX2kgPCBkdmFsdWVcbi8vIFdlIG5lZWQgdG8gc2VsZWN0IHRoZSBmYXN0ZXN0IG9uZSB0aGF0IHdvcmtzIGluIHRoaXMgZW52aXJvbm1lbnQuXG5cbi8vIGFtMTogdXNlIGEgc2luZ2xlIG11bHQgYW5kIGRpdmlkZSB0byBnZXQgdGhlIGhpZ2ggYml0cyxcbi8vIG1heCBkaWdpdCBiaXRzIHNob3VsZCBiZSAyNiBiZWNhdXNlXG4vLyBtYXggaW50ZXJuYWwgdmFsdWUgPSAyKmR2YWx1ZV4yLTIqZHZhbHVlICg8IDJeNTMpXG5cbmZ1bmN0aW9uIGFtMShpLCB4LCB3LCBqLCBjLCBuKSB7XG4gIHdoaWxlICgtLW4gPj0gMCkge1xuICAgIHZhciB2ID0geCAqIHRoaXNbaSsrXSArIHdbal0gKyBjO1xuICAgIGMgPSBNYXRoLmZsb29yKHYgLyAweDQwMDAwMDApO1xuICAgIHdbaisrXSA9IHYgJiAweDNmZmZmZmY7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG4vLyBhbTIgYXZvaWRzIGEgYmlnIG11bHQtYW5kLWV4dHJhY3QgY29tcGxldGVseS5cbi8vIE1heCBkaWdpdCBiaXRzIHNob3VsZCBiZSA8PSAzMCBiZWNhdXNlIHdlIGRvIGJpdHdpc2Ugb3BzXG4vLyBvbiB2YWx1ZXMgdXAgdG8gMipoZHZhbHVlXjItaGR2YWx1ZS0xICg8IDJeMzEpXG5cbmZ1bmN0aW9uIGFtMihpLCB4LCB3LCBqLCBjLCBuKSB7XG4gIHZhciB4bCA9IHggJiAweDdmZmYsXG4gICAgeGggPSB4ID4+IDE1O1xuICB3aGlsZSAoLS1uID49IDApIHtcbiAgICB2YXIgbCA9IHRoaXNbaV0gJiAweDdmZmY7XG4gICAgdmFyIGggPSB0aGlzW2krK10gPj4gMTU7XG4gICAgdmFyIG0gPSB4aCAqIGwgKyBoICogeGw7XG4gICAgbCA9IHhsICogbCArICgobSAmIDB4N2ZmZikgPDwgMTUpICsgd1tqXSArIChjICYgMHgzZmZmZmZmZik7XG4gICAgYyA9IChsID4+PiAzMCkgKyAobSA+Pj4gMTUpICsgeGggKiBoICsgKGMgPj4+IDMwKTtcbiAgICB3W2orK10gPSBsICYgMHgzZmZmZmZmZjtcbiAgfVxuICByZXR1cm4gYztcbn1cbi8vIEFsdGVybmF0ZWx5LCBzZXQgbWF4IGRpZ2l0IGJpdHMgdG8gMjggc2luY2Ugc29tZVxuLy8gYnJvd3NlcnMgc2xvdyBkb3duIHdoZW4gZGVhbGluZyB3aXRoIDMyLWJpdCBudW1iZXJzLlxuXG5mdW5jdGlvbiBhbTMoaSwgeCwgdywgaiwgYywgbikge1xuICB2YXIgeGwgPSB4ICYgMHgzZmZmLFxuICAgIHhoID0geCA+PiAxNDtcbiAgd2hpbGUgKC0tbiA+PSAwKSB7XG4gICAgdmFyIGwgPSB0aGlzW2ldICYgMHgzZmZmO1xuICAgIHZhciBoID0gdGhpc1tpKytdID4+IDE0O1xuICAgIHZhciBtID0geGggKiBsICsgaCAqIHhsO1xuICAgIGwgPSB4bCAqIGwgKyAoKG0gJiAweDNmZmYpIDw8IDE0KSArIHdbal0gKyBjO1xuICAgIGMgPSAobCA+PiAyOCkgKyAobSA+PiAxNCkgKyB4aCAqIGg7XG4gICAgd1tqKytdID0gbCAmIDB4ZmZmZmZmZjtcbiAgfVxuICByZXR1cm4gYztcbn1cbi8qaWYoal9sbSAmJiAobmF2aWdhdG9yICE9IHVuZGVmaW5lZCAmJiBcblx0bmF2aWdhdG9yLmFwcE5hbWUgPT0gXCJNaWNyb3NvZnQgSW50ZXJuZXQgRXhwbG9yZXJcIikpIHtcbiAgQmlnSW50ZWdlci5wcm90b3R5cGUuYW0gPSBhbTI7XG4gIGRiaXRzID0gMzA7XG59XG5lbHNlIGlmKGpfbG0gJiYgKG5hdmlnYXRvciAhPSB1bmRlZmluZWQgJiYgbmF2aWdhdG9yLmFwcE5hbWUgIT0gXCJOZXRzY2FwZVwiKSkgeyovXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hbSA9IGFtMTtcbmRiaXRzID0gMjY7XG4vKn1cbmVsc2UgeyAvLyBNb3ppbGxhL05ldHNjYXBlIHNlZW1zIHRvIHByZWZlciBhbTNcbiAgQmlnSW50ZWdlci5wcm90b3R5cGUuYW0gPSBhbTM7XG4gIGRiaXRzID0gMjg7XG59Ki9cblxuQmlnSW50ZWdlci5wcm90b3R5cGUuREIgPSBkYml0cztcbkJpZ0ludGVnZXIucHJvdG90eXBlLkRNID0gKCgxIDw8IGRiaXRzKSAtIDEpO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuRFYgPSAoMSA8PCBkYml0cyk7XG5cbnZhciBCSV9GUCA9IDUyO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuRlYgPSBNYXRoLnBvdygyLCBCSV9GUCk7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5GMSA9IEJJX0ZQIC0gZGJpdHM7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5GMiA9IDIgKiBkYml0cyAtIEJJX0ZQO1xuXG4vLyBEaWdpdCBjb252ZXJzaW9uc1xudmFyIEJJX1JNID0gXCIwMTIzNDU2Nzg5YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpcIjtcbnZhciBCSV9SQyA9IG5ldyBBcnJheSgpO1xudmFyIHJyLCB2djtcbnJyID0gXCIwXCIuY2hhckNvZGVBdCgwKTtcbmZvciAodnYgPSAwOyB2diA8PSA5OyArK3Z2KSBCSV9SQ1tycisrXSA9IHZ2O1xucnIgPSBcImFcIi5jaGFyQ29kZUF0KDApO1xuZm9yICh2diA9IDEwOyB2diA8IDM2OyArK3Z2KSBCSV9SQ1tycisrXSA9IHZ2O1xucnIgPSBcIkFcIi5jaGFyQ29kZUF0KDApO1xuZm9yICh2diA9IDEwOyB2diA8IDM2OyArK3Z2KSBCSV9SQ1tycisrXSA9IHZ2O1xuXG5mdW5jdGlvbiBpbnQyY2hhcihuKSB7XG4gIHJldHVybiBCSV9STS5jaGFyQXQobik7XG59XG5cbmZ1bmN0aW9uIGludEF0KHMsIGkpIHtcbiAgdmFyIGMgPSBCSV9SQ1tzLmNoYXJDb2RlQXQoaSldO1xuICByZXR1cm4gKGMgPT0gbnVsbCkgPyAtMSA6IGM7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvcHkgdGhpcyB0byByXG5cbmZ1bmN0aW9uIGJucENvcHlUbyhyKSB7XG4gIGZvciAodmFyIGkgPSB0aGlzLnQgLSAxOyBpID49IDA7IC0taSkgcltpXSA9IHRoaXNbaV07XG4gIHIudCA9IHRoaXMudDtcbiAgci5zID0gdGhpcy5zO1xufVxuXG4vLyAocHJvdGVjdGVkKSBzZXQgZnJvbSBpbnRlZ2VyIHZhbHVlIHgsIC1EViA8PSB4IDwgRFZcblxuZnVuY3Rpb24gYm5wRnJvbUludCh4KSB7XG4gIHRoaXMudCA9IDE7XG4gIHRoaXMucyA9ICh4IDwgMCkgPyAtMSA6IDA7XG4gIGlmICh4ID4gMCkgdGhpc1swXSA9IHg7XG4gIGVsc2UgaWYgKHggPCAtMSkgdGhpc1swXSA9IHggKyBEVjtcbiAgZWxzZSB0aGlzLnQgPSAwO1xufVxuXG4vLyByZXR1cm4gYmlnaW50IGluaXRpYWxpemVkIHRvIHZhbHVlXG5cbmZ1bmN0aW9uIG5idihpKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHIuZnJvbUludChpKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHNldCBmcm9tIHN0cmluZyBhbmQgcmFkaXhcblxuZnVuY3Rpb24gYm5wRnJvbVN0cmluZyhzLCBiKSB7XG4gIHZhciBrO1xuICBpZiAoYiA9PSAxNikgayA9IDQ7XG4gIGVsc2UgaWYgKGIgPT0gOCkgayA9IDM7XG4gIGVsc2UgaWYgKGIgPT0gMjU2KSBrID0gODsgLy8gYnl0ZSBhcnJheVxuICBlbHNlIGlmIChiID09IDIpIGsgPSAxO1xuICBlbHNlIGlmIChiID09IDMyKSBrID0gNTtcbiAgZWxzZSBpZiAoYiA9PSA0KSBrID0gMjtcbiAgZWxzZSB7XG4gICAgdGhpcy5mcm9tUmFkaXgocywgYik7XG4gICAgcmV0dXJuO1xuICB9XG4gIHRoaXMudCA9IDA7XG4gIHRoaXMucyA9IDA7XG4gIHZhciBpID0gcy5sZW5ndGgsXG4gICAgbWkgPSBmYWxzZSxcbiAgICBzaCA9IDA7XG4gIHdoaWxlICgtLWkgPj0gMCkge1xuICAgIHZhciB4ID0gKGsgPT0gOCkgPyBzW2ldICYgMHhmZiA6IGludEF0KHMsIGkpO1xuICAgIGlmICh4IDwgMCkge1xuICAgICAgaWYgKHMuY2hhckF0KGkpID09IFwiLVwiKSBtaSA9IHRydWU7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgbWkgPSBmYWxzZTtcbiAgICBpZiAoc2ggPT0gMClcbiAgICAgIHRoaXNbdGhpcy50KytdID0geDtcbiAgICBlbHNlIGlmIChzaCArIGsgPiB0aGlzLkRCKSB7XG4gICAgICB0aGlzW3RoaXMudCAtIDFdIHw9ICh4ICYgKCgxIDw8ICh0aGlzLkRCIC0gc2gpKSAtIDEpKSA8PCBzaDtcbiAgICAgIHRoaXNbdGhpcy50KytdID0gKHggPj4gKHRoaXMuREIgLSBzaCkpO1xuICAgIH0gZWxzZVxuICAgICAgdGhpc1t0aGlzLnQgLSAxXSB8PSB4IDw8IHNoO1xuICAgIHNoICs9IGs7XG4gICAgaWYgKHNoID49IHRoaXMuREIpIHNoIC09IHRoaXMuREI7XG4gIH1cbiAgaWYgKGsgPT0gOCAmJiAoc1swXSAmIDB4ODApICE9IDApIHtcbiAgICB0aGlzLnMgPSAtMTtcbiAgICBpZiAoc2ggPiAwKSB0aGlzW3RoaXMudCAtIDFdIHw9ICgoMSA8PCAodGhpcy5EQiAtIHNoKSkgLSAxKSA8PCBzaDtcbiAgfVxuICB0aGlzLmNsYW1wKCk7XG4gIGlmIChtaSkgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHRoaXMsIHRoaXMpO1xufVxuXG4vLyAocHJvdGVjdGVkKSBjbGFtcCBvZmYgZXhjZXNzIGhpZ2ggd29yZHNcblxuZnVuY3Rpb24gYm5wQ2xhbXAoKSB7XG4gIHZhciBjID0gdGhpcy5zICYgdGhpcy5ETTtcbiAgd2hpbGUgKHRoaXMudCA+IDAgJiYgdGhpc1t0aGlzLnQgLSAxXSA9PSBjKS0tdGhpcy50O1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gc3RyaW5nIHJlcHJlc2VudGF0aW9uIGluIGdpdmVuIHJhZGl4XG5cbmZ1bmN0aW9uIGJuVG9TdHJpbmcoYikge1xuICBpZiAodGhpcy5zIDwgMCkgcmV0dXJuIFwiLVwiICsgdGhpcy5uZWdhdGUoKS50b1N0cmluZyhiKTtcbiAgdmFyIGs7XG4gIGlmIChiID09IDE2KSBrID0gNDtcbiAgZWxzZSBpZiAoYiA9PSA4KSBrID0gMztcbiAgZWxzZSBpZiAoYiA9PSAyKSBrID0gMTtcbiAgZWxzZSBpZiAoYiA9PSAzMikgayA9IDU7XG4gIGVsc2UgaWYgKGIgPT0gNCkgayA9IDI7XG4gIGVsc2UgcmV0dXJuIHRoaXMudG9SYWRpeChiKTtcbiAgdmFyIGttID0gKDEgPDwgaykgLSAxLFxuICAgIGQsIG0gPSBmYWxzZSxcbiAgICByID0gXCJcIixcbiAgICBpID0gdGhpcy50O1xuICB2YXIgcCA9IHRoaXMuREIgLSAoaSAqIHRoaXMuREIpICUgaztcbiAgaWYgKGktLSA+IDApIHtcbiAgICBpZiAocCA8IHRoaXMuREIgJiYgKGQgPSB0aGlzW2ldID4+IHApID4gMCkge1xuICAgICAgbSA9IHRydWU7XG4gICAgICByID0gaW50MmNoYXIoZCk7XG4gICAgfVxuICAgIHdoaWxlIChpID49IDApIHtcbiAgICAgIGlmIChwIDwgaykge1xuICAgICAgICBkID0gKHRoaXNbaV0gJiAoKDEgPDwgcCkgLSAxKSkgPDwgKGsgLSBwKTtcbiAgICAgICAgZCB8PSB0aGlzWy0taV0gPj4gKHAgKz0gdGhpcy5EQiAtIGspO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZCA9ICh0aGlzW2ldID4+IChwIC09IGspKSAmIGttO1xuICAgICAgICBpZiAocCA8PSAwKSB7XG4gICAgICAgICAgcCArPSB0aGlzLkRCO1xuICAgICAgICAgIC0taTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGQgPiAwKSBtID0gdHJ1ZTtcbiAgICAgIGlmIChtKSByICs9IGludDJjaGFyKGQpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbSA/IHIgOiBcIjBcIjtcbn1cblxuLy8gKHB1YmxpYykgLXRoaXNcblxuZnVuY3Rpb24gYm5OZWdhdGUoKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIEJpZ0ludGVnZXIuWkVSTy5zdWJUbyh0aGlzLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHx0aGlzfFxuXG5mdW5jdGlvbiBibkFicygpIHtcbiAgcmV0dXJuICh0aGlzLnMgPCAwKSA/IHRoaXMubmVnYXRlKCkgOiB0aGlzO1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gKyBpZiB0aGlzID4gYSwgLSBpZiB0aGlzIDwgYSwgMCBpZiBlcXVhbFxuXG5mdW5jdGlvbiBibkNvbXBhcmVUbyhhKSB7XG4gIHZhciByID0gdGhpcy5zIC0gYS5zO1xuICBpZiAociAhPSAwKSByZXR1cm4gcjtcbiAgdmFyIGkgPSB0aGlzLnQ7XG4gIHIgPSBpIC0gYS50O1xuICBpZiAociAhPSAwKSByZXR1cm4gcjtcbiAgd2hpbGUgKC0taSA+PSAwKSBpZiAoKHIgPSB0aGlzW2ldIC0gYVtpXSkgIT0gMCkgcmV0dXJuIHI7XG4gIHJldHVybiAwO1xufVxuXG4vLyByZXR1cm5zIGJpdCBsZW5ndGggb2YgdGhlIGludGVnZXIgeFxuXG5mdW5jdGlvbiBuYml0cyh4KSB7XG4gIHZhciByID0gMSxcbiAgICB0O1xuICBpZiAoKHQgPSB4ID4+PiAxNikgIT0gMCkge1xuICAgIHggPSB0O1xuICAgIHIgKz0gMTY7XG4gIH1cbiAgaWYgKCh0ID0geCA+PiA4KSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgciArPSA4O1xuICB9XG4gIGlmICgodCA9IHggPj4gNCkgIT0gMCkge1xuICAgIHggPSB0O1xuICAgIHIgKz0gNDtcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDIpICE9IDApIHtcbiAgICB4ID0gdDtcbiAgICByICs9IDI7XG4gIH1cbiAgaWYgKCh0ID0geCA+PiAxKSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgciArPSAxO1xuICB9XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gdGhlIG51bWJlciBvZiBiaXRzIGluIFwidGhpc1wiXG5cbmZ1bmN0aW9uIGJuQml0TGVuZ3RoKCkge1xuICBpZiAodGhpcy50IDw9IDApIHJldHVybiAwO1xuICByZXR1cm4gdGhpcy5EQiAqICh0aGlzLnQgLSAxKSArIG5iaXRzKHRoaXNbdGhpcy50IC0gMV0gXiAodGhpcy5zICYgdGhpcy5ETSkpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA8PCBuKkRCXG5cbmZ1bmN0aW9uIGJucERMU2hpZnRUbyhuLCByKSB7XG4gIHZhciBpO1xuICBmb3IgKGkgPSB0aGlzLnQgLSAxOyBpID49IDA7IC0taSkgcltpICsgbl0gPSB0aGlzW2ldO1xuICBmb3IgKGkgPSBuIC0gMTsgaSA+PSAwOyAtLWkpIHJbaV0gPSAwO1xuICByLnQgPSB0aGlzLnQgKyBuO1xuICByLnMgPSB0aGlzLnM7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzID4+IG4qREJcblxuZnVuY3Rpb24gYm5wRFJTaGlmdFRvKG4sIHIpIHtcbiAgZm9yICh2YXIgaSA9IG47IGkgPCB0aGlzLnQ7ICsraSkgcltpIC0gbl0gPSB0aGlzW2ldO1xuICByLnQgPSBNYXRoLm1heCh0aGlzLnQgLSBuLCAwKTtcbiAgci5zID0gdGhpcy5zO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA8PCBuXG5cbmZ1bmN0aW9uIGJucExTaGlmdFRvKG4sIHIpIHtcbiAgdmFyIGJzID0gbiAlIHRoaXMuREI7XG4gIHZhciBjYnMgPSB0aGlzLkRCIC0gYnM7XG4gIHZhciBibSA9ICgxIDw8IGNicykgLSAxO1xuICB2YXIgZHMgPSBNYXRoLmZsb29yKG4gLyB0aGlzLkRCKSxcbiAgICBjID0gKHRoaXMucyA8PCBicykgJiB0aGlzLkRNLFxuICAgIGk7XG4gIGZvciAoaSA9IHRoaXMudCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgcltpICsgZHMgKyAxXSA9ICh0aGlzW2ldID4+IGNicykgfCBjO1xuICAgIGMgPSAodGhpc1tpXSAmIGJtKSA8PCBicztcbiAgfVxuICBmb3IgKGkgPSBkcyAtIDE7IGkgPj0gMDsgLS1pKSByW2ldID0gMDtcbiAgcltkc10gPSBjO1xuICByLnQgPSB0aGlzLnQgKyBkcyArIDE7XG4gIHIucyA9IHRoaXMucztcbiAgci5jbGFtcCgpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA+PiBuXG5cbmZ1bmN0aW9uIGJucFJTaGlmdFRvKG4sIHIpIHtcbiAgci5zID0gdGhpcy5zO1xuICB2YXIgZHMgPSBNYXRoLmZsb29yKG4gLyB0aGlzLkRCKTtcbiAgaWYgKGRzID49IHRoaXMudCkge1xuICAgIHIudCA9IDA7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBicyA9IG4gJSB0aGlzLkRCO1xuICB2YXIgY2JzID0gdGhpcy5EQiAtIGJzO1xuICB2YXIgYm0gPSAoMSA8PCBicykgLSAxO1xuICByWzBdID0gdGhpc1tkc10gPj4gYnM7XG4gIGZvciAodmFyIGkgPSBkcyArIDE7IGkgPCB0aGlzLnQ7ICsraSkge1xuICAgIHJbaSAtIGRzIC0gMV0gfD0gKHRoaXNbaV0gJiBibSkgPDwgY2JzO1xuICAgIHJbaSAtIGRzXSA9IHRoaXNbaV0gPj4gYnM7XG4gIH1cbiAgaWYgKGJzID4gMCkgclt0aGlzLnQgLSBkcyAtIDFdIHw9ICh0aGlzLnMgJiBibSkgPDwgY2JzO1xuICByLnQgPSB0aGlzLnQgLSBkcztcbiAgci5jbGFtcCgpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyAtIGFcblxuZnVuY3Rpb24gYm5wU3ViVG8oYSwgcikge1xuICB2YXIgaSA9IDAsXG4gICAgYyA9IDAsXG4gICAgbSA9IE1hdGgubWluKGEudCwgdGhpcy50KTtcbiAgd2hpbGUgKGkgPCBtKSB7XG4gICAgYyArPSB0aGlzW2ldIC0gYVtpXTtcbiAgICByW2krK10gPSBjICYgdGhpcy5ETTtcbiAgICBjID4+PSB0aGlzLkRCO1xuICB9XG4gIGlmIChhLnQgPCB0aGlzLnQpIHtcbiAgICBjIC09IGEucztcbiAgICB3aGlsZSAoaSA8IHRoaXMudCkge1xuICAgICAgYyArPSB0aGlzW2ldO1xuICAgICAgcltpKytdID0gYyAmIHRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjICs9IHRoaXMucztcbiAgfSBlbHNlIHtcbiAgICBjICs9IHRoaXMucztcbiAgICB3aGlsZSAoaSA8IGEudCkge1xuICAgICAgYyAtPSBhW2ldO1xuICAgICAgcltpKytdID0gYyAmIHRoaXMuRE07XG4gICAgICBjID4+PSB0aGlzLkRCO1xuICAgIH1cbiAgICBjIC09IGEucztcbiAgfVxuICByLnMgPSAoYyA8IDApID8gLTEgOiAwO1xuICBpZiAoYyA8IC0xKSByW2krK10gPSB0aGlzLkRWICsgYztcbiAgZWxzZSBpZiAoYyA+IDApIHJbaSsrXSA9IGM7XG4gIHIudCA9IGk7XG4gIHIuY2xhbXAoKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXMgKiBhLCByICE9IHRoaXMsYSAoSEFDIDE0LjEyKVxuLy8gXCJ0aGlzXCIgc2hvdWxkIGJlIHRoZSBsYXJnZXIgb25lIGlmIGFwcHJvcHJpYXRlLlxuXG5mdW5jdGlvbiBibnBNdWx0aXBseVRvKGEsIHIpIHtcbiAgdmFyIHggPSB0aGlzLmFicygpLFxuICAgIHkgPSBhLmFicygpO1xuICB2YXIgaSA9IHgudDtcbiAgci50ID0gaSArIHkudDtcbiAgd2hpbGUgKC0taSA+PSAwKSByW2ldID0gMDtcbiAgZm9yIChpID0gMDsgaSA8IHkudDsgKytpKSByW2kgKyB4LnRdID0geC5hbSgwLCB5W2ldLCByLCBpLCAwLCB4LnQpO1xuICByLnMgPSAwO1xuICByLmNsYW1wKCk7XG4gIGlmICh0aGlzLnMgIT0gYS5zKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8ociwgcik7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzXjIsIHIgIT0gdGhpcyAoSEFDIDE0LjE2KVxuXG5mdW5jdGlvbiBibnBTcXVhcmVUbyhyKSB7XG4gIHZhciB4ID0gdGhpcy5hYnMoKTtcbiAgdmFyIGkgPSByLnQgPSAyICogeC50O1xuICB3aGlsZSAoLS1pID49IDApIHJbaV0gPSAwO1xuICBmb3IgKGkgPSAwOyBpIDwgeC50IC0gMTsgKytpKSB7XG4gICAgdmFyIGMgPSB4LmFtKGksIHhbaV0sIHIsIDIgKiBpLCAwLCAxKTtcbiAgICBpZiAoKHJbaSArIHgudF0gKz0geC5hbShpICsgMSwgMiAqIHhbaV0sIHIsIDIgKiBpICsgMSwgYywgeC50IC0gaSAtIDEpKSA+PSB4LkRWKSB7XG4gICAgICByW2kgKyB4LnRdIC09IHguRFY7XG4gICAgICByW2kgKyB4LnQgKyAxXSA9IDE7XG4gICAgfVxuICB9XG4gIGlmIChyLnQgPiAwKSByW3IudCAtIDFdICs9IHguYW0oaSwgeFtpXSwgciwgMiAqIGksIDAsIDEpO1xuICByLnMgPSAwO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIGRpdmlkZSB0aGlzIGJ5IG0sIHF1b3RpZW50IGFuZCByZW1haW5kZXIgdG8gcSwgciAoSEFDIDE0LjIwKVxuLy8gciAhPSBxLCB0aGlzICE9IG0uICBxIG9yIHIgbWF5IGJlIG51bGwuXG5cbmZ1bmN0aW9uIGJucERpdlJlbVRvKG0sIHEsIHIpIHtcbiAgdmFyIHBtID0gbS5hYnMoKTtcbiAgaWYgKHBtLnQgPD0gMCkgcmV0dXJuO1xuICB2YXIgcHQgPSB0aGlzLmFicygpO1xuICBpZiAocHQudCA8IHBtLnQpIHtcbiAgICBpZiAocSAhPSBudWxsKSBxLmZyb21JbnQoMCk7XG4gICAgaWYgKHIgIT0gbnVsbCkgdGhpcy5jb3B5VG8ocik7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChyID09IG51bGwpIHIgPSBuYmkoKTtcbiAgdmFyIHkgPSBuYmkoKSxcbiAgICB0cyA9IHRoaXMucyxcbiAgICBtcyA9IG0ucztcbiAgdmFyIG5zaCA9IHRoaXMuREIgLSBuYml0cyhwbVtwbS50IC0gMV0pOyAvLyBub3JtYWxpemUgbW9kdWx1c1xuICBpZiAobnNoID4gMCkge1xuICAgIHBtLmxTaGlmdFRvKG5zaCwgeSk7XG4gICAgcHQubFNoaWZ0VG8obnNoLCByKTtcbiAgfSBlbHNlIHtcbiAgICBwbS5jb3B5VG8oeSk7XG4gICAgcHQuY29weVRvKHIpO1xuICB9XG4gIHZhciB5cyA9IHkudDtcbiAgdmFyIHkwID0geVt5cyAtIDFdO1xuICBpZiAoeTAgPT0gMCkgcmV0dXJuO1xuICB2YXIgeXQgPSB5MCAqICgxIDw8IHRoaXMuRjEpICsgKCh5cyA+IDEpID8geVt5cyAtIDJdID4+IHRoaXMuRjIgOiAwKTtcbiAgdmFyIGQxID0gdGhpcy5GViAvIHl0LFxuICAgIGQyID0gKDEgPDwgdGhpcy5GMSkgLyB5dCxcbiAgICBlID0gMSA8PCB0aGlzLkYyO1xuICB2YXIgaSA9IHIudCxcbiAgICBqID0gaSAtIHlzLFxuICAgIHQgPSAocSA9PSBudWxsKSA/IG5iaSgpIDogcTtcbiAgeS5kbFNoaWZ0VG8oaiwgdCk7XG4gIGlmIChyLmNvbXBhcmVUbyh0KSA+PSAwKSB7XG4gICAgcltyLnQrK10gPSAxO1xuICAgIHIuc3ViVG8odCwgcik7XG4gIH1cbiAgQmlnSW50ZWdlci5PTkUuZGxTaGlmdFRvKHlzLCB0KTtcbiAgdC5zdWJUbyh5LCB5KTsgLy8gXCJuZWdhdGl2ZVwiIHkgc28gd2UgY2FuIHJlcGxhY2Ugc3ViIHdpdGggYW0gbGF0ZXJcbiAgd2hpbGUgKHkudCA8IHlzKSB5W3kudCsrXSA9IDA7XG4gIHdoaWxlICgtLWogPj0gMCkge1xuICAgIC8vIEVzdGltYXRlIHF1b3RpZW50IGRpZ2l0XG4gICAgdmFyIHFkID0gKHJbLS1pXSA9PSB5MCkgPyB0aGlzLkRNIDogTWF0aC5mbG9vcihyW2ldICogZDEgKyAocltpIC0gMV0gKyBlKSAqIGQyKTtcbiAgICBpZiAoKHJbaV0gKz0geS5hbSgwLCBxZCwgciwgaiwgMCwgeXMpKSA8IHFkKSB7IC8vIFRyeSBpdCBvdXRcbiAgICAgIHkuZGxTaGlmdFRvKGosIHQpO1xuICAgICAgci5zdWJUbyh0LCByKTtcbiAgICAgIHdoaWxlIChyW2ldIDwgLS1xZCkgci5zdWJUbyh0LCByKTtcbiAgICB9XG4gIH1cbiAgaWYgKHEgIT0gbnVsbCkge1xuICAgIHIuZHJTaGlmdFRvKHlzLCBxKTtcbiAgICBpZiAodHMgIT0gbXMpIEJpZ0ludGVnZXIuWkVSTy5zdWJUbyhxLCBxKTtcbiAgfVxuICByLnQgPSB5cztcbiAgci5jbGFtcCgpO1xuICBpZiAobnNoID4gMCkgci5yU2hpZnRUbyhuc2gsIHIpOyAvLyBEZW5vcm1hbGl6ZSByZW1haW5kZXJcbiAgaWYgKHRzIDwgMCkgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHIsIHIpO1xufVxuXG4vLyAocHVibGljKSB0aGlzIG1vZCBhXG5cbmZ1bmN0aW9uIGJuTW9kKGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5hYnMoKS5kaXZSZW1UbyhhLCBudWxsLCByKTtcbiAgaWYgKHRoaXMucyA8IDAgJiYgci5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSA+IDApIGEuc3ViVG8ociwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyBNb2R1bGFyIHJlZHVjdGlvbiB1c2luZyBcImNsYXNzaWNcIiBhbGdvcml0aG1cblxuZnVuY3Rpb24gQ2xhc3NpYyhtKSB7XG4gIHRoaXMubSA9IG07XG59XG5cbmZ1bmN0aW9uIGNDb252ZXJ0KHgpIHtcbiAgaWYgKHgucyA8IDAgfHwgeC5jb21wYXJlVG8odGhpcy5tKSA+PSAwKSByZXR1cm4geC5tb2QodGhpcy5tKTtcbiAgZWxzZSByZXR1cm4geDtcbn1cblxuZnVuY3Rpb24gY1JldmVydCh4KSB7XG4gIHJldHVybiB4O1xufVxuXG5mdW5jdGlvbiBjUmVkdWNlKHgpIHtcbiAgeC5kaXZSZW1Ubyh0aGlzLm0sIG51bGwsIHgpO1xufVxuXG5mdW5jdGlvbiBjTXVsVG8oeCwgeSwgcikge1xuICB4Lm11bHRpcGx5VG8oeSwgcik7XG4gIHRoaXMucmVkdWNlKHIpO1xufVxuXG5mdW5jdGlvbiBjU3FyVG8oeCwgcikge1xuICB4LnNxdWFyZVRvKHIpO1xuICB0aGlzLnJlZHVjZShyKTtcbn1cblxuQ2xhc3NpYy5wcm90b3R5cGUuY29udmVydCA9IGNDb252ZXJ0O1xuQ2xhc3NpYy5wcm90b3R5cGUucmV2ZXJ0ID0gY1JldmVydDtcbkNsYXNzaWMucHJvdG90eXBlLnJlZHVjZSA9IGNSZWR1Y2U7XG5DbGFzc2ljLnByb3RvdHlwZS5tdWxUbyA9IGNNdWxUbztcbkNsYXNzaWMucHJvdG90eXBlLnNxclRvID0gY1NxclRvO1xuXG4vLyAocHJvdGVjdGVkKSByZXR1cm4gXCItMS90aGlzICUgMl5EQlwiOyB1c2VmdWwgZm9yIE1vbnQuIHJlZHVjdGlvblxuLy8ganVzdGlmaWNhdGlvbjpcbi8vICAgICAgICAgeHkgPT0gMSAobW9kIG0pXG4vLyAgICAgICAgIHh5ID0gIDEra21cbi8vICAgeHkoMi14eSkgPSAoMStrbSkoMS1rbSlcbi8vIHhbeSgyLXh5KV0gPSAxLWteMm1eMlxuLy8geFt5KDIteHkpXSA9PSAxIChtb2QgbV4yKVxuLy8gaWYgeSBpcyAxL3ggbW9kIG0sIHRoZW4geSgyLXh5KSBpcyAxL3ggbW9kIG1eMlxuLy8gc2hvdWxkIHJlZHVjZSB4IGFuZCB5KDIteHkpIGJ5IG1eMiBhdCBlYWNoIHN0ZXAgdG8ga2VlcCBzaXplIGJvdW5kZWQuXG4vLyBKUyBtdWx0aXBseSBcIm92ZXJmbG93c1wiIGRpZmZlcmVudGx5IGZyb20gQy9DKyssIHNvIGNhcmUgaXMgbmVlZGVkIGhlcmUuXG5cbmZ1bmN0aW9uIGJucEludkRpZ2l0KCkge1xuICBpZiAodGhpcy50IDwgMSkgcmV0dXJuIDA7XG4gIHZhciB4ID0gdGhpc1swXTtcbiAgaWYgKCh4ICYgMSkgPT0gMCkgcmV0dXJuIDA7XG4gIHZhciB5ID0geCAmIDM7IC8vIHkgPT0gMS94IG1vZCAyXjJcbiAgeSA9ICh5ICogKDIgLSAoeCAmIDB4ZikgKiB5KSkgJiAweGY7IC8vIHkgPT0gMS94IG1vZCAyXjRcbiAgeSA9ICh5ICogKDIgLSAoeCAmIDB4ZmYpICogeSkpICYgMHhmZjsgLy8geSA9PSAxL3ggbW9kIDJeOFxuICB5ID0gKHkgKiAoMiAtICgoKHggJiAweGZmZmYpICogeSkgJiAweGZmZmYpKSkgJiAweGZmZmY7IC8vIHkgPT0gMS94IG1vZCAyXjE2XG4gIC8vIGxhc3Qgc3RlcCAtIGNhbGN1bGF0ZSBpbnZlcnNlIG1vZCBEViBkaXJlY3RseTtcbiAgLy8gYXNzdW1lcyAxNiA8IERCIDw9IDMyIGFuZCBhc3N1bWVzIGFiaWxpdHkgdG8gaGFuZGxlIDQ4LWJpdCBpbnRzXG4gIHkgPSAoeSAqICgyIC0geCAqIHkgJSB0aGlzLkRWKSkgJSB0aGlzLkRWOyAvLyB5ID09IDEveCBtb2QgMl5kYml0c1xuICAvLyB3ZSByZWFsbHkgd2FudCB0aGUgbmVnYXRpdmUgaW52ZXJzZSwgYW5kIC1EViA8IHkgPCBEVlxuICByZXR1cm4gKHkgPiAwKSA/IHRoaXMuRFYgLSB5IDogLXk7XG59XG5cbi8vIE1vbnRnb21lcnkgcmVkdWN0aW9uXG5cbmZ1bmN0aW9uIE1vbnRnb21lcnkobSkge1xuICB0aGlzLm0gPSBtO1xuICB0aGlzLm1wID0gbS5pbnZEaWdpdCgpO1xuICB0aGlzLm1wbCA9IHRoaXMubXAgJiAweDdmZmY7XG4gIHRoaXMubXBoID0gdGhpcy5tcCA+PiAxNTtcbiAgdGhpcy51bSA9ICgxIDw8IChtLkRCIC0gMTUpKSAtIDE7XG4gIHRoaXMubXQyID0gMiAqIG0udDtcbn1cblxuLy8geFIgbW9kIG1cblxuZnVuY3Rpb24gbW9udENvbnZlcnQoeCkge1xuICB2YXIgciA9IG5iaSgpO1xuICB4LmFicygpLmRsU2hpZnRUbyh0aGlzLm0udCwgcik7XG4gIHIuZGl2UmVtVG8odGhpcy5tLCBudWxsLCByKTtcbiAgaWYgKHgucyA8IDAgJiYgci5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSA+IDApIHRoaXMubS5zdWJUbyhyLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIHgvUiBtb2QgbVxuXG5mdW5jdGlvbiBtb250UmV2ZXJ0KHgpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgeC5jb3B5VG8ocik7XG4gIHRoaXMucmVkdWNlKHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8geCA9IHgvUiBtb2QgbSAoSEFDIDE0LjMyKVxuXG5mdW5jdGlvbiBtb250UmVkdWNlKHgpIHtcbiAgd2hpbGUgKHgudCA8PSB0aGlzLm10MikgLy8gcGFkIHggc28gYW0gaGFzIGVub3VnaCByb29tIGxhdGVyXG4gICAgeFt4LnQrK10gPSAwO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubS50OyArK2kpIHtcbiAgICAvLyBmYXN0ZXIgd2F5IG9mIGNhbGN1bGF0aW5nIHUwID0geFtpXSptcCBtb2QgRFZcbiAgICB2YXIgaiA9IHhbaV0gJiAweDdmZmY7XG4gICAgdmFyIHUwID0gKGogKiB0aGlzLm1wbCArICgoKGogKiB0aGlzLm1waCArICh4W2ldID4+IDE1KSAqIHRoaXMubXBsKSAmIHRoaXMudW0pIDw8IDE1KSkgJiB4LkRNO1xuICAgIC8vIHVzZSBhbSB0byBjb21iaW5lIHRoZSBtdWx0aXBseS1zaGlmdC1hZGQgaW50byBvbmUgY2FsbFxuICAgIGogPSBpICsgdGhpcy5tLnQ7XG4gICAgeFtqXSArPSB0aGlzLm0uYW0oMCwgdTAsIHgsIGksIDAsIHRoaXMubS50KTtcbiAgICAvLyBwcm9wYWdhdGUgY2FycnlcbiAgICB3aGlsZSAoeFtqXSA+PSB4LkRWKSB7XG4gICAgICB4W2pdIC09IHguRFY7XG4gICAgICB4Wysral0rKztcbiAgICB9XG4gIH1cbiAgeC5jbGFtcCgpO1xuICB4LmRyU2hpZnRUbyh0aGlzLm0udCwgeCk7XG4gIGlmICh4LmNvbXBhcmVUbyh0aGlzLm0pID49IDApIHguc3ViVG8odGhpcy5tLCB4KTtcbn1cblxuLy8gciA9IFwieF4yL1IgbW9kIG1cIjsgeCAhPSByXG5cbmZ1bmN0aW9uIG1vbnRTcXJUbyh4LCByKSB7XG4gIHguc3F1YXJlVG8ocik7XG4gIHRoaXMucmVkdWNlKHIpO1xufVxuXG4vLyByID0gXCJ4eS9SIG1vZCBtXCI7IHgseSAhPSByXG5cbmZ1bmN0aW9uIG1vbnRNdWxUbyh4LCB5LCByKSB7XG4gIHgubXVsdGlwbHlUbyh5LCByKTtcbiAgdGhpcy5yZWR1Y2Uocik7XG59XG5cbk1vbnRnb21lcnkucHJvdG90eXBlLmNvbnZlcnQgPSBtb250Q29udmVydDtcbk1vbnRnb21lcnkucHJvdG90eXBlLnJldmVydCA9IG1vbnRSZXZlcnQ7XG5Nb250Z29tZXJ5LnByb3RvdHlwZS5yZWR1Y2UgPSBtb250UmVkdWNlO1xuTW9udGdvbWVyeS5wcm90b3R5cGUubXVsVG8gPSBtb250TXVsVG87XG5Nb250Z29tZXJ5LnByb3RvdHlwZS5zcXJUbyA9IG1vbnRTcXJUbztcblxuLy8gKHByb3RlY3RlZCkgdHJ1ZSBpZmYgdGhpcyBpcyBldmVuXG5cbmZ1bmN0aW9uIGJucElzRXZlbigpIHtcbiAgcmV0dXJuICgodGhpcy50ID4gMCkgPyAodGhpc1swXSAmIDEpIDogdGhpcy5zKSA9PSAwO1xufVxuXG4vLyAocHJvdGVjdGVkKSB0aGlzXmUsIGUgPCAyXjMyLCBkb2luZyBzcXIgYW5kIG11bCB3aXRoIFwiclwiIChIQUMgMTQuNzkpXG5cbmZ1bmN0aW9uIGJucEV4cChlLCB6KSB7XG4gIGlmIChlID4gMHhmZmZmZmZmZiB8fCBlIDwgMSkgcmV0dXJuIEJpZ0ludGVnZXIuT05FO1xuICB2YXIgciA9IG5iaSgpLFxuICAgIHIyID0gbmJpKCksXG4gICAgZyA9IHouY29udmVydCh0aGlzKSxcbiAgICBpID0gbmJpdHMoZSkgLSAxO1xuICBnLmNvcHlUbyhyKTtcbiAgd2hpbGUgKC0taSA+PSAwKSB7XG4gICAgei5zcXJUbyhyLCByMik7XG4gICAgaWYgKChlICYgKDEgPDwgaSkpID4gMCkgei5tdWxUbyhyMiwgZywgcik7XG4gICAgZWxzZSB7XG4gICAgICB2YXIgdCA9IHI7XG4gICAgICByID0gcjI7XG4gICAgICByMiA9IHQ7XG4gICAgfVxuICB9XG4gIHJldHVybiB6LnJldmVydChyKTtcbn1cblxuLy8gKHB1YmxpYykgdGhpc15lICUgbSwgMCA8PSBlIDwgMl4zMlxuXG5mdW5jdGlvbiBibk1vZFBvd0ludChlLCBtKSB7XG4gIHZhciB6O1xuICBpZiAoZSA8IDI1NiB8fCBtLmlzRXZlbigpKSB6ID0gbmV3IENsYXNzaWMobSk7XG4gIGVsc2UgeiA9IG5ldyBNb250Z29tZXJ5KG0pO1xuICByZXR1cm4gdGhpcy5leHAoZSwgeik7XG59XG5cbi8vIHByb3RlY3RlZFxuQmlnSW50ZWdlci5wcm90b3R5cGUuY29weVRvID0gYm5wQ29weVRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZnJvbUludCA9IGJucEZyb21JbnQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5mcm9tU3RyaW5nID0gYm5wRnJvbVN0cmluZztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmNsYW1wID0gYm5wQ2xhbXA7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kbFNoaWZ0VG8gPSBibnBETFNoaWZ0VG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kclNoaWZ0VG8gPSBibnBEUlNoaWZ0VG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5sU2hpZnRUbyA9IGJucExTaGlmdFRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuclNoaWZ0VG8gPSBibnBSU2hpZnRUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLnN1YlRvID0gYm5wU3ViVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tdWx0aXBseVRvID0gYm5wTXVsdGlwbHlUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLnNxdWFyZVRvID0gYm5wU3F1YXJlVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kaXZSZW1UbyA9IGJucERpdlJlbVRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuaW52RGlnaXQgPSBibnBJbnZEaWdpdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmlzRXZlbiA9IGJucElzRXZlbjtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmV4cCA9IGJucEV4cDtcblxuLy8gcHVibGljXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS50b1N0cmluZyA9IGJuVG9TdHJpbmc7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5uZWdhdGUgPSBibk5lZ2F0ZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmFicyA9IGJuQWJzO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuY29tcGFyZVRvID0gYm5Db21wYXJlVG87XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5iaXRMZW5ndGggPSBibkJpdExlbmd0aDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1vZCA9IGJuTW9kO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubW9kUG93SW50ID0gYm5Nb2RQb3dJbnQ7XG5cbi8vIFwiY29uc3RhbnRzXCJcbkJpZ0ludGVnZXIuWkVSTyA9IG5idigwKTtcbkJpZ0ludGVnZXIuT05FID0gbmJ2KDEpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEJpZ0ludGVnZXI7XG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMDMtMjAwNSAgVG9tIFd1ICh0andAY3MuU3RhbmZvcmQuRURVKSBcbiAqIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogTW9kaWZpZWQgYnkgUmVjdXJpdHkgTGFicyBHbWJIXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nXG4gKiBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbiAqIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuICogd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuICogZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvXG4gKiBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG9cbiAqIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMtSVNcIiBBTkQgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgXG4gKiBFWFBSRVNTLCBJTVBMSUVEIE9SIE9USEVSV0lTRSwgSU5DTFVESU5HIFdJVEhPVVQgTElNSVRBVElPTiwgQU5ZIFxuICogV0FSUkFOVFkgT0YgTUVSQ0hBTlRBQklMSVRZIE9SIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgXG4gKlxuICogSU4gTk8gRVZFTlQgU0hBTEwgVE9NIFdVIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIElOQ0lERU5UQUwsXG4gKiBJTkRJUkVDVCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT0YgQU5ZIEtJTkQsIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVJcbiAqIFJFU1VMVElORyBGUk9NIExPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgT1IgTk9UIEFEVklTRUQgT0ZcbiAqIFRIRSBQT1NTSUJJTElUWSBPRiBEQU1BR0UsIEFORCBPTiBBTlkgVEhFT1JZIE9GIExJQUJJTElUWSwgQVJJU0lORyBPVVRcbiAqIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SIFBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXG4gKlxuICogSW4gYWRkaXRpb24sIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uIGFwcGxpZXM6XG4gKlxuICogQWxsIHJlZGlzdHJpYnV0aW9ucyBtdXN0IHJldGFpbiBhbiBpbnRhY3QgY29weSBvZiB0aGlzIGNvcHlyaWdodCBub3RpY2VcbiAqIGFuZCBkaXNjbGFpbWVyLlxuICovXG5cblxuLy8gRXh0ZW5kZWQgSmF2YVNjcmlwdCBCTiBmdW5jdGlvbnMsIHJlcXVpcmVkIGZvciBSU0EgcHJpdmF0ZSBvcHMuXG5cbi8vIFZlcnNpb24gMS4xOiBuZXcgQmlnSW50ZWdlcihcIjBcIiwgMTApIHJldHVybnMgXCJwcm9wZXJcIiB6ZXJvXG4vLyBWZXJzaW9uIDEuMjogc3F1YXJlKCkgQVBJLCBpc1Byb2JhYmxlUHJpbWUgZml4XG5cbi8vIChwdWJsaWMpXG5mdW5jdGlvbiBibkNsb25lKCkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmNvcHlUbyhyKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiB2YWx1ZSBhcyBpbnRlZ2VyXG5cbmZ1bmN0aW9uIGJuSW50VmFsdWUoKSB7XG4gIGlmICh0aGlzLnMgPCAwKSB7XG4gICAgaWYgKHRoaXMudCA9PSAxKSByZXR1cm4gdGhpc1swXSAtIHRoaXMuRFY7XG4gICAgZWxzZSBpZiAodGhpcy50ID09IDApIHJldHVybiAtMTtcbiAgfSBlbHNlIGlmICh0aGlzLnQgPT0gMSkgcmV0dXJuIHRoaXNbMF07XG4gIGVsc2UgaWYgKHRoaXMudCA9PSAwKSByZXR1cm4gMDtcbiAgLy8gYXNzdW1lcyAxNiA8IERCIDwgMzJcbiAgcmV0dXJuICgodGhpc1sxXSAmICgoMSA8PCAoMzIgLSB0aGlzLkRCKSkgLSAxKSkgPDwgdGhpcy5EQikgfCB0aGlzWzBdO1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gdmFsdWUgYXMgYnl0ZVxuXG5mdW5jdGlvbiBibkJ5dGVWYWx1ZSgpIHtcbiAgcmV0dXJuICh0aGlzLnQgPT0gMCkgPyB0aGlzLnMgOiAodGhpc1swXSA8PCAyNCkgPj4gMjQ7XG59XG5cbi8vIChwdWJsaWMpIHJldHVybiB2YWx1ZSBhcyBzaG9ydCAoYXNzdW1lcyBEQj49MTYpXG5cbmZ1bmN0aW9uIGJuU2hvcnRWYWx1ZSgpIHtcbiAgcmV0dXJuICh0aGlzLnQgPT0gMCkgPyB0aGlzLnMgOiAodGhpc1swXSA8PCAxNikgPj4gMTY7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHJldHVybiB4IHMudC4gcl54IDwgRFZcblxuZnVuY3Rpb24gYm5wQ2h1bmtTaXplKHIpIHtcbiAgcmV0dXJuIE1hdGguZmxvb3IoTWF0aC5MTjIgKiB0aGlzLkRCIC8gTWF0aC5sb2cocikpO1xufVxuXG4vLyAocHVibGljKSAwIGlmIHRoaXMgPT0gMCwgMSBpZiB0aGlzID4gMFxuXG5mdW5jdGlvbiBiblNpZ051bSgpIHtcbiAgaWYgKHRoaXMucyA8IDApIHJldHVybiAtMTtcbiAgZWxzZSBpZiAodGhpcy50IDw9IDAgfHwgKHRoaXMudCA9PSAxICYmIHRoaXNbMF0gPD0gMCkpIHJldHVybiAwO1xuICBlbHNlIHJldHVybiAxO1xufVxuXG4vLyAocHJvdGVjdGVkKSBjb252ZXJ0IHRvIHJhZGl4IHN0cmluZ1xuXG5mdW5jdGlvbiBibnBUb1JhZGl4KGIpIHtcbiAgaWYgKGIgPT0gbnVsbCkgYiA9IDEwO1xuICBpZiAodGhpcy5zaWdudW0oKSA9PSAwIHx8IGIgPCAyIHx8IGIgPiAzNikgcmV0dXJuIFwiMFwiO1xuICB2YXIgY3MgPSB0aGlzLmNodW5rU2l6ZShiKTtcbiAgdmFyIGEgPSBNYXRoLnBvdyhiLCBjcyk7XG4gIHZhciBkID0gbmJ2KGEpLFxuICAgIHkgPSBuYmkoKSxcbiAgICB6ID0gbmJpKCksXG4gICAgciA9IFwiXCI7XG4gIHRoaXMuZGl2UmVtVG8oZCwgeSwgeik7XG4gIHdoaWxlICh5LnNpZ251bSgpID4gMCkge1xuICAgIHIgPSAoYSArIHouaW50VmFsdWUoKSkudG9TdHJpbmcoYikuc3Vic3RyKDEpICsgcjtcbiAgICB5LmRpdlJlbVRvKGQsIHksIHopO1xuICB9XG4gIHJldHVybiB6LmludFZhbHVlKCkudG9TdHJpbmcoYikgKyByO1xufVxuXG4vLyAocHJvdGVjdGVkKSBjb252ZXJ0IGZyb20gcmFkaXggc3RyaW5nXG5cbmZ1bmN0aW9uIGJucEZyb21SYWRpeChzLCBiKSB7XG4gIHRoaXMuZnJvbUludCgwKTtcbiAgaWYgKGIgPT0gbnVsbCkgYiA9IDEwO1xuICB2YXIgY3MgPSB0aGlzLmNodW5rU2l6ZShiKTtcbiAgdmFyIGQgPSBNYXRoLnBvdyhiLCBjcyksXG4gICAgbWkgPSBmYWxzZSxcbiAgICBqID0gMCxcbiAgICB3ID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHggPSBpbnRBdChzLCBpKTtcbiAgICBpZiAoeCA8IDApIHtcbiAgICAgIGlmIChzLmNoYXJBdChpKSA9PSBcIi1cIiAmJiB0aGlzLnNpZ251bSgpID09IDApIG1pID0gdHJ1ZTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICB3ID0gYiAqIHcgKyB4O1xuICAgIGlmICgrK2ogPj0gY3MpIHtcbiAgICAgIHRoaXMuZE11bHRpcGx5KGQpO1xuICAgICAgdGhpcy5kQWRkT2Zmc2V0KHcsIDApO1xuICAgICAgaiA9IDA7XG4gICAgICB3ID0gMDtcbiAgICB9XG4gIH1cbiAgaWYgKGogPiAwKSB7XG4gICAgdGhpcy5kTXVsdGlwbHkoTWF0aC5wb3coYiwgaikpO1xuICAgIHRoaXMuZEFkZE9mZnNldCh3LCAwKTtcbiAgfVxuICBpZiAobWkpIEJpZ0ludGVnZXIuWkVSTy5zdWJUbyh0aGlzLCB0aGlzKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgYWx0ZXJuYXRlIGNvbnN0cnVjdG9yXG5cbmZ1bmN0aW9uIGJucEZyb21OdW1iZXIoYSwgYiwgYykge1xuICBpZiAoXCJudW1iZXJcIiA9PSB0eXBlb2YgYikge1xuICAgIC8vIG5ldyBCaWdJbnRlZ2VyKGludCxpbnQsUk5HKVxuICAgIGlmIChhIDwgMikgdGhpcy5mcm9tSW50KDEpO1xuICAgIGVsc2Uge1xuICAgICAgdGhpcy5mcm9tTnVtYmVyKGEsIGMpO1xuICAgICAgaWYgKCF0aGlzLnRlc3RCaXQoYSAtIDEpKSAvLyBmb3JjZSBNU0Igc2V0XG4gICAgICAgIHRoaXMuYml0d2lzZVRvKEJpZ0ludGVnZXIuT05FLnNoaWZ0TGVmdChhIC0gMSksIG9wX29yLCB0aGlzKTtcbiAgICAgIGlmICh0aGlzLmlzRXZlbigpKSB0aGlzLmRBZGRPZmZzZXQoMSwgMCk7IC8vIGZvcmNlIG9kZFxuICAgICAgd2hpbGUgKCF0aGlzLmlzUHJvYmFibGVQcmltZShiKSkge1xuICAgICAgICB0aGlzLmRBZGRPZmZzZXQoMiwgMCk7XG4gICAgICAgIGlmICh0aGlzLmJpdExlbmd0aCgpID4gYSkgdGhpcy5zdWJUbyhCaWdJbnRlZ2VyLk9ORS5zaGlmdExlZnQoYSAtIDEpLCB0aGlzKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gbmV3IEJpZ0ludGVnZXIoaW50LFJORylcbiAgICB2YXIgeCA9IG5ldyBBcnJheSgpLFxuICAgICAgdCA9IGEgJiA3O1xuICAgIHgubGVuZ3RoID0gKGEgPj4gMykgKyAxO1xuICAgIGIubmV4dEJ5dGVzKHgpO1xuICAgIGlmICh0ID4gMCkgeFswXSAmPSAoKDEgPDwgdCkgLSAxKTtcbiAgICBlbHNlIHhbMF0gPSAwO1xuICAgIHRoaXMuZnJvbVN0cmluZyh4LCAyNTYpO1xuICB9XG59XG5cbi8vIChwdWJsaWMpIGNvbnZlcnQgdG8gYmlnZW5kaWFuIGJ5dGUgYXJyYXlcblxuZnVuY3Rpb24gYm5Ub0J5dGVBcnJheSgpIHtcbiAgdmFyIGkgPSB0aGlzLnQsXG4gICAgciA9IG5ldyBBcnJheSgpO1xuICByWzBdID0gdGhpcy5zO1xuICB2YXIgcCA9IHRoaXMuREIgLSAoaSAqIHRoaXMuREIpICUgOCxcbiAgICBkLCBrID0gMDtcbiAgaWYgKGktLSA+IDApIHtcbiAgICBpZiAocCA8IHRoaXMuREIgJiYgKGQgPSB0aGlzW2ldID4+IHApICE9ICh0aGlzLnMgJiB0aGlzLkRNKSA+PiBwKVxuICAgICAgcltrKytdID0gZCB8ICh0aGlzLnMgPDwgKHRoaXMuREIgLSBwKSk7XG4gICAgd2hpbGUgKGkgPj0gMCkge1xuICAgICAgaWYgKHAgPCA4KSB7XG4gICAgICAgIGQgPSAodGhpc1tpXSAmICgoMSA8PCBwKSAtIDEpKSA8PCAoOCAtIHApO1xuICAgICAgICBkIHw9IHRoaXNbLS1pXSA+PiAocCArPSB0aGlzLkRCIC0gOCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkID0gKHRoaXNbaV0gPj4gKHAgLT0gOCkpICYgMHhmZjtcbiAgICAgICAgaWYgKHAgPD0gMCkge1xuICAgICAgICAgIHAgKz0gdGhpcy5EQjtcbiAgICAgICAgICAtLWk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vaWYoKGQmMHg4MCkgIT0gMCkgZCB8PSAtMjU2O1xuICAgICAgLy9pZihrID09IDAgJiYgKHRoaXMucyYweDgwKSAhPSAoZCYweDgwKSkgKytrO1xuICAgICAgaWYgKGsgPiAwIHx8IGQgIT0gdGhpcy5zKSByW2srK10gPSBkO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcjtcbn1cblxuZnVuY3Rpb24gYm5FcXVhbHMoYSkge1xuICByZXR1cm4gKHRoaXMuY29tcGFyZVRvKGEpID09IDApO1xufVxuXG5mdW5jdGlvbiBibk1pbihhKSB7XG4gIHJldHVybiAodGhpcy5jb21wYXJlVG8oYSkgPCAwKSA/IHRoaXMgOiBhO1xufVxuXG5mdW5jdGlvbiBibk1heChhKSB7XG4gIHJldHVybiAodGhpcy5jb21wYXJlVG8oYSkgPiAwKSA/IHRoaXMgOiBhO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyBvcCBhIChiaXR3aXNlKVxuXG5mdW5jdGlvbiBibnBCaXR3aXNlVG8oYSwgb3AsIHIpIHtcbiAgdmFyIGksIGYsIG0gPSBNYXRoLm1pbihhLnQsIHRoaXMudCk7XG4gIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIHJbaV0gPSBvcCh0aGlzW2ldLCBhW2ldKTtcbiAgaWYgKGEudCA8IHRoaXMudCkge1xuICAgIGYgPSBhLnMgJiB0aGlzLkRNO1xuICAgIGZvciAoaSA9IG07IGkgPCB0aGlzLnQ7ICsraSkgcltpXSA9IG9wKHRoaXNbaV0sIGYpO1xuICAgIHIudCA9IHRoaXMudDtcbiAgfSBlbHNlIHtcbiAgICBmID0gdGhpcy5zICYgdGhpcy5ETTtcbiAgICBmb3IgKGkgPSBtOyBpIDwgYS50OyArK2kpIHJbaV0gPSBvcChmLCBhW2ldKTtcbiAgICByLnQgPSBhLnQ7XG4gIH1cbiAgci5zID0gb3AodGhpcy5zLCBhLnMpO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgJiBhXG5cbmZ1bmN0aW9uIG9wX2FuZCh4LCB5KSB7XG4gIHJldHVybiB4ICYgeTtcbn1cblxuZnVuY3Rpb24gYm5BbmQoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmJpdHdpc2VUbyhhLCBvcF9hbmQsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyB8IGFcblxuZnVuY3Rpb24gb3Bfb3IoeCwgeSkge1xuICByZXR1cm4geCB8IHk7XG59XG5cbmZ1bmN0aW9uIGJuT3IoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLmJpdHdpc2VUbyhhLCBvcF9vciwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB0aGlzIF4gYVxuXG5mdW5jdGlvbiBvcF94b3IoeCwgeSkge1xuICByZXR1cm4geCBeIHk7XG59XG5cbmZ1bmN0aW9uIGJuWG9yKGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5iaXR3aXNlVG8oYSwgb3BfeG9yLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgJiB+YVxuXG5mdW5jdGlvbiBvcF9hbmRub3QoeCwgeSkge1xuICByZXR1cm4geCAmIH55O1xufVxuXG5mdW5jdGlvbiBibkFuZE5vdChhKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHRoaXMuYml0d2lzZVRvKGEsIG9wX2FuZG5vdCwgcik7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSB+dGhpc1xuXG5mdW5jdGlvbiBibk5vdCgpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnQ7ICsraSkgcltpXSA9IHRoaXMuRE0gJiB+dGhpc1tpXTtcbiAgci50ID0gdGhpcy50O1xuICByLnMgPSB+dGhpcy5zO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyA8PCBuXG5cbmZ1bmN0aW9uIGJuU2hpZnRMZWZ0KG4pIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgaWYgKG4gPCAwKSB0aGlzLnJTaGlmdFRvKC1uLCByKTtcbiAgZWxzZSB0aGlzLmxTaGlmdFRvKG4sIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyA+PiBuXG5cbmZ1bmN0aW9uIGJuU2hpZnRSaWdodChuKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIGlmIChuIDwgMCkgdGhpcy5sU2hpZnRUbygtbiwgcik7XG4gIGVsc2UgdGhpcy5yU2hpZnRUbyhuLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIHJldHVybiBpbmRleCBvZiBsb3dlc3QgMS1iaXQgaW4geCwgeCA8IDJeMzFcblxuZnVuY3Rpb24gbGJpdCh4KSB7XG4gIGlmICh4ID09IDApIHJldHVybiAtMTtcbiAgdmFyIHIgPSAwO1xuICBpZiAoKHggJiAweGZmZmYpID09IDApIHtcbiAgICB4ID4+PSAxNjtcbiAgICByICs9IDE2O1xuICB9XG4gIGlmICgoeCAmIDB4ZmYpID09IDApIHtcbiAgICB4ID4+PSA4O1xuICAgIHIgKz0gODtcbiAgfVxuICBpZiAoKHggJiAweGYpID09IDApIHtcbiAgICB4ID4+PSA0O1xuICAgIHIgKz0gNDtcbiAgfVxuICBpZiAoKHggJiAzKSA9PSAwKSB7XG4gICAgeCA+Pj0gMjtcbiAgICByICs9IDI7XG4gIH1cbiAgaWYgKCh4ICYgMSkgPT0gMCkrK3I7XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSByZXR1cm5zIGluZGV4IG9mIGxvd2VzdCAxLWJpdCAob3IgLTEgaWYgbm9uZSlcblxuZnVuY3Rpb24gYm5HZXRMb3dlc3RTZXRCaXQoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy50OyArK2kpXG4gICAgaWYgKHRoaXNbaV0gIT0gMCkgcmV0dXJuIGkgKiB0aGlzLkRCICsgbGJpdCh0aGlzW2ldKTtcbiAgaWYgKHRoaXMucyA8IDApIHJldHVybiB0aGlzLnQgKiB0aGlzLkRCO1xuICByZXR1cm4gLTE7XG59XG5cbi8vIHJldHVybiBudW1iZXIgb2YgMSBiaXRzIGluIHhcblxuZnVuY3Rpb24gY2JpdCh4KSB7XG4gIHZhciByID0gMDtcbiAgd2hpbGUgKHggIT0gMCkge1xuICAgIHggJj0geCAtIDE7XG4gICAgKytyO1xuICB9XG4gIHJldHVybiByO1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gbnVtYmVyIG9mIHNldCBiaXRzXG5cbmZ1bmN0aW9uIGJuQml0Q291bnQoKSB7XG4gIHZhciByID0gMCxcbiAgICB4ID0gdGhpcy5zICYgdGhpcy5ETTtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnQ7ICsraSkgciArPSBjYml0KHRoaXNbaV0gXiB4KTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRydWUgaWZmIG50aCBiaXQgaXMgc2V0XG5cbmZ1bmN0aW9uIGJuVGVzdEJpdChuKSB7XG4gIHZhciBqID0gTWF0aC5mbG9vcihuIC8gdGhpcy5EQik7XG4gIGlmIChqID49IHRoaXMudCkgcmV0dXJuICh0aGlzLnMgIT0gMCk7XG4gIHJldHVybiAoKHRoaXNbal0gJiAoMSA8PCAobiAlIHRoaXMuREIpKSkgIT0gMCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgb3AgKDE8PG4pXG5cbmZ1bmN0aW9uIGJucENoYW5nZUJpdChuLCBvcCkge1xuICB2YXIgciA9IEJpZ0ludGVnZXIuT05FLnNoaWZ0TGVmdChuKTtcbiAgdGhpcy5iaXR3aXNlVG8ociwgb3AsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyB8ICgxPDxuKVxuXG5mdW5jdGlvbiBiblNldEJpdChuKSB7XG4gIHJldHVybiB0aGlzLmNoYW5nZUJpdChuLCBvcF9vcik7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgJiB+KDE8PG4pXG5cbmZ1bmN0aW9uIGJuQ2xlYXJCaXQobikge1xuICByZXR1cm4gdGhpcy5jaGFuZ2VCaXQobiwgb3BfYW5kbm90KTtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyBeICgxPDxuKVxuXG5mdW5jdGlvbiBibkZsaXBCaXQobikge1xuICByZXR1cm4gdGhpcy5jaGFuZ2VCaXQobiwgb3BfeG9yKTtcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXMgKyBhXG5cbmZ1bmN0aW9uIGJucEFkZFRvKGEsIHIpIHtcbiAgdmFyIGkgPSAwLFxuICAgIGMgPSAwLFxuICAgIG0gPSBNYXRoLm1pbihhLnQsIHRoaXMudCk7XG4gIHdoaWxlIChpIDwgbSkge1xuICAgIGMgKz0gdGhpc1tpXSArIGFbaV07XG4gICAgcltpKytdID0gYyAmIHRoaXMuRE07XG4gICAgYyA+Pj0gdGhpcy5EQjtcbiAgfVxuICBpZiAoYS50IDwgdGhpcy50KSB7XG4gICAgYyArPSBhLnM7XG4gICAgd2hpbGUgKGkgPCB0aGlzLnQpIHtcbiAgICAgIGMgKz0gdGhpc1tpXTtcbiAgICAgIHJbaSsrXSA9IGMgJiB0aGlzLkRNO1xuICAgICAgYyA+Pj0gdGhpcy5EQjtcbiAgICB9XG4gICAgYyArPSB0aGlzLnM7XG4gIH0gZWxzZSB7XG4gICAgYyArPSB0aGlzLnM7XG4gICAgd2hpbGUgKGkgPCBhLnQpIHtcbiAgICAgIGMgKz0gYVtpXTtcbiAgICAgIHJbaSsrXSA9IGMgJiB0aGlzLkRNO1xuICAgICAgYyA+Pj0gdGhpcy5EQjtcbiAgICB9XG4gICAgYyArPSBhLnM7XG4gIH1cbiAgci5zID0gKGMgPCAwKSA/IC0xIDogMDtcbiAgaWYgKGMgPiAwKSByW2krK10gPSBjO1xuICBlbHNlIGlmIChjIDwgLTEpIHJbaSsrXSA9IHRoaXMuRFYgKyBjO1xuICByLnQgPSBpO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgKyBhXG5cbmZ1bmN0aW9uIGJuQWRkKGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5hZGRUbyhhLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgLSBhXG5cbmZ1bmN0aW9uIGJuU3VidHJhY3QoYSkge1xuICB2YXIgciA9IG5iaSgpO1xuICB0aGlzLnN1YlRvKGEsIHIpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gKHB1YmxpYykgdGhpcyAqIGFcblxuZnVuY3Rpb24gYm5NdWx0aXBseShhKSB7XG4gIHZhciByID0gbmJpKCk7XG4gIHRoaXMubXVsdGlwbHlUbyhhLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXNeMlxuXG5mdW5jdGlvbiBiblNxdWFyZSgpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5zcXVhcmVUbyhyKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgLyBhXG5cbmZ1bmN0aW9uIGJuRGl2aWRlKGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5kaXZSZW1UbyhhLCByLCBudWxsKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIHRoaXMgJSBhXG5cbmZ1bmN0aW9uIGJuUmVtYWluZGVyKGEpIHtcbiAgdmFyIHIgPSBuYmkoKTtcbiAgdGhpcy5kaXZSZW1UbyhhLCBudWxsLCByKTtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIFt0aGlzL2EsdGhpcyVhXVxuXG5mdW5jdGlvbiBibkRpdmlkZUFuZFJlbWFpbmRlcihhKSB7XG4gIHZhciBxID0gbmJpKCksXG4gICAgciA9IG5iaSgpO1xuICB0aGlzLmRpdlJlbVRvKGEsIHEsIHIpO1xuICByZXR1cm4gbmV3IEFycmF5KHEsIHIpO1xufVxuXG4vLyAocHJvdGVjdGVkKSB0aGlzICo9IG4sIHRoaXMgPj0gMCwgMSA8IG4gPCBEVlxuXG5mdW5jdGlvbiBibnBETXVsdGlwbHkobikge1xuICB0aGlzW3RoaXMudF0gPSB0aGlzLmFtKDAsIG4gLSAxLCB0aGlzLCAwLCAwLCB0aGlzLnQpO1xuICArK3RoaXMudDtcbiAgdGhpcy5jbGFtcCgpO1xufVxuXG4vLyAocHJvdGVjdGVkKSB0aGlzICs9IG4gPDwgdyB3b3JkcywgdGhpcyA+PSAwXG5cbmZ1bmN0aW9uIGJucERBZGRPZmZzZXQobiwgdykge1xuICBpZiAobiA9PSAwKSByZXR1cm47XG4gIHdoaWxlICh0aGlzLnQgPD0gdykgdGhpc1t0aGlzLnQrK10gPSAwO1xuICB0aGlzW3ddICs9IG47XG4gIHdoaWxlICh0aGlzW3ddID49IHRoaXMuRFYpIHtcbiAgICB0aGlzW3ddIC09IHRoaXMuRFY7XG4gICAgaWYgKCsrdyA+PSB0aGlzLnQpIHRoaXNbdGhpcy50KytdID0gMDtcbiAgICArK3RoaXNbd107XG4gIH1cbn1cblxuLy8gQSBcIm51bGxcIiByZWR1Y2VyXG5cbmZ1bmN0aW9uIE51bGxFeHAoKSB7fVxuXG5mdW5jdGlvbiBuTm9wKHgpIHtcbiAgcmV0dXJuIHg7XG59XG5cbmZ1bmN0aW9uIG5NdWxUbyh4LCB5LCByKSB7XG4gIHgubXVsdGlwbHlUbyh5LCByKTtcbn1cblxuZnVuY3Rpb24gblNxclRvKHgsIHIpIHtcbiAgeC5zcXVhcmVUbyhyKTtcbn1cblxuTnVsbEV4cC5wcm90b3R5cGUuY29udmVydCA9IG5Ob3A7XG5OdWxsRXhwLnByb3RvdHlwZS5yZXZlcnQgPSBuTm9wO1xuTnVsbEV4cC5wcm90b3R5cGUubXVsVG8gPSBuTXVsVG87XG5OdWxsRXhwLnByb3RvdHlwZS5zcXJUbyA9IG5TcXJUbztcblxuLy8gKHB1YmxpYykgdGhpc15lXG5cbmZ1bmN0aW9uIGJuUG93KGUpIHtcbiAgcmV0dXJuIHRoaXMuZXhwKGUsIG5ldyBOdWxsRXhwKCkpO1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gbG93ZXIgbiB3b3JkcyBvZiBcInRoaXMgKiBhXCIsIGEudCA8PSBuXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5cbmZ1bmN0aW9uIGJucE11bHRpcGx5TG93ZXJUbyhhLCBuLCByKSB7XG4gIHZhciBpID0gTWF0aC5taW4odGhpcy50ICsgYS50LCBuKTtcbiAgci5zID0gMDsgLy8gYXNzdW1lcyBhLHRoaXMgPj0gMFxuICByLnQgPSBpO1xuICB3aGlsZSAoaSA+IDApIHJbLS1pXSA9IDA7XG4gIHZhciBqO1xuICBmb3IgKGogPSByLnQgLSB0aGlzLnQ7IGkgPCBqOyArK2kpIHJbaSArIHRoaXMudF0gPSB0aGlzLmFtKDAsIGFbaV0sIHIsIGksIDAsIHRoaXMudCk7XG4gIGZvciAoaiA9IE1hdGgubWluKGEudCwgbik7IGkgPCBqOyArK2kpIHRoaXMuYW0oMCwgYVtpXSwgciwgaSwgMCwgbiAtIGkpO1xuICByLmNsYW1wKCk7XG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSBcInRoaXMgKiBhXCIgd2l0aG91dCBsb3dlciBuIHdvcmRzLCBuID4gMFxuLy8gXCJ0aGlzXCIgc2hvdWxkIGJlIHRoZSBsYXJnZXIgb25lIGlmIGFwcHJvcHJpYXRlLlxuXG5mdW5jdGlvbiBibnBNdWx0aXBseVVwcGVyVG8oYSwgbiwgcikge1xuICAtLW47XG4gIHZhciBpID0gci50ID0gdGhpcy50ICsgYS50IC0gbjtcbiAgci5zID0gMDsgLy8gYXNzdW1lcyBhLHRoaXMgPj0gMFxuICB3aGlsZSAoLS1pID49IDApIHJbaV0gPSAwO1xuICBmb3IgKGkgPSBNYXRoLm1heChuIC0gdGhpcy50LCAwKTsgaSA8IGEudDsgKytpKVxuICAgIHJbdGhpcy50ICsgaSAtIG5dID0gdGhpcy5hbShuIC0gaSwgYVtpXSwgciwgMCwgMCwgdGhpcy50ICsgaSAtIG4pO1xuICByLmNsYW1wKCk7XG4gIHIuZHJTaGlmdFRvKDEsIHIpO1xufVxuXG4vLyBCYXJyZXR0IG1vZHVsYXIgcmVkdWN0aW9uXG5cbmZ1bmN0aW9uIEJhcnJldHQobSkge1xuICAvLyBzZXR1cCBCYXJyZXR0XG4gIHRoaXMucjIgPSBuYmkoKTtcbiAgdGhpcy5xMyA9IG5iaSgpO1xuICBCaWdJbnRlZ2VyLk9ORS5kbFNoaWZ0VG8oMiAqIG0udCwgdGhpcy5yMik7XG4gIHRoaXMubXUgPSB0aGlzLnIyLmRpdmlkZShtKTtcbiAgdGhpcy5tID0gbTtcbn1cblxuZnVuY3Rpb24gYmFycmV0dENvbnZlcnQoeCkge1xuICBpZiAoeC5zIDwgMCB8fCB4LnQgPiAyICogdGhpcy5tLnQpIHJldHVybiB4Lm1vZCh0aGlzLm0pO1xuICBlbHNlIGlmICh4LmNvbXBhcmVUbyh0aGlzLm0pIDwgMCkgcmV0dXJuIHg7XG4gIGVsc2Uge1xuICAgIHZhciByID0gbmJpKCk7XG4gICAgeC5jb3B5VG8ocik7XG4gICAgdGhpcy5yZWR1Y2Uocik7XG4gICAgcmV0dXJuIHI7XG4gIH1cbn1cblxuZnVuY3Rpb24gYmFycmV0dFJldmVydCh4KSB7XG4gIHJldHVybiB4O1xufVxuXG4vLyB4ID0geCBtb2QgbSAoSEFDIDE0LjQyKVxuXG5mdW5jdGlvbiBiYXJyZXR0UmVkdWNlKHgpIHtcbiAgeC5kclNoaWZ0VG8odGhpcy5tLnQgLSAxLCB0aGlzLnIyKTtcbiAgaWYgKHgudCA+IHRoaXMubS50ICsgMSkge1xuICAgIHgudCA9IHRoaXMubS50ICsgMTtcbiAgICB4LmNsYW1wKCk7XG4gIH1cbiAgdGhpcy5tdS5tdWx0aXBseVVwcGVyVG8odGhpcy5yMiwgdGhpcy5tLnQgKyAxLCB0aGlzLnEzKTtcbiAgdGhpcy5tLm11bHRpcGx5TG93ZXJUbyh0aGlzLnEzLCB0aGlzLm0udCArIDEsIHRoaXMucjIpO1xuICB3aGlsZSAoeC5jb21wYXJlVG8odGhpcy5yMikgPCAwKSB4LmRBZGRPZmZzZXQoMSwgdGhpcy5tLnQgKyAxKTtcbiAgeC5zdWJUbyh0aGlzLnIyLCB4KTtcbiAgd2hpbGUgKHguY29tcGFyZVRvKHRoaXMubSkgPj0gMCkgeC5zdWJUbyh0aGlzLm0sIHgpO1xufVxuXG4vLyByID0geF4yIG1vZCBtOyB4ICE9IHJcblxuZnVuY3Rpb24gYmFycmV0dFNxclRvKHgsIHIpIHtcbiAgeC5zcXVhcmVUbyhyKTtcbiAgdGhpcy5yZWR1Y2Uocik7XG59XG5cbi8vIHIgPSB4KnkgbW9kIG07IHgseSAhPSByXG5cbmZ1bmN0aW9uIGJhcnJldHRNdWxUbyh4LCB5LCByKSB7XG4gIHgubXVsdGlwbHlUbyh5LCByKTtcbiAgdGhpcy5yZWR1Y2Uocik7XG59XG5cbkJhcnJldHQucHJvdG90eXBlLmNvbnZlcnQgPSBiYXJyZXR0Q29udmVydDtcbkJhcnJldHQucHJvdG90eXBlLnJldmVydCA9IGJhcnJldHRSZXZlcnQ7XG5CYXJyZXR0LnByb3RvdHlwZS5yZWR1Y2UgPSBiYXJyZXR0UmVkdWNlO1xuQmFycmV0dC5wcm90b3R5cGUubXVsVG8gPSBiYXJyZXR0TXVsVG87XG5CYXJyZXR0LnByb3RvdHlwZS5zcXJUbyA9IGJhcnJldHRTcXJUbztcblxuLy8gKHB1YmxpYykgdGhpc15lICUgbSAoSEFDIDE0Ljg1KVxuXG5mdW5jdGlvbiBibk1vZFBvdyhlLCBtKSB7XG4gIHZhciBpID0gZS5iaXRMZW5ndGgoKSxcbiAgICBrLCByID0gbmJ2KDEpLFxuICAgIHo7XG4gIGlmIChpIDw9IDApIHJldHVybiByO1xuICBlbHNlIGlmIChpIDwgMTgpIGsgPSAxO1xuICBlbHNlIGlmIChpIDwgNDgpIGsgPSAzO1xuICBlbHNlIGlmIChpIDwgMTQ0KSBrID0gNDtcbiAgZWxzZSBpZiAoaSA8IDc2OCkgayA9IDU7XG4gIGVsc2UgayA9IDY7XG4gIGlmIChpIDwgOClcbiAgICB6ID0gbmV3IENsYXNzaWMobSk7XG4gIGVsc2UgaWYgKG0uaXNFdmVuKCkpXG4gICAgeiA9IG5ldyBCYXJyZXR0KG0pO1xuICBlbHNlXG4gICAgeiA9IG5ldyBNb250Z29tZXJ5KG0pO1xuXG4gIC8vIHByZWNvbXB1dGF0aW9uXG4gIHZhciBnID0gbmV3IEFycmF5KCksXG4gICAgbiA9IDMsXG4gICAgazEgPSBrIC0gMSxcbiAgICBrbSA9ICgxIDw8IGspIC0gMTtcbiAgZ1sxXSA9IHouY29udmVydCh0aGlzKTtcbiAgaWYgKGsgPiAxKSB7XG4gICAgdmFyIGcyID0gbmJpKCk7XG4gICAgei5zcXJUbyhnWzFdLCBnMik7XG4gICAgd2hpbGUgKG4gPD0ga20pIHtcbiAgICAgIGdbbl0gPSBuYmkoKTtcbiAgICAgIHoubXVsVG8oZzIsIGdbbiAtIDJdLCBnW25dKTtcbiAgICAgIG4gKz0gMjtcbiAgICB9XG4gIH1cblxuICB2YXIgaiA9IGUudCAtIDEsXG4gICAgdywgaXMxID0gdHJ1ZSxcbiAgICByMiA9IG5iaSgpLFxuICAgIHQ7XG4gIGkgPSBuYml0cyhlW2pdKSAtIDE7XG4gIHdoaWxlIChqID49IDApIHtcbiAgICBpZiAoaSA+PSBrMSkgdyA9IChlW2pdID4+IChpIC0gazEpKSAmIGttO1xuICAgIGVsc2Uge1xuICAgICAgdyA9IChlW2pdICYgKCgxIDw8IChpICsgMSkpIC0gMSkpIDw8IChrMSAtIGkpO1xuICAgICAgaWYgKGogPiAwKSB3IHw9IGVbaiAtIDFdID4+ICh0aGlzLkRCICsgaSAtIGsxKTtcbiAgICB9XG5cbiAgICBuID0gaztcbiAgICB3aGlsZSAoKHcgJiAxKSA9PSAwKSB7XG4gICAgICB3ID4+PSAxO1xuICAgICAgLS1uO1xuICAgIH1cbiAgICBpZiAoKGkgLT0gbikgPCAwKSB7XG4gICAgICBpICs9IHRoaXMuREI7XG4gICAgICAtLWo7XG4gICAgfVxuICAgIGlmIChpczEpIHsgLy8gcmV0ID09IDEsIGRvbid0IGJvdGhlciBzcXVhcmluZyBvciBtdWx0aXBseWluZyBpdFxuICAgICAgZ1t3XS5jb3B5VG8ocik7XG4gICAgICBpczEgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2hpbGUgKG4gPiAxKSB7XG4gICAgICAgIHouc3FyVG8ociwgcjIpO1xuICAgICAgICB6LnNxclRvKHIyLCByKTtcbiAgICAgICAgbiAtPSAyO1xuICAgICAgfVxuICAgICAgaWYgKG4gPiAwKSB6LnNxclRvKHIsIHIyKTtcbiAgICAgIGVsc2Uge1xuICAgICAgICB0ID0gcjtcbiAgICAgICAgciA9IHIyO1xuICAgICAgICByMiA9IHQ7XG4gICAgICB9XG4gICAgICB6Lm11bFRvKHIyLCBnW3ddLCByKTtcbiAgICB9XG5cbiAgICB3aGlsZSAoaiA+PSAwICYmIChlW2pdICYgKDEgPDwgaSkpID09IDApIHtcbiAgICAgIHouc3FyVG8ociwgcjIpO1xuICAgICAgdCA9IHI7XG4gICAgICByID0gcjI7XG4gICAgICByMiA9IHQ7XG4gICAgICBpZiAoLS1pIDwgMCkge1xuICAgICAgICBpID0gdGhpcy5EQiAtIDE7XG4gICAgICAgIC0tajtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHoucmV2ZXJ0KHIpO1xufVxuXG4vLyAocHVibGljKSBnY2QodGhpcyxhKSAoSEFDIDE0LjU0KVxuXG5mdW5jdGlvbiBibkdDRChhKSB7XG4gIHZhciB4ID0gKHRoaXMucyA8IDApID8gdGhpcy5uZWdhdGUoKSA6IHRoaXMuY2xvbmUoKTtcbiAgdmFyIHkgPSAoYS5zIDwgMCkgPyBhLm5lZ2F0ZSgpIDogYS5jbG9uZSgpO1xuICBpZiAoeC5jb21wYXJlVG8oeSkgPCAwKSB7XG4gICAgdmFyIHQgPSB4O1xuICAgIHggPSB5O1xuICAgIHkgPSB0O1xuICB9XG4gIHZhciBpID0geC5nZXRMb3dlc3RTZXRCaXQoKSxcbiAgICBnID0geS5nZXRMb3dlc3RTZXRCaXQoKTtcbiAgaWYgKGcgPCAwKSByZXR1cm4geDtcbiAgaWYgKGkgPCBnKSBnID0gaTtcbiAgaWYgKGcgPiAwKSB7XG4gICAgeC5yU2hpZnRUbyhnLCB4KTtcbiAgICB5LnJTaGlmdFRvKGcsIHkpO1xuICB9XG4gIHdoaWxlICh4LnNpZ251bSgpID4gMCkge1xuICAgIGlmICgoaSA9IHguZ2V0TG93ZXN0U2V0Qml0KCkpID4gMCkgeC5yU2hpZnRUbyhpLCB4KTtcbiAgICBpZiAoKGkgPSB5LmdldExvd2VzdFNldEJpdCgpKSA+IDApIHkuclNoaWZ0VG8oaSwgeSk7XG4gICAgaWYgKHguY29tcGFyZVRvKHkpID49IDApIHtcbiAgICAgIHguc3ViVG8oeSwgeCk7XG4gICAgICB4LnJTaGlmdFRvKDEsIHgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB5LnN1YlRvKHgsIHkpO1xuICAgICAgeS5yU2hpZnRUbygxLCB5KTtcbiAgICB9XG4gIH1cbiAgaWYgKGcgPiAwKSB5LmxTaGlmdFRvKGcsIHkpO1xuICByZXR1cm4geTtcbn1cblxuLy8gKHByb3RlY3RlZCkgdGhpcyAlIG4sIG4gPCAyXjI2XG5cbmZ1bmN0aW9uIGJucE1vZEludChuKSB7XG4gIGlmIChuIDw9IDApIHJldHVybiAwO1xuICB2YXIgZCA9IHRoaXMuRFYgJSBuLFxuICAgIHIgPSAodGhpcy5zIDwgMCkgPyBuIC0gMSA6IDA7XG4gIGlmICh0aGlzLnQgPiAwKVxuICAgIGlmIChkID09IDApIHIgPSB0aGlzWzBdICUgbjtcbiAgICBlbHNlIGZvciAodmFyIGkgPSB0aGlzLnQgLSAxOyBpID49IDA7IC0taSkgciA9IChkICogciArIHRoaXNbaV0pICUgbjtcbiAgcmV0dXJuIHI7XG59XG5cbi8vIChwdWJsaWMpIDEvdGhpcyAlIG0gKEhBQyAxNC42MSlcblxuZnVuY3Rpb24gYm5Nb2RJbnZlcnNlKG0pIHtcbiAgdmFyIGFjID0gbS5pc0V2ZW4oKTtcbiAgaWYgKCh0aGlzLmlzRXZlbigpICYmIGFjKSB8fCBtLnNpZ251bSgpID09IDApIHJldHVybiBCaWdJbnRlZ2VyLlpFUk87XG4gIHZhciB1ID0gbS5jbG9uZSgpLFxuICAgIHYgPSB0aGlzLmNsb25lKCk7XG4gIHZhciBhID0gbmJ2KDEpLFxuICAgIGIgPSBuYnYoMCksXG4gICAgYyA9IG5idigwKSxcbiAgICBkID0gbmJ2KDEpO1xuICB3aGlsZSAodS5zaWdudW0oKSAhPSAwKSB7XG4gICAgd2hpbGUgKHUuaXNFdmVuKCkpIHtcbiAgICAgIHUuclNoaWZ0VG8oMSwgdSk7XG4gICAgICBpZiAoYWMpIHtcbiAgICAgICAgaWYgKCFhLmlzRXZlbigpIHx8ICFiLmlzRXZlbigpKSB7XG4gICAgICAgICAgYS5hZGRUbyh0aGlzLCBhKTtcbiAgICAgICAgICBiLnN1YlRvKG0sIGIpO1xuICAgICAgICB9XG4gICAgICAgIGEuclNoaWZ0VG8oMSwgYSk7XG4gICAgICB9IGVsc2UgaWYgKCFiLmlzRXZlbigpKSBiLnN1YlRvKG0sIGIpO1xuICAgICAgYi5yU2hpZnRUbygxLCBiKTtcbiAgICB9XG4gICAgd2hpbGUgKHYuaXNFdmVuKCkpIHtcbiAgICAgIHYuclNoaWZ0VG8oMSwgdik7XG4gICAgICBpZiAoYWMpIHtcbiAgICAgICAgaWYgKCFjLmlzRXZlbigpIHx8ICFkLmlzRXZlbigpKSB7XG4gICAgICAgICAgYy5hZGRUbyh0aGlzLCBjKTtcbiAgICAgICAgICBkLnN1YlRvKG0sIGQpO1xuICAgICAgICB9XG4gICAgICAgIGMuclNoaWZ0VG8oMSwgYyk7XG4gICAgICB9IGVsc2UgaWYgKCFkLmlzRXZlbigpKSBkLnN1YlRvKG0sIGQpO1xuICAgICAgZC5yU2hpZnRUbygxLCBkKTtcbiAgICB9XG4gICAgaWYgKHUuY29tcGFyZVRvKHYpID49IDApIHtcbiAgICAgIHUuc3ViVG8odiwgdSk7XG4gICAgICBpZiAoYWMpIGEuc3ViVG8oYywgYSk7XG4gICAgICBiLnN1YlRvKGQsIGIpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2LnN1YlRvKHUsIHYpO1xuICAgICAgaWYgKGFjKSBjLnN1YlRvKGEsIGMpO1xuICAgICAgZC5zdWJUbyhiLCBkKTtcbiAgICB9XG4gIH1cbiAgaWYgKHYuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSAhPSAwKSByZXR1cm4gQmlnSW50ZWdlci5aRVJPO1xuICBpZiAoZC5jb21wYXJlVG8obSkgPj0gMCkgcmV0dXJuIGQuc3VidHJhY3QobSk7XG4gIGlmIChkLnNpZ251bSgpIDwgMCkgZC5hZGRUbyhtLCBkKTtcbiAgZWxzZSByZXR1cm4gZDtcbiAgaWYgKGQuc2lnbnVtKCkgPCAwKSByZXR1cm4gZC5hZGQobSk7XG4gIGVsc2UgcmV0dXJuIGQ7XG59XG5cbnZhciBsb3dwcmltZXMgPSBbMiwgMywgNSwgNywgMTEsIDEzLCAxNywgMTksIDIzLCAyOSwgMzEsIDM3LCA0MSwgNDMsIDQ3LCA1MywgNTksIDYxLCA2NywgNzEsIDczLCA3OSwgODMsIDg5LCA5NywgMTAxLFxuICAgIDEwMywgMTA3LCAxMDksIDExMywgMTI3LCAxMzEsIDEzNywgMTM5LCAxNDksIDE1MSwgMTU3LCAxNjMsIDE2NywgMTczLCAxNzksIDE4MSwgMTkxLCAxOTMsIDE5NywgMTk5LCAyMTEsIDIyMywgMjI3LFxuICAgIDIyOSwgMjMzLCAyMzksIDI0MSwgMjUxLCAyNTcsIDI2MywgMjY5LCAyNzEsIDI3NywgMjgxLCAyODMsIDI5MywgMzA3LCAzMTEsIDMxMywgMzE3LCAzMzEsIDMzNywgMzQ3LCAzNDksIDM1MywgMzU5LFxuICAgIDM2NywgMzczLCAzNzksIDM4MywgMzg5LCAzOTcsIDQwMSwgNDA5LCA0MTksIDQyMSwgNDMxLCA0MzMsIDQzOSwgNDQzLCA0NDksIDQ1NywgNDYxLCA0NjMsIDQ2NywgNDc5LCA0ODcsIDQ5MSwgNDk5LFxuICAgIDUwMywgNTA5LCA1MjEsIDUyMywgNTQxLCA1NDcsIDU1NywgNTYzLCA1NjksIDU3MSwgNTc3LCA1ODcsIDU5MywgNTk5LCA2MDEsIDYwNywgNjEzLCA2MTcsIDYxOSwgNjMxLCA2NDEsIDY0MywgNjQ3LFxuICAgIDY1MywgNjU5LCA2NjEsIDY3MywgNjc3LCA2ODMsIDY5MSwgNzAxLCA3MDksIDcxOSwgNzI3LCA3MzMsIDczOSwgNzQzLCA3NTEsIDc1NywgNzYxLCA3NjksIDc3MywgNzg3LCA3OTcsIDgwOSwgODExLFxuICAgIDgyMSwgODIzLCA4MjcsIDgyOSwgODM5LCA4NTMsIDg1NywgODU5LCA4NjMsIDg3NywgODgxLCA4ODMsIDg4NywgOTA3LCA5MTEsIDkxOSwgOTI5LCA5MzcsIDk0MSwgOTQ3LCA5NTMsIDk2NywgOTcxLFxuICAgIDk3NywgOTgzLCA5OTEsIDk5N1xuXTtcbnZhciBscGxpbSA9ICgxIDw8IDI2KSAvIGxvd3ByaW1lc1tsb3dwcmltZXMubGVuZ3RoIC0gMV07XG5cbi8vIChwdWJsaWMpIHRlc3QgcHJpbWFsaXR5IHdpdGggY2VydGFpbnR5ID49IDEtLjVedFxuXG5mdW5jdGlvbiBibklzUHJvYmFibGVQcmltZSh0KSB7XG4gIHZhciBpLCB4ID0gdGhpcy5hYnMoKTtcbiAgaWYgKHgudCA9PSAxICYmIHhbMF0gPD0gbG93cHJpbWVzW2xvd3ByaW1lcy5sZW5ndGggLSAxXSkge1xuICAgIGZvciAoaSA9IDA7IGkgPCBsb3dwcmltZXMubGVuZ3RoOyArK2kpXG4gICAgICBpZiAoeFswXSA9PSBsb3dwcmltZXNbaV0pIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoeC5pc0V2ZW4oKSkgcmV0dXJuIGZhbHNlO1xuICBpID0gMTtcbiAgd2hpbGUgKGkgPCBsb3dwcmltZXMubGVuZ3RoKSB7XG4gICAgdmFyIG0gPSBsb3dwcmltZXNbaV0sXG4gICAgICBqID0gaSArIDE7XG4gICAgd2hpbGUgKGogPCBsb3dwcmltZXMubGVuZ3RoICYmIG0gPCBscGxpbSkgbSAqPSBsb3dwcmltZXNbaisrXTtcbiAgICBtID0geC5tb2RJbnQobSk7XG4gICAgd2hpbGUgKGkgPCBqKSBpZiAobSAlIGxvd3ByaW1lc1tpKytdID09IDApIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4geC5taWxsZXJSYWJpbih0KTtcbn1cblxuLyogYWRkZWQgYnkgUmVjdXJpdHkgTGFicyAqL1xuXG5mdW5jdGlvbiBuYml0cyh4KSB7XG4gIHZhciBuID0gMSxcbiAgICB0O1xuICBpZiAoKHQgPSB4ID4+PiAxNikgIT0gMCkge1xuICAgIHggPSB0O1xuICAgIG4gKz0gMTY7XG4gIH1cbiAgaWYgKCh0ID0geCA+PiA4KSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgbiArPSA4O1xuICB9XG4gIGlmICgodCA9IHggPj4gNCkgIT0gMCkge1xuICAgIHggPSB0O1xuICAgIG4gKz0gNDtcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDIpICE9IDApIHtcbiAgICB4ID0gdDtcbiAgICBuICs9IDI7XG4gIH1cbiAgaWYgKCh0ID0geCA+PiAxKSAhPSAwKSB7XG4gICAgeCA9IHQ7XG4gICAgbiArPSAxO1xuICB9XG4gIHJldHVybiBuO1xufVxuXG5mdW5jdGlvbiBiblRvTVBJKCkge1xuICB2YXIgYmEgPSB0aGlzLnRvQnl0ZUFycmF5KCk7XG4gIHZhciBzaXplID0gKGJhLmxlbmd0aCAtIDEpICogOCArIG5iaXRzKGJhWzBdKTtcbiAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChzaXplICYgMHhGRjAwKSA+PiA4KTtcbiAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoc2l6ZSAmIDB4RkYpO1xuICByZXN1bHQgKz0gdXRpbC5iaW4yc3RyKGJhKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cbi8qIEVORCBvZiBhZGRpdGlvbiAqL1xuXG4vLyAocHJvdGVjdGVkKSB0cnVlIGlmIHByb2JhYmx5IHByaW1lIChIQUMgNC4yNCwgTWlsbGVyLVJhYmluKVxuZnVuY3Rpb24gYm5wTWlsbGVyUmFiaW4odCkge1xuICB2YXIgbjEgPSB0aGlzLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKTtcbiAgdmFyIGsgPSBuMS5nZXRMb3dlc3RTZXRCaXQoKTtcbiAgaWYgKGsgPD0gMCkgcmV0dXJuIGZhbHNlO1xuICB2YXIgciA9IG4xLnNoaWZ0UmlnaHQoayk7XG4gIHQgPSAodCArIDEpID4+IDE7XG4gIGlmICh0ID4gbG93cHJpbWVzLmxlbmd0aCkgdCA9IGxvd3ByaW1lcy5sZW5ndGg7XG4gIHZhciBhID0gbmJpKCk7XG4gIHZhciBqLCBiYXNlcyA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHQ7ICsraSkge1xuICAgIC8vUGljayBiYXNlcyBhdCByYW5kb20sIGluc3RlYWQgb2Ygc3RhcnRpbmcgYXQgMlxuICAgIGZvciAoOzspIHtcbiAgICAgIGogPSBsb3dwcmltZXNbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbG93cHJpbWVzLmxlbmd0aCldO1xuICAgICAgaWYgKGJhc2VzLmluZGV4T2YoaikgPT0gLTEpIGJyZWFrO1xuICAgIH1cbiAgICBiYXNlcy5wdXNoKGopO1xuICAgIGEuZnJvbUludChqKTtcbiAgICB2YXIgeSA9IGEubW9kUG93KHIsIHRoaXMpO1xuICAgIGlmICh5LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgIT0gMCAmJiB5LmNvbXBhcmVUbyhuMSkgIT0gMCkge1xuICAgICAgdmFyIGogPSAxO1xuICAgICAgd2hpbGUgKGorKyA8IGsgJiYgeS5jb21wYXJlVG8objEpICE9IDApIHtcbiAgICAgICAgeSA9IHkubW9kUG93SW50KDIsIHRoaXMpO1xuICAgICAgICBpZiAoeS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpID09IDApIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIGlmICh5LmNvbXBhcmVUbyhuMSkgIT0gMCkgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2pzYm4uanMnKTtcblxuLy8gcHJvdGVjdGVkXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jaHVua1NpemUgPSBibnBDaHVua1NpemU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS50b1JhZGl4ID0gYm5wVG9SYWRpeDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmZyb21SYWRpeCA9IGJucEZyb21SYWRpeDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmZyb21OdW1iZXIgPSBibnBGcm9tTnVtYmVyO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYml0d2lzZVRvID0gYm5wQml0d2lzZVRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuY2hhbmdlQml0ID0gYm5wQ2hhbmdlQml0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYWRkVG8gPSBibnBBZGRUbztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRNdWx0aXBseSA9IGJucERNdWx0aXBseTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmRBZGRPZmZzZXQgPSBibnBEQWRkT2Zmc2V0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUubXVsdGlwbHlMb3dlclRvID0gYm5wTXVsdGlwbHlMb3dlclRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubXVsdGlwbHlVcHBlclRvID0gYm5wTXVsdGlwbHlVcHBlclRvO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubW9kSW50ID0gYm5wTW9kSW50O1xuQmlnSW50ZWdlci5wcm90b3R5cGUubWlsbGVyUmFiaW4gPSBibnBNaWxsZXJSYWJpbjtcblxuLy8gcHVibGljXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jbG9uZSA9IGJuQ2xvbmU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5pbnRWYWx1ZSA9IGJuSW50VmFsdWU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5ieXRlVmFsdWUgPSBibkJ5dGVWYWx1ZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnNob3J0VmFsdWUgPSBiblNob3J0VmFsdWU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zaWdudW0gPSBiblNpZ051bTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnRvQnl0ZUFycmF5ID0gYm5Ub0J5dGVBcnJheTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmVxdWFscyA9IGJuRXF1YWxzO1xuQmlnSW50ZWdlci5wcm90b3R5cGUubWluID0gYm5NaW47XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tYXggPSBibk1heDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLmFuZCA9IGJuQW5kO1xuQmlnSW50ZWdlci5wcm90b3R5cGUub3IgPSBibk9yO1xuQmlnSW50ZWdlci5wcm90b3R5cGUueG9yID0gYm5Yb3I7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hbmROb3QgPSBibkFuZE5vdDtcbkJpZ0ludGVnZXIucHJvdG90eXBlLm5vdCA9IGJuTm90O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc2hpZnRMZWZ0ID0gYm5TaGlmdExlZnQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zaGlmdFJpZ2h0ID0gYm5TaGlmdFJpZ2h0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZ2V0TG93ZXN0U2V0Qml0ID0gYm5HZXRMb3dlc3RTZXRCaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5iaXRDb3VudCA9IGJuQml0Q291bnQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS50ZXN0Qml0ID0gYm5UZXN0Qml0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuc2V0Qml0ID0gYm5TZXRCaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5jbGVhckJpdCA9IGJuQ2xlYXJCaXQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5mbGlwQml0ID0gYm5GbGlwQml0O1xuQmlnSW50ZWdlci5wcm90b3R5cGUuYWRkID0gYm5BZGQ7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zdWJ0cmFjdCA9IGJuU3VidHJhY3Q7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tdWx0aXBseSA9IGJuTXVsdGlwbHk7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5kaXZpZGUgPSBibkRpdmlkZTtcbkJpZ0ludGVnZXIucHJvdG90eXBlLnJlbWFpbmRlciA9IGJuUmVtYWluZGVyO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuZGl2aWRlQW5kUmVtYWluZGVyID0gYm5EaXZpZGVBbmRSZW1haW5kZXI7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5tb2RQb3cgPSBibk1vZFBvdztcbkJpZ0ludGVnZXIucHJvdG90eXBlLm1vZEludmVyc2UgPSBibk1vZEludmVyc2U7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5wb3cgPSBiblBvdztcbkJpZ0ludGVnZXIucHJvdG90eXBlLmdjZCA9IGJuR0NEO1xuQmlnSW50ZWdlci5wcm90b3R5cGUuaXNQcm9iYWJsZVByaW1lID0gYm5Jc1Byb2JhYmxlUHJpbWU7XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS50b01QSSA9IGJuVG9NUEk7XG5cbi8vIEpTQk4tc3BlY2lmaWMgZXh0ZW5zaW9uXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5zcXVhcmUgPSBiblNxdWFyZTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG4vL1xuLy8gUlNBIGltcGxlbWVudGF0aW9uXG5cbnZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnLi9qc2JuLmpzJyksXG4gIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyksXG4gIHJhbmRvbSA9IHJlcXVpcmUoJy4uL3JhbmRvbS5qcycpO1xuXG5mdW5jdGlvbiBTZWN1cmVSYW5kb20oKSB7XG4gIGZ1bmN0aW9uIG5leHRCeXRlcyhieXRlQXJyYXkpIHtcbiAgICBmb3IgKHZhciBuID0gMDsgbiA8IGJ5dGVBcnJheS5sZW5ndGg7IG4rKykge1xuICAgICAgYnl0ZUFycmF5W25dID0gcmFuZG9tLmdldFNlY3VyZVJhbmRvbU9jdGV0KCk7XG4gICAgfVxuICB9XG4gIHRoaXMubmV4dEJ5dGVzID0gbmV4dEJ5dGVzO1xufVxuXG5mdW5jdGlvbiBSU0EoKSB7XG4gIC8qKlxuICAgKiBUaGlzIGZ1bmN0aW9uIHVzZXMganNibiBCaWcgTnVtIGxpYnJhcnkgdG8gZGVjcnlwdCBSU0FcbiAgICogQHBhcmFtIG1cbiAgICogICAgICAgICAgICBtZXNzYWdlXG4gICAqIEBwYXJhbSBkXG4gICAqICAgICAgICAgICAgUlNBIGQgYXMgQmlnSW50ZWdlclxuICAgKiBAcGFyYW0gcFxuICAgKiAgICAgICAgICAgIFJTQSBwIGFzIEJpZ0ludGVnZXJcbiAgICogQHBhcmFtIHFcbiAgICogICAgICAgICAgICBSU0EgcSBhcyBCaWdJbnRlZ2VyXG4gICAqIEBwYXJhbSB1XG4gICAqICAgICAgICAgICAgUlNBIHUgYXMgQmlnSW50ZWdlclxuICAgKiBAcmV0dXJuIHtCaWdJbnRlZ2VyfSBUaGUgZGVjcnlwdGVkIHZhbHVlIG9mIHRoZSBtZXNzYWdlXG4gICAqL1xuICBmdW5jdGlvbiBkZWNyeXB0KG0sIGQsIHAsIHEsIHUpIHtcbiAgICB2YXIgeHAgPSBtLm1vZChwKS5tb2RQb3coZC5tb2QocC5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkpLCBwKTtcbiAgICB2YXIgeHEgPSBtLm1vZChxKS5tb2RQb3coZC5tb2QocS5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkpLCBxKTtcbiAgICB1dGlsLnByaW50X2RlYnVnKFwicnNhLmpzIGRlY3J5cHRcXG54cG46XCIgKyB1dGlsLmhleHN0cmR1bXAoeHAudG9NUEkoKSkgKyBcIlxcbnhxbjpcIiArIHV0aWwuaGV4c3RyZHVtcCh4cS50b01QSSgpKSk7XG5cbiAgICB2YXIgdCA9IHhxLnN1YnRyYWN0KHhwKTtcbiAgICBpZiAodFswXSA9PSAwKSB7XG4gICAgICB0ID0geHAuc3VidHJhY3QoeHEpO1xuICAgICAgdCA9IHQubXVsdGlwbHkodSkubW9kKHEpO1xuICAgICAgdCA9IHEuc3VidHJhY3QodCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHQgPSB0Lm11bHRpcGx5KHUpLm1vZChxKTtcbiAgICB9XG4gICAgcmV0dXJuIHQubXVsdGlwbHkocCkuYWRkKHhwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBlbmNyeXB0IG1lc3NhZ2VcbiAgICogQHBhcmFtIG0gbWVzc2FnZSBhcyBCaWdJbnRlZ2VyXG4gICAqIEBwYXJhbSBlIHB1YmxpYyBNUEkgcGFydCBhcyBCaWdJbnRlZ2VyXG4gICAqIEBwYXJhbSBuIHB1YmxpYyBNUEkgcGFydCBhcyBCaWdJbnRlZ2VyXG4gICAqIEByZXR1cm4gQmlnSW50ZWdlclxuICAgKi9cbiAgZnVuY3Rpb24gZW5jcnlwdChtLCBlLCBuKSB7XG4gICAgcmV0dXJuIG0ubW9kUG93SW50KGUsIG4pO1xuICB9XG5cbiAgLyogU2lnbiBhbmQgVmVyaWZ5ICovXG4gIGZ1bmN0aW9uIHNpZ24obSwgZCwgbikge1xuICAgIHJldHVybiBtLm1vZFBvdyhkLCBuKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHZlcmlmeSh4LCBlLCBuKSB7XG4gICAgcmV0dXJuIHgubW9kUG93SW50KGUsIG4pO1xuICB9XG5cbiAgLy8gXCJlbXB0eVwiIFJTQSBrZXkgY29uc3RydWN0b3JcblxuICBmdW5jdGlvbiBrZXlPYmplY3QoKSB7XG4gICAgdGhpcy5uID0gbnVsbDtcbiAgICB0aGlzLmUgPSAwO1xuICAgIHRoaXMuZWUgPSBudWxsO1xuICAgIHRoaXMuZCA9IG51bGw7XG4gICAgdGhpcy5wID0gbnVsbDtcbiAgICB0aGlzLnEgPSBudWxsO1xuICAgIHRoaXMuZG1wMSA9IG51bGw7XG4gICAgdGhpcy5kbXExID0gbnVsbDtcbiAgICB0aGlzLnUgPSBudWxsO1xuICB9XG5cbiAgLy8gR2VuZXJhdGUgYSBuZXcgcmFuZG9tIHByaXZhdGUga2V5IEIgYml0cyBsb25nLCB1c2luZyBwdWJsaWMgZXhwdCBFXG5cbiAgZnVuY3Rpb24gZ2VuZXJhdGUoQiwgRSkge1xuICAgIHZhciBrZXkgPSBuZXcga2V5T2JqZWN0KCk7XG4gICAgdmFyIHJuZyA9IG5ldyBTZWN1cmVSYW5kb20oKTtcbiAgICB2YXIgcXMgPSBCID4+IDE7XG4gICAga2V5LmUgPSBwYXJzZUludChFLCAxNik7XG4gICAga2V5LmVlID0gbmV3IEJpZ0ludGVnZXIoRSwgMTYpO1xuICAgIGZvciAoOzspIHtcbiAgICAgIGZvciAoOzspIHtcbiAgICAgICAga2V5LnAgPSBuZXcgQmlnSW50ZWdlcihCIC0gcXMsIDEsIHJuZyk7XG4gICAgICAgIGlmIChrZXkucC5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkuZ2NkKGtleS5lZSkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA9PSAwICYmIGtleS5wLmlzUHJvYmFibGVQcmltZSgxMCkpXG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBmb3IgKDs7KSB7XG4gICAgICAgIGtleS5xID0gbmV3IEJpZ0ludGVnZXIocXMsIDEsIHJuZyk7XG4gICAgICAgIGlmIChrZXkucS5zdWJ0cmFjdChCaWdJbnRlZ2VyLk9ORSkuZ2NkKGtleS5lZSkuY29tcGFyZVRvKEJpZ0ludGVnZXIuT05FKSA9PSAwICYmIGtleS5xLmlzUHJvYmFibGVQcmltZSgxMCkpXG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoa2V5LnAuY29tcGFyZVRvKGtleS5xKSA8PSAwKSB7XG4gICAgICAgIHZhciB0ID0ga2V5LnA7XG4gICAgICAgIGtleS5wID0ga2V5LnE7XG4gICAgICAgIGtleS5xID0gdDtcbiAgICAgIH1cbiAgICAgIHZhciBwMSA9IGtleS5wLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKTtcbiAgICAgIHZhciBxMSA9IGtleS5xLnN1YnRyYWN0KEJpZ0ludGVnZXIuT05FKTtcbiAgICAgIHZhciBwaGkgPSBwMS5tdWx0aXBseShxMSk7XG4gICAgICBpZiAocGhpLmdjZChrZXkuZWUpLmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPT0gMCkge1xuICAgICAgICBrZXkubiA9IGtleS5wLm11bHRpcGx5KGtleS5xKTtcbiAgICAgICAga2V5LmQgPSBrZXkuZWUubW9kSW52ZXJzZShwaGkpO1xuICAgICAgICBrZXkuZG1wMSA9IGtleS5kLm1vZChwMSk7XG4gICAgICAgIGtleS5kbXExID0ga2V5LmQubW9kKHExKTtcbiAgICAgICAga2V5LnUgPSBrZXkucC5tb2RJbnZlcnNlKGtleS5xKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBrZXk7XG4gIH1cblxuICB0aGlzLmVuY3J5cHQgPSBlbmNyeXB0O1xuICB0aGlzLmRlY3J5cHQgPSBkZWNyeXB0O1xuICB0aGlzLnZlcmlmeSA9IHZlcmlmeTtcbiAgdGhpcy5zaWduID0gc2lnbjtcbiAgdGhpcy5nZW5lcmF0ZSA9IGdlbmVyYXRlO1xuICB0aGlzLmtleU9iamVjdCA9IGtleU9iamVjdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBSU0E7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQSBcblxuLy8gVGhlIEdQRzRCcm93c2VycyBjcnlwdG8gaW50ZXJmYWNlXG5cbnZhciB0eXBlX21waSA9IHJlcXVpcmUoJy4uL3R5cGUvbXBpLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAvKipcbiAgICogUmV0cmlldmUgc2VjdXJlIHJhbmRvbSBieXRlIHN0cmluZyBvZiB0aGUgc3BlY2lmaWVkIGxlbmd0aFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbmd0aCBMZW5ndGggaW4gYnl0ZXMgdG8gZ2VuZXJhdGVcbiAgICogQHJldHVybiB7U3RyaW5nfSBSYW5kb20gYnl0ZSBzdHJpbmdcbiAgICovXG4gIGdldFJhbmRvbUJ5dGVzOiBmdW5jdGlvbihsZW5ndGgpIHtcbiAgICB2YXIgcmVzdWx0ID0gJyc7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy5nZXRTZWN1cmVSYW5kb21PY3RldCgpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICAvKipcbiAgICogUmV0dXJuIGEgcHNldWRvLXJhbmRvbSBudW1iZXIgaW4gdGhlIHNwZWNpZmllZCByYW5nZVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGZyb20gTWluIG9mIHRoZSByYW5kb20gbnVtYmVyXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gdG8gTWF4IG9mIHRoZSByYW5kb20gbnVtYmVyIChtYXggMzJiaXQpXG4gICAqIEByZXR1cm4ge0ludGVnZXJ9IEEgcHNldWRvIHJhbmRvbSBudW1iZXJcbiAgICovXG4gIGdldFBzZXVkb1JhbmRvbTogZnVuY3Rpb24oZnJvbSwgdG8pIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpICogKHRvIC0gZnJvbSkpICsgZnJvbTtcbiAgfSxcblxuICAvKipcbiAgICogUmV0dXJuIGEgc2VjdXJlIHJhbmRvbSBudW1iZXIgaW4gdGhlIHNwZWNpZmllZCByYW5nZVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGZyb20gTWluIG9mIHRoZSByYW5kb20gbnVtYmVyXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gdG8gTWF4IG9mIHRoZSByYW5kb20gbnVtYmVyIChtYXggMzJiaXQpXG4gICAqIEByZXR1cm4ge0ludGVnZXJ9IEEgc2VjdXJlIHJhbmRvbSBudW1iZXJcbiAgICovXG4gIGdldFNlY3VyZVJhbmRvbTogZnVuY3Rpb24oZnJvbSwgdG8pIHtcbiAgICB2YXIgYnVmID0gbmV3IFVpbnQzMkFycmF5KDEpO1xuICAgIHdpbmRvdy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGJ1Zik7XG4gICAgdmFyIGJpdHMgPSAoKHRvIC0gZnJvbSkpLnRvU3RyaW5nKDIpLmxlbmd0aDtcbiAgICB3aGlsZSAoKGJ1ZlswXSAmIChNYXRoLnBvdygyLCBiaXRzKSAtIDEpKSA+ICh0byAtIGZyb20pKVxuICAgICAgd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYnVmKTtcbiAgICByZXR1cm4gZnJvbSArIChNYXRoLmFicyhidWZbMF0gJiAoTWF0aC5wb3coMiwgYml0cykgLSAxKSkpO1xuICB9LFxuXG4gIGdldFNlY3VyZVJhbmRvbU9jdGV0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnVmID0gbmV3IFVpbnQzMkFycmF5KDEpO1xuICAgIHdpbmRvdy5jcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGJ1Zik7XG4gICAgcmV0dXJuIGJ1ZlswXSAmIDB4RkY7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIHNlY3VyZSByYW5kb20gYmlnIGludGVnZXIgb2YgYml0cyBsZW5ndGhcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBiaXRzIEJpdCBsZW5ndGggb2YgdGhlIE1QSSB0byBjcmVhdGVcbiAgICogQHJldHVybiB7QmlnSW50ZWdlcn0gUmVzdWx0aW5nIGJpZyBpbnRlZ2VyXG4gICAqL1xuICBnZXRSYW5kb21CaWdJbnRlZ2VyOiBmdW5jdGlvbihiaXRzKSB7XG4gICAgaWYgKGJpdHMgPCAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgdmFyIG51bUJ5dGVzID0gTWF0aC5mbG9vcigoYml0cyArIDcpIC8gOCk7XG5cbiAgICB2YXIgcmFuZG9tQml0cyA9IHRoaXMuZ2V0UmFuZG9tQnl0ZXMobnVtQnl0ZXMpO1xuICAgIGlmIChiaXRzICUgOCA+IDApIHtcblxuICAgICAgcmFuZG9tQml0cyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICAoTWF0aC5wb3coMiwgYml0cyAlIDgpIC0gMSkgJlxuICAgICAgICByYW5kb21CaXRzLmNoYXJDb2RlQXQoMCkpICtcbiAgICAgICAgcmFuZG9tQml0cy5zdWJzdHJpbmcoMSk7XG4gICAgfVxuICAgIHZhciBtcGkgPSBuZXcgdHlwZV9tcGkoKTtcbiAgICBtcGkuZnJvbUJ5dGVzKHJhbmRvbUJpdHMpO1xuICAgIHJldHVybiBtcGkudG9CaWdJbnRlZ2VyKCk7XG4gIH0sXG5cbiAgZ2V0UmFuZG9tQmlnSW50ZWdlckluUmFuZ2U6IGZ1bmN0aW9uKG1pbiwgbWF4KSB7XG4gICAgaWYgKG1heC5jb21wYXJlVG8obWluKSA8PSAwKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHJhbmdlID0gbWF4LnN1YnRyYWN0KG1pbik7XG4gICAgdmFyIHIgPSB0aGlzLmdldFJhbmRvbUJpZ0ludGVnZXIocmFuZ2UuYml0TGVuZ3RoKCkpO1xuICAgIHdoaWxlIChyID4gcmFuZ2UpIHtcbiAgICAgIHIgPSB0aGlzLmdldFJhbmRvbUJpZ0ludGVnZXIocmFuZ2UuYml0TGVuZ3RoKCkpO1xuICAgIH1cbiAgICByZXR1cm4gbWluLmFkZChyKTtcbiAgfVxuXG59O1xuIiwidmFyIHB1YmxpY0tleSA9IHJlcXVpcmUoJy4vcHVibGljX2tleScpLFxuICBwa2NzMSA9IHJlcXVpcmUoJy4vcGtjczEuanMnKSxcbiAgaGFzaE1vZHVsZSA9IHJlcXVpcmUoJy4vaGFzaCcpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgLyoqXG4gICAqIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGFsZ28gcHVibGljIEtleSBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBoYXNoX2FsZ28gSGFzaCBhbGdvcml0aG1cbiAgICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IG1zZ19NUElzIFNpZ25hdHVyZSBtdWx0aXByZWNpc2lvbiBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gcHVibGlja2V5X01QSXMgUHVibGljIGtleSBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBcbiAgICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSBvbiB3aGVyZSB0aGUgc2lnbmF0dXJlIHdhcyBjb21wdXRlZCBvbi5cbiAgICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBzaWduYXR1cmUgKHNpZ19kYXRhIHdhcyBlcXVhbCB0byBkYXRhIG92ZXIgaGFzaClcbiAgICovXG4gIHZlcmlmeTogZnVuY3Rpb24oYWxnbywgaGFzaF9hbGdvLCBtc2dfTVBJcywgcHVibGlja2V5X01QSXMsIGRhdGEpIHtcbiAgICB2YXIgY2FsY19oYXNoID0gaGFzaE1vZHVsZS5kaWdlc3QoaGFzaF9hbGdvLCBkYXRhKTtcblxuICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgY2FzZSAxOlxuICAgICAgICAvLyBSU0EgKEVuY3J5cHQgb3IgU2lnbikgW0hBQ10gIFxuICAgICAgY2FzZSAyOlxuICAgICAgICAvLyBSU0EgRW5jcnlwdC1Pbmx5IFtIQUNdXG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vIFJTQSBTaWduLU9ubHkgW0hBQ11cbiAgICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICAgIHZhciBuID0gcHVibGlja2V5X01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgIHZhciBlID0gcHVibGlja2V5X01QSXNbMV0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgIHZhciB4ID0gbXNnX01QSXNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgIHZhciBkb3B1YmxpYyA9IHJzYS52ZXJpZnkoeCwgZSwgbik7XG4gICAgICAgIHZhciBoYXNoID0gcGtjczEuZW1zYS5kZWNvZGUoaGFzaF9hbGdvLCBkb3B1YmxpYy50b01QSSgpLnN1YnN0cmluZygyKSk7XG4gICAgICAgIGlmIChoYXNoID09IC0xKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQS0NTMSBwYWRkaW5nIGluIG1lc3NhZ2Ugb3Iga2V5IGluY29ycmVjdC4gQWJvcnRpbmcuLi4nKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaGFzaCA9PSBjYWxjX2hhc2g7XG5cbiAgICAgIGNhc2UgMTY6XG4gICAgICAgIC8vIEVsZ2FtYWwgKEVuY3J5cHQtT25seSkgW0VMR0FNQUxdIFtIQUNdXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInNpZ25pbmcgd2l0aCBFbGdhbWFsIGlzIG5vdCBkZWZpbmVkIGluIHRoZSBPcGVuUEdQIHN0YW5kYXJkLlwiKTtcbiAgICAgIGNhc2UgMTc6XG4gICAgICAgIC8vIERTQSAoRGlnaXRhbCBTaWduYXR1cmUgQWxnb3JpdGhtKSBbRklQUzE4Nl0gW0hBQ11cbiAgICAgICAgdmFyIGRzYSA9IG5ldyBwdWJsaWNLZXkuZHNhKCk7XG4gICAgICAgIHZhciBzMSA9IG1zZ19NUElzWzBdLnRvQmlnSW50ZWdlcigpO1xuICAgICAgICB2YXIgczIgPSBtc2dfTVBJc1sxXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHAgPSBwdWJsaWNrZXlfTVBJc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHEgPSBwdWJsaWNrZXlfTVBJc1sxXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIGcgPSBwdWJsaWNrZXlfTVBJc1syXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHkgPSBwdWJsaWNrZXlfTVBJc1szXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIG0gPSBkYXRhO1xuICAgICAgICB2YXIgZG9wdWJsaWMgPSBkc2EudmVyaWZ5KGhhc2hfYWxnbywgczEsIHMyLCBtLCBwLCBxLCBnLCB5KTtcbiAgICAgICAgcmV0dXJuIGRvcHVibGljLmNvbXBhcmVUbyhzMSkgPT0gMDtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzaWduYXR1cmUgYWxnb3JpdGhtLicpO1xuICAgIH1cblxuICB9LFxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBzaWduYXR1cmUgb24gZGF0YSB1c2luZyB0aGUgc3BlY2lmaWVkIGFsZ29yaXRobVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGhhc2hfYWxnbyBoYXNoIEFsZ29yaXRobSB0byB1c2UgKFNlZSBSRkM0ODgwIDkuNClcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBhbGdvIEFzeW1tZXRyaWMgY2lwaGVyIGFsZ29yaXRobSB0byB1c2UgKFNlZSBSRkM0ODgwIDkuMSlcbiAgICogQHBhcmFtIHtvcGVucGdwX3R5cGVfbXBpW119IHB1YmxpY01QSXMgUHVibGljIGtleSBtdWx0aXByZWNpc2lvbiBpbnRlZ2VycyBcbiAgICogb2YgdGhlIHByaXZhdGUga2V5IFxuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gc2VjcmV0TVBJcyBQcml2YXRlIGtleSBtdWx0aXByZWNpc2lvbiBcbiAgICogaW50ZWdlcnMgd2hpY2ggaXMgdXNlZCB0byBzaWduIHRoZSBkYXRhXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBkYXRhIERhdGEgdG8gYmUgc2lnbmVkXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfdHlwZV9tcGlbXX1cbiAgICovXG4gIHNpZ246IGZ1bmN0aW9uKGhhc2hfYWxnbywgYWxnbywga2V5SW50ZWdlcnMsIGRhdGEpIHtcblxuICAgIHN3aXRjaCAoYWxnbykge1xuICAgICAgY2FzZSAxOlxuICAgICAgICAvLyBSU0EgKEVuY3J5cHQgb3IgU2lnbikgW0hBQ10gIFxuICAgICAgY2FzZSAyOlxuICAgICAgICAvLyBSU0EgRW5jcnlwdC1Pbmx5IFtIQUNdXG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vIFJTQSBTaWduLU9ubHkgW0hBQ11cbiAgICAgICAgdmFyIHJzYSA9IG5ldyBwdWJsaWNLZXkucnNhKCk7XG4gICAgICAgIHZhciBkID0ga2V5SW50ZWdlcnNbMl0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgIHZhciBuID0ga2V5SW50ZWdlcnNbMF0udG9CaWdJbnRlZ2VyKCk7XG4gICAgICAgIHZhciBtID0gcGtjczEuZW1zYS5lbmNvZGUoaGFzaF9hbGdvLFxuICAgICAgICAgIGRhdGEsIGtleUludGVnZXJzWzBdLmJ5dGVMZW5ndGgoKSk7XG5cbiAgICAgICAgcmV0dXJuIHJzYS5zaWduKG0sIGQsIG4pLnRvTVBJKCk7XG5cbiAgICAgIGNhc2UgMTc6XG4gICAgICAgIC8vIERTQSAoRGlnaXRhbCBTaWduYXR1cmUgQWxnb3JpdGhtKSBbRklQUzE4Nl0gW0hBQ11cbiAgICAgICAgdmFyIGRzYSA9IG5ldyBwdWJsaWNLZXkuZHNhKCk7XG5cbiAgICAgICAgdmFyIHAgPSBrZXlJbnRlZ2Vyc1swXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHEgPSBrZXlJbnRlZ2Vyc1sxXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIGcgPSBrZXlJbnRlZ2Vyc1syXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHkgPSBrZXlJbnRlZ2Vyc1szXS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIHggPSBrZXlJbnRlZ2Vyc1s0XS50b0JpZ0ludGVnZXIoKTtcbiAgICAgICAgdmFyIG0gPSBkYXRhO1xuICAgICAgICB2YXIgcmVzdWx0ID0gZHNhLnNpZ24oaGFzaF9hbGdvLCBtLCBnLCBwLCBxLCB4KTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0WzBdLnRvU3RyaW5nKCkgKyByZXN1bHRbMV0udG9TdHJpbmcoKTtcbiAgICAgIGNhc2UgMTY6XG4gICAgICAgIC8vIEVsZ2FtYWwgKEVuY3J5cHQtT25seSkgW0VMR0FNQUxdIFtIQUNdXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignU2lnbmluZyB3aXRoIEVsZ2FtYWwgaXMgbm90IGRlZmluZWQgaW4gdGhlIE9wZW5QR1Agc3RhbmRhcmQuJyk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2lnbmF0dXJlIGFsZ29yaXRobS4nKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy9cbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vL1xuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vL1xuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCcuL2Jhc2U2NC5qcycpO1xudmFyIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKTtcbnZhciBjb25maWcgPSByZXF1aXJlKCcuLi9jb25maWcnKTtcblxuLyoqXG4gKiBGaW5kcyBvdXQgd2hpY2ggQXNjaWkgQXJtb3JpbmcgdHlwZSBpcyB1c2VkLiBUaGlzIGlzIGFuIGludGVybmFsIGZ1bmN0aW9uXG4gKiBAcGFyYW0ge1N0cmluZ30gdGV4dCBbU3RyaW5nXSBhc2NpaSBhcm1vcmVkIHRleHRcbiAqIEByZXR1cm5zIHtJbnRlZ2VyfSAwID0gTUVTU0FHRSBQQVJUIG4gb2YgbVxuICogICAgICAgICAxID0gTUVTU0FHRSBQQVJUIG5cbiAqICAgICAgICAgMiA9IFNJR05FRCBNRVNTQUdFXG4gKiAgICAgICAgIDMgPSBQR1AgTUVTU0FHRVxuICogICAgICAgICA0ID0gUFVCTElDIEtFWSBCTE9DS1xuICogICAgICAgICA1ID0gUFJJVkFURSBLRVkgQkxPQ0tcbiAqICAgICAgICAgbnVsbCA9IHVua25vd25cbiAqL1xuZnVuY3Rpb24gZ2V0X3R5cGUodGV4dCkge1xuICB2YXIgc3BsaXR0ZWR0ZXh0ID0gdGV4dC5zcGxpdCgnLS0tLS0nKTtcbiAgLy8gQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgWC9ZXG4gIC8vIFVzZWQgZm9yIG11bHRpLXBhcnQgbWVzc2FnZXMsIHdoZXJlIHRoZSBhcm1vciBpcyBzcGxpdCBhbW9uZ3N0IFlcbiAgLy8gcGFydHMsIGFuZCB0aGlzIGlzIHRoZSBYdGggcGFydCBvdXQgb2YgWS5cbiAgaWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgXFxkK1xcL1xcZCsvKSkge1xuICAgIHJldHVybiBlbnVtcy5hcm1vci5tdWx0aXBhcnRfc2VjdGlvbjtcbiAgfSBlbHNlXG4gIC8vIEJFR0lOIFBHUCBNRVNTQUdFLCBQQVJUIFhcbiAgLy8gVXNlZCBmb3IgbXVsdGktcGFydCBtZXNzYWdlcywgd2hlcmUgdGhpcyBpcyB0aGUgWHRoIHBhcnQgb2YgYW5cbiAgLy8gdW5zcGVjaWZpZWQgbnVtYmVyIG9mIHBhcnRzLiBSZXF1aXJlcyB0aGUgTUVTU0FHRS1JRCBBcm1vclxuICAvLyBIZWFkZXIgdG8gYmUgdXNlZC5cbiAgaWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIE1FU1NBR0UsIFBBUlQgXFxkKy8pKSB7XG4gICAgcmV0dXJuIGVudW1zLmFybW9yLm11bHRpcGFydF9sYXN0O1xuXG4gIH0gZWxzZVxuICAvLyBCRUdJTiBQR1AgU0lHTkFUVVJFXG4gIC8vIFVzZWQgZm9yIGRldGFjaGVkIHNpZ25hdHVyZXMsIE9wZW5QR1AvTUlNRSBzaWduYXR1cmVzLCBhbmRcbiAgLy8gY2xlYXJ0ZXh0IHNpZ25hdHVyZXMuIE5vdGUgdGhhdCBQR1AgMi54IHVzZXMgQkVHSU4gUEdQIE1FU1NBR0VcbiAgLy8gZm9yIGRldGFjaGVkIHNpZ25hdHVyZXMuXG4gIGlmIChzcGxpdHRlZHRleHRbMV0ubWF0Y2goL0JFR0lOIFBHUCBTSUdORUQgTUVTU0FHRS8pKSB7XG4gICAgcmV0dXJuIGVudW1zLmFybW9yLnNpZ25lZDtcblxuICB9IGVsc2VcbiAgLy8gQkVHSU4gUEdQIE1FU1NBR0VcbiAgLy8gVXNlZCBmb3Igc2lnbmVkLCBlbmNyeXB0ZWQsIG9yIGNvbXByZXNzZWQgZmlsZXMuXG4gIGlmIChzcGxpdHRlZHRleHRbMV0ubWF0Y2goL0JFR0lOIFBHUCBNRVNTQUdFLykpIHtcbiAgICByZXR1cm4gZW51bXMuYXJtb3IubWVzc2FnZTtcblxuICB9IGVsc2VcbiAgLy8gQkVHSU4gUEdQIFBVQkxJQyBLRVkgQkxPQ0tcbiAgLy8gVXNlZCBmb3IgYXJtb3JpbmcgcHVibGljIGtleXMuXG4gIGlmIChzcGxpdHRlZHRleHRbMV0ubWF0Y2goL0JFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLLykpIHtcbiAgICByZXR1cm4gZW51bXMuYXJtb3IucHVibGljX2tleTtcblxuICB9IGVsc2VcbiAgLy8gQkVHSU4gUEdQIFBSSVZBVEUgS0VZIEJMT0NLXG4gIC8vIFVzZWQgZm9yIGFybW9yaW5nIHByaXZhdGUga2V5cy5cbiAgaWYgKHNwbGl0dGVkdGV4dFsxXS5tYXRjaCgvQkVHSU4gUEdQIFBSSVZBVEUgS0VZIEJMT0NLLykpIHtcbiAgICByZXR1cm4gZW51bXMuYXJtb3IucHJpdmF0ZV9rZXk7XG4gIH1cbn1cblxuLyoqXG4gKiBBZGQgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiB0byB0aGUgYXJtb3IgdmVyc2lvbiBvZiBhbiBPcGVuUEdQIGJpbmFyeVxuICogcGFja2V0IGJsb2NrLlxuICogQGF1dGhvciAgQWxleFxuICogQHZlcnNpb24gMjAxMS0xMi0xNlxuICogQHJldHVybnMge1N0cmluZ30gVGhlIGhlYWRlciBpbmZvcm1hdGlvblxuICovXG5mdW5jdGlvbiBhcm1vcl9hZGRoZWFkZXIoKSB7XG4gIHZhciByZXN1bHQgPSBcIlwiO1xuICBpZiAoY29uZmlnLnNob3dfdmVyc2lvbikge1xuICAgIHJlc3VsdCArPSBcIlZlcnNpb246IFwiICsgY29uZmlnLnZlcnNpb25zdHJpbmcgKyAnXFxyXFxuJztcbiAgfVxuICBpZiAoY29uZmlnLnNob3dfY29tbWVudCkge1xuICAgIHJlc3VsdCArPSBcIkNvbW1lbnQ6IFwiICsgY29uZmlnLmNvbW1lbnRzdHJpbmcgKyAnXFxyXFxuJztcbiAgfVxuICByZXN1bHQgKz0gJ1xcclxcbic7XG4gIHJldHVybiByZXN1bHQ7XG59XG5cblxuXG4vKipcbiAqIENhbGN1bGF0ZXMgYSBjaGVja3N1bSBvdmVyIHRoZSBnaXZlbiBkYXRhIGFuZCByZXR1cm5zIGl0IGJhc2U2NCBlbmNvZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBEYXRhIHRvIGNyZWF0ZSBhIENSQy0yNCBjaGVja3N1bSBmb3JcbiAqIEByZXR1cm4ge1N0cmluZ30gQmFzZTY0IGVuY29kZWQgY2hlY2tzdW1cbiAqL1xuZnVuY3Rpb24gZ2V0Q2hlY2tTdW0oZGF0YSkge1xuICB2YXIgYyA9IGNyZWF0ZWNyYzI0KGRhdGEpO1xuICB2YXIgc3RyID0gXCJcIiArIFN0cmluZy5mcm9tQ2hhckNvZGUoYyA+PiAxNikgK1xuICAgIFN0cmluZy5mcm9tQ2hhckNvZGUoKGMgPj4gOCkgJiAweEZGKSArXG4gICAgU3RyaW5nLmZyb21DaGFyQ29kZShjICYgMHhGRik7XG4gIHJldHVybiBiYXNlNjQuZW5jb2RlKHN0cik7XG59XG5cbi8qKlxuICogQ2FsY3VsYXRlcyB0aGUgY2hlY2tzdW0gb3ZlciB0aGUgZ2l2ZW4gZGF0YSBhbmQgY29tcGFyZXMgaXQgd2l0aCB0aGUgXG4gKiBnaXZlbiBiYXNlNjQgZW5jb2RlZCBjaGVja3N1bVxuICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBjcmVhdGUgYSBDUkMtMjQgY2hlY2tzdW0gZm9yXG4gKiBAcGFyYW0ge1N0cmluZ30gY2hlY2tzdW0gQmFzZTY0IGVuY29kZWQgY2hlY2tzdW1cbiAqIEByZXR1cm4ge0Jvb2xlYW59IFRydWUgaWYgdGhlIGdpdmVuIGNoZWNrc3VtIGlzIGNvcnJlY3Q7IG90aGVyd2lzZSBmYWxzZVxuICovXG5mdW5jdGlvbiB2ZXJpZnlDaGVja1N1bShkYXRhLCBjaGVja3N1bSkge1xuICB2YXIgYyA9IGdldENoZWNrU3VtKGRhdGEpO1xuICB2YXIgZCA9IGNoZWNrc3VtO1xuICByZXR1cm4gY1swXSA9PSBkWzBdICYmIGNbMV0gPT0gZFsxXSAmJiBjWzJdID09IGRbMl07XG59XG4vKipcbiAqIEludGVybmFsIGZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSBhIENSQy0yNCBjaGVja3N1bSBvdmVyIGEgZ2l2ZW4gc3RyaW5nIChkYXRhKVxuICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBjcmVhdGUgYSBDUkMtMjQgY2hlY2tzdW0gZm9yXG4gKiBAcmV0dXJuIHtJbnRlZ2VyfSBUaGUgQ1JDLTI0IGNoZWNrc3VtIGFzIG51bWJlclxuICovXG52YXIgY3JjX3RhYmxlID0gW1xuICAgIDB4MDAwMDAwMDAsIDB4MDA4NjRjZmIsIDB4MDE4YWQ1MGQsIDB4MDEwYzk5ZjYsIDB4MDM5M2U2ZTEsIDB4MDMxNWFhMWEsIDB4MDIxOTMzZWMsIDB4MDI5ZjdmMTcsIDB4MDdhMTgxMzksXG4gICAgMHgwNzI3Y2RjMiwgMHgwNjJiNTQzNCwgMHgwNmFkMThjZiwgMHgwNDMyNjdkOCwgMHgwNGI0MmIyMywgMHgwNWI4YjJkNSwgMHgwNTNlZmUyZSwgMHgwZmM1NGU4OSwgMHgwZjQzMDI3MixcbiAgICAweDBlNGY5Yjg0LCAweDBlYzlkNzdmLCAweDBjNTZhODY4LCAweDBjZDBlNDkzLCAweDBkZGM3ZDY1LCAweDBkNWEzMTllLCAweDA4NjRjZmIwLCAweDA4ZTI4MzRiLCAweDA5ZWUxYWJkLFxuICAgIDB4MDk2ODU2NDYsIDB4MGJmNzI5NTEsIDB4MGI3MTY1YWEsIDB4MGE3ZGZjNWMsIDB4MGFmYmIwYTcsIDB4MWYwY2QxZTksIDB4MWY4YTlkMTIsIDB4MWU4NjA0ZTQsIDB4MWUwMDQ4MWYsXG4gICAgMHgxYzlmMzcwOCwgMHgxYzE5N2JmMywgMHgxZDE1ZTIwNSwgMHgxZDkzYWVmZSwgMHgxOGFkNTBkMCwgMHgxODJiMWMyYiwgMHgxOTI3ODVkZCwgMHgxOWExYzkyNiwgMHgxYjNlYjYzMSxcbiAgICAweDFiYjhmYWNhLCAweDFhYjQ2MzNjLCAweDFhMzIyZmM3LCAweDEwYzk5ZjYwLCAweDEwNGZkMzliLCAweDExNDM0YTZkLCAweDExYzUwNjk2LCAweDEzNWE3OTgxLCAweDEzZGMzNTdhLFxuICAgIDB4MTJkMGFjOGMsIDB4MTI1NmUwNzcsIDB4MTc2ODFlNTksIDB4MTdlZTUyYTIsIDB4MTZlMmNiNTQsIDB4MTY2NDg3YWYsIDB4MTRmYmY4YjgsIDB4MTQ3ZGI0NDMsIDB4MTU3MTJkYjUsXG4gICAgMHgxNWY3NjE0ZSwgMHgzZTE5YTNkMiwgMHgzZTlmZWYyOSwgMHgzZjkzNzZkZiwgMHgzZjE1M2EyNCwgMHgzZDhhNDUzMywgMHgzZDBjMDljOCwgMHgzYzAwOTAzZSwgMHgzYzg2ZGNjNSxcbiAgICAweDM5YjgyMmViLCAweDM5M2U2ZTEwLCAweDM4MzJmN2U2LCAweDM4YjRiYjFkLCAweDNhMmJjNDBhLCAweDNhYWQ4OGYxLCAweDNiYTExMTA3LCAweDNiMjc1ZGZjLCAweDMxZGNlZDViLFxuICAgIDB4MzE1YWExYTAsXG4gICAgMHgzMDU2Mzg1NiwgMHgzMGQwNzRhZCwgMHgzMjRmMGJiYSwgMHgzMmM5NDc0MSwgMHgzM2M1ZGViNywgMHgzMzQzOTI0YywgMHgzNjdkNmM2MiwgMHgzNmZiMjA5OSwgMHgzN2Y3Yjk2ZixcbiAgICAweDM3NzFmNTk0LCAweDM1ZWU4YTgzLCAweDM1NjhjNjc4LCAweDM0NjQ1ZjhlLCAweDM0ZTIxMzc1LCAweDIxMTU3MjNiLCAweDIxOTMzZWMwLCAweDIwOWZhNzM2LCAweDIwMTllYmNkLFxuICAgIDB4MjI4Njk0ZGEsIDB4MjIwMGQ4MjEsIDB4MjMwYzQxZDcsIDB4MjM4YTBkMmMsIDB4MjZiNGYzMDIsIDB4MjYzMmJmZjksIDB4MjczZTI2MGYsIDB4MjdiODZhZjQsIDB4MjUyNzE1ZTMsXG4gICAgMHgyNWExNTkxOCwgMHgyNGFkYzBlZSwgMHgyNDJiOGMxNSwgMHgyZWQwM2NiMiwgMHgyZTU2NzA0OSwgMHgyZjVhZTliZiwgMHgyZmRjYTU0NCwgMHgyZDQzZGE1MywgMHgyZGM1OTZhOCxcbiAgICAweDJjYzkwZjVlLCAweDJjNGY0M2E1LCAweDI5NzFiZDhiLCAweDI5ZjdmMTcwLCAweDI4ZmI2ODg2LCAweDI4N2QyNDdkLCAweDJhZTI1YjZhLCAweDJhNjQxNzkxLCAweDJiNjg4ZTY3LFxuICAgIDB4MmJlZWMyOWMsIDB4N2MzMzQ3YTQsIDB4N2NiNTBiNWYsIDB4N2RiOTkyYTksIDB4N2QzZmRlNTIsIDB4N2ZhMGExNDUsIDB4N2YyNmVkYmUsIDB4N2UyYTc0NDgsIDB4N2VhYzM4YjMsXG4gICAgMHg3YjkyYzY5ZCwgMHg3YjE0OGE2NiwgMHg3YTE4MTM5MCwgMHg3YTllNWY2YiwgMHg3ODAxMjA3YywgMHg3ODg3NmM4NywgMHg3OThiZjU3MSwgMHg3OTBkYjk4YSwgMHg3M2Y2MDkyZCxcbiAgICAweDczNzA0NWQ2LCAweDcyN2NkYzIwLCAweDcyZmE5MGRiLCAweDcwNjVlZmNjLCAweDcwZTNhMzM3LCAweDcxZWYzYWMxLCAweDcxNjk3NjNhLCAweDc0NTc4ODE0LCAweDc0ZDFjNGVmLFxuICAgIDB4NzVkZDVkMTksIDB4NzU1YjExZTIsIDB4NzdjNDZlZjUsIDB4Nzc0MjIyMGUsIDB4NzY0ZWJiZjgsIDB4NzZjOGY3MDMsIDB4NjMzZjk2NGQsIDB4NjNiOWRhYjYsIDB4NjJiNTQzNDAsXG4gICAgMHg2MjMzMGZiYixcbiAgICAweDYwYWM3MGFjLCAweDYwMmEzYzU3LCAweDYxMjZhNWExLCAweDYxYTBlOTVhLCAweDY0OWUxNzc0LCAweDY0MTg1YjhmLCAweDY1MTRjMjc5LCAweDY1OTI4ZTgyLCAweDY3MGRmMTk1LFxuICAgIDB4Njc4YmJkNmUsIDB4NjY4NzI0OTgsIDB4NjYwMTY4NjMsIDB4NmNmYWQ4YzQsIDB4NmM3Yzk0M2YsIDB4NmQ3MDBkYzksIDB4NmRmNjQxMzIsIDB4NmY2OTNlMjUsIDB4NmZlZjcyZGUsXG4gICAgMHg2ZWUzZWIyOCwgMHg2ZTY1YTdkMywgMHg2YjViNTlmZCwgMHg2YmRkMTUwNiwgMHg2YWQxOGNmMCwgMHg2YTU3YzAwYiwgMHg2OGM4YmYxYywgMHg2ODRlZjNlNywgMHg2OTQyNmExMSxcbiAgICAweDY5YzQyNmVhLCAweDQyMmFlNDc2LCAweDQyYWNhODhkLCAweDQzYTAzMTdiLCAweDQzMjY3ZDgwLCAweDQxYjkwMjk3LCAweDQxM2Y0ZTZjLCAweDQwMzNkNzlhLCAweDQwYjU5YjYxLFxuICAgIDB4NDU4YjY1NGYsIDB4NDUwZDI5YjQsIDB4NDQwMWIwNDIsIDB4NDQ4N2ZjYjksIDB4NDYxODgzYWUsIDB4NDY5ZWNmNTUsIDB4NDc5MjU2YTMsIDB4NDcxNDFhNTgsIDB4NGRlZmFhZmYsXG4gICAgMHg0ZDY5ZTYwNCwgMHg0YzY1N2ZmMiwgMHg0Y2UzMzMwOSwgMHg0ZTdjNGMxZSwgMHg0ZWZhMDBlNSwgMHg0ZmY2OTkxMywgMHg0ZjcwZDVlOCwgMHg0YTRlMmJjNiwgMHg0YWM4NjczZCxcbiAgICAweDRiYzRmZWNiLCAweDRiNDJiMjMwLCAweDQ5ZGRjZDI3LCAweDQ5NWI4MWRjLCAweDQ4NTcxODJhLCAweDQ4ZDE1NGQxLCAweDVkMjYzNTlmLCAweDVkYTA3OTY0LCAweDVjYWNlMDkyLFxuICAgIDB4NWMyYWFjNjksIDB4NWViNWQzN2UsIDB4NWUzMzlmODUsIDB4NWYzZjA2NzMsIDB4NWZiOTRhODgsIDB4NWE4N2I0YTYsIDB4NWEwMWY4NWQsIDB4NWIwZDYxYWIsIDB4NWI4YjJkNTAsXG4gICAgMHg1OTE0NTI0NywgMHg1OTkyMWViYywgMHg1ODllODc0YSwgMHg1ODE4Y2JiMSwgMHg1MmUzN2IxNiwgMHg1MjY1MzdlZCwgMHg1MzY5YWUxYiwgMHg1M2VmZTJlMCwgMHg1MTcwOWRmNyxcbiAgICAweDUxZjZkMTBjLFxuICAgIDB4NTBmYTQ4ZmEsIDB4NTA3YzA0MDEsIDB4NTU0MmZhMmYsIDB4NTVjNGI2ZDQsIDB4NTRjODJmMjIsIDB4NTQ0ZTYzZDksIDB4NTZkMTFjY2UsIDB4NTY1NzUwMzUsIDB4NTc1YmM5YzMsXG4gICAgMHg1N2RkODUzOFxuXTtcblxuZnVuY3Rpb24gY3JlYXRlY3JjMjQoaW5wdXQpIHtcbiAgdmFyIGNyYyA9IDB4QjcwNENFO1xuICB2YXIgaW5kZXggPSAwO1xuXG4gIHdoaWxlICgoaW5wdXQubGVuZ3RoIC0gaW5kZXgpID4gMTYpIHtcbiAgICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXgpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDEpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDIpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDMpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDQpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDUpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDYpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDcpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDgpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDkpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDEwKSkgJiAweGZmXTtcbiAgICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXggKyAxMSkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMTIpKSAmIDB4ZmZdO1xuICAgIGNyYyA9IChjcmMgPDwgOCkgXiBjcmNfdGFibGVbKChjcmMgPj4gMTYpIF4gaW5wdXQuY2hhckNvZGVBdChpbmRleCArIDEzKSkgJiAweGZmXTtcbiAgICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXggKyAxNCkpICYgMHhmZl07XG4gICAgY3JjID0gKGNyYyA8PCA4KSBeIGNyY190YWJsZVsoKGNyYyA+PiAxNikgXiBpbnB1dC5jaGFyQ29kZUF0KGluZGV4ICsgMTUpKSAmIDB4ZmZdO1xuICAgIGluZGV4ICs9IDE2O1xuICB9XG5cbiAgZm9yICh2YXIgaiA9IGluZGV4OyBqIDwgaW5wdXQubGVuZ3RoOyBqKyspIHtcbiAgICBjcmMgPSAoY3JjIDw8IDgpIF4gY3JjX3RhYmxlWygoY3JjID4+IDE2KSBeIGlucHV0LmNoYXJDb2RlQXQoaW5kZXgrKykpICYgMHhmZl07XG4gIH1cbiAgcmV0dXJuIGNyYyAmIDB4ZmZmZmZmO1xufVxuXG4vKipcbiAqIERlQXJtb3IgYW4gT3BlblBHUCBhcm1vcmVkIG1lc3NhZ2U7IHZlcmlmeSB0aGUgY2hlY2tzdW0gYW5kIHJldHVybiBcbiAqIHRoZSBlbmNvZGVkIGJ5dGVzXG4gKiBAcGFyYW0ge1N0cmluZ30gdGV4dCBPcGVuUEdQIGFybW9yZWQgbWVzc2FnZVxuICogQHJldHVybnMgeyhCb29sZWFufE9iamVjdCl9IEVpdGhlciBmYWxzZSBpbiBjYXNlIG9mIGFuIGVycm9yIFxuICogb3IgYW4gb2JqZWN0IHdpdGggYXR0cmlidXRlIFwidGV4dFwiIGNvbnRhaW5pbmcgdGhlIG1lc3NhZ2UgdGV4dFxuICogYW5kIGFuIGF0dHJpYnV0ZSBcImRhdGFcIiBjb250YWluaW5nIHRoZSBieXRlcy5cbiAqL1xuZnVuY3Rpb24gZGVhcm1vcih0ZXh0KSB7XG4gIHRleHQgPSB0ZXh0LnJlcGxhY2UoL1xcci9nLCAnJyk7XG5cbiAgdmFyIHR5cGUgPSBnZXRfdHlwZSh0ZXh0KTtcblxuICBpZiAodHlwZSAhPSAyKSB7XG4gICAgdmFyIHNwbGl0dGVkdGV4dCA9IHRleHQuc3BsaXQoJy0tLS0tJyk7XG5cbiAgICB2YXIgcmVzdWx0ID0ge1xuICAgICAgZGF0YTogYmFzZTY0LmRlY29kZShcbiAgICAgICAgc3BsaXR0ZWR0ZXh0WzJdXG4gICAgICAgIC5zcGxpdCgnXFxuXFxuJylbMV1cbiAgICAgICAgLnNwbGl0KFwiXFxuPVwiKVswXVxuICAgICAgICAucmVwbGFjZSgvXFxuLSAvZywgXCJcXG5cIikpLFxuICAgICAgdHlwZTogdHlwZVxuICAgIH07XG5cbiAgICBpZiAodmVyaWZ5Q2hlY2tTdW0ocmVzdWx0LmRhdGEsXG4gICAgICBzcGxpdHRlZHRleHRbMl1cbiAgICAgIC5zcGxpdCgnXFxuXFxuJylbMV1cbiAgICAgIC5zcGxpdChcIlxcbj1cIilbMV1cbiAgICAgIC5zcGxpdCgnXFxuJylbMF0pKVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIGVsc2Uge1xuICAgICAgdXRpbC5wcmludF9lcnJvcihcIkFzY2lpIGFybW9yIGludGVncml0eSBjaGVjayBvbiBtZXNzYWdlIGZhaWxlZDogJ1wiICsgc3BsaXR0ZWR0ZXh0WzJdXG4gICAgICAgIC5zcGxpdCgnXFxuXFxuJylbMV1cbiAgICAgICAgLnNwbGl0KFwiXFxuPVwiKVsxXVxuICAgICAgICAuc3BsaXQoJ1xcbicpWzBdICsgXCInIHNob3VsZCBiZSAnXCIgKyBnZXRDaGVja1N1bShyZXN1bHQuZGF0YSkpICsgXCInXCI7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBzcGxpdHRlZHRleHQgPSB0ZXh0LnNwbGl0KCctLS0tLScpO1xuXG4gICAgdmFyIHJlc3VsdCA9IHtcbiAgICAgIHRleHQ6IHNwbGl0dGVkdGV4dFsyXVxuICAgICAgICAucmVwbGFjZSgvXFxuLSAvZywgXCJcXG5cIilcbiAgICAgICAgLnNwbGl0KFwiXFxuXFxuXCIpWzFdLFxuICAgICAgZGF0YTogYmFzZTY0LmRlY29kZShzcGxpdHRlZHRleHRbNF1cbiAgICAgICAgLnNwbGl0KFwiXFxuXFxuXCIpWzFdXG4gICAgICAgIC5zcGxpdChcIlxcbj1cIilbMF0pLFxuICAgICAgdHlwZTogdHlwZVxuICAgIH07XG5cbiAgICBpZiAodmVyaWZ5Q2hlY2tTdW0ocmVzdWx0LmRhdGEsIHNwbGl0dGVkdGV4dFs0XVxuICAgICAgLnNwbGl0KFwiXFxuXFxuXCIpWzFdXG4gICAgICAuc3BsaXQoXCJcXG49XCIpWzFdKSlcblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICBlbHNlIHtcbiAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJBc2NpaSBhcm1vciBpbnRlZ3JpdHkgY2hlY2sgb24gbWVzc2FnZSBmYWlsZWRcIik7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG59XG5cblxuLyoqXG4gKiBBcm1vciBhbiBPcGVuUEdQIGJpbmFyeSBwYWNrZXQgYmxvY2tcbiAqIEBwYXJhbSB7SW50ZWdlcn0gbWVzc2FnZXR5cGUgdHlwZSBvZiB0aGUgbWVzc2FnZVxuICogQHBhcmFtIGJvZHlcbiAqIEBwYXJhbSB7SW50ZWdlcn0gcGFydGluZGV4XG4gKiBAcGFyYW0ge0ludGVnZXJ9IHBhcnR0b3RhbFxuICogQHJldHVybnMge1N0cmluZ30gQXJtb3JlZCB0ZXh0XG4gKi9cbmZ1bmN0aW9uIGFybW9yKG1lc3NhZ2V0eXBlLCBib2R5LCBwYXJ0aW5kZXgsIHBhcnR0b3RhbCkge1xuICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgc3dpdGNoIChtZXNzYWdldHlwZSkge1xuICAgIGNhc2UgZW51bXMuYXJtb3IubXVsdGlwYXJ0X3NlY3Rpb246XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUJFR0lOIFBHUCBNRVNTQUdFLCBQQVJUIFwiICsgcGFydGluZGV4ICsgXCIvXCIgKyBwYXJ0dG90YWwgKyBcIi0tLS0tXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gYXJtb3JfYWRkaGVhZGVyKCk7XG4gICAgICByZXN1bHQgKz0gYmFzZTY0LmVuY29kZShib2R5KTtcbiAgICAgIHJlc3VsdCArPSBcIlxcclxcbj1cIiArIGdldENoZWNrU3VtKGJvZHkpICsgXCJcXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tRU5EIFBHUCBNRVNTQUdFLCBQQVJUIFwiICsgcGFydGluZGV4ICsgXCIvXCIgKyBwYXJ0dG90YWwgKyBcIi0tLS0tXFxyXFxuXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIGVudW1zLmFybW9yLm11dGxpcGFydF9sYXN0OlxuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1CRUdJTiBQR1AgTUVTU0FHRSwgUEFSVCBcIiArIHBhcnRpbmRleCArIFwiLS0tLS1cXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBhcm1vcl9hZGRoZWFkZXIoKTtcbiAgICAgIHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGJvZHkpO1xuICAgICAgcmVzdWx0ICs9IFwiXFxyXFxuPVwiICsgZ2V0Q2hlY2tTdW0oYm9keSkgKyBcIlxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1FTkQgUEdQIE1FU1NBR0UsIFBBUlQgXCIgKyBwYXJ0aW5kZXggKyBcIi0tLS0tXFxyXFxuXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIGVudW1zLmFybW9yLnNpZ25lZDpcbiAgICAgIHJlc3VsdCArPSBcIlxcclxcbi0tLS0tQkVHSU4gUEdQIFNJR05FRCBNRVNTQUdFLS0tLS1cXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBcIkhhc2g6IFwiICsgYm9keS5oYXNoICsgXCJcXHJcXG5cXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBib2R5LnRleHQucmVwbGFjZSgvXFxuLS9nLCBcIlxcbi0gLVwiKTtcbiAgICAgIHJlc3VsdCArPSBcIlxcclxcbi0tLS0tQkVHSU4gUEdQIFNJR05BVFVSRS0tLS0tXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gYXJtb3JfYWRkaGVhZGVyKCk7XG4gICAgICByZXN1bHQgKz0gYmFzZTY0LmVuY29kZShib2R5LmRhdGEpO1xuICAgICAgcmVzdWx0ICs9IFwiXFxyXFxuPVwiICsgZ2V0Q2hlY2tTdW0oYm9keS5kYXRhKSArIFwiXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUVORCBQR1AgU0lHTkFUVVJFLS0tLS1cXHJcXG5cIjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgZW51bXMuYXJtb3IubWVzc2FnZTpcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tQkVHSU4gUEdQIE1FU1NBR0UtLS0tLVxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IGFybW9yX2FkZGhlYWRlcigpO1xuICAgICAgcmVzdWx0ICs9IGJhc2U2NC5lbmNvZGUoYm9keSk7XG4gICAgICByZXN1bHQgKz0gXCJcXHJcXG49XCIgKyBnZXRDaGVja1N1bShib2R5KSArIFwiXFxyXFxuXCI7XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tXFxyXFxuXCI7XG4gICAgICBicmVhaztcbiAgICBjYXNlIGVudW1zLmFybW9yLnB1YmxpY19rZXk6XG4gICAgICByZXN1bHQgKz0gXCItLS0tLUJFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS1cXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBhcm1vcl9hZGRoZWFkZXIoKTtcbiAgICAgIHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGJvZHkpO1xuICAgICAgcmVzdWx0ICs9IFwiXFxyXFxuPVwiICsgZ2V0Q2hlY2tTdW0oYm9keSkgKyBcIlxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLVxcclxcblxcclxcblwiO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSBlbnVtcy5hcm1vci5wcml2YXRlX2tleTpcbiAgICAgIHJlc3VsdCArPSBcIi0tLS0tQkVHSU4gUEdQIFBSSVZBVEUgS0VZIEJMT0NLLS0tLS1cXHJcXG5cIjtcbiAgICAgIHJlc3VsdCArPSBhcm1vcl9hZGRoZWFkZXIoKTtcbiAgICAgIHJlc3VsdCArPSBiYXNlNjQuZW5jb2RlKGJvZHkpO1xuICAgICAgcmVzdWx0ICs9IFwiXFxyXFxuPVwiICsgZ2V0Q2hlY2tTdW0oYm9keSkgKyBcIlxcclxcblwiO1xuICAgICAgcmVzdWx0ICs9IFwiLS0tLS1FTkQgUEdQIFBSSVZBVEUgS0VZIEJMT0NLLS0tLS1cXHJcXG5cIjtcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGVuY29kZTogYXJtb3IsXG4gIGRlY29kZTogZGVhcm1vclxufTtcbiIsIi8qIE9wZW5QR1AgcmFkaXgtNjQvYmFzZTY0IHN0cmluZyBlbmNvZGluZy9kZWNvZGluZ1xuICogQ29weXJpZ2h0IDIwMDUgSGVyYmVydCBIYW5ld2lua2VsLCB3d3cuaGFuZVdJTi5kZVxuICogdmVyc2lvbiAxLjAsIGNoZWNrIHd3dy5oYW5lV0lOLmRlIGZvciB0aGUgbGF0ZXN0IHZlcnNpb25cbiAqXG4gKiBUaGlzIHNvZnR3YXJlIGlzIHByb3ZpZGVkIGFzLWlzLCB3aXRob3V0IGV4cHJlc3Mgb3IgaW1wbGllZCB3YXJyYW50eS4gIFxuICogUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgZGlzdHJpYnV0ZSBvciBzZWxsIHRoaXMgc29mdHdhcmUsIHdpdGggb3JcbiAqIHdpdGhvdXQgZmVlLCBmb3IgYW55IHB1cnBvc2UgYW5kIGJ5IGFueSBpbmRpdmlkdWFsIG9yIG9yZ2FuaXphdGlvbiwgaXMgaGVyZWJ5XG4gKiBncmFudGVkLCBwcm92aWRlZCB0aGF0IHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBhcmFncmFwaCBhcHBlYXIgXG4gKiBpbiBhbGwgY29waWVzLiBEaXN0cmlidXRpb24gYXMgYSBwYXJ0IG9mIGFuIGFwcGxpY2F0aW9uIG9yIGJpbmFyeSBtdXN0XG4gKiBpbmNsdWRlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGluIHRoZSBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHNcbiAqIHByb3ZpZGVkIHdpdGggdGhlIGFwcGxpY2F0aW9uIG9yIGRpc3RyaWJ1dGlvbi5cbiAqL1xuXG52YXIgYjY0cyA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcblxuZnVuY3Rpb24gczJyKHQpIHtcbiAgdmFyIGEsIGMsIG47XG4gIHZhciByID0gJycsXG4gICAgbCA9IDAsXG4gICAgcyA9IDA7XG4gIHZhciB0bCA9IHQubGVuZ3RoO1xuXG4gIGZvciAobiA9IDA7IG4gPCB0bDsgbisrKSB7XG4gICAgYyA9IHQuY2hhckNvZGVBdChuKTtcbiAgICBpZiAocyA9PSAwKSB7XG4gICAgICByICs9IGI2NHMuY2hhckF0KChjID4+IDIpICYgNjMpO1xuICAgICAgYSA9IChjICYgMykgPDwgNDtcbiAgICB9IGVsc2UgaWYgKHMgPT0gMSkge1xuICAgICAgciArPSBiNjRzLmNoYXJBdCgoYSB8IChjID4+IDQpICYgMTUpKTtcbiAgICAgIGEgPSAoYyAmIDE1KSA8PCAyO1xuICAgIH0gZWxzZSBpZiAocyA9PSAyKSB7XG4gICAgICByICs9IGI2NHMuY2hhckF0KGEgfCAoKGMgPj4gNikgJiAzKSk7XG4gICAgICBsICs9IDE7XG4gICAgICBpZiAoKGwgJSA2MCkgPT0gMClcbiAgICAgICAgciArPSBcIlxcblwiO1xuICAgICAgciArPSBiNjRzLmNoYXJBdChjICYgNjMpO1xuICAgIH1cbiAgICBsICs9IDE7XG4gICAgaWYgKChsICUgNjApID09IDApXG4gICAgICByICs9IFwiXFxuXCI7XG5cbiAgICBzICs9IDE7XG4gICAgaWYgKHMgPT0gMylcbiAgICAgIHMgPSAwO1xuICB9XG4gIGlmIChzID4gMCkge1xuICAgIHIgKz0gYjY0cy5jaGFyQXQoYSk7XG4gICAgbCArPSAxO1xuICAgIGlmICgobCAlIDYwKSA9PSAwKVxuICAgICAgciArPSBcIlxcblwiO1xuICAgIHIgKz0gJz0nO1xuICAgIGwgKz0gMTtcbiAgfVxuICBpZiAocyA9PSAxKSB7XG4gICAgaWYgKChsICUgNjApID09IDApXG4gICAgICByICs9IFwiXFxuXCI7XG4gICAgciArPSAnPSc7XG4gIH1cblxuICByZXR1cm4gcjtcbn1cblxuZnVuY3Rpb24gcjJzKHQpIHtcbiAgdmFyIGMsIG47XG4gIHZhciByID0gJycsXG4gICAgcyA9IDAsXG4gICAgYSA9IDA7XG4gIHZhciB0bCA9IHQubGVuZ3RoO1xuXG4gIGZvciAobiA9IDA7IG4gPCB0bDsgbisrKSB7XG4gICAgYyA9IGI2NHMuaW5kZXhPZih0LmNoYXJBdChuKSk7XG4gICAgaWYgKGMgPj0gMCkge1xuICAgICAgaWYgKHMpXG4gICAgICAgIHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShhIHwgKGMgPj4gKDYgLSBzKSkgJiAyNTUpO1xuICAgICAgcyA9IChzICsgMikgJiA3O1xuICAgICAgYSA9IChjIDw8IHMpICYgMjU1O1xuICAgIH1cbiAgfVxuICByZXR1cm4gcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGVuY29kZTogczJyLFxuICBkZWNvZGU6IHIyc1xufVxuIiwidmFyIGVudW1zID0ge1xuXG4gIC8qKiBBIHN0cmluZyB0byBrZXkgc3BlY2lmaWVyIHR5cGVcbiAgICogQGVudW0ge0ludGVnZXJ9XG4gICAqL1xuICBzMms6IHtcbiAgICBzaW1wbGU6IDAsXG4gICAgc2FsdGVkOiAxLFxuICAgIGl0ZXJhdGVkOiAzLFxuICAgIGdudTogMTAxXG4gIH0sXG5cbiAgLyoqIFJGQzQ4ODAsIHNlY3Rpb24gOS4xIFxuICAgKiBAZW51bSB7U3RyaW5nfVxuICAgKi9cbiAgcHVibGljS2V5OiB7XG4gICAgcnNhX2VuY3J5cHRfc2lnbjogMSxcbiAgICByc2FfZW5jcnlwdDogMixcbiAgICByc2Ffc2lnbjogMyxcbiAgICBlbGdhbWFsOiAxNixcbiAgICBkc2E6IDE3XG4gIH0sXG5cbiAgLyoqIFJGQzQ4ODAsIHNlY3Rpb24gOS4yIFxuICAgKiBAZW51bSB7U3RyaW5nfVxuICAgKi9cbiAgc3ltbWV0cmljOiB7XG4gICAgcGxhaW50ZXh0OiAwLFxuICAgIC8qKiBOb3QgaW1wbGVtZW50ZWQhICovXG4gICAgaWRlYTogMSxcbiAgICB0cmlwbGVkZXM6IDIsXG4gICAgY2FzdDU6IDMsXG4gICAgYmxvd2Zpc2g6IDQsXG4gICAgYWVzMTI4OiA3LFxuICAgIGFlczE5MjogOCxcbiAgICBhZXMyNTY6IDksXG4gICAgdHdvZmlzaDogMTBcbiAgfSxcblxuICAvKiogUkZDNDg4MCwgc2VjdGlvbiA5LjNcbiAgICogQGVudW0ge1N0cmluZ31cbiAgICovXG4gIGNvbXByZXNzaW9uOiB7XG4gICAgdW5jb21wcmVzc2VkOiAwLFxuICAgIC8qKiBSRkMxOTUxICovXG4gICAgemlwOiAxLFxuICAgIC8qKiBSRkMxOTUwICovXG4gICAgemxpYjogMixcbiAgICBiemlwMjogM1xuICB9LFxuXG4gIC8qKiBSRkM0ODgwLCBzZWN0aW9uIDkuNFxuICAgKiBAZW51bSB7U3RyaW5nfVxuICAgKi9cbiAgaGFzaDoge1xuICAgIG1kNTogMSxcbiAgICBzaGExOiAyLFxuICAgIHJpcGVtZDogMyxcbiAgICBzaGEyNTY6IDgsXG4gICAgc2hhMzg0OiA5LFxuICAgIHNoYTUxMjogMTAsXG4gICAgc2hhMjI0OiAxMVxuICB9LFxuXG5cbiAgLyoqXG4gICAqIEBlbnVtIHtTdHJpbmd9XG4gICAqIEEgbGlzdCBvZiBwYWNrZXQgdHlwZXMgYW5kIG51bWVyaWMgdGFncyBhc3NvY2lhdGVkIHdpdGggdGhlbS5cbiAgICovXG4gIHBhY2tldDoge1xuICAgIHB1YmxpY19rZXlfZW5jcnlwdGVkX3Nlc3Npb25fa2V5OiAxLFxuICAgIHNpZ25hdHVyZTogMixcbiAgICBzeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5OiAzLFxuICAgIG9uZV9wYXNzX3NpZ25hdHVyZTogNCxcbiAgICBzZWNyZXRfa2V5OiA1LFxuICAgIHB1YmxpY19rZXk6IDYsXG4gICAgc2VjcmV0X3N1YmtleTogNyxcbiAgICBjb21wcmVzc2VkOiA4LFxuICAgIHN5bW1ldHJpY2FsbHlfZW5jcnlwdGVkOiA5LFxuICAgIG1hcmtlcjogMTAsXG4gICAgbGl0ZXJhbDogMTEsXG4gICAgdHJ1c3Q6IDEyLFxuICAgIHVzZXJpZDogMTMsXG4gICAgcHVibGljX3N1YmtleTogMTQsXG4gICAgdXNlcl9hdHRyaWJ1dGU6IDE3LFxuICAgIHN5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZDogMTgsXG4gICAgbW9kaWZpY2F0aW9uX2RldGVjdGlvbl9jb2RlOiAxOVxuICB9LFxuXG5cbiAgLyoqXG4gICAqIERhdGEgdHlwZXMgaW4gdGhlIGxpdGVyYWwgcGFja2V0XG4gICAqIEByZWFkb25seVxuICAgKiBAZW51bSB7U3RyaW5nfVxuICAgKi9cbiAgbGl0ZXJhbDoge1xuICAgIC8qKiBCaW5hcnkgZGF0YSAqL1xuICAgIGJpbmFyeTogJ2InLmNoYXJDb2RlQXQoKSxcbiAgICAvKiogVGV4dCBkYXRhICovXG4gICAgdGV4dDogJ3QnLmNoYXJDb2RlQXQoKSxcbiAgICAvKiogVXRmOCBkYXRhICovXG4gICAgdXRmODogJ3UnLmNoYXJDb2RlQXQoKVxuICB9LFxuXG5cbiAgLyoqIE9uZSBwYXNzIHNpZ25hdHVyZSBwYWNrZXQgdHlwZVxuICAgKiBAZW51bSB7U3RyaW5nfSAqL1xuICBzaWduYXR1cmU6IHtcbiAgICAvKiogMHgwMDogU2lnbmF0dXJlIG9mIGEgYmluYXJ5IGRvY3VtZW50LiAqL1xuICAgIGJpbmFyeTogMCxcbiAgICAvKiogMHgwMTogU2lnbmF0dXJlIG9mIGEgY2Fub25pY2FsIHRleHQgZG9jdW1lbnQuXG4gICAgICogQ2Fub25pY2FseXppbmcgdGhlIGRvY3VtZW50IGJ5IGNvbnZlcnRpbmcgbGluZSBlbmRpbmdzLiAqL1xuICAgIHRleHQ6IDEsXG4gICAgLyoqIDB4MDI6IFN0YW5kYWxvbmUgc2lnbmF0dXJlLlxuICAgICAqIFRoaXMgc2lnbmF0dXJlIGlzIGEgc2lnbmF0dXJlIG9mIG9ubHkgaXRzIG93biBzdWJwYWNrZXQgY29udGVudHMuXG4gICAgICogSXQgaXMgY2FsY3VsYXRlZCBpZGVudGljYWxseSB0byBhIHNpZ25hdHVyZSBvdmVyIGEgemVyby1sZW5naFxuICAgICAqIGJpbmFyeSBkb2N1bWVudC4gIE5vdGUgdGhhdCBpdCBkb2Vzbid0IG1ha2Ugc2Vuc2UgdG8gaGF2ZSBhIFYzXG4gICAgICogc3RhbmRhbG9uZSBzaWduYXR1cmUuICovXG4gICAgc3RhbmRhbG9uZTogMixcbiAgICAvKiogMHgxMDogR2VuZXJpYyBjZXJ0aWZpY2F0aW9uIG9mIGEgVXNlciBJRCBhbmQgUHVibGljLUtleSBwYWNrZXQuXG4gICAgICogVGhlIGlzc3VlciBvZiB0aGlzIGNlcnRpZmljYXRpb24gZG9lcyBub3QgbWFrZSBhbnkgcGFydGljdWxhclxuICAgICAqIGFzc2VydGlvbiBhcyB0byBob3cgd2VsbCB0aGUgY2VydGlmaWVyIGhhcyBjaGVja2VkIHRoYXQgdGhlIG93bmVyXG4gICAgICogb2YgdGhlIGtleSBpcyBpbiBmYWN0IHRoZSBwZXJzb24gZGVzY3JpYmVkIGJ5IHRoZSBVc2VyIElELiAqL1xuICAgIGNlcnRfZ2VuZXJpYzogMTYsXG4gICAgLyoqIDB4MTE6IFBlcnNvbmEgY2VydGlmaWNhdGlvbiBvZiBhIFVzZXIgSUQgYW5kIFB1YmxpYy1LZXkgcGFja2V0LlxuICAgICAqIFRoZSBpc3N1ZXIgb2YgdGhpcyBjZXJ0aWZpY2F0aW9uIGhhcyBub3QgZG9uZSBhbnkgdmVyaWZpY2F0aW9uIG9mXG4gICAgICogdGhlIGNsYWltIHRoYXQgdGhlIG93bmVyIG9mIHRoaXMga2V5IGlzIHRoZSBVc2VyIElEIHNwZWNpZmllZC4gKi9cbiAgICBjZXJ0X3BlcnNvbmE6IDE3LFxuICAgIC8qKiAweDEyOiBDYXN1YWwgY2VydGlmaWNhdGlvbiBvZiBhIFVzZXIgSUQgYW5kIFB1YmxpYy1LZXkgcGFja2V0LlxuICAgICAqIFRoZSBpc3N1ZXIgb2YgdGhpcyBjZXJ0aWZpY2F0aW9uIGhhcyBkb25lIHNvbWUgY2FzdWFsXG4gICAgICogdmVyaWZpY2F0aW9uIG9mIHRoZSBjbGFpbSBvZiBpZGVudGl0eS4gKi9cbiAgICBjZXJ0X2Nhc3VhbDogMTgsXG4gICAgLyoqIDB4MTM6IFBvc2l0aXZlIGNlcnRpZmljYXRpb24gb2YgYSBVc2VyIElEIGFuZCBQdWJsaWMtS2V5IHBhY2tldC5cbiAgICAgKiBUaGUgaXNzdWVyIG9mIHRoaXMgY2VydGlmaWNhdGlvbiBoYXMgZG9uZSBzdWJzdGFudGlhbFxuICAgICAqIHZlcmlmaWNhdGlvbiBvZiB0aGUgY2xhaW0gb2YgaWRlbnRpdHkuXG4gICAgICogXG4gICAgICogTW9zdCBPcGVuUEdQIGltcGxlbWVudGF0aW9ucyBtYWtlIHRoZWlyIFwia2V5IHNpZ25hdHVyZXNcIiBhcyAweDEwXG4gICAgICogY2VydGlmaWNhdGlvbnMuICBTb21lIGltcGxlbWVudGF0aW9ucyBjYW4gaXNzdWUgMHgxMS0weDEzXG4gICAgICogY2VydGlmaWNhdGlvbnMsIGJ1dCBmZXcgZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIHRoZSB0eXBlcy4gKi9cbiAgICBjZXJ0X3Bvc2l0aXZlOiAxOSxcbiAgICAvKiogMHgzMDogQ2VydGlmaWNhdGlvbiByZXZvY2F0aW9uIHNpZ25hdHVyZVxuICAgICAqIFRoaXMgc2lnbmF0dXJlIHJldm9rZXMgYW4gZWFybGllciBVc2VyIElEIGNlcnRpZmljYXRpb24gc2lnbmF0dXJlXG4gICAgICogKHNpZ25hdHVyZSBjbGFzcyAweDEwIHRocm91Z2ggMHgxMykgb3IgZGlyZWN0LWtleSBzaWduYXR1cmVcbiAgICAgKiAoMHgxRikuICBJdCBzaG91bGQgYmUgaXNzdWVkIGJ5IHRoZSBzYW1lIGtleSB0aGF0IGlzc3VlZCB0aGVcbiAgICAgKiByZXZva2VkIHNpZ25hdHVyZSBvciBhbiBhdXRob3JpemVkIHJldm9jYXRpb24ga2V5LiAgVGhlIHNpZ25hdHVyZVxuICAgICAqIGlzIGNvbXB1dGVkIG92ZXIgdGhlIHNhbWUgZGF0YSBhcyB0aGUgY2VydGlmaWNhdGUgdGhhdCBpdFxuICAgICAqIHJldm9rZXMsIGFuZCBzaG91bGQgaGF2ZSBhIGxhdGVyIGNyZWF0aW9uIGRhdGUgdGhhbiB0aGF0XG4gICAgICogY2VydGlmaWNhdGUuICovXG4gICAgY2VydF9yZXZvY2F0aW9uOiA0OCxcbiAgICAvKiogMHgxODogU3Via2V5IEJpbmRpbmcgU2lnbmF0dXJlXG4gICAgICogVGhpcyBzaWduYXR1cmUgaXMgYSBzdGF0ZW1lbnQgYnkgdGhlIHRvcC1sZXZlbCBzaWduaW5nIGtleSB0aGF0XG4gICAgICogaW5kaWNhdGVzIHRoYXQgaXQgb3ducyB0aGUgc3Via2V5LiAgVGhpcyBzaWduYXR1cmUgaXMgY2FsY3VsYXRlZFxuICAgICAqIGRpcmVjdGx5IG9uIHRoZSBwcmltYXJ5IGtleSBhbmQgc3Via2V5LCBhbmQgbm90IG9uIGFueSBVc2VyIElEIG9yXG4gICAgICogb3RoZXIgcGFja2V0cy4gIEEgc2lnbmF0dXJlIHRoYXQgYmluZHMgYSBzaWduaW5nIHN1YmtleSBNVVNUIGhhdmVcbiAgICAgKiBhbiBFbWJlZGRlZCBTaWduYXR1cmUgc3VicGFja2V0IGluIHRoaXMgYmluZGluZyBzaWduYXR1cmUgdGhhdFxuICAgICAqIGNvbnRhaW5zIGEgMHgxOSBzaWduYXR1cmUgbWFkZSBieSB0aGUgc2lnbmluZyBzdWJrZXkgb24gdGhlXG4gICAgICogcHJpbWFyeSBrZXkgYW5kIHN1YmtleS4gKi9cbiAgICBzdWJrZXlfYmluZGluZzogMjQsXG4gICAgLyoqIDB4MTk6IFByaW1hcnkgS2V5IEJpbmRpbmcgU2lnbmF0dXJlXG5cdFx0KiBUaGlzIHNpZ25hdHVyZSBpcyBhIHN0YXRlbWVudCBieSBhIHNpZ25pbmcgc3Via2V5LCBpbmRpY2F0aW5nXG5cdFx0KiB0aGF0IGl0IGlzIG93bmVkIGJ5IHRoZSBwcmltYXJ5IGtleSBhbmQgc3Via2V5LiAgVGhpcyBzaWduYXR1cmVcblx0XHQqIGlzIGNhbGN1bGF0ZWQgdGhlIHNhbWUgd2F5IGFzIGEgMHgxOCBzaWduYXR1cmU6IGRpcmVjdGx5IG9uIHRoZVxuXHRcdCogcHJpbWFyeSBrZXkgYW5kIHN1YmtleSwgYW5kIG5vdCBvbiBhbnkgVXNlciBJRCBvciBvdGhlciBwYWNrZXRzLlxuXHRcdFxuXHRcdCogV2hlbiBhIHNpZ25hdHVyZSBpcyBtYWRlIG92ZXIgYSBrZXksIHRoZSBoYXNoIGRhdGEgc3RhcnRzIHdpdGggdGhlXG5cdFx0KiBvY3RldCAweDk5LCBmb2xsb3dlZCBieSBhIHR3by1vY3RldCBsZW5ndGggb2YgdGhlIGtleSwgYW5kIHRoZW4gYm9keVxuXHRcdCogb2YgdGhlIGtleSBwYWNrZXQuICAoTm90ZSB0aGF0IHRoaXMgaXMgYW4gb2xkLXN0eWxlIHBhY2tldCBoZWFkZXIgZm9yXG5cdFx0KiBhIGtleSBwYWNrZXQgd2l0aCB0d28tb2N0ZXQgbGVuZ3RoLikgIEEgc3Via2V5IGJpbmRpbmcgc2lnbmF0dXJlXG5cdFx0KiAodHlwZSAweDE4KSBvciBwcmltYXJ5IGtleSBiaW5kaW5nIHNpZ25hdHVyZSAodHlwZSAweDE5KSB0aGVuIGhhc2hlc1xuXHRcdCogdGhlIHN1YmtleSB1c2luZyB0aGUgc2FtZSBmb3JtYXQgYXMgdGhlIG1haW4ga2V5IChhbHNvIHVzaW5nIDB4OTkgYXNcblx0XHQqIHRoZSBmaXJzdCBvY3RldCkuICovXG4gICAga2V5X2JpbmRpbmc6IDI1LFxuICAgIC8qKiAweDFGOiBTaWduYXR1cmUgZGlyZWN0bHkgb24gYSBrZXlcbiAgICAgKiBUaGlzIHNpZ25hdHVyZSBpcyBjYWxjdWxhdGVkIGRpcmVjdGx5IG9uIGEga2V5LiAgSXQgYmluZHMgdGhlXG4gICAgICogaW5mb3JtYXRpb24gaW4gdGhlIFNpZ25hdHVyZSBzdWJwYWNrZXRzIHRvIHRoZSBrZXksIGFuZCBpc1xuICAgICAqIGFwcHJvcHJpYXRlIHRvIGJlIHVzZWQgZm9yIHN1YnBhY2tldHMgdGhhdCBwcm92aWRlIGluZm9ybWF0aW9uXG4gICAgICogYWJvdXQgdGhlIGtleSwgc3VjaCBhcyB0aGUgUmV2b2NhdGlvbiBLZXkgc3VicGFja2V0LiAgSXQgaXMgYWxzb1xuICAgICAqIGFwcHJvcHJpYXRlIGZvciBzdGF0ZW1lbnRzIHRoYXQgbm9uLXNlbGYgY2VydGlmaWVycyB3YW50IHRvIG1ha2VcbiAgICAgKiBhYm91dCB0aGUga2V5IGl0c2VsZiwgcmF0aGVyIHRoYW4gdGhlIGJpbmRpbmcgYmV0d2VlbiBhIGtleSBhbmQgYVxuICAgICAqIG5hbWUuICovXG4gICAga2V5OiAzMSxcbiAgICAvKiogMHgyMDogS2V5IHJldm9jYXRpb24gc2lnbmF0dXJlXG4gICAgICogVGhlIHNpZ25hdHVyZSBpcyBjYWxjdWxhdGVkIGRpcmVjdGx5IG9uIHRoZSBrZXkgYmVpbmcgcmV2b2tlZC4gIEFcbiAgICAgKiByZXZva2VkIGtleSBpcyBub3QgdG8gYmUgdXNlZC4gIE9ubHkgcmV2b2NhdGlvbiBzaWduYXR1cmVzIGJ5IHRoZVxuICAgICAqIGtleSBiZWluZyByZXZva2VkLCBvciBieSBhbiBhdXRob3JpemVkIHJldm9jYXRpb24ga2V5LCBzaG91bGQgYmVcbiAgICAgKiBjb25zaWRlcmVkIHZhbGlkIHJldm9jYXRpb24gc2lnbmF0dXJlcy5hICovXG4gICAga2V5X3Jldm9jYXRpb246IDMyLFxuICAgIC8qKiAweDI4OiBTdWJrZXkgcmV2b2NhdGlvbiBzaWduYXR1cmVcbiAgICAgKiBUaGUgc2lnbmF0dXJlIGlzIGNhbGN1bGF0ZWQgZGlyZWN0bHkgb24gdGhlIHN1YmtleSBiZWluZyByZXZva2VkLlxuICAgICAqIEEgcmV2b2tlZCBzdWJrZXkgaXMgbm90IHRvIGJlIHVzZWQuICBPbmx5IHJldm9jYXRpb24gc2lnbmF0dXJlc1xuICAgICAqIGJ5IHRoZSB0b3AtbGV2ZWwgc2lnbmF0dXJlIGtleSB0aGF0IGlzIGJvdW5kIHRvIHRoaXMgc3Via2V5LCBvclxuICAgICAqIGJ5IGFuIGF1dGhvcml6ZWQgcmV2b2NhdGlvbiBrZXksIHNob3VsZCBiZSBjb25zaWRlcmVkIHZhbGlkXG4gICAgICogcmV2b2NhdGlvbiBzaWduYXR1cmVzLlxuICAgICAqIEtleSByZXZvY2F0aW9uIHNpZ25hdHVyZXMgKHR5cGVzIDB4MjAgYW5kIDB4MjgpXG4gICAgICogaGFzaCBvbmx5IHRoZSBrZXkgYmVpbmcgcmV2b2tlZC4gKi9cbiAgICBzdWJrZXlfcmV2b2NhdGlvbjogNDAsXG4gICAgLyoqIDB4NDA6IFRpbWVzdGFtcCBzaWduYXR1cmUuXG4gICAgICogVGhpcyBzaWduYXR1cmUgaXMgb25seSBtZWFuaW5nZnVsIGZvciB0aGUgdGltZXN0YW1wIGNvbnRhaW5lZCBpblxuICAgICAqIGl0LiAqL1xuICAgIHRpbWVzdGFtcDogNjQsXG4gICAgLyoqICAgIDB4NTA6IFRoaXJkLVBhcnR5IENvbmZpcm1hdGlvbiBzaWduYXR1cmUuXG4gICAgICogVGhpcyBzaWduYXR1cmUgaXMgYSBzaWduYXR1cmUgb3ZlciBzb21lIG90aGVyIE9wZW5QR1AgU2lnbmF0dXJlXG4gICAgICogcGFja2V0KHMpLiAgSXQgaXMgYW5hbG9nb3VzIHRvIGEgbm90YXJ5IHNlYWwgb24gdGhlIHNpZ25lZCBkYXRhLlxuICAgICAqIEEgdGhpcmQtcGFydHkgc2lnbmF0dXJlIFNIT1VMRCBpbmNsdWRlIFNpZ25hdHVyZSBUYXJnZXRcbiAgICAgKiBzdWJwYWNrZXQocykgdG8gZ2l2ZSBlYXN5IGlkZW50aWZpY2F0aW9uLiAgTm90ZSB0aGF0IHdlIHJlYWxseSBkb1xuICAgICAqIG1lYW4gU0hPVUxELiAgVGhlcmUgYXJlIHBsYXVzaWJsZSB1c2VzIGZvciB0aGlzIChzdWNoIGFzIGEgYmxpbmRcbiAgICAgKiBwYXJ0eSB0aGF0IG9ubHkgc2VlcyB0aGUgc2lnbmF0dXJlLCBub3QgdGhlIGtleSBvciBzb3VyY2VcbiAgICAgKiBkb2N1bWVudCkgdGhhdCBjYW5ub3QgaW5jbHVkZSBhIHRhcmdldCBzdWJwYWNrZXQuICovXG4gICAgdGhpcmRfcGFydHk6IDgwXG4gIH0sXG5cbiAgc2lnbmF0dXJlU3VicGFja2V0OiB7XG4gICAgc2lnbmF0dXJlX2NyZWF0aW9uX3RpbWU6IDIsXG4gICAgc2lnbmF0dXJlX2V4cGlyYXRpb25fdGltZTogMyxcbiAgICBleHBvcnRhYmxlX2NlcnRpZmljYXRpb246IDQsXG4gICAgdHJ1c3Rfc2lnbmF0dXJlOiA1LFxuICAgIHJlZ3VsYXJfZXhwcmVzc2lvbjogNixcbiAgICByZXZvY2FibGU6IDcsXG4gICAga2V5X2V4cGlyYXRpb25fdGltZTogOSxcbiAgICBwbGFjZWhvbGRlcl9iYWNrd2FyZHNfY29tcGF0aWJpbGl0eTogMTAsXG4gICAgcHJlZmVycmVkX3N5bW1ldHJpY19hbGdvcml0aG1zOiAxMSxcbiAgICByZXZvY2F0aW9uX2tleTogMTIsXG4gICAgaXNzdWVyOiAxNixcbiAgICBub3RhdGlvbl9kYXRhOiAyMCxcbiAgICBwcmVmZXJyZWRfaGFzaF9hbGdvcml0aG1zOiAyMSxcbiAgICBwcmVmZXJyZWRfY29tcHJlc3Npb25fYWxnb3JpdGhtczogMjIsXG4gICAga2V5X3NlcnZlcl9wcmVmZXJlbmNlczogMjMsXG4gICAgcHJlZmVycmVkX2tleV9zZXJ2ZXI6IDI0LFxuICAgIHByaW1hcnlfdXNlcl9pZDogMjUsXG4gICAgcG9saWN5X3VyaTogMjYsXG4gICAga2V5X2ZsYWdzOiAyNyxcbiAgICBzaWduZXJzX3VzZXJfaWQ6IDI4LFxuICAgIHJlYXNvbl9mb3JfcmV2b2NhdGlvbjogMjksXG4gICAgZmVhdHVyZXM6IDMwLFxuICAgIHNpZ25hdHVyZV90YXJnZXQ6IDMxLFxuICAgIGVtYmVkZGVkX3NpZ25hdHVyZTogMzJcbiAgfSxcblxuICBrZXlGbGFnczoge1xuICAgIC8vIDB4MDEgLSBUaGlzIGtleSBtYXkgYmUgdXNlZCB0byBjZXJ0aWZ5IG90aGVyIGtleXMuXG4gICAgY2VydGlmeV9rZXlzOiAxLFxuICAgIC8vIDB4MDIgLSBUaGlzIGtleSBtYXkgYmUgdXNlZCB0byBzaWduIGRhdGEuXG4gICAgc2lnbl9kYXRhOiAyLFxuICAgIC8vIDB4MDQgLSBUaGlzIGtleSBtYXkgYmUgdXNlZCB0byBlbmNyeXB0IGNvbW11bmljYXRpb25zLlxuICAgIGVuY3J5cHRfY29tbXVuaWNhdGlvbjogNCxcbiAgICAvLyAweDA4IC0gVGhpcyBrZXkgbWF5IGJlIHVzZWQgdG8gZW5jcnlwdCBzdG9yYWdlLlxuICAgIGVuY3J5cHRfc3RvcmFnZTogOCxcbiAgICAvLyAweDEwIC0gVGhlIHByaXZhdGUgY29tcG9uZW50IG9mIHRoaXMga2V5IG1heSBoYXZlIGJlZW4gc3BsaXRcbiAgICAvLyAgICAgICAgYnkgYSBzZWNyZXQtc2hhcmluZyBtZWNoYW5pc20uXG4gICAgc3BsaXRfcHJpdmF0ZV9rZXk6IDE2LFxuICAgIC8vIDB4MjAgLSBUaGlzIGtleSBtYXkgYmUgdXNlZCBmb3IgYXV0aGVudGljYXRpb24uXG4gICAgYXV0aGVudGljYXRpb246IDMyLFxuICAgIC8vIDB4ODAgLSBUaGUgcHJpdmF0ZSBjb21wb25lbnQgb2YgdGhpcyBrZXkgbWF5IGJlIGluIHRoZVxuICAgIC8vICAgICAgICBwb3NzZXNzaW9uIG9mIG1vcmUgdGhhbiBvbmUgcGVyc29uLlxuICAgIHNoYXJlZF9wcml2YXRlX2tleTogMTI4XG4gIH0sXG5cbiAgYXJtb3I6IHtcbiAgICBtdWx0aXBhcnRfc2VjdGlvbjogMCxcbiAgICBtdWx0aXBhcnRfbGFzdDogMSxcbiAgICBzaWduZWQ6IDIsXG4gICAgbWVzc2FnZTogMyxcbiAgICBwdWJsaWNfa2V5OiA0LFxuICAgIHByaXZhdGVfa2V5OiA1XG4gIH0sXG5cbiAgLy8gQXNzZXJ0cyB2YWxpZGl0eSBhbmQgY29udmVydHMgZnJvbSBzdHJpbmcvaW50ZWdlciB0byBpbnRlZ2VyLlxuICB3cml0ZTogZnVuY3Rpb24odHlwZSwgZSkge1xuICAgIGlmICh0eXBlb2YgZSA9PSAnbnVtYmVyJykge1xuICAgICAgZSA9IHRoaXMucmVhZCh0eXBlLCBlKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZVtlXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdHlwZVtlXTtcbiAgICB9IGVsc2UgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGVudW0gdmFsdWUuJyk7XG4gIH0sXG4gIC8vIENvbnZlcnRzIGZyb20gYW4gaW50ZWdlciB0byBzdHJpbmcuXG4gIHJlYWQ6IGZ1bmN0aW9uKHR5cGUsIGUpIHtcbiAgICBmb3IgKHZhciBpIGluIHR5cGUpXG4gICAgICBpZiAodHlwZVtpXSA9PSBlKSByZXR1cm4gaTtcblxuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBlbnVtIHZhbHVlLicpO1xuICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZW51bXM7XG4iLCJcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9vcGVucGdwLmpzJyk7XG5tb2R1bGUuZXhwb3J0cy5rZXkgPSByZXF1aXJlKCcuL2tleS5qcycpO1xubW9kdWxlLmV4cG9ydHMubWVzc2FnZSA9IHJlcXVpcmUoJy4vbWVzc2FnZS5qcycpO1xubW9kdWxlLmV4cG9ydHMudXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xubW9kdWxlLmV4cG9ydHMucGFja2V0ID0gcmVxdWlyZSgnLi9wYWNrZXQnKTtcbm1vZHVsZS5leHBvcnRzLm1waSA9IHJlcXVpcmUoJy4vdHlwZS9tcGkuanMnKTtcbm1vZHVsZS5leHBvcnRzLnMyayA9IHJlcXVpcmUoJy4vdHlwZS9zMmsuanMnKTtcbm1vZHVsZS5leHBvcnRzLmtleWlkID0gcmVxdWlyZSgnLi90eXBlL2tleWlkLmpzJyk7XG5tb2R1bGUuZXhwb3J0cy5hcm1vciA9IHJlcXVpcmUoJy4vZW5jb2RpbmcvYXJtb3IuanMnKTtcbm1vZHVsZS5leHBvcnRzLmVudW1zID0gcmVxdWlyZSgnLi9lbnVtcy5qcycpO1xubW9kdWxlLmV4cG9ydHMuY29uZmlnID0gcmVxdWlyZSgnLi9jb25maWcnKTtcbm1vZHVsZS5leHBvcnRzLmNyeXB0byA9IHJlcXVpcmUoJy4vY3J5cHRvJyk7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgcGFja2V0ID0gcmVxdWlyZSgnLi9wYWNrZXQnKTtcbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4vZW51bXMuanMnKTtcbnZhciBhcm1vciA9IHJlcXVpcmUoJy4vZW5jb2RpbmcvYXJtb3IuanMnKTtcbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBDbGFzcyB0aGF0IHJlcHJlc2VudHMgYW4gT3BlblBHUCBrZXkuIE11c3QgY29udGFpbiBhIG1hc3RlciBrZXkuIFxuICogQHBhcmFtICB7cGFja2V0bGlzdH0gcGFja2V0bGlzdCBbZGVzY3JpcHRpb25dXG4gKiBDYW4gY29udGFpbiBhZGRpdGlvbmFsIHN1YmtleXMsIHNpZ25hdHVyZXMsXG4gKiB1c2VyIGlkcywgdXNlciBhdHRyaWJ1dGVzLlxuICovXG5cbiBmdW5jdGlvbiBrZXkocGFja2V0bGlzdCkge1xuXG4gIHRoaXMucGFja2V0cyA9IHBhY2tldGxpc3QgfHwgbmV3IHBhY2tldC5saXN0KCk7XG5cbiAgLyoqIFxuICAgKiBSZXR1cm5zIHRoZSBwcmltYXJ5IGtleSBwYWNrZXQgKHNlY3JldCBvciBwdWJsaWMpXG4gICAqIEByZXR1cm5zIHtwYWNrZXRfc2VjcmV0X2tleXxwYWNrZXRfcHVibGljX2tleXxudWxsfSBcbiAgICovXG4gIHRoaXMuZ2V0S2V5UGFja2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnBhY2tldHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICh0aGlzLnBhY2tldHNbaV0udGFnID09IGVudW1zLnBhY2tldC5wdWJsaWNfa2V5IHx8XG4gICAgICAgIHRoaXMucGFja2V0c1tpXS50YWcgPT0gZW51bXMucGFja2V0LnNlY3JldF9rZXkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFja2V0c1tpXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKiogXG4gICAqIFJldHVybnMgYWxsIHRoZSBwcml2YXRlIGFuZCBwdWJsaWMgc3Via2V5IHBhY2tldHNcbiAgICogQHJldHVybnMge1twdWJsaWNfc3Via2V5fHNlY3JldF9zdWJrZXldfSBcbiAgICovXG4gIHRoaXMuZ2V0U3Via2V5UGFja2V0cyA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIHN1YmtleXMgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5wYWNrZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5wYWNrZXRzW2ldLnRhZyA9PSBlbnVtcy5wYWNrZXQucHVibGljX3N1YmtleSB8fFxuICAgICAgICB0aGlzLnBhY2tldHNbaV0udGFnID09IGVudW1zLnBhY2tldC5zZWNyZXRfc3Via2V5KSB7XG4gICAgICAgIHN1YmtleXMucHVzaCh0aGlzLnBhY2tldHNbaV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzdWJrZXlzO1xuICB9XG5cbiAgLyoqIFxuICAgKiBSZXR1cm5zIGFsbCB0aGUgcHJpdmF0ZSBhbmQgcHVibGljIGtleSBhbmQgc3Via2V5IHBhY2tldHNcbiAgICogQHJldHVybnMge1twdWJsaWNfc3Via2V5fHNlY3JldF9zdWJrZXl8cGFja2V0X3NlY3JldF9rZXl8cGFja2V0X3B1YmxpY19rZXldfSBcbiAgICovXG4gIHRoaXMuZ2V0QWxsS2V5UGFja2V0cyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBbdGhpcy5nZXRLZXlQYWNrZXQoKV0uY29uY2F0KHRoaXMuZ2V0U3Via2V5UGFja2V0cygpKTtcbiAgfVxuXG4gIC8qKiBcbiAgICogUmV0dXJucyBrZXkgSURzIG9mIGFsbCBrZXkgcGFja2V0c1xuICAgKiBAcmV0dXJucyB7W2tleWlkXX0gXG4gICAqL1xuICB0aGlzLmdldEtleUlkcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBrZXlJZHMgPSBbXTtcbiAgICB2YXIga2V5cyA9IHRoaXMuZ2V0QWxsS2V5UGFja2V0cygpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAga2V5SWRzLnB1c2goa2V5c1tpXS5nZXRLZXlJZCgpKTtcbiAgICB9XG4gICAgcmV0dXJuIGtleUlkcztcbiAgfVxuXG4gIGZ1bmN0aW9uIGZpbmRLZXkoa2V5cywga2V5SWRzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIga2V5SWQgPSBrZXlzW2ldLmdldEtleUlkKCk7IFxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBrZXlJZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKGtleUlkLmVxdWFscyhrZXlJZHNbal0pKSB7XG4gICAgICAgICAgcmV0dXJuIGtleXNbaV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBmaXJzdCBwdWJsaWMga2V5IHBhY2tldCBmb3IgZ2l2ZW4gYXJyYXkgb2Yga2V5IElEc1xuICAgKiBAcGFyYW0gIHtba2V5aWRdfSBrZXlJZHMgXG4gICAqIEByZXR1cm4ge3B1YmxpY19zdWJrZXl8cGFja2V0X3B1YmxpY19rZXl8bnVsbH0gICAgICAgXG4gICAqL1xuICB0aGlzLmdldFB1YmxpY0tleVBhY2tldCA9IGZ1bmN0aW9uKGtleUlkcykge1xuICAgIHZhciBrZXlzID0gdGhpcy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5wdWJsaWNfa2V5LCBlbnVtcy5wYWNrZXQucHVibGljX3N1YmtleSk7XG4gICAgcmV0dXJuIGZpbmRLZXkoa2V5cywga2V5SWRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGZpcnN0IHByaXZhdGUga2V5IHBhY2tldCBmb3IgZ2l2ZW4gYXJyYXkgb2Yga2V5IElEc1xuICAgKiBAcGFyYW0gIHtba2V5aWRdfSBrZXlJZHNcbiAgICogQHJldHVybiB7c2VjcmV0X3N1YmtleXxwYWNrZXRfc2VjcmV0X2tleXxudWxsfSAgICAgICBcbiAgICovXG4gIHRoaXMuZ2V0UHJpdmF0ZUtleVBhY2tldCA9IGZ1bmN0aW9uKGtleUlkcykge1xuICAgIHZhciBrZXlzID0gdGhpcy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5zZWNyZXRfa2V5LCBlbnVtcy5wYWNrZXQuc2VjcmV0X3N1YmtleSk7XG4gICAgcmV0dXJuIGZpbmRLZXkoa2V5cywga2V5SWRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhpcyBpcyBhIHB1YmxpYyBrZXlcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIHRoaXMuaXNQdWJsaWMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcHVibGljS2V5UGFja2V0cyA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQucHVibGljX2tleSk7XG4gICAgcmV0dXJuIHB1YmxpY0tleVBhY2tldHMubGVuZ3RoID8gdHJ1ZSA6IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIGlzIGEgcHJpdmF0ZSBrZXlcbiAgICogQHJldHVybiB7Qm9vbGVhbn1cbiAgICovXG4gIHRoaXMuaXNQcml2YXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByaXZhdGVLZXlQYWNrZXRzID0gdGhpcy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5wcml2YXRlX2tleSk7XG4gICAgcmV0dXJuIHByaXZhdGVLZXlQYWNrZXRzLmxlbmd0aCA/IHRydWUgOiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGtleSBhcyBwdWJsaWMga2V5XG4gICAqIEByZXR1cm4ge2tleX0gcHVibGljIGtleVxuICAgKi9cbiAgdGhpcy50b1B1YmxpYyA9IGZ1bmN0aW9uKCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5wYWNrZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5wYWNrZXRzW2ldLnRhZyA9PSBlbnVtcy5wYWNrZXQuc2VjcmV0X2tleSkge1xuICAgICAgICB2YXIgYnl0ZXMgPSB0aGlzLnBhY2tldHNbaV0ud3JpdGVQdWJsaWNLZXkoKTtcbiAgICAgICAgdmFyIHB1YktleVBhY2tldCA9IG5ldyBwYWNrZXQucHVibGljX2tleSgpO1xuICAgICAgICBwdWJLZXlQYWNrZXQucmVhZChieXRlcyk7XG4gICAgICAgIHRoaXMucGFja2V0c1tpXSA9IHB1YktleVBhY2tldDtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnBhY2tldHNbaV0udGFnID09IGVudW1zLnBhY2tldC5zZWNyZXRfc3Via2V5KSB7XG4gICAgICAgIHZhciBieXRlcyA9IHRoaXMucGFja2V0c1tpXS53cml0ZVB1YmxpY0tleSgpO1xuICAgICAgICB2YXIgcHViU3Via2V5UGFja2V0ID0gbmV3IHBhY2tldC5wdWJsaWNfc3Via2V5KCk7XG4gICAgICAgIHB1YlN1YmtleVBhY2tldC5yZWFkKGJ5dGVzKTtcbiAgICAgICAgdGhpcy5wYWNrZXRzW2ldID0gcHViU3Via2V5UGFja2V0O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIEFTQ0lJIGFybW9yZWQgdGV4dCBvZiBrZXlcbiAgICogQHJldHVybiB7U3RyaW5nfSBBU0NJSSBhcm1vclxuICAgKi9cbiAgdGhpcy5hcm1vciA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0eXBlID0gdGhpcy5pc1B1YmxpYygpID8gZW51bXMuYXJtb3IucHVibGljX2tleSA6IGVudW1zLmFybW9yLnByaXZhdGVfa2V5O1xuICAgIHJldHVybiBhcm1vci5lbmNvZGUodHlwZSwgdGhpcy5wYWNrZXRzLndyaXRlKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZmlyc3Qga2V5IHBhY2tldCB0aGF0IGlzIGF2YWlsYWJsZSBmb3Igc2lnbmluZ1xuICAgKiBAcmV0dXJuIHtwdWJsaWNfc3Via2V5fHNlY3JldF9zdWJrZXl8cGFja2V0X3NlY3JldF9rZXl8cGFja2V0X3B1YmxpY19rZXl8bnVsbH1cbiAgICovXG4gIHRoaXMuZ2V0U2lnbmluZ0tleVBhY2tldCA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIHNpZ25pbmcgPSBbIGVudW1zLnB1YmxpY0tleS5yc2FfZW5jcnlwdF9zaWduLCBlbnVtcy5wdWJsaWNLZXkucnNhX3NpZ24sIGVudW1zLnB1YmxpY0tleS5kc2FdO1xuXG4gICAgc2lnbmluZyA9IHNpZ25pbmcubWFwKGZ1bmN0aW9uKHMpIHtcbiAgICAgIHJldHVybiBlbnVtcy5yZWFkKGVudW1zLnB1YmxpY0tleSwgcyk7XG4gICAgfSk7XG5cbiAgICB2YXIga2V5cyA9IHRoaXMuZ2V0QWxsS2V5UGFja2V0cygpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoc2lnbmluZy5pbmRleE9mKGtleXNbaV0uYWxnb3JpdGhtKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuIGtleXNbaV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwcmVmZXJyZWQgc2lnbmF0dXJlIGhhc2ggYWxnb3JpdGhtIG9mIHRoaXMga2V5XG4gICAqIEByZXR1cm4ge1N0cmluZ31cbiAgICovXG4gIGZ1bmN0aW9uIGdldFByZWZlcnJlZFNpZ25hdHVyZUhhc2hBbGdvcml0aG0oKSB7XG4gICAgLy9UT0RPIGltcGxlbWVudDogaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzQ4ODAjc2VjdGlvbi01LjIuMy44XG4gICAgLy9zZXBhcmF0ZSBwcml2YXRlIGtleSBwcmVmZXJlbmNlIGZyb20gZGlnZXN0IHByZWZlcmVuY2VzXG4gICAgcmV0dXJuIGNvbmZpZy5wcmVmZXJfaGFzaF9hbGdvcml0aG07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgZmlyc3QgdmFsaWQgZW5jcnlwdGlvbiBrZXkgcGFja2V0IGZvciB0aGlzIGtleVxuICAgKiBAcmV0dXJucyB7cHVibGljX3N1YmtleXxzZWNyZXRfc3Via2V5fHBhY2tldF9zZWNyZXRfa2V5fHBhY2tldF9wdWJsaWNfa2V5fG51bGx9IGtleSBwYWNrZXQgb3IgbnVsbCBpZiBubyBlbmNyeXB0aW9uIGtleSBoYXMgYmVlbiBmb3VuZFxuICAgKi9cbiAgdGhpcy5nZXRFbmNyeXB0aW9uS2V5UGFja2V0ID0gZnVuY3Rpb24oKSB7XG4gICAgLy8gVjQ6IGJ5IGNvbnZlbnRpb24gc3Via2V5cyBhcmUgcHJlZmVyZWQgZm9yIGVuY3J5cHRpb24gc2VydmljZVxuICAgIC8vIFYzOiBrZXlzIE1VU1QgTk9UIGhhdmUgc3Via2V5c1xuICAgIHZhciBpc1ZhbGlkRW5jcnlwdGlvbktleSA9IGZ1bmN0aW9uKGtleSkge1xuICAgICAgLy9UT0RPIGV2YWx1YXRlIGtleSBmbGFnczogaHR0cDovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNDg4MCNzZWN0aW9uLTUuMi4zLjIxXG4gICAgICByZXR1cm4ga2V5LmFsZ29yaXRobSAhPSBlbnVtcy5yZWFkKGVudW1zLnB1YmxpY0tleSwgZW51bXMucHVibGljS2V5LmRzYSkgJiYga2V5LmFsZ29yaXRobSAhPSBlbnVtcy5yZWFkKGVudW1zLnB1YmxpY0tleSxcbiAgICAgICAgZW51bXMucHVibGljS2V5LnJzYV9zaWduKTtcbiAgICAgIC8vVE9ETyB2ZXJpZnkga2V5XG4gICAgICAvLyYmIGtleXMudmVyaWZ5S2V5KClcbiAgICB9O1xuXG4gICAgdmFyIHN1YmtleXMgPSB0aGlzLmdldFN1YmtleVBhY2tldHMoKTtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgc3Via2V5cy5sZW5ndGg7IGorKykge1xuICAgICAgaWYgKGlzVmFsaWRFbmNyeXB0aW9uS2V5KHN1YmtleXNbal0pKSB7XG4gICAgICAgIHJldHVybiBzdWJrZXlzW2pdO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBpZiBubyB2YWxpZCBzdWJrZXkgZm9yIGVuY3J5cHRpb24sIHVzZSBwcmltYXJ5IGtleVxuICAgIHZhciBwcmltYXJ5S2V5ID0gdGhpcy5nZXRLZXlQYWNrZXQoKTtcbiAgICBpZiAoaXNWYWxpZEVuY3J5cHRpb25LZXkocHJpbWFyeUtleSkpIHtcbiAgICAgIHJldHVybiBwcmltYXJ5S2V5O1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyBhbGwgc2VjcmV0IGtleSBhbmQgc3Via2V5IHBhY2tldHNcbiAgICogQHBhcmFtICB7U3RyaW5nfSBwYXNzcGhyYXNlIFxuICAgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIGFsbCBrZXkgYW5kIHN1YmtleSBwYWNrZXRzIGRlY3J5cHRlZCBzdWNjZXNzZnVsbHlcbiAgICovXG4gIHRoaXMuZGVjcnlwdCA9IGZ1bmN0aW9uKHBhc3NwaHJhc2UpIHtcbiAgICB2YXIga2V5cyA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQuc2VjcmV0X2tleSwgZW51bXMucGFja2V0LnNlY3JldF9zdWJrZXkpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHN1Y2Nlc3MgPSBrZXlzW2ldLmRlY3J5cHQocGFzc3BocmFzZSk7XG4gICAgICBpZiAoIXN1Y2Nlc3MpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogRGVjcnlwdHMgc3BlY2lmaWMga2V5IHBhY2tldHMgYnkga2V5IElEXG4gICAqIEBwYXJhbSAge1trZXlpZF19IGtleUlkc1xuICAgKiBAcGFyYW0gIHtTdHJpbmd9IHBhc3NwaHJhc2UgXG4gICAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgYWxsIGtleSBwYWNrZXRzIGRlY3J5cHRlZCBzdWNjZXNzZnVsbHlcbiAgICovXG4gIHRoaXMuZGVjcnlwdEtleVBhY2tldCA9IGZ1bmN0aW9uKGtleUlkcywgcGFzc3BocmFzZSkge1xuICAgIC8vVE9ETyByZXR1cm4gdmFsdWVcbiAgICB2YXIga2V5cyA9IHRoaXMucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQuc2VjcmV0X2tleSwgZW51bXMucGFja2V0LnNlY3JldF9zdWJrZXkpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGtleUlkID0ga2V5c1tpXS5nZXRLZXlJZCgpOyBcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwga2V5SWRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChrZXlJZC5lcXVhbHMoa2V5SWRzW2pdKSkge1xuICAgICAgICAgIHZhciBzdWNjZXNzID0ga2V5c1tpXS5kZWNyeXB0KHBhc3NwaHJhc2UpO1xuICAgICAgICAgIGlmICghc3VjY2VzcykgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLy8gVE9ET1xuICB0aGlzLnZlcmlmeSA9IGZ1bmN0aW9uKCkge1xuXG4gIH1cbiAgLy8gVE9ET1xuICB0aGlzLnJldm9rZSA9IGZ1bmN0aW9uKCkge1xuXG4gIH1cblxufVxuXG4vKipcbiAqIHJlYWRzIGFuIE9wZW5QR1AgYXJtb3JlZCB0ZXh0IGFuZCByZXR1cm5zIGEga2V5IG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IGFybW9yZWRUZXh0IHRleHQgdG8gYmUgcGFyc2VkXG4gKiBAcmV0dXJuIHtrZXl9IG5ldyBrZXkgb2JqZWN0XG4gKi9cbmtleS5yZWFkQXJtb3JlZCA9IGZ1bmN0aW9uKGFybW9yZWRUZXh0KSB7XG4gIC8vVE9ETyBob3cgZG8gd2Ugd2FudCB0byBoYW5kbGUgYmFkIHRleHQ/IEV4Y2VwdGlvbiB0aHJvd2luZ1xuICAvL1RPRE8gZG9uJ3QgYWNjZXB0IG5vbi1rZXkgYXJtb3JlZCB0ZXh0c1xuICB2YXIgaW5wdXQgPSBhcm1vci5kZWNvZGUoYXJtb3JlZFRleHQpLmRhdGE7XG4gIHZhciBwYWNrZXRsaXN0ID0gbmV3IHBhY2tldC5saXN0KCk7XG4gIHBhY2tldGxpc3QucmVhZChpbnB1dCk7XG4gIHZhciBuZXdLZXkgPSBuZXcga2V5KHBhY2tldGxpc3QpO1xuICByZXR1cm4gbmV3S2V5O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGtleTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBwYWNrZXQgPSByZXF1aXJlKCcuL3BhY2tldCcpO1xudmFyIGVudW1zID0gcmVxdWlyZSgnLi9lbnVtcy5qcycpO1xudmFyIGFybW9yID0gcmVxdWlyZSgnLi9lbmNvZGluZy9hcm1vci5qcycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBUaGUgY2xhc3MgdGhhdCBkZWFscyB3aXRoIHN0b3JhZ2Ugb2YgdGhlIGtleXJpbmcuIEN1cnJlbnRseSB0aGUgb25seSBvcHRpb24gaXMgdG8gdXNlIEhUTUw1IGxvY2FsIHN0b3JhZ2UuXG4gKi9cbnZhciBrZXlyaW5nID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuYXJtb3JlZFBhY2tldGxpc3RzID0gW107XG4gIHRoaXMucGFyc2VkUGFja2V0bGlzdHMgPSBbXTtcblxuICAvKipcbiAgICogSW5pdGlhbGl6YXRpb24gcm91dGluZSBmb3IgdGhlIGtleXJpbmcuIFRoaXMgbWV0aG9kIHJlYWRzIHRoZSBcbiAgICoga2V5cmluZyBmcm9tIEhUTUw1IGxvY2FsIHN0b3JhZ2UgYW5kIGluaXRpYWxpemVzIHRoaXMgaW5zdGFuY2UuXG4gICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBieSBvcGVucGdwLmluaXQoKS5cbiAgICovXG4gIGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgdmFyIGFybW9yZWRQYWNrZXRsaXN0cyA9IEpTT04ucGFyc2Uod2luZG93LmxvY2FsU3RvcmFnZS5nZXRJdGVtKFwiYXJtb3JlZFBhY2tldGxpc3RzXCIpKTtcbiAgICBpZiAoYXJtb3JlZFBhY2tldGxpc3RzID09PSBudWxsIHx8IGFybW9yZWRQYWNrZXRsaXN0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGFybW9yZWRQYWNrZXRsaXN0cyA9IFtdO1xuICAgIH1cbiAgICB0aGlzLmFybW9yZWRQYWNrZXRsaXN0cyA9IGFybW9yZWRQYWNrZXRsaXN0cztcblxuICAgIHZhciBwYWNrZXRsaXN0O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJtb3JlZFBhY2tldGxpc3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBwYWNrZXRsaXN0ID0gbmV3IHBhY2tldC5saXN0KCk7XG4gICAgICBwYWNrZXRsaXN0LnJlYWQoYXJtb3JlZFBhY2tldGxpc3RzW2ldKTtcbiAgICAgIHRoaXMucGFyc2VkUGFja2V0bGlzdHMucHVzaChwYWNrZXRsaXN0KTtcbiAgICB9XG4gIH1cbiAgdGhpcy5pbml0ID0gaW5pdDtcblxuICAvKipcbiAgICogU2F2ZXMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGtleXJpbmcgdG8gSFRNTDUgbG9jYWwgc3RvcmFnZS5cbiAgICogVGhlIHByaXZhdGVLZXlzIGFycmF5IGFuZCBwdWJsaWNLZXlzIGFycmF5IGdldHMgU3RyaW5naWZpZWQgdXNpbmcgSlNPTlxuICAgKi9cbiAgZnVuY3Rpb24gc3RvcmUoKSB7XG4gICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKFwiYXJtb3JlZFBhY2tldGxpc3RzXCIsIEpTT04uc3RyaW5naWZ5KHRoaXMuYXJtb3JlZFBhY2tldGxpc3RzKSk7XG4gIH1cbiAgdGhpcy5zdG9yZSA9IHN0b3JlO1xuXG4gIGZ1bmN0aW9uIGVtYWlsUGFja2V0Q2hlY2socGFja2V0LCBlbWFpbCkge1xuICAgIHZhciBlbWFpbE1hdGNoID0gZmFsc2U7XG4gICAgdmFyIHBhY2tldEVtYWlsO1xuICAgIGVtYWlsID0gZW1haWwudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAocGFja2V0LnRhZyA9PSBlbnVtcy5wYWNrZXQudXNlcmlkKSB7XG4gICAgICBwYWNrZXRFbWFpbCA9IHBhY2tldC51c2VyaWQ7XG4gICAgICAvL3dlIG5lZWQgdG8gZ2V0IGp1c3QgdGhlIGVtYWlsIGZyb20gdGhlIHVzZXJpZCBwYWNrZXRcbiAgICAgIHBhY2tldEVtYWlsID0gcGFja2V0RW1haWwuc3BsaXQoJzwnKVsxXS5zcGxpdCgnPCcpWzBdLnRyaW0udG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChwYWNrZXRFbWFpbCA9PSBlbWFpbCkge1xuICAgICAgICBlbWFpbE1hdGNoID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGVtYWlsTWF0Y2g7XG4gIH1cblxuICBmdW5jdGlvbiBpZFBhY2tldENoZWNrKHBhY2tldCwgaWQpIHtcbiAgICBpZiAocGFja2V0LmdldEtleUlkICYmIHBhY2tldC5nZXRLZXlJZCgpLndyaXRlKCkgPT0gaWQpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBmdW5jdGlvbiBoZWxwZXJDaGVja0lkZW50aXR5QW5kUGFja2V0TWF0Y2goaWRlbnRpdHlGdW5jdGlvbiwgaWRlbnRpdHlJbnB1dCwgcGFja2V0VHlwZSwgcGFja2V0bGlzdCkge1xuICAgIHZhciBwYWNrZXQ7XG4gICAgZm9yICh2YXIgbCA9IDA7IGwgPCBwYWNrZXRsaXN0Lmxlbmd0aDsgbCsrKSB7XG4gICAgICBwYWNrZXQgPSBwYWNrZXRsaXN0W2xdO1xuICAgICAgaWRlbnRpdHlNYXRjaCA9IGlkZW50aXR5RnVuY3Rpb24ocGFja2V0LCBpZGVudGl0eUlucHV0KTtcbiAgICAgIGlmICghcGFja2V0VHlwZSkge1xuICAgICAgICBwYWNrZXRNYXRjaCA9IHRydWU7XG4gICAgICB9IGVsc2UgaWYgKHBhY2tldC50YWcgPT0gcGFja2V0VHlwZSkge1xuICAgICAgICBwYWNrZXRNYXRjaCA9IHRydWU7XG4gICAgICB9XG4gICAgICBpZiAocGFja2V0TWF0Y2ggJiYgaWRlbnRpdHlNYXRjaCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgZnVuY3Rpb24gY2hlY2tGb3JJZGVudGl0eUFuZFBhY2tldE1hdGNoKGlkZW50aXR5RnVuY3Rpb24sIGlkZW50aXR5SW5wdXQsIHBhY2tldFR5cGUpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIHZhciBwYWNrZXRsaXN0O1xuICAgIHZhciBpZGVudGl0eU1hdGNoO1xuICAgIHZhciBwYWNrZXRNYXRjaDtcbiAgICBmb3IgKHZhciBwID0gMDsgcCA8IHRoaXMucGFyc2VkUGFja2V0bGlzdHMubGVuZ3RoOyBwKyspIHtcbiAgICAgIGlkZW50aXR5TWF0Y2ggPSBmYWxzZTtcbiAgICAgIHBhY2tldE1hdGNoID0gZmFsc2U7XG4gICAgICBwYWNrZXRsaXN0ID0gdGhpcy5wYXJzZWRQYWNrZXRsaXN0c1twXTtcbiAgICAgIGlmIChoZWxwZXJDaGVja0lkZW50aXR5QW5kUGFja2V0TWF0Y2goaWRlbnRpdHlGdW5jdGlvbiwgaWRlbnRpdHlJbnB1dCwgcGFja2V0VHlwZSwgcGFja2V0bGlzdCkpIHtcbiAgICAgICAgcmVzdWx0cy5wdXNoKHBhY2tldGxpc3QpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuICB0aGlzLmNoZWNrRm9ySWRlbnRpdHlBbmRQYWNrZXRNYXRjaCA9IGNoZWNrRm9ySWRlbnRpdHlBbmRQYWNrZXRNYXRjaDtcblxuICAvKipcbiAgICogc2VhcmNoZXMgYWxsIHB1YmxpYyBrZXlzIGluIHRoZSBrZXlyaW5nIG1hdGNoaW5nIHRoZSBhZGRyZXNzIG9yIGFkZHJlc3MgcGFydCBvZiB0aGUgdXNlciBpZHNcbiAgICogQHBhcmFtIHtTdHJpbmd9IGVtYWlsX2FkZHJlc3NcbiAgICogQHJldHVybiB7b3BlbnBncF9tc2dfcHVibGlja2V5W119IFRoZSBwdWJsaWMga2V5cyBhc3NvY2lhdGVkIHdpdGggcHJvdmlkZWQgZW1haWwgYWRkcmVzcy5cbiAgICovXG4gIGZ1bmN0aW9uIGdldFB1YmxpY0tleUZvckFkZHJlc3MoZW1haWwpIHtcbiAgICByZXR1cm4gY2hlY2tGb3JJZGVudGl0eUFuZFBhY2tldE1hdGNoKGVtYWlsUGFja2V0Q2hlY2ssIGVtYWlsLCBlbnVtcy5wYWNrZXQucHVibGljX2tleSk7XG4gIH1cbiAgdGhpcy5nZXRQdWJsaWNLZXlGb3JBZGRyZXNzID0gZ2V0UHVibGljS2V5Rm9yQWRkcmVzcztcblxuICAvKipcbiAgICogU2VhcmNoZXMgdGhlIGtleXJpbmcgZm9yIGEgcHJpdmF0ZSBrZXkgY29udGFpbmluZyB0aGUgc3BlY2lmaWVkIGVtYWlsIGFkZHJlc3NcbiAgICogQHBhcmFtIHtTdHJpbmd9IGVtYWlsX2FkZHJlc3MgZW1haWwgYWRkcmVzcyB0byBzZWFyY2ggZm9yXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXlbXX0gcHJpdmF0ZSBrZXlzIGZvdW5kXG4gICAqL1xuICBmdW5jdGlvbiBnZXRQcml2YXRlS2V5Rm9yQWRkcmVzcyhlbWFpbF9hZGRyZXNzKSB7XG4gICAgcmV0dXJuIGNoZWNrRm9ySWRlbnRpdHlBbmRQYWNrZXRNYXRjaChlbWFpbFBhY2tldENoZWNrLCBlbWFpbCwgZW51bXMucGFja2V0LnNlY3JldF9rZXkpO1xuICB9XG4gIHRoaXMuZ2V0UHJpdmF0ZUtleUZvckFkZHJlc3MgPSBnZXRQcml2YXRlS2V5Rm9yQWRkcmVzcztcblxuICAvKipcbiAgICogU2VhcmNoZXMgdGhlIGtleXJpbmcgZm9yIHB1YmxpYyBrZXlzIGhhdmluZyB0aGUgc3BlY2lmaWVkIGtleSBpZFxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5SWQgcHJvdmlkZWQgYXMgc3RyaW5nIG9mIGhleCBudW1iZXIgKGxvd2VyY2FzZSlcbiAgICogQHJldHVybiB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleVtdfSBwdWJsaWMga2V5cyBmb3VuZFxuICAgKi9cbiAgZnVuY3Rpb24gZ2V0UGFja2V0bGlzdHNGb3JLZXlJZChrZXlJZCkge1xuICAgIHJldHVybiB0aGlzLmNoZWNrRm9ySWRlbnRpdHlBbmRQYWNrZXRNYXRjaChpZFBhY2tldENoZWNrLCBrZXlJZCk7XG4gIH1cbiAgdGhpcy5nZXRQYWNrZXRsaXN0c0ZvcktleUlkID0gZ2V0UGFja2V0bGlzdHNGb3JLZXlJZDtcblxuICAvKipcbiAgICogSW1wb3J0cyBhIHBhY2tldCBsaXN0IChwdWJsaWMgb3IgcHJpdmF0ZSBrZXkgYmxvY2spIGZyb20gYW4gYXNjaWkgYXJtb3JlZCBtZXNzYWdlIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gYXJtb3JlZCBtZXNzYWdlIHRvIHJlYWQgdGhlIHBhY2tldHMva2V5IGZyb21cbiAgICovXG4gIGZ1bmN0aW9uIGltcG9ydFBhY2tldGxpc3QoYXJtb3JlZCkge1xuICAgIHRoaXMuYXJtb3JlZFBhY2tldGxpc3RzLnB1c2goYXJtb3JlZCk7XG5cbiAgICB2YXIgZGVhcm1vcmVkID0gYXJtb3IuZGVjb2RlKGFybW9yZWQucmVwbGFjZSgvXFxyL2csICcnKSkuZGF0YTtcblxuICAgIHBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcbiAgICBwYWNrZXRsaXN0LnJlYWQoZGVhcm1vcmVkKTtcbiAgICB0aGlzLnBhcnNlZFBhY2tldGxpc3RzLnB1c2gocGFja2V0bGlzdCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICB0aGlzLmltcG9ydFBhY2tldGxpc3QgPSBpbXBvcnRQYWNrZXRsaXN0O1xuXG4gIC8qKlxuICAgKiBUT0RPXG4gICAqIHJldHVybnMgdGhlIG9wZW5wZ3BfbXNnX3ByaXZhdGVrZXkgcmVwcmVzZW50YXRpb24gb2YgdGhlIHB1YmxpYyBrZXkgYXQgcHVibGljIGtleSByaW5nIGluZGV4ICBcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpbmRleCB0aGUgaW5kZXggb2YgdGhlIHB1YmxpYyBrZXkgd2l0aGluIHRoZSBwdWJsaWNLZXlzIGFycmF5XG4gICAqIEByZXR1cm4ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXl9IHRoZSBwdWJsaWMga2V5IG9iamVjdFxuICAgKi9cbiAgZnVuY3Rpb24gZXhwb3J0UHVibGljS2V5KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMucHVibGljS2V5W2luZGV4XTtcbiAgfVxuICB0aGlzLmV4cG9ydFB1YmxpY0tleSA9IGV4cG9ydFB1YmxpY0tleTtcblxuICAvKipcbiAgICogVE9ET1xuICAgKiBSZW1vdmVzIGEgcHVibGljIGtleSBmcm9tIHRoZSBwdWJsaWMga2V5IGtleXJpbmcgYXQgdGhlIHNwZWNpZmllZCBpbmRleCBcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBpbmRleCB0aGUgaW5kZXggb2YgdGhlIHB1YmxpYyBrZXkgd2l0aGluIHRoZSBwdWJsaWNLZXlzIGFycmF5XG4gICAqIEByZXR1cm4ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXl9IFRoZSBwdWJsaWMga2V5IG9iamVjdCB3aGljaCBoYXMgYmVlbiByZW1vdmVkXG4gICAqL1xuICBmdW5jdGlvbiByZW1vdmVQdWJsaWNLZXkoaW5kZXgpIHtcbiAgICB2YXIgcmVtb3ZlZCA9IHRoaXMucHVibGljS2V5cy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIHRoaXMuc3RvcmUoKTtcbiAgICByZXR1cm4gcmVtb3ZlZDtcbiAgfVxuICB0aGlzLnJlbW92ZVB1YmxpY0tleSA9IHJlbW92ZVB1YmxpY0tleTtcblxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBuZXcga2V5cmluZygpO1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHBhY2tldCA9IHJlcXVpcmUoJy4vcGFja2V0Jyk7XG52YXIgZW51bXMgPSByZXF1aXJlKCcuL2VudW1zLmpzJyk7XG52YXIgYXJtb3IgPSByZXF1aXJlKCcuL2VuY29kaW5nL2FybW9yLmpzJyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi9jb25maWcnKTtcbnZhciBjcnlwdG8gPSByZXF1aXJlKCcuL2NyeXB0bycpO1xudmFyIHV0aWwgPSByZXF1aXJlKCcuL3V0aWwnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgQSBnZW5lcmljIG1lc3NhZ2UgY29udGFpbmluZyBvbmUgb3IgbW9yZSBsaXRlcmFsIHBhY2tldHMuXG4gKi9cblxuZnVuY3Rpb24gbWVzc2FnZShwYWNrZXRsaXN0KSB7XG5cbiAgdGhpcy5wYWNrZXRzID0gcGFja2V0bGlzdCB8fCBuZXcgcGFja2V0Lmxpc3QoKTtcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUga2V5IElEcyBvZiB0aGUga2V5cyB0byB3aGljaCB0aGUgc2Vzc2lvbiBrZXkgaXMgZW5jcnlwdGVkXG4gICAqIEByZXR1cm4ge1trZXlJZF19IGFycmF5IG9mIGtleWlkIG9iamVjdHNcbiAgICovXG4gIHRoaXMuZ2V0RW5jcnlwdGlvbktleUlkcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBrZXlJZHMgPSBbXTtcbiAgICB2YXIgcGtFU0tleVBhY2tldGxpc3QgPSB0aGlzLnBhY2tldHMuZmlsdGVyQnlUYWcoZW51bXMucGFja2V0LnB1YmxpY19rZXlfZW5jcnlwdGVkX3Nlc3Npb25fa2V5KTtcbiAgICBwa0VTS2V5UGFja2V0bGlzdC5mb3JFYWNoKGZ1bmN0aW9uKHBhY2tldCkge1xuICAgICAga2V5SWRzLnB1c2gocGFja2V0LnB1YmxpY0tleUlkKTtcbiAgICB9KTtcbiAgICByZXR1cm4ga2V5SWRzO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGtleSBJRHMgb2YgdGhlIGtleXMgdGhhdCBzaWduZWQgdGhlIG1lc3NhZ2VcbiAgICogQHJldHVybiB7W2tleUlkXX0gYXJyYXkgb2Yga2V5aWQgb2JqZWN0c1xuICAgKi9cbiAgdGhpcy5nZXRTaWduaW5nS2V5SWRzID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGtleUlkcyA9IFtdO1xuICAgIHZhciBtc2cgPSB0aGlzLnVud3JhcENvbXByZXNzZWQoKTtcbiAgICAvLyBzZWFyY2ggZm9yIG9uZSBwYXNzIHNpZ25hdHVyZXNcbiAgICB2YXIgb25lUGFzc1NpZ0xpc3QgPSBtc2cucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQub25lX3Bhc3Nfc2lnbmF0dXJlKTtcbiAgICBvbmVQYXNzU2lnTGlzdC5mb3JFYWNoKGZ1bmN0aW9uKHBhY2tldCkge1xuICAgICAga2V5SWRzLnB1c2gocGFja2V0LnNpZ25pbmdLZXlJZCk7XG4gICAgfSk7XG4gICAgLy8gaWYgbm90aGluZyBmb3VuZCBsb29rIGZvciBzaWduYXR1cmUgcGFja2V0c1xuICAgIGlmICgha2V5SWRzLmxlbmd0aCkge1xuICAgICAgdmFyIHNpZ25hdHVyZUxpc3QgPSBtc2cucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQuc2lnbmF0dXJlKTtcbiAgICAgIHNpZ25hdHVyZUxpc3QuZm9yRWFjaChmdW5jdGlvbihwYWNrZXQpIHtcbiAgICAgICAga2V5SWRzLnB1c2gocGFja2V0Lmlzc3VlcktleUlkKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4ga2V5SWRzO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtrZXl9IHByaXZhdGVLZXkgcHJpdmF0ZSBrZXkgd2l0aCBkZWNyeXB0ZWQgc2VjcmV0IGRhdGEgICAgICAgICAgIFxuICAgKiBAcmV0dXJuIHtbbWVzc2FnZV19IG5ldyBtZXNzYWdlIHdpdGggZGVjcnlwdGVkIGNvbnRlbnRcbiAgICovXG4gIHRoaXMuZGVjcnlwdCA9IGZ1bmN0aW9uKHByaXZhdGVLZXkpIHtcbiAgICB2YXIgZW5jcnlwdGlvbktleUlkcyA9IHRoaXMuZ2V0RW5jcnlwdGlvbktleUlkcygpO1xuICAgIGlmICghZW5jcnlwdGlvbktleUlkcy5sZW5ndGgpIHtcbiAgICAgIC8vIG5vdGhpbmcgdG8gZGVjcnlwdCByZXR1cm4gdW5tb2RpZmllZCBtZXNzYWdlXG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgdmFyIHByaXZhdGVLZXlQYWNrZXQgPSBwcml2YXRlS2V5LmdldFByaXZhdGVLZXlQYWNrZXQoZW5jcnlwdGlvbktleUlkcyk7XG4gICAgaWYgKCFwcml2YXRlS2V5UGFja2V0LmlzRGVjcnlwdGVkKSB0aHJvdyBuZXcgRXJyb3IoJ1ByaXZhdGUga2V5IGlzIG5vdCBkZWNyeXB0ZWQuJyk7XG4gICAgdmFyIHBrRVNLZXlQYWNrZXRsaXN0ID0gdGhpcy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5wdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleSk7XG4gICAgdmFyIHBrRVNLZXlQYWNrZXQ7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwa0VTS2V5UGFja2V0bGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHBrRVNLZXlQYWNrZXRsaXN0W2ldLnB1YmxpY0tleUlkLmVxdWFscyhwcml2YXRlS2V5UGFja2V0LmdldEtleUlkKCkpKSB7XG4gICAgICAgIHBrRVNLZXlQYWNrZXQgPSBwa0VTS2V5UGFja2V0bGlzdFtpXTtcbiAgICAgICAgcGtFU0tleVBhY2tldC5kZWNyeXB0KHByaXZhdGVLZXlQYWNrZXQpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHBrRVNLZXlQYWNrZXQpIHtcbiAgICAgIHZhciBzeW1FbmNyeXB0ZWRQYWNrZXRsaXN0ID0gdGhpcy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5zeW1tZXRyaWNhbGx5X2VuY3J5cHRlZCwgZW51bXMucGFja2V0LnN5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZCk7XG4gICAgICBpZiAoc3ltRW5jcnlwdGVkUGFja2V0bGlzdC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgdmFyIHN5bUVuY3J5cHRlZFBhY2tldCA9IHN5bUVuY3J5cHRlZFBhY2tldGxpc3RbMF07XG4gICAgICAgIHN5bUVuY3J5cHRlZFBhY2tldC5kZWNyeXB0KHBrRVNLZXlQYWNrZXQuc2Vzc2lvbktleUFsZ29yaXRobSwgcGtFU0tleVBhY2tldC5zZXNzaW9uS2V5KTtcbiAgICAgICAgcmV0dXJuIG5ldyBtZXNzYWdlKHN5bUVuY3J5cHRlZFBhY2tldC5wYWNrZXRzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IGxpdGVyYWwgZGF0YSB0aGF0IGlzIHRoZSBib2R5IG9mIHRoZSBtZXNzYWdlXG4gICAqIEByZXR1cm4ge1N0cmluZ3xudWxsfSBsaXRlcmFsIGJvZHkgb2YgdGhlIG1lc3NhZ2UgYXMgc3RyaW5nXG4gICAqL1xuICB0aGlzLmdldExpdGVyYWxEYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGxpdGVyYWwgPSB0aGlzLnBhY2tldHMuZmluZFBhY2tldChlbnVtcy5wYWNrZXQubGl0ZXJhbCk7XG4gICAgcmV0dXJuIGxpdGVyYWwgJiYgbGl0ZXJhbC5kYXRhIHx8IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGxpdGVyYWwgZGF0YSBhcyB0ZXh0XG4gICAqIEByZXR1cm4ge1N0cmluZ3xudWxsfSBsaXRlcmFsIGJvZHkgb2YgdGhlIG1lc3NhZ2UgaW50ZXJwcmV0ZWQgYXMgdGV4dFxuICAgKi9cbiAgdGhpcy5nZXRUZXh0ID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGxpdGVyYWwgPSB0aGlzLnBhY2tldHMuZmluZFBhY2tldChlbnVtcy5wYWNrZXQubGl0ZXJhbCk7XG4gICAgaWYgKGxpdGVyYWwpIHtcbiAgICAgIHZhciBkYXRhID0gbGl0ZXJhbC5kYXRhO1xuICAgICAgaWYgKGxpdGVyYWwuZm9ybWF0ID09IGVudW1zLnJlYWQoZW51bXMubGl0ZXJhbCwgZW51bXMubGl0ZXJhbC5iaW5hcnkpXG4gICAgICAgIHx8IGxpdGVyYWwuZm9ybWF0ID09IGVudW1zLnJlYWQoZW51bXMubGl0ZXJhbCwgZW51bXMubGl0ZXJhbC50ZXh0KSkge1xuICAgICAgICAvLyB0ZXh0IGluIGEgbGl0ZXJhbCBwYWNrZXQgd2l0aCBmb3JtYXQgJ2JpbmFyeScgb3IgJ3RleHQnIGNvdWxkIGJlIHV0ZjgsIHRoZXJlZm9yZSBkZWNvZGVcbiAgICAgICAgZGF0YSA9IHV0aWwuZGVjb2RlX3V0ZjgoZGF0YSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVuY3J5cHQgdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtICB7W2tleV19IGtleXMgYXJyYXkgb2Yga2V5cywgdXNlZCB0byBlbmNyeXB0IHRoZSBtZXNzYWdlXG4gICAqIEByZXR1cm4ge1ttZXNzYWdlXX0gbmV3IG1lc3NhZ2Ugd2l0aCBlbmNyeXB0ZWQgY29udGVudFxuICAgKi9cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oa2V5cykge1xuICAgIHZhciBwYWNrZXRsaXN0ID0gbmV3IHBhY2tldC5saXN0KCk7XG4gICAgLy9UT0RPIGdldCBwcmVmZXJyZWQgYWxnbyBmcm9tIHNpZ25hdHVyZVxuICAgIHZhciBzZXNzaW9uS2V5ID0gY3J5cHRvLmdlbmVyYXRlU2Vzc2lvbktleShlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyKSk7XG4gICAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgICAgdmFyIGVuY3J5cHRpb25LZXlQYWNrZXQgPSBrZXkuZ2V0RW5jcnlwdGlvbktleVBhY2tldCgpO1xuICAgICAgaWYgKGVuY3J5cHRpb25LZXlQYWNrZXQpIHtcbiAgICAgICAgdmFyIHBrRVNLZXlQYWNrZXQgPSBuZXcgcGFja2V0LnB1YmxpY19rZXlfZW5jcnlwdGVkX3Nlc3Npb25fa2V5KCk7XG4gICAgICAgIHBrRVNLZXlQYWNrZXQucHVibGljS2V5SWQgPSBlbmNyeXB0aW9uS2V5UGFja2V0LmdldEtleUlkKCk7XG4gICAgICAgIHBrRVNLZXlQYWNrZXQucHVibGljS2V5QWxnb3JpdGhtID0gZW5jcnlwdGlvbktleVBhY2tldC5hbGdvcml0aG07XG4gICAgICAgIHBrRVNLZXlQYWNrZXQuc2Vzc2lvbktleSA9IHNlc3Npb25LZXk7XG4gICAgICAgIC8vVE9ETyBnZXQgcHJlZmVycmVkIGFsZ28gZnJvbSBzaWduYXR1cmVcbiAgICAgICAgcGtFU0tleVBhY2tldC5zZXNzaW9uS2V5QWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsIGNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcik7XG4gICAgICAgIHBrRVNLZXlQYWNrZXQuZW5jcnlwdChlbmNyeXB0aW9uS2V5UGFja2V0KTtcbiAgICAgICAgcGFja2V0bGlzdC5wdXNoKHBrRVNLZXlQYWNrZXQpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHZhciBzeW1FbmNyeXB0ZWRQYWNrZXQ7XG4gICAgaWYgKGNvbmZpZy5pbnRlZ3JpdHlfcHJvdGVjdCkge1xuICAgICAgc3ltRW5jcnlwdGVkUGFja2V0ID0gbmV3IHBhY2tldC5zeW1fZW5jcnlwdGVkX2ludGVncml0eV9wcm90ZWN0ZWQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3ltRW5jcnlwdGVkUGFja2V0ID0gbmV3IHBhY2tldC5zeW1tZXRyaWNhbGx5X2VuY3J5cHRlZCgpO1xuICAgIH1cbiAgICBzeW1FbmNyeXB0ZWRQYWNrZXQucGFja2V0cyA9IHRoaXMucGFja2V0cztcbiAgICAvL1RPRE8gZ2V0IHByZWZlcnJlZCBhbGdvIGZyb20gc2lnbmF0dXJlXG4gICAgc3ltRW5jcnlwdGVkUGFja2V0LmVuY3J5cHQoZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsIGNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlciksIHNlc3Npb25LZXkpO1xuICAgIHBhY2tldGxpc3QucHVzaChzeW1FbmNyeXB0ZWRQYWNrZXQpO1xuICAgIHJldHVybiBuZXcgbWVzc2FnZShwYWNrZXRsaXN0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIHRoZSBtZXNzYWdlICh0aGUgbGl0ZXJhbCBkYXRhIHBhY2tldCBvZiB0aGUgbWVzc2FnZSlcbiAgICogQHBhcmFtICB7W2tleV19IHByaXZhdGVLZXkgcHJpdmF0ZSBrZXlzIHdpdGggZGVjcnlwdGVkIHNlY3JldCBrZXkgZGF0YSBmb3Igc2lnbmluZ1xuICAgKiBAcmV0dXJuIHttZXNzYWdlfSAgICAgIG5ldyBtZXNzYWdlIHdpdGggc2lnbmVkIGNvbnRlbnRcbiAgICovXG4gIHRoaXMuc2lnbiA9IGZ1bmN0aW9uKHByaXZhdGVLZXlzKSB7XG5cbiAgICB2YXIgcGFja2V0bGlzdCA9IG5ldyBwYWNrZXQubGlzdCgpO1xuXG4gICAgdmFyIGxpdGVyYWxEYXRhUGFja2V0ID0gdGhpcy5wYWNrZXRzLmZpbmRQYWNrZXQoZW51bXMucGFja2V0LmxpdGVyYWwpO1xuICAgIGlmICghbGl0ZXJhbERhdGFQYWNrZXQpIHRocm93IG5ldyBFcnJvcignTm8gbGl0ZXJhbCBkYXRhIHBhY2tldCB0byBzaWduLicpO1xuICAgIFxuICAgIHZhciBsaXRlcmFsRm9ybWF0ID0gZW51bXMud3JpdGUoZW51bXMubGl0ZXJhbCwgbGl0ZXJhbERhdGFQYWNrZXQuZm9ybWF0KTtcbiAgICB2YXIgc2lnbmF0dXJlVHlwZSA9IGxpdGVyYWxGb3JtYXQgPT0gZW51bXMubGl0ZXJhbC5iaW5hcnkgXG4gICAgICAgICAgICAgICAgICAgICAgICA/IGVudW1zLnNpZ25hdHVyZS5iaW5hcnkgOiBlbnVtcy5zaWduYXR1cmUudGV4dDsgXG4gICAgXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwcml2YXRlS2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIG9uZVBhc3NTaWcgPSBuZXcgcGFja2V0Lm9uZV9wYXNzX3NpZ25hdHVyZSgpO1xuICAgICAgb25lUGFzc1NpZy50eXBlID0gc2lnbmF0dXJlVHlwZTtcbiAgICAgIC8vVE9ETyBnZXQgcHJlZmVycmVkIGhhc2hnIGFsZ28gZnJvbSBrZXkgc2lnbmF0dXJlXG4gICAgICBvbmVQYXNzU2lnLmhhc2hBbGdvcml0aG0gPSBjb25maWcucHJlZmVyX2hhc2hfYWxnb3JpdGhtO1xuICAgICAgdmFyIHNpZ25pbmdLZXlQYWNrZXQgPSBwcml2YXRlS2V5c1tpXS5nZXRTaWduaW5nS2V5UGFja2V0KCk7XG4gICAgICBvbmVQYXNzU2lnLnB1YmxpY0tleUFsZ29yaXRobSA9IHNpZ25pbmdLZXlQYWNrZXQuYWxnb3JpdGhtO1xuICAgICAgb25lUGFzc1NpZy5zaWduaW5nS2V5SWQgPSBzaWduaW5nS2V5UGFja2V0LmdldEtleUlkKCk7XG4gICAgICBwYWNrZXRsaXN0LnB1c2gob25lUGFzc1NpZyk7XG4gICAgfVxuXG4gICAgcGFja2V0bGlzdC5wdXNoKGxpdGVyYWxEYXRhUGFja2V0KTtcbiAgICBcbiAgICBmb3IgKHZhciBpID0gcHJpdmF0ZUtleXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciBzaWduYXR1cmVQYWNrZXQgPSBuZXcgcGFja2V0LnNpZ25hdHVyZSgpO1xuICAgICAgc2lnbmF0dXJlUGFja2V0LnNpZ25hdHVyZVR5cGUgPSBzaWduYXR1cmVUeXBlO1xuICAgICAgc2lnbmF0dXJlUGFja2V0Lmhhc2hBbGdvcml0aG0gPSBjb25maWcucHJlZmVyX2hhc2hfYWxnb3JpdGhtO1xuICAgICAgc2lnbmF0dXJlUGFja2V0LnB1YmxpY0tleUFsZ29yaXRobSA9IHNpZ25pbmdLZXlQYWNrZXQuYWxnb3JpdGhtO1xuICAgICAgaWYgKCFzaWduaW5nS2V5UGFja2V0LmlzRGVjcnlwdGVkKSB0aHJvdyBuZXcgRXJyb3IoJ1ByaXZhdGUga2V5IGlzIG5vdCBkZWNyeXB0ZWQuJyk7XG4gICAgICBzaWduYXR1cmVQYWNrZXQuc2lnbihzaWduaW5nS2V5UGFja2V0LCBsaXRlcmFsRGF0YVBhY2tldCk7XG4gICAgICBwYWNrZXRsaXN0LnB1c2goc2lnbmF0dXJlUGFja2V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IG1lc3NhZ2UocGFja2V0bGlzdCk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZ5IG1lc3NhZ2Ugc2lnbmF0dXJlc1xuICAgKiBAcGFyYW0ge1trZXldfSBwdWJsaWNLZXlzIHB1YmxpYyBrZXlzIHRvIHZlcmlmeSBzaWduYXR1cmVzXG4gICAqIEByZXR1cm4ge1t7J2tleWlkJzoga2V5aWQsICd2YWxpZCc6IEJvb2xlYW59XX0gbGlzdCBvZiBzaWduZXIncyBrZXlpZCBhbmQgdmFsaWRpdHkgb2Ygc2lnbmF0dXJlXG4gICAqL1xuICB0aGlzLnZlcmlmeSA9IGZ1bmN0aW9uKHB1YmxpY0tleXMpIHtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgdmFyIG1zZyA9IHRoaXMudW53cmFwQ29tcHJlc3NlZCgpO1xuICAgIHZhciBsaXRlcmFsRGF0YUxpc3QgPSBtc2cucGFja2V0cy5maWx0ZXJCeVRhZyhlbnVtcy5wYWNrZXQubGl0ZXJhbCk7XG4gICAgaWYgKGxpdGVyYWxEYXRhTGlzdC5sZW5ndGggIT09IDEpIHRocm93IG5ldyBFcnJvcignQ2FuIG9ubHkgdmVyaWZ5IG1lc3NhZ2Ugd2l0aCBvbmUgbGl0ZXJhbCBkYXRhIHBhY2tldC4nKTtcbiAgICB2YXIgc2lnbmF0dXJlTGlzdCA9IG1zZy5wYWNrZXRzLmZpbHRlckJ5VGFnKGVudW1zLnBhY2tldC5zaWduYXR1cmUpO1xuICAgIHB1YmxpY0tleXMuZm9yRWFjaChmdW5jdGlvbihwdWJLZXkpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2lnbmF0dXJlTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcHVibGljS2V5UGFja2V0ID0gcHViS2V5LmdldFB1YmxpY0tleVBhY2tldChbc2lnbmF0dXJlTGlzdFtpXS5pc3N1ZXJLZXlJZF0pO1xuICAgICAgICBpZiAocHVibGljS2V5UGFja2V0KSB7XG4gICAgICAgICAgdmFyIHZlcmlmaWVkU2lnID0ge307XG4gICAgICAgICAgdmVyaWZpZWRTaWcua2V5aWQgPSBzaWduYXR1cmVMaXN0W2ldLmlzc3VlcktleUlkO1xuICAgICAgICAgIHZlcmlmaWVkU2lnLnN0YXR1cyA9IHNpZ25hdHVyZUxpc3RbaV0udmVyaWZ5KHB1YmxpY0tleVBhY2tldCwgbGl0ZXJhbERhdGFMaXN0WzBdKTtcbiAgICAgICAgICByZXN1bHQucHVzaCh2ZXJpZmllZFNpZyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFVud3JhcCBjb21wcmVzc2VkIG1lc3NhZ2VcbiAgICogQHJldHVybiB7bWVzc2FnZX0gbWVzc2FnZSBDb250ZW50IG9mIGNvbXByZXNzZWQgbWVzc2FnZVxuICAgKi9cbiAgdGhpcy51bndyYXBDb21wcmVzc2VkID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGNvbXByZXNzZWQgPSB0aGlzLnBhY2tldHMuZmlsdGVyQnlUYWcoZW51bXMucGFja2V0LmNvbXByZXNzZWQpO1xuICAgIGlmIChjb21wcmVzc2VkLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIG5ldyBtZXNzYWdlKGNvbXByZXNzZWRbMF0ucGFja2V0cyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIEFTQ0lJIGFybW9yZWQgdGV4dCBvZiBtZXNzYWdlXG4gICAqIEByZXR1cm4ge1N0cmluZ30gQVNDSUkgYXJtb3JcbiAgICovXG4gIHRoaXMuYXJtb3IgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXJtb3IuZW5jb2RlKGVudW1zLmFybW9yLm1lc3NhZ2UsIHRoaXMucGFja2V0cy53cml0ZSgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyBhIG1lc3NhZ2UgYW5kIGdlbmVyYXRlcyB1c2VyIGludGVyZmFjZSBtZXNzYWdlIG91dCBvZiB0aGUgZm91bmQuXG4gICAqIE1EQyB3aWxsIGJlIHZlcmlmaWVkIGFzIHdlbGwgYXMgbWVzc2FnZSBzaWduYXR1cmVzXG4gICAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0gcHJpdmF0ZV9rZXkgdGhlIHByaXZhdGUgdGhlIG1lc3NhZ2UgaXMgZW5jcnlwdGVkIHdpdGggKGNvcnJlc3BvbmRpbmcgdG8gdGhlIHNlc3Npb24ga2V5KVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZHNlc3Npb25rZXl9IHNlc3Npb25rZXkgdGhlIHNlc3Npb24ga2V5IHRvIGJlIHVzZWQgdG8gZGVjcnlwdCB0aGUgbWVzc2FnZVxuICAgKiBAcGFyYW0ge29wZW5wZ3BfbXNnX3B1YmxpY2tleX0gcHVia2V5IEFycmF5IG9mIHB1YmxpYyBrZXlzIHRvIGNoZWNrIHNpZ25hdHVyZSBhZ2FpbnN0LiBJZiBub3QgcHJvdmlkZWQsIGNoZWNrcyBsb2NhbCBrZXlzdG9yZS5cbiAgICogQHJldHVybiB7U3RyaW5nfSBwbGFpbnRleHQgb2YgdGhlIG1lc3NhZ2Ugb3IgbnVsbCBvbiBlcnJvclxuICAgKi9cbiAgZnVuY3Rpb24gZGVjcnlwdEFuZFZlcmlmeVNpZ25hdHVyZShwcml2YXRlX2tleSwgc2Vzc2lvbmtleSwgcHVia2V5KSB7XG4gICAgaWYgKHByaXZhdGVfa2V5ID09IG51bGwgfHwgc2Vzc2lvbmtleSA9PSBudWxsIHx8IHNlc3Npb25rZXkgPT0gXCJcIilcbiAgICAgIHJldHVybiBudWxsO1xuICAgIHZhciBkZWNyeXB0ZWQgPSBzZXNzaW9ua2V5LmRlY3J5cHQodGhpcywgcHJpdmF0ZV9rZXkua2V5bWF0ZXJpYWwpO1xuICAgIGlmIChkZWNyeXB0ZWQgPT0gbnVsbClcbiAgICAgIHJldHVybiBudWxsO1xuICAgIHZhciBwYWNrZXQ7XG4gICAgdmFyIHBvc2l0aW9uID0gMDtcbiAgICB2YXIgbGVuID0gZGVjcnlwdGVkLmxlbmd0aDtcbiAgICB2YXIgdmFsaWRTaWduYXR1cmVzID0gbmV3IEFycmF5KCk7XG4gICAgdXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcIm9wZW5wZ3AubXNnLm1lc3NnZSBkZWNyeXB0OlxcblwiLCBkZWNyeXB0ZWQpO1xuXG4gICAgdmFyIG1lc3NhZ2VzID0gb3BlbnBncC5yZWFkX21lc3NhZ2VzX2RlYXJtb3JlZCh7XG4gICAgICB0ZXh0OiBkZWNyeXB0ZWQsXG4gICAgICBvcGVucGdwOiBkZWNyeXB0ZWRcbiAgICB9KTtcbiAgICBmb3IgKHZhciBtIGluIG1lc3NhZ2VzKSB7XG4gICAgICBpZiAobWVzc2FnZXNbbV0uZGF0YSkge1xuICAgICAgICB0aGlzLnRleHQgPSBtZXNzYWdlc1ttXS5kYXRhO1xuICAgICAgfVxuICAgICAgaWYgKG1lc3NhZ2VzW21dLnNpZ25hdHVyZSkge1xuICAgICAgICB2YWxpZFNpZ25hdHVyZXMucHVzaChtZXNzYWdlc1ttXS52ZXJpZnlTaWduYXR1cmUocHVia2V5KSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiB0aGlzLnRleHQsXG4gICAgICB2YWxpZFNpZ25hdHVyZXM6IHZhbGlkU2lnbmF0dXJlc1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpZXMgYSBtZXNzYWdlIHNpZ25hdHVyZS4gVGhpcyBmdW5jdGlvbiBjYW4gYmUgY2FsbGVkIGFmdGVyIHJlYWRfbWVzc2FnZSBpZiB0aGUgbWVzc2FnZSB3YXMgc2lnbmVkIG9ubHkuXG4gICAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHVibGlja2V5fSBwdWJrZXkgQXJyYXkgb2YgcHVibGljIGtleXMgdG8gY2hlY2sgc2lnbmF0dXJlIGFnYWluc3QuIElmIG5vdCBwcm92aWRlZCwgY2hlY2tzIGxvY2FsIGtleXN0b3JlLlxuICAgKiBAcmV0dXJuIHtib29sZWFufSB0cnVlIGlmIHRoZSBzaWduYXR1cmUgd2FzIGNvcnJlY3Q7IG90aGVyd2lzZSBmYWxzZVxuICAgKi9cbiAgZnVuY3Rpb24gdmVyaWZ5U2lnbmF0dXJlKHB1YmtleSkge1xuICAgIHZhciByZXN1bHQgPSBmYWxzZTtcbiAgICBpZiAodGhpcy5zaWduYXR1cmUudGFnVHlwZSA9PSAyKSB7XG4gICAgICBpZiAoIXB1YmtleSB8fCBwdWJrZXkubGVuZ3RoID09IDApIHtcbiAgICAgICAgdmFyIHB1YmtleTtcbiAgICAgICAgaWYgKHRoaXMuc2lnbmF0dXJlLnZlcnNpb24gPT0gNCkge1xuICAgICAgICAgIHB1YmtleSA9IG9wZW5wZ3Aua2V5cmluZy5nZXRQdWJsaWNLZXlzRm9yS2V5SWQodGhpcy5zaWduYXR1cmUuaXNzdWVyS2V5SWQpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2lnbmF0dXJlLnZlcnNpb24gPT0gMykge1xuICAgICAgICAgIHB1YmtleSA9IG9wZW5wZ3Aua2V5cmluZy5nZXRQdWJsaWNLZXlzRm9yS2V5SWQodGhpcy5zaWduYXR1cmUua2V5SWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJ1bmtub3duIHNpZ25hdHVyZSB0eXBlIG9uIG1lc3NhZ2UhXCIpO1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHB1YmtleS5sZW5ndGggPT0gMClcbiAgICAgICAgdXRpbC5wcmludF93YXJuaW5nKFwiVW5hYmxlIHRvIHZlcmlmeSBzaWduYXR1cmUgb2YgaXNzdWVyOiBcIiArIHV0aWwuaGV4c3RyZHVtcCh0aGlzLnNpZ25hdHVyZS5pc3N1ZXJLZXlJZCkgK1xuICAgICAgICAgIFwiLiBQdWJsaWMga2V5IG5vdCBmb3VuZCBpbiBrZXlyaW5nLlwiKTtcbiAgICAgIGVsc2Uge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHB1YmtleS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciB0b2hhc2ggPSB0aGlzLnRleHQucmVwbGFjZSgvXFxyXFxuL2csIFwiXFxuXCIpLnJlcGxhY2UoL1xcbi9nLCBcIlxcclxcblwiKTtcbiAgICAgICAgICBpZiAodGhpcy5zaWduYXR1cmUudmVyaWZ5KHRvaGFzaCwgcHVia2V5W2ldKSkge1xuICAgICAgICAgICAgdXRpbC5wcmludF9pbmZvKFwiRm91bmQgR29vZCBTaWduYXR1cmUgZnJvbSBcIiArIHB1YmtleVtpXS5vYmoudXNlcklkc1swXS50ZXh0ICsgXCIgKDB4XCIgKyB1dGlsLmhleHN0cmR1bXAoXG4gICAgICAgICAgICAgIHB1YmtleVtpXS5vYmouZ2V0S2V5SWQoKSkuc3Vic3RyaW5nKDgpICsgXCIpXCIpO1xuICAgICAgICAgICAgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIlNpZ25hdHVyZSB2ZXJpZmljYXRpb24gZmFpbGVkOiBCYWQgU2lnbmF0dXJlIGZyb20gXCIgKyBwdWJrZXlbaV0ub2JqLnVzZXJJZHNbMF0udGV4dCArXG4gICAgICAgICAgICAgIFwiICgweFwiICsgdXRpbC5oZXhzdHJkdW1wKHB1YmtleVswXS5vYmouZ2V0S2V5SWQoKSkuc3Vic3RyaW5nKDgpICsgXCIpXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG5cbi8qKlxuICogcmVhZHMgYW4gT3BlblBHUCBhcm1vcmVkIG1lc3NhZ2UgYW5kIHJldHVybnMgYSBtZXNzYWdlIG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IGFybW9yZWRUZXh0IHRleHQgdG8gYmUgcGFyc2VkXG4gKiBAcmV0dXJuIHttZXNzYWdlfSBuZXcgbWVzc2FnZSBvYmplY3RcbiAqL1xubWVzc2FnZS5yZWFkQXJtb3JlZCA9IGZ1bmN0aW9uKGFybW9yZWRUZXh0KSB7XG4gIC8vVE9ETyBob3cgZG8gd2Ugd2FudCB0byBoYW5kbGUgYmFkIHRleHQ/IEV4Y2VwdGlvbiB0aHJvd2luZ1xuICAvL1RPRE8gZG9uJ3QgYWNjZXB0IG5vbi1tZXNzYWdlIGFybW9yZWQgdGV4dHNcbiAgdmFyIGlucHV0ID0gYXJtb3IuZGVjb2RlKGFybW9yZWRUZXh0KS5kYXRhO1xuICB2YXIgcGFja2V0bGlzdCA9IG5ldyBwYWNrZXQubGlzdCgpO1xuICBwYWNrZXRsaXN0LnJlYWQoaW5wdXQpO1xuICB2YXIgbmV3TWVzc2FnZSA9IG5ldyBtZXNzYWdlKHBhY2tldGxpc3QpO1xuICByZXR1cm4gbmV3TWVzc2FnZTtcbn1cblxuLyoqXG4gKiBjcmVhdGVzIG5ldyBtZXNzYWdlIG9iamVjdCBmcm9tIHRleHRcbiAqIEBwYXJhbSB7U3RyaW5nfSB0ZXh0XG4gKiBAcmV0dXJuIHttZXNzYWdlfSBuZXcgbWVzc2FnZSBvYmplY3RcbiAqL1xubWVzc2FnZS5mcm9tVGV4dCA9IGZ1bmN0aW9uKHRleHQpIHtcbiAgdmFyIGxpdGVyYWxEYXRhUGFja2V0ID0gbmV3IHBhY2tldC5saXRlcmFsKCk7XG4gIC8vIHRleHQgd2lsbCBiZSBjb252ZXJ0ZWQgdG8gVVRGOFxuICBsaXRlcmFsRGF0YVBhY2tldC5zZXQodGV4dCk7XG4gIHZhciBsaXRlcmFsRGF0YVBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcbiAgbGl0ZXJhbERhdGFQYWNrZXRsaXN0LnB1c2gobGl0ZXJhbERhdGFQYWNrZXQpO1xuICB2YXIgbmV3TWVzc2FnZSA9IG5ldyBtZXNzYWdlKGxpdGVyYWxEYXRhUGFja2V0bGlzdCk7XG4gIHJldHVybiBuZXdNZXNzYWdlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1lc3NhZ2U7IiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxuLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IFRoZSBvcGVucGdwIGJhc2UgY2xhc3Mgc2hvdWxkIHByb3ZpZGUgYWxsIG9mIHRoZSBmdW5jdGlvbmFsaXR5IFxuICogdG8gY29uc3VtZSB0aGUgb3BlbnBncC5qcyBsaWJyYXJ5LiBBbGwgYWRkaXRpb25hbCBjbGFzc2VzIGFyZSBkb2N1bWVudGVkIFxuICogZm9yIGV4dGVuZGluZyBhbmQgZGV2ZWxvcGluZyBvbiB0b3Agb2YgdGhlIGJhc2UgbGlicmFyeS5cbiAqL1xuXG52YXIgYXJtb3IgPSByZXF1aXJlKCcuL2VuY29kaW5nL2FybW9yLmpzJyk7XG52YXIgcGFja2V0ID0gcmVxdWlyZSgnLi9wYWNrZXQnKTtcbnZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG52YXIgZW51bXMgPSByZXF1aXJlKCcuL2VudW1zLmpzJyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi9jb25maWcnKTtcbnZhciBtZXNzYWdlID0gcmVxdWlyZSgnLi9tZXNzYWdlLmpzJyk7XG5cbi8qKlxuICogR1BHNEJyb3dzZXJzIENvcmUgaW50ZXJmYWNlLiBBIHNpbmdsZSBpbnN0YW5jZSBpcyBob2xkXG4gKiBmcm9tIHRoZSBiZWdpbm5pbmcuIFRvIHVzZSB0aGlzIGxpYnJhcnkgY2FsbCBcIm9wZW5wZ3AuaW5pdCgpXCJcbiAqIEBhbGlhcyBvcGVucGdwXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgTWFpbiBPcGVucGdwLmpzIGNsYXNzLiBVc2UgdGhpcyB0byBpbml0aWF0ZSBhbmQgbWFrZSBhbGwgY2FsbHMgdG8gdGhpcyBsaWJyYXJ5LlxuICovXG5mdW5jdGlvbiBfb3BlbnBncCgpIHtcblxuICAvKipcbiAgICogRW5jcnlwdHMgbWVzc2FnZSB0ZXh0IHdpdGgga2V5c1xuICAgKiBAcGFyYW0gIHtba2V5XX0gIGtleXMgYXJyYXkgb2Yga2V5cywgdXNlZCB0byBlbmNyeXB0IHRoZSBtZXNzYWdlXG4gICAqIEBwYXJhbSAge1N0cmluZ30gdGV4dCBtZXNzYWdlIGFzIG5hdGl2ZSBKYXZhU2NyaXB0IHN0cmluZ1xuICAgKiBAcmV0dXJuIHtTdHJpbmd9ICAgICAgZW5jcnlwdGVkIEFTQ0lJIGFybW9yZWQgbWVzc2FnZVxuICAgKi9cbiAgZnVuY3Rpb24gZW5jcnlwdE1lc3NhZ2Uoa2V5cywgdGV4dCkge1xuICAgIHZhciBtc2cgPSBtZXNzYWdlLmZyb21UZXh0KHRleHQpO1xuICAgIG1zZyA9IG1zZy5lbmNyeXB0KGtleXMpO1xuICAgIHZhciBhcm1vcmVkID0gYXJtb3IuZW5jb2RlKGVudW1zLmFybW9yLm1lc3NhZ2UsIG1zZy5wYWNrZXRzLndyaXRlKCkpO1xuICAgIHJldHVybiBhcm1vcmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFNpZ25zIG1lc3NhZ2UgdGV4dCBhbmQgZW5jcnlwdHMgaXRcbiAgICogQHBhcmFtICB7W2tleV19ICBwdWJsaWNLZXlzIGFycmF5IG9mIGtleXMsIHVzZWQgdG8gZW5jcnlwdCB0aGUgbWVzc2FnZVxuICAgKiBAcGFyYW0gIHtrZXl9ICAgIHByaXZhdGVLZXkgcHJpdmF0ZSBrZXkgd2l0aCBkZWNyeXB0ZWQgc2VjcmV0IGtleSBkYXRhIGZvciBzaWduaW5nXG4gICAqIEBwYXJhbSAge1N0cmluZ30gdGV4dCAgICAgICBtZXNzYWdlIGFzIG5hdGl2ZSBKYXZhU2NyaXB0IHN0cmluZ1xuICAgKiBAcmV0dXJuIHtTdHJpbmd9ICAgICAgICAgICAgZW5jcnlwdGVkIEFTQ0lJIGFybW9yZWQgbWVzc2FnZVxuICAgKi9cbiAgZnVuY3Rpb24gc2lnbkFuZEVuY3J5cHRNZXNzYWdlKHB1YmxpY0tleXMsIHByaXZhdGVLZXksIHRleHQpIHtcbiAgICB2YXIgbXNnID0gbWVzc2FnZS5mcm9tVGV4dCh0ZXh0KTtcbiAgICBtc2cgPSBtc2cuc2lnbihbcHJpdmF0ZUtleV0pO1xuICAgIG1zZyA9IG1zZy5lbmNyeXB0KHB1YmxpY0tleXMpO1xuICAgIHZhciBhcm1vcmVkID0gYXJtb3IuZW5jb2RlKGVudW1zLmFybW9yLm1lc3NhZ2UsIG1zZy5wYWNrZXRzLndyaXRlKCkpO1xuICAgIHJldHVybiBhcm1vcmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIG1lc3NhZ2VcbiAgICogQHBhcmFtICB7a2V5fSAgICAgcHJpdmF0ZUtleSBwcml2YXRlIGtleSB3aXRoIGRlY3J5cHRlZCBzZWNyZXQga2V5IGRhdGFcbiAgICogQHBhcmFtICB7bWVzc2FnZX0gbWVzc2FnZSAgICB0aGUgbWVzc2FnZSBvYmplY3Qgd2l0aCB0aGUgZW5jcnlwdGVkIGRhdGFcbiAgICogQHJldHVybiB7U3RyaW5nfG51bGx9ICAgICAgICBkZWNyeXB0ZWQgbWVzc2FnZSBhcyBhcyBuYXRpdmUgSmF2YVNjcmlwdCBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvciBudWxsIGlmIG5vIGxpdGVyYWwgZGF0YSBmb3VuZFxuICAgKi9cbiAgZnVuY3Rpb24gZGVjcnlwdE1lc3NhZ2UocHJpdmF0ZUtleSwgbWVzc2FnZSkge1xuICAgIG1lc3NhZ2UgPSBtZXNzYWdlLmRlY3J5cHQocHJpdmF0ZUtleSk7XG4gICAgcmV0dXJuIG1lc3NhZ2UuZ2V0VGV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIG1lc3NhZ2UgYW5kIHZlcmlmaWVzIHNpZ25hdHVyZXNcbiAgICogQHBhcmFtICB7a2V5fSAgICAgcHJpdmF0ZUtleSBwcml2YXRlIGtleSB3aXRoIGRlY3J5cHRlZCBzZWNyZXQga2V5IGRhdGFcbiAgICogQHBhcmFtICB7W2tleV19ICAgcHVibGljS2V5cyBwdWJsaWMga2V5cyB0byB2ZXJpZnkgc2lnbmF0dXJlc1xuICAgKiBAcGFyYW0gIHttZXNzYWdlfSBtZXNzYWdlICAgIHRoZSBtZXNzYWdlIG9iamVjdCB3aXRoIHNpZ25lZCBhbmQgZW5jcnlwdGVkIGRhdGFcbiAgICogQHJldHVybiB7eyd0ZXh0JzogU3RyaW5nLCBzaWduYXR1cmVzOiBbeydrZXlpZCc6IGtleWlkLCAnc3RhdHVzJzogQm9vbGVhbn1dfX1cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNyeXB0ZWQgbWVzc2FnZSBhcyBhcyBuYXRpdmUgSmF2YVNjcmlwdCBzdHJpbmdcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aXRoIHZlcmlmaWVkIHNpZ25hdHVyZXMgb3IgbnVsbCBpZiBubyBsaXRlcmFsIGRhdGEgZm91bmRcbiAgICovXG4gIGZ1bmN0aW9uIGRlY3J5cHRBbmRWZXJpZnlNZXNzYWdlKHByaXZhdGVLZXksIHB1YmxpY0tleXMsIG1lc3NhZ2UpIHtcbiAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UuZGVjcnlwdChwcml2YXRlS2V5KTtcbiAgICByZXN1bHQudGV4dCA9IG1lc3NhZ2UuZ2V0VGV4dCgpO1xuICAgIGlmIChyZXN1bHQudGV4dCkge1xuICAgICAgcmVzdWx0LnNpZ25hdHVyZXMgPSBtZXNzYWdlLnZlcmlmeShwdWJsaWNLZXlzKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZnVuY3Rpb24gdmVyaWZ5TWVzc2FnZShwdWJsaWNLZXlzLCBtZXNzYWdlUGFja2V0bGlzdCkge1xuXG4gIH1cblxuICBmdW5jdGlvbiBzaWduTWVzc2FnZShwcml2YXRlS2V5LCBtZXNzYWdlUGFja2V0bGlzdCkge1xuXG4gIH1cblxuICAvKipcbiAgICogVE9ETzogdXBkYXRlIHRoaXMgZG9jXG4gICAqIGdlbmVyYXRlcyBhIG5ldyBrZXkgcGFpciBmb3Igb3BlbnBncC4gQmV0YSBzdGFnZS4gQ3VycmVudGx5IG9ubHkgXG4gICAqIHN1cHBvcnRzIFJTQSBrZXlzLCBhbmQgbm8gc3Via2V5cy5cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBrZXlUeXBlIHRvIGluZGljYXRlIHdoYXQgdHlwZSBvZiBrZXkgdG8gbWFrZS4gXG4gICAqIFJTQSBpcyAxLiBGb2xsb3dzIGFsZ29yaXRobXMgb3V0bGluZWQgaW4gT3BlblBHUC5cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBudW1CaXRzIG51bWJlciBvZiBiaXRzIGZvciB0aGUga2V5IGNyZWF0aW9uLiAoc2hvdWxkIFxuICAgKiBiZSAxMDI0KywgZ2VuZXJhbGx5KVxuICAgKiBAcGFyYW0ge1N0cmluZ30gdXNlcklkIGFzc3VtZXMgYWxyZWFkeSBpbiBmb3JtIG9mIFwiVXNlciBOYW1lIFxuICAgKiA8dXNlcm5hbWVAZW1haWwuY29tPlwiXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwYXNzcGhyYXNlIFRoZSBwYXNzcGhyYXNlIHVzZWQgdG8gZW5jcnlwdCB0aGUgcmVzdWx0aW5nIHByaXZhdGUga2V5XG4gICAqIEByZXR1cm4ge09iamVjdH0ge3ByaXZhdGVLZXk6IFtvcGVucGdwX21zZ19wcml2YXRla2V5XSwgXG4gICAqIHByaXZhdGVLZXlBcm1vcmVkOiBbc3RyaW5nXSwgcHVibGljS2V5QXJtb3JlZDogW3N0cmluZ119XG4gICAqL1xuICBmdW5jdGlvbiBnZW5lcmF0ZUtleVBhaXIoa2V5VHlwZSwgbnVtQml0cywgdXNlcklkLCBwYXNzcGhyYXNlKSB7XG4gICAgdmFyIHBhY2tldGxpc3QgPSBuZXcgcGFja2V0Lmxpc3QoKTtcblxuICAgIHZhciBzZWNyZXRLZXlQYWNrZXQgPSBuZXcgcGFja2V0LnNlY3JldF9rZXkoKTtcbiAgICBzZWNyZXRLZXlQYWNrZXQuYWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGtleVR5cGUpO1xuICAgIHNlY3JldEtleVBhY2tldC5nZW5lcmF0ZShudW1CaXRzKTtcbiAgICBzZWNyZXRLZXlQYWNrZXQuZW5jcnlwdChwYXNzcGhyYXNlKTtcblxuICAgIHZhciB1c2VySWRQYWNrZXQgPSBuZXcgcGFja2V0LnVzZXJpZCgpO1xuICAgIHVzZXJJZFBhY2tldC5yZWFkKHVzZXJJZCk7XG5cbiAgICB2YXIgZGF0YVRvU2lnbiA9IHt9O1xuICAgIGRhdGFUb1NpZ24udXNlcmlkID0gdXNlcklkUGFja2V0O1xuICAgIGRhdGFUb1NpZ24ua2V5ID0gc2VjcmV0S2V5UGFja2V0O1xuICAgIHZhciBzaWduYXR1cmVQYWNrZXQgPSBuZXcgcGFja2V0LnNpZ25hdHVyZSgpO1xuICAgIHNpZ25hdHVyZVBhY2tldC5zaWduYXR1cmVUeXBlID0gZW51bXMuc2lnbmF0dXJlLmNlcnRfZ2VuZXJpYztcbiAgICBzaWduYXR1cmVQYWNrZXQucHVibGljS2V5QWxnb3JpdGhtID0ga2V5VHlwZTtcbiAgICAvL1RPRE8gd2Ugc2hvdWxkIGxvYWQgcHJlZmVycmVkIGhhc2ggZnJvbSBjb25maWcsIG9yIGFzIGlucHV0IHRvIHRoaXMgZnVuY3Rpb25cbiAgICBzaWduYXR1cmVQYWNrZXQuaGFzaEFsZ29yaXRobSA9IGVudW1zLmhhc2guc2hhMjU2O1xuICAgIHNpZ25hdHVyZVBhY2tldC5rZXlGbGFncyA9IFtlbnVtcy5rZXlGbGFncy5jZXJ0aWZ5X2tleXMgfCBlbnVtcy5rZXlGbGFncy5zaWduX2RhdGFdO1xuICAgIHNpZ25hdHVyZVBhY2tldC5zaWduKHNlY3JldEtleVBhY2tldCwgZGF0YVRvU2lnbik7XG5cbiAgICB2YXIgc2VjcmV0U3Via2V5UGFja2V0ID0gbmV3IHBhY2tldC5zZWNyZXRfc3Via2V5KCk7XG4gICAgc2VjcmV0U3Via2V5UGFja2V0LmFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMucHVibGljS2V5LCBrZXlUeXBlKTtcbiAgICBzZWNyZXRTdWJrZXlQYWNrZXQuZ2VuZXJhdGUobnVtQml0cyk7XG4gICAgc2VjcmV0U3Via2V5UGFja2V0LmVuY3J5cHQocGFzc3BocmFzZSk7XG5cbiAgICBkYXRhVG9TaWduID0ge307XG4gICAgZGF0YVRvU2lnbi5rZXkgPSBzZWNyZXRLZXlQYWNrZXQ7XG4gICAgZGF0YVRvU2lnbi5iaW5kID0gc2VjcmV0U3Via2V5UGFja2V0O1xuICAgIHZhciBzdWJrZXlTaWduYXR1cmVQYWNrZXQgPSBuZXcgcGFja2V0LnNpZ25hdHVyZSgpO1xuICAgIHN1YmtleVNpZ25hdHVyZVBhY2tldC5zaWduYXR1cmVUeXBlID0gZW51bXMuc2lnbmF0dXJlLnN1YmtleV9iaW5kaW5nO1xuICAgIHN1YmtleVNpZ25hdHVyZVBhY2tldC5wdWJsaWNLZXlBbGdvcml0aG0gPSBrZXlUeXBlO1xuICAgIC8vVE9ETyB3ZSBzaG91bGQgbG9hZCBwcmVmZXJyZWQgaGFzaCBmcm9tIGNvbmZpZywgb3IgYXMgaW5wdXQgdG8gdGhpcyBmdW5jdGlvblxuICAgIHN1YmtleVNpZ25hdHVyZVBhY2tldC5oYXNoQWxnb3JpdGhtID0gZW51bXMuaGFzaC5zaGEyNTY7XG4gICAgc3Via2V5U2lnbmF0dXJlUGFja2V0LmtleUZsYWdzID0gW2VudW1zLmtleUZsYWdzLmVuY3J5cHRfY29tbXVuaWNhdGlvbiB8IGVudW1zLmtleUZsYWdzLmVuY3J5cHRfc3RvcmFnZV07XG4gICAgc3Via2V5U2lnbmF0dXJlUGFja2V0LnNpZ24oc2VjcmV0S2V5UGFja2V0LCBkYXRhVG9TaWduKTtcblxuICAgIHBhY2tldGxpc3QucHVzaChzZWNyZXRLZXlQYWNrZXQpO1xuICAgIHBhY2tldGxpc3QucHVzaCh1c2VySWRQYWNrZXQpO1xuICAgIHBhY2tldGxpc3QucHVzaChzaWduYXR1cmVQYWNrZXQpO1xuICAgIHBhY2tldGxpc3QucHVzaChzZWNyZXRTdWJrZXlQYWNrZXQpO1xuICAgIHBhY2tldGxpc3QucHVzaChzdWJrZXlTaWduYXR1cmVQYWNrZXQpO1xuXG4gICAgdmFyIGFybW9yZWQgPSBhcm1vci5lbmNvZGUoZW51bXMuYXJtb3IucHJpdmF0ZV9rZXksIHBhY2tldGxpc3Qud3JpdGUoKSk7XG4gICAgcmV0dXJuIGFybW9yZWQ7XG4gIH1cblxuICAvKipcbiAgICogY3JlYXRlcyBhIGJpbmFyeSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYW4gZW5jcnlwdGVkIGFuZCBzaWduZWQgbWVzc2FnZS5cbiAgICogVGhlIG1lc3NhZ2Ugd2lsbCBiZSBlbmNyeXB0ZWQgd2l0aCB0aGUgcHVibGljIGtleXMgc3BlY2lmaWVkIGFuZCBzaWduZWRcbiAgICogd2l0aCB0aGUgc3BlY2lmaWVkIHByaXZhdGUga2V5LlxuICAgKiBAcGFyYW0ge09iamVjdH0gcHJpdmF0ZWtleSB7b2JqOiBbb3BlbnBncF9tc2dfcHJpdmF0ZWtleV19IFByaXZhdGUga2V5IFxuICAgKiB0byBiZSB1c2VkIHRvIHNpZ24gdGhlIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtPYmplY3RbXX0gcHVibGlja2V5cyBBbiBhcnJhZiBvZiB7b2JqOiBbb3BlbnBncF9tc2dfcHVibGlja2V5XX1cbiAgICogLSBwdWJsaWMga2V5cyB0byBiZSB1c2VkIHRvIGVuY3J5cHQgdGhlIG1lc3NhZ2UgXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdldGV4dCBtZXNzYWdlIHRleHQgdG8gZW5jcnlwdCBhbmQgc2lnblxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGEgYmluYXJ5IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgbWVzc2FnZSB3aGljaCBcbiAgICogY2FuIGJlIE9wZW5QR1AgYXJtb3JlZFxuICAgKi9cbiAgZnVuY3Rpb24gd3JpdGVfc2lnbmVkX2FuZF9lbmNyeXB0ZWRfbWVzc2FnZShwcml2YXRla2V5LCBwdWJsaWNrZXlzLCBtZXNzYWdldGV4dCkge1xuICAgIHZhciByZXN1bHQgPSBcIlwiO1xuICAgIHZhciBpO1xuICAgIHZhciBsaXRlcmFsID0gbmV3IG9wZW5wZ3BfcGFja2V0X2xpdGVyYWxkYXRhKCkud3JpdGVfcGFja2V0KG1lc3NhZ2V0ZXh0LnJlcGxhY2UoL1xcclxcbi9nLCBcIlxcblwiKS5yZXBsYWNlKC9cXG4vZyxcbiAgICAgIFwiXFxyXFxuXCIpKTtcbiAgICB1dGlsLnByaW50X2RlYnVnX2hleHN0cl9kdW1wKFwibGl0ZXJhbF9wYWNrZXQ6IHxcIiArIGxpdGVyYWwgKyBcInxcXG5cIiwgbGl0ZXJhbCk7XG4gICAgZm9yIChpID0gMDsgaSA8IHB1YmxpY2tleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBvbmVwYXNzc2lnbmF0dXJlID0gbmV3IG9wZW5wZ3BfcGFja2V0X29uZXBhc3NzaWduYXR1cmUoKTtcbiAgICAgIHZhciBvbmVwYXNzc2lnc3RyID0gXCJcIjtcbiAgICAgIGlmIChpID09PSAwKVxuICAgICAgICBvbmVwYXNzc2lnc3RyID0gb25lcGFzc3NpZ25hdHVyZS53cml0ZV9wYWNrZXQoMSwgb3BlbnBncC5jb25maWcuY29uZmlnLnByZWZlcl9oYXNoX2FsZ29yaXRobSwgcHJpdmF0ZWtleSwgZmFsc2UpO1xuICAgICAgZWxzZVxuICAgICAgICBvbmVwYXNzc2lnc3RyID0gb25lcGFzc3NpZ25hdHVyZS53cml0ZV9wYWNrZXQoMSwgb3BlbnBncC5jb25maWcuY29uZmlnLnByZWZlcl9oYXNoX2FsZ29yaXRobSwgcHJpdmF0ZWtleSwgZmFsc2UpO1xuICAgICAgdXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcIm9uZXBhc3NzaWdzdHI6IHxcIiArIG9uZXBhc3NzaWdzdHIgKyBcInxcXG5cIiwgb25lcGFzc3NpZ3N0cik7XG4gICAgICB2YXIgZGF0YXNpZ25hdHVyZSA9IG5ldyBvcGVucGdwX3BhY2tldF9zaWduYXR1cmUoKS53cml0ZV9tZXNzYWdlX3NpZ25hdHVyZSgxLCBtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZShcbiAgICAgICAgL1xcbi9nLCBcIlxcclxcblwiKSwgcHJpdmF0ZWtleSk7XG4gICAgICB1dGlsLnByaW50X2RlYnVnX2hleHN0cl9kdW1wKFwiZGF0YXNpZ25hdHVyZTogfFwiICsgZGF0YXNpZ25hdHVyZS5vcGVucGdwICsgXCJ8XFxuXCIsIGRhdGFzaWduYXR1cmUub3BlbnBncCk7XG4gICAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgICByZXN1bHQgPSBvbmVwYXNzc2lnc3RyICsgbGl0ZXJhbCArIGRhdGFzaWduYXR1cmUub3BlbnBncDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCA9IG9uZXBhc3NzaWdzdHIgKyByZXN1bHQgKyBkYXRhc2lnbmF0dXJlLm9wZW5wZ3A7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdXRpbC5wcmludF9kZWJ1Z19oZXhzdHJfZHVtcChcInNpZ25lZCBwYWNrZXQ6IHxcIiArIHJlc3VsdCArIFwifFxcblwiLCByZXN1bHQpO1xuICAgIC8vIHNpZ25hdHVyZXMgZG9uZS4uIG5vdyBlbmNyeXB0aW9uXG4gICAgdmFyIHNlc3Npb25rZXkgPSBvcGVucGdwX2NyeXB0b19nZW5lcmF0ZVNlc3Npb25LZXkob3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyKTtcbiAgICB2YXIgcmVzdWx0MiA9IFwiXCI7XG5cbiAgICAvLyBjcmVhdGluZyBzZXNzaW9uIGtleXMgZm9yIGVhY2ggcmVjaXBpZW50XG4gICAgZm9yIChpID0gMDsgaSA8IHB1YmxpY2tleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwa2V5ID0gcHVibGlja2V5c1tpXS5nZXRFbmNyeXB0aW9uS2V5KCk7XG4gICAgICBpZiAocGtleSA9PT0gbnVsbCkge1xuICAgICAgICB1dGlsLnByaW50X2Vycm9yKFwibm8gZW5jcnlwdGlvbiBrZXkgZm91bmQhIEtleSBpcyBmb3Igc2lnbmluZyBvbmx5LlwiKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXN1bHQyICs9IG5ldyBvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRzZXNzaW9ua2V5KCkuXG4gICAgICB3cml0ZV9wdWJfa2V5X3BhY2tldChcbiAgICAgICAgcGtleS5nZXRLZXlJZCgpLFxuICAgICAgICBwa2V5Lk1QSXMsXG4gICAgICAgIHBrZXkucHVibGljS2V5QWxnb3JpdGhtLFxuICAgICAgICBvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsXG4gICAgICAgIHNlc3Npb25rZXkpO1xuICAgIH1cbiAgICBpZiAob3BlbnBncC5jb25maWcuY29uZmlnLmludGVncml0eV9wcm90ZWN0KSB7XG4gICAgICByZXN1bHQyICs9IG5ldyBvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRpbnRlZ3JpdHlwcm90ZWN0ZWRkYXRhKCkud3JpdGVfcGFja2V0KG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5lbmNyeXB0aW9uX2NpcGhlcixcbiAgICAgICAgc2Vzc2lvbmtleSwgcmVzdWx0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YSgpLndyaXRlX3BhY2tldChvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsIHNlc3Npb25rZXksXG4gICAgICAgIHJlc3VsdCk7XG4gICAgfVxuICAgIHJldHVybiBhcm1vci5lbmNvZGUoMywgcmVzdWx0MiwgbnVsbCwgbnVsbCk7XG4gIH1cbiAgLyoqXG4gICAqIGNyZWF0ZXMgYSBiaW5hcnkgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGFuIGVuY3J5cHRlZCBtZXNzYWdlLlxuICAgKiBUaGUgbWVzc2FnZSB3aWxsIGJlIGVuY3J5cHRlZCB3aXRoIHRoZSBwdWJsaWMga2V5cyBzcGVjaWZpZWQgXG4gICAqIEBwYXJhbSB7T2JqZWN0W119IHB1YmxpY2tleXMgQW4gYXJyYXkgb2Yge29iajogW29wZW5wZ3BfbXNnX3B1YmxpY2tleV19XG4gICAqIC1wdWJsaWMga2V5cyB0byBiZSB1c2VkIHRvIGVuY3J5cHQgdGhlIG1lc3NhZ2UgXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdldGV4dCBtZXNzYWdlIHRleHQgdG8gZW5jcnlwdFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IGEgYmluYXJ5IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgbWVzc2FnZVxuICAgKiB3aGljaCBjYW4gYmUgT3BlblBHUCBhcm1vcmVkXG4gICAqL1xuICBmdW5jdGlvbiB3cml0ZV9lbmNyeXB0ZWRfbWVzc2FnZShwdWJsaWNrZXlzLCBtZXNzYWdldGV4dCkge1xuICAgIHZhciByZXN1bHQgPSBcIlwiO1xuICAgIHZhciBsaXRlcmFsID0gbmV3IG9wZW5wZ3BfcGFja2V0X2xpdGVyYWxkYXRhKCkud3JpdGVfcGFja2V0KG1lc3NhZ2V0ZXh0LnJlcGxhY2UoL1xcclxcbi9nLCBcIlxcblwiKS5yZXBsYWNlKC9cXG4vZyxcbiAgICAgIFwiXFxyXFxuXCIpKTtcbiAgICB1dGlsLnByaW50X2RlYnVnX2hleHN0cl9kdW1wKFwibGl0ZXJhbF9wYWNrZXQ6IHxcIiArIGxpdGVyYWwgKyBcInxcXG5cIiwgbGl0ZXJhbCk7XG4gICAgcmVzdWx0ID0gbGl0ZXJhbDtcblxuICAgIC8vIHNpZ25hdHVyZXMgZG9uZS4uIG5vdyBlbmNyeXB0aW9uXG4gICAgdmFyIHNlc3Npb25rZXkgPSBvcGVucGdwX2NyeXB0b19nZW5lcmF0ZVNlc3Npb25LZXkob3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyKTtcbiAgICB2YXIgcmVzdWx0MiA9IFwiXCI7XG5cbiAgICAvLyBjcmVhdGluZyBzZXNzaW9uIGtleXMgZm9yIGVhY2ggcmVjaXBpZW50XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwdWJsaWNrZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgcGtleSA9IHB1YmxpY2tleXNbaV0uZ2V0RW5jcnlwdGlvbktleSgpO1xuICAgICAgaWYgKHBrZXkgPT09IG51bGwpIHtcbiAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIm5vIGVuY3J5cHRpb24ga2V5IGZvdW5kISBLZXkgaXMgZm9yIHNpZ25pbmcgb25seS5cIik7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgcmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkc2Vzc2lvbmtleSgpLlxuICAgICAgd3JpdGVfcHViX2tleV9wYWNrZXQoXG4gICAgICAgIHBrZXkuZ2V0S2V5SWQoKSxcbiAgICAgICAgcGtleS5NUElzLFxuICAgICAgICBwa2V5LnB1YmxpY0tleUFsZ29yaXRobSxcbiAgICAgICAgb3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyLFxuICAgICAgICBzZXNzaW9ua2V5KTtcbiAgICB9XG4gICAgaWYgKG9wZW5wZ3AuY29uZmlnLmNvbmZpZy5pbnRlZ3JpdHlfcHJvdGVjdCkge1xuICAgICAgcmVzdWx0MiArPSBuZXcgb3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkaW50ZWdyaXR5cHJvdGVjdGVkZGF0YSgpLndyaXRlX3BhY2tldChvcGVucGdwLmNvbmZpZy5jb25maWcuZW5jcnlwdGlvbl9jaXBoZXIsXG4gICAgICAgIHNlc3Npb25rZXksIHJlc3VsdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdDIgKz0gbmV3IG9wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGEoKS53cml0ZV9wYWNrZXQob3BlbnBncC5jb25maWcuY29uZmlnLmVuY3J5cHRpb25fY2lwaGVyLCBzZXNzaW9ua2V5LFxuICAgICAgICByZXN1bHQpO1xuICAgIH1cbiAgICByZXR1cm4gYXJtb3IuZW5jb2RlKDMsIHJlc3VsdDIsIG51bGwsIG51bGwpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNyZWF0ZXMgYSBiaW5hcnkgc3RyaW5nIHJlcHJlc2VudGF0aW9uIGEgc2lnbmVkIG1lc3NhZ2UuXG4gICAqIFRoZSBtZXNzYWdlIHdpbGwgYmUgc2lnbmVkIHdpdGggdGhlIHNwZWNpZmllZCBwcml2YXRlIGtleS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHByaXZhdGVrZXkge29iajogW29wZW5wZ3BfbXNnX3ByaXZhdGVrZXldfVxuICAgKiAtIHRoZSBwcml2YXRlIGtleSB0byBiZSB1c2VkIHRvIHNpZ24gdGhlIG1lc3NhZ2UgXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdldGV4dCBtZXNzYWdlIHRleHQgdG8gc2lnblxuICAgKiBAcmV0dXJuIHtPYmplY3R9IHtPYmplY3Q6IHRleHQgW1N0cmluZ119LCBvcGVucGdwOiB7U3RyaW5nfSBhIGJpbmFyeVxuICAgKiAgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtZXNzYWdlIHdoaWNoIGNhbiBiZSBPcGVuUEdQXG4gICAqICAgYXJtb3JlZChvcGVucGdwKSBhbmQgYSB0ZXh0IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtZXNzYWdlICh0ZXh0KS4gXG4gICAqIFRoaXMgY2FuIGJlIGRpcmVjdGx5IHVzZWQgdG8gT3BlblBHUCBhcm1vciB0aGUgbWVzc2FnZVxuICAgKi9cbiAgZnVuY3Rpb24gd3JpdGVfc2lnbmVkX21lc3NhZ2UocHJpdmF0ZWtleSwgbWVzc2FnZXRleHQpIHtcbiAgICB2YXIgc2lnID0gbmV3IG9wZW5wZ3BfcGFja2V0X3NpZ25hdHVyZSgpLndyaXRlX21lc3NhZ2Vfc2lnbmF0dXJlKDEsIG1lc3NhZ2V0ZXh0LnJlcGxhY2UoL1xcclxcbi9nLCBcIlxcblwiKS5yZXBsYWNlKC9cXG4vLFxuICAgICAgXCJcXHJcXG5cIiksIHByaXZhdGVrZXkpO1xuICAgIHZhciByZXN1bHQgPSB7XG4gICAgICB0ZXh0OiBtZXNzYWdldGV4dC5yZXBsYWNlKC9cXHJcXG4vZywgXCJcXG5cIikucmVwbGFjZSgvXFxuLywgXCJcXHJcXG5cIiksXG4gICAgICBvcGVucGdwOiBzaWcub3BlbnBncCxcbiAgICAgIGhhc2g6IHNpZy5oYXNoXG4gICAgfTtcbiAgICByZXR1cm4gYXJtb3IuZW5jb2RlKDIsIHJlc3VsdCwgbnVsbCwgbnVsbCk7XG4gIH1cblxuICB0aGlzLmdlbmVyYXRlS2V5UGFpciA9IGdlbmVyYXRlS2V5UGFpcjtcbiAgdGhpcy53cml0ZV9zaWduZWRfbWVzc2FnZSA9IHdyaXRlX3NpZ25lZF9tZXNzYWdlO1xuICB0aGlzLnNpZ25BbmRFbmNyeXB0TWVzc2FnZSA9IHNpZ25BbmRFbmNyeXB0TWVzc2FnZTtcbiAgdGhpcy5kZWNyeXB0QW5kVmVyaWZ5TWVzc2FnZSA9IGRlY3J5cHRBbmRWZXJpZnlNZXNzYWdlXG4gIHRoaXMuZW5jcnlwdE1lc3NhZ2UgPSBlbmNyeXB0TWVzc2FnZTtcbiAgdGhpcy5kZWNyeXB0TWVzc2FnZSA9IGRlY3J5cHRNZXNzYWdlO1xuXG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IF9vcGVucGdwKCk7XG4iLCJ2YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpO1xuXG4vLyBUaGlzIGlzIHByZXR0eSB1Z2x5LCBidXQgYnJvd3NlcmlmeSBuZWVkcyB0byBoYXZlIHRoZSByZXF1aXJlcyBleHBsaWNpdGx5IHdyaXR0ZW4uXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgY29tcHJlc3NlZDogcmVxdWlyZSgnLi9jb21wcmVzc2VkLmpzJyksXG4gIHN5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZDogcmVxdWlyZSgnLi9zeW1fZW5jcnlwdGVkX2ludGVncml0eV9wcm90ZWN0ZWQuanMnKSxcbiAgcHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXk6IHJlcXVpcmUoJy4vcHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkuanMnKSxcbiAgc3ltX2VuY3J5cHRlZF9zZXNzaW9uX2tleTogcmVxdWlyZSgnLi9zeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5LmpzJyksXG4gIGxpdGVyYWw6IHJlcXVpcmUoJy4vbGl0ZXJhbC5qcycpLFxuICBwdWJsaWNfa2V5OiByZXF1aXJlKCcuL3B1YmxpY19rZXkuanMnKSxcbiAgc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQ6IHJlcXVpcmUoJy4vc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQuanMnKSxcbiAgbWFya2VyOiByZXF1aXJlKCcuL21hcmtlci5qcycpLFxuICBwdWJsaWNfc3Via2V5OiByZXF1aXJlKCcuL3B1YmxpY19zdWJrZXkuanMnKSxcbiAgdXNlcl9hdHRyaWJ1dGU6IHJlcXVpcmUoJy4vdXNlcl9hdHRyaWJ1dGUuanMnKSxcbiAgb25lX3Bhc3Nfc2lnbmF0dXJlOiByZXF1aXJlKCcuL29uZV9wYXNzX3NpZ25hdHVyZS5qcycpLFxuICBzZWNyZXRfa2V5OiByZXF1aXJlKCcuL3NlY3JldF9rZXkuanMnKSxcbiAgdXNlcmlkOiByZXF1aXJlKCcuL3VzZXJpZC5qcycpLFxuICBzZWNyZXRfc3Via2V5OiByZXF1aXJlKCcuL3NlY3JldF9zdWJrZXkuanMnKSxcbiAgc2lnbmF0dXJlOiByZXF1aXJlKCcuL3NpZ25hdHVyZS5qcycpLFxuICB0cnVzdDogcmVxdWlyZSgnLi90cnVzdC5qcycpXG59XG5cbmZvciAodmFyIGkgaW4gZW51bXMucGFja2V0KSB7XG4gIHZhciBwYWNrZXRDbGFzcyA9IG1vZHVsZS5leHBvcnRzW2ldO1xuXG4gIGlmIChwYWNrZXRDbGFzcyAhPSB1bmRlZmluZWQpXG4gICAgcGFja2V0Q2xhc3MucHJvdG90eXBlLnRhZyA9IGVudW1zLnBhY2tldFtpXTtcbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG4gIEpYRyA9IHJlcXVpcmUoJy4uL2NvbXByZXNzaW9uL2p4Zy5qcycpLFxuICBiYXNlNjQgPSByZXF1aXJlKCcuLi9lbmNvZGluZy9iYXNlNjQuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIENvbXByZXNzZWQgRGF0YSBQYWNrZXQgKFRhZyA4KVxuICogXG4gKiBSRkM0ODgwIDUuNjpcbiAqIFRoZSBDb21wcmVzc2VkIERhdGEgcGFja2V0IGNvbnRhaW5zIGNvbXByZXNzZWQgZGF0YS4gIFR5cGljYWxseSwgdGhpc1xuICogcGFja2V0IGlzIGZvdW5kIGFzIHRoZSBjb250ZW50cyBvZiBhbiBlbmNyeXB0ZWQgcGFja2V0LCBvciBmb2xsb3dpbmdcbiAqIGEgU2lnbmF0dXJlIG9yIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQsIGFuZCBjb250YWlucyBhIGxpdGVyYWwgZGF0YVxuICogcGFja2V0LlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9jb21wcmVzc2VkKCkge1xuICAvKiogQHR5cGUge3BhY2tldGxpc3R9ICovXG4gIHRoaXMucGFja2V0cztcbiAgLyoqIEB0eXBlIHtjb21wcmVzc2lvbn0gKi9cbiAgdGhpcy5hbGdvcml0aG0gPSAndW5jb21wcmVzc2VkJztcblxuICB0aGlzLmNvbXByZXNzZWQgPSBudWxsO1xuXG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIHRoZSBwYWNrZXQuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIGEgdGFnIDggcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gUG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcbiAgICogQHBhckFNIHtpTlRFR0VSfSBMRU4gbEVOR1RIIE9GIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2YgXG4gICAqIGlucHV0IGF0IHBvc2l0aW9uXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2NvbXByZXNzZWR9IE9iamVjdCByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAvLyBPbmUgb2N0ZXQgdGhhdCBnaXZlcyB0aGUgYWxnb3JpdGhtIHVzZWQgdG8gY29tcHJlc3MgdGhlIHBhY2tldC5cbiAgICB0aGlzLmFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMuY29tcHJlc3Npb24sIGJ5dGVzLmNoYXJDb2RlQXQoMCkpO1xuXG4gICAgLy8gQ29tcHJlc3NlZCBkYXRhLCB3aGljaCBtYWtlcyB1cCB0aGUgcmVtYWluZGVyIG9mIHRoZSBwYWNrZXQuXG4gICAgdGhpcy5jb21wcmVzc2VkID0gYnl0ZXMuc3Vic3RyKDEpO1xuXG4gICAgdGhpcy5kZWNvbXByZXNzKCk7XG4gIH1cblxuXG5cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLmNvbXByZXNzZWQgPT0gbnVsbClcbiAgICAgIHRoaXMuY29tcHJlc3MoKTtcblxuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLmNvbXByZXNzaW9uLCB0aGlzLmFsZ29yaXRobSkpICsgdGhpcy5jb21wcmVzc2VkO1xuICB9XG5cblxuICAvKipcbiAgICogRGVjb21wcmVzc2lvbiBtZXRob2QgZm9yIGRlY29tcHJlc3NpbmcgdGhlIGNvbXByZXNzZWQgZGF0YVxuICAgKiByZWFkIGJ5IHJlYWRfcGFja2V0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIGRlY29tcHJlc3NlZCBkYXRhXG4gICAqL1xuICB0aGlzLmRlY29tcHJlc3MgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZGVjb21wcmVzc2VkO1xuXG4gICAgc3dpdGNoICh0aGlzLmFsZ29yaXRobSkge1xuICAgICAgY2FzZSAndW5jb21wcmVzc2VkJzpcbiAgICAgICAgZGVjb21wcmVzc2VkID0gdGhpcy5jb21wcmVzc2VkO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnemlwJzpcbiAgICAgICAgdmFyIGNvbXBEYXRhID0gdGhpcy5jb21wcmVzc2VkO1xuXG4gICAgICAgIHZhciByYWRpeCA9IGJhc2U2NC5lbmNvZGUoY29tcERhdGEpLnJlcGxhY2UoL1xcbi9nLCBcIlwiKTtcbiAgICAgICAgLy8gbm8gaGVhZGVyIGluIHRoaXMgY2FzZSwgZGlyZWN0bHkgY2FsbCBkZWZsYXRlXG4gICAgICAgIHZhciBqeGdfb2JqID0gbmV3IEpYRy5VdGlsLlVuemlwKEpYRy5VdGlsLkJhc2U2NC5kZWNvZGVBc0FycmF5KHJhZGl4KSk7XG5cbiAgICAgICAgZGVjb21wcmVzc2VkID0gdW5lc2NhcGUoanhnX29iai5kZWZsYXRlKClbMF1bMF0pO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnemxpYic6XG4gICAgICAgIC8vUkZDIDE5NTAuIEJpdHMgMC0zIENvbXByZXNzaW9uIE1ldGhvZFxuICAgICAgICB2YXIgY29tcHJlc3Npb25NZXRob2QgPSB0aGlzLmNvbXByZXNzZWQuY2hhckNvZGVBdCgwKSAlIDB4MTA7XG5cbiAgICAgICAgLy9CaXRzIDQtNyBSRkMgMTk1MCBhcmUgTFo3NyBXaW5kb3cuIEdlbmVyYWxseSB0aGlzIHZhbHVlIGlzIDcgPT0gMzJrIHdpbmRvdyBzaXplLlxuICAgICAgICAvLyAybmQgQnl0ZSBpbiBSRkMgMTk1MCBpcyBmb3IgXCJGTEFHc1wiIEFsbG93cyBmb3IgYSBEaWN0aW9uYXJ5IFxuICAgICAgICAvLyAoaG93IGlzIHRoaXMgZGVmaW5lZCkuIEJhc2ljIGNoZWNrc3VtLCBhbmQgY29tcHJlc3Npb24gbGV2ZWwuXG5cbiAgICAgICAgaWYgKGNvbXByZXNzaW9uTWV0aG9kID09IDgpIHsgLy9DTSA4IGlzIGZvciBERUZMQVRFLCBSRkMgMTk1MVxuICAgICAgICAgIC8vIHJlbW92ZSA0IGJ5dGVzIEFETEVSMzIgY2hlY2tzdW0gZnJvbSB0aGUgZW5kXG4gICAgICAgICAgdmFyIGNvbXBEYXRhID0gdGhpcy5jb21wcmVzc2VkLnN1YnN0cmluZygwLCB0aGlzLmNvbXByZXNzZWQubGVuZ3RoIC0gNCk7XG4gICAgICAgICAgdmFyIHJhZGl4ID0gYmFzZTY0LmVuY29kZShjb21wRGF0YSkucmVwbGFjZSgvXFxuL2csIFwiXCIpO1xuICAgICAgICAgIC8vVE9ETyBjaGVjayBBRExFUjMyIGNoZWNrc3VtXG4gICAgICAgICAgZGVjb21wcmVzc2VkID0gSlhHLmRlY29tcHJlc3MocmFkaXgpO1xuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSBaTElCIG9ubHkgc3VwcG9ydHMgXCIgK1xuICAgICAgICAgICAgXCJERUZMQVRFIGNvbXByZXNzaW9uIG1ldGhvZC5cIik7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2J6aXAyJzpcbiAgICAgICAgLy8gVE9ETzogbmVlZCB0byBpbXBsZW1lbnQgdGhpc1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbXByZXNzaW9uIGFsZ29yaXRobSBCWmlwMiBbQloyXSBpcyBub3QgaW1wbGVtZW50ZWQuJyk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb21wcmVzc2lvbiBhbGdvcml0aG0gdW5rbm93biA6XCIgKyB0aGlzLmFsb2dyaXRobSk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHRoaXMucGFja2V0cy5yZWFkKGRlY29tcHJlc3NlZCk7XG4gIH1cblxuICAvKipcbiAgICogQ29tcHJlc3MgdGhlIHBhY2tldCBkYXRhIChtZW1iZXIgZGVjb21wcmVzc2VkRGF0YSlcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSB0eXBlIEFsZ29yaXRobSB0byBiZSB1c2VkIC8vIFNlZSBSRkMgNDg4MCA5LjNcbiAgICogQHBhcmFtIHtTdHJpbmd9IGRhdGEgRGF0YSB0byBiZSBjb21wcmVzc2VkXG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIGNvbXByZXNzZWQgZGF0YSBzdG9yZWQgaW4gYXR0cmlidXRlIGNvbXByZXNzZWREYXRhXG4gICAqL1xuICB0aGlzLmNvbXByZXNzID0gZnVuY3Rpb24oKSB7XG4gICAgc3dpdGNoICh0aGlzLmFsZ29yaXRobSkge1xuXG4gICAgICBjYXNlICd1bmNvbXByZXNzZWQnOlxuICAgICAgICAvLyAtIFVuY29tcHJlc3NlZFxuICAgICAgICB0aGlzLmNvbXByZXNzZWQgPSB0aGlzLnBhY2tldHMud3JpdGUoKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3ppcCc6XG4gICAgICAgIC8vIC0gWklQIFtSRkMxOTUxXVxuICAgICAgICB1dGlsLnByaW50X2Vycm9yKFwiQ29tcHJlc3Npb24gYWxnb3JpdGhtIFpJUCBbUkZDMTk1MV0gaXMgbm90IGltcGxlbWVudGVkLlwiKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ3psaWInOlxuICAgICAgICAvLyAtIFpMSUIgW1JGQzE5NTBdXG4gICAgICAgIC8vIFRPRE86IG5lZWQgdG8gaW1wbGVtZW50IHRoaXNcbiAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIkNvbXByZXNzaW9uIGFsZ29yaXRobSBaTElCIFtSRkMxOTUwXSBpcyBub3QgaW1wbGVtZW50ZWQuXCIpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnYnppcDInOlxuICAgICAgICAvLyAgLSBCWmlwMiBbQloyXVxuICAgICAgICAvLyBUT0RPOiBuZWVkIHRvIGltcGxlbWVudCB0aGlzXG4gICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJDb21wcmVzc2lvbiBhbGdvcml0aG0gQlppcDIgW0JaMl0gaXMgbm90IGltcGxlbWVudGVkLlwiKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHV0aWwucHJpbnRfZXJyb3IoXCJDb21wcmVzc2lvbiBhbGdvcml0aG0gdW5rbm93biA6XCIgKyB0aGlzLnR5cGUpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn07XG4iLCJ2YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgbGlzdDogcmVxdWlyZSgnLi9wYWNrZXRsaXN0LmpzJyksXG59O1xuXG52YXIgcGFja2V0cyA9IHJlcXVpcmUoJy4vYWxsX3BhY2tldHMuanMnKTtcblxuZm9yICh2YXIgaSBpbiBwYWNrZXRzKVxuICBtb2R1bGUuZXhwb3J0c1tpXSA9IHBhY2tldHNbaV07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgTGl0ZXJhbCBEYXRhIFBhY2tldCAoVGFnIDExKVxuICogXG4gKiBSRkM0ODgwIDUuOTogQSBMaXRlcmFsIERhdGEgcGFja2V0IGNvbnRhaW5zIHRoZSBib2R5IG9mIGEgbWVzc2FnZTsgZGF0YSB0aGF0XG4gKiBpcyBub3QgdG8gYmUgZnVydGhlciBpbnRlcnByZXRlZC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfbGl0ZXJhbCgpIHtcbiAgdGhpcy5mb3JtYXQgPSAndXRmOCc7IC8vIGRlZmF1bHQgZm9ybWF0IGZvciBsaXRlcmFsIGRhdGEgcGFja2V0c1xuICB0aGlzLmRhdGEgPSAnJzsgLy8gbGl0ZXJhbCBkYXRhIHJlcHJlc2VudGF0aW9uIGFzIG5hdGl2ZSBKYXZhU2NyaXB0IHN0cmluZyBvciBieXRlc1xuICB0aGlzLmRhdGUgPSBuZXcgRGF0ZSgpO1xuXG5cbiAgLyoqXG4gICAqIFNldCB0aGUgcGFja2V0IGRhdGEgdG8gYSBqYXZhc2NyaXB0IG5hdGl2ZSBzdHJpbmcgb3IgYSBzcXVlbmNlIG9mIFxuICAgKiBieXRlcy4gQ29udmVyc2lvbiB0byB0aGUgcHJvdmlkZWQgZm9ybWF0IHRha2VzIHBsYWNlIHdoZW4gdGhlIFxuICAgKiBwYWNrZXQgaXMgd3JpdHRlbi5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBBbnkgbmF0aXZlIGphdmFzY3JpcHQgc3RyaW5nXG4gICAqIEBwYXJhbSB7J3V0Zjh8J2JpbmFyeSd8J3RleHQnfSBmb3JtYXQgVGhlIGZvcm1hdCB0aGUgcGFja2V0IGRhdGEgd2lsbCBiZSB3cml0dGVuIHRvLFxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdHMgdG8gJ3V0ZjgnXG4gICAqL1xuICB0aGlzLnNldCA9IGZ1bmN0aW9uKHN0ciwgZm9ybWF0KSB7XG4gICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQgfHwgdGhpcy5mb3JtYXQ7XG4gICAgdGhpcy5kYXRhID0gc3RyO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgcGFja2V0IGRhdGEgdG8gdmFsdWUgcmVwcmVzZW50ZWQgYnkgdGhlIHByb3ZpZGVkIHN0cmluZyBvZiBieXRlcy5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGJ5dGVzIFRoZSBzdHJpbmcgb2YgYnl0ZXNcbiAgICogQHBhcmFtIHsndXRmOHwnYmluYXJ5J3wndGV4dCd9IGZvcm1hdCBUaGUgZm9ybWF0IG9mIHRoZSBzdHJpbmcgb2YgYnl0ZXNcbiAgICovXG4gIHRoaXMuc2V0Qnl0ZXMgPSBmdW5jdGlvbihieXRlcywgZm9ybWF0KSB7XG4gICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgc3dpdGNoIChmb3JtYXQpIHtcbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgICBieXRlcyA9IHV0aWwuZGVjb2RlX3V0ZjgoYnl0ZXMpO1xuICAgICAgICBieXRlcyA9IGJ5dGVzLnJlcGxhY2UoL1xcclxcbi9nLCAnXFxuJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndGV4dCc6XG4gICAgICAgIGJ5dGVzID0gYnl0ZXMucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHRoaXMuZGF0YSA9IGJ5dGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgYnl0ZSBzZXF1ZW5jZSByZXByZXNlbnRpbmcgdGhlIGxpdGVyYWwgcGFja2V0IGRhdGFcbiAgICogQHJldHVybnMge1N0cmluZ30gQSBzZXF1ZW5jZSBvZiBieXRlc1xuICAgKi9cbiAgdGhpcy5nZXRCeXRlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBieXRlcyA9IHRoaXMuZGF0YTtcbiAgICBzd2l0Y2ggKHRoaXMuZm9ybWF0KSB7XG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgICAgYnl0ZXMgPSBieXRlcy5yZXBsYWNlKC9cXG4vZywgJ1xcclxcbicpO1xuICAgICAgICBieXRlcyA9IHV0aWwuZW5jb2RlX3V0ZjgoYnl0ZXMpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RleHQnOlxuICAgICAgICBieXRlcyA9IGJ5dGVzLnJlcGxhY2UoL1xcbi9nLCAnXFxyXFxuJyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuXG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgbGl0ZXJhbCBkYXRhIHBhY2tldCAodGFnIDExKS5cbiAgICogXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIGEgdGFnIDExIHBhY2tldFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uXG4gICAqICAgICAgICAgICAgUG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5cbiAgICogICAgICAgICAgICBMZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZlxuICAgKiAgICAgICAgICAgIGlucHV0IGF0IHBvc2l0aW9uXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IG9iamVjdCByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAvLyAtIEEgb25lLW9jdGV0IGZpZWxkIHRoYXQgZGVzY3JpYmVzIGhvdyB0aGUgZGF0YSBpcyBmb3JtYXR0ZWQuXG5cbiAgICB2YXIgZm9ybWF0ID0gZW51bXMucmVhZChlbnVtcy5saXRlcmFsLCBieXRlc1swXS5jaGFyQ29kZUF0KCkpO1xuXG4gICAgdmFyIGZpbGVuYW1lX2xlbiA9IGJ5dGVzLmNoYXJDb2RlQXQoMSk7XG4gICAgdGhpcy5maWxlbmFtZSA9IHV0aWwuZGVjb2RlX3V0ZjgoYnl0ZXMuc3Vic3RyKDIsIGZpbGVuYW1lX2xlbikpO1xuXG4gICAgdGhpcy5kYXRlID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIoMiArIGZpbGVuYW1lX2xlbiwgNCkpO1xuXG4gICAgdmFyIGRhdGEgPSBieXRlcy5zdWJzdHJpbmcoNiArIGZpbGVuYW1lX2xlbik7XG5cbiAgICB0aGlzLnNldEJ5dGVzKGRhdGEsIGZvcm1hdCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgcGFja2V0XG4gICAqIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBUaGUgZGF0YSB0byBiZSBpbnNlcnRlZCBhcyBib2R5XG4gICAqIEByZXR1cm4ge1N0cmluZ30gc3RyaW5nLXJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYWNrZXRcbiAgICovXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZmlsZW5hbWUgPSB1dGlsLmVuY29kZV91dGY4KFwibXNnLnR4dFwiKTtcblxuICAgIHZhciBkYXRhID0gdGhpcy5nZXRCeXRlcygpO1xuXG4gICAgdmFyIHJlc3VsdCA9ICcnO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLmxpdGVyYWwsIHRoaXMuZm9ybWF0KSk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoZmlsZW5hbWUubGVuZ3RoKTtcbiAgICByZXN1bHQgKz0gZmlsZW5hbWU7XG4gICAgcmVzdWx0ICs9IHV0aWwud3JpdGVEYXRlKHRoaXMuZGF0ZSk7XG4gICAgcmVzdWx0ICs9IGRhdGE7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIHN0cmFuZ2UgXCJNYXJrZXIgcGFja2V0XCIgKFRhZyAxMClcbiAqIFxuICogUkZDNDg4MCA1Ljg6IEFuIGV4cGVyaW1lbnRhbCB2ZXJzaW9uIG9mIFBHUCB1c2VkIHRoaXMgcGFja2V0IGFzIHRoZSBMaXRlcmFsXG4gKiBwYWNrZXQsIGJ1dCBubyByZWxlYXNlZCB2ZXJzaW9uIG9mIFBHUCBnZW5lcmF0ZWQgTGl0ZXJhbCBwYWNrZXRzIHdpdGggdGhpc1xuICogdGFnLiBXaXRoIFBHUCA1LngsIHRoaXMgcGFja2V0IGhhcyBiZWVuIHJlYXNzaWduZWQgYW5kIGlzIHJlc2VydmVkIGZvciB1c2UgYXNcbiAqIHRoZSBNYXJrZXIgcGFja2V0LlxuICogXG4gKiBTdWNoIGEgcGFja2V0IE1VU1QgYmUgaWdub3JlZCB3aGVuIHJlY2VpdmVkLlxuICovXG5mdW5jdGlvbiBwYWNrZXRfbWFya2VyKCkge1xuICAvKipcbiAgICogUGFyc2luZyBmdW5jdGlvbiBmb3IgYSBsaXRlcmFsIGRhdGEgcGFja2V0ICh0YWcgMTApLlxuICAgKiBcbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFBheWxvYWQgb2YgYSB0YWcgMTAgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb25cbiAgICogICAgICAgICAgICBQb3NpdGlvbiB0byBzdGFydCByZWFkaW5nIGZyb20gdGhlIGlucHV0IHN0cmluZ1xuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlblxuICAgKiAgICAgICAgICAgIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mXG4gICAqICAgICAgICAgICAgaW5wdXQgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YX0gT2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIGlmIChieXRlc1swXS5jaGFyQ29kZUF0KCkgPT0gMHg1MCAmJiAvLyBQXG4gICAgYnl0ZXNbMV0uY2hhckNvZGVBdCgpID09IDB4NDcgJiYgLy8gR1xuICAgIGJ5dGVzWzJdLmNoYXJDb2RlQXQoKSA9PSAweDUwKSAvLyBQXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICAvLyBtYXJrZXIgcGFja2V0IGRvZXMgbm90IGNvbnRhaW4gXCJQR1BcIlxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHBhY2tldF9tYXJrZXI7XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgT25lLVBhc3MgU2lnbmF0dXJlIFBhY2tldHMgKFRhZyA0KVxuICogXG4gKiBSRkM0ODgwIDUuNDpcbiAqIFRoZSBPbmUtUGFzcyBTaWduYXR1cmUgcGFja2V0IHByZWNlZGVzIHRoZSBzaWduZWQgZGF0YSBhbmQgY29udGFpbnNcbiAqIGVub3VnaCBpbmZvcm1hdGlvbiB0byBhbGxvdyB0aGUgcmVjZWl2ZXIgdG8gYmVnaW4gY2FsY3VsYXRpbmcgYW55XG4gKiBoYXNoZXMgbmVlZGVkIHRvIHZlcmlmeSB0aGUgc2lnbmF0dXJlLiAgSXQgYWxsb3dzIHRoZSBTaWduYXR1cmVcbiAqIHBhY2tldCB0byBiZSBwbGFjZWQgYXQgdGhlIGVuZCBvZiB0aGUgbWVzc2FnZSwgc28gdGhhdCB0aGUgc2lnbmVyXG4gKiBjYW4gY29tcHV0ZSB0aGUgZW50aXJlIHNpZ25lZCBtZXNzYWdlIGluIG9uZSBwYXNzLlxuICovXG5cbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG4gIHR5cGVfa2V5aWQgPSByZXF1aXJlKCcuLi90eXBlL2tleWlkLmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X29uZV9wYXNzX3NpZ25hdHVyZSgpIHtcbiAgdGhpcy52ZXJzaW9uID0gbnVsbDsgLy8gQSBvbmUtb2N0ZXQgdmVyc2lvbiBudW1iZXIuICBUaGUgY3VycmVudCB2ZXJzaW9uIGlzIDMuXG4gIHRoaXMudHlwZSA9IG51bGw7IC8vIEEgb25lLW9jdGV0IHNpZ25hdHVyZSB0eXBlLiAgU2lnbmF0dXJlIHR5cGVzIGFyZSBkZXNjcmliZWQgaW4gUkZDNDg4MCBTZWN0aW9uIDUuMi4xLlxuICB0aGlzLmhhc2hBbGdvcml0aG0gPSBudWxsOyAvLyBBIG9uZS1vY3RldCBudW1iZXIgZGVzY3JpYmluZyB0aGUgaGFzaCBhbGdvcml0aG0gdXNlZC4gKFNlZSBSRkM0ODgwIDkuNClcbiAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSBudWxsOyAvLyBBIG9uZS1vY3RldCBudW1iZXIgZGVzY3JpYmluZyB0aGUgcHVibGljLWtleSBhbGdvcml0aG0gdXNlZC4gKFNlZSBSRkM0ODgwIDkuMSlcbiAgdGhpcy5zaWduaW5nS2V5SWQgPSBudWxsOyAvLyBBbiBlaWdodC1vY3RldCBudW1iZXIgaG9sZGluZyB0aGUgS2V5IElEIG9mIHRoZSBzaWduaW5nIGtleS5cbiAgdGhpcy5mbGFncyA9IG51bGw7IC8vICBBIG9uZS1vY3RldCBudW1iZXIgaG9sZGluZyBhIGZsYWcgc2hvd2luZyB3aGV0aGVyIHRoZSBzaWduYXR1cmUgaXMgbmVzdGVkLiAgQSB6ZXJvIHZhbHVlIGluZGljYXRlcyB0aGF0IHRoZSBuZXh0IHBhY2tldCBpcyBhbm90aGVyIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQgdGhhdCBkZXNjcmliZXMgYW5vdGhlciBzaWduYXR1cmUgdG8gYmUgYXBwbGllZCB0byB0aGUgc2FtZSBtZXNzYWdlIGRhdGEuXG5cbiAgLyoqXG4gICAqIHBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgb25lLXBhc3Mgc2lnbmF0dXJlIHBhY2tldCAodGFnIDQpLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gYnl0ZXMgcGF5bG9hZCBvZiBhIHRhZyA0IHBhY2tldFxuICAgKiBAcmV0dXJuIHtwYWNrZXRfb25lX3Bhc3Nfc2lnbmF0dXJlfSBvYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIG15cG9zID0gMDtcbiAgICAvLyBBIG9uZS1vY3RldCB2ZXJzaW9uIG51bWJlci4gIFRoZSBjdXJyZW50IHZlcnNpb24gaXMgMy5cbiAgICB0aGlzLnZlcnNpb24gPSBieXRlcy5jaGFyQ29kZUF0KG15cG9zKyspO1xuXG4gICAgLy8gQSBvbmUtb2N0ZXQgc2lnbmF0dXJlIHR5cGUuICBTaWduYXR1cmUgdHlwZXMgYXJlIGRlc2NyaWJlZCBpblxuICAgIC8vICAgU2VjdGlvbiA1LjIuMS5cbiAgICB0aGlzLnR5cGUgPSBlbnVtcy5yZWFkKGVudW1zLnNpZ25hdHVyZSwgYnl0ZXMuY2hhckNvZGVBdChteXBvcysrKSk7XG5cbiAgICAvLyBBIG9uZS1vY3RldCBudW1iZXIgZGVzY3JpYmluZyB0aGUgaGFzaCBhbGdvcml0aG0gdXNlZC5cbiAgICB0aGlzLmhhc2hBbGdvcml0aG0gPSBlbnVtcy5yZWFkKGVudW1zLmhhc2gsIGJ5dGVzLmNoYXJDb2RlQXQobXlwb3MrKykpO1xuXG4gICAgLy8gQSBvbmUtb2N0ZXQgbnVtYmVyIGRlc2NyaWJpbmcgdGhlIHB1YmxpYy1rZXkgYWxnb3JpdGhtIHVzZWQuXG4gICAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSBlbnVtcy5yZWFkKGVudW1zLnB1YmxpY0tleSwgYnl0ZXMuY2hhckNvZGVBdChteXBvcysrKSk7XG5cbiAgICAvLyBBbiBlaWdodC1vY3RldCBudW1iZXIgaG9sZGluZyB0aGUgS2V5IElEIG9mIHRoZSBzaWduaW5nIGtleS5cbiAgICB0aGlzLnNpZ25pbmdLZXlJZCA9IG5ldyB0eXBlX2tleWlkKCk7XG4gICAgdGhpcy5zaWduaW5nS2V5SWQucmVhZChieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICBteXBvcyArPSA4O1xuXG4gICAgLy8gQSBvbmUtb2N0ZXQgbnVtYmVyIGhvbGRpbmcgYSBmbGFnIHNob3dpbmcgd2hldGhlciB0aGUgc2lnbmF0dXJlXG4gICAgLy8gICBpcyBuZXN0ZWQuICBBIHplcm8gdmFsdWUgaW5kaWNhdGVzIHRoYXQgdGhlIG5leHQgcGFja2V0IGlzXG4gICAgLy8gICBhbm90aGVyIE9uZS1QYXNzIFNpZ25hdHVyZSBwYWNrZXQgdGhhdCBkZXNjcmliZXMgYW5vdGhlclxuICAgIC8vICAgc2lnbmF0dXJlIHRvIGJlIGFwcGxpZWQgdG8gdGhlIHNhbWUgbWVzc2FnZSBkYXRhLlxuICAgIHRoaXMuZmxhZ3MgPSBieXRlcy5jaGFyQ29kZUF0KG15cG9zKyspO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIGNyZWF0ZXMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBvbmUtcGFzcyBzaWduYXR1cmUgcGFja2V0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSBvbmUtcGFzcyBzaWduYXR1cmUgcGFja2V0XG4gICAqL1xuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHJlc3VsdCA9IFwiXCI7XG5cbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgzKTtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5zaWduYXR1cmUsIHRoaXMudHlwZSkpO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLmhhc2gsIHRoaXMuaGFzaEFsZ29yaXRobSkpO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLnB1YmxpY0tleSwgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0pKTtcbiAgICByZXN1bHQgKz0gdGhpcy5zaWduaW5nS2V5SWQud3JpdGUoKTtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLmZsYWdzKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICByZWFkU2ltcGxlTGVuZ3RoOiBmdW5jdGlvbihieXRlcykge1xuICAgIHZhciBsZW4gPSAwLFxuICAgICAgb2Zmc2V0LFxuICAgICAgdHlwZSA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcblxuXG4gICAgaWYgKHR5cGUgPCAxOTIpIHtcbiAgICAgIGxlbiA9IGJ5dGVzWzBdLmNoYXJDb2RlQXQoKTtcbiAgICAgIG9mZnNldCA9IDE7XG4gICAgfSBlbHNlIGlmICh0eXBlIDwgMjU1KSB7XG4gICAgICBsZW4gPSAoKGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSAtIDE5MikgPDwgOCkgKyAoYnl0ZXNbMV0uY2hhckNvZGVBdCgpKSArIDE5MjtcbiAgICAgIG9mZnNldCA9IDI7XG4gICAgfSBlbHNlIGlmICh0eXBlID09IDI1NSkge1xuICAgICAgbGVuID0gdXRpbC5yZWFkTnVtYmVyKGJ5dGVzLnN1YnN0cigxLCA0KSk7XG4gICAgICBvZmZzZXQgPSA1O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBsZW46IGxlbixcbiAgICAgIG9mZnNldDogb2Zmc2V0XG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogRW5jb2RlcyBhIGdpdmVuIGludGVnZXIgb2YgbGVuZ3RoIHRvIHRoZSBvcGVucGdwIGxlbmd0aCBzcGVjaWZpZXIgdG8gYVxuICAgKiBzdHJpbmdcbiAgICogXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuZ3RoIFRoZSBsZW5ndGggdG8gZW5jb2RlXG4gICAqIEByZXR1cm4ge1N0cmluZ30gU3RyaW5nIHdpdGggb3BlbnBncCBsZW5ndGggcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHdyaXRlU2ltcGxlTGVuZ3RoOiBmdW5jdGlvbihsZW5ndGgpIHtcbiAgICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgICBpZiAobGVuZ3RoIDwgMTkyKSB7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShsZW5ndGgpO1xuICAgIH0gZWxzZSBpZiAobGVuZ3RoID4gMTkxICYmIGxlbmd0aCA8IDgzODQpIHtcbiAgICAgIC8qXG4gICAgICAgKiBsZXQgYSA9ICh0b3RhbCBkYXRhIHBhY2tldCBsZW5ndGgpIC0gMTkyIGxldCBiYyA9IHR3byBvY3RldFxuICAgICAgICogcmVwcmVzZW50YXRpb24gb2YgYSBsZXQgZCA9IGIgKyAxOTJcbiAgICAgICAqL1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKChsZW5ndGggLSAxOTIpID4+IDgpICsgMTkyKTtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKChsZW5ndGggLSAxOTIpICYgMHhGRik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDI1NSk7XG4gICAgICByZXN1bHQgKz0gdXRpbC53cml0ZU51bWJlcihsZW5ndGgsIDQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIC8qKlxuICAgKiBXcml0ZXMgYSBwYWNrZXQgaGVhZGVyIHZlcnNpb24gNCB3aXRoIHRoZSBnaXZlbiB0YWdfdHlwZSBhbmQgbGVuZ3RoIHRvIGFcbiAgICogc3RyaW5nXG4gICAqIFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHRhZ190eXBlIFRhZyB0eXBlXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuZ3RoIExlbmd0aCBvZiB0aGUgcGF5bG9hZFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFN0cmluZyBvZiB0aGUgaGVhZGVyXG4gICAqL1xuICB3cml0ZUhlYWRlcjogZnVuY3Rpb24odGFnX3R5cGUsIGxlbmd0aCkge1xuICAgIC8qIHdlJ3JlIG9ubHkgZ2VuZXJhdGluZyB2NCBwYWNrZXQgaGVhZGVycyBoZXJlICovXG4gICAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhDMCB8IHRhZ190eXBlKTtcbiAgICByZXN1bHQgKz0gdGhpcy53cml0ZVNpbXBsZUxlbmd0aChsZW5ndGgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgLyoqXG4gICAqIFdyaXRlcyBhIHBhY2tldCBoZWFkZXIgVmVyc2lvbiAzIHdpdGggdGhlIGdpdmVuIHRhZ190eXBlIGFuZCBsZW5ndGggdG8gYVxuICAgKiBzdHJpbmdcbiAgICogXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gdGFnX3R5cGUgVGFnIHR5cGVcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW5ndGggTGVuZ3RoIG9mIHRoZSBwYXlsb2FkXG4gICAqIEByZXR1cm4ge1N0cmluZ30gU3RyaW5nIG9mIHRoZSBoZWFkZXJcbiAgICovXG4gIHdyaXRlT2xkSGVhZGVyOiBmdW5jdGlvbih0YWdfdHlwZSwgbGVuZ3RoKSB7XG4gICAgdmFyIHJlc3VsdCA9IFwiXCI7XG4gICAgaWYgKGxlbmd0aCA8IDI1Nikge1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHg4MCB8ICh0YWdfdHlwZSA8PCAyKSk7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShsZW5ndGgpO1xuICAgIH0gZWxzZSBpZiAobGVuZ3RoIDwgNjU1MzYpIHtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4ODAgfCAodGFnX3R5cGUgPDwgMikgfCAxKTtcbiAgICAgIHJlc3VsdCArPSB1dGlsLndyaXRlTnVtYmVyKGxlbmd0aCwgMik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4ODAgfCAodGFnX3R5cGUgPDwgMikgfCAyKTtcbiAgICAgIHJlc3VsdCArPSB1dGlsLndyaXRlTnVtYmVyKGxlbmd0aCwgNCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgLyoqXG4gICAqIEdlbmVyaWMgc3RhdGljIFBhY2tldCBQYXJzZXIgZnVuY3Rpb25cbiAgICogXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBJbnB1dCBzdHJlYW0gYXMgc3RyaW5nXG4gICAqIEBwYXJhbSB7aW50ZWdlcn0gcG9zaXRpb24gUG9zaXRpb24gdG8gc3RhcnQgcGFyc2luZ1xuICAgKiBAcGFyYW0ge2ludGVnZXJ9IGxlbiBMZW5ndGggb2YgdGhlIGlucHV0IGZyb20gcG9zaXRpb24gb25cbiAgICogQHJldHVybiB7T2JqZWN0fSBSZXR1cm5zIGEgcGFyc2VkIG9wZW5wZ3BfcGFja2V0XG4gICAqL1xuICByZWFkOiBmdW5jdGlvbihpbnB1dCwgcG9zaXRpb24sIGxlbikge1xuICAgIC8vIHNvbWUgc2FuaXR5IGNoZWNrc1xuICAgIGlmIChpbnB1dCA9PSBudWxsIHx8IGlucHV0Lmxlbmd0aCA8PSBwb3NpdGlvbiB8fCBpbnB1dC5zdWJzdHJpbmcocG9zaXRpb24pLmxlbmd0aCA8IDIgfHwgKGlucHV0W3Bvc2l0aW9uXS5jaGFyQ29kZUF0KCkgJlxuICAgICAgMHg4MCkgPT0gMCkge1xuICAgICAgdXRpbFxuICAgICAgICAucHJpbnRfZXJyb3IoXCJFcnJvciBkdXJpbmcgcGFyc2luZy4gVGhpcyBtZXNzYWdlIC8ga2V5IGlzIHByb2JhYmx5IG5vdCBjb250YWluaW5nIGEgdmFsaWQgT3BlblBHUCBmb3JtYXQuXCIpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciBteXBvcyA9IHBvc2l0aW9uO1xuICAgIHZhciB0YWcgPSAtMTtcbiAgICB2YXIgZm9ybWF0ID0gLTE7XG4gICAgdmFyIHBhY2tldF9sZW5ndGg7XG5cbiAgICBmb3JtYXQgPSAwOyAvLyAwID0gb2xkIGZvcm1hdDsgMSA9IG5ldyBmb3JtYXRcbiAgICBpZiAoKGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDQwKSAhPSAwKSB7XG4gICAgICBmb3JtYXQgPSAxO1xuICAgIH1cblxuICAgIHZhciBwYWNrZXRfbGVuZ3RoX3R5cGU7XG4gICAgaWYgKGZvcm1hdCkge1xuICAgICAgLy8gbmV3IGZvcm1hdCBoZWFkZXJcbiAgICAgIHRhZyA9IGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDNGOyAvLyBiaXQgNS0wXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIG9sZCBmb3JtYXQgaGVhZGVyXG4gICAgICB0YWcgPSAoaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSAmIDB4M0YpID4+IDI7IC8vIGJpdCA1LTJcbiAgICAgIHBhY2tldF9sZW5ndGhfdHlwZSA9IGlucHV0W215cG9zXS5jaGFyQ29kZUF0KCkgJiAweDAzOyAvLyBiaXQgMS0wXG4gICAgfVxuXG4gICAgLy8gaGVhZGVyIG9jdGV0IHBhcnNpbmcgZG9uZVxuICAgIG15cG9zKys7XG5cbiAgICAvLyBwYXJzZWQgbGVuZ3RoIGZyb20gbGVuZ3RoIGZpZWxkXG4gICAgdmFyIGJvZHlkYXRhID0gbnVsbDtcblxuICAgIC8vIHVzZWQgZm9yIHBhcnRpYWwgYm9keSBsZW5ndGhzXG4gICAgdmFyIHJlYWxfcGFja2V0X2xlbmd0aCA9IC0xO1xuICAgIGlmICghZm9ybWF0KSB7XG4gICAgICAvLyA0LjIuMS4gT2xkIEZvcm1hdCBQYWNrZXQgTGVuZ3Roc1xuICAgICAgc3dpdGNoIChwYWNrZXRfbGVuZ3RoX3R5cGUpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIC8vIFRoZSBwYWNrZXQgaGFzIGEgb25lLW9jdGV0IGxlbmd0aC4gVGhlIGhlYWRlciBpcyAyIG9jdGV0c1xuICAgICAgICAgIC8vIGxvbmcuXG4gICAgICAgICAgcGFja2V0X2xlbmd0aCA9IGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIC8vIFRoZSBwYWNrZXQgaGFzIGEgdHdvLW9jdGV0IGxlbmd0aC4gVGhlIGhlYWRlciBpcyAzIG9jdGV0c1xuICAgICAgICAgIC8vIGxvbmcuXG4gICAgICAgICAgcGFja2V0X2xlbmd0aCA9IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDwgOCkgfCBpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAvLyBUaGUgcGFja2V0IGhhcyBhIGZvdXItb2N0ZXQgbGVuZ3RoLiBUaGUgaGVhZGVyIGlzIDVcbiAgICAgICAgICAvLyBvY3RldHMgbG9uZy5cbiAgICAgICAgICBwYWNrZXRfbGVuZ3RoID0gKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCAyNCkgfCAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpIDw8IDE2KSB8IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDxcbiAgICAgICAgICAgIDgpIHwgaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIC8vIDMgLSBUaGUgcGFja2V0IGlzIG9mIGluZGV0ZXJtaW5hdGUgbGVuZ3RoLiBUaGUgaGVhZGVyIGlzIDFcbiAgICAgICAgICAvLyBvY3RldCBsb25nLCBhbmQgdGhlIGltcGxlbWVudGF0aW9uIG11c3QgZGV0ZXJtaW5lIGhvdyBsb25nXG4gICAgICAgICAgLy8gdGhlIHBhY2tldCBpcy4gSWYgdGhlIHBhY2tldCBpcyBpbiBhIGZpbGUsIHRoaXMgbWVhbnMgdGhhdFxuICAgICAgICAgIC8vIHRoZSBwYWNrZXQgZXh0ZW5kcyB1bnRpbCB0aGUgZW5kIG9mIHRoZSBmaWxlLiBJbiBnZW5lcmFsLCBcbiAgICAgICAgICAvLyBhbiBpbXBsZW1lbnRhdGlvbiBTSE9VTEQgTk9UIHVzZSBpbmRldGVybWluYXRlLWxlbmd0aCBcbiAgICAgICAgICAvLyBwYWNrZXRzIGV4Y2VwdCB3aGVyZSB0aGUgZW5kIG9mIHRoZSBkYXRhIHdpbGwgYmUgY2xlYXIgXG4gICAgICAgICAgLy8gZnJvbSB0aGUgY29udGV4dCwgYW5kIGV2ZW4gdGhlbiBpdCBpcyBiZXR0ZXIgdG8gdXNlIGEgXG4gICAgICAgICAgLy8gZGVmaW5pdGUgbGVuZ3RoLCBvciBhIG5ldyBmb3JtYXQgaGVhZGVyLiBUaGUgbmV3IGZvcm1hdCBcbiAgICAgICAgICAvLyBoZWFkZXJzIGRlc2NyaWJlZCBiZWxvdyBoYXZlIGEgbWVjaGFuaXNtIGZvciBwcmVjaXNlbHlcbiAgICAgICAgICAvLyBlbmNvZGluZyBkYXRhIG9mIGluZGV0ZXJtaW5hdGUgbGVuZ3RoLlxuICAgICAgICAgIHBhY2tldF9sZW5ndGggPSBsZW47XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICB9IGVsc2UgLy8gNC4yLjIuIE5ldyBGb3JtYXQgUGFja2V0IExlbmd0aHNcbiAgICB7XG5cbiAgICAgIC8vIDQuMi4yLjEuIE9uZS1PY3RldCBMZW5ndGhzXG4gICAgICBpZiAoaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSA8IDE5Mikge1xuICAgICAgICBwYWNrZXRfbGVuZ3RoID0gaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICB1dGlsLnByaW50X2RlYnVnKFwiMSBieXRlIGxlbmd0aDpcIiArIHBhY2tldF9sZW5ndGgpO1xuICAgICAgICAvLyA0LjIuMi4yLiBUd28tT2N0ZXQgTGVuZ3Roc1xuICAgICAgfSBlbHNlIGlmIChpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpID49IDE5MiAmJiBpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpIDwgMjI0KSB7XG4gICAgICAgIHBhY2tldF9sZW5ndGggPSAoKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSAtIDE5MikgPDwgOCkgKyAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpKSArIDE5MjtcbiAgICAgICAgdXRpbC5wcmludF9kZWJ1ZyhcIjIgYnl0ZSBsZW5ndGg6XCIgKyBwYWNrZXRfbGVuZ3RoKTtcbiAgICAgICAgLy8gNC4yLjIuNC4gUGFydGlhbCBCb2R5IExlbmd0aHNcbiAgICAgIH0gZWxzZSBpZiAoaW5wdXRbbXlwb3NdLmNoYXJDb2RlQXQoKSA+IDIyMyAmJiBpbnB1dFtteXBvc10uY2hhckNvZGVBdCgpIDwgMjU1KSB7XG4gICAgICAgIHBhY2tldF9sZW5ndGggPSAxIDw8IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgJiAweDFGKTtcbiAgICAgICAgdXRpbC5wcmludF9kZWJ1ZyhcIjQgYnl0ZSBsZW5ndGg6XCIgKyBwYWNrZXRfbGVuZ3RoKTtcbiAgICAgICAgLy8gRUVFSywgd2UncmUgcmVhZGluZyB0aGUgZnVsbCBkYXRhIGhlcmUuLi5cbiAgICAgICAgdmFyIG15cG9zMiA9IG15cG9zICsgcGFja2V0X2xlbmd0aDtcbiAgICAgICAgYm9keWRhdGEgPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MsIG15cG9zICsgcGFja2V0X2xlbmd0aCk7XG4gICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgaWYgKGlucHV0W215cG9zMl0uY2hhckNvZGVBdCgpIDwgMTkyKSB7XG4gICAgICAgICAgICB2YXIgdG1wbGVuID0gaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgICAgIHBhY2tldF9sZW5ndGggKz0gdG1wbGVuO1xuICAgICAgICAgICAgYm9keWRhdGEgKz0gaW5wdXQuc3Vic3RyaW5nKG15cG9zMiwgbXlwb3MyICsgdG1wbGVuKTtcbiAgICAgICAgICAgIG15cG9zMiArPSB0bXBsZW47XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9IGVsc2UgaWYgKGlucHV0W215cG9zMl0uY2hhckNvZGVBdCgpID49IDE5MiAmJiBpbnB1dFtteXBvczJdLmNoYXJDb2RlQXQoKSA8IDIyNCkge1xuICAgICAgICAgICAgdmFyIHRtcGxlbiA9ICgoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSAtIDE5MikgPDwgOCkgKyAoaW5wdXRbbXlwb3MyKytdLmNoYXJDb2RlQXQoKSkgKyAxOTI7XG4gICAgICAgICAgICBwYWNrZXRfbGVuZ3RoICs9IHRtcGxlbjtcbiAgICAgICAgICAgIGJvZHlkYXRhICs9IGlucHV0LnN1YnN0cmluZyhteXBvczIsIG15cG9zMiArIHRtcGxlbik7XG4gICAgICAgICAgICBteXBvczIgKz0gdG1wbGVuO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfSBlbHNlIGlmIChpbnB1dFtteXBvczJdLmNoYXJDb2RlQXQoKSA+IDIyMyAmJiBpbnB1dFtteXBvczJdLmNoYXJDb2RlQXQoKSA8IDI1NSkge1xuICAgICAgICAgICAgdmFyIHRtcGxlbiA9IDEgPDwgKGlucHV0W215cG9zMisrXS5jaGFyQ29kZUF0KCkgJiAweDFGKTtcbiAgICAgICAgICAgIHBhY2tldF9sZW5ndGggKz0gdG1wbGVuO1xuICAgICAgICAgICAgYm9keWRhdGEgKz0gaW5wdXQuc3Vic3RyaW5nKG15cG9zMiwgbXlwb3MyICsgdG1wbGVuKTtcbiAgICAgICAgICAgIG15cG9zMiArPSB0bXBsZW47XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG15cG9zMisrO1xuICAgICAgICAgICAgdmFyIHRtcGxlbiA9IChpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpIDw8IDI0KSB8IChpbnB1dFtteXBvczIrK10uY2hhckNvZGVBdCgpIDw8IDE2KSB8IChpbnB1dFtteXBvczIrK11cbiAgICAgICAgICAgICAgLmNoYXJDb2RlQXQoKSA8PCA4KSB8IGlucHV0W215cG9zMisrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgICAgICBib2R5ZGF0YSArPSBpbnB1dC5zdWJzdHJpbmcobXlwb3MyLCBteXBvczIgKyB0bXBsZW4pO1xuICAgICAgICAgICAgcGFja2V0X2xlbmd0aCArPSB0bXBsZW47XG4gICAgICAgICAgICBteXBvczIgKz0gdG1wbGVuO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlYWxfcGFja2V0X2xlbmd0aCA9IG15cG9zMjtcbiAgICAgICAgLy8gNC4yLjIuMy4gRml2ZS1PY3RldCBMZW5ndGhzXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBteXBvcysrO1xuICAgICAgICBwYWNrZXRfbGVuZ3RoID0gKGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKSA8PCAyNCkgfCAoaW5wdXRbbXlwb3MrK10uY2hhckNvZGVBdCgpIDw8IDE2KSB8IChpbnB1dFtteXBvcysrXS5jaGFyQ29kZUF0KCkgPDxcbiAgICAgICAgICA4KSB8IGlucHV0W215cG9zKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpZiB0aGVyZSB3YXMnbnQgYSBwYXJ0aWFsIGJvZHkgbGVuZ3RoOiB1c2UgdGhlIHNwZWNpZmllZFxuICAgIC8vIHBhY2tldF9sZW5ndGhcbiAgICBpZiAocmVhbF9wYWNrZXRfbGVuZ3RoID09IC0xKSB7XG4gICAgICByZWFsX3BhY2tldF9sZW5ndGggPSBwYWNrZXRfbGVuZ3RoO1xuICAgIH1cblxuICAgIGlmIChib2R5ZGF0YSA9PSBudWxsKSB7XG4gICAgICBib2R5ZGF0YSA9IGlucHV0LnN1YnN0cmluZyhteXBvcywgbXlwb3MgKyByZWFsX3BhY2tldF9sZW5ndGgpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0YWc6IHRhZyxcbiAgICAgIHBhY2tldDogYm9keWRhdGEsXG4gICAgICBvZmZzZXQ6IG15cG9zICsgcmVhbF9wYWNrZXRfbGVuZ3RoXG4gICAgfTtcbiAgfVxufVxuIiwidmFyIHBhY2tldFBhcnNlciA9IHJlcXVpcmUoJy4vcGFja2V0LmpzJyksXG4gIHBhY2tldHMgPSByZXF1aXJlKCcuL2FsbF9wYWNrZXRzLmpzJyksXG4gIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgVGhpcyBjbGFzcyByZXByZXNlbnRzIGEgbGlzdCBvZiBvcGVucGdwIHBhY2tldHMuXG4gKiBUYWtlIGNhcmUgd2hlbiBpdGVyYXRpbmcgb3ZlciBpdCAtIHRoZSBwYWNrZXRzIHRoZW1zZWx2ZXNcbiAqIGFyZSBzdG9yZWQgYXMgbnVtZXJpY2FsIGluZGljZXMuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0bGlzdCgpIHtcbiAgLyoqIFRoZSBudW1iZXIgb2YgcGFja2V0cyBjb250YWluZWQgd2l0aGluIHRoZSBsaXN0LlxuICAgKiBAcmVhZG9ubHlcbiAgICogQHR5cGUge0ludGVnZXJ9ICovXG4gIHRoaXMubGVuZ3RoID0gMDtcblxuICAvKipcbiAgICogUmVhZHMgYSBzdHJlYW0gb2YgYmluYXJ5IGRhdGEgYW5kIGludGVycHJlbnRzIGl0IGFzIGEgbGlzdCBvZiBwYWNrZXRzLlxuICAgKiBAcGFyYW0ge29wZW5wZ3BfYnl0ZWFycmF5fSBBbiBhcnJheSBvZiBieXRlcy5cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIGkgPSAwO1xuXG4gICAgd2hpbGUgKGkgPCBieXRlcy5sZW5ndGgpIHtcbiAgICAgIHZhciBwYXJzZWQgPSBwYWNrZXRQYXJzZXIucmVhZChieXRlcywgaSwgYnl0ZXMubGVuZ3RoIC0gaSk7XG4gICAgICBpID0gcGFyc2VkLm9mZnNldDtcblxuICAgICAgdmFyIHRhZyA9IGVudW1zLnJlYWQoZW51bXMucGFja2V0LCBwYXJzZWQudGFnKTtcbiAgICAgIHZhciBwYWNrZXQgPSBuZXcgcGFja2V0c1t0YWddKCk7XG5cbiAgICAgIHRoaXMucHVzaChwYWNrZXQpO1xuXG4gICAgICBwYWNrZXQucmVhZChwYXJzZWQucGFja2V0KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGJpbmFyeSByZXByZXNlbnRhdGlvbiBvZiBvcGVucGdwIG9iamVjdHMgY29udGFpbmVkIHdpdGhpbiB0aGVcbiAgICogY2xhc3MgaW5zdGFuY2UuXG4gICAqIEByZXR1cm5zIHtvcGVucGdwX2J5dGVhcnJheX0gQW4gYXJyYXkgb2YgYnl0ZXMgY29udGFpbmluZyB2YWxpZCBvcGVucGdwIHBhY2tldHMuXG4gICAqL1xuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGJ5dGVzID0gJyc7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBwYWNrZXRieXRlcyA9IHRoaXNbaV0ud3JpdGUoKTtcbiAgICAgIGJ5dGVzICs9IHBhY2tldFBhcnNlci53cml0ZUhlYWRlcih0aGlzW2ldLnRhZywgcGFja2V0Ynl0ZXMubGVuZ3RoKTtcbiAgICAgIGJ5dGVzICs9IHBhY2tldGJ5dGVzO1xuICAgIH1cblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgcGFja2V0IHRvIHRoZSBsaXN0LiBUaGlzIGlzIHRoZSBvbmx5IHN1cHBvcnRlZCBtZXRob2Qgb2YgZG9pbmcgc287XG4gICAqIHdyaXRpbmcgdG8gcGFja2V0bGlzdFtpXSBkaXJlY3RseSB3aWxsIHJlc3VsdCBpbiBhbiBlcnJvci5cbiAgICovXG4gIHRoaXMucHVzaCA9IGZ1bmN0aW9uKHBhY2tldCkge1xuICAgIHBhY2tldC5wYWNrZXRzID0gcGFja2V0LnBhY2tldHMgfHwgbmV3IHBhY2tldGxpc3QoKTtcblxuICAgIHRoaXNbdGhpcy5sZW5ndGhdID0gcGFja2V0O1xuICAgIHRoaXMubGVuZ3RoKys7XG4gIH1cblxuICAvKipcbiAgKiBDcmVhdGVzIGEgbmV3IHBhY2tldExpc3Qgd2l0aCBhbGwgcGFja2V0cyB0aGF0IHBhc3MgdGhlIHRlc3QgaW1wbGVtZW50ZWQgYnkgdGhlIHByb3ZpZGVkIGZ1bmN0aW9uLlxuICAqL1xuICB0aGlzLmZpbHRlciA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG5cbiAgICB2YXIgZmlsdGVyZWQgPSBuZXcgcGFja2V0bGlzdCgpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoY2FsbGJhY2sodGhpc1tpXSwgaSwgdGhpcykpIHtcbiAgICAgICAgZmlsdGVyZWQucHVzaCh0aGlzW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmlsdGVyZWQ7XG4gIH1cblxuICAvKipcbiAgKiBDcmVhdGVzIGEgbmV3IHBhY2tldExpc3Qgd2l0aCBhbGwgcGFja2V0cyBmcm9tIHRoZSBnaXZlbiB0eXBlc1xuICAqL1xuICB0aGlzLmZpbHRlckJ5VGFnID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgIHZhciBmaWx0ZXJlZCA9IG5ldyBwYWNrZXRsaXN0KCk7XG4gICAgdmFyIHRoYXQgPSB0aGlzO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoYXJncy5zb21lKGZ1bmN0aW9uKHBhY2tldFR5cGUpIHtyZXR1cm4gdGhhdFtpXS50YWcgPT0gcGFja2V0VHlwZX0pKSB7XG4gICAgICAgIGZpbHRlcmVkLnB1c2godGhpc1tpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZpbHRlcmVkO1xuICB9IFxuXG4gIC8qKlxuICAqIEV4ZWN1dGVzIHRoZSBwcm92aWRlZCBjYWxsYmFjayBvbmNlIGZvciBlYWNoIGVsZW1lbnRcbiAgKi9cbiAgdGhpcy5mb3JFYWNoID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNhbGxiYWNrKHRoaXNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmF2ZXJzZXMgcGFja2V0IHRyZWUgYW5kIHJldHVybnMgZmlyc3QgbWF0Y2hpbmcgcGFja2V0XG4gICAqIEBwYXJhbSAge2VudW1zLnBhY2tldH0gdHlwZSBUaGUgcGFja2V0IHR5cGVcbiAgICogQHJldHVybiB7cGFja2V0fG51bGx9ICAgICAgXG4gICAqL1xuICB0aGlzLmZpbmRQYWNrZXQgPSBmdW5jdGlvbih0eXBlKSB7XG4gICAgdmFyIHBhY2tldGxpc3QgPSB0aGlzLmZpbHRlckJ5VGFnKHR5cGUpO1xuICAgIGlmIChwYWNrZXRsaXN0Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHBhY2tldGxpc3RbMF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBmb3VuZCA9IG51bGw7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHRoaXNbaV0ucGFja2V0cy5sZW5ndGgpIHtcbiAgICAgICAgICBmb3VuZCA9IHRoaXNbaV0ucGFja2V0cy5maW5kUGFja2V0KHR5cGUpO1xuICAgICAgICAgIGlmIChmb3VuZCkgcmV0dXJuIGZvdW5kO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICB0eXBlX21waSA9IHJlcXVpcmUoJy4uL3R5cGUvbXBpLmpzJyksXG4gIHR5cGVfa2V5aWQgPSByZXF1aXJlKCcuLi90eXBlL2tleWlkLmpzJyksXG4gIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgY3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBLZXkgTWF0ZXJpYWwgUGFja2V0IChUYWcgNSw2LDcsMTQpXG4gKiAgIFxuICogUkZDNDQ4MCA1LjU6XG4gKiBBIGtleSBtYXRlcmlhbCBwYWNrZXQgY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBhIHB1YmxpYyBvclxuICogcHJpdmF0ZSBrZXkuICBUaGVyZSBhcmUgZm91ciB2YXJpYW50cyBvZiB0aGlzIHBhY2tldCB0eXBlLCBhbmQgdHdvXG4gKiBtYWpvciB2ZXJzaW9ucy4gIENvbnNlcXVlbnRseSwgdGhpcyBzZWN0aW9uIGlzIGNvbXBsZXguXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3B1YmxpY19rZXkoKSB7XG4gIC8qKiBLZXkgY3JlYXRpb24gZGF0ZS5cbiAgICogQHR5cGUge0RhdGV9ICovXG4gIHRoaXMuY3JlYXRlZCA9IG5ldyBEYXRlKCk7XG4gIC8qKiBBIGxpc3Qgb2YgbXVsdGlwcmVjaXNpb24gaW50ZWdlcnNcbiAgICogQHR5cGUge29wZW5wZ3BfdHlwZV9tcGl9ICovXG4gIHRoaXMubXBpID0gW107XG4gIC8qKiBQdWJsaWMga2V5IGFsZ29yaXRobVxuICAgKiBAdHlwZSB7b3BlbnBncC5wdWJsaWNrZXl9ICovXG4gIHRoaXMuYWxnb3JpdGhtID0gJ3JzYV9zaWduJztcblxuXG4gIC8qKlxuICAgKiBJbnRlcm5hbCBQYXJzZXIgZm9yIHB1YmxpYyBrZXlzIGFzIHNwZWNpZmllZCBpbiBSRkMgNDg4MCBzZWN0aW9uIFxuICAgKiA1LjUuMiBQdWJsaWMtS2V5IFBhY2tldCBGb3JtYXRzXG4gICAqIGNhbGxlZCBieSByZWFkX3RhZyZsdDtudW0mZ3Q7XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBJbnB1dCBzdHJpbmcgdG8gcmVhZCB0aGUgcGFja2V0IGZyb21cbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBwb3NpdGlvbiBTdGFydCBwb3NpdGlvbiBmb3IgdGhlIHBhcnNlclxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBMZW5ndGggb2YgdGhlIHBhY2tldCBvciByZW1haW5pbmcgbGVuZ3RoIG9mIGlucHV0XG4gICAqIEByZXR1cm4ge09iamVjdH0gVGhpcyBvYmplY3Qgd2l0aCBhdHRyaWJ1dGVzIHNldCBieSB0aGUgcGFyc2VyXG4gICAqL1xuICB0aGlzLnJlYWRQdWJsaWNLZXkgPSB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIC8vIEEgb25lLW9jdGV0IHZlcnNpb24gbnVtYmVyICgzIG9yIDQpLlxuICAgIHZhciB2ZXJzaW9uID0gYnl0ZXNbMF0uY2hhckNvZGVBdCgpO1xuXG4gICAgaWYgKHZlcnNpb24gPT0gNCkge1xuICAgICAgLy8gLSBBIGZvdXItb2N0ZXQgbnVtYmVyIGRlbm90aW5nIHRoZSB0aW1lIHRoYXQgdGhlIGtleSB3YXMgY3JlYXRlZC5cbiAgICAgIHRoaXMuY3JlYXRlZCA9IHV0aWwucmVhZERhdGUoYnl0ZXMuc3Vic3RyKDEsIDQpKTtcblxuICAgICAgLy8gLSBBIG9uZS1vY3RldCBudW1iZXIgZGVub3RpbmcgdGhlIHB1YmxpYy1rZXkgYWxnb3JpdGhtIG9mIHRoaXMga2V5LlxuICAgICAgdGhpcy5hbGdvcml0aG0gPSBlbnVtcy5yZWFkKGVudW1zLnB1YmxpY0tleSwgYnl0ZXNbNV0uY2hhckNvZGVBdCgpKTtcblxuICAgICAgdmFyIG1waWNvdW50ID0gY3J5cHRvLmdldFB1YmxpY01waUNvdW50KHRoaXMuYWxnb3JpdGhtKTtcbiAgICAgIHRoaXMubXBpID0gW107XG5cbiAgICAgIHZhciBibXBpID0gYnl0ZXMuc3Vic3RyKDYpO1xuICAgICAgdmFyIHAgPSAwO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1waWNvdW50ICYmIHAgPCBibXBpLmxlbmd0aDsgaSsrKSB7XG5cbiAgICAgICAgdGhpcy5tcGlbaV0gPSBuZXcgdHlwZV9tcGkoKTtcblxuICAgICAgICBwICs9IHRoaXMubXBpW2ldLnJlYWQoYm1waS5zdWJzdHIocCkpXG5cbiAgICAgICAgaWYgKHAgPiBibXBpLmxlbmd0aClcbiAgICAgICAgICB1dGlsLnByaW50X2Vycm9yKFwib3BlbnBncC5wYWNrZXQua2V5bWF0ZXJpYWwuanNcXG5cIiArICdlcnJvciByZWFkaW5nIE1QSSBAOicgKyBwKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHAgKyA2O1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1ZlcnNpb24gJyArIHZlcnNpb24gKyAnIG9mIHRoZSBrZXkgcGFja2V0IGlzIHVuc3VwcG9ydGVkLicpO1xuICAgIH1cbiAgfVxuXG4gIC8qXG4gICAqIFNhbWUgYXMgd3JpdGVfcHJpdmF0ZV9rZXksIGJ1dCBoYXMgbGVzcyBpbmZvcm1hdGlvbiBiZWNhdXNlIG9mIFxuICAgKiBwdWJsaWMga2V5LlxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGtleVR5cGUgRm9sbG93cyB0aGUgT3BlblBHUCBhbGdvcml0aG0gc3RhbmRhcmQsIFxuICAgKiBJRSAxIGNvcnJlc3BvbmRzIHRvIFJTQS5cbiAgICogQHBhcmFtIHtSU0Eua2V5T2JqZWN0fSBrZXlcbiAgICogQHBhcmFtIHRpbWVQYWNrZXRcbiAgICogQHJldHVybiB7T2JqZWN0fSB7Ym9keTogW3N0cmluZ11PcGVuUEdQIHBhY2tldCBib2R5IGNvbnRlbnRzLCBcbiAgICogaGVhZGVyOiBbc3RyaW5nXSBPcGVuUEdQIHBhY2tldCBoZWFkZXIsIHN0cmluZzogW3N0cmluZ10gaGVhZGVyK2JvZHl9XG4gICAqL1xuICB0aGlzLndyaXRlUHVibGljS2V5ID0gdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIFZlcnNpb25cbiAgICB2YXIgcmVzdWx0ID0gU3RyaW5nLmZyb21DaGFyQ29kZSg0KTtcbiAgICByZXN1bHQgKz0gdXRpbC53cml0ZURhdGUodGhpcy5jcmVhdGVkKTtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5wdWJsaWNLZXksIHRoaXMuYWxnb3JpdGhtKSk7XG5cbiAgICB2YXIgbXBpY291bnQgPSBjcnlwdG8uZ2V0UHVibGljTXBpQ291bnQodGhpcy5hbGdvcml0aG0pO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtcGljb3VudDsgaSsrKSB7XG4gICAgICByZXN1bHQgKz0gdGhpcy5tcGlbaV0ud3JpdGUoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gV3JpdGUgYW4gb2xkIHZlcnNpb24gcGFja2V0IC0gaXQncyB1c2VkIGJ5IHNvbWUgb2YgdGhlIGludGVybmFsIHJvdXRpbmVzLlxuICB0aGlzLndyaXRlT2xkID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGJ5dGVzID0gdGhpcy53cml0ZVB1YmxpY0tleSgpO1xuXG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoMHg5OSkgK1xuICAgICAgdXRpbC53cml0ZU51bWJlcihieXRlcy5sZW5ndGgsIDIpICtcbiAgICAgIGJ5dGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgdGhlIGtleSBpZCBvZiB0aGUga2V5IFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEEgOCBieXRlIGtleSBpZFxuICAgKi9cbiAgdGhpcy5nZXRLZXlJZCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBrZXlpZCA9IG5ldyB0eXBlX2tleWlkKCk7XG4gICAga2V5aWQucmVhZCh0aGlzLmdldEZpbmdlcnByaW50KCkuc3Vic3RyKDEyLCA4KSk7XG4gICAgcmV0dXJuIGtleWlkO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgdGhlIGZpbmdlcnByaW50IG9mIHRoZSBrZXlcbiAgICogQHJldHVybiB7U3RyaW5nfSBBIHN0cmluZyBjb250YWluaW5nIHRoZSBmaW5nZXJwcmludFxuICAgKi9cbiAgdGhpcy5nZXRGaW5nZXJwcmludCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB0b0hhc2ggPSB0aGlzLndyaXRlT2xkKCk7XG4gICAgcmV0dXJuIGNyeXB0by5oYXNoLnNoYTEodG9IYXNoLCB0b0hhc2gubGVuZ3RoKTtcbiAgfVxuXG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgdHlwZV9rZXlpZCA9IHJlcXVpcmUoJy4uL3R5cGUva2V5aWQuanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgdHlwZV9tcGkgPSByZXF1aXJlKCcuLi90eXBlL21waS5qcycpLFxuICBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG4gIGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpO1xuXG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIFB1YmxpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IFBhY2tldHMgKFRhZyAxKVxuICogXG4gKiBSRkM0ODgwIDUuMTogQSBQdWJsaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXQgaG9sZHMgdGhlIHNlc3Npb24ga2V5XG4gKiB1c2VkIHRvIGVuY3J5cHQgYSBtZXNzYWdlLiBaZXJvIG9yIG1vcmUgUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXlcbiAqIHBhY2tldHMgYW5kL29yIFN5bW1ldHJpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldHMgbWF5IHByZWNlZGUgYVxuICogU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQsIHdoaWNoIGhvbGRzIGFuIGVuY3J5cHRlZCBtZXNzYWdlLiBUaGVcbiAqIG1lc3NhZ2UgaXMgZW5jcnlwdGVkIHdpdGggdGhlIHNlc3Npb24ga2V5LCBhbmQgdGhlIHNlc3Npb24ga2V5IGlzIGl0c2VsZlxuICogZW5jcnlwdGVkIGFuZCBzdG9yZWQgaW4gdGhlIEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXQocykuIFRoZVxuICogU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQgaXMgcHJlY2VkZWQgYnkgb25lIFB1YmxpYy1LZXkgRW5jcnlwdGVkXG4gKiBTZXNzaW9uIEtleSBwYWNrZXQgZm9yIGVhY2ggT3BlblBHUCBrZXkgdG8gd2hpY2ggdGhlIG1lc3NhZ2UgaXMgZW5jcnlwdGVkLlxuICogVGhlIHJlY2lwaWVudCBvZiB0aGUgbWVzc2FnZSBmaW5kcyBhIHNlc3Npb24ga2V5IHRoYXQgaXMgZW5jcnlwdGVkIHRvIHRoZWlyXG4gKiBwdWJsaWMga2V5LCBkZWNyeXB0cyB0aGUgc2Vzc2lvbiBrZXksIGFuZCB0aGVuIHVzZXMgdGhlIHNlc3Npb24ga2V5IHRvXG4gKiBkZWNyeXB0IHRoZSBtZXNzYWdlLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9wdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleSgpIHtcbiAgdGhpcy52ZXJzaW9uID0gMztcblxuICB0aGlzLnB1YmxpY0tleUlkID0gbmV3IHR5cGVfa2V5aWQoKTtcbiAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSAncnNhX2VuY3J5cHQnO1xuXG4gIHRoaXMuc2Vzc2lvbktleSA9IG51bGw7XG4gIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA9ICdhZXMyNTYnO1xuXG4gIC8qKiBAdHlwZSB7b3BlbnBncF90eXBlX21waVtdfSAqL1xuICB0aGlzLmVuY3J5cHRlZCA9IFtdO1xuXG4gIC8qKlxuICAgKiBQYXJzaW5nIGZ1bmN0aW9uIGZvciBhIHB1YmxpY2tleSBlbmNyeXB0ZWQgc2Vzc2lvbiBrZXkgcGFja2V0ICh0YWcgMSkuXG4gICAqIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgUGF5bG9hZCBvZiBhIHRhZyAxIHBhY2tldFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgc3RyaW5nXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIExlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mXG4gICAqICAgICAgICAgICAgaW5wdXQgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YX0gT2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuXG4gICAgdGhpcy52ZXJzaW9uID0gYnl0ZXNbMF0uY2hhckNvZGVBdCgpO1xuICAgIHRoaXMucHVibGljS2V5SWQucmVhZChieXRlcy5zdWJzdHIoMSkpO1xuICAgIHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gZW51bXMucmVhZChlbnVtcy5wdWJsaWNLZXksIGJ5dGVzWzldLmNoYXJDb2RlQXQoKSk7XG5cbiAgICB2YXIgaSA9IDEwO1xuXG4gICAgdmFyIGludGVnZXJDb3VudCA9IChmdW5jdGlvbihhbGdvKSB7XG4gICAgICBzd2l0Y2ggKGFsZ28pIHtcbiAgICAgICAgY2FzZSAncnNhX2VuY3J5cHQnOlxuICAgICAgICBjYXNlICdyc2FfZW5jcnlwdF9zaWduJzpcbiAgICAgICAgICByZXR1cm4gMTtcblxuICAgICAgICBjYXNlICdlbGdhbWFsJzpcbiAgICAgICAgICByZXR1cm4gMjtcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgYWxnb3JpdGhtLlwiKTtcbiAgICAgIH1cbiAgICB9KSh0aGlzLnB1YmxpY0tleUFsZ29yaXRobSk7XG5cbiAgICB0aGlzLmVuY3J5cHRlZCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBpbnRlZ2VyQ291bnQ7IGorKykge1xuICAgICAgdmFyIG1waSA9IG5ldyB0eXBlX21waSgpO1xuICAgICAgaSArPSBtcGkucmVhZChieXRlcy5zdWJzdHIoaSkpO1xuICAgICAgdGhpcy5lbmNyeXB0ZWQucHVzaChtcGkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYSB0YWcgMSBwYWNrZXRcbiAgICogXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwdWJsaWNLZXlJZFxuICAgKiAgICAgICAgICAgICBUaGUgcHVibGljIGtleSBpZCBjb3JyZXNwb25kaW5nIHRvIHB1YmxpY01QSXMga2V5IGFzIHN0cmluZ1xuICAgKiBAcGFyYW0ge29wZW5wZ3BfdHlwZV9tcGlbXX0gcHVibGljTVBJc1xuICAgKiAgICAgICAgICAgIE11bHRpcHJlY2lzaW9uIGludGVnZXIgb2JqZWN0cyBkZXNjcmliaW5nIHRoZSBwdWJsaWMga2V5XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcHViYWxnb1xuICAgKiAgICAgICAgICAgIFRoZSBjb3JyZXNwb25kaW5nIHB1YmxpYyBrZXkgYWxnb3JpdGhtIC8vIFNlZSBSRkM0ODgwIDkuMVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHN5bW1hbGdvXG4gICAqICAgICAgICAgICAgVGhlIHN5bW1ldHJpYyBjaXBoZXIgYWxnb3JpdGhtIHVzZWQgdG8gZW5jcnlwdCB0aGUgZGF0YSBcbiAgICogICAgICAgICAgICB3aXRoaW4gYW4gZW5jcnlwdGVkZGF0YXBhY2tldCBvciBlbmNyeXB0ZWRpbnRlZ3JpdHktXG4gICAqICAgICAgICAgICAgcHJvdGVjdGVkZGF0YXBhY2tldCBcbiAgICogICAgICAgICAgICBmb2xsb3dpbmcgdGhpcyBwYWNrZXQgLy9TZWUgUkZDNDg4MCA5LjJcbiAgICogQHBhcmFtIHtTdHJpbmd9IHNlc3Npb25rZXlcbiAgICogICAgICAgICAgICBBIHN0cmluZyBvZiByYW5kb21ieXRlcyByZXByZXNlbnRpbmcgdGhlIHNlc3Npb24ga2V5XG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHN0cmluZyByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIHJlc3VsdCA9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy52ZXJzaW9uKTtcbiAgICByZXN1bHQgKz0gdGhpcy5wdWJsaWNLZXlJZC53cml0ZSgpO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKFxuICAgICAgZW51bXMud3JpdGUoZW51bXMucHVibGljS2V5LCB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSkpO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmVuY3J5cHRlZC5sZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0ICs9IHRoaXMuZW5jcnlwdGVkW2ldLndyaXRlKClcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgdGhpcy5lbmNyeXB0ID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgdmFyIGRhdGEgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKFxuICAgICAgZW51bXMud3JpdGUoZW51bXMuc3ltbWV0cmljLCB0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0pKTtcblxuICAgIGRhdGEgKz0gdGhpcy5zZXNzaW9uS2V5O1xuICAgIHZhciBjaGVja3N1bSA9IHV0aWwuY2FsY19jaGVja3N1bSh0aGlzLnNlc3Npb25LZXkpO1xuICAgIGRhdGEgKz0gdXRpbC53cml0ZU51bWJlcihjaGVja3N1bSwgMik7XG5cbiAgICB2YXIgbXBpID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgbXBpLmZyb21CeXRlcyhjcnlwdG8ucGtjczEuZW1lLmVuY29kZShcbiAgICAgIGRhdGEsXG4gICAgICBrZXkubXBpWzBdLmJ5dGVMZW5ndGgoKSkpO1xuXG4gICAgdGhpcy5lbmNyeXB0ZWQgPSBjcnlwdG8ucHVibGljS2V5RW5jcnlwdChcbiAgICAgIHRoaXMucHVibGljS2V5QWxnb3JpdGhtLFxuICAgICAga2V5Lm1waSxcbiAgICAgIG1waSk7XG4gIH1cblxuICAvKipcbiAgICogRGVjcnlwdHMgdGhlIHNlc3Npb24ga2V5IChvbmx5IGZvciBwdWJsaWMga2V5IGVuY3J5cHRlZCBzZXNzaW9uIGtleVxuICAgKiBwYWNrZXRzICh0YWcgMSlcbiAgICogXG4gICAqIEBwYXJhbSB7b3BlbnBncF9tc2dfbWVzc2FnZX0gbXNnXG4gICAqICAgICAgICAgICAgVGhlIG1lc3NhZ2Ugb2JqZWN0ICh3aXRoIG1lbWJlciBlbmNyeXB0ZWREYXRhXG4gICAqIEBwYXJhbSB7b3BlbnBncF9tc2dfcHJpdmF0ZWtleX0ga2V5XG4gICAqICAgICAgICAgICAgUHJpdmF0ZSBrZXkgd2l0aCBzZWNNUElzIHVubG9ja2VkXG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHVuZW5jcnlwdGVkIHNlc3Npb24ga2V5XG4gICAqL1xuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihrZXkpIHtcbiAgICB2YXIgcmVzdWx0ID0gY3J5cHRvLnB1YmxpY0tleURlY3J5cHQoXG4gICAgICB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSxcbiAgICAgIGtleS5tcGksXG4gICAgICB0aGlzLmVuY3J5cHRlZCkudG9CeXRlcygpO1xuXG4gICAgdmFyIGNoZWNrc3VtID0gdXRpbC5yZWFkTnVtYmVyKHJlc3VsdC5zdWJzdHIocmVzdWx0Lmxlbmd0aCAtIDIpKTtcblxuICAgIHZhciBkZWNvZGVkID0gY3J5cHRvLnBrY3MxLmVtZS5kZWNvZGUoXG4gICAgICByZXN1bHQsXG4gICAgICBrZXkubXBpWzBdLmJ5dGVMZW5ndGgoKSk7XG5cbiAgICB2YXIga2V5ID0gZGVjb2RlZC5zdWJzdHJpbmcoMSwgZGVjb2RlZC5sZW5ndGggLSAyKTtcblxuICAgIGlmIChjaGVja3N1bSAhPSB1dGlsLmNhbGNfY2hlY2tzdW0oa2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaGVja3N1bSBtaXNtYXRjaCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNlc3Npb25LZXkgPSBrZXk7XG4gICAgICB0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0gPVxuICAgICAgICBlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgZGVjb2RlZC5jaGFyQ29kZUF0KDApKTtcbiAgICB9XG4gIH1cbn07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgcHVibGljX2tleSA9IHJlcXVpcmUoJy4vcHVibGljX2tleS5qcycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHB1YmxpY19zdWJrZXkoKSB7XG4gIHB1YmxpY19rZXkuY2FsbCh0aGlzKTtcbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBwdWJsaWNLZXkgPSByZXF1aXJlKCcuL3B1YmxpY19rZXkuanMnKSxcbiAgZW51bXMgPSByZXF1aXJlKCcuLi9lbnVtcy5qcycpLFxuICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICBjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKSxcbiAgdHlwZV9tcGkgPSByZXF1aXJlKCcuLi90eXBlL21waS5qcycpLFxuICB0eXBlX3MyayA9IHJlcXVpcmUoJy4uL3R5cGUvczJrLmpzJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBLZXkgTWF0ZXJpYWwgUGFja2V0IChUYWcgNSw2LDcsMTQpXG4gKiAgIFxuICogUkZDNDQ4MCA1LjU6XG4gKiBBIGtleSBtYXRlcmlhbCBwYWNrZXQgY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiBhYm91dCBhIHB1YmxpYyBvclxuICogcHJpdmF0ZSBrZXkuICBUaGVyZSBhcmUgZm91ciB2YXJpYW50cyBvZiB0aGlzIHBhY2tldCB0eXBlLCBhbmQgdHdvXG4gKiBtYWpvciB2ZXJzaW9ucy4gIENvbnNlcXVlbnRseSwgdGhpcyBzZWN0aW9uIGlzIGNvbXBsZXguXG4gKi9cbmZ1bmN0aW9uIHBhY2tldF9zZWNyZXRfa2V5KCkge1xuICBwdWJsaWNLZXkuY2FsbCh0aGlzKTtcbiAgLy8gZW5jcnlwdGVkIHNlY3JldC1rZXkgZGF0YVxuICB0aGlzLmVuY3J5cHRlZCA9IG51bGw7XG4gIC8vIGluZGljYXRvciBpZiBzZWNyZXQta2V5IGRhdGEgaXMgYXZhaWxhYmxlIGluIGRlY3J5cHRlZCBmb3JtXG4gIHRoaXMuaXNEZWNyeXB0ZWQgPSBmYWxzZTtcblxuXG4gIGZ1bmN0aW9uIGdldF9oYXNoX2xlbihoYXNoKSB7XG4gICAgaWYgKGhhc2ggPT0gJ3NoYTEnKVxuICAgICAgcmV0dXJuIDIwO1xuICAgIGVsc2VcbiAgICAgIHJldHVybiAyO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0X2hhc2hfZm4oaGFzaCkge1xuICAgIGlmIChoYXNoID09ICdzaGExJylcbiAgICAgIHJldHVybiBjcnlwdG8uaGFzaC5zaGExO1xuICAgIGVsc2VcbiAgICAgIHJldHVybiBmdW5jdGlvbihjKSB7XG4gICAgICAgIHJldHVybiB1dGlsLndyaXRlTnVtYmVyKHV0aWwuY2FsY19jaGVja3N1bShjKSwgMik7XG4gICAgfTtcbiAgfVxuXG4gIC8vIEhlbHBlciBmdW5jdGlvblxuXG4gIGZ1bmN0aW9uIHBhcnNlX2NsZWFydGV4dF9tcGkoaGFzaF9hbGdvcml0aG0sIGNsZWFydGV4dCwgYWxnb3JpdGhtKSB7XG4gICAgdmFyIGhhc2hsZW4gPSBnZXRfaGFzaF9sZW4oaGFzaF9hbGdvcml0aG0pLFxuICAgICAgaGFzaGZuID0gZ2V0X2hhc2hfZm4oaGFzaF9hbGdvcml0aG0pO1xuXG4gICAgdmFyIGhhc2h0ZXh0ID0gY2xlYXJ0ZXh0LnN1YnN0cihjbGVhcnRleHQubGVuZ3RoIC0gaGFzaGxlbik7XG4gICAgY2xlYXJ0ZXh0ID0gY2xlYXJ0ZXh0LnN1YnN0cigwLCBjbGVhcnRleHQubGVuZ3RoIC0gaGFzaGxlbik7XG5cbiAgICB2YXIgaGFzaCA9IGhhc2hmbihjbGVhcnRleHQpO1xuXG4gICAgaWYgKGhhc2ggIT0gaGFzaHRleHQpXG4gICAgICByZXR1cm4gbmV3IEVycm9yKFwiSGFzaCBtaXNtYXRjaC5cIik7XG5cbiAgICB2YXIgbXBpcyA9IGNyeXB0by5nZXRQcml2YXRlTXBpQ291bnQoYWxnb3JpdGhtKTtcblxuICAgIHZhciBqID0gMDtcbiAgICB2YXIgbXBpID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1waXMgJiYgaiA8IGNsZWFydGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgbXBpW2ldID0gbmV3IHR5cGVfbXBpKCk7XG4gICAgICBqICs9IG1waVtpXS5yZWFkKGNsZWFydGV4dC5zdWJzdHIoaikpO1xuICAgIH1cblxuICAgIHJldHVybiBtcGk7XG4gIH1cblxuICBmdW5jdGlvbiB3cml0ZV9jbGVhcnRleHRfbXBpKGhhc2hfYWxnb3JpdGhtLCBhbGdvcml0aG0sIG1waSkge1xuICAgIHZhciBieXRlcyA9ICcnO1xuICAgIHZhciBkaXNjYXJkID0gY3J5cHRvLmdldFB1YmxpY01waUNvdW50KGFsZ29yaXRobSk7XG5cbiAgICBmb3IgKHZhciBpID0gZGlzY2FyZDsgaSA8IG1waS5sZW5ndGg7IGkrKykge1xuICAgICAgYnl0ZXMgKz0gbXBpW2ldLndyaXRlKCk7XG4gICAgfVxuXG5cbiAgICBieXRlcyArPSBnZXRfaGFzaF9mbihoYXNoX2FsZ29yaXRobSkoYnl0ZXMpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cblxuICAvLyA1LjUuMy4gIFNlY3JldC1LZXkgUGFja2V0IEZvcm1hdHNcblxuICAvKipcbiAgICogSW50ZXJuYWwgcGFyc2VyIGZvciBwcml2YXRlIGtleXMgYXMgc3BlY2lmaWVkIGluIFJGQyA0ODgwIHNlY3Rpb24gNS41LjNcbiAgICogQHBhcmFtIHtTdHJpbmd9IGJ5dGVzIElucHV0IHN0cmluZyB0byByZWFkIHRoZSBwYWNrZXQgZnJvbVxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAvLyAtIEEgUHVibGljLUtleSBvciBQdWJsaWMtU3Via2V5IHBhY2tldCwgYXMgZGVzY3JpYmVkIGFib3ZlLlxuICAgIHZhciBsZW4gPSB0aGlzLnJlYWRQdWJsaWNLZXkoYnl0ZXMpO1xuXG4gICAgYnl0ZXMgPSBieXRlcy5zdWJzdHIobGVuKTtcblxuXG4gICAgLy8gLSBPbmUgb2N0ZXQgaW5kaWNhdGluZyBzdHJpbmctdG8ta2V5IHVzYWdlIGNvbnZlbnRpb25zLiAgWmVyb1xuICAgIC8vICAgaW5kaWNhdGVzIHRoYXQgdGhlIHNlY3JldC1rZXkgZGF0YSBpcyBub3QgZW5jcnlwdGVkLiAgMjU1IG9yIDI1NFxuICAgIC8vICAgaW5kaWNhdGVzIHRoYXQgYSBzdHJpbmctdG8ta2V5IHNwZWNpZmllciBpcyBiZWluZyBnaXZlbi4gIEFueVxuICAgIC8vICAgb3RoZXIgdmFsdWUgaXMgYSBzeW1tZXRyaWMta2V5IGVuY3J5cHRpb24gYWxnb3JpdGhtIGlkZW50aWZpZXIuXG4gICAgdmFyIGlzRW5jcnlwdGVkID0gYnl0ZXNbMF0uY2hhckNvZGVBdCgpO1xuXG4gICAgaWYgKGlzRW5jcnlwdGVkKSB7XG4gICAgICB0aGlzLmVuY3J5cHRlZCA9IGJ5dGVzO1xuICAgIH0gZWxzZSB7XG5cbiAgICAgIC8vIC0gUGxhaW4gb3IgZW5jcnlwdGVkIG11bHRpcHJlY2lzaW9uIGludGVnZXJzIGNvbXByaXNpbmcgdGhlIHNlY3JldFxuICAgICAgLy8gICBrZXkgZGF0YS4gIFRoZXNlIGFsZ29yaXRobS1zcGVjaWZpYyBmaWVsZHMgYXJlIGFzIGRlc2NyaWJlZFxuICAgICAgLy8gICBiZWxvdy5cbiAgICAgIHZhciBwYXJzZWRNUEkgPSBwYXJzZV9jbGVhcnRleHRfbXBpKCdtb2QnLCBieXRlcy5zdWJzdHIoMSksIHRoaXMuYWxnb3JpdGhtKTtcbiAgICAgIGlmIChwYXJzZWRNUEkgaW5zdGFuY2VvZiBFcnJvcilcbiAgICAgICAgdGhyb3cgcGFyc2VkTVBJO1xuICAgICAgdGhpcy5tcGkgPSB0aGlzLm1waS5jb25jYXQocGFyc2VkTVBJKTtcbiAgICAgIHRoaXMuaXNEZWNyeXB0ZWQgPSB0cnVlO1xuICAgIH1cblxuICB9O1xuXG4gIC8qKiBDcmVhdGVzIGFuIE9wZW5QR1Aga2V5IHBhY2tldCBmb3IgdGhlIGdpdmVuIGtleS5cbiAgICAqIEByZXR1cm4ge1N0cmluZ30gQSBzdHJpbmcgb2YgYnl0ZXMgY29udGFpbmluZyB0aGUgc2VjcmV0IGtleSBPcGVuUEdQIHBhY2tldFxuICAgICovXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnl0ZXMgPSB0aGlzLndyaXRlUHVibGljS2V5KCk7XG5cbiAgICBpZiAoIXRoaXMuZW5jcnlwdGVkKSB7XG4gICAgICBieXRlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuXG4gICAgICBieXRlcyArPSB3cml0ZV9jbGVhcnRleHRfbXBpKCdtb2QnLCB0aGlzLmFsZ29yaXRobSwgdGhpcy5tcGkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBieXRlcyArPSB0aGlzLmVuY3J5cHRlZDtcbiAgICB9XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH07XG5cblxuXG5cbiAgLyoqIEVuY3J5cHQgdGhlIHBheWxvYWQuIEJ5IGRlZmF1bHQsIHdlIHVzZSBhZXMyNTYgYW5kIGl0ZXJhdGVkLCBzYWx0ZWQgc3RyaW5nXG4gICAqIHRvIGtleSBzcGVjaWZpZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhc3NwaHJhc2VcbiAgICovXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKHBhc3NwaHJhc2UpIHtcblxuICAgIHZhciBzMmsgPSBuZXcgdHlwZV9zMmsoKSxcbiAgICAgIHN5bW1ldHJpYyA9ICdhZXMyNTYnLFxuICAgICAgY2xlYXJ0ZXh0ID0gd3JpdGVfY2xlYXJ0ZXh0X21waSgnc2hhMScsIHRoaXMuYWxnb3JpdGhtLCB0aGlzLm1waSksXG4gICAgICBrZXkgPSBwcm9kdWNlRW5jcnlwdGlvbktleShzMmssIHBhc3NwaHJhc2UsIHN5bW1ldHJpYyksXG4gICAgICBibG9ja0xlbiA9IGNyeXB0by5jaXBoZXJbc3ltbWV0cmljXS5ibG9ja1NpemUsXG4gICAgICBpdiA9IGNyeXB0by5yYW5kb20uZ2V0UmFuZG9tQnl0ZXMoYmxvY2tMZW4pO1xuXG5cbiAgICB0aGlzLmVuY3J5cHRlZCA9ICcnO1xuICAgIHRoaXMuZW5jcnlwdGVkICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMjU0KTtcbiAgICB0aGlzLmVuY3J5cHRlZCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLnN5bW1ldHJpYywgc3ltbWV0cmljKSk7XG4gICAgdGhpcy5lbmNyeXB0ZWQgKz0gczJrLndyaXRlKCk7XG4gICAgdGhpcy5lbmNyeXB0ZWQgKz0gaXY7XG5cbiAgICB0aGlzLmVuY3J5cHRlZCArPSBjcnlwdG8uY2ZiLm5vcm1hbEVuY3J5cHQoc3ltbWV0cmljLCBrZXksIGNsZWFydGV4dCwgaXYpO1xuICB9O1xuXG4gIGZ1bmN0aW9uIHByb2R1Y2VFbmNyeXB0aW9uS2V5KHMyaywgcGFzc3BocmFzZSwgYWxnb3JpdGhtKSB7XG4gICAgcmV0dXJuIHMyay5wcm9kdWNlX2tleShwYXNzcGhyYXNlLFxuICAgICAgY3J5cHRvLmNpcGhlclthbGdvcml0aG1dLmtleVNpemUpO1xuICB9XG5cbiAgLyoqXG4gICAqIERlY3J5cHRzIHRoZSBwcml2YXRlIGtleSBNUElzIHdoaWNoIGFyZSBuZWVkZWQgdG8gdXNlIHRoZSBrZXkuXG4gICAqIG9wZW5wZ3BfcGFja2V0X2tleW1hdGVyaWFsLmhhc1VuZW5jcnlwdGVkU2VjcmV0S2V5RGF0YSBzaG91bGQgYmUgXG4gICAqIGZhbHNlIG90aGVyd2lzZVxuICAgKiBhIGNhbGwgdG8gdGhpcyBmdW5jdGlvbiBpcyBub3QgbmVlZGVkXG4gICAqIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyX3Bhc3NwaHJhc2UgVGhlIHBhc3NwaHJhc2UgZm9yIHRoaXMgcHJpdmF0ZSBrZXkgXG4gICAqIGFzIHN0cmluZ1xuICAgKiBAcmV0dXJuIHtCb29sZWFufSBUcnVlIGlmIHRoZSBwYXNzcGhyYXNlIHdhcyBjb3JyZWN0IG9yIE1QSSBhbHJlYWR5XG4gICAqICAgICAgICAgICAgICAgICAgIGRlY3J5cHRlZDsgZmFsc2UgaWYgbm90XG4gICAqL1xuICB0aGlzLmRlY3J5cHQgPSBmdW5jdGlvbihwYXNzcGhyYXNlKSB7XG4gICAgaWYgKHRoaXMuaXNEZWNyeXB0ZWQpXG4gICAgICByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciBpID0gMCxcbiAgICAgIHN5bW1ldHJpYyxcbiAgICAgIGtleTtcblxuICAgIHZhciBzMmtfdXNhZ2UgPSB0aGlzLmVuY3J5cHRlZFtpKytdLmNoYXJDb2RlQXQoKTtcblxuICAgIC8vIC0gW09wdGlvbmFsXSBJZiBzdHJpbmctdG8ta2V5IHVzYWdlIG9jdGV0IHdhcyAyNTUgb3IgMjU0LCBhIG9uZS1cbiAgICAvLyAgIG9jdGV0IHN5bW1ldHJpYyBlbmNyeXB0aW9uIGFsZ29yaXRobS5cbiAgICBpZiAoczJrX3VzYWdlID09IDI1NSB8fCBzMmtfdXNhZ2UgPT0gMjU0KSB7XG4gICAgICBzeW1tZXRyaWMgPSB0aGlzLmVuY3J5cHRlZFtpKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgIHN5bW1ldHJpYyA9IGVudW1zLnJlYWQoZW51bXMuc3ltbWV0cmljLCBzeW1tZXRyaWMpO1xuXG4gICAgICAvLyAtIFtPcHRpb25hbF0gSWYgc3RyaW5nLXRvLWtleSB1c2FnZSBvY3RldCB3YXMgMjU1IG9yIDI1NCwgYVxuICAgICAgLy8gICBzdHJpbmctdG8ta2V5IHNwZWNpZmllci4gIFRoZSBsZW5ndGggb2YgdGhlIHN0cmluZy10by1rZXlcbiAgICAgIC8vICAgc3BlY2lmaWVyIGlzIGltcGxpZWQgYnkgaXRzIHR5cGUsIGFzIGRlc2NyaWJlZCBhYm92ZS5cbiAgICAgIHZhciBzMmsgPSBuZXcgdHlwZV9zMmsoKTtcbiAgICAgIGkgKz0gczJrLnJlYWQodGhpcy5lbmNyeXB0ZWQuc3Vic3RyKGkpKTtcblxuICAgICAga2V5ID0gcHJvZHVjZUVuY3J5cHRpb25LZXkoczJrLCBwYXNzcGhyYXNlLCBzeW1tZXRyaWMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzeW1tZXRyaWMgPSBzMmtfdXNhZ2U7XG4gICAgICBzeW1tZXRyaWMgPSBlbnVtcy5yZWFkKGVudW1zLnN5bW1ldHJpYywgc3ltbWV0cmljKTtcbiAgICAgIGtleSA9IGNyeXB0by5oYXNoLm1kNShwYXNzcGhyYXNlKTtcbiAgICB9XG5cblxuICAgIC8vIC0gW09wdGlvbmFsXSBJZiBzZWNyZXQgZGF0YSBpcyBlbmNyeXB0ZWQgKHN0cmluZy10by1rZXkgdXNhZ2Ugb2N0ZXRcbiAgICAvLyAgIG5vdCB6ZXJvKSwgYW4gSW5pdGlhbCBWZWN0b3IgKElWKSBvZiB0aGUgc2FtZSBsZW5ndGggYXMgdGhlXG4gICAgLy8gICBjaXBoZXIncyBibG9jayBzaXplLlxuICAgIHZhciBpdiA9IHRoaXMuZW5jcnlwdGVkLnN1YnN0cihpLFxuICAgICAgY3J5cHRvLmNpcGhlcltzeW1tZXRyaWNdLmJsb2NrU2l6ZSk7XG5cbiAgICBpICs9IGl2Lmxlbmd0aDtcblxuICAgIHZhciBjbGVhcnRleHQsXG4gICAgICBjaXBoZXJ0ZXh0ID0gdGhpcy5lbmNyeXB0ZWQuc3Vic3RyKGkpO1xuXG4gICAgY2xlYXJ0ZXh0ID0gY3J5cHRvLmNmYi5ub3JtYWxEZWNyeXB0KHN5bW1ldHJpYywga2V5LCBjaXBoZXJ0ZXh0LCBpdik7XG5cbiAgICB2YXIgaGFzaCA9IHMya191c2FnZSA9PSAyNTQgP1xuICAgICAgJ3NoYTEnIDpcbiAgICAgICdtb2QnO1xuXG4gICAgdmFyIHBhcnNlZE1QSSA9IHBhcnNlX2NsZWFydGV4dF9tcGkoaGFzaCwgY2xlYXJ0ZXh0LCB0aGlzLmFsZ29yaXRobSk7XG4gICAgaWYgKHBhcnNlZE1QSSBpbnN0YW5jZW9mIEVycm9yKVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIHRoaXMubXBpID0gdGhpcy5tcGkuY29uY2F0KHBhcnNlZE1QSSk7XG4gICAgdGhpcy5pc0RlY3J5cHRlZCA9IHRydWU7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cbiAgdGhpcy5nZW5lcmF0ZSA9IGZ1bmN0aW9uKGJpdHMpIHtcbiAgICB0aGlzLm1waSA9IGNyeXB0by5nZW5lcmF0ZU1waSh0aGlzLmFsZ29yaXRobSwgYml0cyk7XG4gICAgdGhpcy5pc0RlY3J5cHRlZCA9IHRydWU7XG4gIH07XG5cbn1cblxucGFja2V0X3NlY3JldF9rZXkucHJvdG90eXBlID0gbmV3IHB1YmxpY0tleTtcblxubW9kdWxlLmV4cG9ydHMgPSBwYWNrZXRfc2VjcmV0X2tleTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBzZWNyZXRfa2V5ID0gcmVxdWlyZSgnLi9zZWNyZXRfa2V5LmpzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gc2VjcmV0X3N1YmtleSgpIHtcbiAgc2VjcmV0X2tleS5jYWxsKHRoaXMpO1xufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG4gIHBhY2tldCA9IHJlcXVpcmUoJy4vcGFja2V0LmpzJyksXG4gIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgY3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyksXG4gIHR5cGVfbXBpID0gcmVxdWlyZSgnLi4vdHlwZS9tcGkuanMnKSxcbiAgdHlwZV9rZXlpZCA9IHJlcXVpcmUoJy4uL3R5cGUva2V5aWQuanMnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIFNpZ25hdHVyZSBQYWNrZXQgKFRhZyAyKVxuICogXG4gKiBSRkM0NDgwIDUuMjpcbiAqIEEgU2lnbmF0dXJlIHBhY2tldCBkZXNjcmliZXMgYSBiaW5kaW5nIGJldHdlZW4gc29tZSBwdWJsaWMga2V5IGFuZFxuICogc29tZSBkYXRhLiAgVGhlIG1vc3QgY29tbW9uIHNpZ25hdHVyZXMgYXJlIGEgc2lnbmF0dXJlIG9mIGEgZmlsZSBvciBhXG4gKiBibG9jayBvZiB0ZXh0LCBhbmQgYSBzaWduYXR1cmUgdGhhdCBpcyBhIGNlcnRpZmljYXRpb24gb2YgYSBVc2VyIElELlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9zaWduYXR1cmUoKSB7XG5cbiAgdGhpcy52ZXJzaW9uID0gbnVsbDtcbiAgdGhpcy5zaWduYXR1cmVUeXBlID0gbnVsbDtcbiAgdGhpcy5oYXNoQWxnb3JpdGhtID0gbnVsbDtcbiAgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0gPSBudWxsO1xuXG4gIHRoaXMuc2lnbmF0dXJlRGF0YSA9IG51bGw7XG4gIHRoaXMuc2lnbmVkSGFzaFZhbHVlID0gbnVsbDtcbiAgdGhpcy5tcGkgPSBudWxsO1xuXG4gIHRoaXMuY3JlYXRlZCA9IG5ldyBEYXRlKCk7XG4gIHRoaXMuc2lnbmF0dXJlRXhwaXJhdGlvblRpbWUgPSBudWxsO1xuICB0aGlzLnNpZ25hdHVyZU5ldmVyRXhwaXJlcyA9IG51bGw7XG4gIHRoaXMuZXhwb3J0YWJsZSA9IG51bGw7XG4gIHRoaXMudHJ1c3RMZXZlbCA9IG51bGw7XG4gIHRoaXMudHJ1c3RBbW91bnQgPSBudWxsO1xuICB0aGlzLnJlZ3VsYXJFeHByZXNzaW9uID0gbnVsbDtcbiAgdGhpcy5yZXZvY2FibGUgPSBudWxsO1xuICB0aGlzLmtleUV4cGlyYXRpb25UaW1lID0gbnVsbDtcbiAgdGhpcy5rZXlOZXZlckV4cGlyZXMgPSBudWxsO1xuICB0aGlzLnByZWZlcnJlZFN5bW1ldHJpY0FsZ29yaXRobXMgPSBudWxsO1xuICB0aGlzLnJldm9jYXRpb25LZXlDbGFzcyA9IG51bGw7XG4gIHRoaXMucmV2b2NhdGlvbktleUFsZ29yaXRobSA9IG51bGw7XG4gIHRoaXMucmV2b2NhdGlvbktleUZpbmdlcnByaW50ID0gbnVsbDtcbiAgdGhpcy5pc3N1ZXJLZXlJZCA9IG5ldyB0eXBlX2tleWlkKCk7XG4gIHRoaXMubm90YXRpb24gPSBudWxsO1xuICB0aGlzLnByZWZlcnJlZEhhc2hBbGdvcml0aG1zID0gbnVsbDtcbiAgdGhpcy5wcmVmZXJyZWRDb21wcmVzc2lvbkFsZ29yaXRobXMgPSBudWxsO1xuICB0aGlzLmtleVNlcnZlclByZWZlcmVuY2VzID0gbnVsbDtcbiAgdGhpcy5wcmVmZXJyZWRLZXlTZXJ2ZXIgPSBudWxsO1xuICB0aGlzLmlzUHJpbWFyeVVzZXJJRCA9IG51bGw7XG4gIHRoaXMucG9saWN5VVJJID0gbnVsbDtcbiAgdGhpcy5rZXlGbGFncyA9IG51bGw7XG4gIHRoaXMuc2lnbmVyc1VzZXJJZCA9IG51bGw7XG4gIHRoaXMucmVhc29uRm9yUmV2b2NhdGlvbkZsYWcgPSBudWxsO1xuICB0aGlzLnJlYXNvbkZvclJldm9jYXRpb25TdHJpbmcgPSBudWxsO1xuICB0aGlzLmZlYXR1cmVzID0gbnVsbDtcbiAgdGhpcy5zaWduYXR1cmVUYXJnZXRQdWJsaWNLZXlBbGdvcml0aG0gPSBudWxsO1xuICB0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2hBbGdvcml0aG0gPSBudWxsO1xuICB0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2ggPSBudWxsO1xuICB0aGlzLmVtYmVkZGVkU2lnbmF0dXJlID0gbnVsbDtcblxuICB0aGlzLnZlcmlmaWVkID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIHBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgc2lnbmF0dXJlIHBhY2tldCAodGFnIDIpLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gYnl0ZXMgcGF5bG9hZCBvZiBhIHRhZyAyIHBhY2tldFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIHBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgYnl0ZXMgc3RyaW5nXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIGxlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mIGJ5dGVzIGF0IHBvc2l0aW9uXG4gICAqIEByZXR1cm4ge29wZW5wZ3BfcGFja2V0X2VuY3J5cHRlZGRhdGF9IG9iamVjdCByZXByZXNlbnRhdGlvblxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgaSA9IDA7XG5cbiAgICB0aGlzLnZlcnNpb24gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcbiAgICAvLyBzd2l0Y2ggb24gdmVyc2lvbiAoMyBhbmQgNClcbiAgICBzd2l0Y2ggKHRoaXMudmVyc2lvbikge1xuICAgICAgY2FzZSAzOlxuICAgICAgICAvLyBPbmUtb2N0ZXQgbGVuZ3RoIG9mIGZvbGxvd2luZyBoYXNoZWQgbWF0ZXJpYWwuIE1VU1QgYmUgNS5cbiAgICAgICAgaWYgKGJ5dGVzW2krK10uY2hhckNvZGVBdCgpICE9IDUpXG4gICAgICAgICAgdXRpbC5wcmludF9kZWJ1ZyhcIm9wZW5wZ3AucGFja2V0LnNpZ25hdHVyZS5qc1xcblwiICtcbiAgICAgICAgICAgICdpbnZhbGlkIE9uZS1vY3RldCBsZW5ndGggb2YgZm9sbG93aW5nIGhhc2hlZCBtYXRlcmlhbC4nICtcbiAgICAgICAgICAgICdNVVNUIGJlIDUuIEA6JyArIChpIC0gMSkpO1xuXG4gICAgICAgIHZhciBzaWdwb3MgPSBpO1xuICAgICAgICAvLyBPbmUtb2N0ZXQgc2lnbmF0dXJlIHR5cGUuXG4gICAgICAgIHRoaXMuc2lnbmF0dXJlVHlwZSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuXG4gICAgICAgIC8vIEZvdXItb2N0ZXQgY3JlYXRpb24gdGltZS5cbiAgICAgICAgdGhpcy5jcmVhdGVkID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIoaSwgNCkpO1xuICAgICAgICBpICs9IDQ7XG5cbiAgICAgICAgLy8gc3RvcmluZyBkYXRhIGFwcGVuZGVkIHRvIGRhdGEgd2hpY2ggZ2V0cyB2ZXJpZmllZFxuICAgICAgICB0aGlzLnNpZ25hdHVyZURhdGEgPSBieXRlcy5zdWJzdHJpbmcoc2lncG9zLCBpKTtcblxuICAgICAgICAvLyBFaWdodC1vY3RldCBLZXkgSUQgb2Ygc2lnbmVyLlxuICAgICAgICB0aGlzLmlzc3VlcktleUlkLnJlYWQoYnl0ZXMuc3Vic3RyaW5nKGksIGkgKyA4KSk7XG4gICAgICAgIGkgKz0gODtcblxuICAgICAgICAvLyBPbmUtb2N0ZXQgcHVibGljLWtleSBhbGdvcml0aG0uXG4gICAgICAgIHRoaXMucHVibGljS2V5QWxnb3JpdGhtID0gYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG5cbiAgICAgICAgLy8gT25lLW9jdGV0IGhhc2ggYWxnb3JpdGhtLlxuICAgICAgICB0aGlzLmhhc2hBbGdvcml0aG0gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlVHlwZSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuICAgICAgICB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSA9IGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuICAgICAgICB0aGlzLmhhc2hBbGdvcml0aG0gPSBieXRlc1tpKytdLmNoYXJDb2RlQXQoKTtcblxuICAgICAgICBmdW5jdGlvbiBzdWJwYWNrZXRzKGJ5dGVzKSB7XG4gICAgICAgICAgLy8gVHdvLW9jdGV0IHNjYWxhciBvY3RldCBjb3VudCBmb3IgZm9sbG93aW5nIHN1YnBhY2tldCBkYXRhLlxuICAgICAgICAgIHZhciBzdWJwYWNrZXRfbGVuZ3RoID0gdXRpbC5yZWFkTnVtYmVyKFxuICAgICAgICAgICAgYnl0ZXMuc3Vic3RyKDAsIDIpKTtcblxuICAgICAgICAgIHZhciBpID0gMjtcblxuICAgICAgICAgIC8vIHN1YnBhY2tldCBkYXRhIHNldCAoemVybyBvciBtb3JlIHN1YnBhY2tldHMpXG4gICAgICAgICAgdmFyIHN1YnBhY2tlZF9yZWFkID0gMDtcbiAgICAgICAgICB3aGlsZSAoaSA8IDIgKyBzdWJwYWNrZXRfbGVuZ3RoKSB7XG5cbiAgICAgICAgICAgIHZhciBsZW4gPSBwYWNrZXQucmVhZFNpbXBsZUxlbmd0aChieXRlcy5zdWJzdHIoaSkpO1xuICAgICAgICAgICAgaSArPSBsZW4ub2Zmc2V0O1xuXG4gICAgICAgICAgICB0aGlzLnJlYWRfc3ViX3BhY2tldChieXRlcy5zdWJzdHIoaSwgbGVuLmxlbikpO1xuXG4gICAgICAgICAgICBpICs9IGxlbi5sZW47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBoYXNoZWQgc3VicGFja2V0c1xuICAgICAgICBpICs9IHN1YnBhY2tldHMuY2FsbCh0aGlzLCBieXRlcy5zdWJzdHIoaSksIHRydWUpO1xuXG4gICAgICAgIC8vIEEgVjQgc2lnbmF0dXJlIGhhc2hlcyB0aGUgcGFja2V0IGJvZHlcbiAgICAgICAgLy8gc3RhcnRpbmcgZnJvbSBpdHMgZmlyc3QgZmllbGQsIHRoZSB2ZXJzaW9uIG51bWJlciwgdGhyb3VnaCB0aGUgZW5kXG4gICAgICAgIC8vIG9mIHRoZSBoYXNoZWQgc3VicGFja2V0IGRhdGEuICBUaHVzLCB0aGUgZmllbGRzIGhhc2hlZCBhcmUgdGhlXG4gICAgICAgIC8vIHNpZ25hdHVyZSB2ZXJzaW9uLCB0aGUgc2lnbmF0dXJlIHR5cGUsIHRoZSBwdWJsaWMta2V5IGFsZ29yaXRobSwgdGhlXG4gICAgICAgIC8vIGhhc2ggYWxnb3JpdGhtLCB0aGUgaGFzaGVkIHN1YnBhY2tldCBsZW5ndGgsIGFuZCB0aGUgaGFzaGVkXG4gICAgICAgIC8vIHN1YnBhY2tldCBib2R5LlxuICAgICAgICB0aGlzLnNpZ25hdHVyZURhdGEgPSBieXRlcy5zdWJzdHIoMCwgaSk7XG5cbiAgICAgICAgLy8gdW5oYXNoZWQgc3VicGFja2V0c1xuICAgICAgICBpICs9IHN1YnBhY2tldHMuY2FsbCh0aGlzLCBieXRlcy5zdWJzdHIoaSksIGZhbHNlKTtcblxuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVmVyc2lvbiAnICsgdmVyc2lvbiArICcgb2YgdGhlIHNpZ25hdHVyZSBpcyB1bnN1cHBvcnRlZC4nKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgLy8gVHdvLW9jdGV0IGZpZWxkIGhvbGRpbmcgbGVmdCAxNiBiaXRzIG9mIHNpZ25lZCBoYXNoIHZhbHVlLlxuICAgIHRoaXMuc2lnbmVkSGFzaFZhbHVlID0gYnl0ZXMuc3Vic3RyKGksIDIpO1xuICAgIGkgKz0gMjtcblxuICAgIHRoaXMuc2lnbmF0dXJlID0gYnl0ZXMuc3Vic3RyKGkpO1xuICB9O1xuXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zaWduYXR1cmVEYXRhICtcbiAgICAgIHV0aWwud3JpdGVOdW1iZXIoMCwgMikgKyAvLyBOdW1iZXIgb2YgdW5zaWduZWQgc3VicGFja2V0cy5cbiAgICB0aGlzLnNpZ25lZEhhc2hWYWx1ZSArXG4gICAgICB0aGlzLnNpZ25hdHVyZTtcbiAgfTtcblxuICAvKipcbiAgICogU2lnbnMgcHJvdmlkZWQgZGF0YS4gVGhpcyBuZWVkcyB0byBiZSBkb25lIHByaW9yIHRvIHNlcmlhbGl6YXRpb24uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIENvbnRhaW5zIHBhY2tldHMgdG8gYmUgc2lnbmVkLlxuICAgKiBAcGFyYW0ge29wZW5wZ3BfbXNnX3ByaXZhdGVrZXl9IHByaXZhdGVrZXkgcHJpdmF0ZSBrZXkgdXNlZCB0byBzaWduIHRoZSBtZXNzYWdlLiBcbiAgICovXG4gIHRoaXMuc2lnbiA9IGZ1bmN0aW9uKGtleSwgZGF0YSkge1xuICAgIHZhciBzaWduYXR1cmVUeXBlID0gZW51bXMud3JpdGUoZW51bXMuc2lnbmF0dXJlLCB0aGlzLnNpZ25hdHVyZVR5cGUpLFxuICAgICAgcHVibGljS2V5QWxnb3JpdGhtID0gZW51bXMud3JpdGUoZW51bXMucHVibGljS2V5LCB0aGlzLnB1YmxpY0tleUFsZ29yaXRobSksXG4gICAgICBoYXNoQWxnb3JpdGhtID0gZW51bXMud3JpdGUoZW51bXMuaGFzaCwgdGhpcy5oYXNoQWxnb3JpdGhtKTtcblxuICAgIHZhciByZXN1bHQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDQpO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHNpZ25hdHVyZVR5cGUpO1xuICAgIHJlc3VsdCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHB1YmxpY0tleUFsZ29yaXRobSk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoaGFzaEFsZ29yaXRobSk7XG5cbiAgICB0aGlzLmlzc3VlcktleUlkID0ga2V5LmdldEtleUlkKCk7XG5cbiAgICAvLyBBZGQgaGFzaGVkIHN1YnBhY2tldHNcbiAgICByZXN1bHQgKz0gdGhpcy53cml0ZV9hbGxfc3ViX3BhY2tldHMoKTtcblxuICAgIHRoaXMuc2lnbmF0dXJlRGF0YSA9IHJlc3VsdDtcblxuICAgIHZhciB0cmFpbGVyID0gdGhpcy5jYWxjdWxhdGVUcmFpbGVyKCk7XG5cbiAgICB2YXIgdG9IYXNoID0gdGhpcy50b1NpZ24oc2lnbmF0dXJlVHlwZSwgZGF0YSkgK1xuICAgICAgdGhpcy5zaWduYXR1cmVEYXRhICsgdHJhaWxlcjtcblxuICAgIHZhciBoYXNoID0gY3J5cHRvLmhhc2guZGlnZXN0KGhhc2hBbGdvcml0aG0sIHRvSGFzaCk7XG5cbiAgICB0aGlzLnNpZ25lZEhhc2hWYWx1ZSA9IGhhc2guc3Vic3RyKDAsIDIpO1xuXG4gICAgdGhpcy5zaWduYXR1cmUgPSBjcnlwdG8uc2lnbmF0dXJlLnNpZ24oaGFzaEFsZ29yaXRobSxcbiAgICAgIHB1YmxpY0tleUFsZ29yaXRobSwga2V5Lm1waSwgdG9IYXNoKTtcbiAgfTtcblxuICAvKipcbiAgICogQ3JlYXRlcyBzdHJpbmcgb2YgYnl0ZXMgd2l0aCBhbGwgc3VicGFja2V0IGRhdGFcbiAgICogQHJldHVybiB7U3RyaW5nfSBhIHN0cmluZy1yZXByZXNlbnRhdGlvbiBvZiBhIGFsbCBzdWJwYWNrZXQgZGF0YVxuICAgKi9cbiAgdGhpcy53cml0ZV9hbGxfc3ViX3BhY2tldHMgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgc3ViID0gZW51bXMuc2lnbmF0dXJlU3VicGFja2V0O1xuICAgIHZhciByZXN1bHQgPSAnJztcbiAgICB2YXIgYnl0ZXMgPSAnJztcbiAgICBpZiAodGhpcy5jcmVhdGVkICE9PSBudWxsKSB7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIuc2lnbmF0dXJlX2NyZWF0aW9uX3RpbWUsIHV0aWwud3JpdGVEYXRlKHRoaXMuY3JlYXRlZCkpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zaWduYXR1cmVFeHBpcmF0aW9uVGltZSAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLnNpZ25hdHVyZV9leHBpcmF0aW9uX3RpbWUsIHV0aWwud3JpdGVEYXRlKHRoaXMuc2lnbmF0dXJlRXhwaXJhdGlvblRpbWUpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuZXhwb3J0YWJsZSAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLmV4cG9ydGFibGVfY2VydGlmaWNhdGlvbiwgU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLmV4cG9ydGFibGUgPyAxIDogMCkpO1xuICAgIH1cbiAgICBpZiAodGhpcy50cnVzdExldmVsICE9PSBudWxsKSB7XG4gICAgICBieXRlcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy50cnVzdExldmVsKSArIFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy50cnVzdEFtb3VudCk7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIudHJ1c3Rfc2lnbmF0dXJlLCBieXRlcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnJlZ3VsYXJFeHByZXNzaW9uICE9PSBudWxsKSB7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIucmVndWxhcl9leHByZXNzaW9uLCB0aGlzLnJlZ3VsYXJFeHByZXNzaW9uKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucmV2b2NhYmxlICE9PSBudWxsKSB7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIucmV2b2NhYmxlLCBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMucmV2b2NhYmxlID8gMSA6IDApKTtcbiAgICB9XG4gICAgaWYgKHRoaXMua2V5RXhwaXJhdGlvblRpbWUgIT09IG51bGwpIHtcbiAgICAgIHJlc3VsdCArPSB3cml0ZV9zdWJfcGFja2V0KHN1Yi5rZXlfZXhwaXJhdGlvbl90aW1lLCB1dGlsLndyaXRlRGF0ZSh0aGlzLmtleUV4cGlyYXRpb25UaW1lKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnByZWZlcnJlZFN5bW1ldHJpY0FsZ29yaXRobXMgIT09IG51bGwpIHtcbiAgICAgIGJ5dGVzID0gdXRpbC5iaW4yc3RyKHRoaXMucHJlZmVycmVkU3ltbWV0cmljQWxnb3JpdGhtcyk7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIucHJlZmVycmVkX3N5bW1ldHJpY19hbGdvcml0aG1zLCBieXRlcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnJldm9jYXRpb25LZXlDbGFzcyAhPT0gbnVsbCkge1xuICAgICAgYnl0ZXMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMucmV2b2NhdGlvbktleUNsYXNzKTtcbiAgICAgIGJ5dGVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy5yZXZvY2F0aW9uS2V5QWxnb3JpdGhtKTtcbiAgICAgIGJ5dGVzICs9IHRoaXMucmV2b2NhdGlvbktleUZpbmdlcnByaW50O1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLnJldm9jYXRpb25fa2V5LCBieXRlcyk7XG4gICAgfVxuICAgIGlmICghdGhpcy5pc3N1ZXJLZXlJZC5pc051bGwoKSkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLmlzc3VlciwgdGhpcy5pc3N1ZXJLZXlJZC53cml0ZSgpKTtcbiAgICB9XG4gICAgaWYgKHRoaXMubm90YXRpb24gIT09IG51bGwpIHtcbiAgICAgIGZvciAodmFyIG5hbWUgaW4gdGhpcy5ub3RhdGlvbikge1xuICAgICAgICBpZiAodGhpcy5ub3RhdGlvbi5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgIHZhciB2YWx1ZSA9IHRoaXMubm90YXRpb25bbmFtZV07XG4gICAgICAgICAgYnl0ZXMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4ODApO1xuICAgICAgICAgIGJ5dGVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMCk7XG4gICAgICAgICAgYnl0ZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgwKTtcbiAgICAgICAgICBieXRlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuICAgICAgICAgIC8vIDIgb2N0ZXRzIG9mIG5hbWUgbGVuZ3RoXG4gICAgICAgICAgYnl0ZXMgKz0gdXRpbC53cml0ZU51bWJlcihuYW1lLmxlbmd0aCwgMik7XG4gICAgICAgICAgLy8gMiBvY3RldHMgb2YgdmFsdWUgbGVuZ3RoXG4gICAgICAgICAgYnl0ZXMgKz0gdXRpbC53cml0ZU51bWJlcih2YWx1ZS5sZW5ndGgsIDIpO1xuICAgICAgICAgIGJ5dGVzICs9IG5hbWUgKyB2YWx1ZTtcbiAgICAgICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIubm90YXRpb25fZGF0YSwgYnl0ZXMpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBcbiAgICBpZiAodGhpcy5wcmVmZXJyZWRIYXNoQWxnb3JpdGhtcyAhPT0gbnVsbCkge1xuICAgICAgYnl0ZXMgPSB1dGlsLmJpbjJzdHIodGhpcy5wcmVmZXJyZWRIYXNoQWxnb3JpdGhtcyk7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIucHJlZmVycmVkX2hhc2hfYWxnb3JpdGhtcywgYnl0ZXMpO1xuICAgIH1cbiAgICBpZiAodGhpcy5wcmVmZXJyZWRDb21wcmVzc2lvbkFsZ29yaXRobXMgIT09IG51bGwpIHtcbiAgICAgIGJ5dGVzID0gdXRpbC5iaW4yc3RyKHRoaXMucHJlZmVycmVkQ29tcHJlc3Npb25BbGdvcml0aG1zKTtcbiAgICAgIHJlc3VsdCArPSB3cml0ZV9zdWJfcGFja2V0KHN1Yi5wcmVmZXJyZWRfaGFzaF9hbGdvcml0aG1zLCBieXRlcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLmtleVNlcnZlclByZWZlcmVuY2VzICE9PSBudWxsKSB7XG4gICAgICBieXRlcyA9IHV0aWwuYmluMnN0cih0aGlzLmtleVNlcnZlclByZWZlcmVuY2VzKTtcbiAgICAgIHJlc3VsdCArPSB3cml0ZV9zdWJfcGFja2V0KHN1Yi5rZXlfc2VydmVyX3ByZWZlcmVuY2VzLCBieXRlcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLnByZWZlcnJlZEtleVNlcnZlciAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLnByZWZlcnJlZF9rZXlfc2VydmVyLCB0aGlzLnByZWZlcnJlZEtleVNlcnZlcik7XG4gICAgfVxuICAgIGlmICh0aGlzLmlzUHJpbWFyeVVzZXJJRCAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLnByaW1hcnlfdXNlcl9pZCwgU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLmlzUHJpbWFyeVVzZXJJRCA/IDEgOiAwKSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnBvbGljeVVSSSAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLnBvbGljeV91cmksIHRoaXMucG9saWN5VVJJKTsgXG4gICAgfVxuICAgIGlmICh0aGlzLmtleUZsYWdzICE9PSBudWxsKSB7XG4gICAgICBieXRlcyA9IHV0aWwuYmluMnN0cih0aGlzLmtleUZsYWdzKTtcbiAgICAgIHJlc3VsdCArPSB3cml0ZV9zdWJfcGFja2V0KHN1Yi5rZXlfZmxhZ3MsIGJ5dGVzKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc2lnbmVyc1VzZXJJZCAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLnNpZ25lcnNfdXNlcl9pZCwgdGhpcy5zaWduZXJzVXNlcklkKTsgXG4gICAgfVxuICAgIGlmICh0aGlzLnJlYXNvbkZvclJldm9jYXRpb25GbGFnICE9PSBudWxsKSB7XG4gICAgICBieXRlcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy5yZWFzb25Gb3JSZXZvY2F0aW9uRmxhZyk7XG4gICAgICBieXRlcyArPSB0aGlzLnJlYXNvbkZvclJldm9jYXRpb25TdHJpbmc7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIucmVhc29uX2Zvcl9yZXZvY2F0aW9uLCBieXRlcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLmZlYXR1cmVzICE9PSBudWxsKSB7XG4gICAgICBieXRlcyA9IHV0aWwuYmluMnN0cih0aGlzLmZlYXR1cmVzKTtcbiAgICAgIHJlc3VsdCArPSB3cml0ZV9zdWJfcGFja2V0KHN1Yi5mZWF0dXJlcywgYnl0ZXMpO1xuICAgIH1cbiAgICBpZiAodGhpcy5zaWduYXR1cmVUYXJnZXRQdWJsaWNLZXlBbGdvcml0aG0gIT09IG51bGwpIHtcbiAgICAgIGJ5dGVzID0gU3RyaW5nLmZyb21DaGFyQ29kZSh0aGlzLnNpZ25hdHVyZVRhcmdldFB1YmxpY0tleUFsZ29yaXRobSk7XG4gICAgICBieXRlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMuc2lnbmF0dXJlVGFyZ2V0SGFzaEFsZ29yaXRobSk7XG4gICAgICBieXRlcyArPSB0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2g7XG4gICAgICByZXN1bHQgKz0gd3JpdGVfc3ViX3BhY2tldChzdWIuc2lnbmF0dXJlX3RhcmdldCwgYnl0ZXMpO1xuICAgIH1cbiAgICBpZiAodGhpcy5lbWJlZGRlZFNpZ25hdHVyZSAhPT0gbnVsbCkge1xuICAgICAgcmVzdWx0ICs9IHdyaXRlX3N1Yl9wYWNrZXQoc3ViLmVtYmVkZGVkX3NpZ25hdHVyZSwgdGhpcy5lbWJlZGRlZFNpZ25hdHVyZS53cml0ZSgpKTtcbiAgICB9XG4gICAgcmVzdWx0ID0gdXRpbC53cml0ZU51bWJlcihyZXN1bHQubGVuZ3RoLCAyKSArIHJlc3VsdDtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8qKlxuICAgKiBjcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgc3ViIHNpZ25hdHVyZSBwYWNrZXQgKFNlZSBSRkMgNDg4MCA1LjIuMy4xKVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHR5cGUgc3VicGFja2V0IHNpZ25hdHVyZSB0eXBlLiBTaWduYXR1cmUgdHlwZXMgYXMgZGVzY3JpYmVkIFxuICAgKiBpbiBSRkM0ODgwIFNlY3Rpb24gNS4yLjMuMlxuICAgKiBAcGFyYW0ge1N0cmluZ30gZGF0YSBkYXRhIHRvIGJlIGluY2x1ZGVkXG4gICAqIEByZXR1cm4ge1N0cmluZ30gYSBzdHJpbmctcmVwcmVzZW50YXRpb24gb2YgYSBzdWIgc2lnbmF0dXJlIHBhY2tldCAoU2VlIFJGQyA0ODgwIDUuMi4zLjEpXG4gICAqL1xuICBmdW5jdGlvbiB3cml0ZV9zdWJfcGFja2V0KHR5cGUsIGRhdGEpIHtcbiAgICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgICByZXN1bHQgKz0gcGFja2V0LndyaXRlU2ltcGxlTGVuZ3RoKGRhdGEubGVuZ3RoICsgMSk7XG4gICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUodHlwZSk7XG4gICAgcmVzdWx0ICs9IGRhdGE7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIFY0IHNpZ25hdHVyZSBzdWIgcGFja2V0c1xuXG4gIHRoaXMucmVhZF9zdWJfcGFja2V0ID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgbXlwb3MgPSAwO1xuXG4gICAgZnVuY3Rpb24gcmVhZF9hcnJheShwcm9wLCBieXRlcykge1xuICAgICAgdGhpc1twcm9wXSA9IFtdO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRoaXNbcHJvcF0ucHVzaChieXRlc1tpXS5jaGFyQ29kZUF0KCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRoZSBsZWZ0d29zdCBiaXQgZGVub3RlcyBhIFwiY3JpdGljYWxcIiBwYWNrZXQsIGJ1dCB3ZSBpZ25vcmUgaXQuXG4gICAgdmFyIHR5cGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgJiAweDdGO1xuXG4gICAgLy8gc3VicGFja2V0IHR5cGVcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgLy8gU2lnbmF0dXJlIENyZWF0aW9uIFRpbWVcbiAgICAgICAgdGhpcy5jcmVhdGVkID0gdXRpbC5yZWFkRGF0ZShieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIC8vIFNpZ25hdHVyZSBFeHBpcmF0aW9uIFRpbWVcbiAgICAgICAgdmFyIHRpbWUgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXG4gICAgICAgIHRoaXMuc2lnbmF0dXJlTmV2ZXJFeHBpcmVzID0gdGltZS5nZXRUaW1lKCkgPT0gMDtcbiAgICAgICAgdGhpcy5zaWduYXR1cmVFeHBpcmF0aW9uVGltZSA9IHRpbWU7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIC8vIEV4cG9ydGFibGUgQ2VydGlmaWNhdGlvblxuICAgICAgICB0aGlzLmV4cG9ydGFibGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgPT0gMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDU6XG4gICAgICAgIC8vIFRydXN0IFNpZ25hdHVyZVxuICAgICAgICB0aGlzLnRydXN0TGV2ZWwgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMudHJ1c3RBbW91bnQgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA2OlxuICAgICAgICAvLyBSZWd1bGFyIEV4cHJlc3Npb25cbiAgICAgICAgdGhpcy5yZWd1bGFyRXhwcmVzc2lvbiA9IGJ5dGVzLnN1YnN0cihteXBvcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA3OlxuICAgICAgICAvLyBSZXZvY2FibGVcbiAgICAgICAgdGhpcy5yZXZvY2FibGUgPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCkgPT0gMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDk6XG4gICAgICAgIC8vIEtleSBFeHBpcmF0aW9uIFRpbWVcbiAgICAgICAgdmFyIHRpbWUgPSB1dGlsLnJlYWREYXRlKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuXG4gICAgICAgIHRoaXMua2V5RXhwaXJhdGlvblRpbWUgPSB0aW1lO1xuICAgICAgICB0aGlzLmtleU5ldmVyRXhwaXJlcyA9IHRpbWUuZ2V0VGltZSgpID09IDA7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDExOlxuICAgICAgICAvLyBQcmVmZXJyZWQgU3ltbWV0cmljIEFsZ29yaXRobXNcbiAgICAgICAgdGhpcy5wcmVmZXJyZWRTeW1tZXRyaWNBbGdvcml0aG1zID0gW107XG5cbiAgICAgICAgd2hpbGUgKG15cG9zICE9IGJ5dGVzLmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMucHJlZmVycmVkU3ltbWV0cmljQWxnb3JpdGhtcy5wdXNoKGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKSk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTI6XG4gICAgICAgIC8vIFJldm9jYXRpb24gS2V5XG4gICAgICAgIC8vICgxIG9jdGV0IG9mIGNsYXNzLCAxIG9jdGV0IG9mIHB1YmxpYy1rZXkgYWxnb3JpdGhtIElELCAyMFxuICAgICAgICAvLyBvY3RldHMgb2ZcbiAgICAgICAgLy8gZmluZ2VycHJpbnQpXG4gICAgICAgIHRoaXMucmV2b2NhdGlvbktleUNsYXNzID0gYnl0ZXNbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICB0aGlzLnJldm9jYXRpb25LZXlBbGdvcml0aG0gPSBieXRlc1tteXBvcysrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIHRoaXMucmV2b2NhdGlvbktleUZpbmdlcnByaW50ID0gYnl0ZXMuc3Vic3RyKG15cG9zLCAyMCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIDE2OlxuICAgICAgICAvLyBJc3N1ZXJcbiAgICAgICAgdGhpcy5pc3N1ZXJLZXlJZC5yZWFkKGJ5dGVzLnN1YnN0cihteXBvcykpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAyMDpcbiAgICAgICAgLy8gTm90YXRpb24gRGF0YVxuICAgICAgICAvLyBXZSBkb24ndCBrbm93IGhvdyB0byBoYW5kbGUgYW55dGhpbmcgYnV0IGEgdGV4dCBmbGFnZ2VkIGRhdGEuXG4gICAgICAgIGlmIChieXRlc1tteXBvc10uY2hhckNvZGVBdCgpID09IDB4ODApIHtcblxuICAgICAgICAgIC8vIFdlIGV4dHJhY3Qga2V5L3ZhbHVlIHR1cGxlIGZyb20gdGhlIGJ5dGUgc3RyZWFtLlxuICAgICAgICAgIG15cG9zICs9IDQ7XG4gICAgICAgICAgdmFyIG0gPSB1dGlsLnJlYWROdW1iZXIoYnl0ZXMuc3Vic3RyKG15cG9zLCAyKSk7XG4gICAgICAgICAgbXlwb3MgKz0gMlxuICAgICAgICAgIHZhciBuID0gdXRpbC5yZWFkTnVtYmVyKGJ5dGVzLnN1YnN0cihteXBvcywgMikpO1xuICAgICAgICAgIG15cG9zICs9IDJcblxuICAgICAgICAgIHZhciBuYW1lID0gYnl0ZXMuc3Vic3RyKG15cG9zLCBtKSxcbiAgICAgICAgICAgIHZhbHVlID0gYnl0ZXMuc3Vic3RyKG15cG9zICsgbSwgbik7XG5cbiAgICAgICAgICB0aGlzLm5vdGF0aW9uID0gdGhpcy5ub3RhdGlvbiB8fCB7fTtcbiAgICAgICAgICB0aGlzLm5vdGF0aW9uW25hbWVdID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSB0aHJvdyBuZXcgRXJyb3IoXCJVbnN1cHBvcnRlZCBub3RhdGlvbiBmbGFnLlwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDIxOlxuICAgICAgICAvLyBQcmVmZXJyZWQgSGFzaCBBbGdvcml0aG1zXG4gICAgICAgIHJlYWRfYXJyYXkuY2FsbCh0aGlzLCAncHJlZmVycmVkSGFzaEFsZ29yaXRobXMnLCBieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDIyOlxuICAgICAgICAvLyBQcmVmZXJyZWQgQ29tcHJlc3Npb24gQWxnb3JpdGhtc1xuICAgICAgICByZWFkX2FycmF5LmNhbGwodGhpcywgJ3ByZWZlcnJlZENvbXByZXNzaW9uQWxnb3JpdGhtcyAnLCBieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDIzOlxuICAgICAgICAvLyBLZXkgU2VydmVyIFByZWZlcmVuY2VzXG4gICAgICAgIHJlYWRfYXJyYXkuY2FsbCh0aGlzLCAna2V5U2VydmVyUHJlZmVyZW5jZXNzJywgYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyNDpcbiAgICAgICAgLy8gUHJlZmVycmVkIEtleSBTZXJ2ZXJcbiAgICAgICAgdGhpcy5wcmVmZXJyZWRLZXlTZXJ2ZXIgPSBieXRlcy5zdWJzdHIobXlwb3MpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjU6XG4gICAgICAgIC8vIFByaW1hcnkgVXNlciBJRFxuICAgICAgICB0aGlzLmlzUHJpbWFyeVVzZXJJRCA9IGJ5dGVzW215cG9zKytdICE9IDA7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyNjpcbiAgICAgICAgLy8gUG9saWN5IFVSSVxuICAgICAgICB0aGlzLnBvbGljeVVSSSA9IGJ5dGVzLnN1YnN0cihteXBvcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyNzpcbiAgICAgICAgLy8gS2V5IEZsYWdzXG4gICAgICAgIHJlYWRfYXJyYXkuY2FsbCh0aGlzLCAna2V5RmxhZ3MnLCBieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI4OlxuICAgICAgICAvLyBTaWduZXIncyBVc2VyIElEXG4gICAgICAgIHRoaXMuc2lnbmVyc1VzZXJJZCArPSBieXRlcy5zdWJzdHIobXlwb3MpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjk6XG4gICAgICAgIC8vIFJlYXNvbiBmb3IgUmV2b2NhdGlvblxuICAgICAgICB0aGlzLnJlYXNvbkZvclJldm9jYXRpb25GbGFnID0gYnl0ZXNbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuICAgICAgICB0aGlzLnJlYXNvbkZvclJldm9jYXRpb25TdHJpbmcgPSBieXRlcy5zdWJzdHIobXlwb3MpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzA6XG4gICAgICAgIC8vIEZlYXR1cmVzXG4gICAgICAgIHJlYWRfYXJyYXkuY2FsbCh0aGlzLCAnZmVhdHVyZXMnLCBieXRlcy5zdWJzdHIobXlwb3MpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDMxOlxuICAgICAgICAvLyBTaWduYXR1cmUgVGFyZ2V0XG4gICAgICAgIC8vICgxIG9jdGV0IHB1YmxpYy1rZXkgYWxnb3JpdGhtLCAxIG9jdGV0IGhhc2ggYWxnb3JpdGhtLCBOIG9jdGV0cyBoYXNoKVxuICAgICAgICB0aGlzLnNpZ25hdHVyZVRhcmdldFB1YmxpY0tleUFsZ29yaXRobSA9IGJ5dGVzW215cG9zKytdLmNoYXJDb2RlQXQoKTtcbiAgICAgICAgdGhpcy5zaWduYXR1cmVUYXJnZXRIYXNoQWxnb3JpdGhtID0gYnl0ZXNbbXlwb3MrK10uY2hhckNvZGVBdCgpO1xuXG4gICAgICAgIHZhciBsZW4gPSBjcnlwdG8uZ2V0SGFzaEJ5dGVMZW5ndGgodGhpcy5zaWduYXR1cmVUYXJnZXRIYXNoQWxnb3JpdGhtKTtcblxuICAgICAgICB0aGlzLnNpZ25hdHVyZVRhcmdldEhhc2ggPSBieXRlcy5zdWJzdHIobXlwb3MsIGxlbik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzMjpcbiAgICAgICAgLy8gRW1iZWRkZWQgU2lnbmF0dXJlXG4gICAgICAgIHRoaXMuZW1iZWRkZWRTaWduYXR1cmUgPSBuZXcgcGFja2V0X3NpZ25hdHVyZSgpO1xuICAgICAgICB0aGlzLmVtYmVkZGVkU2lnbmF0dXJlLnJlYWQoYnl0ZXMuc3Vic3RyKG15cG9zKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdXRpbC5wcmludF9lcnJvcihcIm9wZW5wZ3AucGFja2V0LnNpZ25hdHVyZS5qc1xcblwiICtcbiAgICAgICAgICAndW5rbm93biBzaWduYXR1cmUgc3VicGFja2V0IHR5cGUgJyArIHR5cGUgKyBcIiBAOlwiICsgbXlwb3MgK1xuICAgICAgICAgIFwiIHN1YnBsZW46XCIgKyBzdWJwbGVuICsgXCIgbGVuOlwiICsgbGVuKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9O1xuXG4gIC8vIFByb2R1Y2VzIGRhdGEgdG8gcHJvZHVjZSBzaWduYXR1cmUgb25cbiAgdGhpcy50b1NpZ24gPSBmdW5jdGlvbih0eXBlLCBkYXRhKSB7XG4gICAgdmFyIHQgPSBlbnVtcy5zaWduYXR1cmU7XG5cbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgdC5iaW5hcnk6XG4gICAgICAvLyBjb252ZXJzaW9uIHRvIENSTEYgbGluZSBlbmRpbmdzIGRvbmUgaW4gbGl0ZXJhbCBkYXRhIHBhY2tldFxuICAgICAgY2FzZSB0LnRleHQ6XG4gICAgICAgIHJldHVybiBkYXRhLmdldEJ5dGVzKCk7XG5cbiAgICAgIGNhc2UgdC5zdGFuZGFsb25lOlxuICAgICAgICByZXR1cm4gJyc7XG5cbiAgICAgIGNhc2UgdC5jZXJ0X2dlbmVyaWM6XG4gICAgICBjYXNlIHQuY2VydF9wZXJzb25hOlxuICAgICAgY2FzZSB0LmNlcnRfY2FzdWFsOlxuICAgICAgY2FzZSB0LmNlcnRfcG9zaXRpdmU6XG4gICAgICBjYXNlIHQuY2VydF9yZXZvY2F0aW9uOlxuICAgICAgICB7XG4gICAgICAgICAgdmFyIHBhY2tldCwgdGFnO1xuXG4gICAgICAgICAgaWYgKGRhdGEudXNlcmlkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRhZyA9IDB4QjQ7XG4gICAgICAgICAgICBwYWNrZXQgPSBkYXRhLnVzZXJpZDtcbiAgICAgICAgICB9IGVsc2UgaWYgKGRhdGEudXNlcmF0dHJpYnV0ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0YWcgPSAweEQxO1xuICAgICAgICAgICAgcGFja2V0ID0gZGF0YS51c2VyYXR0cmlidXRlO1xuICAgICAgICAgIH0gZWxzZSB0aHJvdyBuZXcgRXJyb3IoJ0VpdGhlciBhIHVzZXJpZCBvciB1c2VyYXR0cmlidXRlIHBhY2tldCBuZWVkcyB0byBiZSAnICtcbiAgICAgICAgICAgICAgJ3N1cHBsaWVkIGZvciBjZXJ0aWZpY2F0aW9uLicpO1xuXG4gICAgICAgICAgdmFyIGJ5dGVzID0gcGFja2V0LndyaXRlKCk7XG5cbiAgICAgICAgICByZXR1cm4gdGhpcy50b1NpZ24odC5rZXksIGRhdGEpICtcbiAgICAgICAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUodGFnKSArXG4gICAgICAgICAgICB1dGlsLndyaXRlTnVtYmVyKGJ5dGVzLmxlbmd0aCwgNCkgK1xuICAgICAgICAgICAgYnl0ZXM7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgdC5zdWJrZXlfYmluZGluZzpcbiAgICAgIGNhc2UgdC5rZXlfYmluZGluZzpcbiAgICAgICAge1xuICAgICAgICAgIHJldHVybiB0aGlzLnRvU2lnbih0LmtleSwgZGF0YSkgKyB0aGlzLnRvU2lnbih0LmtleSwge1xuICAgICAgICAgICAga2V5OiBkYXRhLmJpbmRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSB0LmtleTpcbiAgICAgICAge1xuICAgICAgICAgIGlmIChkYXRhLmtleSA9PSB1bmRlZmluZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBwYWNrZXQgaXMgcmVxdWlyZWQgZm9yIHRoaXMgc2lndGF0dXJlLicpO1xuXG4gICAgICAgICAgcmV0dXJuIGRhdGEua2V5LndyaXRlT2xkKCk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgdC5rZXlfcmV2b2NhdGlvbjpcbiAgICAgIGNhc2UgdC5zdWJrZXlfcmV2b2NhdGlvbjpcbiAgICAgICAgcmV0dXJuIHRoaXMudG9TaWduKHQua2V5LCBkYXRhKTtcbiAgICAgIGNhc2UgdC50aW1lc3RhbXA6XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIGNhc2UgdC50aGlyZF9wYXJ0eTpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb3QgaW1wbGVtZW50ZWQnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gc2lnbmF0dXJlIHR5cGUuJylcbiAgICB9XG4gIH1cblxuXG4gIHRoaXMuY2FsY3VsYXRlVHJhaWxlciA9IGZ1bmN0aW9uKCkge1xuICAgIC8vIGNhbGN1bGF0aW5nIHRoZSB0cmFpbGVyXG4gICAgdmFyIHRyYWlsZXIgPSAnJztcbiAgICAvLyBWMyBzaWduYXR1cmVzIGRvbid0IGhhdmUgYSB0cmFpbGVyXG4gICAgaWYgKHRoaXMudmVyc2lvbiA9PSAzKSByZXR1cm4gdHJhaWxlcjtcbiAgICB0cmFpbGVyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoNCk7IC8vIFZlcnNpb25cbiAgICB0cmFpbGVyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoMHhGRik7XG4gICAgdHJhaWxlciArPSB1dGlsLndyaXRlTnVtYmVyKHRoaXMuc2lnbmF0dXJlRGF0YS5sZW5ndGgsIDQpO1xuICAgIHJldHVybiB0cmFpbGVyXG4gIH1cblxuXG4gIC8qKlxuICAgKiB2ZXJpZnlzIHRoZSBzaWduYXR1cmUgcGFja2V0LiBOb3RlOiBub3Qgc2lnbmF0dXJlIHR5cGVzIGFyZSBpbXBsZW1lbnRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IGRhdGEgZGF0YSB3aGljaCBvbiB0aGUgc2lnbmF0dXJlIGFwcGxpZXNcbiAgICogQHBhcmFtIHtwdWJsaWNfc3Via2V5fHBhY2tldF9wdWJsaWNfa2V5fSBrZXkgdGhlIHB1YmxpYyBrZXkgdG8gdmVyaWZ5IHRoZSBzaWduYXR1cmVcbiAgICogQHJldHVybiB7Ym9vbGVhbn0gVHJ1ZSBpZiBtZXNzYWdlIGlzIHZlcmlmaWVkLCBlbHNlIGZhbHNlLlxuICAgKi9cbiAgdGhpcy52ZXJpZnkgPSBmdW5jdGlvbihrZXksIGRhdGEpIHtcbiAgICB2YXIgc2lnbmF0dXJlVHlwZSA9IGVudW1zLndyaXRlKGVudW1zLnNpZ25hdHVyZSwgdGhpcy5zaWduYXR1cmVUeXBlKSxcbiAgICAgIHB1YmxpY0tleUFsZ29yaXRobSA9IGVudW1zLndyaXRlKGVudW1zLnB1YmxpY0tleSwgdGhpcy5wdWJsaWNLZXlBbGdvcml0aG0pLFxuICAgICAgaGFzaEFsZ29yaXRobSA9IGVudW1zLndyaXRlKGVudW1zLmhhc2gsIHRoaXMuaGFzaEFsZ29yaXRobSk7XG5cbiAgICB2YXIgYnl0ZXMgPSB0aGlzLnRvU2lnbihzaWduYXR1cmVUeXBlLCBkYXRhKSxcbiAgICAgIHRyYWlsZXIgPSB0aGlzLmNhbGN1bGF0ZVRyYWlsZXIoKTtcblxuXG4gICAgdmFyIG1waWNvdW50ID0gMDtcbiAgICAvLyBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBSU0Egc2lnbmF0dXJlczpcbiAgICAvLyBcdCAgICAtIG11bHRpcHJlY2lzaW9uIG51bWJlciAoTVBJKSBvZiBSU0Egc2lnbmF0dXJlIHZhbHVlIG0qKmQgbW9kIG4uXG4gICAgaWYgKHB1YmxpY0tleUFsZ29yaXRobSA+IDAgJiYgcHVibGljS2V5QWxnb3JpdGhtIDwgNClcbiAgICAgIG1waWNvdW50ID0gMTtcbiAgICAvLyAgICBBbGdvcml0aG0tU3BlY2lmaWMgRmllbGRzIGZvciBEU0Egc2lnbmF0dXJlczpcbiAgICAvLyAgICAgIC0gTVBJIG9mIERTQSB2YWx1ZSByLlxuICAgIC8vICAgICAgLSBNUEkgb2YgRFNBIHZhbHVlIHMuXG4gICAgZWxzZSBpZiAocHVibGljS2V5QWxnb3JpdGhtID09IDE3KVxuICAgICAgbXBpY291bnQgPSAyO1xuXG4gICAgdmFyIG1waSA9IFtdLFxuICAgICAgaSA9IDA7XG4gICAgZm9yICh2YXIgaiA9IDA7IGogPCBtcGljb3VudDsgaisrKSB7XG4gICAgICBtcGlbal0gPSBuZXcgdHlwZV9tcGkoKTtcbiAgICAgIGkgKz0gbXBpW2pdLnJlYWQodGhpcy5zaWduYXR1cmUuc3Vic3RyKGkpKTtcbiAgICB9XG5cbiAgICB0aGlzLnZlcmlmaWVkID0gY3J5cHRvLnNpZ25hdHVyZS52ZXJpZnkocHVibGljS2V5QWxnb3JpdGhtLFxuICAgICAgaGFzaEFsZ29yaXRobSwgbXBpLCBrZXkubXBpLFxuICAgICAgYnl0ZXMgKyB0aGlzLnNpZ25hdHVyZURhdGEgKyB0cmFpbGVyKTtcblxuICAgIHJldHVybiB0aGlzLnZlcmlmaWVkO1xuICB9XG59XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgY3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBTeW0uIEVuY3J5cHRlZCBJbnRlZ3JpdHkgUHJvdGVjdGVkIERhdGEgXG4gKiBQYWNrZXQgKFRhZyAxOClcbiAqIFxuICogUkZDNDg4MCA1LjEzOiBUaGUgU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgSW50ZWdyaXR5IFByb3RlY3RlZCBEYXRhIHBhY2tldCBpc1xuICogYSB2YXJpYW50IG9mIHRoZSBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIHBhY2tldC4gSXQgaXMgYSBuZXcgZmVhdHVyZVxuICogY3JlYXRlZCBmb3IgT3BlblBHUCB0aGF0IGFkZHJlc3NlcyB0aGUgcHJvYmxlbSBvZiBkZXRlY3RpbmcgYSBtb2RpZmljYXRpb24gdG9cbiAqIGVuY3J5cHRlZCBkYXRhLiBJdCBpcyB1c2VkIGluIGNvbWJpbmF0aW9uIHdpdGggYSBNb2RpZmljYXRpb24gRGV0ZWN0aW9uIENvZGVcbiAqIHBhY2tldC5cbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9zeW1fZW5jcnlwdGVkX2ludGVncml0eV9wcm90ZWN0ZWQoKSB7XG4gIC8qKiBUaGUgZW5jcnlwdGVkIHBheWxvYWQuICovXG4gIHRoaXMuZW5jcnlwdGVkID0gbnVsbDsgLy8gc3RyaW5nXG4gIC8qKiBAdHlwZSB7Qm9vbGVhbn1cbiAgICogSWYgYWZ0ZXIgZGVjcnlwdGluZyB0aGUgcGFja2V0IHRoaXMgaXMgc2V0IHRvIHRydWUsXG4gICAqIGEgbW9kaWZpY2F0aW9uIGhhcyBiZWVuIGRldGVjdGVkIGFuZCB0aHVzIHRoZSBjb250ZW50c1xuICAgKiBzaG91bGQgYmUgZGlzY2FyZGVkLlxuICAgKi9cbiAgdGhpcy5tb2RpZmljYXRpb24gPSBmYWxzZTtcbiAgdGhpcy5wYWNrZXRzO1xuXG5cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICAvLyAtIEEgb25lLW9jdGV0IHZlcnNpb24gbnVtYmVyLiBUaGUgb25seSBjdXJyZW50bHkgZGVmaW5lZCB2YWx1ZSBpc1xuICAgIC8vIDEuXG4gICAgdmFyIHZlcnNpb24gPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG5cbiAgICBpZiAodmVyc2lvbiAhPSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcGFja2V0IHZlcnNpb24uJyk7XG4gICAgfVxuXG4gICAgLy8gLSBFbmNyeXB0ZWQgZGF0YSwgdGhlIG91dHB1dCBvZiB0aGUgc2VsZWN0ZWQgc3ltbWV0cmljLWtleSBjaXBoZXJcbiAgICAvLyAgIG9wZXJhdGluZyBpbiBDaXBoZXIgRmVlZGJhY2sgbW9kZSB3aXRoIHNoaWZ0IGFtb3VudCBlcXVhbCB0byB0aGVcbiAgICAvLyAgIGJsb2NrIHNpemUgb2YgdGhlIGNpcGhlciAoQ0ZCLW4gd2hlcmUgbiBpcyB0aGUgYmxvY2sgc2l6ZSkuXG4gICAgdGhpcy5lbmNyeXB0ZWQgPSBieXRlcy5zdWJzdHIoMSk7XG4gIH1cblxuICB0aGlzLndyaXRlID0gZnVuY3Rpb24oKSB7XG5cbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgxKSAvLyBWZXJzaW9uXG4gICAgKyB0aGlzLmVuY3J5cHRlZDtcbiAgfVxuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKHNlc3Npb25LZXlBbGdvcml0aG0sIGtleSkge1xuICAgIHZhciBieXRlcyA9IHRoaXMucGFja2V0cy53cml0ZSgpXG5cbiAgICB2YXIgcHJlZml4cmFuZG9tID0gY3J5cHRvLmdldFByZWZpeFJhbmRvbShzZXNzaW9uS2V5QWxnb3JpdGhtKTtcbiAgICB2YXIgcHJlZml4ID0gcHJlZml4cmFuZG9tICsgcHJlZml4cmFuZG9tLmNoYXJBdChwcmVmaXhyYW5kb20ubGVuZ3RoIC0gMikgKyBwcmVmaXhyYW5kb20uY2hhckF0KHByZWZpeHJhbmRvbS5sZW5ndGggLVxuICAgICAgMSlcblxuICAgIHZhciB0b2hhc2ggPSBieXRlcztcblxuXG4gICAgLy8gTW9kaWZpY2F0aW9uIGRldGVjdGlvbiBjb2RlIHBhY2tldC5cbiAgICB0b2hhc2ggKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweEQzKTtcbiAgICB0b2hhc2ggKz0gU3RyaW5nLmZyb21DaGFyQ29kZSgweDE0KTtcblxuXG4gICAgdG9oYXNoICs9IGNyeXB0by5oYXNoLnNoYTEocHJlZml4ICsgdG9oYXNoKTtcblxuXG4gICAgdGhpcy5lbmNyeXB0ZWQgPSBjcnlwdG8uY2ZiLmVuY3J5cHQocHJlZml4cmFuZG9tLFxuICAgICAgc2Vzc2lvbktleUFsZ29yaXRobSwgdG9oYXNoLCBrZXksIGZhbHNlKS5zdWJzdHJpbmcoMCxcbiAgICAgIHByZWZpeC5sZW5ndGggKyB0b2hhc2gubGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyB0aGUgZW5jcnlwdGVkIGRhdGEgY29udGFpbmVkIGluIHRoaXMgb2JqZWN0IHJlYWRfcGFja2V0IG11c3RcbiAgICogaGF2ZSBiZWVuIGNhbGxlZCBiZWZvcmVcbiAgICogXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gc2Vzc2lvbktleUFsZ29yaXRobVxuICAgKiAgICAgICAgICAgIFRoZSBzZWxlY3RlZCBzeW1tZXRyaWMgZW5jcnlwdGlvbiBhbGdvcml0aG0gdG8gYmUgdXNlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30ga2V5IFRoZSBrZXkgb2YgY2lwaGVyIGJsb2Nrc2l6ZSBsZW5ndGggdG8gYmUgdXNlZFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSBkZWNyeXB0ZWQgZGF0YSBvZiB0aGlzIHBhY2tldFxuICAgKi9cbiAgdGhpcy5kZWNyeXB0ID0gZnVuY3Rpb24oc2Vzc2lvbktleUFsZ29yaXRobSwga2V5KSB7XG4gICAgdmFyIGRlY3J5cHRlZCA9IGNyeXB0by5jZmIuZGVjcnlwdChcbiAgICAgIHNlc3Npb25LZXlBbGdvcml0aG0sIGtleSwgdGhpcy5lbmNyeXB0ZWQsIGZhbHNlKTtcblxuXG4gICAgLy8gdGhlcmUgbXVzdCBiZSBhIG1vZGlmaWNhdGlvbiBkZXRlY3Rpb24gY29kZSBwYWNrZXQgYXMgdGhlXG4gICAgLy8gbGFzdCBwYWNrZXQgYW5kIGV2ZXJ5dGhpbmcgZ2V0cyBoYXNoZWQgZXhjZXB0IHRoZSBoYXNoIGl0c2VsZlxuICAgIHRoaXMuaGFzaCA9IGNyeXB0by5oYXNoLnNoYTEoXG4gICAgICBjcnlwdG8uY2ZiLm1kYyhzZXNzaW9uS2V5QWxnb3JpdGhtLCBrZXksIHRoaXMuZW5jcnlwdGVkKSArIGRlY3J5cHRlZC5zdWJzdHJpbmcoMCwgZGVjcnlwdGVkLmxlbmd0aCAtIDIwKSk7XG5cblxuICAgIHZhciBtZGMgPSBkZWNyeXB0ZWQuc3Vic3RyKGRlY3J5cHRlZC5sZW5ndGggLSAyMCwgMjApO1xuXG4gICAgaWYgKHRoaXMuaGFzaCAhPSBtZGMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTW9kaWZpY2F0aW9uIGRldGVjdGVkLicpO1xuICAgIH0gZWxzZVxuICAgICAgdGhpcy5wYWNrZXRzLnJlYWQoZGVjcnlwdGVkLnN1YnN0cigwLCBkZWNyeXB0ZWQubGVuZ3RoIC0gMjIpKTtcbiAgfVxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB0eXBlX3MyayA9IHJlcXVpcmUoJy4uL3R5cGUvczJrLmpzJyksXG4gIGVudW1zID0gcmVxdWlyZSgnLi4vZW51bXMuanMnKSxcbiAgY3J5cHRvID0gcmVxdWlyZSgnLi4vY3J5cHRvJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIFB1YmxpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IFBhY2tldHMgKFRhZyAxKVxuICogXG4gKiBSRkM0ODgwIDUuMTogQSBQdWJsaWMtS2V5IEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXQgaG9sZHMgdGhlIHNlc3Npb24ga2V5XG4gKiB1c2VkIHRvIGVuY3J5cHQgYSBtZXNzYWdlLiBaZXJvIG9yIG1vcmUgUHVibGljLUtleSBFbmNyeXB0ZWQgU2Vzc2lvbiBLZXlcbiAqIHBhY2tldHMgYW5kL29yIFN5bW1ldHJpYy1LZXkgRW5jcnlwdGVkIFNlc3Npb24gS2V5IHBhY2tldHMgbWF5IHByZWNlZGUgYVxuICogU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQsIHdoaWNoIGhvbGRzIGFuIGVuY3J5cHRlZCBtZXNzYWdlLiBUaGVcbiAqIG1lc3NhZ2UgaXMgZW5jcnlwdGVkIHdpdGggdGhlIHNlc3Npb24ga2V5LCBhbmQgdGhlIHNlc3Npb24ga2V5IGlzIGl0c2VsZlxuICogZW5jcnlwdGVkIGFuZCBzdG9yZWQgaW4gdGhlIEVuY3J5cHRlZCBTZXNzaW9uIEtleSBwYWNrZXQocykuIFRoZVxuICogU3ltbWV0cmljYWxseSBFbmNyeXB0ZWQgRGF0YSBQYWNrZXQgaXMgcHJlY2VkZWQgYnkgb25lIFB1YmxpYy1LZXkgRW5jcnlwdGVkXG4gKiBTZXNzaW9uIEtleSBwYWNrZXQgZm9yIGVhY2ggT3BlblBHUCBrZXkgdG8gd2hpY2ggdGhlIG1lc3NhZ2UgaXMgZW5jcnlwdGVkLlxuICogVGhlIHJlY2lwaWVudCBvZiB0aGUgbWVzc2FnZSBmaW5kcyBhIHNlc3Npb24ga2V5IHRoYXQgaXMgZW5jcnlwdGVkIHRvIHRoZWlyXG4gKiBwdWJsaWMga2V5LCBkZWNyeXB0cyB0aGUgc2Vzc2lvbiBrZXksIGFuZCB0aGVuIHVzZXMgdGhlIHNlc3Npb24ga2V5IHRvXG4gKiBkZWNyeXB0IHRoZSBtZXNzYWdlLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHBhY2tldF9zeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5KCkge1xuICB0aGlzLnRhZyA9IDM7XG4gIHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0gPSBudWxsO1xuICB0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0gPSAnYWVzMjU2JztcbiAgdGhpcy5lbmNyeXB0ZWQgPSBudWxsO1xuICB0aGlzLnMyayA9IG5ldyB0eXBlX3MyaygpO1xuXG4gIC8qKlxuICAgKiBQYXJzaW5nIGZ1bmN0aW9uIGZvciBhIHN5bW1ldHJpYyBlbmNyeXB0ZWQgc2Vzc2lvbiBrZXkgcGFja2V0ICh0YWcgMykuXG4gICAqIFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgUGF5bG9hZCBvZiBhIHRhZyAxIHBhY2tldFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgc3RyaW5nXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuXG4gICAqICAgICAgICAgICAgTGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2ZcbiAgICogICAgICAgICAgICBpbnB1dCBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBPYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgLy8gQSBvbmUtb2N0ZXQgdmVyc2lvbiBudW1iZXIuIFRoZSBvbmx5IGN1cnJlbnRseSBkZWZpbmVkIHZlcnNpb24gaXMgNC5cbiAgICB0aGlzLnZlcnNpb24gPSBieXRlc1swXS5jaGFyQ29kZUF0KCk7XG5cbiAgICAvLyBBIG9uZS1vY3RldCBudW1iZXIgZGVzY3JpYmluZyB0aGUgc3ltbWV0cmljIGFsZ29yaXRobSB1c2VkLlxuICAgIHZhciBhbGdvID0gZW51bXMucmVhZChlbnVtcy5zeW1tZXRyaWMsIGJ5dGVzWzFdLmNoYXJDb2RlQXQoKSk7XG5cbiAgICAvLyBBIHN0cmluZy10by1rZXkgKFMySykgc3BlY2lmaWVyLCBsZW5ndGggYXMgZGVmaW5lZCBhYm92ZS5cbiAgICB2YXIgczJrbGVuZ3RoID0gdGhpcy5zMmsucmVhZChieXRlcy5zdWJzdHIoMikpO1xuXG4gICAgLy8gT3B0aW9uYWxseSwgdGhlIGVuY3J5cHRlZCBzZXNzaW9uIGtleSBpdHNlbGYsIHdoaWNoIGlzIGRlY3J5cHRlZFxuICAgIC8vIHdpdGggdGhlIHN0cmluZy10by1rZXkgb2JqZWN0LlxuICAgIHZhciBkb25lID0gczJrbGVuZ3RoICsgMjtcblxuICAgIGlmIChkb25lIDwgYnl0ZXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmVuY3J5cHRlZCA9IGJ5dGVzLnN1YnN0cihkb25lKTtcbiAgICAgIHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0gPSBhbGdvXG4gICAgfSBlbHNlXG4gICAgICB0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0gPSBhbGdvO1xuICB9XG5cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhbGdvID0gdGhpcy5lbmNyeXB0ZWQgPT0gbnVsbCA/XG4gICAgICB0aGlzLnNlc3Npb25LZXlBbGdvcml0aG0gOlxuICAgICAgdGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobTtcblxuICAgIHZhciBieXRlcyA9IFN0cmluZy5mcm9tQ2hhckNvZGUodGhpcy52ZXJzaW9uKSArXG4gICAgICBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLnN5bW1ldHJpYywgYWxnbykpICtcbiAgICAgIHRoaXMuczJrLndyaXRlKCk7XG5cbiAgICBpZiAodGhpcy5lbmNyeXB0ZWQgIT0gbnVsbClcbiAgICAgIGJ5dGVzICs9IHRoaXMuZW5jcnlwdGVkO1xuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWNyeXB0cyB0aGUgc2Vzc2lvbiBrZXkgKG9ubHkgZm9yIHB1YmxpYyBrZXkgZW5jcnlwdGVkIHNlc3Npb24ga2V5XG4gICAqIHBhY2tldHMgKHRhZyAxKVxuICAgKiBcbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19tZXNzYWdlfSBtc2dcbiAgICogICAgICAgICAgICBUaGUgbWVzc2FnZSBvYmplY3QgKHdpdGggbWVtYmVyIGVuY3J5cHRlZERhdGFcbiAgICogQHBhcmFtIHtvcGVucGdwX21zZ19wcml2YXRla2V5fSBrZXlcbiAgICogICAgICAgICAgICBQcml2YXRlIGtleSB3aXRoIHNlY01QSXMgdW5sb2NrZWRcbiAgICogQHJldHVybiB7U3RyaW5nfSBUaGUgdW5lbmNyeXB0ZWQgc2Vzc2lvbiBrZXlcbiAgICovXG4gIHRoaXMuZGVjcnlwdCA9IGZ1bmN0aW9uKHBhc3NwaHJhc2UpIHtcbiAgICB2YXIgYWxnbyA9IHRoaXMuc2Vzc2lvbktleUVuY3J5cHRpb25BbGdvcml0aG0gIT0gbnVsbCA/XG4gICAgICB0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtIDpcbiAgICAgIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobTtcblxuXG4gICAgdmFyIGxlbmd0aCA9IGNyeXB0by5jaXBoZXJbYWxnb10ua2V5U2l6ZTtcbiAgICB2YXIga2V5ID0gdGhpcy5zMmsucHJvZHVjZV9rZXkocGFzc3BocmFzZSwgbGVuZ3RoKTtcblxuICAgIGlmICh0aGlzLmVuY3J5cHRlZCA9PSBudWxsKSB7XG4gICAgICB0aGlzLnNlc3Npb25LZXkgPSBrZXk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGRlY3J5cHRlZCA9IGNyeXB0by5jZmIuZGVjcnlwdChcbiAgICAgICAgdGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSwga2V5LCB0aGlzLmVuY3J5cHRlZCwgdHJ1ZSk7XG5cbiAgICAgIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMuc3ltbWV0cmljLFxuICAgICAgICBkZWNyeXB0ZWRbMF0ua2V5Q29kZUF0KCkpO1xuXG4gICAgICB0aGlzLnNlc3Npb25LZXkgPSBkZWNyeXB0ZWQuc3Vic3RyKDEpO1xuICAgIH1cbiAgfVxuXG4gIHRoaXMuZW5jcnlwdCA9IGZ1bmN0aW9uKHBhc3NwaHJhc2UpIHtcbiAgICB2YXIgbGVuZ3RoID0gY3J5cHRvLmdldEtleUxlbmd0aCh0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtKTtcbiAgICB2YXIga2V5ID0gdGhpcy5zMmsucHJvZHVjZV9rZXkocGFzc3BocmFzZSwgbGVuZ3RoKTtcblxuICAgIHZhciBwcml2YXRlX2tleSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICBlbnVtcy53cml0ZShlbnVtcy5zeW1tZXRyaWMsIHRoaXMuc2Vzc2lvbktleUFsZ29yaXRobSkpICtcblxuICAgIGNyeXB0by5nZXRSYW5kb21CeXRlcyhcbiAgICAgIGNyeXB0by5nZXRLZXlMZW5ndGgodGhpcy5zZXNzaW9uS2V5QWxnb3JpdGhtKSk7XG5cbiAgICB0aGlzLmVuY3J5cHRlZCA9IGNyeXB0by5jZmIuZW5jcnlwdChcbiAgICAgIGNyeXB0by5nZXRQcmVmaXhSYW5kb20odGhpcy5zZXNzaW9uS2V5RW5jcnlwdGlvbkFsZ29yaXRobSksXG4gICAgICB0aGlzLnNlc3Npb25LZXlFbmNyeXB0aW9uQWxnb3JpdGhtLCBrZXksIHByaXZhdGVfa2V5LCB0cnVlKTtcbiAgfVxufTtcbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBjcnlwdG8gPSByZXF1aXJlKCcuLi9jcnlwdG8nKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgUGFja2V0IChUYWcgOSlcbiAqIFxuICogUkZDNDg4MCA1Ljc6IFRoZSBTeW1tZXRyaWNhbGx5IEVuY3J5cHRlZCBEYXRhIHBhY2tldCBjb250YWlucyBkYXRhIGVuY3J5cHRlZFxuICogd2l0aCBhIHN5bW1ldHJpYy1rZXkgYWxnb3JpdGhtLiBXaGVuIGl0IGhhcyBiZWVuIGRlY3J5cHRlZCwgaXQgY29udGFpbnMgb3RoZXJcbiAqIHBhY2tldHMgKHVzdWFsbHkgYSBsaXRlcmFsIGRhdGEgcGFja2V0IG9yIGNvbXByZXNzZWQgZGF0YSBwYWNrZXQsIGJ1dCBpblxuICogdGhlb3J5IG90aGVyIFN5bW1ldHJpY2FsbHkgRW5jcnlwdGVkIERhdGEgcGFja2V0cyBvciBzZXF1ZW5jZXMgb2YgcGFja2V0c1xuICogdGhhdCBmb3JtIHdob2xlIE9wZW5QR1AgbWVzc2FnZXMpLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gcGFja2V0X3N5bW1ldHJpY2FsbHlfZW5jcnlwdGVkKCkge1xuICB0aGlzLmVuY3J5cHRlZCA9IG51bGw7XG4gIC8qKiBEZWNyeXB0ZWQgcGFja2V0cyBjb250YWluZWQgd2l0aGluLiBcbiAgICogQHR5cGUge29wZW5wZ3BfcGFja2V0bGlzdH0gKi9cbiAgdGhpcy5wYWNrZXRzO1xuXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdGhpcy5lbmNyeXB0ZWQgPSBieXRlcztcbiAgfVxuXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5lbmNyeXB0ZWQ7XG4gIH1cblxuICAvKipcbiAgICogU3ltbWV0cmljYWxseSBkZWNyeXB0IHRoZSBwYWNrZXQgZGF0YVxuICAgKiBcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBzZXNzaW9uS2V5QWxnb3JpdGhtXG4gICAqICAgICAgICAgICAgIFN5bW1ldHJpYyBrZXkgYWxnb3JpdGhtIHRvIHVzZSAvLyBTZWUgUkZDNDg4MCA5LjJcbiAgICogQHBhcmFtIHtTdHJpbmd9IGtleVxuICAgKiAgICAgICAgICAgICBLZXkgYXMgc3RyaW5nIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgbGVuZ3RoIHRvIHRoZVxuICAgKiAgICAgICAgICAgIGFsZ29yaXRobVxuICAgKiBAcmV0dXJuIFRoZSBkZWNyeXB0ZWQgZGF0YTtcbiAgICovXG4gIHRoaXMuZGVjcnlwdCA9IGZ1bmN0aW9uKHNlc3Npb25LZXlBbGdvcml0aG0sIGtleSkge1xuICAgIHZhciBkZWNyeXB0ZWQgPSBjcnlwdG8uY2ZiLmRlY3J5cHQoXG4gICAgICBzZXNzaW9uS2V5QWxnb3JpdGhtLCBrZXksIHRoaXMuZW5jcnlwdGVkLCB0cnVlKTtcblxuICAgIHRoaXMucGFja2V0cy5yZWFkKGRlY3J5cHRlZCk7XG4gIH1cblxuICB0aGlzLmVuY3J5cHQgPSBmdW5jdGlvbihhbGdvLCBrZXkpIHtcbiAgICB2YXIgZGF0YSA9IHRoaXMucGFja2V0cy53cml0ZSgpO1xuXG4gICAgdGhpcy5lbmNyeXB0ZWQgPSBjcnlwdG8uY2ZiLmVuY3J5cHQoXG4gICAgICBjcnlwdG8uZ2V0UHJlZml4UmFuZG9tKGFsZ28pLCBhbGdvLCBkYXRhLCBrZXksIHRydWUpO1xuICB9XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfdHJ1c3QoKSB7XG5cbn07XG4iLCIvLyBHUEc0QnJvd3NlcnMgLSBBbiBPcGVuUEdQIGltcGxlbWVudGF0aW9uIGluIGphdmFzY3JpcHRcbi8vIENvcHlyaWdodCAoQykgMjAxMSBSZWN1cml0eSBMYWJzIEdtYkhcbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuLy8gbW9kaWZ5IGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyXG4vLyB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbi8vIFxuLy8gVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4vLyBidXQgV0lUSE9VVCBBTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZlxuLy8gTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlVcbi8vIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4vLyBcbi8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYWxvbmcgd2l0aCB0aGlzIGxpYnJhcnk7IGlmIG5vdCwgd3JpdGUgdG8gdGhlIEZyZWUgU29mdHdhcmVcbi8vIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0cmVldCwgRmlmdGggRmxvb3IsIEJvc3RvbiwgTUEgIDAyMTEwLTEzMDEgIFVTQVxuXG4vKiogXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2MgSW1wbGVtZW50YXRpb24gb2YgdGhlIFVzZXIgQXR0cmlidXRlIFBhY2tldCAoVGFnIDE3KVxuICogIFRoZSBVc2VyIEF0dHJpYnV0ZSBwYWNrZXQgaXMgYSB2YXJpYXRpb24gb2YgdGhlIFVzZXIgSUQgcGFja2V0LiAgSXRcbiAqICBpcyBjYXBhYmxlIG9mIHN0b3JpbmcgbW9yZSB0eXBlcyBvZiBkYXRhIHRoYW4gdGhlIFVzZXIgSUQgcGFja2V0LFxuICogIHdoaWNoIGlzIGxpbWl0ZWQgdG8gdGV4dC4gIExpa2UgdGhlIFVzZXIgSUQgcGFja2V0LCBhIFVzZXIgQXR0cmlidXRlXG4gKiAgcGFja2V0IG1heSBiZSBjZXJ0aWZpZWQgYnkgdGhlIGtleSBvd25lciAoXCJzZWxmLXNpZ25lZFwiKSBvciBhbnkgb3RoZXJcbiAqICBrZXkgb3duZXIgd2hvIGNhcmVzIHRvIGNlcnRpZnkgaXQuICBFeGNlcHQgYXMgbm90ZWQsIGEgVXNlciBBdHRyaWJ1dGVcbiAqICBwYWNrZXQgbWF5IGJlIHVzZWQgYW55d2hlcmUgdGhhdCBhIFVzZXIgSUQgcGFja2V0IG1heSBiZSB1c2VkLlxuICpcbiAqICBXaGlsZSBVc2VyIEF0dHJpYnV0ZSBwYWNrZXRzIGFyZSBub3QgYSByZXF1aXJlZCBwYXJ0IG9mIHRoZSBPcGVuUEdQXG4gKiAgc3RhbmRhcmQsIGltcGxlbWVudGF0aW9ucyBTSE9VTEQgcHJvdmlkZSBhdCBsZWFzdCBlbm91Z2hcbiAqICBjb21wYXRpYmlsaXR5IHRvIHByb3Blcmx5IGhhbmRsZSBhIGNlcnRpZmljYXRpb24gc2lnbmF0dXJlIG9uIHRoZVxuICogIFVzZXIgQXR0cmlidXRlIHBhY2tldC4gIEEgc2ltcGxlIHdheSB0byBkbyB0aGlzIGlzIGJ5IHRyZWF0aW5nIHRoZVxuICogIFVzZXIgQXR0cmlidXRlIHBhY2tldCBhcyBhIFVzZXIgSUQgcGFja2V0IHdpdGggb3BhcXVlIGNvbnRlbnRzLCBidXRcbiAqICBhbiBpbXBsZW1lbnRhdGlvbiBtYXkgdXNlIGFueSBtZXRob2QgZGVzaXJlZC5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfdXNlcl9hdHRyaWJ1dGUoKSB7XG4gIHRoaXMudGFnID0gMTc7XG4gIHRoaXMuYXR0cmlidXRlcyA9IFtdO1xuXG4gIC8qKlxuICAgKiBwYXJzaW5nIGZ1bmN0aW9uIGZvciBhIHVzZXIgYXR0cmlidXRlIHBhY2tldCAodGFnIDE3KS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IHBheWxvYWQgb2YgYSB0YWcgMTcgcGFja2V0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gcG9zaXRpb24gcG9zaXRpb24gdG8gc3RhcnQgcmVhZGluZyBmcm9tIHRoZSBpbnB1dCBzdHJpbmdcbiAgICogQHBhcmFtIHtJbnRlZ2VyfSBsZW4gbGVuZ3RoIG9mIHRoZSBwYWNrZXQgb3IgdGhlIHJlbWFpbmluZyBsZW5ndGggb2YgaW5wdXQgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF9wYWNrZXRfZW5jcnlwdGVkZGF0YX0gb2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoaSA8IGJ5dGVzLmxlbmd0aCkge1xuICAgICAgdmFyIGxlbiA9IG9wZW5wZ3BfcGFja2V0LnJlYWRfc2ltcGxlX2xlbmd0aChieXRlcyk7XG5cbiAgICAgIGkgKz0gbGVuLm9mZnNldDtcbiAgICAgIHRoaXMuYXR0cmlidXRlcy5wdXNoKGJ5dGVzLnN1YnN0cihpLCBsZW4ubGVuKSk7XG4gICAgICBpICs9IGxlbi5sZW47XG4gICAgfVxuICB9XG59O1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbi8qKlxuICogQGNsYXNzXG4gKiBAY2xhc3NkZXNjIEltcGxlbWVudGF0aW9uIG9mIHRoZSBVc2VyIElEIFBhY2tldCAoVGFnIDEzKVxuICogQSBVc2VyIElEIHBhY2tldCBjb25zaXN0cyBvZiBVVEYtOCB0ZXh0IHRoYXQgaXMgaW50ZW5kZWQgdG8gcmVwcmVzZW50XG4gKiB0aGUgbmFtZSBhbmQgZW1haWwgYWRkcmVzcyBvZiB0aGUga2V5IGhvbGRlci4gIEJ5IGNvbnZlbnRpb24sIGl0XG4gKiBpbmNsdWRlcyBhbiBSRkMgMjgyMiBbUkZDMjgyMl0gbWFpbCBuYW1lLWFkZHIsIGJ1dCB0aGVyZSBhcmUgbm9cbiAqIHJlc3RyaWN0aW9ucyBvbiBpdHMgY29udGVudC4gIFRoZSBwYWNrZXQgbGVuZ3RoIGluIHRoZSBoZWFkZXJcbiAqIHNwZWNpZmllcyB0aGUgbGVuZ3RoIG9mIHRoZSBVc2VyIElELiBcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBwYWNrZXRfdXNlcmlkKCkge1xuICAvKiogQHR5cGUge1N0cmluZ30gQSBzdHJpbmcgY29udGFpbmluZyB0aGUgdXNlciBpZC4gVXN1YWxseSBpbiB0aGUgZm9ybVxuICAgKiBKb2huIERvZSA8am9obkBleGFtcGxlLmNvbT4gXG4gICAqL1xuICB0aGlzLnVzZXJpZCA9ICcnO1xuXG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgdXNlciBpZCBwYWNrZXQgKHRhZyAxMykuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBwYXlsb2FkIG9mIGEgdGFnIDEzIHBhY2tldFxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIHBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgc3RyaW5nXG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gbGVuIGxlbmd0aCBvZiB0aGUgcGFja2V0IG9yIHRoZSByZW1haW5pbmcgbGVuZ3RoIG9mIGlucHV0IFxuICAgKiBhdCBwb3NpdGlvblxuICAgKiBAcmV0dXJuIHtvcGVucGdwX3BhY2tldF9lbmNyeXB0ZWRkYXRhfSBvYmplY3QgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMucmVhZCA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdGhpcy51c2VyaWQgPSB1dGlsLmRlY29kZV91dGY4KGJ5dGVzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB1c2VyIGlkIHBhY2tldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gdXNlcl9pZCB0aGUgdXNlciBpZCBhcyBzdHJpbmcgKFwiSm9obiBEb2UgPGpvaG4uZG9lQG1haWwudXNcIilcbiAgICogQHJldHVybiB7U3RyaW5nfSBzdHJpbmcgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdXRpbC5lbmNvZGVfdXRmOCh0aGlzLnVzZXJpZCk7XG4gIH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0eXBlIGtleSBpZCAoUkZDNDg4MCAzLjMpXG4gKiAgQSBLZXkgSUQgaXMgYW4gZWlnaHQtb2N0ZXQgc2NhbGFyIHRoYXQgaWRlbnRpZmllcyBhIGtleS5cbiAgIEltcGxlbWVudGF0aW9ucyBTSE9VTEQgTk9UIGFzc3VtZSB0aGF0IEtleSBJRHMgYXJlIHVuaXF1ZS4gIFRoZVxuICAgc2VjdGlvbiBcIkVuaGFuY2VkIEtleSBGb3JtYXRzXCIgYmVsb3cgZGVzY3JpYmVzIGhvdyBLZXkgSURzIGFyZVxuICAgZm9ybWVkLlxuICovXG5mdW5jdGlvbiBrZXlpZCgpIHtcblxuICB0aGlzLmJ5dGVzID0gJyc7XG5cblxuICAvKipcbiAgICogUGFyc2luZyBtZXRob2QgZm9yIGEga2V5IGlkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBJbnB1dCB0byByZWFkIHRoZSBrZXkgaWQgZnJvbSBcbiAgICogQHBhcmFtIHtpbnRlZ2VyfSBwb3NpdGlvbiBQb3NpdGlvbiB3aGVyZSB0byBzdGFydCByZWFkaW5nIHRoZSBrZXkgXG4gICAqIGlkIGZyb20gaW5wdXRcbiAgICogQHJldHVybiB7b3BlbnBncF90eXBlX2tleWlkfSBUaGlzIG9iamVjdFxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB0aGlzLmJ5dGVzID0gYnl0ZXMuc3Vic3RyKDAsIDgpO1xuICB9XG5cbiAgdGhpcy53cml0ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmJ5dGVzO1xuICB9XG5cbiAgdGhpcy50b0hleCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB1dGlsLmhleHN0cmR1bXAodGhpcy5ieXRlcyk7XG4gIH1cblxuICB0aGlzLmVxdWFscyA9IGZ1bmN0aW9uKGtleWlkKSB7XG4gICAgcmV0dXJuIHRoaXMuYnl0ZXMgPT0ga2V5aWQuYnl0ZXM7XG4gIH1cblxuICB0aGlzLmlzTnVsbCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmJ5dGVzID09PSAnJztcbiAgfVxufVxuXG5rZXlpZC5tYXBUb0hleCA9IGZ1bmN0aW9uKGtleWlkKSB7XG4gIHJldHVybiBrZXlpZC50b0hleCgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGtleWlkO1xuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxuLy8gSGludDogV2UgaG9sZCBvdXIgTVBJcyBhcyBhbiBhcnJheSBvZiBvY3RldHMgaW4gYmlnIGVuZGlhbiBmb3JtYXQgcHJlY2VlZGluZyBhIHR3b1xuLy8gb2N0ZXQgc2NhbGFyOiBNUEk6IFthLGIsYyxkLGUsZl1cbi8vIC0gTVBJIHNpemU6IChhIDw8IDgpIHwgYiBcbi8vIC0gTVBJID0gYyB8IGQgPDwgOCB8IGUgPDwgKChNUEkubGVuZ3RoIC0yKSo4KSB8IGYgKChNUEkubGVuZ3RoIC0yKSo4KVxuXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4uL2NyeXB0by9wdWJsaWNfa2V5L2pzYm4uanMnKSxcbiAgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcblxuLyoqXG4gKiBAY2xhc3NcbiAqIEBjbGFzc2Rlc2NJbXBsZW1lbnRhdGlvbiBvZiB0eXBlIE1QSSAoUkZDNDg4MCAzLjIpXG4gKiBNdWx0aXByZWNpc2lvbiBpbnRlZ2VycyAoYWxzbyBjYWxsZWQgTVBJcykgYXJlIHVuc2lnbmVkIGludGVnZXJzIHVzZWRcbiAqIHRvIGhvbGQgbGFyZ2UgaW50ZWdlcnMgc3VjaCBhcyB0aGUgb25lcyB1c2VkIGluIGNyeXB0b2dyYXBoaWNcbiAqIGNhbGN1bGF0aW9ucy5cbiAqIEFuIE1QSSBjb25zaXN0cyBvZiB0d28gcGllY2VzOiBhIHR3by1vY3RldCBzY2FsYXIgdGhhdCBpcyB0aGUgbGVuZ3RoXG4gKiBvZiB0aGUgTVBJIGluIGJpdHMgZm9sbG93ZWQgYnkgYSBzdHJpbmcgb2Ygb2N0ZXRzIHRoYXQgY29udGFpbiB0aGVcbiAqIGFjdHVhbCBpbnRlZ2VyLlxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1waSgpIHtcbiAgLyoqIEFuIGltcGxlbWVudGF0aW9uIGRlcGVuZGVudCBpbnRlZ2VyICovXG4gIHRoaXMuZGF0YSA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgbXBpIChSRkMgNDg4MCAzLjIpLlxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgUGF5bG9hZCBvZiBtcGkgZGF0YVxuICAgKiBAcGFyYW0ge0ludGVnZXJ9IHBvc2l0aW9uIFBvc2l0aW9uIHRvIHN0YXJ0IHJlYWRpbmcgZnJvbSB0aGUgaW5wdXQgXG4gICAqIHN0cmluZ1xuICAgKiBAcGFyYW0ge0ludGVnZXJ9IGxlbiBMZW5ndGggb2YgdGhlIHBhY2tldCBvciB0aGUgcmVtYWluaW5nIGxlbmd0aCBvZiBcbiAgICogaW5wdXQgYXQgcG9zaXRpb25cbiAgICogQHJldHVybiB7b3BlbnBncF90eXBlX21waX0gT2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0aGlzLnJlYWQgPSBmdW5jdGlvbihieXRlcykge1xuICAgIHZhciBiaXRzID0gKGJ5dGVzWzBdLmNoYXJDb2RlQXQoKSA8PCA4KSB8IGJ5dGVzWzFdLmNoYXJDb2RlQXQoKTtcblxuICAgIC8vIEFkZGl0aW9uYWwgcnVsZXM6XG4gICAgLy9cbiAgICAvLyAgICBUaGUgc2l6ZSBvZiBhbiBNUEkgaXMgKChNUEkubGVuZ3RoICsgNykgLyA4KSArIDIgb2N0ZXRzLlxuICAgIC8vXG4gICAgLy8gICAgVGhlIGxlbmd0aCBmaWVsZCBvZiBhbiBNUEkgZGVzY3JpYmVzIHRoZSBsZW5ndGggc3RhcnRpbmcgZnJvbSBpdHNcbiAgICAvL1x0ICBtb3N0IHNpZ25pZmljYW50IG5vbi16ZXJvIGJpdC4gIFRodXMsIHRoZSBNUEkgWzAwIDAyIDAxXSBpcyBub3RcbiAgICAvLyAgICBmb3JtZWQgY29ycmVjdGx5LiAgSXQgc2hvdWxkIGJlIFswMCAwMSAwMV0uXG5cbiAgICAvLyBUT0RPOiBWZXJpZmljYXRpb24gb2YgdGhpcyBzaXplIG1ldGhvZCEgVGhpcyBzaXplIGNhbGN1bGF0aW9uIGFzXG4gICAgLy8gXHRcdCBzcGVjaWZpZWQgYWJvdmUgaXMgbm90IGFwcGxpY2FibGUgaW4gSmF2YVNjcmlwdFxuICAgIHZhciBieXRlbGVuID0gTWF0aC5jZWlsKGJpdHMgLyA4KTtcblxuICAgIHZhciByYXcgPSBieXRlcy5zdWJzdHIoMiwgYnl0ZWxlbik7XG4gICAgdGhpcy5mcm9tQnl0ZXMocmF3KTtcblxuICAgIHJldHVybiAyICsgYnl0ZWxlbjtcbiAgfVxuXG4gIHRoaXMuZnJvbUJ5dGVzID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB0aGlzLmRhdGEgPSBuZXcgQmlnSW50ZWdlcih1dGlsLmhleHN0cmR1bXAoYnl0ZXMpLCAxNik7XG4gIH1cblxuICB0aGlzLnRvQnl0ZXMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy53cml0ZSgpLnN1YnN0cigyKTtcbiAgfVxuXG4gIHRoaXMuYnl0ZUxlbmd0aCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnRvQnl0ZXMoKS5sZW5ndGg7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgdGhlIG1waSBvYmplY3QgdG8gYSBzdHJpbmcgYXMgc3BlY2lmaWVkIGluIFJGQzQ4ODAgMy4yXG4gICAqIEByZXR1cm4ge1N0cmluZ30gbXBpIEJ5dGUgcmVwcmVzZW50YXRpb25cbiAgICovXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhLnRvTVBJKCk7XG4gIH1cblxuICB0aGlzLnRvQmlnSW50ZWdlciA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmRhdGEuY2xvbmUoKTtcbiAgfVxuXG4gIHRoaXMuZnJvbUJpZ0ludGVnZXIgPSBmdW5jdGlvbihibikge1xuICAgIHRoaXMuZGF0YSA9IGJuLmNsb25lKCk7XG4gIH1cbn1cbiIsIi8vIEdQRzRCcm93c2VycyAtIEFuIE9wZW5QR1AgaW1wbGVtZW50YXRpb24gaW4gamF2YXNjcmlwdFxuLy8gQ29weXJpZ2h0IChDKSAyMDExIFJlY3VyaXR5IExhYnMgR21iSFxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4vLyBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbi8vIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuLy8gXG4vLyBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbi8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4vLyBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuLy8gTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbi8vIFxuLy8gWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuLy8gTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGUgRnJlZSBTb2Z0d2FyZVxuLy8gRm91bmRhdGlvbiwgSW5jLiwgNTEgRnJhbmtsaW4gU3RyZWV0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAgMDIxMTAtMTMwMSAgVVNBXG5cbnZhciBlbnVtcyA9IHJlcXVpcmUoJy4uL2VudW1zLmpzJyksXG4gIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyksXG4gIGNyeXB0byA9IHJlcXVpcmUoJy4uL2NyeXB0bycpO1xuXG4vKipcbiAqIEBjbGFzc1xuICogQGNsYXNzZGVzYyBJbXBsZW1lbnRhdGlvbiBvZiB0aGUgU3RyaW5nLXRvLWtleSBzcGVjaWZpZXIgKFJGQzQ4ODAgMy43KVxuICogU3RyaW5nLXRvLWtleSAoUzJLKSBzcGVjaWZpZXJzIGFyZSB1c2VkIHRvIGNvbnZlcnQgcGFzc3BocmFzZSBzdHJpbmdzXG4gICBpbnRvIHN5bW1ldHJpYy1rZXkgZW5jcnlwdGlvbi9kZWNyeXB0aW9uIGtleXMuICBUaGV5IGFyZSB1c2VkIGluIHR3b1xuICAgcGxhY2VzLCBjdXJyZW50bHk6IHRvIGVuY3J5cHQgdGhlIHNlY3JldCBwYXJ0IG9mIHByaXZhdGUga2V5cyBpbiB0aGVcbiAgIHByaXZhdGUga2V5cmluZywgYW5kIHRvIGNvbnZlcnQgcGFzc3BocmFzZXMgdG8gZW5jcnlwdGlvbiBrZXlzIGZvclxuICAgc3ltbWV0cmljYWxseSBlbmNyeXB0ZWQgbWVzc2FnZXMuXG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gczJrKCkge1xuICAvKiogQHR5cGUge29wZW5wZ3AuaGFzaH0gKi9cbiAgdGhpcy5hbGdvcml0aG0gPSAnc2hhMjU2JztcbiAgLyoqIEB0eXBlIHtvcGVucGdwX3R5cGVfczJrLnR5cGV9ICovXG4gIHRoaXMudHlwZSA9ICdpdGVyYXRlZCc7XG4gIHRoaXMuYyA9IDk2O1xuICAvKiogQHR5cGUge29wZW5wZ3BfYnl0ZWFycmF5fSBcbiAgICogRWlnaHQgYnl0ZXMgb2Ygc2FsdC4gKi9cbiAgdGhpcy5zYWx0ID0gY3J5cHRvLnJhbmRvbS5nZXRSYW5kb21CeXRlcyg4KTtcblxuXG4gIC8vIEV4cG9uZW4gYmlhcywgZGVmaW5lZCBpbiBSRkM0ODgwXG4gIHZhciBleHBiaWFzID0gNjtcblxuICB0aGlzLmdldF9jb3VudCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAoMTYgKyAodGhpcy5jICYgMTUpKSA8PCAoKHRoaXMuYyA+PiA0KSArIGV4cGJpYXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNpbmcgZnVuY3Rpb24gZm9yIGEgc3RyaW5nLXRvLWtleSBzcGVjaWZpZXIgKFJGQyA0ODgwIDMuNykuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBQYXlsb2FkIG9mIHN0cmluZy10by1rZXkgc3BlY2lmaWVyXG4gICAqIEByZXR1cm4ge0ludGVnZXJ9IEFjdHVhbCBsZW5ndGggb2YgdGhlIG9iamVjdFxuICAgKi9cbiAgdGhpcy5yZWFkID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgaSA9IDA7XG4gICAgdGhpcy50eXBlID0gZW51bXMucmVhZChlbnVtcy5zMmssIGJ5dGVzW2krK10uY2hhckNvZGVBdCgpKTtcbiAgICB0aGlzLmFsZ29yaXRobSA9IGVudW1zLnJlYWQoZW51bXMuaGFzaCwgYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCkpO1xuXG4gICAgc3dpdGNoICh0aGlzLnR5cGUpIHtcbiAgICAgIGNhc2UgJ3NpbXBsZSc6XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdzYWx0ZWQnOlxuICAgICAgICB0aGlzLnNhbHQgPSBieXRlcy5zdWJzdHIoaSwgOCk7XG4gICAgICAgIGkgKz0gODtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ2l0ZXJhdGVkJzpcbiAgICAgICAgdGhpcy5zYWx0ID0gYnl0ZXMuc3Vic3RyKGksIDgpO1xuICAgICAgICBpICs9IDg7XG5cbiAgICAgICAgLy8gT2N0ZXQgMTA6IGNvdW50LCBhIG9uZS1vY3RldCwgY29kZWQgdmFsdWVcbiAgICAgICAgdGhpcy5jID0gYnl0ZXNbaSsrXS5jaGFyQ29kZUF0KCk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdnbnUnOlxuICAgICAgICBpZiAoYnl0ZXMuc3Vic3RyKGksIDMpID09IFwiR05VXCIpIHtcbiAgICAgICAgICBpICs9IDM7IC8vIEdOVVxuICAgICAgICAgIHZhciBnbnVFeHRUeXBlID0gMTAwMCArIGJ5dGVzW2krK10uY2hhckNvZGVBdCgpO1xuICAgICAgICAgIGlmIChnbnVFeHRUeXBlID09IDEwMDEpIHtcbiAgICAgICAgICAgIHRoaXMudHlwZSA9IGdudUV4dFR5cGU7XG4gICAgICAgICAgICAvLyBHbnVQRyBleHRlbnNpb24gbW9kZSAxMDAxIC0tIGRvbid0IHdyaXRlIHNlY3JldCBrZXkgYXQgYWxsXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gczJrIGdudSBwcm90ZWN0aW9uIG1vZGUuXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHMyayB0eXBlLlwiKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVW5rbm93biBzMmsgdHlwZS5cIik7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHJldHVybiBpO1xuICB9XG5cblxuICAvKipcbiAgICogd3JpdGVzIGFuIHMyayBoYXNoIGJhc2VkIG9uIHRoZSBpbnB1dHMuXG4gICAqIEByZXR1cm4ge1N0cmluZ30gUHJvZHVjZWQga2V5IG9mIGhhc2hBbGdvcml0aG0gaGFzaCBsZW5ndGhcbiAgICovXG4gIHRoaXMud3JpdGUgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYnl0ZXMgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGVudW1zLndyaXRlKGVudW1zLnMyaywgdGhpcy50eXBlKSk7XG4gICAgYnl0ZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShlbnVtcy53cml0ZShlbnVtcy5oYXNoLCB0aGlzLmFsZ29yaXRobSkpO1xuXG4gICAgc3dpdGNoICh0aGlzLnR5cGUpIHtcbiAgICAgIGNhc2UgJ3NpbXBsZSc6XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnc2FsdGVkJzpcbiAgICAgICAgYnl0ZXMgKz0gdGhpcy5zYWx0O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2l0ZXJhdGVkJzpcbiAgICAgICAgYnl0ZXMgKz0gdGhpcy5zYWx0O1xuICAgICAgICBieXRlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHRoaXMuYyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH07XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICAvKipcbiAgICogUHJvZHVjZXMgYSBrZXkgdXNpbmcgdGhlIHNwZWNpZmllZCBwYXNzcGhyYXNlIGFuZCB0aGUgZGVmaW5lZCBcbiAgICogaGFzaEFsZ29yaXRobSBcbiAgICogQHBhcmFtIHtTdHJpbmd9IHBhc3NwaHJhc2UgUGFzc3BocmFzZSBjb250YWluaW5nIHVzZXIgaW5wdXRcbiAgICogQHJldHVybiB7U3RyaW5nfSBQcm9kdWNlZCBrZXkgd2l0aCBhIGxlbmd0aCBjb3JyZXNwb25kaW5nIHRvIFxuICAgKiBoYXNoQWxnb3JpdGhtIGhhc2ggbGVuZ3RoXG4gICAqL1xuICB0aGlzLnByb2R1Y2Vfa2V5ID0gZnVuY3Rpb24ocGFzc3BocmFzZSwgbnVtQnl0ZXMpIHtcbiAgICBwYXNzcGhyYXNlID0gdXRpbC5lbmNvZGVfdXRmOChwYXNzcGhyYXNlKTtcblxuICAgIGZ1bmN0aW9uIHJvdW5kKHByZWZpeCwgczJrKSB7XG4gICAgICB2YXIgYWxnb3JpdGhtID0gZW51bXMud3JpdGUoZW51bXMuaGFzaCwgczJrLmFsZ29yaXRobSk7XG5cbiAgICAgIHN3aXRjaCAoczJrLnR5cGUpIHtcbiAgICAgICAgY2FzZSAnc2ltcGxlJzpcbiAgICAgICAgICByZXR1cm4gY3J5cHRvLmhhc2guZGlnZXN0KGFsZ29yaXRobSwgcHJlZml4ICsgcGFzc3BocmFzZSk7XG5cbiAgICAgICAgY2FzZSAnc2FsdGVkJzpcbiAgICAgICAgICByZXR1cm4gY3J5cHRvLmhhc2guZGlnZXN0KGFsZ29yaXRobSxcbiAgICAgICAgICAgIHByZWZpeCArIHMyay5zYWx0ICsgcGFzc3BocmFzZSk7XG5cbiAgICAgICAgY2FzZSAnaXRlcmF0ZWQnOlxuICAgICAgICAgIHZhciBpc3AgPSBbXSxcbiAgICAgICAgICAgIGNvdW50ID0gczJrLmdldF9jb3VudCgpO1xuICAgICAgICAgIGRhdGEgPSBzMmsuc2FsdCArIHBhc3NwaHJhc2U7XG5cbiAgICAgICAgICB3aGlsZSAoaXNwLmxlbmd0aCAqIGRhdGEubGVuZ3RoIDwgY291bnQpXG4gICAgICAgICAgICBpc3AucHVzaChkYXRhKTtcblxuICAgICAgICAgIGlzcCA9IGlzcC5qb2luKCcnKTtcblxuICAgICAgICAgIGlmIChpc3AubGVuZ3RoID4gY291bnQpXG4gICAgICAgICAgICBpc3AgPSBpc3Auc3Vic3RyKDAsIGNvdW50KTtcblxuICAgICAgICAgIHJldHVybiBjcnlwdG8uaGFzaC5kaWdlc3QoYWxnb3JpdGhtLCBwcmVmaXggKyBpc3ApO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgcmVzdWx0ID0gJycsXG4gICAgICBwcmVmaXggPSAnJztcblxuICAgIHdoaWxlIChyZXN1bHQubGVuZ3RoIDw9IG51bUJ5dGVzKSB7XG4gICAgICByZXN1bHQgKz0gcm91bmQocHJlZml4LCB0aGlzKTtcbiAgICAgIHByZWZpeCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDApO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQuc3Vic3RyKDAsIG51bUJ5dGVzKTtcbiAgfVxufVxuIiwiLy8gR1BHNEJyb3dzZXJzIC0gQW4gT3BlblBHUCBpbXBsZW1lbnRhdGlvbiBpbiBqYXZhc2NyaXB0XG4vLyBDb3B5cmlnaHQgKEMpIDIwMTEgUmVjdXJpdHkgTGFicyBHbWJIXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3Jcbi8vIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbi8vIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuLy8gdmVyc2lvbiAyLjEgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNpb24uXG4vLyBcbi8vIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuLy8gYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2Zcbi8vIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gIFNlZSB0aGUgR05VXG4vLyBMZXNzZXIgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLlxuLy8gXG4vLyBZb3Ugc2hvdWxkIGhhdmUgcmVjZWl2ZWQgYSBjb3B5IG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4vLyBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4vLyBGb3VuZGF0aW9uLCBJbmMuLCA1MSBGcmFua2xpbiBTdHJlZXQsIEZpZnRoIEZsb29yLCBCb3N0b24sIE1BICAwMjExMC0xMzAxICBVU0FcblxudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4uL2NvbmZpZycpO1xuXG52YXIgVXRpbCA9IGZ1bmN0aW9uKCkge1xuXG4gIHRoaXMucmVhZE51bWJlciA9IGZ1bmN0aW9uKGJ5dGVzKSB7XG4gICAgdmFyIG4gPSAwO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbiA8PD0gODtcbiAgICAgIG4gKz0gYnl0ZXNbaV0uY2hhckNvZGVBdCgpO1xuICAgIH1cblxuICAgIHJldHVybiBuO1xuICB9O1xuXG4gIHRoaXMud3JpdGVOdW1iZXIgPSBmdW5jdGlvbihuLCBieXRlcykge1xuICAgIHZhciBiID0gJyc7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlczsgaSsrKSB7XG4gICAgICBiICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKG4gPj4gKDggKiAoYnl0ZXMgLSBpIC0gMSkpKSAmIDB4RkYpO1xuICAgIH1cblxuICAgIHJldHVybiBiO1xuICB9O1xuXG5cblxuICB0aGlzLnJlYWREYXRlID0gZnVuY3Rpb24oYnl0ZXMpIHtcbiAgICB2YXIgbiA9IHRoaXMucmVhZE51bWJlcihieXRlcyk7XG4gICAgdmFyIGQgPSBuZXcgRGF0ZSgpO1xuICAgIGQuc2V0VGltZShuICogMTAwMCk7XG4gICAgcmV0dXJuIGQ7XG4gIH07XG5cbiAgdGhpcy53cml0ZURhdGUgPSBmdW5jdGlvbih0aW1lKSB7XG4gICAgdmFyIG51bWVyaWMgPSBNYXRoLnJvdW5kKHRpbWUuZ2V0VGltZSgpIC8gMTAwMCk7XG5cbiAgICByZXR1cm4gdGhpcy53cml0ZU51bWJlcihudW1lcmljLCA0KTtcbiAgfTtcblxuICB0aGlzLmVtYWlsUmVnRXggPSAvXlsrYS16QS1aMC05Xy4tXStAKFthLXpBLVowLTktXStcXC4pK1thLXpBLVowLTldezIsNn0kLztcblxuICB0aGlzLmRlYnVnID0gZmFsc2U7XG5cbiAgdGhpcy5oZXhkdW1wID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgdmFyIHIgPSBbXTtcbiAgICB2YXIgZSA9IHN0ci5sZW5ndGg7XG4gICAgdmFyIGMgPSAwO1xuICAgIHZhciBoO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAoYyA8IGUpIHtcbiAgICAgIGggPSBzdHIuY2hhckNvZGVBdChjKyspLnRvU3RyaW5nKDE2KTtcbiAgICAgIHdoaWxlIChoLmxlbmd0aCA8IDIpIGggPSBcIjBcIiArIGg7XG4gICAgICByLnB1c2goXCIgXCIgKyBoKTtcbiAgICAgIGkrKztcbiAgICAgIGlmIChpICUgMzIgPT0gMClcbiAgICAgICAgci5wdXNoKFwiXFxuICAgICAgICAgICBcIik7XG4gICAgfVxuICAgIHJldHVybiByLmpvaW4oJycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgaGV4c3RyaW5nIGZyb20gYSBiaW5hcnlcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gY29udmVydFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFN0cmluZyBjb250YWluaW5nIHRoZSBoZXhhZGVjaW1hbCB2YWx1ZXNcbiAgICovXG4gIHRoaXMuaGV4c3RyZHVtcCA9IGZ1bmN0aW9uKHN0cikge1xuICAgIGlmIChzdHIgPT0gbnVsbClcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIHZhciByID0gW107XG4gICAgdmFyIGUgPSBzdHIubGVuZ3RoO1xuICAgIHZhciBjID0gMDtcbiAgICB2YXIgaDtcbiAgICB3aGlsZSAoYyA8IGUpIHtcbiAgICAgIGggPSBzdHJbYysrXS5jaGFyQ29kZUF0KCkudG9TdHJpbmcoMTYpO1xuICAgICAgd2hpbGUgKGgubGVuZ3RoIDwgMikgaCA9IFwiMFwiICsgaDtcbiAgICAgIHIucHVzaChcIlwiICsgaCk7XG4gICAgfVxuICAgIHJldHVybiByLmpvaW4oJycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYmluYXJ5IHN0cmluZyBmcm9tIGEgaGV4IGVuY29kZWQgc3RyaW5nXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgSGV4IHN0cmluZyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gU3RyaW5nIGNvbnRhaW5pbmcgdGhlIGJpbmFyeSB2YWx1ZXNcbiAgICovXG4gIHRoaXMuaGV4MmJpbiA9IGZ1bmN0aW9uKGhleCkge1xuICAgIHZhciBzdHIgPSAnJztcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhleC5sZW5ndGg7IGkgKz0gMilcbiAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHBhcnNlSW50KGhleC5zdWJzdHIoaSwgMiksIDE2KSk7XG4gICAgcmV0dXJuIHN0cjtcbiAgfTtcblxuICAvKipcbiAgICogQ3JlYXRpbmcgYSBoZXggc3RyaW5nIGZyb20gYW4gYmluYXJ5IGFycmF5IG9mIGludGVnZXJzICgwLi4yNTUpXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgQXJyYXkgb2YgYnl0ZXMgdG8gY29udmVydFxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IEhleGFkZWNpbWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBhcnJheVxuICAgKi9cbiAgdGhpcy5oZXhpZHVtcCA9IGZ1bmN0aW9uKHN0cikge1xuICAgIHZhciByID0gW107XG4gICAgdmFyIGUgPSBzdHIubGVuZ3RoO1xuICAgIHZhciBjID0gMDtcbiAgICB2YXIgaDtcbiAgICB3aGlsZSAoYyA8IGUpIHtcbiAgICAgIGggPSBzdHJbYysrXS50b1N0cmluZygxNik7XG4gICAgICB3aGlsZSAoaC5sZW5ndGggPCAyKSBoID0gXCIwXCIgKyBoO1xuICAgICAgci5wdXNoKFwiXCIgKyBoKTtcbiAgICB9XG4gICAgcmV0dXJuIHIuam9pbignJyk7XG4gIH07XG5cblxuICAvKipcbiAgICogQ29udmVydCBhIG5hdGl2ZSBqYXZhc2NyaXB0IHN0cmluZyB0byBhIHN0cmluZyBvZiB1dGY4IGJ5dGVzXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgVGhlIHN0cmluZyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gQSB2YWxpZCBzcXVlbmNlIG9mIHV0ZjggYnl0ZXNcbiAgICovXG4gIHRoaXMuZW5jb2RlX3V0ZjggPSBmdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gdW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgc3RyaW5nIG9mIHV0ZjggYnl0ZXMgdG8gYSBuYXRpdmUgamF2YXNjcmlwdCBzdHJpbmdcbiAgICogQHBhcmFtIHtTdHJpbmd9IHV0ZjggQSB2YWxpZCBzcXVlbmNlIG9mIHV0ZjggYnl0ZXNcbiAgICogQHJldHVybiB7U3RyaW5nfSBBIG5hdGl2ZSBqYXZhc2NyaXB0IHN0cmluZ1xuICAgKi9cbiAgdGhpcy5kZWNvZGVfdXRmOCA9IGZ1bmN0aW9uKHV0ZjgpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUodXRmOCkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiB1dGY4O1xuICAgIH1cbiAgfTtcblxuICB2YXIgc3RyMmJpbiA9IGZ1bmN0aW9uKHN0ciwgcmVzdWx0KSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFtpXSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgdmFyIGJpbjJzdHIgPSBmdW5jdGlvbihiaW4pIHtcbiAgICB2YXIgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJpbi5sZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0LnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShiaW5baV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0LmpvaW4oJycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgc3RyaW5nIHRvIGFuIGFycmF5IG9mIGludGVnZXJzKDAuMjU1KVxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge0ludGVnZXJbXX0gQW4gYXJyYXkgb2YgKGJpbmFyeSkgaW50ZWdlcnNcbiAgICovXG4gIHRoaXMuc3RyMmJpbiA9IGZ1bmN0aW9uKHN0cikge1xuICAgIHJldHVybiBzdHIyYmluKHN0ciwgbmV3IEFycmF5KHN0ci5sZW5ndGgpKTtcbiAgfTtcblxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGFuIGFycmF5IG9mIGludGVnZXJzKDAuMjU1KSB0byBhIHN0cmluZyBcbiAgICogQHBhcmFtIHtJbnRlZ2VyW119IGJpbiBBbiBhcnJheSBvZiAoYmluYXJ5KSBpbnRlZ2VycyB0byBjb252ZXJ0XG4gICAqIEByZXR1cm4ge1N0cmluZ30gVGhlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgYXJyYXlcbiAgICovXG4gIHRoaXMuYmluMnN0ciA9IGJpbjJzdHI7XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgYSBzdHJpbmcgdG8gYSBVaW50OEFycmF5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIGNvbnZlcnRcbiAgICogQHJldHVybiB7VWludDhBcnJheX0gVGhlIGFycmF5IG9mIChiaW5hcnkpIGludGVnZXJzXG4gICAqL1xuICB0aGlzLnN0cjJVaW50OEFycmF5ID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgcmV0dXJuIHN0cjJiaW4oc3RyLCBuZXcgVWludDhBcnJheShuZXcgQXJyYXlCdWZmZXIoc3RyLmxlbmd0aCkpKTtcbiAgfTtcblxuICAvKipcbiAgICogQ29udmVydCBhIFVpbnQ4QXJyYXkgdG8gYSBzdHJpbmcuIFRoaXMgY3VycmVudGx5IGZ1bmN0aW9ucyBcbiAgICogdGhlIHNhbWUgYXMgYmluMnN0ci4gXG4gICAqIEBwYXJhbSB7VWludDhBcnJheX0gYmluIEFuIGFycmF5IG9mIChiaW5hcnkpIGludGVnZXJzIHRvIGNvbnZlcnRcbiAgICogQHJldHVybiB7U3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGFycmF5XG4gICAqL1xuICB0aGlzLlVpbnQ4QXJyYXkyc3RyID0gYmluMnN0cjtcblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyBhIDE2Yml0IHN1bSBvZiBhIHN0cmluZyBieSBhZGRpbmcgZWFjaCBjaGFyYWN0ZXIgXG4gICAqIGNvZGVzIG1vZHVsdXMgNjU1MzVcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRleHQgU3RyaW5nIHRvIGNyZWF0ZSBhIHN1bSBvZlxuICAgKiBAcmV0dXJuIHtJbnRlZ2VyfSBBbiBpbnRlZ2VyIGNvbnRhaW5pbmcgdGhlIHN1bSBvZiBhbGwgY2hhcmFjdGVyIFxuICAgKiBjb2RlcyAlIDY1NTM1XG4gICAqL1xuICB0aGlzLmNhbGNfY2hlY2tzdW0gPSBmdW5jdGlvbih0ZXh0KSB7XG4gICAgdmFyIGNoZWNrc3VtID0ge1xuICAgICAgczogMCxcbiAgICAgIGFkZDogZnVuY3Rpb24oc2FkZCkge1xuICAgICAgICB0aGlzLnMgPSAodGhpcy5zICsgc2FkZCkgJSA2NTUzNjtcbiAgICAgIH1cbiAgICB9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGV4dC5sZW5ndGg7IGkrKykge1xuICAgICAgY2hlY2tzdW0uYWRkKHRleHQuY2hhckNvZGVBdChpKSk7XG4gICAgfVxuICAgIHJldHVybiBjaGVja3N1bS5zO1xuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYSBkZWJ1ZyBtZXNzYWdlLiBEZWJ1ZyBcbiAgICogbWVzc2FnZXMgYXJlIG9ubHkgcHJpbnRlZCBpZlxuICAgKiBvcGVucGdwLmNvbmZpZy5kZWJ1ZyBpcyBzZXQgdG8gdHJ1ZS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgb2YgdGhlIGRlYnVnIG1lc3NhZ2VcbiAgICovXG4gIHRoaXMucHJpbnRfZGVidWcgPSBmdW5jdGlvbihzdHIpIHtcbiAgICBpZiAoY29uZmlnLmRlYnVnKSB7XG4gICAgICBjb25zb2xlLmxvZyhzdHIpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogSGVscGVyIGZ1bmN0aW9uIHRvIHByaW50IGEgZGVidWcgbWVzc2FnZS4gRGVidWcgXG4gICAqIG1lc3NhZ2VzIGFyZSBvbmx5IHByaW50ZWQgaWZcbiAgICogb3BlbnBncC5jb25maWcuZGVidWcgaXMgc2V0IHRvIHRydWUuXG4gICAqIERpZmZlcmVudCB0aGFuIHByaW50X2RlYnVnIGJlY2F1c2Ugd2lsbCBjYWxsIGhleHN0cmR1bXAgaWZmIG5lY2Vzc2FyeS5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgb2YgdGhlIGRlYnVnIG1lc3NhZ2VcbiAgICovXG4gIHRoaXMucHJpbnRfZGVidWdfaGV4c3RyX2R1bXAgPSBmdW5jdGlvbihzdHIsIHN0clRvSGV4KSB7XG4gICAgaWYgKGNvbmZpZy5kZWJ1Zykge1xuICAgICAgc3RyID0gc3RyICsgdGhpcy5oZXhzdHJkdW1wKHN0clRvSGV4KTtcbiAgICAgIGNvbnNvbGUubG9nKHN0cik7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYW4gZXJyb3IgbWVzc2FnZS4gXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIG9mIHRoZSBlcnJvciBtZXNzYWdlXG4gICAqL1xuICB0aGlzLnByaW50X2Vycm9yID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgaWYgKGNvbmZpZy5kZWJ1ZylcbiAgICAgIHRocm93IHN0cjtcbiAgICBjb25zb2xlLmxvZyhzdHIpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gcHJpbnQgYW4gaW5mbyBtZXNzYWdlLiBcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgb2YgdGhlIGluZm8gbWVzc2FnZVxuICAgKi9cbiAgdGhpcy5wcmludF9pbmZvID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgaWYgKGNvbmZpZy5kZWJ1ZylcbiAgICAgIGNvbnNvbGUubG9nKHN0cik7XG4gIH07XG5cbiAgdGhpcy5wcmludF93YXJuaW5nID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgY29uc29sZS5sb2coc3RyKTtcbiAgfTtcblxuICB0aGlzLmdldExlZnROQml0cyA9IGZ1bmN0aW9uKHN0cmluZywgYml0Y291bnQpIHtcbiAgICB2YXIgcmVzdCA9IGJpdGNvdW50ICUgODtcbiAgICBpZiAocmVzdCA9PSAwKVxuICAgICAgcmV0dXJuIHN0cmluZy5zdWJzdHJpbmcoMCwgYml0Y291bnQgLyA4KTtcbiAgICB2YXIgYnl0ZXMgPSAoYml0Y291bnQgLSByZXN0KSAvIDggKyAxO1xuICAgIHZhciByZXN1bHQgPSBzdHJpbmcuc3Vic3RyaW5nKDAsIGJ5dGVzKTtcbiAgICByZXR1cm4gdGhpcy5zaGlmdFJpZ2h0KHJlc3VsdCwgOCAtIHJlc3QpOyAvLyArU3RyaW5nLmZyb21DaGFyQ29kZShzdHJpbmcuY2hhckNvZGVBdChieXRlcyAtMSkgPDwgKDgtcmVzdCkgJiAweEZGKTtcbiAgfTtcblxuICAvKipcbiAgICogU2hpZnRpbmcgYSBzdHJpbmcgdG8gbiBiaXRzIHJpZ2h0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSBUaGUgc3RyaW5nIHRvIHNoaWZ0XG4gICAqIEBwYXJhbSB7SW50ZWdlcn0gYml0Y291bnQgQW1vdW50IG9mIGJpdHMgdG8gc2hpZnQgKE1VU1QgYmUgc21hbGxlciBcbiAgICogdGhhbiA5KVxuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFJlc3VsdGluZyBzdHJpbmcuIFxuICAgKi9cbiAgdGhpcy5zaGlmdFJpZ2h0ID0gZnVuY3Rpb24odmFsdWUsIGJpdGNvdW50KSB7XG4gICAgdmFyIHRlbXAgPSB1dGlsLnN0cjJiaW4odmFsdWUpO1xuICAgIGlmIChiaXRjb3VudCAlIDggIT0gMCkge1xuICAgICAgZm9yICh2YXIgaSA9IHRlbXAubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgdGVtcFtpXSA+Pj0gYml0Y291bnQgJSA4O1xuICAgICAgICBpZiAoaSA+IDApXG4gICAgICAgICAgdGVtcFtpXSB8PSAodGVtcFtpIC0gMV0gPDwgKDggLSAoYml0Y291bnQgJSA4KSkpICYgMHhGRjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdXRpbC5iaW4yc3RyKHRlbXApO1xuICB9O1xuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGFsZ29yaXRobSB0eXBlIGFzIHN0cmluZ1xuICAgKiBAcmV0dXJuIHtTdHJpbmd9IFN0cmluZyByZXByZXNlbnRpbmcgdGhlIG1lc3NhZ2UgdHlwZVxuICAgKi9cbiAgdGhpcy5nZXRfaGFzaEFsZ29yaXRobVN0cmluZyA9IGZ1bmN0aW9uKGFsZ28pIHtcbiAgICBzd2l0Y2ggKGFsZ28pIHtcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmV0dXJuIFwiTUQ1XCI7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIHJldHVybiBcIlNIQTFcIjtcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgcmV0dXJuIFwiUklQRU1EMTYwXCI7XG4gICAgICBjYXNlIDg6XG4gICAgICAgIHJldHVybiBcIlNIQTI1NlwiO1xuICAgICAgY2FzZSA5OlxuICAgICAgICByZXR1cm4gXCJTSEEzODRcIjtcbiAgICAgIGNhc2UgMTA6XG4gICAgICAgIHJldHVybiBcIlNIQTUxMlwiO1xuICAgICAgY2FzZSAxMTpcbiAgICAgICAgcmV0dXJuIFwiU0hBMjI0XCI7XG4gICAgfVxuICAgIHJldHVybiBcInVua25vd25cIjtcbiAgfTtcblxufTtcblxuLyoqXG4gKiBhbiBpbnN0YW5jZSB0aGF0IHNob3VsZCBiZSB1c2VkLiBcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBuZXcgVXRpbCgpO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJBRVMgUmlqbmRhZWwgY2lwaGVyIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBlY2JfdGJsLnR4dFwiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKTtcbiAgdmFyIHV0aWwgPSBvcGVucGdwLnV0aWw7XG5cbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheSgpO1xuXG4gIGZ1bmN0aW9uIHRlc3RfYWVzKGlucHV0LCBrZXksIG91dHB1dCkge1xuICAgIHZhciBhZXMgPSBuZXcgb3BlbnBncC5jcnlwdG8uY2lwaGVyLmFlczEyOCh1dGlsLmJpbjJzdHIoa2V5KSk7XG5cbiAgICB2YXIgcmVzdWx0ID0gdXRpbC5iaW4yc3RyKGFlcy5lbmNyeXB0KGlucHV0KSk7XG5cbiAgICByZXR1cm4gdXRpbC5oZXhzdHJkdW1wKHJlc3VsdCkgPT0gdXRpbC5oZXhzdHJkdW1wKHV0aWwuYmluMnN0cihvdXRwdXQpKTtcbiAgfTtcblxuICB2YXIgdGVzdHZlY3RvcnMxMjggPSBbW1sweDAwLDB4MDEsMHgwMiwweDAzLDB4MDUsMHgwNiwweDA3LDB4MDgsMHgwQSwweDBCLDB4MEMsMHgwRCwweDBGLDB4MTAsMHgxMSwweDEyXSxbMHg1MCwweDY4LDB4MTIsMHhBNCwweDVGLDB4MDgsMHhDOCwweDg5LDB4QjksMHg3RiwweDU5LDB4ODAsMHgwMywweDhCLDB4ODMsMHg1OV0sWzB4RDgsMHhGNSwweDMyLDB4NTMsMHg4MiwweDg5LDB4RUYsMHg3RCwweDA2LDB4QjUsMHgwNiwweEE0LDB4RkQsMHg1QiwweEU5LDB4QzldXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgxNCwweDE1LDB4MTYsMHgxNywweDE5LDB4MUEsMHgxQiwweDFDLDB4MUUsMHgxRiwweDIwLDB4MjEsMHgyMywweDI0LDB4MjUsMHgyNl0sWzB4NUMsMHg2RCwweDcxLDB4Q0EsMHgzMCwweERFLDB4OEIsMHg4QiwweDAwLDB4NTQsMHg5OSwweDg0LDB4RDIsMHhFQywweDdELDB4NEJdLFsweDU5LDB4QUIsMHgzMCwweEY0LDB4RDQsMHhFRSwweDZFLDB4NEYsMHhGOSwweDkwLDB4N0UsMHhGNiwweDVCLDB4MUYsMHhCNiwweDhDXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MjgsMHgyOSwweDJBLDB4MkIsMHgyRCwweDJFLDB4MkYsMHgzMCwweDMyLDB4MzMsMHgzNCwweDM1LDB4MzcsMHgzOCwweDM5LDB4M0FdLFsweDUzLDB4RjMsMHhGNCwweEM2LDB4NEYsMHg4NiwweDE2LDB4RTQsMHhFNywweEM1LDB4NjEsMHg5OSwweEY0LDB4OEYsMHgyMSwweEY2XSxbMHhCRiwweDFFLDB4RDIsMHhGQywweEIyLDB4QUYsMHgzRiwweEQ0LDB4MTQsMHg0MywweEI1LDB4NkQsMHg4NSwweDAyLDB4NUMsMHhCMV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDNDLDB4M0QsMHgzRSwweDNGLDB4NDEsMHg0MiwweDQzLDB4NDQsMHg0NiwweDQ3LDB4NDgsMHg0OSwweDRCLDB4NEMsMHg0RCwweDRFXSxbMHhBMSwweEVCLDB4NjUsMHhBMywweDQ4LDB4NzEsMHg2NSwweEZCLDB4MEYsMHgxQywweDI3LDB4RkYsMHg5OSwweDU5LDB4RjcsMHgwM10sWzB4NzMsMHgxNiwweDYzLDB4MkQsMHg1QywweDMyLDB4MjMsMHgzRSwweERDLDB4QjAsMHg3OCwweDA1LDB4NjAsMHhFQSwweEU4LDB4QjJdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg1MCwweDUxLDB4NTIsMHg1MywweDU1LDB4NTYsMHg1NywweDU4LDB4NUEsMHg1QiwweDVDLDB4NUQsMHg1RiwweDYwLDB4NjEsMHg2Ml0sWzB4MzUsMHg1MywweEVDLDB4RjAsMHhCMSwweDczLDB4OTUsMHg1OCwweEIwLDB4OEUsMHgzNSwweDBBLDB4OTgsMHhBMywweDlCLDB4RkFdLFsweDQwLDB4OEMsMHgwNywweDNFLDB4M0UsMHgyNSwweDM4LDB4MDcsMHgyQiwweDcyLDB4NjIsMHg1RSwweDY4LDB4QjgsMHgzNiwweDRCXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NjQsMHg2NSwweDY2LDB4NjcsMHg2OSwweDZBLDB4NkIsMHg2QywweDZFLDB4NkYsMHg3MCwweDcxLDB4NzMsMHg3NCwweDc1LDB4NzZdLFsweDY3LDB4NDIsMHg5OSwweDY5LDB4NDksMHgwQiwweDk3LDB4MTEsMHhBRSwweDJCLDB4MDEsMHhEQywweDQ5LDB4N0EsMHhGRCwweEU4XSxbMHhFMSwweEY5LDB4NEQsMHhGQSwweDc3LDB4NjUsMHg5NywweEJFLDB4QUMsMHhBMiwweDYyLDB4RjIsMHhGNiwweDM2LDB4NkYsMHhFQV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDc4LDB4NzksMHg3QSwweDdCLDB4N0QsMHg3RSwweDdGLDB4ODAsMHg4MiwweDgzLDB4ODQsMHg4NSwweDg3LDB4ODgsMHg4OSwweDhBXSxbMHg5MywweDM4LDB4NUMsMHgxRiwweDJBLDB4RUMsMHg4QiwweEVELDB4MTksMHgyRiwweDVBLDB4OEUsMHgxNiwweDFELDB4RDUsMHgwOF0sWzB4RjIsMHg5RSwweDk4LDB4NkMsMHg2QSwweDFDLDB4MjcsMHhENywweEIyLDB4OUYsMHhGRCwweDdFLDB4RTksMHgyQiwweDc1LDB4RjFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg4QywweDhELDB4OEUsMHg4RiwweDkxLDB4OTIsMHg5MywweDk0LDB4OTYsMHg5NywweDk4LDB4OTksMHg5QiwweDlDLDB4OUQsMHg5RV0sWzB4QjUsMHhCRiwweDk0LDB4NkIsMHhFMSwweDlCLDB4RUIsMHg4RCwweEIzLDB4OTgsMHgzQiwweDVGLDB4NEMsMHg2RSwweDhELDB4REJdLFsweDEzLDB4MUMsMHg4OCwweDZBLDB4NTcsMHhGOCwweEMyLDB4RTcsMHgxMywweEFCLDB4QTYsMHg5NSwweDVFLDB4MkIsMHg1NSwweEI1XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4QTAsMHhBMSwweEEyLDB4QTMsMHhBNSwweEE2LDB4QTcsMHhBOCwweEFBLDB4QUIsMHhBQywweEFELDB4QUYsMHhCMCwweEIxLDB4QjJdLFsweDQxLDB4MzIsMHgxRSwweEUxLDB4MEUsMHgyMSwweEJELDB4OTAsMHg3MiwweDI3LDB4QzQsMHg0NSwweDBGLDB4RjQsMHgyMywweDI0XSxbMHhEMiwweEFCLDB4NzYsMHg2MiwweERGLDB4OUIsMHg4QywweDc0LDB4MDIsMHgxMCwweEU1LDB4RUUsMHhCNiwweDFDLDB4MTksMHg5RF1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEI0LDB4QjUsMHhCNiwweEI3LDB4QjksMHhCQSwweEJCLDB4QkMsMHhCRSwweEJGLDB4QzAsMHhDMSwweEMzLDB4QzQsMHhDNSwweEM2XSxbMHgwMCwweEE4LDB4MkYsMHg1OSwweEM5LDB4MUMsMHg4NCwweDg2LDB4RDEsMHgyQywweDBBLDB4ODAsMHgxMiwweDRGLDB4NjAsMHg4OV0sWzB4MTQsMHhDMSwweDA1LDB4NTQsMHhCMiwweDg1LDB4OUMsMHg0OCwweDRDLDB4QUIsMHg1OCwweDY5LDB4QkIsMHhFNywweEM0LDB4NzBdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhDOCwweEM5LDB4Q0EsMHhDQiwweENELDB4Q0UsMHhDRiwweEQwLDB4RDIsMHhEMywweEQ0LDB4RDUsMHhENywweEQ4LDB4RDksMHhEQV0sWzB4N0MsMHhFMCwweEZELDB4MDcsMHg2NywweDU0LDB4NjksMHgxQiwweDRCLDB4QkQsMHg5RiwweEFGLDB4OEEsMHgxMywweDcyLDB4RkVdLFsweERCLDB4NEQsMHg0OSwweDhGLDB4MEEsMHg0OSwweENGLDB4NTUsMHg0NCwweDVELDB4NTAsMHgyQywweDFGLDB4OUEsMHhCMywweEI1XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4REMsMHhERCwweERFLDB4REYsMHhFMSwweEUyLDB4RTMsMHhFNCwweEU2LDB4RTcsMHhFOCwweEU5LDB4RUIsMHhFQywweEVELDB4RUVdLFsweDIzLDB4NjAsMHg1QSwweDgyLDB4NDMsMHhEMCwweDc3LDB4NjQsMHg1NCwweDFCLDB4QzUsMHhBRCwweDM1LDB4NUIsMHgzMSwweDI5XSxbMHg2RCwweDk2LDB4RkUsMHhGNywweEQ2LDB4NjUsMHg5MCwweEE3LDB4N0EsMHg3NywweEJCLDB4MjAsMHg1NiwweDY2LDB4N0YsMHg3Rl1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEYwLDB4RjEsMHhGMiwweEYzLDB4RjUsMHhGNiwweEY3LDB4RjgsMHhGQSwweEZCLDB4RkMsMHhGRCwweEZFLDB4MDEsMHgwMCwweDAyXSxbMHgxMiwweEE4LDB4Q0YsMHhBMiwweDNFLDB4QTcsMHg2NCwweEZELDB4ODcsMHg2MiwweDMyLDB4QjQsMHhFOCwweDQyLDB4QkMsMHg0NF0sWzB4MzEsMHg2RiwweEI2LDB4OEUsMHhEQiwweEE3LDB4MzYsMHhDNSwweDNFLDB4NzgsMHg0NywweDdCLDB4RjksMHgxMywweDcyLDB4NUNdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgwNCwweDA1LDB4MDYsMHgwNywweDA5LDB4MEEsMHgwQiwweDBDLDB4MEUsMHgwRiwweDEwLDB4MTEsMHgxMywweDE0LDB4MTUsMHgxNl0sWzB4QkMsMHhBRiwweDMyLDB4NDEsMHg1RSwweDgzLDB4MDgsMHhCMywweDcyLDB4M0UsMHg1RiwweERELDB4ODUsMHgzQywweENDLDB4ODBdLFsweDY5LDB4MzYsMHhGMiwweEI5LDB4M0EsMHhGOCwweDM5LDB4N0YsMHhEMywweEE3LDB4NzEsMHhGQywweDAxLDB4MUMsMHg4QywweDM3XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MkMsMHgyRCwweDJFLDB4MkYsMHgzMSwweDMyLDB4MzMsMHgzNCwweDM2LDB4MzcsMHgzOCwweDM5LDB4M0IsMHgzQywweDNELDB4M0VdLFsweDg5LDB4QUYsMHhBRSwweDY4LDB4NUQsMHg4MCwweDFBLDB4RDcsMHg0NywweEFDLDB4RTksMHgxRiwweEM0LDB4OUEsMHhERCwweEUwXSxbMHhGMywweEY5LDB4MkYsMHg3QSwweDlDLDB4NTksMHgxNywweDlDLDB4MUYsMHhDQywweDJDLDB4MkIsMHhBMCwweEIwLDB4ODIsMHhDRF1dXTtcbiAgXG4gIHZhciB0ZXN0dmVjdG9yczE5MiA9IFtbWzB4MDAsMHgwMSwweDAyLDB4MDMsMHgwNSwweDA2LDB4MDcsMHgwOCwweDBBLDB4MEIsMHgwQywweDBELDB4MEYsMHgxMCwweDExLDB4MTIsMHgxNCwweDE1LDB4MTYsMHgxNywweDE5LDB4MUEsMHgxQiwweDFDXSxbMHgyRCwweDMzLDB4RUUsMHhGMiwweEMwLDB4NDMsMHgwQSwweDhBLDB4OUUsMHhCRiwweDQ1LDB4RTgsMHgwOSwweEM0LDB4MEIsMHhCNl0sWzB4REYsMHhGNCwweDk0LDB4NUUsMHgwMywweDM2LDB4REYsMHg0QywweDFDLDB4NTYsMHhCQywweDcwLDB4MEUsMHhGRiwweDgzLDB4N0ZdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgxRSwweDFGLDB4MjAsMHgyMSwweDIzLDB4MjQsMHgyNSwweDI2LDB4MjgsMHgyOSwweDJBLDB4MkIsMHgyRCwweDJFLDB4MkYsMHgzMCwweDMyLDB4MzMsMHgzNCwweDM1LDB4MzcsMHgzOCwweDM5LDB4M0FdLFsweDZBLDB4QTMsMHg3NSwweEQxLDB4RkEsMHgxNSwweDVBLDB4NjEsMHhGQiwweDcyLDB4MzUsMHgzRSwweDBBLDB4NUEsMHg4NywweDU2XSxbMHhCNiwweEZELDB4REUsMHhGNCwweDc1LDB4MjcsMHg2NSwweEUzLDB4NDcsMHhENSwweEQyLDB4REMsMHgxOSwweDZELDB4MTIsMHg1Ml1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDNDLDB4M0QsMHgzRSwweDNGLDB4NDEsMHg0MiwweDQzLDB4NDQsMHg0NiwweDQ3LDB4NDgsMHg0OSwweDRCLDB4NEMsMHg0RCwweDRFLDB4NTAsMHg1MSwweDUyLDB4NTMsMHg1NSwweDU2LDB4NTcsMHg1OF0sWzB4QkMsMHgzNywweDM2LDB4NTEsMHg4QiwweDk0LDB4OTAsMHhEQywweEI4LDB4RUQsMHg2MCwweEVCLDB4MjYsMHg3NSwweDhFLDB4RDRdLFsweEQyLDB4MzYsMHg4NCwweEUzLDB4RDksMHg2MywweEIzLDB4QUYsMHhDRiwweDFBLDB4MTEsMHg0QSwweENBLDB4OTAsMHhDQiwweEQ2XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NUEsMHg1QiwweDVDLDB4NUQsMHg1RiwweDYwLDB4NjEsMHg2MiwweDY0LDB4NjUsMHg2NiwweDY3LDB4NjksMHg2QSwweDZCLDB4NkMsMHg2RSwweDZGLDB4NzAsMHg3MSwweDczLDB4NzQsMHg3NSwweDc2XSxbMHhBQSwweDIxLDB4NDQsMHgwMiwweEI0LDB4NkMsMHhGRiwweEI5LDB4RjcsMHg2MSwweEVDLDB4MTEsMHgyNiwweDNBLDB4MzEsMHgxRV0sWzB4M0EsMHg3QSwweEMwLDB4MjcsMHg3NSwweDNFLDB4MkEsMHgxOCwweEMyLDB4Q0UsMHhBQiwweDlFLDB4MTcsMHhDMSwweDFGLDB4RDBdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg3OCwweDc5LDB4N0EsMHg3QiwweDdELDB4N0UsMHg3RiwweDgwLDB4ODIsMHg4MywweDg0LDB4ODUsMHg4NywweDg4LDB4ODksMHg4QSwweDhDLDB4OEQsMHg4RSwweDhGLDB4OTEsMHg5MiwweDkzLDB4OTRdLFsweDAyLDB4QUUsMHhBOCwweDZFLDB4NTcsMHgyRSwweEVBLDB4QjYsMHg2QiwweDJDLDB4M0EsMHhGNSwweEU5LDB4QTQsMHg2RiwweEQ2XSxbMHg4RiwweDY3LDB4ODYsMHhCRCwweDAwLDB4NzUsMHgyOCwweEJBLDB4MjYsMHg2MCwweDNDLDB4MTYsMHgwMSwweENELDB4RDAsMHhEOF1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDk2LDB4OTcsMHg5OCwweDk5LDB4OUIsMHg5QywweDlELDB4OUUsMHhBMCwweEExLDB4QTIsMHhBMywweEE1LDB4QTYsMHhBNywweEE4LDB4QUEsMHhBQiwweEFDLDB4QUQsMHhBRiwweEIwLDB4QjEsMHhCMl0sWzB4RTIsMHhBRSwweEY2LDB4QUMsMHhDMywweDNCLDB4OTYsMHg1QywweDRGLDB4QTEsMHhGOSwweDFDLDB4NzUsMHhGRiwweDZGLDB4MzZdLFsweEQxLDB4N0QsMHgwNywweDNCLDB4MDEsMHhFNywweDE1LDB4MDIsMHhFMiwweDhCLDB4NDcsMHhBQiwweDU1LDB4MTEsMHg2OCwweEIzXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4QjQsMHhCNSwweEI2LDB4QjcsMHhCOSwweEJBLDB4QkIsMHhCQywweEJFLDB4QkYsMHhDMCwweEMxLDB4QzMsMHhDNCwweEM1LDB4QzYsMHhDOCwweEM5LDB4Q0EsMHhDQiwweENELDB4Q0UsMHhDRiwweEQwXSxbMHgwNiwweDU5LDB4REYsMHg0NiwweDQyLDB4NzEsMHg2MiwweEI5LDB4NDMsMHg0OCwweDY1LDB4REQsMHg5NCwweDk5LDB4RjksMHgxRF0sWzB4QTQsMHg2OSwweERBLDB4NTEsMHg3MSwweDE5LDB4RkEsMHhCOSwweDU4LDB4NzYsMHhGNCwweDFELDB4MDYsMHhENCwweDBGLDB4RkFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHhEMiwweEQzLDB4RDQsMHhENSwweEQ3LDB4RDgsMHhEOSwweERBLDB4REMsMHhERCwweERFLDB4REYsMHhFMSwweEUyLDB4RTMsMHhFNCwweEU2LDB4RTcsMHhFOCwweEU5LDB4RUIsMHhFQywweEVELDB4RUVdLFsweDQ5LDB4QTQsMHg0MiwweDM5LDB4QzcsMHg0OCwweEZFLDB4QjQsMHg1NiwweEY1LDB4OUMsMHgyNywweDZBLDB4NTYsMHg1OCwweERGXSxbMHg2MCwweDkxLDB4QUEsMHgzQiwweDY5LDB4NUMsMHgxMSwweEY1LDB4QzAsMHhCNiwweEFELDB4MjYsMHhEMywweEQ4LDB4NjIsMHhGRl1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEYwLDB4RjEsMHhGMiwweEYzLDB4RjUsMHhGNiwweEY3LDB4RjgsMHhGQSwweEZCLDB4RkMsMHhGRCwweEZFLDB4MDEsMHgwMCwweDAyLDB4MDQsMHgwNSwweDA2LDB4MDcsMHgwOSwweDBBLDB4MEIsMHgwQ10sWzB4NjYsMHgyMCwweDhGLDB4NkUsMHg5RCwweDA0LDB4NTIsMHg1QiwweERFLDB4REIsMHgyNywweDMzLDB4QjYsMHhBNiwweEJFLDB4MzddLFsweDcwLDB4RjksMHhFNiwweDdGLDB4OUYsMHg4RCwweEYxLDB4MjksMHg0MSwweDMxLDB4NjYsMHgyRCwweEM2LDB4RTYsMHg5MywweDY0XV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4MEUsMHgwRiwweDEwLDB4MTEsMHgxMywweDE0LDB4MTUsMHgxNiwweDE4LDB4MTksMHgxQSwweDFCLDB4MUQsMHgxRSwweDFGLDB4MjAsMHgyMiwweDIzLDB4MjQsMHgyNSwweDI3LDB4MjgsMHgyOSwweDJBXSxbMHgzMywweDkzLDB4RjgsMHhERiwweEM3LDB4MjksMHhDOSwweDdGLDB4NTQsMHg4MCwweEI5LDB4NTAsMHhCQywweDk2LDB4NjYsMHhCMF0sWzB4RDEsMHg1NCwweERDLDB4QUYsMHhBRCwweDhCLDB4MjAsMHg3RiwweEE1LDB4Q0IsMHhDOSwweDVFLDB4OTksMHg5NiwweEI1LDB4NTldXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHgyQywweDJELDB4MkUsMHgyRiwweDMxLDB4MzIsMHgzMywweDM0LDB4MzYsMHgzNywweDM4LDB4MzksMHgzQiwweDNDLDB4M0QsMHgzRSwweDQwLDB4NDEsMHg0MiwweDQzLDB4NDUsMHg0NiwweDQ3LDB4NDhdLFsweDYwLDB4NjgsMHgzNCwweEM4LDB4Q0UsMHgwNiwweDNGLDB4MzIsMHgzNCwweENGLDB4MTEsMHg0NSwweDMyLDB4NUQsMHhCRCwweDcxXSxbMHg0OSwweDM0LDB4RDUsMHg0MSwweEU4LDB4QjQsMHg2RiwweEEzLDB4MzksMHhDOCwweDA1LDB4QTcsMHhBRSwweEI5LDB4RTUsMHhEQV1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweDRBLDB4NEIsMHg0QywweDRELDB4NEYsMHg1MCwweDUxLDB4NTIsMHg1NCwweDU1LDB4NTYsMHg1NywweDU5LDB4NUEsMHg1QiwweDVDLDB4NUUsMHg1RiwweDYwLDB4NjEsMHg2MywweDY0LDB4NjUsMHg2Nl0sWzB4RkUsMHhDMSwweEMwLDB4NEYsMHg1MiwweDlCLDB4QkQsMHgxNywweEQ4LDB4Q0UsMHhDRiwweENDLDB4NDcsMHgxOCwweEIxLDB4N0ZdLFsweDYyLDB4NTYsMHg0QywweDczLDB4OEYsMHgzRSwweEZFLDB4MTgsMHg2RSwweDFBLDB4MTIsMHg3QSwweDBDLDB4NEQsMHgzQywweDYxXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbWzB4NjgsMHg2OSwweDZBLDB4NkIsMHg2RCwweDZFLDB4NkYsMHg3MCwweDcyLDB4NzMsMHg3NCwweDc1LDB4NzcsMHg3OCwweDc5LDB4N0EsMHg3QywweDdELDB4N0UsMHg3RiwweDgxLDB4ODIsMHg4MywweDg0XSxbMHgzMiwweERGLDB4OTksMHhCNCwweDMxLDB4RUQsMHg1RCwweEM1LDB4QUMsMHhGOCwweENBLDB4RjYsMHhEQywweDZDLDB4RTQsMHg3NV0sWzB4MDcsMHg4MCwweDVBLDB4QTAsMHg0MywweDk4LDB4NkUsMHhCMiwweDM2LDB4OTMsMHhFMiwweDNCLDB4RUYsMHg4RiwweDM0LDB4MzhdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtbMHg4NiwweDg3LDB4ODgsMHg4OSwweDhCLDB4OEMsMHg4RCwweDhFLDB4OTAsMHg5MSwweDkyLDB4OTMsMHg5NSwweDk2LDB4OTcsMHg5OCwweDlBLDB4OUIsMHg5QywweDlELDB4OUYsMHhBMCwweEExLDB4QTJdLFsweDdGLDB4REMsMHgyQiwweDc0LDB4NkYsMHgzRiwweDY2LDB4NTIsMHg5NiwweDk0LDB4M0IsMHg4MywweDcxLDB4MEQsMHgxRiwweDgyXSxbMHhERiwweDBCLDB4NDksMHgzMSwweDAzLDB4OEIsMHhBRCwweEU4LDB4NDgsMHhERSwweEUzLDB4QjQsMHhCOCwweDVBLDB4QTQsMHg0Ql1dLFxuICAgICAgICAgICAgICAgICAgICAgICAgW1sweEE0LDB4QTUsMHhBNiwweEE3LDB4QTksMHhBQSwweEFCLDB4QUMsMHhBRSwweEFGLDB4QjAsMHhCMSwweEIzLDB4QjQsMHhCNSwweEI2LDB4QjgsMHhCOSwweEJBLDB4QkIsMHhCRCwweEJFLDB4QkYsMHhDMF0sWzB4OEYsMHhCQSwweDE1LDB4MTAsMHhBMywweEM1LDB4QjgsMHg3RSwweDJFLDB4QUEsMHgzRiwweDdBLDB4OTEsMHg0NSwweDVDLDB4QTJdLFsweDU5LDB4MkQsMHg1RiwweERFLDB4RDcsMHg2NSwweDgyLDB4RTQsMHgxNCwweDNDLDB4NjUsMHgwOSwweDkzLDB4MDksMHg0NywweDdDXV1dO1xuICBcbiAgdmFyIHRlc3R2ZWN0b3JzMjU2ID0gW1tbMHgwMCwweDAxLDB4MDIsMHgwMywweDA1LDB4MDYsMHgwNywweDA4LDB4MEEsMHgwQiwweDBDLDB4MEQsMHgwRiwweDEwLDB4MTEsMHgxMiwweDE0LDB4MTUsMHgxNiwweDE3LDB4MTksMHgxQSwweDFCLDB4MUMsMHgxRSwweDFGLDB4MjAsMHgyMSwweDIzLDB4MjQsMHgyNSwweDI2XSxbMHg4MywweDRFLDB4QUQsMHhGQywweENBLDB4QzcsMHhFMSwweEIzLDB4MDYsMHg2NCwweEIxLDB4QUIsMHhBNCwweDQ4LDB4MTUsMHhBQl0sWzB4MTksMHg0NiwweERBLDB4QkYsMHg2QSwweDAzLDB4QTIsMHhBMiwweEMzLDB4RDAsMHhCMCwweDUwLDB4ODAsMHhBRSwweEQ2LDB4RkNdXSxcbiAgICAgICAgICAgICAgW1sweDI4LDB4MjksMHgyQSwweDJCLDB4MkQsMHgyRSwweDJGLDB4MzAsMHgzMiwweDMzLDB4MzQsMHgzNSwweDM3LDB4MzgsMHgzOSwweDNBLDB4M0MsMHgzRCwweDNFLDB4M0YsMHg0MSwweDQyLDB4NDMsMHg0NCwweDQ2LDB4NDcsMHg0OCwweDQ5LDB4NEIsMHg0QywweDRELDB4NEVdLFsweEQ5LDB4REMsMHg0RCwweEJBLDB4MzAsMHgyMSwweEIwLDB4NUQsMHg2NywweEMwLDB4NTEsMHg4RiwweDcyLDB4QjYsMHgyQiwweEYxXSxbMHg1RSwweEQzLDB4MDEsMHhENywweDQ3LDB4RDMsMHhDQywweDcxLDB4NTQsMHg0NSwweEVCLDB4REUsMHhDNiwweDJGLDB4MkYsMHhCNF1dLFxuICAgICAgICAgICAgICBbWzB4NTAsMHg1MSwweDUyLDB4NTMsMHg1NSwweDU2LDB4NTcsMHg1OCwweDVBLDB4NUIsMHg1QywweDVELDB4NUYsMHg2MCwweDYxLDB4NjIsMHg2NCwweDY1LDB4NjYsMHg2NywweDY5LDB4NkEsMHg2QiwweDZDLDB4NkUsMHg2RiwweDcwLDB4NzEsMHg3MywweDc0LDB4NzUsMHg3Nl0sWzB4QTIsMHg5MSwweEQ4LDB4NjMsMHgwMSwweEE0LDB4QTcsMHgzOSwweEY3LDB4MzksMHgyMSwweDczLDB4QUEsMHgzQywweDYwLDB4NENdLFsweDY1LDB4ODUsMHhDOCwweEY0LDB4M0QsMHgxMywweEE2LDB4QkUsMHhBQiwweDY0LDB4MTksMHhGQywweDU5LDB4MzUsMHhCOSwweEQwXV0sXG4gICAgICAgICAgICAgIFtbMHg3OCwweDc5LDB4N0EsMHg3QiwweDdELDB4N0UsMHg3RiwweDgwLDB4ODIsMHg4MywweDg0LDB4ODUsMHg4NywweDg4LDB4ODksMHg4QSwweDhDLDB4OEQsMHg4RSwweDhGLDB4OTEsMHg5MiwweDkzLDB4OTQsMHg5NiwweDk3LDB4OTgsMHg5OSwweDlCLDB4OUMsMHg5RCwweDlFXSxbMHg0MiwweDY0LDB4QjIsMHg2OSwweDY0LDB4OTgsMHhERSwweDRELDB4RjcsMHg5NywweDg4LDB4QTksMHhGOCwweDNFLDB4OTMsMHg5MF0sWzB4MkEsMHg1QiwweDU2LDB4QTUsMHg5NiwweDY4LDB4MEYsMHhDQywweDBFLDB4MDUsMHhGNSwweEUwLDB4RjEsMHg1MSwweEVDLDB4QUVdXSxcbiAgICAgICAgICAgICAgW1sweEEwLDB4QTEsMHhBMiwweEEzLDB4QTUsMHhBNiwweEE3LDB4QTgsMHhBQSwweEFCLDB4QUMsMHhBRCwweEFGLDB4QjAsMHhCMSwweEIyLDB4QjQsMHhCNSwweEI2LDB4QjcsMHhCOSwweEJBLDB4QkIsMHhCQywweEJFLDB4QkYsMHhDMCwweEMxLDB4QzMsMHhDNCwweEM1LDB4QzZdLFsweEVFLDB4OTksMHgzMiwweEIzLDB4NzIsMHgxOCwweDA0LDB4RDUsMHhBOCwweDNFLDB4RjUsMHg5NCwweDkyLDB4NDUsMHhCNiwweEY2XSxbMHhGNSwweEQ2LDB4RkYsMHg0MSwweDRGLDB4RDIsMHhDNiwweDE4LDB4MTQsMHg5NCwweEQyLDB4MEMsMHgzNywweEYyLDB4QjgsMHhDNF1dLFxuICAgICAgICAgICAgICBbWzB4QzgsMHhDOSwweENBLDB4Q0IsMHhDRCwweENFLDB4Q0YsMHhEMCwweEQyLDB4RDMsMHhENCwweEQ1LDB4RDcsMHhEOCwweEQ5LDB4REEsMHhEQywweERELDB4REUsMHhERiwweEUxLDB4RTIsMHhFMywweEU0LDB4RTYsMHhFNywweEU4LDB4RTksMHhFQiwweEVDLDB4RUQsMHhFRV0sWzB4RTYsMHgyNCwweDhGLDB4NTUsMHhDNSwweEZELDB4Q0IsMHhDQSwweDlDLDB4QkIsMHhCMCwweDFDLDB4ODgsMHhBMiwweEVBLDB4NzddLFsweDg1LDB4MzksMHg5QywweDAxLDB4RjUsMHg5RiwweEZGLDB4QjUsMHgyMCwweDRGLDB4MTksMHhGOCwweDQ4LDB4MkYsMHgwMCwweEI4XV0sXG4gICAgICAgICAgICAgIFtbMHhGMCwweEYxLDB4RjIsMHhGMywweEY1LDB4RjYsMHhGNywweEY4LDB4RkEsMHhGQiwweEZDLDB4RkQsMHhGRSwweDAxLDB4MDAsMHgwMiwweDA0LDB4MDUsMHgwNiwweDA3LDB4MDksMHgwQSwweDBCLDB4MEMsMHgwRSwweDBGLDB4MTAsMHgxMSwweDEzLDB4MTQsMHgxNSwweDE2XSxbMHhCOCwweDM1LDB4OEUsMHg0MSwweEI5LDB4REYsMHhGNiwweDVGLDB4RDQsMHg2MSwweEQ1LDB4NUEsMHg5OSwweDI2LDB4NjIsMHg0N10sWzB4OTIsMHgwOSwweDdCLDB4NEMsMHg4OCwweEEwLDB4NDEsMHhERCwweEY5LDB4ODEsMHg0NCwweEJDLDB4OEQsMHgyMiwweEU4LDB4RTddXSxcbiAgICAgICAgICAgICAgW1sweDE4LDB4MTksMHgxQSwweDFCLDB4MUQsMHgxRSwweDFGLDB4MjAsMHgyMiwweDIzLDB4MjQsMHgyNSwweDI3LDB4MjgsMHgyOSwweDJBLDB4MkMsMHgyRCwweDJFLDB4MkYsMHgzMSwweDMyLDB4MzMsMHgzNCwweDM2LDB4MzcsMHgzOCwweDM5LDB4M0IsMHgzQywweDNELDB4M0VdLFsweEYwLDB4RTIsMHhENywweDIyLDB4NjAsMHhBRiwweDU4LDB4RTIsMHgxRSwweDAxLDB4NUEsMHhCMywweEE0LDB4QzAsMHhEOSwweDA2XSxbMHg4OSwweEJELDB4NUIsMHg3MywweEIzLDB4NTYsMHhBQiwweDQxLDB4MkEsMHhFRiwweDlGLDB4NzYsMHhDRSwweEEyLDB4RDYsMHg1Q11dLFxuICAgICAgICAgICAgICBbWzB4NDAsMHg0MSwweDQyLDB4NDMsMHg0NSwweDQ2LDB4NDcsMHg0OCwweDRBLDB4NEIsMHg0QywweDRELDB4NEYsMHg1MCwweDUxLDB4NTIsMHg1NCwweDU1LDB4NTYsMHg1NywweDU5LDB4NUEsMHg1QiwweDVDLDB4NUUsMHg1RiwweDYwLDB4NjEsMHg2MywweDY0LDB4NjUsMHg2Nl0sWzB4NDcsMHg1QiwweDhCLDB4ODIsMHgzQywweEU4LDB4ODksMHgzRCwweEIzLDB4QzQsMHg0QSwweDlGLDB4MkEsMHgzNywweDlGLDB4RjddLFsweDI1LDB4MzYsMHg5NiwweDkwLDB4OTMsMHhDNSwweDVGLDB4RjksMHg0NSwweDQ2LDB4OTIsMHhGMiwweEZBLDB4QzIsMHhGNSwweDMwXV0sXG4gICAgICAgICAgICAgIFtbMHg2OCwweDY5LDB4NkEsMHg2QiwweDZELDB4NkUsMHg2RiwweDcwLDB4NzIsMHg3MywweDc0LDB4NzUsMHg3NywweDc4LDB4NzksMHg3QSwweDdDLDB4N0QsMHg3RSwweDdGLDB4ODEsMHg4MiwweDgzLDB4ODQsMHg4NiwweDg3LDB4ODgsMHg4OSwweDhCLDB4OEMsMHg4RCwweDhFXSxbMHg2OCwweDhGLDB4NTIsMHg4MSwweDk0LDB4NTgsMHgxMiwweDg2LDB4MkYsMHg1RiwweDMwLDB4NzYsMHhDRiwweDgwLDB4NDEsMHgyRl0sWzB4MDcsMHhGQywweDc2LDB4QTgsMHg3MiwweDg0LDB4M0YsMHgzRiwweDZFLDB4MDAsMHg4MSwweEVFLDB4OTMsMHg5NiwweEQ2LDB4MzddXSxcbiAgICAgICAgICAgICAgW1sweDkwLDB4OTEsMHg5MiwweDkzLDB4OTUsMHg5NiwweDk3LDB4OTgsMHg5QSwweDlCLDB4OUMsMHg5RCwweDlGLDB4QTAsMHhBMSwweEEyLDB4QTQsMHhBNSwweEE2LDB4QTcsMHhBOSwweEFBLDB4QUIsMHhBQywweEFFLDB4QUYsMHhCMCwweEIxLDB4QjMsMHhCNCwweEI1LDB4QjZdLFsweDA4LDB4RDEsMHhEMiwweEJDLDB4NzUsMHgwQSwweEY1LDB4NTMsMHgzNiwweDVELDB4MzUsMHhFNywweDVBLDB4RkEsMHhDRSwweEFBXSxbMHhFMywweDhCLDB4QTgsMHhFQywweDJBLDB4QTcsMHg0MSwweDM1LDB4OEQsMHhDQywweDkzLDB4RTgsMHhGMSwweDQxLDB4QzQsMHg5MV1dLFxuICAgICAgICAgICAgICBbWzB4QjgsMHhCOSwweEJBLDB4QkIsMHhCRCwweEJFLDB4QkYsMHhDMCwweEMyLDB4QzMsMHhDNCwweEM1LDB4QzcsMHhDOCwweEM5LDB4Q0EsMHhDQywweENELDB4Q0UsMHhDRiwweEQxLDB4RDIsMHhEMywweEQ0LDB4RDYsMHhENywweEQ4LDB4RDksMHhEQiwweERDLDB4REQsMHhERV0sWzB4ODcsMHgwNywweDEyLDB4MUYsMHg0NywweENDLDB4M0UsMHhGQywweEVDLDB4QTUsMHhGOSwweEE4LDB4NDcsMHg0OSwweDUwLDB4QTFdLFsweEQwLDB4MjgsMHhFRSwweDIzLDB4RTQsMHhBOCwweDkwLDB4NzUsMHhEMCwweEIwLDB4M0UsMHg4NiwweDhELDB4N0QsMHgzQSwweDQyXV0sXG4gICAgICAgICAgICAgIFtbMHhFMCwweEUxLDB4RTIsMHhFMywweEU1LDB4RTYsMHhFNywweEU4LDB4RUEsMHhFQiwweEVDLDB4RUQsMHhFRiwweEYwLDB4RjEsMHhGMiwweEY0LDB4RjUsMHhGNiwweEY3LDB4RjksMHhGQSwweEZCLDB4RkMsMHhGRSwweEZFLDB4MDEsMHgwMSwweDAzLDB4MDQsMHgwNSwweDA2XSxbMHhFNSwweDFBLDB4QTAsMHhCMSwweDM1LDB4REIsMHhBNSwweDY2LDB4OTMsMHg5QywweDNCLDB4NjMsMHg1OSwweEE5LDB4ODAsMHhDNV0sWzB4OEMsMHhEOSwweDQyLDB4M0QsMHhGQywweDQ1LDB4OUUsMHg1NCwweDcxLDB4NTUsMHhDNSwweEQxLDB4RDUsMHgyMiwweEU1LDB4NDBdXSxcbiAgICAgICAgICAgICAgW1sweDA4LDB4MDksMHgwQSwweDBCLDB4MEQsMHgwRSwweDBGLDB4MTAsMHgxMiwweDEzLDB4MTQsMHgxNSwweDE3LDB4MTgsMHgxOSwweDFBLDB4MUMsMHgxRCwweDFFLDB4MUYsMHgyMSwweDIyLDB4MjMsMHgyNCwweDI2LDB4MjcsMHgyOCwweDI5LDB4MkIsMHgyQywweDJELDB4MkVdLFsweDA2LDB4OUEsMHgwMCwweDdGLDB4QzcsMHg2QSwweDQ1LDB4OUYsMHg5OCwweEJBLDB4RjksMHgxNywweEZFLDB4REYsMHg5NSwweDIxXSxbMHgwOCwweDBFLDB4OTUsMHgxNywweEVCLDB4MTYsMHg3NywweDcxLDB4OUEsMHhDRiwweDcyLDB4ODAsMHg4NiwweDA0LDB4MEEsMHhFM11dLFxuICAgICAgICAgICAgICBbWzB4MzAsMHgzMSwweDMyLDB4MzMsMHgzNSwweDM2LDB4MzcsMHgzOCwweDNBLDB4M0IsMHgzQywweDNELDB4M0YsMHg0MCwweDQxLDB4NDIsMHg0NCwweDQ1LDB4NDYsMHg0NywweDQ5LDB4NEEsMHg0QiwweDRDLDB4NEUsMHg0RiwweDUwLDB4NTEsMHg1MywweDU0LDB4NTUsMHg1Nl0sWzB4NzIsMHg2MSwweDY1LDB4QzEsMHg3MiwweDNGLDB4QkMsMHhGNiwweEMwLDB4MjYsMHhENywweEQwLDB4MEIsMHgwOSwweDEwLDB4MjddLFsweDdDLDB4MTcsMHgwMCwweDIxLDB4MUEsMHgzOSwweDkxLDB4RkMsMHgwRSwweENELDB4RUQsMHgwQSwweEIzLDB4RTUsMHg3NiwweEIwXV1dO1xuXG4gIHZhciByZXMgPSB0cnVlO1xuICB2YXIgaiA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMxMjgubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcmVzMiA9IHRlc3RfYWVzKHRlc3R2ZWN0b3JzMTI4W2ldWzFdLHRlc3R2ZWN0b3JzMTI4W2ldWzBdLHRlc3R2ZWN0b3JzMTI4W2ldWzJdKTtcbiAgICByZXMgJj0gcmVzMjtcbiAgICBpZiAoIXJlczIpIHtcbiAgICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgMTI4IGJpdCBrZXkgdmVjdG9yIHdpdGggYmxvY2sgXCIrXG4gICAgICAgIHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMxMjhbaV1bMV0pK1xuICAgICAgICBcIiBhbmQga2V5IFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMxMjhbaV1bMF0pK1xuICAgICAgICBcIiBzaG91bGQgYmUgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczEyOFtpXVsyXSksXG4gICAgICAgIGZhbHNlKTtcbiAgICAgIGorKztcbiAgICB9XG4gIH1cbiAgaWYgKHJlcykge1xuICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIjEyOCBiaXQga2V5IHRlc3QgdmVjdG9ycyBjb21wbGV0ZWQuXCIsdHJ1ZSlcbiAgICBqKys7XG4gIH1cbiAgXG4gIHJlcyA9IHRydWU7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMxOTIubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcmVzMiA9IHRlc3RfYWVzKHRlc3R2ZWN0b3JzMTkyW2ldWzFdLHRlc3R2ZWN0b3JzMTkyW2ldWzBdLHRlc3R2ZWN0b3JzMTkyW2ldWzJdKTtcbiAgICByZXMgJj0gcmVzMjtcbiAgICBpZiAoIXJlczIpIHtcbiAgICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgMTkyIGJpdCBrZXkgdmVjdG9yIHdpdGggYmxvY2sgXCIrXG4gICAgICAgIHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMxOTJbaV1bMV0pK1xuICAgICAgICBcIiBhbmQga2V5IFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMxOTJbaV1bMF0pK1xuICAgICAgICBcIiBzaG91bGQgYmUgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yczE5MltpXVsyXSksXG4gICAgICAgIGZhbHNlKTtcbiAgICAgIGorKztcbiAgICB9XG4gIH1cbiAgaWYgKHJlcykge1xuICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIjE5MiBiaXQga2V5IHRlc3QgdmVjdG9ycyBjb21wbGV0ZWQuXCIsdHJ1ZSlcbiAgICBqKys7XG4gIH1cblxuICByZXMgPSB0cnVlO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRlc3R2ZWN0b3JzMjU2Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJlczIgPSB0ZXN0X2Flcyh0ZXN0dmVjdG9yczI1NltpXVsxXSx0ZXN0dmVjdG9yczI1NltpXVswXSx0ZXN0dmVjdG9yczI1NltpXVsyXSk7XG4gICAgcmVzICY9IHJlczI7XG4gICAgaWYgKCFyZXMyKSB7XG4gICAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIDI1NiBiaXQga2V5IHZlY3RvciB3aXRoIGJsb2NrIFwiK1xuICAgICAgICB1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMjU2W2ldWzFdKStcbiAgICAgICAgXCIgYW5kIGtleSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzMjU2W2ldWzBdKStcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnMyNTZbaV1bMl0pLFxuICAgICAgICBmYWxzZSk7XG4gICAgICBqKys7XG4gICAgfVxuICB9XG4gIGlmIChyZXMpIHtcbiAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCIyNTYgYml0IGtleSB0ZXN0IHZlY3RvcnMgY29tcGxldGVkLlwiLCB0cnVlKVxuICAgIGorKztcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59KTtcbiIsInZhciB1bml0ID0gcmVxdWlyZSgnLi4vLi4vdW5pdC5qcycpO1xuXG51bml0LnJlZ2lzdGVyKFwiQmxvd2Zpc2ggY2lwaGVyIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBodHRwOi8vd3d3LnNjaG5laWVyLmNvbS9jb2RlL3ZlY3RvcnMudHh0XCIsIGZ1bmN0aW9uKCkge1xuICB2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLy4uLycpLFxuICAgIHV0aWwgPSBvcGVucGdwLnV0aWwsXG4gICAgQkZlbmNyeXB0ID0gb3BlbnBncC5jcnlwdG8uY2lwaGVyLmJsb3dmaXNoO1xuXG4gIHZhciByZXN1bHQgPSBbXTtcbiAgZnVuY3Rpb24gdGVzdF9iZihpbnB1dCwga2V5LCBvdXRwdXQpIHtcbiAgICB2YXIgYmxvd2Zpc2ggPSBuZXcgb3BlbnBncC5jcnlwdG8uY2lwaGVyLmJsb3dmaXNoKHV0aWwuYmluMnN0cihrZXkpKTtcbiAgICB2YXIgcmVzdWx0ID0gdXRpbC5iaW4yc3RyKGJsb3dmaXNoLmVuY3J5cHQoaW5wdXQpKTtcblxuICAgIHJldHVybiAodXRpbC5oZXhzdHJkdW1wKHJlc3VsdCkgPT0gdXRpbC5oZXhzdHJkdW1wKHV0aWwuYmluMnN0cihvdXRwdXQpKSk7XG4gIH1cbiAgdmFyIHRlc3R2ZWN0b3JzID0gW1tbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHg0RSwweEY5LDB4OTcsMHg0NSwweDYxLDB4OTgsMHhERCwweDc4XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4NTEsMHg4NiwweDZGLDB4RDUsMHhCOCwweDVFLDB4Q0IsMHg4QV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDMwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDEwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDFdLFsweDdELDB4ODUsMHg2RiwweDlBLDB4NjEsMHgzMCwweDYzLDB4RjJdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExXSxbMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExXSxbMHgyNCwweDY2LDB4REQsMHg4NywweDhCLDB4OTYsMHgzQywweDlEXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMV0sWzB4NjEsMHhGOSwweEMzLDB4ODAsMHgyMiwweDgxLDB4QjAsMHg5Nl1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDExLDB4MTEsMHgxMSwweDExLDB4MTEsMHgxMSwweDExLDB4MTFdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDdELDB4MEMsMHhDNiwweDMwLDB4QUYsMHhEQSwweDFFLDB4QzddXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHg0RSwweEY5LDB4OTcsMHg0NSwweDYxLDB4OTgsMHhERCwweDc4XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkUsMHhEQywweEJBLDB4OTgsMHg3NiwweDU0LDB4MzIsMHgxMF0sWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4MEEsMHhDRSwweEFCLDB4MEYsMHhDNiwweEEwLDB4QTIsMHg4RF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDdDLDB4QTEsMHgxMCwweDQ1LDB4NEEsMHgxQSwweDZFLDB4NTddLFsweDAxLDB4QTEsMHhENiwweEQwLDB4MzksMHg3NywweDY3LDB4NDJdLFsweDU5LDB4QzYsMHg4MiwweDQ1LDB4RUIsMHgwNSwweDI4LDB4MkJdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMSwweDMxLDB4RDksMHg2MSwweDlELDB4QzEsMHgzNywweDZFXSxbMHg1QywweEQ1LDB4NEMsMHhBOCwweDNELDB4RUYsMHg1NywweERBXSxbMHhCMSwweEI4LDB4Q0MsMHgwQiwweDI1LDB4MEYsMHgwOSwweEEwXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDcsMHhBMSwweDEzLDB4M0UsMHg0QSwweDBCLDB4MjYsMHg4Nl0sWzB4MDIsMHg0OCwweEQ0LDB4MzgsMHgwNiwweEY2LDB4NzEsMHg3Ml0sWzB4MTcsMHgzMCwweEU1LDB4NzcsMHg4QiwweEVBLDB4MUQsMHhBNF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDM4LDB4NDksMHg2NywweDRDLDB4MjYsMHgwMiwweDMxLDB4OUVdLFsweDUxLDB4NDUsMHg0QiwweDU4LDB4MkQsMHhERiwweDQ0LDB4MEFdLFsweEEyLDB4NUUsMHg3OCwweDU2LDB4Q0YsMHgyNiwweDUxLDB4RUJdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwNCwweEI5LDB4MTUsMHhCQSwweDQzLDB4RkUsMHhCNSwweEI2XSxbMHg0MiwweEZELDB4NDQsMHgzMCwweDU5LDB4NTcsMHg3RiwweEEyXSxbMHgzNSwweDM4LDB4ODIsMHhCMSwweDA5LDB4Q0UsMHg4RiwweDFBXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgxMywweEI5LDB4NzAsMHhGRCwweDM0LDB4RjIsMHhDRV0sWzB4MDUsMHg5QiwweDVFLDB4MDgsMHg1MSwweENGLDB4MTQsMHgzQV0sWzB4NDgsMHhGNCwweEQwLDB4ODgsMHg0QywweDM3LDB4OTksMHgxOF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4NzAsMHhGMSwweDc1LDB4NDYsMHg4RiwweEI1LDB4RTZdLFsweDA3LDB4NTYsMHhEOCwweEUwLDB4NzcsMHg0NywweDYxLDB4RDJdLFsweDQzLDB4MjEsMHg5MywweEI3LDB4ODksMHg1MSwweEZDLDB4OThdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg0MywweDI5LDB4N0YsMHhBRCwweDM4LDB4RTMsMHg3MywweEZFXSxbMHg3NiwweDI1LDB4MTQsMHhCOCwweDI5LDB4QkYsMHg0OCwweDZBXSxbMHgxMywweEYwLDB4NDEsMHg1NCwweEQ2LDB4OUQsMHgxQSwweEU1XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDcsMHhBNywweDEzLDB4NzAsMHg0NSwweERBLDB4MkEsMHgxNl0sWzB4M0IsMHhERCwweDExLDB4OTAsMHg0OSwweDM3LDB4MjgsMHgwMl0sWzB4MkUsMHhFRCwweERBLDB4OTMsMHhGRiwweEQzLDB4OUMsMHg3OV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDA0LDB4NjgsMHg5MSwweDA0LDB4QzIsMHhGRCwweDNCLDB4MkZdLFsweDI2LDB4OTUsMHg1RiwweDY4LDB4MzUsMHhBRiwweDYwLDB4OUFdLFsweEQ4LDB4ODcsMHhFMCwweDM5LDB4M0MsMHgyRCwweEE2LDB4RTNdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgzNywweEQwLDB4NkIsMHhCNSwweDE2LDB4Q0IsMHg3NSwweDQ2XSxbMHgxNiwweDRELDB4NUUsMHg0MCwweDRGLDB4MjcsMHg1MiwweDMyXSxbMHg1RiwweDk5LDB4RDAsMHg0RiwweDVCLDB4MTYsMHgzOSwweDY5XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MUYsMHgwOCwweDI2LDB4MEQsMHgxQSwweEMyLDB4NDYsMHg1RV0sWzB4NkIsMHgwNSwweDZFLDB4MTgsMHg3NSwweDlGLDB4NUMsMHhDQV0sWzB4NEEsMHgwNSwweDdBLDB4M0IsMHgyNCwweEQzLDB4OTcsMHg3Ql1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDU4LDB4NDAsMHgyMywweDY0LDB4MUEsMHhCQSwweDYxLDB4NzZdLFsweDAwLDB4NEIsMHhENiwweEVGLDB4MDksMHgxNywweDYwLDB4NjJdLFsweDQ1LDB4MjAsMHgzMSwweEMxLDB4RTQsMHhGQSwweERBLDB4OEVdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMiwweDU4LDB4MTYsMHgxNiwweDQ2LDB4MjksMHhCMCwweDA3XSxbMHg0OCwweDBELDB4MzksMHgwMCwweDZFLDB4RTcsMHg2MiwweEYyXSxbMHg3NSwweDU1LDB4QUUsMHgzOSwweEY1LDB4OUIsMHg4NywweEJEXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4NDksMHg3OSwweDNFLDB4QkMsMHg3OSwweEIzLDB4MjUsMHg4Rl0sWzB4NDMsMHg3NSwweDQwLDB4QzgsMHg2OSwweDhGLDB4M0MsMHhGQV0sWzB4NTMsMHhDNSwweDVGLDB4OUMsMHhCNCwweDlGLDB4QzAsMHgxOV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDRGLDB4QjAsMHg1RSwweDE1LDB4MTUsMHhBQiwweDczLDB4QTddLFsweDA3LDB4MkQsMHg0MywweEEwLDB4NzcsMHgwNywweDUyLDB4OTJdLFsweDdBLDB4OEUsMHg3QiwweEZBLDB4OTMsMHg3RSwweDg5LDB4QTNdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHg0OSwweEU5LDB4NUQsMHg2RCwweDRDLDB4QTIsMHgyOSwweEJGXSxbMHgwMiwweEZFLDB4NTUsMHg3NywweDgxLDB4MTcsMHhGMSwweDJBXSxbMHhDRiwweDlDLDB4NUQsMHg3QSwweDQ5LDB4ODYsMHhBRCwweEI1XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHg4MywweDEwLDB4REMsMHg0MCwweDlCLDB4MjYsMHhENl0sWzB4MUQsMHg5RCwweDVDLDB4NTAsMHgxOCwweEY3LDB4MjgsMHhDMl0sWzB4RDEsMHhBQiwweEIyLDB4OTAsMHg2NSwweDhCLDB4QzcsMHg3OF1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDFDLDB4NTgsMHg3RiwweDFDLDB4MTMsMHg5MiwweDRGLDB4RUZdLFsweDMwLDB4NTUsMHgzMiwweDI4LDB4NkQsMHg2RiwweDI5LDB4NUFdLFsweDU1LDB4Q0IsMHgzNywweDc0LDB4RDEsMHgzRSwweEYyLDB4MDFdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMSwweDAxLDB4MDEsMHgwMSwweDAxLDB4MDEsMHgwMSwweDAxXSxbMHgwMSwweDIzLDB4NDUsMHg2NywweDg5LDB4QUIsMHhDRCwweEVGXSxbMHhGQSwweDM0LDB4RUMsMHg0OCwweDQ3LDB4QjIsMHg2OCwweEIyXV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MUYsMHgxRiwweDFGLDB4MUYsMHgwRSwweDBFLDB4MEUsMHgwRV0sWzB4MDEsMHgyMywweDQ1LDB4NjcsMHg4OSwweEFCLDB4Q0QsMHhFRl0sWzB4QTcsMHg5MCwweDc5LDB4NTEsMHgwOCwweEVBLDB4M0MsMHhBRV1dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweEUwLDB4RkUsMHhFMCwweEZFLDB4RjEsMHhGRSwweEYxLDB4RkVdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweEMzLDB4OUUsMHgwNywweDJELDB4OUYsMHhBQywweDYzLDB4MURdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwXSxbMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGXSxbMHgwMSwweDQ5LDB4MzMsMHhFMCwweENELDB4QUYsMHhGNiwweEU0XV0sXG4gICAgICAgICAgICAgICAgICAgICBbWzB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRl0sWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RjIsMHgxRSwweDlBLDB4NzcsMHhCNywweDFDLDB4NDksMHhCQ11dLFxuICAgICAgICAgICAgICAgICAgICAgW1sweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDBdLFsweDI0LDB4NTksMHg0NiwweDg4LDB4NTcsMHg1NCwweDM2LDB4OUFdXSxcbiAgICAgICAgICAgICAgICAgICAgIFtbMHhGRSwweERDLDB4QkEsMHg5OCwweDc2LDB4NTQsMHgzMiwweDEwXSxbMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGLDB4RkYsMHhGRiwweEZGXSxbMHg2QiwweDVDLDB4NUEsMHg5QywweDVELDB4OUUsMHgwQSwweDVBXV1dO1xuXG4gIHZhciByZXMgPSB0cnVlO1xuICB2YXIgaiA9IDA7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcmVzMiA9IHRlc3RfYmYodGVzdHZlY3RvcnNbaV1bMV0sdGVzdHZlY3RvcnNbaV1bMF0sdGVzdHZlY3RvcnNbaV1bMl0pO1xuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3IgXCIraStcIiB3aXRoIGJsb2NrIFwiK1xuICAgICAgICB1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzBdKStcbiAgICAgICAgXCIgYW5kIGtleSBcIit1dGlsLmhleGlkdW1wKHRlc3R2ZWN0b3JzW2ldWzFdKStcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMl0pLCBmYWxzZSk7XG4gICAgICBqKys7XG4gICAgfVxuICB9XG4gIGlmIChyZXMpIHtcbiAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCIzNCB0ZXN0IHZlY3RvcnMgY29tcGxldGVkIFwiLCB0cnVlKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIkNBU1QtMTI4IGNpcGhlciB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gUkZDMjE0NFwiLCBmdW5jdGlvbigpIHtcblx0dmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcblx0XHR1dGlsID0gb3BlbnBncC51dGlsO1xuXG5cdHZhciByZXN1bHQgPSBbXTtcblx0ZnVuY3Rpb24gdGVzdF9jYXN0KGlucHV0LCBrZXksIG91dHB1dCkge1xuXHRcdHZhciBjYXN0NSA9IG5ldyBvcGVucGdwLmNyeXB0by5jaXBoZXIuY2FzdDUodXRpbC5iaW4yc3RyKGtleSkpO1xuXHRcdHZhciByZXN1bHQgPSB1dGlsLmJpbjJzdHIoY2FzdDUuZW5jcnlwdChpbnB1dCkpO1xuXG5cdFx0cmV0dXJuIHV0aWwuaGV4c3RyZHVtcChyZXN1bHQpID09IHV0aWwuaGV4c3RyZHVtcCh1dGlsLmJpbjJzdHIob3V0cHV0KSk7XG5cdH1cblx0XG5cdHZhciB0ZXN0dmVjdG9ycyA9IFtbWzB4MDEsMHgyMywweDQ1LDB4NjcsMHgxMiwweDM0LDB4NTYsMHg3OCwweDIzLDB4NDUsMHg2NywweDg5LDB4MzQsMHg1NiwweDc4LDB4OUFdLFsweDAxLDB4MjMsMHg0NSwweDY3LDB4ODksMHhBQiwweENELDB4RUZdLFsweDIzLDB4OEIsMHg0RiwweEU1LDB4ODQsMHg3RSwweDQ0LDB4QjJdXV07XG5cblx0Zm9yICh2YXIgaSA9IDA7IGkgPCB0ZXN0dmVjdG9ycy5sZW5ndGg7IGkrKykge1xuXHRcdHJlc3VsdFtpXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgdmVjdG9yIHdpdGggYmxvY2sgXCIrXG5cdFx0XHRcdHV0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMF0pK1xuXHRcdFx0XHRcIiBhbmQga2V5IFwiK3V0aWwuaGV4aWR1bXAodGVzdHZlY3RvcnNbaV1bMV0pK1xuXHRcdFx0XHRcIiBzaG91bGQgYmUgXCIrdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVsyXSksXG5cdFx0XHR0ZXN0X2Nhc3QodGVzdHZlY3RvcnNbaV1bMV0sdGVzdHZlY3RvcnNbaV1bMF0sdGVzdHZlY3RvcnNbaV1bMl0pKTtcblx0fVxuXHRyZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcclxuXHJcbnVuaXQucmVnaXN0ZXIoXCJUcmlwbGVERVMgKEVERSkgY2lwaGVyIHRlc3Qgd2l0aCB0ZXN0IHZlY3RvcnMgZnJvbSBodHRwOi8vY3NyYy5uaXN0Lmdvdi9wdWJsaWNhdGlvbnMvbmlzdHB1YnMvODAwLTIwLzgwMC0yMC5wZGZcIiwgZnVuY3Rpb24oKSB7XHJcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcclxuICAgIHV0aWwgPSBvcGVucGdwLnV0aWw7XHJcblxyXG4gIHZhciByZXN1bHQgPSBbXTtcclxuICB2YXIga2V5ID0gdXRpbC5iaW4yc3RyKFsxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMSwxLDEsMV0pO1xyXG4gIHZhciB0ZXN0dmVjdG9ycyA9IFtbWzB4ODAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4OTUsMHhGOCwweEE1LDB4RTUsMHhERCwweDMxLDB4RDksMHgwMF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4NDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4REQsMHg3RiwweDEyLDB4MUMsMHhBNSwweDAxLDB4NTYsMHgxOV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MjAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MkUsMHg4NiwweDUzLDB4MTAsMHg0RiwweDM4LDB4MzQsMHhFQV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MTAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NEIsMHhEMywweDg4LDB4RkYsMHg2QywweEQ4LDB4MUQsMHg0Rl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDgsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MjAsMHhCOSwweEU3LDB4NjcsMHhCMiwweEZCLDB4MTQsMHg1Nl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDQsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NTUsMHg1NywweDkzLDB4ODAsMHhENywweDcxLDB4MzgsMHhFRl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDIsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NkMsMHhDNSwweERFLDB4RkEsMHhBRiwweDA0LDB4NTEsMHgyRl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDEsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MEQsMHg5RiwweDI3LDB4OUIsMHhBNSwweEQ4LDB4NzIsMHg2MF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHg4MCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RDksMHgwMywweDFCLDB4MDIsMHg3MSwweEJELDB4NUEsMHgwQV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHg0MCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NDIsMHg0MiwweDUwLDB4QjMsMHg3QywweDNELDB4RDksMHg1MV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgyMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4QjgsMHgwNiwweDFCLDB4N0UsMHhDRCwweDlBLDB4MjEsMHhFNV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgxMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RjEsMHg1RCwweDBGLDB4MjgsMHg2QiwweDY1LDB4QkQsMHgyOF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwOCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4QUQsMHhEMCwweENDLDB4OEQsMHg2RSwweDVELDB4RUIsMHhBMV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwNCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RTYsMHhENSwweEY4LDB4MjcsMHg1MiwweEFELDB4NjMsMHhEMV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMiwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RUMsMHhCRiwweEUzLDB4QkQsMHgzRiwweDU5LDB4MUEsMHg1RV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMSwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RjMsMHg1NiwweDgzLDB4NDMsMHg3OSwweEQxLDB4NjUsMHhDRF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDgwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MkIsMHg5RiwweDk4LDB4MkYsMHgyMCwweDAzLDB4N0YsMHhBOV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDQwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4ODgsMHg5RCwweEUwLDB4NjgsMHhBMSwweDZGLDB4MEIsMHhFNl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDIwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RTEsMHg5RSwweDI3LDB4NUQsMHg4NCwweDZBLDB4MTIsMHg5OF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDEwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MzIsMHg5QSwweDhFLDB4RDUsMHgyMywweEQ3LDB4MUEsMHhFQ11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDA4LDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RTcsMHhGQywweEUyLDB4MjUsMHg1NywweEQyLDB4M0MsMHg5N11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDA0LDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4MTIsMHhBOSwweEY1LDB4ODEsMHg3RiwweEYyLDB4RDYsMHg1RF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAyLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4QTQsMHg4NCwweEMzLDB4QUQsMHgzOCwweERDLDB4OUMsMHgxOV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAxLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RkIsMHhFMCwweDBBLDB4OEEsMHgxRSwweEY4LDB4QUQsMHg3Ml1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4ODAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NzUsMHgwRCwweDA3LDB4OTQsMHgwNywweDUyLDB4MTMsMHg2M11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4NDAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4NjQsMHhGRSwweEVELDB4OUMsMHg3MiwweDRDLDB4MkYsMHhBRl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MjAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RjAsMHgyQiwweDI2LDB4M0IsMHgzMiwweDhFLDB4MkIsMHg2MF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MTAsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4OUQsMHg2NCwweDU1LDB4NUEsMHg5QSwweDEwLDB4QjgsMHg1Ml1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDgsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RDEsMHgwNiwweEZGLDB4MEIsMHhFRCwweDUyLDB4NTUsMHhEN11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDQsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RTEsMHg2NSwweDJDLDB4NkIsMHgxMywweDhDLDB4NjQsMHhBNV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDIsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4RTQsMHgyOCwweDU4LDB4MTEsMHg4NiwweEVDLDB4OEYsMHg0Nl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDEsMHgwMCwweDAwLDB4MDAsMHgwMF0sWzB4QUUsMHhCNSwweEY1LDB4RUQsMHhFMiwweDJELDB4MUEsMHgzNl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHg4MCwweDAwLDB4MDAsMHgwMF0sWzB4RTksMHg0MywweEQ3LDB4NTYsMHg4QSwweEVDLDB4MEMsMHg1Q11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHg0MCwweDAwLDB4MDAsMHgwMF0sWzB4REYsMHg5OCwweEM4LDB4MjcsMHg2RiwweDU0LDB4QjAsMHg0Ql1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgyMCwweDAwLDB4MDAsMHgwMF0sWzB4QjEsMHg2MCwweEU0LDB4NjgsMHgwRiwweDZDLDB4NjksMHg2Rl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgxMCwweDAwLDB4MDAsMHgwMF0sWzB4RkEsMHgwNywweDUyLDB4QjAsMHg3RCwweDlDLDB4NEEsMHhCOF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwOCwweDAwLDB4MDAsMHgwMF0sWzB4Q0EsMHgzQSwweDJCLDB4MDMsMHg2RCwweEJDLDB4ODUsMHgwMl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwNCwweDAwLDB4MDAsMHgwMF0sWzB4NUUsMHgwOSwweDA1LDB4NTEsMHg3QiwweEI1LDB4OUIsMHhDRl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMiwweDAwLDB4MDAsMHgwMF0sWzB4ODEsMHg0RSwweEVCLDB4M0IsMHg5MSwweEQ5LDB4MDcsMHgyNl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMSwweDAwLDB4MDAsMHgwMF0sWzB4NEQsMHg0OSwweERCLDB4MTUsMHgzMiwweDkxLDB4OUMsMHg5Rl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDgwLDB4MDAsMHgwMF0sWzB4MjUsMHhFQiwweDVGLDB4QzMsMHhGOCwweENGLDB4MDYsMHgyMV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDQwLDB4MDAsMHgwMF0sWzB4QUIsMHg2QSwweDIwLDB4QzAsMHg2MiwweDBELDB4MUMsMHg2Rl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDIwLDB4MDAsMHgwMF0sWzB4NzksMHhFOSwweDBELDB4QkMsMHg5OCwweEY5LDB4MkMsMHhDQV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDEwLDB4MDAsMHgwMF0sWzB4ODYsMHg2RSwweENFLDB4REQsMHg4MCwweDcyLDB4QkIsMHgwRV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDA4LDB4MDAsMHgwMF0sWzB4OEIsMHg1NCwweDUzLDB4NkYsMHgyRiwweDNFLDB4NjQsMHhBOF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDA0LDB4MDAsMHgwMF0sWzB4RUEsMHg1MSwweEQzLDB4OTcsMHg1NSwweDk1LDB4QjgsMHg2Ql1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAyLDB4MDAsMHgwMF0sWzB4Q0EsMHhGRiwweEM2LDB4QUMsMHg0NSwweDQyLDB4REUsMHgzMV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAxLDB4MDAsMHgwMF0sWzB4OEQsMHhENCwweDVBLDB4MkQsMHhERiwweDkwLDB4NzksMHg2Q11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4ODAsMHgwMF0sWzB4MTAsMHgyOSwweEQ1LDB4NUUsMHg4OCwweDBFLDB4QzIsMHhEMF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4NDAsMHgwMF0sWzB4NUQsMHg4NiwweENCLDB4MjMsMHg2MywweDlELDB4QkUsMHhBOV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MjAsMHgwMF0sWzB4MUQsMHgxQywweEE4LDB4NTMsMHhBRSwweDdDLDB4MEMsMHg1Rl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MTAsMHgwMF0sWzB4Q0UsMHgzMywweDIzLDB4MjksMHgyNCwweDhGLDB4MzIsMHgyOF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDgsMHgwMF0sWzB4ODQsMHgwNSwweEQxLDB4QUIsMHhFMiwweDRGLDB4QjksMHg0Ml1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDQsMHgwMF0sWzB4RTYsMHg0MywweEQ3LDB4ODAsMHg5MCwweENBLDB4NDIsMHgwN11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDIsMHgwMF0sWzB4NDgsMHgyMiwweDFCLDB4OTksMHgzNywweDc0LDB4OEEsMHgyM11dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDEsMHgwMF0sWzB4REQsMHg3QywweDBCLDB4QkQsMHg2MSwweEZBLDB4RkQsMHg1NF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHg4MF0sWzB4MkYsMHhCQywweDI5LDB4MUEsMHg1NywweDBELDB4QjUsMHhDNF1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHg0MF0sWzB4RTAsMHg3QywweDMwLDB4RDcsMHhFNCwweEUyLDB4NkUsMHgxMl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgyMF0sWzB4MDksMHg1MywweEUyLDB4MjUsMHg4RSwweDhFLDB4OTAsMHhBMV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgxMF0sWzB4NUIsMHg3MSwweDFCLDB4QzQsMHhDRSwweEVCLDB4RjIsMHhFRV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwOF0sWzB4Q0MsMHgwOCwweDNGLDB4MUUsMHg2RCwweDlFLDB4ODUsMHhGNl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwNF0sWzB4RDIsMHhGRCwweDg4LDB4NjcsMHhENSwweDBELDB4MkQsMHhGRV1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMl0sWzB4MDYsMHhFNywweEVBLDB4MjIsMHhDRSwweDkyLDB4NzAsMHg4Rl1dLFxyXG4gICAgICAgICAgICAgICAgICAgICBbWzB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMCwweDAwLDB4MDAsMHgwMV0sWzB4MTYsMHg2QiwweDQwLDB4QjQsMHg0QSwweEJBLDB4NEIsMHhENl1dXTtcclxuXHJcbiAgdmFyIHJlcyA9IHRydWU7XHJcbiAgdmFyIGogPSAwO1xyXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGVzdHZlY3RvcnMubGVuZ3RoOyBpKyspIHtcclxuICAgIHZhciBkZXMgPSBuZXcgb3BlbnBncC5jcnlwdG8uY2lwaGVyLmRlcyhrZXkpO1xyXG5cclxuICAgIHZhciBlbmNyID0gdXRpbC5iaW4yc3RyKGRlcy5lbmNyeXB0KHRlc3R2ZWN0b3JzW2ldWzBdLCBrZXkpKTtcclxuICAgIHZhciByZXMyID0gZW5jciA9PSB1dGlsLmJpbjJzdHIodGVzdHZlY3RvcnNbaV1bMV0pO1xyXG5cclxuICAgIHJlcyAmPSByZXMyO1xyXG5cclxuICAgIGlmICghcmVzMikge1xyXG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3Igd2l0aCBibG9jayBcIiArXHJcbiAgICAgICAgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVswXSkgK1xyXG4gICAgICAgIFwiIGFuZCBrZXkgXCIgKyB1dGlsLmhleHN0cmR1bXAoa2V5KSArXHJcbiAgICAgICAgXCIgc2hvdWxkIGJlIFwiICsgdXRpbC5oZXhpZHVtcCh0ZXN0dmVjdG9yc1tpXVsxXSkgKyBcIiAhPSBcIiArXHJcbiAgICAgICAgdXRpbC5oZXhpZHVtcChlbmNyKSxcclxuICAgICAgZmFsc2UpO1xyXG4gICAgaisrO1xyXG4gICAgfVxyXG4gIH1cclxuICBpZiAocmVzKSB7XHJcbiAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXCJBbGwgM0RFUyBFREUgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZFwiLCB0cnVlKTtcclxuICB9XHJcbiAgcmV0dXJuIHJlc3VsdDtcclxufSk7XHJcblxyXG5cclxudW5pdC5yZWdpc3RlcihcIkRFUyBlbmNyeXB0L2RlY3J5cHQgcGFkZGluZyB0ZXN0c1wiLCBmdW5jdGlvbiAoKSB7XHJcbiAgICB2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLy4uLycpLFxyXG4gICAgICB1dGlsID0gb3BlbnBncC51dGlsO1xyXG5cclxuICAgIHZhciByZXN1bHQgPSBbXTtcclxuICAgIHZhciBrZXkgPSB1dGlsLmJpbjJzdHIoWzB4MDEsIDB4MjMsIDB4NDUsIDB4NjcsIDB4ODksIDB4QUIsIDB4Q0QsIDB4RUZdKTtcclxuICAgIHZhciB0ZXN0dmVjdG9ycyA9IG5ldyBBcnJheSgpO1xyXG4gICAgdGVzdHZlY3RvcnNbMF0gPSBbW1sweDAxXSwgWzB4MjQsIDB4QzcsIDB4NEEsIDB4OUEsIDB4NzksIDB4NzUsIDB4NEIsIDB4QzddXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDIsIDB4MDNdLCBbMHhBNywgMHg3QSwgMHg5QSwgMHg1OSwgMHg4QSwgMHg4NiwgMHg4NSwgMHhDNV1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwMywgMHgwNCwgMHgwNV0sIFsweDAxLCAweENGLCAweEVCLCAweDZBLCAweDc0LCAweDYwLCAweEY1LCAweDAyXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA0LCAweDA1LCAweDA2LCAweDA3XSwgWzB4QTgsIDB4RjAsIDB4M0QsIDB4NTksIDB4QkEsIDB4NkIsIDB4MEUsIDB4NzZdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDUsIDB4MDYsIDB4MDcsIDB4MDgsIDB4MDldLCBbMHg4NiwgMHg0MCwgMHgzMywgMHg2MSwgMHgzRiwgMHg1NSwgMHg3MywgMHg0OV1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNiwgMHgwNywgMHgwOCwgMHgwOSwgMHgwQSwgMHgwQl0sIFsweDEzLCAweDIxLCAweDNFLCAweDBFLCAweENFLCAweDJDLCAweDk0LCAweDAxXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA3LCAweDA4LCAweDA5LCAweDBBLCAweDBCLCAweDBDLCAweDBEXSwgWzB4MzAsIDB4NDksIDB4OTcsIDB4QzEsIDB4REEsIDB4RDUsIDB4NTksIDB4QTVdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDgsIDB4MDksIDB4MEEsIDB4MEIsIDB4MEMsIDB4MEQsIDB4MEUsIDB4MEZdLCBbMHg4MywgMHgyNSwgMHg3OSwgMHgwNiwgMHg1NCwgMHhBNCwgMHg0NCwgMHhEOV1dXTtcclxuICAgIHRlc3R2ZWN0b3JzWzFdID0gW1tbMHgwMV0sIFsweEYyLCAweEFCLCAweDFDLCAweDlFLCAweDcwLCAweDdELCAweENDLCAweDkyXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDAyLCAweDAzXSwgWzB4NkIsIDB4NEMsIDB4NjcsIDB4MjQsIDB4OUYsIDB4QjcsIDB4NEQsIDB4QUNdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDMsIDB4MDQsIDB4MDVdLCBbMHg2OCwgMHg5NSwgMHhBQiwgMHhBOCwgMHhFQSwgMHg1MywgMHgxMywgMHgyM11dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNCwgMHgwNSwgMHgwNiwgMHgwN10sIFsweEM4LCAweERFLCAweDYwLCAweDhGLCAweEY2LCAweDA5LCAweDkwLCAweEI1XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA1LCAweDA2LCAweDA3LCAweDA4LCAweDA5XSwgWzB4MTksIDB4MTMsIDB4NTAsIDB4MjAsIDB4NzAsIDB4NDAsIDB4MkUsIDB4MDldXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDYsIDB4MDcsIDB4MDgsIDB4MDksIDB4MEEsIDB4MEJdLCBbMHhBOCwgMHgyMywgMHg0MCwgMHhDNiwgMHgxNywgMHhBNiwgMHgzMSwgMHg0QV1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNywgMHgwOCwgMHgwOSwgMHgwQSwgMHgwQiwgMHgwQywgMHgwRF0sIFsweDM2LCAweDYyLCAweEYyLCAweDk5LCAweDY4LCAweEQ0LCAweEJGLCAweDdDXV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA4LCAweDA5LCAweDBBLCAweDBCLCAweDBDLCAweDBELCAweDBFLCAweDBGXSwgWzB4ODMsIDB4MjUsIDB4NzksIDB4MDYsIDB4NTQsIDB4QTQsIDB4NDQsIDB4RDksIDB4MDgsIDB4NkYsIDB4OUEsIDB4MUQsIDB4NzQsIDB4QzksIDB4NEQsIDB4NEVdXV07XHJcbiAgICB0ZXN0dmVjdG9yc1syXSA9IFtbWzB4MDFdLCBbMHg4MywgMHg2OCwgMHhFNCwgMHg5QywgMHg4NCwgMHhDQywgMHhDQiwgMHhGMF1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwMiwgMHgwM10sIFsweEJCLCAweEE4LCAweDBCLCAweDY2LCAweDFCLCAweDYyLCAweEM0LCAweEM4XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDAzLCAweDA0LCAweDA1XSwgWzB4OUEsIDB4RDcsIDB4NUEsIDB4MjQsIDB4RkQsIDB4M0YsIDB4QkYsIDB4MjJdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDQsIDB4MDUsIDB4MDYsIDB4MDddLCBbMHgxNCwgMHg0RSwgMHg2OCwgMHg2RCwgMHgyRSwgMHhDMSwgMHhCNywgMHg1Ml1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwNSwgMHgwNiwgMHgwNywgMHgwOCwgMHgwOV0sIFsweDEyLCAweDBBLCAweDUxLCAweDA4LCAweEY5LCAweEEzLCAweDAzLCAweDc0XV0sXHJcblx0ICAgICAgICAgICAgICAgICAgW1sweDA2LCAweDA3LCAweDA4LCAweDA5LCAweDBBLCAweDBCXSwgWzB4QjIsIDB4MDcsIDB4RDEsIDB4MDUsIDB4RjYsIDB4NjcsIDB4QUYsIDB4QkFdXSxcclxuXHQgICAgICAgICAgICAgICAgICBbWzB4MDcsIDB4MDgsIDB4MDksIDB4MEEsIDB4MEIsIDB4MEMsIDB4MERdLCBbMHhDQSwgMHg1OSwgMHg2MSwgMHgzQSwgMHg4MywgMHgyMywgMHgyNiwgMHhERF1dLFxyXG5cdCAgICAgICAgICAgICAgICAgIFtbMHgwOCwgMHgwOSwgMHgwQSwgMHgwQiwgMHgwQywgMHgwRCwgMHgwRSwgMHgwRl0sIFsweDgzLCAweDI1LCAweDc5LCAweDA2LCAweDU0LCAweEE0LCAweDQ0LCAweEQ5XV1dO1xyXG5cclxuICAgIHZhciBkZXMgPSBuZXcgb3BlbnBncC5jcnlwdG8uY2lwaGVyLm9yaWdpbmFsRGVzKGtleSk7XHJcblxyXG4gICAgdmFyIHJlcyA9IHRydWU7XHJcbiAgICB2YXIgaiA9IDA7XHJcblxyXG4gICAgZm9yICh2YXIgcGFkZGluZyA9IDA7IHBhZGRpbmcgPCAzOyBwYWRkaW5nKyspIHtcclxuICAgICAgICB2YXIgdGhpc1ZlY3RvclNldCA9IHRlc3R2ZWN0b3JzW3BhZGRpbmddO1xyXG5cclxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXNWZWN0b3JTZXQubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgdmFyIGVuY3J5cHRlZCA9IGRlcy5lbmNyeXB0KHRoaXNWZWN0b3JTZXRbaV1bMF0sIHBhZGRpbmcpO1xyXG4gICAgICAgICAgICB2YXIgZGVjcnlwdGVkID0gZGVzLmRlY3J5cHQoZW5jcnlwdGVkLCBwYWRkaW5nKTtcclxuXHJcbiAgICAgICAgICAgIHZhciByZXMyID0gKHV0aWwuYmluMnN0cihlbmNyeXB0ZWQpID09IHV0aWwuYmluMnN0cih0aGlzVmVjdG9yU2V0W2ldWzFdKSk7XHJcbiAgICAgICAgICAgIHZhciByZXMzID0gKHV0aWwuYmluMnN0cihkZWNyeXB0ZWQpID09IHV0aWwuYmluMnN0cih0aGlzVmVjdG9yU2V0W2ldWzBdKSk7XHJcbiAgICAgICAgICAgIHJlcyAmPSByZXMyO1xyXG4gICAgICAgICAgICByZXMgJj0gcmVzMztcclxuICAgICAgICAgICAgaWYgKCFyZXMyIHx8ICFyZXMzKSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHRbal0gPSBuZXcgdW5pdC5yZXN1bHQoXHJcbiAgICAgICAgICAgICAgICAgICAgXCJUZXN0aW5nIHZlY3RvciB3aXRoIGJsb2NrIFtcIiArXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHV0aWwuaGV4aWR1bXAodGhpc1ZlY3RvclNldFtpXVswXSkgK1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBcIl0gYW5kIGtleSBbXCIgKyB1dGlsLmhleHN0cmR1bXAoa2V5KSArXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiXSBhbmQgcGFkZGluZyBbXCIgKyBwYWRkaW5nICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgXCJdIHNob3VsZCBiZSBcIiArIHV0aWwuaGV4aWR1bXAodGhpc1ZlY3RvclNldFtpXVsxXSkgKyBcIiAtIEFjdHVhbGx5IFtFTkM6XCIgKyB1dGlsLmhleGlkdW1wKGVuY3J5cHRlZCkgKyBcIiwgREVDOlwiICsgdXRpbC5oZXhpZHVtcChkZWNyeXB0ZWQpICsgXCJdXCIsXHJcbiAgICAgICAgICAgICAgICAgICAgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgaisrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHJlcykge1xyXG4gICAgICAgIHJlc3VsdFtqXSA9IG5ldyB1bml0LnJlc3VsdChcIkFsbCBERVMgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZFwiLCB0cnVlKTtcclxuICAgIH1cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbn0pO1xyXG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIlR3b2Zpc2ggdGVzdCB3aXRoIHRlc3QgdmVjdG9ycyBmcm9tIGh0dHA6Ly93d3cuc2NobmVpZXIuY29tL2NvZGUvZWNiX2l2YWwudHh0XCIsIGZ1bmN0aW9uKCkge1xuICB2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLy4uLycpLFxuICAgIHV0aWwgPSBvcGVucGdwLnV0aWw7XG5cbiAgZnVuY3Rpb24gVEZlbmNyeXB0KGJsb2NrLCBrZXkpIHtcbiAgICB2YXIgdGYgPSBuZXcgb3BlbnBncC5jcnlwdG8uY2lwaGVyLnR3b2Zpc2goa2V5KTtcblxuICAgIHJldHVybiB0Zi5lbmNyeXB0KGJsb2NrKTtcbiAgfVxuXG5cbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIgc3RhcnQgPSBbMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwXTtcbiAgdmFyIHN0YXJ0X3Nob3J0ID0gWzAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDAsMCwwLDBdO1xuICB2YXIgdGVzdHZlY3RvcnMgPSBbWzB4NTcsMHhGRiwweDczLDB4OUQsMHg0RCwweEM5LDB4MkMsMHgxQiwweEQ3LDB4RkMsMHgwMSwweDcwLDB4MEMsMHhDOCwweDIxLDB4NkZdLFxuICAgICAgICAgICAgWzB4RDQsMHgzQiwweEI3LDB4NTUsMHg2RSwweEEzLDB4MkUsMHg0NiwweEYyLDB4QTIsMHg4MiwweEI3LDB4RDQsMHg1QiwweDRFLDB4MERdLFxuICAgICAgICAgICAgWzB4OTAsMHhBRiwweEU5LDB4MUIsMHhCMiwweDg4LDB4NTQsMHg0RiwweDJDLDB4MzIsMHhEQywweDIzLDB4OUIsMHgyNiwweDM1LDB4RTZdLFxuICAgICAgICAgICAgWzB4NkMsMHhCNCwweDU2LDB4MUMsMHg0MCwweEJGLDB4MEEsMHg5NywweDA1LDB4OTMsMHgxQywweEI2LDB4RDQsMHgwOCwweEU3LDB4RkFdLFxuICAgICAgICAgICAgWzB4MzAsMHg1OSwweEQ2LDB4RDYsMHgxNywweDUzLDB4QjksMHg1OCwweEQ5LDB4MkYsMHg0NywweDgxLDB4QzgsMHg2NCwweDBFLDB4NThdLFxuICAgICAgICAgICAgWzB4RTYsMHg5NCwweDY1LDB4NzcsMHgwNSwweDA1LDB4RDcsMHhGOCwweDBFLDB4RjYsMHg4QywweEEzLDB4OEEsMHhCMywweEEzLDB4RDZdLFxuICAgICAgICAgICAgWzB4NUEsMHhCNiwweDdBLDB4NUYsMHg4NSwweDM5LDB4QTQsMHhBNSwweEZELDB4OUYsMHgwMywweDczLDB4QkEsMHg0NiwweDM0LDB4NjZdLFxuICAgICAgICAgICAgWzB4REMsMHgwOSwweDZCLDB4Q0QsMHg5OSwweEZDLDB4NzIsMHhGNywweDk5LDB4MzYsMHhENCwweEM3LDB4NDgsMHhFNywweDVBLDB4RjddLFxuICAgICAgICAgICAgWzB4QzUsMHhBMywweEU3LDB4Q0UsMHhFMCwweEYxLDB4QjcsMHgyNiwweDA1LDB4MjgsMHhBNiwweDhGLDB4QjQsMHhFQSwweDA1LDB4RjJdLFxuICAgICAgICAgICAgWzB4NDMsMHhENSwweENFLDB4QzMsMHgyNywweEIyLDB4NEEsMHhCOSwweDBBLDB4RDMsMHg0QSwweDc5LDB4RDAsMHg0NiwweDkxLDB4NTFdXTtcbiAgdGVzdHZlY3RvcnNbNDddID0gIFsweDQzLDB4MTAsMHg1OCwweEY0LDB4REIsMHhDNywweEY3LDB4MzQsMHhEQSwweDRGLDB4MDIsMHhGMCwweDRDLDB4QzQsMHhGNCwweDU5XTtcbiAgdGVzdHZlY3RvcnNbNDhdID0gIFsweDM3LDB4RkUsMHgyNiwweEZGLDB4MUMsMHhGNiwweDYxLDB4NzUsMHhGNSwweERELDB4RjQsMHhDMywweDNCLDB4OTcsMHhBMiwweDA1XTtcbiAgdmFyIHJlcyA9IHRydWU7XG4gIHZhciBqID0gMDtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OTsgaSsrKSB7XG4gICAgdmFyIHJlczIgPSBmYWxzZTtcbiAgICB2YXIgYmxrLCBrZXksIGN0O1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICBibGsgPSBzdGFydF9zaG9ydDtcbiAgICAgIGtleSA9IHV0aWwuYmluMnN0cihzdGFydCk7XG4gICAgICBjdCA9IHRlc3R2ZWN0b3JzWzBdO1xuICAgICAgcmVzMiA9ICh1dGlsLmJpbjJzdHIoVEZlbmNyeXB0KGJsayxrZXkpKSA9PSB1dGlsLmJpbjJzdHIoY3QpKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IDEpIHtcbiAgICAgIGJsayA9IHRlc3R2ZWN0b3JzWzBdO1xuICAgICAga2V5ID0gdXRpbC5iaW4yc3RyKHN0YXJ0KTtcbiAgICAgIGN0ID0gdGVzdHZlY3RvcnNbMV07XG4gICAgICByZXMyID0gKHV0aWwuYmluMnN0cihURmVuY3J5cHQoYmxrLGtleSkpID09IHV0aWwuYmluMnN0cihjdCkpO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gMikge1xuICAgICAgYmxrID0gdGVzdHZlY3RvcnNbaS0xXTtcbiAgICAgIGtleSA9IHV0aWwuYmluMnN0cih0ZXN0dmVjdG9yc1tpLTJdLmNvbmNhdChzdGFydF9zaG9ydCkpO1xuICAgICAgY3QgPSB0ZXN0dmVjdG9yc1tpXTtcbiAgICAgIHJlczIgPSAodXRpbC5iaW4yc3RyKFRGZW5jcnlwdChibGssa2V5KSkgPT0gdXRpbC5iaW4yc3RyKGN0KSk7XG4gICAgfSBlbHNlIGlmIChpIDwgMTAgfHwgaSA+IDQ2KSB7XG4gICAgICBibGsgPSB0ZXN0dmVjdG9yc1tpLTFdO1xuICAgICAga2V5ID0gdXRpbC5iaW4yc3RyKHRlc3R2ZWN0b3JzW2ktMl0uY29uY2F0KHRlc3R2ZWN0b3JzW2ktM10pKTtcbiAgICAgIGN0ID0gdGVzdHZlY3RvcnNbaV07XG4gICAgICByZXMyID0gKHV0aWwuYmluMnN0cihURmVuY3J5cHQoYmxrLGtleSkpID09IHV0aWwuYmluMnN0cihjdCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0ZXN0dmVjdG9yc1tpXSA9IFRGZW5jcnlwdCh0ZXN0dmVjdG9yc1tpLTFdLHV0aWwuYmluMnN0cih0ZXN0dmVjdG9yc1tpLTJdLmNvbmNhdCh0ZXN0dmVjdG9yc1tpLTNdKSkpO1xuICAgICAgcmVzMiA9IHRydWU7XG4gICAgfVxuICAgIHJlcyAmPSByZXMyO1xuICAgIGlmICghcmVzMikge1xuICAgICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyB2ZWN0b3Igd2l0aCBibG9jayBcIit1dGlsLmhleGlkdW1wKGJsaykrXCIgd2l0aCBrZXkgXCIrIHV0aWwuaGV4c3RyZHVtcChrZXkpICtcIiBzaG91bGQgYmUgXCIrdXRpbC5oZXhpZHVtcChjdCkrXCIgYnV0IGlzIFwiK3V0aWwuaGV4aWR1bXAoVEZlbmNyeXB0KGJsayxrZXkpKSwgZmFsc2UpO1xuICAgICAgaisrO1xuICAgIH1cbiAgfVxuICBpZiAocmVzKSB7XG4gICAgcmVzdWx0W2pdID0gbmV3IHVuaXQucmVzdWx0KFwiNDkgdGVzdCB2ZWN0b3JzIGNvbXBsZXRlZFwiLCB0cnVlKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIkZ1bmN0aW9uYWwgdGVzdGluZyBvZiBvcGVucGdwLmNyeXB0by4qIG1ldGhvZHNcIiwgZnVuY3Rpb24oKSB7XG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vJyk7XG4gIHZhciB1dGlsID0gb3BlbnBncC51dGlsO1xuICB2YXIgcmVzdWx0ID0gW107XG4gIHZhciBSU0FwdWJNUElzdHJzID0gW1xuICAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDgsMHgwMCwweGFjLDB4MTUsMHhiMywweGQ2LDB4ZDIsMHgwZiwweGYwLDB4N2EsMHhkZCwweDIxLDB4YjcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhiZiwweDYxLDB4ZmEsMHhjYSwweDkzLDB4ODYsMHhjOCwweDU1LDB4NWEsMHg0YiwweGE2LDB4YTQsMHgxYSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDYwLDB4YTIsMHgzYSwweDM3LDB4MDYsMHgwOCwweGQ4LDB4MTUsMHg4ZSwweDg1LDB4NDUsMHhhYSwweGI3LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MWQsMHg3YiwweDBiLDB4NzMsMHg5NCwweDU1LDB4MGMsMHg1YywweGVjLDB4YzAsMHgyMiwweDRiLDB4YTEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg2NCwweDIwLDB4N2QsMHg0ZCwweGE4LDB4OTYsMHgxYSwweDY0LDB4MzgsMHg5MywweGNkLDB4ZWMsMHg3MyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDVkLDB4ZjksMHg4OSwweDg4LDB4MjQsMHgzZCwweDQ4LDB4ZmYsMHgzYiwweDg3LDB4NjIsMHhkMCwweDg0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZWEsMHhmZiwweDM5LDB4YjUsMHgyNywweDcwLDB4ZWEsMHg0YSwweGIyLDB4MmUsMHg5ZCwweGYxLDB4N2MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgyMywweGVjLDB4ZjQsMHg1ZSwweGVhLDB4NjEsMHgzZCwweGU1LDB4ZDgsMHgwZCwweGY5LDB4NTksMHg2ZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDI4LDB4MDAsMHhlYiwweGNiLDB4YzksMHg1NSwweDAwLDB4NzIsMHgzMCwweDFmLDB4NjUsMHg5ZCwweGQ2LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MTcsMHg1OCwweDVmLDB4YTYsMHg0YSwweGEwLDB4ZGQsMHhlMSwweDc2LDB4ZjIsMHhlZiwweDIxLDB4OWYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg4NCwweGZjLDB4YWEsMHg1YiwweDUyLDB4NmUsMHhjMSwweGEyLDB4YjksMHhiZCwweGI5LDB4ZjQsMHg5ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDQ5LDB4OTIsMHhmMiwweGFmLDB4NTcsMHg4NiwweGYyLDB4ZWYsMHg3MCwweGJmLDB4NTEsMHg0MCwweGZkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YmYsMHg1NiwweDUxLDB4ZTgsMHgyYywweGEyLDB4NGYsMHhmOCwweGE0LDB4ZDcsMHgzNiwweDE4LDB4ODUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhjZSwweDA5LDB4MGQsMHhiYywweDhkLDB4NjUsMHg1ZSwweDhhLDB4MWQsMHg5OCwweGIwLDB4NGQsMHg5ZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGMxLDB4Y2YsMHg4MiwweGUxLDB4YjcsMHg0MywweDVkLDB4NWEsMHg3MiwweGNkLDB4NTUsMHhkMiwweGZmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YjEsMHhiNCwweDc4LDB4YmYsMHhhMSwweDdkLDB4YWMsMHhkOSwweDFiLDB4YzQsMHhmYSwweDM5LDB4MzQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg5MiwweDA5LDB4ZjksMHgwOCwweDJhLDB4NmIsMHg5ZCwweDE0LDB4NTYsMHgxMiwweDRjLDB4ZTksMHhhNixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDI5LDB4YzEsMHhmMywweGE5LDB4MGIsMHhmYywweDMxLDB4NzUsMHg1OCwweDc0LDB4MmEsMHg4OCwweGFmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZWUsMHhjOSwweGE0LDB4Y2QsMHgxNSwweGRjLDB4MWIsMHg4ZCwweDY0LDB4YzEsMHgzNiwweDE3LDB4YzQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg4ZCwweDVlLDB4OTksMHg3YSwweDViLDB4OWYsMHgzOSwweGQwLDB4MDAsMHg2ZSwweGY5XSksXG4gICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwMCwweDExLDB4MDEsMHgwMCwweDAxXSldO1xuICB2YXIgUlNBc2VjTVBJc3RycyA9IFtcbiAgICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDA3LDB4ZmUsMHgyMywweGZmLDB4Y2UsMHg0NSwweDZjLDB4NjAsMHg2NSwweDQwLDB4NmUsMHhhZSwweDM1LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MTAsMHg1NiwweDYwLDB4ZWUsMHhhYiwweGZhLDB4MTAsMHg0MiwweGJhLDB4YzcsMHgwNCwweGFmLDB4NjMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhjZCwweDNmLDB4NjIsMHhjYSwweDRiLDB4ZmEsMHhlMSwweGE5LDB4NzAsMHhjZCwweDM0LDB4OGIsMHhjOCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDBlLDB4ZTQsMHhjNCwweGJhLDB4ODMsMHgxNywweDVmLDB4YTQsMHhiOCwweGVhLDB4NjAsMHhjMiwweDRkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4OWEsMHhmMiwweGE5LDB4MDMsMHhlYiwweGY2LDB4YWEsMHhjMiwweGI4LDB4OGIsMHg0MywweDEyLDB4ZTksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhmNywweDg4LDB4ZDIsMHg1YSwweGE2LDB4YWEsMHgyMywweDcxLDB4MzEsMHg3NCwweGRiLDB4MTksMHgyMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDE1LDB4NDEsMHgxYiwweDQzLDB4NjgsMHg2MiwweGQ4LDB4YzAsMHg5MywweDkxLDB4ZTgsMHhmYywweGIxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4YTksMHg5YSwweDUyLDB4NmMsMHhlMCwweGJmLDB4NDMsMHgwMSwweGE4LDB4MzcsMHgxNCwweDI4LDB4YmYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwYiwweDE1LDB4NTYsMHgzZSwweGE1LDB4NzksMHhhMCwweGM0LDB4NDIsMHg4OCwweGVlLDB4ZWIsMHgxYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGY0LDB4N2EsMHg0YSwweDU4LDB4MzEsMHg1OCwweDgxLDB4ZDIsMHgzZSwweGRlLDB4MDcsMHg2NCwweDkyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZjAsMHg2MCwweGQzLDB4OWEsMHgyOSwweGNhLDB4YzYsMHg2NywweDc1LDB4MDcsMHhjYSwweDkyLDB4MzksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg1NiwweGY2LDB4MTEsMHg4NCwweGJhLDB4NmQsMHg0YiwweGU2LDB4NmYsMHg2NiwweGMyLDB4MTcsMHhlYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDQ2LDB4NjksMHgxYywweGJiLDB4ZGYsMHhjMCwweDM4LDB4MDAsMHhkNiwweDAxLDB4ZTYsMHg3MCwweDlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NGIsMHg5YiwweDcwLDB4ZWQsMHg1YywweGI4LDB4Y2YsMHhlOCwweDY4LDB4NzEsMHhiZSwweDI0LDB4NmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhiMSwweGEzLDB4MTMsMHhjYywweGYxLDB4YmMsMHg2NywweGRjLDB4ZTAsMHg2OSwweDA5LDB4ODIsMHgzYyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDNiLDB4MGYsMHgxNCwweDk4LDB4NDgsMHgzMCwweGIyLDB4NzAsMHhjNiwweDllLDB4ZmEsMHg0NiwweDhmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZjEsMHhjMCwweDY1LDB4OGUsMHhjNiwweGFlLDB4ZGMsMHg0NywweDkxLDB4MTMsMHgxZSwweGQ2LDB4NGEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhmMiwweGFkLDB4ZGEsMHhjMiwweGM3LDB4MzksMHg3OCwweDk5LDB4ZGUsMHg1NywweDE0LDB4NDUsMHg3ZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDMyLDB4MzgsMHhhMywweDQ0LDB4MGYsMHhlNywweDM5LDB4NGMsMHg2ZiwweDBmLDB4MzIsMHg3ZSwweGYxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NWMsMHg4NCwweDk3LDB4ZGQsMHhhMCwweDBjLDB4ODcsMHg2NiwweDdkLDB4NzUsMHg3OV0pLFxuICAgICAgICAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDQsMHgwMCwweGMyLDB4YmMsMHg3MSwweGY3LDB4NDEsMHg0YSwweDA5LDB4NjYsMHg3MCwweDAyLDB4NjgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg4YiwweGViLDB4ZTIsMHgzNCwweGQxLDB4MTIsMHg4MywweDkzLDB4NzUsMHhlOSwweDcxLDB4MzIsMHhlMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweGVkLDB4MTgsMHg2ZiwweDhlLDB4M2EsMHhmZiwweDIyLDB4NzAsMHgyOCwweDAxLDB4YmYsMHg0YSwweDM5LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NDEsMHhiYiwweDNjLDB4NGEsMHhiYywweGI4LDB4MTMsMHhmYywweDE0LDB4ZjYsMHg3MSwweGExLDB4NDQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgxYywweDAyLDB4YTEsMHg3MywweDgxLDB4Y2MsMHhhMCwweDM1LDB4MDIsMHgzZSwweDk3LDB4YjUsMHhjNCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDk0LDB4MzMsMHhmMSwweGQxLDB4ZGYsMHgxNCwweDNmLDB4ZmIsMHg4ZiwweGI5LDB4NzUsMHg3MCwweGRjLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NzQsMHgzZiwweDA3LDB4MzUsMHg4ZiwweDUzLDB4YWEsMHhiMiwweGQ2LDB4ODgsMHg1MSwweDcxLDB4NGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwMSwweDI0LDB4ZWMsMHg3ZCwweGNhLDB4ZjYsMHhhMiwweGIzLDB4YmIsMHhhZCwweDJlLDB4NjAsMHhmYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDFjLDB4ZWUsMHg0OSwweGQwLDB4NGUsMHg1YywweGUzLDB4MWYsMHg4OCwweDQ4LDB4ZTQsMHg2OCwweDE0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4M2QsMHg3MSwweGJhLDB4ZDcsMHg0ZCwweDM1LDB4MTAsMHg4NiwweDM3LDB4NjIsMHhlMCwweGE1LDB4MGJdKSxcbiAgICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDA0LDB4MDAsMHhlMiwweDM4LDB4ZjksMHhjOCwweDNjLDB4ZDEsMHhjZiwweDYyLDB4OTMsMHhjMywweDc3LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NzYsMHg5NywweDQ0LDB4ZTgsMHhjOCwweGNhLDB4OTMsMHg5YSwweGVmLDB4ZjAsMHg2MywweDc2LDB4MjUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgzYiwweDFjLDB4NDYsMHhmZiwweDkwLDB4MTMsMHg5MSwweDE1LDB4OTcsMHg3ZSwweDg4LDB4OTUsMHhkNCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDdmLDB4MmYsMHg1MiwweDZlLDB4MGQsMHg1NSwweDU1LDB4MmUsMHhmMSwweDU4LDB4NWMsMHg3ZSwweDU2LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZDQsMHg0OCwweGFhLDB4ZGIsMHg4YywweDQ0LDB4NGQsMHg4NCwweDY5LDB4MzMsMHg4NywweDA3LDB4YjIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg3ZSwweGY1LDB4YTAsMHg2MCwweGZiLDB4NzMsMHg1OSwweDQ2LDB4MjksMHhjYiwweDFlLDB4M2YsMHg3YyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDJmLDB4YTYsMHg1MywweGUzLDB4OGMsMHhlZiwweGQ1LDB4ZWIsMHhiYiwweGM4LDB4OWEsMHg4ZSwweDY2LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NGEsMHg0NywweDJmLDB4ZTEsMHhiYSwweDVlLDB4MzIsMHhkNCwweDUyLDB4MDQsMHg4OCwweDlkLDB4NjMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgzZSwweGJhLDB4NzEsMHgyZCwweGY3LDB4NjEsMHhkNSwweGZjLDB4MjYsMHhiZiwweGQ4LDB4NjAsMHg5MixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDdiLDB4OTQsMHhmOCwweDZmLDB4M2QsMHg5NywweDBiLDB4MGMsMHg1MiwweDhjLDB4YjMsMHhiNiwweDhiXSksXG4gICAgICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwNCwweDAwLDB4YjcsMHhjNSwweDRkLDB4NmUsMHgyZiwweGRkLDB4ZWYsMHhlYywweDA3LDB4NzAsMHhhMixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDdjLDB4MWMsMHg5ZCwweDhlLDB4NjYsMHg2MCwweDdjLDB4NjEsMHgxZSwweDQ1LDB4ZTksMHhkYywweDgyLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MmYsMHhjNSwweDdlLDB4MWEsMHhjNiwweGQwLDB4OTIsMHhjNSwweDIyLDB4OWIsMHg5YSwweGZiLDB4NzMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHg5NSwweDk5LDB4ZjIsMHg3YywweGRiLDB4MmEsMHg5MywweDdiLDB4NWEsMHgyOSwweDczLDB4MjQsMHgxNixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDQxLDB4NDksMHhiNSwweGYyLDB4NWYsMHhiZSwweGU3LDB4NjQsMHg0ZCwweGRhLDB4NTIsMHg5ZSwweGMxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4NDEsMHg0MCwweDVlLDB4MDMsMHg5MiwweDhkLDB4MzksMHg5NSwweDFmLDB4NjgsMHg5ZiwweDAwLDB4MmUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHgwYywweDZmLDB4Y2YsMHhkOSwweDZkLDB4NjgsMHhmNywweDAwLDB4NGYsMHgwZSwweGM4LDB4MGIsMHhmYSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAweDUxLDB4ZTAsMHgyMiwweGYwLDB4ZmYsMHhhNywweDQyLDB4ZDQsMHhkZSwweDBiLDB4NDcsMHg4ZiwweDJiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4ZjUsMHg0ZCwweDA0LDB4MzIsMHg5MSwweDg5LDB4NGIsMHgwZSwweDA1LDB4OGQsMHg3MCwweGY5LDB4YmIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMHhlNywweGQ2LDB4NzYsMHhlYSwweDBlLDB4MWEsMHg5MCwweDMwLDB4ZjUsMHg5OCwweDAxLDB4YzUsMHg3M10pXTtcbiAgXG4gIHZhciBEU0FwdWJNUElzdHJzID0gW1xuICAgICAgICAgIHV0aWwuYmluMnN0cihbMHgwOCwweDAwLDB4YTgsMHg4NSwweDVjLDB4MjgsMHgwNSwweDk0LDB4MDMsMHhiZSwweDA3LDB4NmMsMHgxMywweDNlLDB4NjUsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGZiLDB4YjUsMHhlMSwweDk5LDB4N2MsMHhmYSwweDg0LDB4ZTMsMHhhYywweDQ3LDB4YTUsMHhjNCwweDQ2LDB4ZDgsMHg1ZixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4NDQsMHhlOSwweGMxLDB4NmIsMHg2OSwweGY3LDB4MTAsMHg3NiwweDQ5LDB4YTcsMHgyNSwweDg1LDB4ZjQsMHgxYiwweGVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhjNiwweDYwLDB4YzQsMHg1YiwweGFhLDB4ZDQsMHg4NywweGQ2LDB4OGYsMHg5MiwweDU2LDB4N2QsMHg1NSwweDNmLDB4NDUsXG4gICAgICAgICAgICAgICAgICAgICAgICAweGFlLDB4MTIsMHg3MywweGRhLDB4MjksMHg4YywweGJhLDB4MzIsMHhjYywweGQ3LDB4YTQsMHhkMCwweDI0LDB4YjAsMHg3YyxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4ZDgsMHgwYywweDNhLDB4OTEsMHg2ZiwweDk4LDB4NDAsMHg5YywweDlhLDB4YTgsMHhjYywweDI4LDB4MjcsMHg5NSwweDBiLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHhlMSwweDViLDB4YjksMHgzYiwweDFjLDB4MWMsMHhkMiwweGVjLDB4YWIsMHgwNywweDI1LDB4OGQsMHg3YSwweDJhLDB4MmIsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDE2LDB4MTQsMHhlOCwweGRhLDB4NzEsMHhkMiwweGFiLDB4YmEsMHg4NSwweDE0LDB4MGQsMHhjNSwweGUwLDB4ODgsMHhlYixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4YTUsMHhlMiwweGQ1LDB4NDgsMHgzZCwweDc0LDB4MGMsMHg0MSwweGViLDB4ZmQsMHhiNiwweDRlLDB4ZjksMHgyYywweDgyLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHgxNywweGRkLDB4NjQsMHgxZSwweDE5LDB4MzksMHhhMywweDdmLDB4ZjksMHgwMCwweGNkLDB4OWIsMHhkYSwweDJlLDB4YmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDcxLDB4MTIsMHhkZiwweDBkLDB4N2MsMHgwYSwweDZiLDB4MmQsMHgyMSwweDNiLDB4OWMsMHg2NiwweDkzLDB4NGEsMHgxZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4OTAsMHg3OSwweGQzLDB4NWEsMHg1YiwweGU1LDB4YjksMHg5NCwweDFiLDB4ZTYsMHg0NywweDk5LDB4MDYsMHg5OCwweGQ4LFxuICAgICAgICAgICAgICAgICAgICAgICAgMHgyYSwweGU1LDB4ZTIsMHhhNiwweDk1LDB4NmEsMHgwNywweGM4LDB4YWMsMHg3YywweGU5LDB4ZmMsMHhhMiwweDZhLDB4MTYsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDJjLDB4OTQsMHg5OCwweGJkLDB4OTEsMHgwYSwweDdjLDB4N2MsMHgyYywweGI5LDB4N2UsMHhhMiwweDUxLDB4OGIsMHg0NSxcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4MWQsMHg0NiwweDM0LDB4YTgsMHg1MiwweDJiLDB4ZGQsMHhkOSwweGE4LDB4YmMsMHg0NiwweDc4LDB4NjYsMHhlMSwweDcyLFxuICAgICAgICAgICAgICAgICAgICAgICAgMHgxMSwweGYxLDB4Y2IsMHgxYSwweGI2LDB4NGUsMHgwNSwweDU0LDB4ZjcsMHhlOSwweGJlLDB4NGMsMHgyNSwweDU5LDB4MDgsXG4gICAgICAgICAgICAgICAgICAgICAgICAweDlmLDB4ZjgsMHhlYSwweDI1LDB4OTcsMHgzMywweGQ2LDB4YzksMHgwZiwweDU5LDB4MGUsMHhmZCwweDlmLDB4ZGMsMHhlMixcbiAgICAgICAgICAgICAgICAgICAgICAgIDB4YzAsMHhjZiwweDJmXSksXG4gICAgICB1dGlsLmJpbjJzdHIoWzB4MDEsMHgwMCwweGUxLDB4NzIsMHgyYywweGQwLDB4YmIsMHgxYSwweDRmLDB4YjYsMHhiNiwweDk1LDB4NzcsMHg3MSwweDJlLFxuICAgICAgICAgICAgICAgICAgICAweDAxLDB4NDgsMHgzZSwweDM1LDB4NTQsMHg2NCwweDJiLDB4ZWQsMHg0MCwweDVmLDB4NjUsMHgwYywweDU3LDB4MjgsMHg1ZixcbiAgICAgICAgICAgICAgICAgICAgMHhmZCwweGZkLDB4ZmYsMHhkN10pLFxuICAgICAgdXRpbC5iaW4yc3RyKFsweDA3LDB4ZmYsMHg1ZCwweDlmLDB4YzQsMHhiNSwweDYzLDB4MjUsMHg5ZCwweDcyLDB4ODgsMHhlNSwweDUzLDB4NDYsMHg5OCxcbiAgICAgICAgICAgICAgICAgICAgMHhlMywweGU5LDB4NjIsMHhjYiwweDBjLDB4YTEsMHhiNywweDc1LDB4OWYsMHgxOCwweDQxLDB4OTQsMHgzMiwweDI4LDB4MjksXG4gICAgICAgICAgICAgICAgICAgIDB4NmQsMHg2OSwweGUwLDB4M2YsMHg3ZCwweDdiLDB4MmIsMHgwNiwweDVhLDB4MzMsMHg1YywweGQ0LDB4MzYsMHgzMSwweDA5LFxuICAgICAgICAgICAgICAgICAgICAweDU0LDB4ODUsMHg5ZCwweGI4LDB4MjAsMHhmZSwweGRhLDB4ZmMsMHhjZCwweDFmLDB4YjEsMHgyYywweDE1LDB4MDgsMHg5ZCxcbiAgICAgICAgICAgICAgICAgICAgMHgzMiwweDUzLDB4MmYsMHhjMSwweDQyLDB4MjIsMHg2OSwweGZmLDB4NjcsMHgyZSwweDM5LDB4OTcsMHg1MCwweDY2LDB4MzksXG4gICAgICAgICAgICAgICAgICAgIDB4ZGEsMHhjZiwweGZkLDB4NjQsMHg2ZiwweDkxLDB4MDUsMHg2NCwweDM3LDB4YzUsMHgwNywweDI0LDB4YWEsMHg0MCwweGEwLFxuICAgICAgICAgICAgICAgICAgICAweDc1LDB4ODIsMHgxZCwweDk3LDB4OTYsMHgxMiwweGYxLDB4YmQsMHg5ZSwweDA5LDB4MjYsMHgzYywweDk3LDB4NWQsMHg1NyxcbiAgICAgICAgICAgICAgICAgICAgMHhiOCwweDVjLDB4N2QsMHg4OSwweDAzLDB4ODIsMHhjZCwweDQwLDB4ZTUsMHgwMywweGU2LDB4NGEsMHhmYiwweGJjLDB4ZDIsXG4gICAgICAgICAgICAgICAgICAgIDB4ZWYsMHg3YSwweDg5LDB4MDIsMHgwOCwweGM4LDB4NTIsMHhmYSwweDk3LDB4NzQsMHg2NiwweDMyLDB4YWUsMHhhNiwweDUyLFxuICAgICAgICAgICAgICAgICAgICAweDRiLDB4ZWYsMHg1ZiwweGNlLDB4OTEsMHgyMywweDNmLDB4YWIsMHg5ZCwweDYyLDB4MjEsMHhlZiwweDQ4LDB4NmQsMHgwNyxcbiAgICAgICAgICAgICAgICAgICAgMHg1YSwweGJhLDB4ZGYsMHgwMCwweDkxLDB4NTQsMHhlYSwweDVjLDB4ZmEsMHg0YiwweDE2LDB4MjgsMHgxYSwweGNlLDB4NDgsXG4gICAgICAgICAgICAgICAgICAgIDB4YjcsMHg1YywweDUwLDB4YTUsMHg1OSwweGE0LDB4YjQsMHhhZiwweDFmLDB4ZWIsMHg4ZCwweDU4LDB4M2YsMHgwYSwweGE1LFxuICAgICAgICAgICAgICAgICAgICAweDk3LDB4MmIsMHg1MSwweDU2LDB4ZTgsMHg4OCwweGY2LDB4MDcsMHhiYywweGRmLDB4ZmEsMHgyYiwweDdiLDB4ODgsMHhlMCxcbiAgICAgICAgICAgICAgICAgICAgMHg0NiwweGM4LDB4N2EsMHgzZSwweGQ4LDB4ODAsMHhkYiwweDRkLDB4ODcsMHg2MSwweDRmLDB4NjQsMHhjZCwweGViLDB4ZTgsXG4gICAgICAgICAgICAgICAgICAgIDB4MGQsMHg4NiwweDE2LDB4Y2MsMHhkZCwweDZjLDB4NzYsMHg2NiwweGMxLDB4NzMsMHhiNywweDA4LDB4OTgsMHg4OSwweDJmLFxuICAgICAgICAgICAgICAgICAgICAweDY3LDB4NjksMHhkMSwweGZjLDB4OTcsMHg0ZCwweGEyLDB4Y2UsMHhhZCwweGJiLDB4NmYsMHhhYiwweGE1LDB4ZDYsMHgxOCxcbiAgICAgICAgICAgICAgICAgICAgMHhiMywweDFhLDB4OTYsMHgwMiwweGJjLDB4MzEsMHg0MiwweGEyLDB4YWQsMHg3NywweGU4LDB4ZTIsMHg0YywweDk5LDB4ZjksXG4gICAgICAgICAgICAgICAgICAgIDB4ZGQsMHhiZSwweGNkXSksXG4gICAgICB1dGlsLmJpbjJzdHIoWzB4MDcsMHhmZiwweDVkLDB4ZmUsMHg5YywweDk4LDB4ZWYsMHgzYSwweGE2LDB4NDksMHhmMCwweDEwLDB4NjcsMHg3OSwweDJhLFxuICAgICAgICAgICAgICAgICAgICAweDlkLDB4NzksMHg0MywweDA2LDB4YTQsMHhhOCwweDZiLDB4MWEsMHg2ZCwweDFmLDB4NzcsMHg2ZSwweDAwLDB4MzEsMHhiOSxcbiAgICAgICAgICAgICAgICAgICAgMHhlZCwweGM5LDB4NjYsMHhmZiwweGYxLDB4MjEsMHgzMiwweGZhLDB4NjIsMHg0MywweGNkLDB4OTcsMHhkMywweDNkLDB4YWYsXG4gICAgICAgICAgICAgICAgICAgIDB4YjQsMHgyOSwweDI5LDB4MjYsMHg0ZSwweDFjLDB4YTAsMHhhZCwweDFjLDB4MDcsMHgyOCwweDNmLDB4ZTUsMHg0MywweDEwLFxuICAgICAgICAgICAgICAgICAgICAweGJhLDB4YjQsMHgwOCwweGUwLDB4ZGMsMHhhMiwweGMzLDB4NWIsMHgxZiwweGJkLDB4OTQsMHhjNywweDQzLDB4ZTUsMHhmMixcbiAgICAgICAgICAgICAgICAgICAgMHgxNywweDMwLDB4NTQsMHg3ZiwweDE0LDB4YmUsMHhmNCwweGJkLDB4OTEsMHgzYiwweGU0LDB4MzYsMHhhNCwweDUwLDB4NWIsXG4gICAgICAgICAgICAgICAgICAgIDB4MzcsMHg4OSwweDVlLDB4Y2MsMHhjNywweDc0LDB4NTQsMHgzMiwweDIwLDB4MDksMHg2MywweDk4LDB4YjcsMHhkOSwweGFmLFxuICAgICAgICAgICAgICAgICAgICAweDdmLDB4YjAsMHg2YywweDI3LDB4NDMsMHhmZSwweDUyLDB4ZTYsMHgxYSwweDg4LDB4NTksMHgyNSwweGZjLDB4ZWIsMHg0MyxcbiAgICAgICAgICAgICAgICAgICAgMHg1MCwweGM3LDB4NjUsMHg0MywweGMxLDB4ODYsMHg3MywweDU4LDB4NTMsMHgzYSwweGNmLDB4N2EsMHhhMywweDFkLDB4NTYsXG4gICAgICAgICAgICAgICAgICAgIDB4YzgsMHg0YSwweDgwLDB4NzAsMHhiNywweGJmLDB4ZjIsMHhhMywweGVjLDB4ZTgsMHg3NywweDA1LDB4MzMsMHgwOSwweDlkLFxuICAgICAgICAgICAgICAgICAgICAweGFhLDB4Y2EsMHhhMCwweGUxLDB4NjQsMHg2NCwweDZmLDB4NzYsMHg5OSwweDQxLDB4NzUsMHg3OCwweDkwLDB4ZjYsMHhlNyxcbiAgICAgICAgICAgICAgICAgICAgMHgyMywweGU2LDB4ZWMsMHg1MCwweGU1LDB4OTksMHhhOCwweDNlLDB4MWEsMHg0YiwweGM5LDB4ODgsMHg1OCwweDY2LDB4YWUsXG4gICAgICAgICAgICAgICAgICAgIDB4MWEsMHg1MywweDVlLDB4ZTQsMHhiNywweDg2LDB4Y2YsMHhhNiwweGU1LDB4YWQsMHhiNCwweDgwLDB4YTAsMHhmMSwweDBkLFxuICAgICAgICAgICAgICAgICAgICAweDk2LDB4YjgsMHg0MSwweGQwLDB4MDcsMHg5YSwweDIxLDB4OGQsMHg1MCwweDdmLDB4NGYsMHg3MywweDEzLDB4YTIsMHhlMixcbiAgICAgICAgICAgICAgICAgICAgMHgwMiwweDA3LDB4YzMsMHhhMywweDBmLDB4MDksMHgxOCwweDdmLDB4ZjcsMHg2YiwweDkwLDB4NzAsMHhjMCwweGY5LDB4MGMsXG4gICAgICAgICAgICAgICAgICAgIDB4NjcsMHg4ZCwweDlkLDB4MTQsMHhiNiwweDlkLDB4MzIsMHg4MiwweGQwLDB4YjUsMHhjNiwweDU3LDB4ZjAsMHg5MSwweGQ5LFxuICAgICAgICAgICAgICAgICAgICAweGMzLDB4MjYsMHhhZSwweDlmLDB4YTksMHg2NywweDQ5LDB4OTYsMHg1YywweDA3LDB4M2UsMHg0NywweDVjLDB4ZWQsMHg2MCxcbiAgICAgICAgICAgICAgICAgICAgMHgwNywweGFjLDB4NmFdKV07XG4gIHZhciBEU0FzZWNNUElzdHJzID0gW3V0aWwuYmluMnN0cihbMHgwMSwweDAwLDB4OWIsMHg1OCwweGE4LDB4ZjQsMHgwNCwweGIxLDB4ZDUsMHgxNCwweDA5LDB4ZTEsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAweGUxLDB4YTEsMHg4YSwweDBiLDB4YTMsMHhjMywweGEzLDB4NjYsMHhhYSwweDI3LDB4OTksMHg1MCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIDB4MWMsMHg0ZCwweGJhLDB4MjQsMHhlZSwweGRmLDB4ZGYsMHhiOCwweDhlLDB4OGVdKV07XG4gICAgICAgICAgICBcbiAgdmFyIEVsZ2FtYWxwdWJNUElzdHJzID0gXG4gICAgICAgICAgW3V0aWwuYmluMnN0cihbMHgwOCwweDAwLDB4ZWEsMHhjYywweGJlLDB4ZTIsMHhlNCwweDVhLDB4NTEsMHgxOCwweDkzLDB4YTEsMHgxMiwweDJmLFxuICAgICAgICAgICAgICAgICAgICAgMHgwMCwweDk5LDB4NDIsMHhkOCwweDVjLDB4MWMsMHgyZiwweGI2LDB4M2MsMHhkOSwweDk0LDB4NjEsMHhiNCwweDU1LFxuICAgICAgICAgICAgICAgICAgICAgMHg4ZCwweDRlLDB4NzMsMHhlNiwweDY5LDB4YmMsMHgxZCwweDMzLDB4ZTMsMHgyZCwweDkxLDB4MjMsMHg2OSwweDk1LFxuICAgICAgICAgICAgICAgICAgICAgMHg5OCwweGQ3LDB4MTgsMHg1YSwweGFmLDB4YTcsMHg5MywweGM2LDB4MDUsMHg5MywweDNhLDB4YzcsMHhlYSwweGQwLFxuICAgICAgICAgICAgICAgICAgICAgMHhiMSwweGE5LDB4YzcsMHhhYiwweDQxLDB4ODksMHhjOCwweDM4LDB4OTksMHhkYywweDFhLDB4NTcsMHgzNSwweDFhLFxuICAgICAgICAgICAgICAgICAgICAgMHgyNywweDYyLDB4NDAsMHg3MSwweDlmLDB4MzYsMHgxYywweDZkLDB4MTgsMHgxYywweDkzLDB4ZjcsMHhiYSwweDM1LFxuICAgICAgICAgICAgICAgICAgICAgMHgwNiwweGVkLDB4MzAsMHhiOCwweGQ5LDB4OGEsMHg3YywweDAzLDB4YWYsMHhiYSwweDQwLDB4MWYsMHg2MiwweGYxLFxuICAgICAgICAgICAgICAgICAgICAgMHg2ZCwweDg3LDB4MmMsMHhhNiwweDJlLDB4NDYsMHhiMCwweGFhLDB4YmMsMHhiYywweDkzLDB4ZmEsMHg5YiwweDQ3LFxuICAgICAgICAgICAgICAgICAgICAgMHgzZiwweDcwLDB4MWYsMHgyYSwweGMyLDB4NjYsMHg5YywweDdjLDB4NjksMHhlMCwweDJiLDB4MDUsMHhlZSwweGI3LFxuICAgICAgICAgICAgICAgICAgICAgMHhhNywweDdmLDB4ZjMsMHgyMSwweDQ4LDB4ODUsMHhjMiwweDk1LDB4NWYsMHg2ZiwweDFlLDB4YjMsMHg5YiwweDk3LFxuICAgICAgICAgICAgICAgICAgICAgMHhmOCwweDE0LDB4YzMsMHhmZiwweDRkLDB4OTcsMHgyNSwweDI5LDB4OTQsMHg0MSwweDRiLDB4OTAsMHhkOCwweGJhLFxuICAgICAgICAgICAgICAgICAgICAgMHg3MSwweDQ1LDB4NGIsMHgxZSwweDJmLDB4Y2EsMHg4MiwweDVmLDB4NTYsMHg3NywweGU5LDB4ZDMsMHg4OCwweDVkLFxuICAgICAgICAgICAgICAgICAgICAgMHg4YiwweGVjLDB4OTIsMHg4YiwweDhhLDB4MjMsMHg4OCwweDA1LDB4ZjgsMHgyYywweGE4LDB4ZjEsMHg3MCwweDc2LFxuICAgICAgICAgICAgICAgICAgICAgMHhlNywweGJmLDB4NzUsMHhhOCwweDMxLDB4MTQsMHg4ZSwweDc2LDB4YzgsMHgwMSwweGE2LDB4MjUsMHgyNywweDQ5LFxuICAgICAgICAgICAgICAgICAgICAgMHhhZiwweGRjLDB4ZjQsMHhmNiwweGY0LDB4Y2UsMHg5MCwweDg0LDB4MTUsMHgyYiwweDRkLDB4YjMsMHhjYywweDc3LFxuICAgICAgICAgICAgICAgICAgICAgMHhkYiwweDY1LDB4NzEsMHg3NSwweGQzLDB4MDAsMHgxZCwweDIyLDB4YzUsMHg0MiwweDJmLDB4NTEsMHhmYSwweDdiLFxuICAgICAgICAgICAgICAgICAgICAgMHhlYiwweDZlLDB4MDMsMHhkOSwweDQxLDB4ZGQsMHgyZCwweDFhLDB4ZGQsMHgwNywweDc0LDB4OGIsMHhiNywweGEyLFxuICAgICAgICAgICAgICAgICAgICAgMHhmYSwweGIyLDB4NTksMHgwZSwweDBlLDB4OTQsMHg3YywweDAwLDB4YWQsMHg5NSwweDIzLDB4NDIsMHg5MSwweDE4LFxuICAgICAgICAgICAgICAgICAgICAgMHg0YywweDk3LDB4ZjEsMHgyNywweDYyLDB4NzddKSxcbiAgICAgICB1dGlsLmJpbjJzdHIoWzB4MDAsMHgwMywweDA1XSksXG4gICAgICAgdXRpbC5iaW4yc3RyKFsweDA3LDB4ZmYsMHg1NywweDE5LDB4NzYsMHhmYywweDA5LDB4NmEsMHg3YSwweGY3LDB4YmEsMHhiMiwweDQyLDB4YmYsXG4gICAgICAgICAgICAgICAgICAgICAweGNkLDB4MmIsMHhjMSwweDFhLDB4NzksMHgyNSwweDhjLDB4YWQsMHhmNCwweDNhLDB4MGEsMHg3YSwweDliLDB4NGMsXG4gICAgICAgICAgICAgICAgICAgICAweDQ2LDB4M2MsMHhlMCwweDRmLDB4Y2MsMHg2ZSwweGU1LDB4N2EsMHgzMywweDNhLDB4NGUsMHg4MCwweGNiLDB4ZDMsXG4gICAgICAgICAgICAgICAgICAgICAweDYyLDB4ZDcsMHg4ZiwweGUyLDB4YzgsMHhiMCwweGQwLDB4Y2IsMHg0OSwweGM5LDB4OWUsMHgyZCwweDk3LDB4MTYsXG4gICAgICAgICAgICAgICAgICAgICAweDNhLDB4N2QsMHhiMSwweGUxLDB4ZDMsMHhkOSwweGQ3LDB4M2YsMHgyMCwweDYwLDB4ZTMsMHgzZSwweDc3LDB4ZWEsXG4gICAgICAgICAgICAgICAgICAgICAweDBjLDB4ZTQsMHg3YiwweGYwLDB4MzksMHgxYSwweDBkLDB4ZDksMHg4ZiwweDczLDB4ZDIsMHg1MSwweGI4LDB4MGMsXG4gICAgICAgICAgICAgICAgICAgICAweDBlLDB4MTUsMHgxZSwweGFkLDB4N2MsMHhkOCwweDlkLDB4NzQsMHg2ZSwweGEyLDB4MTcsMHg2YiwweDU4LDB4MTQsXG4gICAgICAgICAgICAgICAgICAgICAweDJiLDB4YjcsMHhhZCwweDhhLDB4ZDcsMHg2NiwweGMwLDB4ZGYsMHhlYSwweDJkLDB4ZmMsMHhjNCwweDZlLDB4NjgsXG4gICAgICAgICAgICAgICAgICAgICAweGI2LDB4NGMsMHg5YSwweDE2LDB4YTQsMHgzZCwweGMyLDB4MjYsMHgwYywweGI3LDB4ZDQsMHgxMywweDdiLDB4MjIsXG4gICAgICAgICAgICAgICAgICAgICAweGZkLDB4ODQsMHhkNywweDBmLDB4ZGMsMHg0MiwweDc1LDB4MDUsMHg4NSwweDI5LDB4MDAsMHgzMSwweDFkLDB4ZWMsXG4gICAgICAgICAgICAgICAgICAgICAweDRlLDB4MjIsMHg4YiwweGY2LDB4MzcsMHg4MywweDQ1LDB4ZTUsMHhiMywweDMxLDB4NjEsMHgyYywweDAyLDB4YTEsXG4gICAgICAgICAgICAgICAgICAgICAweGM2LDB4OWQsMHhlYSwweGJhLDB4M2QsMHg4YSwweGFiLDB4MGYsMHg2MSwweDVlLDB4MTQsMHg2NCwweDY5LDB4MWUsXG4gICAgICAgICAgICAgICAgICAgICAweGEwLDB4MTUsMHg0OCwweDg2LDB4ZTUsMHgxMSwweDA2LDB4ZTgsMHhkZSwweDM0LDB4YzcsMHhhNywweDNkLDB4MzUsXG4gICAgICAgICAgICAgICAgICAgICAweGQxLDB4NzYsMHhjMiwweGJlLDB4MDEsMHg4MiwweDYxLDB4OGQsMHhlNywweDdlLDB4MjgsMHgxZCwweDRlLDB4OGMsXG4gICAgICAgICAgICAgICAgICAgICAweGI5LDB4ZTgsMHg3ZSwweGE0LDB4NWYsMHhhNiwweDNhLDB4OWUsMHg1ZCwweGFjLDB4ZjMsMHg2MCwweDIyLDB4MTQsXG4gICAgICAgICAgICAgICAgICAgICAweGQ1LDB4ZDUsMHhiZSwweDFmLDB4ZjAsMHgxOSwweGU2LDB4ODEsMHhmZCwweDVkLDB4ZTEsMHhmOCwweDc2LDB4NWYsXG4gICAgICAgICAgICAgICAgICAgICAweGUzLDB4ZGEsMHhiYSwweDE5LDB4ZjMsMHhjYiwweDEwLDB4YTAsMHg2YiwweGQwLDB4MmQsMHhiZSwweDQwLDB4NDIsXG4gICAgICAgICAgICAgICAgICAgICAweDdiLDB4OWIsMHgxNSwweGE0LDB4MmQsMHhlYywweGNmLDB4MDksMHhkNiwweGUzLDB4OTIsMHhjMywweDhkLDB4NjUsXG4gICAgICAgICAgICAgICAgICAgICAweDZiLDB4NjAsMHg5NywweGRhLDB4NmIsMHhjYV0pXTtcblxuICB2YXIgRWxnYW1hbHNlY01QSXN0cnMgPSBbXG4gICAgICAgICAgICAgdXRpbC5iaW4yc3RyKFsweDAxLDB4NTIsMHgwMiwweDgwLDB4ODcsMHhmNiwweGU0LDB4NDksMHhkNywweDJlLDB4M2UsMHhmZSwweDYwLDB4YjksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAweGEzLDB4MmEsMHhmMCwweDY3LDB4NTgsMHhlOSwweGY2LDB4NDcsMHg4MywweGRlLDB4N2UsMHhmYiwweGJiLDB4YmQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAweGRmLDB4NDgsMHgxMiwweDFiLDB4MDYsMHg3ZCwweDEzLDB4YmMsMHgzYiwweDQ5LDB4ZjksMHg4NiwweGQ0LDB4NTMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAweGVkLDB4MmQsMHg2OF0pXTtcblxuICB2YXIgUlNBcHViTVBJcyA9IFtdO1xuICB2YXIgaTtcbiAgZm9yIChpID0gMDsgaSA8IDI7IGkrKykge1xuICAgIFJTQXB1Yk1QSXNbaV0gPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgICBSU0FwdWJNUElzW2ldLnJlYWQoUlNBcHViTVBJc3Ryc1tpXSk7XG4gIH1cblxuICB2YXIgUlNBc2VjTVBJcyA9IFtdO1xuICBmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgUlNBc2VjTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIFJTQXNlY01QSXNbaV0ucmVhZChSU0FzZWNNUElzdHJzW2ldKTtcbiAgfVxuICAgIFxuICB2YXIgRFNBc2VjTVBJcyA9IFtdO1xuICBmb3IgKGkgPSAwOyBpIDwgMTsgaSsrKSB7XG4gICAgRFNBc2VjTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIERTQXNlY01QSXNbaV0ucmVhZChEU0FzZWNNUElzdHJzW2ldKTtcbiAgfVxuICAgIFxuICB2YXIgRFNBcHViTVBJcyA9IFtdO1xuICBmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKSB7XG4gICAgRFNBcHViTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIERTQXB1Yk1QSXNbaV0ucmVhZChEU0FwdWJNUElzdHJzW2ldKTtcbiAgfVxuICB2YXIgRWxnYW1hbHNlY01QSXMgPSBbXTtcbiAgZm9yIChpID0gMDsgaSA8IDE7IGkrKykge1xuICAgIEVsZ2FtYWxzZWNNUElzW2ldID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRWxnYW1hbHNlY01QSXNbaV0ucmVhZChFbGdhbWFsc2VjTVBJc3Ryc1tpXSk7XG4gIH1cbiAgICBcbiAgdmFyIEVsZ2FtYWxwdWJNUElzID0gW107XG4gIGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICBFbGdhbWFscHViTVBJc1tpXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIEVsZ2FtYWxwdWJNUElzW2ldLnJlYWQoRWxnYW1hbHB1Yk1QSXN0cnNbaV0pO1xuICB9XG5cbiAgLy9PcmlnaW5hbGx5IHdlIHBhc3NlZCBwdWJsaWMgYW5kIHNlY3JldCBNUEkgc2VwYXJhdGVseSwgbm93IHRoZXkgYXJlIGpvaW5lZC4gSXMgdGhpcyB3aGF0IHdlIHdhbnQgdG8gZG8gbG9uZyB0ZXJtP1xuICAvLyBSU0FcbiAgdmFyIFJTQXNpZ25lZERhdGEgPSBvcGVucGdwLmNyeXB0by5zaWduYXR1cmUuc2lnbigyLCAxLCBSU0FwdWJNUElzLmNvbmNhdChSU0FzZWNNUElzKSwgXCJmb29iYXJcIik7XG4gIHZhciBSU0FzaWduZWREYXRhTVBJID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gIFJTQXNpZ25lZERhdGFNUEkucmVhZChSU0FzaWduZWREYXRhKTtcbiAgcmVzdWx0WzBdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBSU0EgU2lnbiBhbmQgVmVyaWZ5XCIsXG4gICAgICBvcGVucGdwLmNyeXB0by5zaWduYXR1cmUudmVyaWZ5KDEsIDIsIFtSU0FzaWduZWREYXRhTVBJXSwgUlNBcHViTVBJcywgXCJmb29iYXJcIikpO1xuXG4gIC8vIERTQSBcbiAgdmFyIERTQXNpZ25lZERhdGEgPSBvcGVucGdwLmNyeXB0by5zaWduYXR1cmUuc2lnbigyLCAxNywgRFNBcHViTVBJcy5jb25jYXQoRFNBc2VjTVBJcyksIFwiZm9vYmFyXCIpO1xuICBcbiAgdmFyIERTQW1zZ01QSXMgPSBbXTtcbiAgICBEU0Ftc2dNUElzWzBdID0gbmV3IG9wZW5wZ3AubXBpKCk7XG4gICAgRFNBbXNnTVBJc1sxXSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICAgIERTQW1zZ01QSXNbMF0ucmVhZChEU0FzaWduZWREYXRhLnN1YnN0cmluZygwLDM0KSk7XG4gICAgRFNBbXNnTVBJc1sxXS5yZWFkKERTQXNpZ25lZERhdGEuc3Vic3RyaW5nKDM0LDY4KSk7XG4gIHJlc3VsdFsxXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3RpbmcgRFNBIFNpZ24gYW5kIFZlcmlmeVwiLFxuICAgICAgb3BlbnBncC5jcnlwdG8uc2lnbmF0dXJlLnZlcmlmeSgxNywgMiwgRFNBbXNnTVBJcywgRFNBcHViTVBJcywgXCJmb29iYXJcIikpO1xuICBcbiAgdmFyIHN5bW1BbGdvID0gXCJhZXMyNTZcIjsgLy8gQUVTMjU2XG4gIHZhciBzeW1tS2V5ID0gb3BlbnBncC5jcnlwdG8uZ2VuZXJhdGVTZXNzaW9uS2V5KHN5bW1BbGdvKTtcbiAgdmFyIHN5bW1lbmNEYXRhT0NGQiA9IG9wZW5wZ3AuY3J5cHRvLmNmYi5lbmNyeXB0KG9wZW5wZ3AuY3J5cHRvLmdldFByZWZpeFJhbmRvbShzeW1tQWxnbyksIHN5bW1BbGdvLCBcImZvb2JhcmZvb2JhcjEyMzQ1Njc4OTBcIiwgc3ltbUtleSwgdHJ1ZSk7XG4gIHZhciBzeW1tZW5jRGF0YUNGQiAgPSBvcGVucGdwLmNyeXB0by5jZmIuZW5jcnlwdChvcGVucGdwLmNyeXB0by5nZXRQcmVmaXhSYW5kb20oc3ltbUFsZ28pLCBzeW1tQWxnbywgXCJmb29iYXJmb29iYXIxMjM0NTY3ODkwXCIsIHN5bW1LZXksIGZhbHNlKTtcbiAgXG4gIHJlc3VsdFsyXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3Rpbmcgc3ltbWV0cmljIGVuY3J5cHQgYW5kIGRlY3J5cHQgd2l0aCBPcGVuUEdQIENGQiByZXN5bmNcIixcbiAgICAgIG9wZW5wZ3AuY3J5cHRvLmNmYi5kZWNyeXB0KHN5bW1BbGdvLHN5bW1LZXksc3ltbWVuY0RhdGFPQ0ZCLHRydWUpID09IFwiZm9vYmFyZm9vYmFyMTIzNDU2Nzg5MFwiKTtcbiAgcmVzdWx0WzNdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBzeW1tZXRyaWMgZW5jcnlwdCBhbmQgZGVjcnlwdCB3aXRob3V0IE9wZW5QR1AgQ0ZCIHJlc3luYyAodXNlZCBpbiBtb2RpZmljYXRpb24gZGV0ZWN0aW9uIGNvZGUgXFxcIk1EQ1xcXCIgcGFja2V0cylcIixcbiAgICAgIG9wZW5wZ3AuY3J5cHRvLmNmYi5kZWNyeXB0KHN5bW1BbGdvLHN5bW1LZXksc3ltbWVuY0RhdGFDRkIsZmFsc2UpID09IFwiZm9vYmFyZm9vYmFyMTIzNDU2Nzg5MFwiKTtcbiAgXG4gIHZhciBSU0FVbmVuY3J5cHRlZERhdGEgPSBuZXcgb3BlbnBncC5tcGkoKTtcbiAgUlNBVW5lbmNyeXB0ZWREYXRhLmZyb21CeXRlcyhvcGVucGdwLmNyeXB0by5wa2NzMS5lbWUuZW5jb2RlKHN5bW1LZXksIFJTQXB1Yk1QSXNbMF0uYnl0ZUxlbmd0aCgpKSk7XG4gIHZhciBSU0FFbmNyeXB0ZWREYXRhID0gb3BlbnBncC5jcnlwdG8ucHVibGljS2V5RW5jcnlwdChcInJzYV9lbmNyeXB0X3NpZ25cIiwgUlNBcHViTVBJcywgUlNBVW5lbmNyeXB0ZWREYXRhKTtcblxuICByZXN1bHRbNF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIGFzeW1tZXRyaWMgZW5jcnlwdCBhbmQgZGVjcnlwdCB1c2luZyBSU0Egd2l0aCBlbWVfcGtjczEgcGFkZGluZ1wiLFxuICAgICAgb3BlbnBncC5jcnlwdG8ucGtjczEuZW1lLmRlY29kZShvcGVucGdwLmNyeXB0by5wdWJsaWNLZXlEZWNyeXB0KFwicnNhX2VuY3J5cHRfc2lnblwiLCBSU0FwdWJNUElzLmNvbmNhdChSU0FzZWNNUElzKSwgUlNBRW5jcnlwdGVkRGF0YSkud3JpdGUoKS5zdWJzdHJpbmcoMiksIFJTQXB1Yk1QSXNbMF0uYnl0ZUxlbmd0aCgpKSA9PSBzeW1tS2V5KTtcblxuICB2YXIgRWxnYW1hbFVuZW5jcnlwdGVkRGF0YSA9IG5ldyBvcGVucGdwLm1waSgpO1xuICBFbGdhbWFsVW5lbmNyeXB0ZWREYXRhLmZyb21CeXRlcyhvcGVucGdwLmNyeXB0by5wa2NzMS5lbWUuZW5jb2RlKHN5bW1LZXksIEVsZ2FtYWxwdWJNUElzWzBdLmJ5dGVMZW5ndGgoKSkpO1xuICB2YXIgRWxnYW1hbEVuY3J5cHRlZERhdGEgPSBvcGVucGdwLmNyeXB0by5wdWJsaWNLZXlFbmNyeXB0KFwiZWxnYW1hbFwiLCBFbGdhbWFscHViTVBJcywgRWxnYW1hbFVuZW5jcnlwdGVkRGF0YSk7XG5cbiAgcmVzdWx0WzVdID0gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBhc3ltbWV0cmljIGVuY3J5cHQgYW5kIGRlY3J5cHQgdXNpbmcgRWxnYW1hbCB3aXRoIGVtZV9wa2NzMSBwYWRkaW5nXCIsXG4gICAgICBvcGVucGdwLmNyeXB0by5wa2NzMS5lbWUuZGVjb2RlKG9wZW5wZ3AuY3J5cHRvLnB1YmxpY0tleURlY3J5cHQoXCJlbGdhbWFsXCIsIEVsZ2FtYWxwdWJNUElzLmNvbmNhdChFbGdhbWFsc2VjTVBJcyksIEVsZ2FtYWxFbmNyeXB0ZWREYXRhKS53cml0ZSgpLnN1YnN0cmluZygyKSwgRWxnYW1hbHB1Yk1QSXNbMF0uYnl0ZUxlbmd0aCgpKSA9PSBzeW1tS2V5KTtcblxuICByZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIk1ENSB0ZXN0IHdpdGggdGVzdCB2ZWN0b3JzIGZyb20gUkZDIDEzMjFcIiwgZnVuY3Rpb24oKSB7XG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vLi4vJyksXG5cdFx0dXRpbCA9IG9wZW5wZ3AudXRpbCxcblx0XHRNRDUgPSBvcGVucGdwLmNyeXB0by5oYXNoLm1kNTtcblxuXHR2YXIgcmVzdWx0ID0gbmV3IEFycmF5KCk7XG5cdHJlc3VsdFswXSA9IG5ldyB1bml0LnJlc3VsdChcIk1ENSAoXFxcIlxcXCIpID0gZDQxZDhjZDk4ZjAwYjIwNGU5ODAwOTk4ZWNmODQyN2VcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChNRDUoXCJcIikpID09IFwiZDQxZDhjZDk4ZjAwYjIwNGU5ODAwOTk4ZWNmODQyN2VcIik7XG5cdHJlc3VsdFsxXSA9IG5ldyB1bml0LnJlc3VsdChcIk1ENSAoXFxcImFcXFwiKSA9IDBjYzE3NWI5YzBmMWI2YTgzMWMzOTllMjY5NzcyNjYxXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoTUQ1IChcImFiY1wiKSkgPT0gXCI5MDAxNTA5ODNjZDI0ZmIwZDY5NjNmN2QyOGUxN2Y3MlwiKTtcblx0cmVzdWx0WzJdID0gbmV3IHVuaXQucmVzdWx0KFwiTUQ1IChcXFwibWVzc2FnZSBkaWdlc3RcXFwiKSA9IGY5NmI2OTdkN2NiNzkzOGQ1MjVhMmYzMWFhZjE2MWQwXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoTUQ1IChcIm1lc3NhZ2UgZGlnZXN0XCIpKSA9PSBcImY5NmI2OTdkN2NiNzkzOGQ1MjVhMmYzMWFhZjE2MWQwXCIpO1xuXHRyZXN1bHRbM10gPSBuZXcgdW5pdC5yZXN1bHQoXCJNRDUgKFxcXCJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elxcXCIpID0gYzNmY2QzZDc2MTkyZTQwMDdkZmI0OTZjY2E2N2UxM2JcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChNRDUgKFwiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpcIikpID09IFwiYzNmY2QzZDc2MTkyZTQwMDdkZmI0OTZjY2E2N2UxM2JcIik7XG5cdHJlc3VsdFs0XSA9IG5ldyB1bml0LnJlc3VsdChcIk1ENSAoXFxcIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5XFxcIikgPSBkMTc0YWI5OGQyNzdkOWY1YTU2MTFjMmM5ZjQxOWQ5ZlwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKE1ENSAoXCJBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OVwiKSkgPT0gXCJkMTc0YWI5OGQyNzdkOWY1YTU2MTFjMmM5ZjQxOWQ5ZlwiKTtcblx0cmVzdWx0WzVdID0gbmV3IHVuaXQucmVzdWx0KFwiTUQ1IChcXFwiMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTBcXFwiKSA9IDU3ZWRmNGEyMmJlM2M5NTVhYzQ5ZGEyZTIxMDdiNjdhXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoTUQ1IChcIjEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwXCIpKSA9PSBcIjU3ZWRmNGEyMmJlM2M5NTVhYzQ5ZGEyZTIxMDdiNjdhXCIpO1xuXHRyZXR1cm4gcmVzdWx0O1xufSk7XG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uLy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIlJJUEUtTUQgMTYwIGJpdHMgdGVzdCB3aXRoIHRlc3QgdmVjdG9ycyBmcm9tIGh0dHA6Ly9ob21lcy5lc2F0Lmt1bGV1dmVuLmJlL35ib3NzZWxhZS9yaXBlbWQxNjAuaHRtbFwiLCBmdW5jdGlvbigpIHtcblxuXHR2YXIgb3BlbnBncCA9IHJlcXVpcmUoJy4uLy4uLy4uLycpLFxuXHRcdHV0aWwgPSBvcGVucGdwLnV0aWwsXG5cdFx0Uk1Ec3RyaW5nID0gb3BlbnBncC5jcnlwdG8uaGFzaC5yaXBlbWQ7XG5cblx0dmFyIHJlc3VsdCA9IG5ldyBBcnJheSgpO1xuXHRyZXN1bHRbMF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJSTURzdHJpbmcgKFxcXCJcXFwiKSA9IDljMTE4NWE1YzVlOWZjNTQ2MTI4MDg5NzdlZThmNTQ4YjIyNThkMzFcIixcblx0XHRcdHV0aWwuaGV4c3RyZHVtcChSTURzdHJpbmcoXCJcIikpID09IFwiOWMxMTg1YTVjNWU5ZmM1NDYxMjgwODk3N2VlOGY1NDhiMjI1OGQzMVwiKTtcblx0cmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiUk1Ec3RyaW5nIChcXFwiYVxcXCIpID0gMGJkYzlkMmQyNTZiM2VlOWRhYWUzNDdiZTZmNGRjODM1YTQ2N2ZmZVwiLFxuXHRcdFx0dXRpbC5oZXhzdHJkdW1wKFJNRHN0cmluZyhcImFcIikpID09IFwiMGJkYzlkMmQyNTZiM2VlOWRhYWUzNDdiZTZmNGRjODM1YTQ2N2ZmZVwiKTtcblx0cmVzdWx0WzJdID0gbmV3IHVuaXQucmVzdWx0KFwiUk1Ec3RyaW5nIChcXFwiYWJjXFxcIikgPSA4ZWIyMDhmN2UwNWQ5ODdhOWIwNDRhOGU5OGM2YjA4N2YxNWEwYmZjXCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoUk1Ec3RyaW5nKFwiYWJjXCIpKSA9PSBcIjhlYjIwOGY3ZTA1ZDk4N2E5YjA0NGE4ZTk4YzZiMDg3ZjE1YTBiZmNcIik7XG5cdHJlc3VsdFszXSA9IG5ldyB1bml0LnJlc3VsdChcIlJNRHN0cmluZyAoXFxcIm1lc3NhZ2UgZGlnZXN0XFxcIikgPSA1ZDA2ODllZjQ5ZDJmYWU1NzJiODgxYjEyM2E4NWZmYTIxNTk1ZjM2XCIsXG5cdFx0XHR1dGlsLmhleHN0cmR1bXAoUk1Ec3RyaW5nKFwibWVzc2FnZSBkaWdlc3RcIikpID09IFwiNWQwNjg5ZWY0OWQyZmFlNTcyYjg4MWIxMjNhODVmZmEyMTU5NWYzNlwiKTtcblx0cmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi8uLi91bml0LmpzJyk7XG5cblxudW5pdC5yZWdpc3RlcihcIlNIQSogdGVzdCB3aXRoIHRlc3QgdmVjdG9ycyBmcm9tIE5JU1QgRklQUyAxODAtMlwiLCBmdW5jdGlvbigpIHtcblx0dmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8uLi8nKSxcblx0XHR1dGlsID0gb3BlbnBncC51dGlsLFxuXHRcdGhhc2ggPSBvcGVucGdwLmNyeXB0by5oYXNoO1xuXG5cdHZhciByZXN1bHQgPSBuZXcgQXJyYXkoKTtcblx0XG5cdHJlc3VsdFswXSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTEgLSBhOTk5M2UzNjQ3MDY4MTZhYmEzZTI1NzE3ODUwYzI2YzljZDBkODlkID0gaGFzaC5zaGExKFxcXCJhYmNcXFwiKSBcIixcblx0XHRcdFwiYTk5OTNlMzY0NzA2ODE2YWJhM2UyNTcxNzg1MGMyNmM5Y2QwZDg5ZFwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTEoXCJhYmNcIikpKTtcblx0cmVzdWx0WzFdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMSAtIDg0OTgzZTQ0MWMzYmQyNmViYWFlNGFhMWY5NTEyOWU1ZTU0NjcwZjEgPSBoYXNoLnNoYTEoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjg0OTgzZTQ0MWMzYmQyNmViYWFlNGFhMWY5NTEyOWU1ZTU0NjcwZjFcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGExKFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcIikpKTtcblx0cmVzdWx0WzJdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMjI0IC0gMjMwOTdkMjIzNDA1ZDgyMjg2NDJhNDc3YmRhMjU1YjMyYWFkYmNlNGJkYTBiM2Y3ZTM2YzlkYTcgPSBoYXNoLnNoYTIyNChcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcIjIzMDk3ZDIyMzQwNWQ4MjI4NjQyYTQ3N2JkYTI1NWIzMmFhZGJjZTRiZGEwYjNmN2UzNmM5ZGE3XCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhMjI0KFwiYWJjXCIpKSk7XG5cdHJlc3VsdFszXSA9IG5ldyB1bml0LnJlc3VsdChcIlNIQTIyNCAtIDc1Mzg4YjE2NTEyNzc2Y2M1ZGJhNWRhMWZkODkwMTUwYjBjNjQ1NWNiNGY1OGIxOTUyNTIyNTI1ID0gaGFzaC5zaGEyMjQoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjc1Mzg4YjE2NTEyNzc2Y2M1ZGJhNWRhMWZkODkwMTUwYjBjNjQ1NWNiNGY1OGIxOTUyNTIyNTI1XCIgPT0gdXRpbC5oZXhzdHJkdW1wKGhhc2guc2hhMjI0KFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcIikpKTtcblx0cmVzdWx0WzRdID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBMjU2IC0gYmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljYjQxMGZmNjFmMjAwMTVhZCA9IGhhc2guc2hhMjU2KFxcXCJhYmNcXFwiKSBcIixcblx0XHRcdFwiYmE3ODE2YmY4ZjAxY2ZlYTQxNDE0MGRlNWRhZTIyMjNiMDAzNjFhMzk2MTc3YTljYjQxMGZmNjFmMjAwMTVhZFwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTI1NihcImFiY1wiKSkpO1xuXHRyZXN1bHRbNV0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEyNTYgLSAyNDhkNmE2MWQyMDYzOGI4ZTVjMDI2OTMwYzNlNjAzOWEzM2NlNDU5NjRmZjIxNjdmNmVjZWRkNDE5ZGIwNmMxID0gaGFzaC5zaGEyNTYoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjI0OGQ2YTYxZDIwNjM4YjhlNWMwMjY5MzBjM2U2MDM5YTMzY2U0NTk2NGZmMjE2N2Y2ZWNlZGQ0MTlkYjA2YzFcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGEyNTYoXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVwiKSkpO1xuXHRyZXN1bHRbNl0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEzODQgLSBjYjAwNzUzZjQ1YTM1ZThiYjVhMDNkNjk5YWM2NTAwNzI3MmMzMmFiMGVkZWQxNjMxYThiNjA1YTQzZmY1YmVkODA4NjA3MmJhMWU3Y2MyMzU4YmFlY2ExMzRjODI1YTcgPSBoYXNoLnNoYTM4NChcXFwiYWJjXFxcIikgXCIsXG5cdFx0XHRcImNiMDA3NTNmNDVhMzVlOGJiNWEwM2Q2OTlhYzY1MDA3MjcyYzMyYWIwZWRlZDE2MzFhOGI2MDVhNDNmZjViZWQ4MDg2MDcyYmExZTdjYzIzNThiYWVjYTEzNGM4MjVhN1wiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTM4NChcImFiY1wiKSkpO1xuXHRyZXN1bHRbN10gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEEzODQgLSAzMzkxZmRkZGZjOGRjNzM5MzcwN2E2NWIxYjQ3MDkzOTdjZjhiMWQxNjJhZjA1YWJmZThmNDUwZGU1ZjM2YmM2YjA0NTVhODUyMGJjNGU2ZjVmZTk1YjFmZTNjODQ1MmIgPSBzdHIzODQoXFxcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXFxcIikgXCIsXG5cdFx0XHRcIjMzOTFmZGRkZmM4ZGM3MzkzNzA3YTY1YjFiNDcwOTM5N2NmOGIxZDE2MmFmMDVhYmZlOGY0NTBkZTVmMzZiYzZiMDQ1NWE4NTIwYmM0ZTZmNWZlOTViMWZlM2M4NDUyYlwiID09IHV0aWwuaGV4c3RyZHVtcChoYXNoLnNoYTM4NChcImFiY2RiY2RlY2RlZmRlZmdlZmdoZmdoaWdoaWpoaWpraWprbGprbG1rbG1ubG1ub21ub3Bub3BxXCIpKSk7XHRcdFx0XHRcdFxuXHRyZXN1bHRbOF0gPSBuZXcgdW5pdC5yZXN1bHQoXCJTSEE1MTIgLSBkZGFmMzVhMTkzNjE3YWJhY2M0MTczNDlhZTIwNDEzMTEyZTZmYTRlODlhOTdlYTIwYTllZWVlNjRiNTVkMzlhMjE5Mjk5MmEyNzRmYzFhODM2YmEzYzIzYTNmZWViYmQ0NTRkNDQyMzY0M2NlODBlMmE5YWM5NGZhNTRjYTQ5ZiA9IGhhc2guc2hhNTEyKFxcXCJhYmNcXFwiKSBcIixcblx0XHRcdFwiZGRhZjM1YTE5MzYxN2FiYWNjNDE3MzQ5YWUyMDQxMzExMmU2ZmE0ZTg5YTk3ZWEyMGE5ZWVlZTY0YjU1ZDM5YTIxOTI5OTJhMjc0ZmMxYTgzNmJhM2MyM2EzZmVlYmJkNDU0ZDQ0MjM2NDNjZTgwZTJhOWFjOTRmYTU0Y2E0OWZcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGE1MTIoXCJhYmNcIikpKTtcblx0cmVzdWx0WzldID0gbmV3IHVuaXQucmVzdWx0KFwiU0hBNTEyIC0gMjA0YThmYzZkZGE4MmYwYTBjZWQ3YmViOGUwOGE0MTY1N2MxNmVmNDY4YjIyOGE4Mjc5YmUzMzFhNzAzYzMzNTk2ZmQxNWMxM2IxYjA3ZjlhYTFkM2JlYTU3Nzg5Y2EwMzFhZDg1YzdhNzFkZDcwMzU0ZWM2MzEyMzhjYTM0NDUgPSBoYXNoLnNoYTUxMihcXFwiYWJjZGJjZGVjZGVmZGVmZ2VmZ2hmZ2hpZ2hpamhpamtpamtsamtsbWtsbW5sbW5vbW5vcG5vcHFcXFwiKSBcIixcblx0XHRcdFwiMjA0YThmYzZkZGE4MmYwYTBjZWQ3YmViOGUwOGE0MTY1N2MxNmVmNDY4YjIyOGE4Mjc5YmUzMzFhNzAzYzMzNTk2ZmQxNWMxM2IxYjA3ZjlhYTFkM2JlYTU3Nzg5Y2EwMzFhZDg1YzdhNzFkZDcwMzU0ZWM2MzEyMzhjYTM0NDVcIiA9PSB1dGlsLmhleHN0cmR1bXAoaGFzaC5zaGE1MTIoXCJhYmNkYmNkZWNkZWZkZWZnZWZnaGZnaGlnaGlqaGlqa2lqa2xqa2xta2xtbmxtbm9tbm9wbm9wcVwiKSkpO1x0XHRcdFx0XHRcblx0cmV0dXJuIHJlc3VsdDtcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJLZXkgZ2VuZXJhdGlvbi9lbmNyeXB0aW9uL2RlY3J5cHRpb25cIiwgZnVuY3Rpb24oKSB7XG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vJyk7XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgdmFyIHRlc3RIZWxwZXIgPSBmdW5jdGlvbihwYXNzcGhyYXNlLCB1c2VyaWQsIG1lc3NhZ2UpIHtcbiAgICB2YXIga2V5ID0gb3BlbnBncC5nZW5lcmF0ZUtleVBhaXIob3BlbnBncC5lbnVtcy5wdWJsaWNLZXkucnNhX2VuY3J5cHRfc2lnbiwgNTEyLCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlcmlkLCBwYXNzcGhyYXNlKTtcblxuICAgIHZhciBpbmZvID0gJ1xcbnBhc3NwaHJhc2U6ICcgKyBwYXNzcGhyYXNlICsgJ1xcbidcbiAgICAgICAgKyAndXNlcmlkOiAnICsgdXNlcmlkICsgJ1xcbidcbiAgICAgICAgKyAnbWVzc2FnZTogJyArIG1lc3NhZ2U7XG5cbiAgICB2YXIgcHJpdktleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKGtleSk7XG5cbiAgICB2YXIgZW5jcnlwdGVkID0gb3BlbnBncC5lbmNyeXB0TWVzc2FnZShbcHJpdktleV0sIG1lc3NhZ2UpO1xuXG4gICAgdmFyIG1zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChlbmNyeXB0ZWQpO1xuXG4gICAgdmFyIGtleWlkcyA9IG1zZy5nZXRFbmNyeXB0aW9uS2V5SWRzKCk7XG5cbiAgICBwcml2S2V5LmRlY3J5cHRLZXlQYWNrZXQoa2V5aWRzLCBwYXNzcGhyYXNlKTtcblxuICAgIHRyeSB7XG4gICAgICB2YXIgZGVjcnlwdGVkID0gb3BlbnBncC5kZWNyeXB0TWVzc2FnZShwcml2S2V5LCBtc2cpO1xuICAgICAgcmV0dXJuIG5ldyB1bml0LnJlc3VsdChtZXNzYWdlICsgJyA9PSAnICsgZGVjcnlwdGVkICsgaW5mbywgbWVzc2FnZSA9PSBkZWNyeXB0ZWQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHJldHVybiBuZXcgdW5pdC5yZXN1bHQoXCJFeGNlcHRpb24gb24gZGVjcnlwdCBvZiBwcml2YXRlIGtleSBwYWNrZXQhXCIgKyBpbmZvLCBmYWxzZSk7XG4gICAgfVxuXG4gIH07XG5cbiAgcmVzdWx0LnB1c2godGVzdEhlbHBlcigncGFzc3dvcmQnLCAnVGVzdCBNY1Rlc3Rpbmd0b24gPHRlc3RAZXhhbXBsZS5jb20+JywgJ2hlbGxvIHdvcmxkJykpO1xuICByZXN1bHQucHVzaCh0ZXN0SGVscGVyKCfil4/il4/il4/il48nLCAn4pmU4pmU4pmU4pmUIDx0ZXN0QGV4YW1wbGUuY29tPicsICfFgsOkw7PEhycpKTtcblxuICByZXR1cm4gcmVzdWx0O1xufSk7XG5cbnVuaXQucmVnaXN0ZXIoXCJNZXNzYWdlIGVuY3J5cHRpb24vZGVjcnlwdGlvblwiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8nKTtcblxuICB2YXIgcmVzdWx0ID0gW107XG5cbiAgdmFyIHB1Yl9rZXkgPSBcbiAgICAgWyctLS0tLUJFR0lOIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0nLFxuICAgICAgJ1ZlcnNpb246IEdudVBHIHYyLjAuMTkgKEdOVS9MaW51eCknLFxuICAgICAgJ1R5cGU6IFJTQS9SU0EnLFxuICAgICAgJycsXG4gICAgICAnbUkwRVVtRXZUZ0VFQU55V3RRUU1PeWJROUpsdERxbWFYMFduTlBKZUxJTElNMzZzdzZ6TDBuZlRRNXpYU1MzKycsXG4gICAgICAnZklGNlAyOWxKRnhwYmxXazAyUFNJRDV6WC9EWVU5L3pqTTJ4UE84T2E0eG8wY1ZUT1RMaisrUmk1bXRyLy9mNScsXG4gICAgICAnR0xzSVh4RnJCSmhEL2doRnNMM09wMEdYT2VMSjlBNWJzT244dGg3eDZKdWNOS3VhUkI2YlFiU1BBQkVCQUFHMCcsXG4gICAgICAnSkZSbGMzUWdUV05VWlhOMGFXNW5kRzl1SUR4MFpYTjBRR1Y0WVcxd2JHVXVZMjl0UG9pNUJCTUJBZ0FqQlFKUycsXG4gICAgICAnWVM5T0Foc3ZCd3NKQ0FjREFnRUdGUWdDQ1FvTEJCWUNBd0VDSGdFQ0Y0QUFDZ2tRU21OaE9rMXVRSlF3REFQNicsXG4gICAgICAnQWdyVHlxa1JsSlZxejJwYjQ2VGZiRE0yVERGN285Q0JuQnpJR294QmhsUndwcUFMejd6Mmt4QkRtd3BRYStraScsXG4gICAgICAnQnEzalpOL1Vvc1k5eThiaHdNQWxuckRZOWpQMWdkQ28rSDBzRDQ4Q2RYeWJibE53YVlwd3FDOFZTcERkVG5kZicsXG4gICAgICAnOWoyd0Uvd2VpaEdwL0RBZHkvMmt5QkNhaU9ZMXNqaFVmSjFHb2dGNDlyQzRqUVJTWVM5T0FRUUE2Ui9QdEJGYScsXG4gICAgICAnSmFUNGpxMTB5cUFTazRzcXdWTXNjNkhjaWZNNWxTZHh6RXhGUDc0bmFVTU15RXNLSFA1M1F4VEYwR3JxdXNhZycsXG4gICAgICAnUWcvWnRnVDBDTjFIVU0xNTJ5N0FDT2RwMWdpS2pwTXpPVFFDbHFDb2NseXZXT0ZCK0wvU3dHRUlKZjdMU0NFcicsXG4gICAgICAnd29CdUppZkpjOHhBVnIwWFgwSnRob1crdVA5MWVUUTNYcHNBRVFFQUFZa0JQUVFZQVFJQUNRVUNVbUV2VGdJYicsXG4gICAgICAnTGdDb0NSQktZMkU2VFc1QWxKMGdCQmtCQWdBR0JRSlNZUzlPQUFvSkVPQ0U5MFJzSUN5WHVxSUVBTm1taVJDQScsXG4gICAgICAnU0Y3WUs3UHZGa2llSk53emVLMFYzRjJsR1grdXU2WTNRL1p4ZHR3YzR4UittZS9DU0Jtc1VSeVhUTzI5T1doUCcsXG4gICAgICAnR0xzelBIOXpTSlU5QmREaTZ2MHlOcHJtRlBYLzFOZzBBYm4vc0Nrd2V0dmp4QzFZSXZUTEZ3dFVMLzd2Nk5TMicsXG4gICAgICAnYlpwc1V4UlRnOStjU3JNV1dTTmppWTlxVUtham0xdHV6UERaWEFVRUFNTm1BTjN4WE4vS2p5dmoyT0syY2swWCcsXG4gICAgICAnVzc0OHNsL3RjM3FpS1BNSiswQWtNRjdQamhtaDlueHFFOStRQ0VsN3FpbkZxcUJManV6Z1VoQlU0UWx3WDFHRCcsXG4gICAgICAnQXROVHE2aWhMTUQ1djFkODJaQzd0TmF0ZGxETUdXbklkdkVNQ3YyR1pjdUlxRFE5clhXczQ5ZTd0cTFObmNMWScsXG4gICAgICAnaHozdFlqS2hvRlRLRUlxM3kzUHAnLFxuICAgICAgJz1oL2FYJyxcbiAgICAgICctLS0tLUVORCBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgdmFyIHByaXZfa2V5ID1cbiAgICAgIFsnLS0tLS1CRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAnVmVyc2lvbjogR251UEcgdjIuMC4xOSAoR05VL0xpbnV4KScsXG4gICAgICAnVHlwZTogUlNBL1JTQScsXG4gICAgICAnUHdkOiBoZWxsbyB3b3JsZCcsXG4gICAgICAnJyxcbiAgICAgICdsUUgrQkZKaEwwNEJCQURjbHJVRUREc20wUFNaYlE2cG1sOUZwelR5WGl5Q3lETityTU9zeTlKMzAwT2MxMGt0JyxcbiAgICAgICcvbnlCZWo5dlpTUmNhVzVWcE5OajBpQStjMS93MkZQZjg0ek5zVHp2RG11TWFOSEZVemt5NC92a1l1WnJhLy8zJyxcbiAgICAgICcrUmk3Q0Y4UmF3U1lRLzRJUmJDOXpxZEJsem5peWZRT1c3RHAvTFllOGVpYm5EU3Jta1FlbTBHMGp3QVJBUUFCJyxcbiAgICAgICcvZ01EQXU3TC8vY3pCcEU0MHAxWnFPOEszazdVZWplbWpzUXFjN2tPcW5sRFlkMVo2LzNORUEvVU0zMFNpaXByJyxcbiAgICAgICdLamRJRlk1K2hwMGhjczZFaWlOcTBQRGZtL1cyais3SGZyWjVrcGVRVnhEZWs0aXJlellacmw3SlMyeGV6YUx2JyxcbiAgICAgICdrMEZ2LzZmeGFzbkZ0ak9NNlFic3R1NjdzNUdwbDl5MDZaeGJQM1ZwVDYyK1hlaWJuL3N3V3JmaUpqdUdFRWhNJyxcbiAgICAgICdiZ25zTXBIdHpBei9MOHk2S1N6VmlHLzA1aEJhcXJ2azMvR2VFQTZuRStvMCswYTZyMExZTFRlbW1xNkZiYUExJyxcbiAgICAgICdQSG8reDdrN29GY0JGVVVlU3pneDc4R2NrdVB3cXIybU5mZUYrSXVTUm5ybHBabDNrY2JIQVNQQU9mRWt5TVhTJyxcbiAgICAgICdzV0dFN2dyQ0FqYnlReU0zT0VYVFN5cW5laHZHUy8xUmRCNmtERHhHd2dFL1FGYndOeUVoNks0ZWFhQVRoVzJqJyxcbiAgICAgICdJRUVJMFdFblJrUGk5Zlh5eGhGc0NMU0kxWGhxVGFxN2lETnFKVHhFK0FYMmI5WnVaWEF4STNUYy83Kyt2RXlMJyxcbiAgICAgICczcDE4Ti9NQjJrdDFXYjFhem1YV0wyRUtsVDFCWjV5RGFKdUJROEJocGhNM3RDUlVaWE4wSUUxalZHVnpkR2x1JyxcbiAgICAgICdaM1J2YmlBOGRHVnpkRUJsZUdGdGNHeGxMbU52YlQ2SXVRUVRBUUlBSXdVQ1VtRXZUZ0liTHdjTENRZ0hBd0lCJyxcbiAgICAgICdCaFVJQWdrS0N3UVdBZ01CQWg0QkFoZUFBQW9KRUVwallUcE5ia0NVTUF3RCtnSUswOHFwRVpTVmFzOXFXK09rJyxcbiAgICAgICczMnd6Tmt3eGU2UFFnWndjeUJxTVFZWlVjS2FnQzgrODlwTVFRNXNLVUd2cElnYXQ0MlRmMUtMR1Bjdkc0Y0RBJyxcbiAgICAgICdKWjZ3MlBZejlZSFFxUGg5TEErUEFuVjhtMjVUY0dtS2NLZ3ZGVXFRM1U1M1gvWTlzQlA4SG9vUnFmd3dIY3Y5JyxcbiAgICAgICdwTWdRbW9qbU5iSTRWSHlkUnFJQmVQYXduUUgrQkZKaEwwNEJCQURwSDgrMEVWb2xwUGlPclhUS29CS1RpeXJCJyxcbiAgICAgICdVeXh6b2R5Sjh6bVZKM0hNVEVVL3ZpZHBRd3pJU3dvYy9uZERGTVhRYXVxNnhxQkNEOW0yQlBRSTNVZFF6WG5iJyxcbiAgICAgICdMc0FJNTJuV0NJcU9rek01TkFLV29LaHlYSzlZNFVINHY5TEFZUWdsL3N0SUlTdkNnRzRtSjhsenpFQld2UmRmJyxcbiAgICAgICdRbTJHaGI2NC8zVjVORGRlbXdBUkFRQUIvZ01EQXU3TC8vY3pCcEU0MGlQY3BMekw3R3dCYldGaFNXZ1NMeTUzJyxcbiAgICAgICdNZDk5S3h3M2NBcFdDb2syRThSOS80VlMwNDkweEtaSWE1eTJJL0s4dGhWaHFrOTZaOEtidDdNUk1DMVdMSGdDJyxcbiAgICAgICdxSnZrZVFDSTZQckZNMFBVSVBMSEFRdERKWUt0YUxYeFl1ZXhjQWRLelpqM0ZIZHRMTldDb29LNm4zdkpsTDFjJyxcbiAgICAgICdXalpjSEoxUEg3VVNsajFqdXA0WGZ4c2J6aXV5c1JVU3lYa2puOTJHWkxtKzY0dkNJaXdocUFZb2l6RjJOSEhHJyxcbiAgICAgICdoUlRONGdRenhyeGdrZVZjaGwrYWc3RGtRVURBTklJVkkrQTYzSmVMSmdXSmlIMWZiWWx3RVNCeUhXK3pCRk50JyxcbiAgICAgICdxU3RqZklPaGpyZk5JYzNSdnNnZ2JEZFdRTGNieG1MWmo0c0IweWRQU2dSS29hVWRSSEpZMFM0dnA5b3VLT3RsJyxcbiAgICAgICcyYXUvUDFCUDNiaEQwZkRYbDkxb2VoZVl0aCtNU21zSkZEZy92Wkp6Q0poRmFROWRwKzJFbmpONWF1TkNOYmFJJyxcbiAgICAgICdiZUZKUkhGZjljaGE4cDNoaCtBSzU0TlJDVCsrQjJNWFlmK1RQd3FYODhqWU1Cdjhrazh2WVVnbzgxMjhyMXpRJyxcbiAgICAgICdFemp2aVFFOUJCZ0JBZ0FKQlFKU1lTOU9BaHN1QUtnSkVFcGpZVHBOYmtDVW5TQUVHUUVDQUFZRkFsSmhMMDRBJyxcbiAgICAgICdDZ2tRNElUM1JHd2dMSmU2b2dRQTJhYUpFSUJJWHRncnMrOFdTSjRrM0RONHJSWGNYYVVaZjY2N3BqZEQ5bkYyJyxcbiAgICAgICczQnpqRkg2Wjc4SklHYXhSSEpkTTdiMDVhRThZdXpNOGYzTklsVDBGME9McS9USTJtdVlVOWYvVTJEUUJ1Zit3JyxcbiAgICAgICdLVEI2MitQRUxWZ2k5TXNYQzFRdi91L28xTFp0bW14VEZGT0QzNXhLc3haWkkyT0pqMnBRcHFPYlcyN004TmxjJyxcbiAgICAgICdCUVFBdzJZQTNmRmMzOHFQSytQWTRyWnlUUmRidmp5eVgrMXplcUlvOHduN1FDUXdYcytPR2FIMmZHb1QzNUFJJyxcbiAgICAgICdTWHVxS2NXcW9FdU83T0JTRUZUaENYQmZVWU1DMDFPcnFLRXN3UG0vVjN6WmtMdTAxcTEyVU13WmFjaDI4UXdLJyxcbiAgICAgICcvWVpseTRpb05EMnRkYXpqMTd1MnJVMmR3dGlIUGUxaU1xR2dWTW9RaXJmTGMraz0nLFxuICAgICAgJz1sdzVlJyxcbiAgICAgICctLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLSddLmpvaW4oJ1xcbicpO1xuXG4gIHZhciBwbGFpbnRleHQgPSAnc2hvcnQgbWVzc2FnZVxcbm5leHQgbGluZVxcbu2VnOq1reyWtC/sobDshKDrp5AnO1xuXG4gIHZhciBrZXkgPSBvcGVucGdwLmtleS5yZWFkQXJtb3JlZChwdWJfa2V5KTtcblxuICB2YXIgZW5jcnlwdGVkID0gb3BlbnBncC5lbmNyeXB0TWVzc2FnZShba2V5XSwgcGxhaW50ZXh0KTtcblxuICB2YXIgbWVzc2FnZSA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChlbmNyeXB0ZWQpO1xuXG4gIHZhciBwcml2S2V5ID0gb3BlbnBncC5rZXkucmVhZEFybW9yZWQocHJpdl9rZXkpO1xuXG4gIC8vIGdldCBrZXkgSURzIHRoZSBtZXNzYWdlIGlzIGVuY3J5cHRlZCBmb3JcbiAgdmFyIGtleWlkcyA9IG1lc3NhZ2UuZ2V0RW5jcnlwdGlvbktleUlkcygpO1xuXG4gIC8vIGRlY3J5cHQgb25seSByZXF1aXJlZCBrZXkgcGFja2V0c1xuICB2YXIgc3VjY2VzcyA9IHByaXZLZXkuZGVjcnlwdEtleVBhY2tldChrZXlpZHMsICdoZWxsbyB3aGF0PycpXG5cbiAgcmVzdWx0LnB1c2gobmV3IHVuaXQucmVzdWx0KCdEZWNyeXB0aW5nIGtleSBwYWNrZXQgd2l0aCB3cm9uZyBwYXNzd29yZCByZXR1cm5zIGZhbHNlJywgIXN1Y2Nlc3MpKTtcblxuICB2YXIgZGVjcnlwdGVkLCBlcnJvcjtcbiAgdHJ5IHtcbiAgICBkZWNyeXB0ZWQgPSBvcGVucGdwLmRlY3J5cHRNZXNzYWdlKHByaXZLZXksIG1lc3NhZ2UpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgZXJyb3IgPSBlO1xuICB9XG4gIHJlc3VsdC5wdXNoKG5ldyB1bml0LnJlc3VsdCgnQ2FsbGluZyBkZWNyeXB0TWVzc2FnZSB3aXRoIG5vdCBkZWNyeXB0ZWQga2V5IHBhY2tldCBsZWFkcyB0byBleGNlcHRpb246IFxcJycgKyAoZXJyb3IgfHwgJycpICsgJ1xcJycsIGVycm9yKSk7XG5cbiAgc3VjY2VzcyA9IHByaXZLZXkuZGVjcnlwdEtleVBhY2tldChrZXlpZHMsICdoZWxsbyB3b3JsZCcpO1xuXG4gIHJlc3VsdC5wdXNoKG5ldyB1bml0LnJlc3VsdCgnRGVjcnlwdGluZyBrZXkgcGFja2V0IHdpdGggY29ycmVjdCBwYXNzd29yZCByZXR1cm5zIHRydWUnLCBzdWNjZXNzKSk7XG5cbiAgZGVjcnlwdGVkID0gb3BlbnBncC5kZWNyeXB0TWVzc2FnZShwcml2S2V5LCBtZXNzYWdlKTtcblxuICByZXN1bHQucHVzaChuZXcgdW5pdC5yZXN1bHQoJ0VuY3J5cHQgcGxhaW4gdGV4dCBhbmQgYWZ0ZXJ3YXJkcyBkZWNyeXB0IGxlYWRzIHRvIHNhbWUgcmVzdWx0JywgcGxhaW50ZXh0ID09IGRlY3J5cHRlZCkpO1xuXG4gIHJldHVybiByZXN1bHQ7XG5cbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJLZXlyaW5nIHRlc3RpbmdcIiwgZnVuY3Rpb24oKSB7XG4gIHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vJyk7XG4gIHZhciBrZXlyaW5nID0gcmVxdWlyZSgnLi4vLi4vc3JjL2tleXJpbmcuanMnKTtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuXG4gIC8vIEV4ZXJjaXNlcyB0aGUgYWJpbGl0eSBvZiBvcGVucGdwX2tleXJpbmcuZ2V0UHVibGljS2V5c0ZvcktleUlkIHRvIHJldHVybiBzdWJrZXlzXG4gIGtleXJpbmcuaW5pdCgpO1xuICBrZXlyaW5nLmltcG9ydFBhY2tldGxpc3QoW1xuICAgICAgICAnLS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICAgJ1ZlcnNpb246IEdudVBHIHYxLjQuMTEgKEdOVS9MaW51eCknLFxuICAgICAgICAnJyxcbiAgICAgICAgJ21RR2lCRkVSdkk0UkJBRDBNL0hHZ2xDdFZOWFBGNzJlaFQ4cmlBWHJsMHJTZWM0UkpDNjFCaCtVQU9oeG41K1UnLFxuICAgICAgICAnZkRnb3M1cDFTcEl6WW1uK004N0pvU1NWTEFqZmFrRmswZ0hnUjlJM2J1N1NJd3EzQmlrazFWdzNnTyt5RFNPNicsXG4gICAgICAgICdUS3BMVUZHWURpQlNTRTFNR2R4QmFkV0xFMWhsUmY1QjJ4NjJnbkdtalNwU1ZibHkzM1BGa29EbXJ3Q2c5ckFwJyxcbiAgICAgICAgJ1JtbmNuRjlHaFdqT0xGa0VvUXc5WXg4RUFPc3h2cThJZzVaMWdrK1pLZkRaZWZ0cEhSZTNGZHJSdGJuaHh2WVknLFxuICAgICAgICAnN3ordzl1ejFFcG9aVXdEUjVHNFgzaFR3SlE3bFhtSU9za2cvK2VSTUxFQXFFWTdiLzd0VzZSYVVKMmQ2RWhzaScsXG4gICAgICAgICdkT1M4OWZJeEVsd2pBT25WT001UzI0ZjBGRFFUVHRvN1FCT294Y05UZmtFSkNIWFNscG9PVW1HQVA4NWZYaDNsJyxcbiAgICAgICAgJ3lQVEdCQUNKZktjNzZVbjNVV0Mxc1dJUkR4WWl5aDNacFp5TkVza29WNkVTVzhqRUkxUm5NbnY1VHJmR0pINUsnLFxuICAgICAgICAnRThqV1g3VFRub0Z5UEp0QlRqbHVjQXRrUWFTNEJiN2RnMUxMamExN3pBcUtOR09KSzJiOWZiMlorbG5UalBpWScsXG4gICAgICAgICdpN0RQSDFYSG5mYUVleGpsaC9VN21ZYTVScndJcGhSeE5pOGdDdXh2ODc0Wk1taEVuN1FXVkdWemRETWdQSFJsJyxcbiAgICAgICAgJ2MzUXpRSFJsYzNRdVkyOXRQb2hpQkJNUkFnQWlCUUpSRWJ5T0Foc0RCZ3NKQ0FjREFnWVZDQUlKQ2dzRUZnSUQnLFxuICAgICAgICAnQVFJZUFRSVhnQUFLQ1JDMHU4TzBNb2EySll4eUFKOU9pMlVsY1VUMFZKTmd3anlsL1ZGOVhjamY5Z0NlSlB2eScsXG4gICAgICAgICdnL2ZwNEVBVThNSklhTjJ5TUk4cExGUzVBYUlFVVJHOG5oRUVBS1ZnZU5EdVlEUHVmTHVKMEdySlYvQ2JYRWpqJyxcbiAgICAgICAgJ2FFUEEwaVRVcVYwblRDUGRBZlEvbm1FM2doNVVsTk1yL3pTSEorYzRGUWhZZExyelJHRE9TelYrbWZQSEgzdCsnLFxuICAgICAgICAnWVZ4K3dhdDBCWXdBQnBIQXRzSXVMSVZvMlJRcVlaWUg4NXRhdHdCa203MUhIVDNqbWxFQXZyNk5GSDM4K3YzcycsXG4gICAgICAgICczdzRXbDAvc2RIeWFlaVNYQUtDeEo0WDFlT2RON0wxcnJiSm96US9nRENGdVZRUC9kY1Y2S3NzczhBdzQ0M2pHJyxcbiAgICAgICAgJ0FZQkxIV2g2bzRHaEFZNi9oMWtpakYweEQrdWMrdE5tVFFuUWkxdEVPb1RlSVpNWG5TUnd0azhYRXVKa2tiQVAnLFxuICAgICAgICAnK3V5dk1neVYzd3JrOXprYVRBaW43bnJqQUVSeGV6Rk9kQkVPdG5CMUNvdkp4dE1uK1JSeGFNRUdwQzRHbkVUeScsXG4gICAgICAgICdONSs2RmtMdUxjTlhpQ1FQNzVhanpPQU4xYUlEL2p1TmpVTnBCYk5wZnFCVjdqMUsrS24wbjlIWVR5UWw5Z2h5JyxcbiAgICAgICAgJzAyNisvNGM4YWcySFYrYmczQkQ3YzJWVFZ1OXhCT0RIc2Z1MHE4UWwvUUI5Vzh0bVl1Z1U2RGVYTUhhZVdQVUgnLFxuICAgICAgICAncGg5OGd1TTlrRjJ5SElpUkJ2QWQ1aTd3T2p3bitJL0lyNm5CUjJ5eEozcDMxQ0RVblVsYmpUUFlnN210UXZIVycsXG4gICAgICAgICdFWTJDcDRTV2lKRUVHQkVDQUFrRkFsRVJ2SjRDR3dJQVVna1F0THZEdERLR3RpVkhJQVFaRVFJQUJnVUNVUkc4JyxcbiAgICAgICAgJ25nQUtDUkFNaU1lUjI5NlkyU2p5QUo5VjN3UkpKMlN6YXpxYWw0a2hXR2ZMdTVSNi93Q2ZRUUlSRDI0eVZkejgnLFxuICAgICAgICAnMmErMmVDcnd5QUxUMkdBaWhBQ2ZTMG5XTTNhMGd0SVRxbmdwSnNSd3MrRXArZUlBbjE1cUQyaXR1dHhOYjhOSScsXG4gICAgICAgICdiUjJnQkI1UW1WSjMnLFxuICAgICAgICAnPXBHQTYnLFxuICAgICAgICAnLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLSdcbiAgICAgICAgXS5qb2luKFwiXFxuXCIpKTtcblxuICB2YXIgbXNnMiA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChbXG4gICAgICAgICctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS0nLFxuICAgICAgICAnVmVyc2lvbjogR251UEcgdjEuNC4xMSAoR05VL0xpbnV4KScsXG4gICAgICAgICcnLFxuICAgICAgICAna0EwREFBSVJESWpIa2R2ZW1Oa0JyQjFpQjJadmJ5NTBlSFJSRWJ6M1ZFVlRWQ0JFUVZSQklERXlNelExTm9oRycsXG4gICAgICAgICdCQUFSQWdBR0JRSlJFYnozQUFvSkVBeUl4NUhiM3BqWjJUY0FuMzJMcERFdUhlOVFyU1JseXZTdVJFS05PRnd6JyxcbiAgICAgICAgJ0FKOXpoNHpzSzRHSVB1RXU4MVlQTm1Ic2p1N0RZZz09JyxcbiAgICAgICAgJz1XYVN4JyxcbiAgICAgICAgJy0tLS0tRU5EIFBHUCBNRVNTQUdFLS0tLS0nXG4gICAgICAgIF0uam9pbihcIlxcblwiKSkucGFja2V0cztcbiAgdmFyIHBhY2tldGxpc3RzID0ga2V5cmluZy5nZXRQYWNrZXRsaXN0c0ZvcktleUlkKG1zZzJbMF0uc2lnbmluZ0tleUlkLndyaXRlKCkpO1xuICB2YXIgcHViS2V5ID0gcGFja2V0bGlzdHNbMF07XG4gIG1zZzJbMl0udmVyaWZ5KHB1YktleVszXSwgbXNnMlsxXSk7XG4gIHJlc3VsdFsyXSA9IG5ldyB1bml0LnJlc3VsdChcIlRlc3Rpbmcga2V5cmluZyBwdWJsaWMgc3Via2V5IHN1cHBvcnRcIixcbiAgICAgICAgICBwYWNrZXRsaXN0cyAhPT0gbnVsbCAmJiBcbiAgICAgICAgICBwYWNrZXRsaXN0cy5sZW5ndGggPT0gMSAmJiBcbiAgICAgICAgICBtc2cyWzJdLnZlcmlmaWVkKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuXG4gXG4iLCJ2YXIgdW5pdCA9IHJlcXVpcmUoJy4uL3VuaXQuanMnKTtcblxudW5pdC5yZWdpc3RlcihcIlBhY2tldCB0ZXN0aW5nXCIsIGZ1bmN0aW9uKCkge1xuXG5cdHZhciBvcGVucGdwID0gcmVxdWlyZSgnLi4vLi4vJyk7XG5cblx0dmFyIGFybW9yZWRfa2V5ID1cblx0XHQnLS0tLS1CRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLVxcbicgK1xuXHRcdCdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpXFxuJyArXG5cdFx0J1xcbicgK1xuXHRcdCdsUUgrQkZGNzlKOEJCQUREaFJVT01VU0dkWU0xS3E5Si92VlMzcUxmYVpId2V5Y0FLbTlTbnBMR0xKRStRYmtpXFxuJyArXG5cdFx0J0pSWExBaHhaK0hnVlRoUjlWWHM4d2JQUjJVWG5EaE1KR2UrVmNNQTBqaXdJT0VBRjB5OU0zWlFzUEZXZ3VlajJcXG4nICtcblx0XHQnMVp5Y2dPd3hZSGVoYktkUHFSSytuRmdGYmh2ZzZmNngyR3QrYTBaYnZpdkdMMUJxU1NHc0wrZGNoUUFSQVFBQlxcbicgK1xuXHRcdCcvZ01EQWlqYXRVTmVVRlpTeWZnMTZ4MzQzLzFKbzZ1MDdMVlRkSDZCY2J4NHlCUWpFSHZsZ2I2bTFlcUVJYloxXFxuJyArXG5cdFx0J2hvbFZ6dDBmU0tUem1seGx0RGFPd0ZMZjdpNDJscU5vV3lmYXFGck9ibEo1QXlzN1ErNnhpSlRCUk9HOXBvK2pcXG4nICtcblx0XHQnWjJBRStoa0JJd0tnaEI2NDVPaWtjaFI0c245RWozaXBlYTV2OSthN1lpbUhsVm1JaXFnTER5Z1F2WGt6WFZhZlxcbicgK1xuXHRcdCdaaTFQMndCN2VVNklmMnhlZVg1R1NSOHJXbytJN3VqbnMwVzhTOVB4QkhsSDNuMW9YVW1GV3NXTFpDWS9xcGtEXFxuJyArXG5cdFx0J0kvRnJvQmhYeEJWUnBRaFFtZHNXUFVkY2dtUVRFajhqblArK2x3U1FleGZnazJRYm9BVzdPRFVBOENsOW95ODdcXG4nICtcblx0XHQnVW9yNXNjaHd3ZEQzb1JvTEdjSlpmUjZEeXU5ZENZZFFTRFdqK0lRczk1aEpRZkhOY2ZqN1hGdFR5T2k3S3h4MFxcbicgK1xuXHRcdCdKeGlvOURlODRRbnhOQW9OWXVMdHdrYVJna1VWS1ZwaDJuWVdKZkFKdW51TU1vc00yV2RjaWRISjVkNlJJZHhCXFxuJyArXG5cdFx0J1U2bzNUK2Q4QlBYdVJRRVpIOStGa0RrYjRpaGFrS08zK1pjb244NWUxWlVVdEIxUVlYUnlhV05ySUR4d1lYUnlcXG4nICtcblx0XHQnYVdOclFHVjRZVzF3YkdVdVkyOXRQb2k1QkJNQkFnQWpCUUpSZS9TZkFoc0RCd3NKQ0FjREFnRUdGUWdDQ1FvTFxcbicgK1xuXHRcdCdCQllDQXdFQ0hnRUNGNEFBQ2drUU9ibGlTZE0vR0VKYmpnUC9mZmVpNGxVNmZYcDhRdTB1Yk5IaDRBNnN3a1RPXFxuJyArXG5cdFx0J2Izc3V1QkVMRTRBMi9wSzVZblc1eUJ5RkZTaTRrcThiSnA1TzZwOXlkWHBPQTM4dDNhUTh3cmJvMHlEdkdla3JcXG4nICtcblx0XHQnMVMxSFdPTGdDYVk3ckVEUXVidUNPSGQyUjgxL1ZRT0p5RzN6Z1g0S0ZJZ2tWeVY5QlpYVXB6NFBYdWhNT1JtdlxcbicgK1xuXHRcdCc4MXV6ZWo5cjdCWWtKNkdkQWY0RVVYdjBud0VFQUtiTzAyanRHRUhldDJmUWZrQVl5Tys3ODlzVHh5ZnJVeTV5XFxuJyArXG5cdFx0J1NBZjVuM0dna3VpSHo4ZEZldmhncVl5TUswT1lFT0NacWRkMWxSQmpMNlVzN1B4VGxqSGMyanRHaG9BZ0U0YVpcXG4nICtcblx0XHQnTEthckkzais1T29mY2FxMCtTMGJocWlRNWhsNkM0U2tkWU9FZUowSGxxMjAwOG4wcEpJbFU0RTV5SXUwb052YlxcbicgK1xuXHRcdCc0KzRvd1RwUkFCRUJBQUgrQXdNQ0tOcTFRMTVRVmxMSnlldUdCRUErN25YUzNhU3k2bUU0bFI1ZjNNbDVOUnF0XFxuJyArXG5cdFx0J2ptNlErVVVJNjlEemhMR1g0akhSeG5hNk5NUDc0UzNDZ2hPejllQ2hNbmRrZldMQy9jMTFoMW5wekxjaStBd0pcXG4nICtcblx0XHQnNDV4TWJ3L09XNVBMbGF4ZHRrZy9TbnNIcEZHQ0F1VFVXWTg3a3VXb0cwSFNWTW45Q2xtKzY3cmRpY09XNkw1YVxcbicgK1xuXHRcdCdDaGZ5V2NWWitIdndqeDhZTTAvajExSWY3b1VrQ1pFc3RTVWVKWU9JMTBKUUxoTkxwRGRrQjg5dlhoQU1hQ3VVXFxuJyArXG5cdFx0J0lqaGRxMHZ2Smk2SnJ1S1FHUEsramFqSjRNTWFubnBRdEtBdnQ4YWlmcXBkb3ZZeTh3NHloMnBHa2FkRnZyc1pcXG4nICtcblx0XHQnbXhwanFtbWF3YWI2emxPVzVXckx4UVZMMWNRUmRySVE3all0dUxBcEdXa1BmeXRTQ0JaMjBwU3lXbm1reGQ0WFxcbicgK1xuXHRcdCdPSW1zNkJqcXJQOUx4QkVYc1BCd2RVQTVJcmFucitVQklQRHhRclRwNWswREpoWEJDcEoxazNaVCsyZHhpUlMyXFxuJyArXG5cdFx0J3NrODN3MlZVQm5YZFlXWngwWWxNcXIzYkRUNko1Zk8rOFY4cGJnWTVCa0hSQ0ZNYWNGeDQ1a20vZnZtSW53UVlcXG4nICtcblx0XHQnQVFJQUNRVUNVWHYwbndJYkRBQUtDUkE1dVdKSjB6OFlRcWIzQS85N25qTGwzM09RWVhWcDlPVGsvVmdFNk8rd1xcbicgK1xuXHRcdCdvU1lhKzZ4TU96c2s3dGx1TElSUXRuSXByZ2EvZTh2RVpYR1RvbVYyYTc3SEJrc2crWWpsVGgvbDhvTXVhb3hHXFxuJyArXG5cdFx0J1FOa01wb1JKS1BpcDI5UlRXNGdMZG5vSlZla1ovYXdrQk4yUzNOTUFyT1pHY2E4VStNMUl1VjdPeVZjaFNWU2xcXG4nICtcblx0XHQnWVJsY2k3MkdIaGx5b3M4WUhBPT1cXG4nICtcblx0XHQnPUtYa2pcXG4nICtcblx0XHQnLS0tLS1FTkQgUEdQIFBSSVZBVEUgS0VZIEJMT0NLLS0tLS0nO1xuXG5cblx0dmFyIHRlc3RzID0gW2Z1bmN0aW9uKCkge1xuXHRcdHZhciBtZXNzYWdlID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblxuXHRcdHZhciBsaXRlcmFsID0gbmV3IG9wZW5wZ3AucGFja2V0LmxpdGVyYWwoKTtcblx0XHRsaXRlcmFsLnNldCgnSGVsbG8gd29ybGQnLCAndXRmOCcpO1xuXHRcdFxuXHRcdHZhciBlbmMgPSBuZXcgb3BlbnBncC5wYWNrZXQuc3ltbWV0cmljYWxseV9lbmNyeXB0ZWQoKTtcblx0XHRtZXNzYWdlLnB1c2goZW5jKTtcblx0XHRlbmMucGFja2V0cy5wdXNoKGxpdGVyYWwpO1xuXG5cdFx0dmFyIGtleSA9ICcxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMicsXG5cdFx0XHRhbGdvID0gJ2FlczI1Nic7XG5cblx0XHRlbmMuZW5jcnlwdChhbGdvLCBrZXkpO1xuXG5cblxuXHRcdHZhciBtc2cyID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRtc2cyLnJlYWQobWVzc2FnZS53cml0ZSgpKTtcblxuXHRcdG1zZzJbMF0uZGVjcnlwdChhbGdvLCBrZXkpO1xuXG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnU3ltbWV0cmljYWxseSBlbmNyeXB0ZWQgcGFja2V0JywgXG5cdFx0XHRtc2cyWzBdLnBhY2tldHNbMF0uZGF0YSA9PSBsaXRlcmFsLmRhdGEpO1xuXG5cdH0sIGZ1bmN0aW9uKCkge1xuXHRcdHZhciBrZXkgPSAnMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTInLFxuXHRcdFx0YWxnbyA9ICdhZXMyNTYnO1xuXG5cdFx0dmFyIGxpdGVyYWwgPSBuZXcgb3BlbnBncC5wYWNrZXQubGl0ZXJhbCgpLFxuXHRcdFx0ZW5jID0gbmV3IG9wZW5wZ3AucGFja2V0LnN5bV9lbmNyeXB0ZWRfaW50ZWdyaXR5X3Byb3RlY3RlZCgpLFxuXHRcdFx0bXNnID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblxuXHRcdG1zZy5wdXNoKGVuYyk7XG5cdFx0bGl0ZXJhbC5zZXQoJ0hlbGxvIHdvcmxkIScsICd1dGY4Jyk7XG5cdFx0ZW5jLnBhY2tldHMucHVzaChsaXRlcmFsKTtcblx0XHRlbmMuZW5jcnlwdChhbGdvLCBrZXkpO1xuXHRcdFxuXG5cblx0XHR2YXIgbXNnMiA9IG5ldyBvcGVucGdwLnBhY2tldC5saXN0KCk7XG5cdFx0bXNnMi5yZWFkKG1zZy53cml0ZSgpKTtcblxuXHRcdG1zZzJbMF0uZGVjcnlwdChhbGdvLCBrZXkpO1xuXG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnU3ltLiBlbmNyeXB0ZWQgaW50ZWdyaXR5IHByb3RlY3RlZCBwYWNrZXQnLCBcblx0XHRcdG1zZzJbMF0ucGFja2V0c1swXS5kYXRhID09IGxpdGVyYWwuZGF0YSk7XG5cdFxuXHR9LCBmdW5jdGlvbigpIHtcblx0XHRcdFxuXHRcdHZhciBtc2cgPSBcblx0XHRcdCctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS1cXG4nICtcblx0XHRcdCdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpXFxuJyArXG5cdFx0XHQnXFxuJyArXG5cdFx0XHQnakEwRUNRTUNwbzdJOFdxc2ViVEowa29CbW02L29xZEhYSlU5YVBlK1BvK25rL2s0L1BackxtbFh3ejJsaHFCZ1xcbicgK1xuXHRcdFx0J0dBbFk5cnhWU3RMQnJnMEhuKzVna2h5SEk5Qjg1ck0xQkVZWFE4cFA1Q1NGdVR3YkozTzJzNjdkelE9PVxcbicgK1xuXHRcdFx0Jz1WWjAvXFxuJyArXG5cdFx0XHQnLS0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLSc7XG5cblxuXG5cdFx0dmFyIG1zZ2J5dGVzID0gb3BlbnBncC5hcm1vci5kZWNvZGUobXNnKS5kYXRhO1xuXG5cdFx0dmFyIHBhcnNlZCA9IG5ldyBvcGVucGdwLnBhY2tldC5saXN0KCk7XG5cdFx0cGFyc2VkLnJlYWQobXNnYnl0ZXMpO1xuXG5cdFx0cGFyc2VkWzBdLmRlY3J5cHQoJ3Rlc3QnKTtcblxuXHRcdHZhciBrZXkgPSBwYXJzZWRbMF0uc2Vzc2lvbktleTtcblx0XHRwYXJzZWRbMV0uZGVjcnlwdChwYXJzZWRbMF0uc2Vzc2lvbktleUFsZ29yaXRobSwga2V5KTtcblx0XHR2YXIgY29tcHJlc3NlZCA9IHBhcnNlZFsxXS5wYWNrZXRzWzBdO1xuXG5cdFx0dmFyIHJlc3VsdCA9IGNvbXByZXNzZWQucGFja2V0c1swXS5kYXRhO1xuXG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnU3ltIGVuY3J5cHRlZCBzZXNzaW9uIGtleSB3aXRoIGEgY29tcHJlc3NlZCBwYWNrZXQnLFxuXHRcdFx0cmVzdWx0ID09ICdIZWxsbyB3b3JsZCFcXG4nKTtcblxuXHR9LCBmdW5jdGlvbigpIHtcblx0XG5cdFx0dmFyIHJzYSA9IG5ldyBvcGVucGdwLmNyeXB0by5wdWJsaWNLZXkucnNhKCksXG5cdFx0XHRtcGkgPSByc2EuZ2VuZXJhdGUoNTEyLCBcIjEwMDAxXCIpXG5cblx0XHR2YXIgbXBpID0gW21waS5uLCBtcGkuZWUsIG1waS5kLCBtcGkucCwgbXBpLnEsIG1waS51XTtcblxuXHRcdG1waSA9IG1waS5tYXAoZnVuY3Rpb24oaykge1xuXHRcdFx0XHR2YXIgbXBpID0gbmV3IG9wZW5wZ3AubXBpKCk7XG5cdFx0XHRcdG1waS5mcm9tQmlnSW50ZWdlcihrKTtcblx0XHRcdFx0cmV0dXJuIG1waTtcblx0XHR9KTtcblxuXHRcdHZhciBlbmMgPSBuZXcgb3BlbnBncC5wYWNrZXQucHVibGljX2tleV9lbmNyeXB0ZWRfc2Vzc2lvbl9rZXkoKSxcblx0XHRcdG1zZyA9IG5ldyBvcGVucGdwLnBhY2tldC5saXN0KCksXG5cdFx0XHRtc2cyID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblxuXHRcdGVuYy5zZXNzaW9uS2V5ID0gJzEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyJztcblx0XHRlbmMucHVibGljS2V5QWxnb3JpdGhtID0gJ3JzYV9lbmNyeXB0Jztcblx0XHRlbmMuc2Vzc2lvbktleUFsZ29yaXRobSA9ICdhZXMyNTYnO1xuXHRcdGVuYy5wdWJsaWNLZXlJZC5ieXRlcyA9ICcxMjM0NTY3OCc7XG5cdFx0ZW5jLmVuY3J5cHQoeyBtcGk6IG1waSB9KTtcblxuXHRcdG1zZy5wdXNoKGVuYyk7XG5cblx0XHRtc2cyLnJlYWQobXNnLndyaXRlKCkpO1xuXG5cdFx0bXNnMlswXS5kZWNyeXB0KHsgbXBpOiBtcGkgfSk7XG5cblx0XHRyZXR1cm4gbmV3IHVuaXQucmVzdWx0KCdQdWJsaWMga2V5IGVuY3J5cHRlZCBzeW1tZXRyaWMga2V5IHBhY2tldCcsIFxuXHRcdFx0bXNnMlswXS5zZXNzaW9uS2V5ID09IGVuYy5zZXNzaW9uS2V5ICYmXG5cdFx0XHRtc2cyWzBdLnNlc3Npb25LZXlBbGdvcml0aG0gPT0gZW5jLnNlc3Npb25LZXlBbGdvcml0aG0pO1xuXHR9LCBmdW5jdGlvbigpIHtcblx0XHR2YXIgYXJtb3JlZF9rZXkgPSBcblx0XHRcdCctLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tXFxuJyArXG5cdFx0XHQnVmVyc2lvbjogR251UEcgdjIuMC4xOSAoR05VL0xpbnV4KVxcbicgK1xuXHRcdFx0J1xcbicgK1xuXHRcdFx0J2xRSFlCRkYzM2lNQkJBQzlZZk9ZYWhKbFdyVmoySjFUalFpWkx1bldsakk0RzllNkFSVHlEOTluZk9rVjNzd2hcXG4nICtcblx0XHRcdCcwV2FPc2U0VXRqN0JmVHFkWWNvZXpoQ2FRcHVFeFV1cEtXWnFtZHVCY3dTbUVCZk51MVh5S2N4bERRdXVrMFZrXFxuJyArXG5cdFx0XHQndmlHQzNrRlJjZS9jSmFLVkZTUlU4VjV6UGd0NktRTnYvd056N3lkRWlzYVNvTmJrNTF2UXQ1b0dmd0FSQVFBQlxcbicgK1xuXHRcdFx0J0FBUDVBVkw4eFdNdUtnTGo5Zzcvd2Z0TUgrak83dmhBeGplMlczWSs4cjhUbk9TbjA1MzZsUXZ6bC9lUXllTENcXG4nICtcblx0XHRcdCdWSzJrMys3K3RyZ083STRLdVhDWFpxZ0FiRWkzbmlEWVhEYUNKKzhnZFI5cXZQTTJnaTlOTTcxVEdYWnZHRTB3XFxuJyArXG5cdFx0XHQnWDhnSVpmcUxUUVdLbTlUSVMvM3RkcnRoNG53aGl5ZTBBU3ljaE9ib0lpTjZWSUVDQU1iQ1E0L25veEdWNnlUS1xcbicgK1xuXHRcdFx0J1ZlenNHU3oraUNNeHoybFYyNzAvQWMyQzVXUGsrT2x4WGxveFVYZUVrR0lyNlhrbWhocGNlZWQyS0w0MVVDOFlcXG4nICtcblx0XHRcdCd3NXR0R0lFQ0FQUHNhaG5pS0d5cXA5Q0h5NlcwQjgzeWhoY0libUxsYVZHMmZ0S3lVRUR4SWdnek9sWHVWcnVlXFxuJyArXG5cdFx0XHQnejlYUmQ2d0Zxd0RkMVFNRlcwdVV5SFBEQ0lGUG52OENBSmFERlNadXR1V2RXTXQxNU5aWGpmZ1JnZkp1RHJ0dlxcbicgK1xuXHRcdFx0J0U3eUZZL3AwZWw4bENpaE9UOFdvSGJUbjFQYkNZTXpOQmMwSWhIYVpLQXRBMnBqa0Urd3p6OUNsUDdRYlIyVnZcXG4nICtcblx0XHRcdCdjbWRsSUR4blpXOXlaMlZBWlhoaGJYQnNaUzVqYjIwK2lMa0VFd0VDQUNNRkFsRjMzaU1DR3dNSEN3a0lCd01DXFxuJyArXG5cdFx0XHQnQVFZVkNBSUpDZ3NFRmdJREFRSWVBUUlYZ0FBS0NSQmNxczM2ZndKQ1hSYnZBLzlMUGlLNldGS2NGb05CbkxFSlxcbicgK1xuXHRcdFx0J21TL0NOa0w4eVRwa3NscENQNitUd0pNYzh1WHF3WWw5L1BXMitDd216WmpzNkpzdlR6TWNSL1piZlpKdVNXNllcXG4nICtcblx0XHRcdCdFc0xOZWpzU3BnY1k5YWlld0d0RSs1M2U1b0tZbmxtVk1UV09QeXdjaUlnTXZYbHpkR2h4Y3dxSjh1MGhUK3VnXFxuJyArXG5cdFx0XHQnOUNqY0FmdVg5eXc4NUx3WHRkR3dOaDdKOFE9PVxcbicgK1xuXHRcdFx0Jz1sS2lTXFxuJyArXG5cdFx0XHQnLS0tLS1FTkQgUEdQIFBSSVZBVEUgS0VZIEJMT0NLLS0tLS0nO1xuXG5cdFx0a2V5ID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRrZXkucmVhZChvcGVucGdwLmFybW9yLmRlY29kZShhcm1vcmVkX2tleSkuZGF0YSk7XG5cdFx0a2V5ID0ga2V5WzBdO1xuXG5cdFx0dmFyIGVuYyA9IG5ldyBvcGVucGdwLnBhY2tldC5wdWJsaWNfa2V5X2VuY3J5cHRlZF9zZXNzaW9uX2tleSgpLFxuXHRcdFx0c2VjcmV0ID0gJzEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyJztcblxuXHRcdGVuYy5zZXNzaW9uS2V5ID0gc2VjcmV0O1xuXHRcdGVuYy5wdWJsaWNLZXlBbGdvcml0aG0gPSAncnNhX2VuY3J5cHQnO1xuXHRcdGVuYy5zZXNzaW9uS2V5QWxnb3JpdGhtID0gJ2FlczI1Nic7XG5cdFx0ZW5jLnB1YmxpY0tleUlkLmJ5dGVzID0gJzEyMzQ1Njc4JztcblxuXHRcdGVuYy5lbmNyeXB0KGtleSk7XG5cblx0XHRlbmMuZGVjcnlwdChrZXkpO1xuXG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnU2VjcmV0IGtleSBwYWNrZXQgKHJlYWRpbmcsIHVuZW5jcnB0ZWQpJyxcblx0XHRcdGVuYy5zZXNzaW9uS2V5ID09IHNlY3JldCk7XG5cdH0sIGZ1bmN0aW9uKCkge1xuXG5cdFx0dmFyIGFybW9yZWRfa2V5ID1cblx0XHRcdCctLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tXFxuJyArXG5cdFx0XHQnVmVyc2lvbjogR251UEcgdjIuMC4xOSAoR05VL0xpbnV4KVxcbicgK1xuXHRcdFx0J1xcbicgK1xuXHRcdFx0J2xRSFlCRkY2Z3RrQkJBREtVT1daSzYvVjc1TU53QlMraExZaWNvUzBTb2pibzNxV1hYcFM3ZU0rdWhpRG00YlBcXG4nICtcblx0XHRcdCdETmpkTlZBMFIrVENqdmhXYmMzVzZjdmRIWVRtSFJNaFRJT2VmbmNaUnQzT3dGN0F2Vms1M2ZLS1BpTk52NUM5XFxuJyArXG5cdFx0XHQnSUs4YmNEaEFrblNPZzFUWFJTcFhMSHRZeTM2QTZpRGdmZk5Tam9DT1ZhZUtwdVJETUEzN1B2SldGUUFSQVFBQlxcbicgK1xuXHRcdFx0J0FBUCtLeEhiT3djcm5QUHVYcHBDWUVldzNYYjdMTVdFU3B2TUZGZ3NteHgxQ096Rm5MamVrMVAxRSt5T1dUN25cXG4nICtcblx0XHRcdCc0b3Bjc0V1YWF6TGsrVHJZU01PdVI2TzZEZ0dnNWMrY3RWUFUrTkdOTkNpaVRrT3p1RCs4b3c4Tmdzb0lOT3hpXFxuJyArXG5cdFx0XHQnNDgxcUxLME5ZcGM1c0VnMzk0SjNmUnV6cGZFaTZEVFMvUnpDTjdZRGlHRmNjTkVDQU03MU51YUF6SDVMclorQlxcbicgK1xuXHRcdFx0JzRPa3d5OUNRUWJnb1lyZGFpYTI0Q2pFYVVPRGFST255TnN2T2IweWRFZWJWQWJHenJzQnI2THJpc1RpZHlac0dcXG4nICtcblx0XHRcdCd0MlQrTDdFQ0FQcENGelpJd3drNmdpWjEwSG1YRWhYWkxYWW1kaFFELzFmd2VncFRyRWNpTUE2TUNjZGtjQ3lPXFxuJyArXG5cdFx0XHQnMi9KK1MrTlhNNjJ5a01HRGhnMmNqaFUxcmovdWFhVUNBSmZDamt3cHhNc0RLSFlERkRYeWpKRnkydkVtQTNzOFxcbicgK1xuXHRcdFx0J2NubUFVREYxY2FQeUVjUEVabVlKUkUrS2Ryb09ENklHaHpwN29BMzRFZjNENkhPQ292SDlZYUNnYmJRYlNtOW9cXG4nICtcblx0XHRcdCdibTU1SUR4cWIyaHVibmxBWlhoaGJYQnNaUzVqYjIwK2lMa0VFd0VDQUNNRkFsRjZndGtDR3dNSEN3a0lCd01DXFxuJyArXG5cdFx0XHQnQVFZVkNBSUpDZ3NFRmdJREFRSWVBUUlYZ0FBS0NSQTZIVE04eVAwOGtlWmdBLzR2TDI3M3pycW5tT3JxbW8vS1xcbicgK1xuXHRcdFx0J1V4UWdEMHZNaE01OGQyNVVqR1lJNkxBWmtBbHMvazRGdkZ0NUdVSFZXSlIzSEJSdXVObEI3VW5kSC91WWxVN2pcXG4nICtcblx0XHRcdCdtL2JRTGlQNHV2RlF1Ukd1Rzc2ZjBPNXQvS3llVWR6cnBOaUpwZTh0WURBbm9QeFV6RU5Zc0l2MGZtMlpJU28xXFxuJyArXG5cdFx0XHQnUW5uWFgyV3VWWkdNWkgxWWhRb2FrWnhibnAwQjJBUlJlb0xaQVFRQXZRdlBwMk1MdTl2blJ2WjNQeTU1OWtRZlxcbicgK1xuXHRcdFx0JzBaNUFuRVhWb2tBTFRuNUEybTUxZExla1E5VDNSaHo4cDlJNkMvWGpWUXdCa3AxVVNPYURVeitMN2xzYk5kWTRcXG4nICtcblx0XHRcdCdZYlVpM2VJQTVSSW1WWGVUSXJEMWhFNENsbEROS21xVDV3Rk4wN2VFdTdRaERFdVlpb08rNGd0ampoVURZZUlBXFxuJyArXG5cdFx0XHQnZENWdFZPLy9xOHJQOHVrWkVjOEFFUUVBQVFBRC9SSGx0dHlOZTNSbkRyL0FvS3g2SFhETHBVbUdsbTVWRERNbVxcbicgK1xuXHRcdFx0J3BndGgxNGoyY1NkQ0pZcUlkSHFPVHZzaVkzMXpZM2pQUUt6ZE9UZ0huc0k0WDJxSzlJbmJ3WGVwU0JrYU9KellcXG4nICtcblx0XHRcdCdpTmhpZlBTVXM5cW9OYXdEcWJGSjhQTVhkNFFRR2dNOTN3K3R1ZEtDNjUwWnVxN003ZVdTZFFnMHU5YW9MWTk3XFxuJyArXG5cdFx0XHQnTXBLeDNEVUZBZ0RBL1Jnb084eFlNZ2tLTjF0dUtXYTYxcWVzTGRKUkFaSS8zY252dHNtbUVCdDl0ZGJjRG9CelxcbicgK1xuXHRcdFx0J2dPSUFBdlVGZ2lwdVA2ZEJXTHlmMk5STlJWVlFkTlRsQWdENnhTN1M4N2cza1RhM0dMY0VJMmN2ZWFQMVdXTktcXG4nICtcblx0XHRcdCdyS0ZuVldzakJLQXJLRnpNUTVONkZNbkZENFQ5Nmkzc1lsQUNFNVVqSDkwU3BPZ0JLT3BkS3pTakFmOW5naHJ3XFxuJyArXG5cdFx0XHQna2JGYkY3MDhaSXBWRXd4dnAvSm9TdXRZVVE0djAxTUltbkNHcXpEVnVTZWYzZXV0TEx1NFpHN2tMZWt4TmF1VlxcbicgK1xuXHRcdFx0Jzh0R0Z3eHNkdHYzMFJMLzNuVytJbndRWUFRSUFDUVVDVVhxQzJRSWJEQUFLQ1JBNkhUTTh5UDA4a1JYakJBQ3VcXG4nICtcblx0XHRcdCdSdEV3alUrcDZxcW0zcG1oN3h6MUN6aFFOMUY3Vk9qOWRGVWVFQ0pKMWl2OEo3MXc1VUlOSDBvdEljZWVCZVd5XFxuJyArXG5cdFx0XHQnTkxBL1F2SzgrNC9iOVFXK1M4YURaeWVacFlnMzdnQndkVE5HTlQ3VHNFQXh6OVNVYng5dVJqYTB3Tm10YjV4V1xcbicgK1xuXHRcdFx0J21HK1ZFOENCWE5rcDhKVFd4MDVBSHd0SzNiYVdsSFd3cHduUmxiVTk0UT09XFxuJyArXG5cdFx0XHQnPUZTd0FcXG4nICtcblx0XHRcdCctLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLSc7XG5cblx0XHR2YXIgYXJtb3JlZF9tc2cgPSBcblx0XHRcdCctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS1cXG4nICtcblx0XHRcdCdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpXFxuJyArXG5cdFx0XHQnXFxuJyArXG5cdFx0XHQnaEl3REZZRVQrN2JmeC9BQkEvOTVVYzk5NDJUZzhvcXBPMHZFdTJlU0t3UEFMTTNhMERyVmRBaUZPSUsvZEptWlxcbicgK1xuXHRcdFx0J1lydFBSdzNFRXdIWmpsNkNPOVJEKzk1aUUyN3RQYnNJQ3cxSzQzZ29mU1Yvd1dzUE82dnZzM2VmdFFZSFN4eGFcXG4nICtcblx0XHRcdCdJUWJUUEltaVJhSjczTWY3aU0zQ050UU00aVVCc3gxSG5VR2wrcnREMG56M2ZMbTZpM0Nqd2lOUVdXNDJJOUpIXFxuJyArXG5cdFx0XHQnQVd2OEV2dnB4WjhYMkNsRmZTVzNVVkJvUk9IZTlDQVdITS80MG5HdXRBWks4TUlnbVVJNHhxa0xGQmJxcVR5eFxcbicgK1xuXHRcdFx0Jy9jRFNDNFErc3Y2NVVYNHVyYmZjN3VKdWsxQ3BqNTQ9XFxuJyArXG5cdFx0XHQnPWlTYUtcXG4nICtcblx0XHRcdCctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJztcblxuXG5cdFx0dmFyIGtleSA9IG5ldyBvcGVucGdwLnBhY2tldC5saXN0KCk7XG5cdFx0a2V5LnJlYWQob3BlbnBncC5hcm1vci5kZWNvZGUoYXJtb3JlZF9rZXkpLmRhdGEpO1xuXHRcdGtleSA9IGtleVszXTtcblxuXHRcdHZhciBtc2cgPSBuZXcgb3BlbnBncC5wYWNrZXQubGlzdCgpO1xuXHRcdG1zZy5yZWFkKG9wZW5wZ3AuYXJtb3IuZGVjb2RlKGFybW9yZWRfbXNnKS5kYXRhKTtcblxuXHRcdG1zZ1swXS5kZWNyeXB0KGtleSk7XG5cdFx0bXNnWzFdLmRlY3J5cHQobXNnWzBdLnNlc3Npb25LZXlBbGdvcml0aG0sIG1zZ1swXS5zZXNzaW9uS2V5KTtcblxuXHRcdHZhciB0ZXh0ID0gbXNnWzFdLnBhY2tldHNbMF0ucGFja2V0c1swXS5kYXRhO1xuXG5cblx0XHRyZXR1cm4gbmV3IHVuaXQucmVzdWx0KCdQdWJsaWMga2V5IGVuY3J5cHRlZCBwYWNrZXQgKHJlYWRpbmcsIEdQRyknLFxuXHRcdFx0dGV4dCA9PSAnSGVsbG8gd29ybGQhJyk7XG5cdH0sIGZ1bmN0aW9uKCkge1xuXG5cdFx0dmFyIHBhc3NwaHJhc2UgPSAnaGVsbG8nLFxuXHRcdFx0YWxnbyA9ICdhZXMyNTYnO1xuXG5cdFx0dmFyIGxpdGVyYWwgPSBuZXcgb3BlbnBncC5wYWNrZXQubGl0ZXJhbCgpLFxuXHRcdFx0a2V5X2VuYyA9IG5ldyBvcGVucGdwLnBhY2tldC5zeW1fZW5jcnlwdGVkX3Nlc3Npb25fa2V5KCksXG5cdFx0XHRlbmMgPSBuZXcgb3BlbnBncC5wYWNrZXQuc3ltX2VuY3J5cHRlZF9pbnRlZ3JpdHlfcHJvdGVjdGVkKCksXG5cdFx0XHRtc2cgPSBuZXcgb3BlbnBncC5wYWNrZXQubGlzdCgpO1xuXG5cdFx0bXNnLnB1c2goa2V5X2VuYyk7XG5cdFx0bXNnLnB1c2goZW5jKTtcblxuXHRcdGtleV9lbmMuc2Vzc2lvbktleUFsZ29yaXRobSA9IGFsZ287XG5cdFx0a2V5X2VuYy5kZWNyeXB0KHBhc3NwaHJhc2UpO1xuXG5cdFx0dmFyIGtleSA9IGtleV9lbmMuc2Vzc2lvbktleTtcblxuXHRcdGxpdGVyYWwuc2V0KCdIZWxsbyB3b3JsZCEnLCAndXRmOCcpO1xuXHRcdGVuYy5wYWNrZXRzLnB1c2gobGl0ZXJhbCk7XG5cdFx0ZW5jLmVuY3J5cHQoYWxnbywga2V5KTtcblxuXG5cdFx0dmFyIG1zZzIgPSBuZXcgb3BlbnBncC5wYWNrZXQubGlzdCgpO1xuXHRcdG1zZzIucmVhZChtc2cud3JpdGUoKSk7XG5cblx0XHRtc2cyWzBdLmRlY3J5cHQocGFzc3BocmFzZSk7XG5cdFx0dmFyIGtleTIgPSBtc2cyWzBdLnNlc3Npb25LZXk7XG5cdFx0bXNnMlsxXS5kZWNyeXB0KG1zZzJbMF0uc2Vzc2lvbktleUFsZ29yaXRobSwga2V5Mik7XG5cblxuXHRcdHJldHVybiBuZXcgdW5pdC5yZXN1bHQoJ1N5bSBlbmNyeXB0ZWQgc2Vzc2lvbiBrZXkgcmVhZGluZy93cml0aW5nJywgXG5cdFx0XHRtc2cyWzFdLnBhY2tldHNbMF0uZGF0YSA9PSBsaXRlcmFsLmRhdGEpO1xuXHRcblx0fSwgZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGFybW9yZWRfbXNnID0gXG5cdFx0XHQnLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tXFxuJyArXG5cdFx0XHQnVmVyc2lvbjogR251UEcgdjIuMC4xOSAoR05VL0xpbnV4KVxcbicgK1xuXHRcdFx0J1xcbicgK1xuXHRcdFx0J2hJd0Q5NUQ5YUhTNWZ4RUJBLzk4Q3dINTRYWm13b2JPbUhVY3ZXY0REUXlzQkVDNHVmN3dBU2lHY1JiZWpEYU9cXG4nICtcblx0XHRcdCdhSnFjcksvM2s4c0JRTU83eU9odnJDUnFxcEdEcW5teDdJYWFLTG5aUzduWUFab0hFc0s5VXlHMGhEYThDZmJvXFxuJyArXG5cdFx0XHQnQ1A0eFpWY2dJdklmQVcvaW4xTGVUMnRkMFFjUU5iZWV3Qm1QZWErdlFFRXZSZ0lQMTB0bEU3TUs4QXk0OGRKSFxcbicgK1xuXHRcdFx0J0FhZ01nTllnN01CVWpwdU9DVnJqTTFwV2phOHV6YlVMZlloVHEzSUo4SDNRaGJkVCtrOWtoWTlmMGFKUEVlWWlcXG4nICtcblx0XHRcdCdkVnY2REs5dXZpTUdjL0RzVkN3NUs4bFFSTGxrY0hjPVxcbicgK1xuXHRcdFx0Jz1wUitDXFxuJyArXG5cdFx0XHQnLS0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLSc7XG5cblx0XHR2YXIga2V5ID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRrZXkucmVhZChvcGVucGdwLmFybW9yLmRlY29kZShhcm1vcmVkX2tleSkuZGF0YSk7XG5cdFx0a2V5ID0ga2V5WzNdO1xuXHRcdGtleS5kZWNyeXB0KCd0ZXN0Jyk7XG5cblx0XHR2YXIgbXNnID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRtc2cucmVhZChvcGVucGdwLmFybW9yLmRlY29kZShhcm1vcmVkX21zZykuZGF0YSk7XG5cblx0XHRtc2dbMF0uZGVjcnlwdChrZXkpO1xuXHRcdG1zZ1sxXS5kZWNyeXB0KG1zZ1swXS5zZXNzaW9uS2V5QWxnb3JpdGhtLCBtc2dbMF0uc2Vzc2lvbktleSk7XG5cblx0XHR2YXIgdGV4dCA9IG1zZ1sxXS5wYWNrZXRzWzBdLnBhY2tldHNbMF0uZGF0YTtcblxuXG5cblx0XHRyZXR1cm4gbmV3IHVuaXQucmVzdWx0KCdTZWNyZXQga2V5IGVuY3J5cHRpb24vZGVjcnlwdGlvbiB0ZXN0Jyxcblx0XHRcdHRleHQgPT0gJ0hlbGxvIHdvcmxkIScpO1xuXHR9LCBmdW5jdGlvbigpIHtcblx0XG5cblx0XHR2YXIga2V5ID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRrZXkucmVhZChvcGVucGdwLmFybW9yLmRlY29kZShhcm1vcmVkX2tleSkuZGF0YSk7XG5cblxuXHRcdHZhciB2ZXJpZmllZCA9IGtleVsyXS52ZXJpZnkoa2V5WzBdLFxuXHRcdFx0e1xuXHRcdFx0XHR1c2VyaWQ6IGtleVsxXSxcblx0XHRcdFx0a2V5OiBrZXlbMF1cblx0XHRcdH0pO1xuXG5cdFx0dmVyaWZpZWQgPSB2ZXJpZmllZCAmJiBrZXlbNF0udmVyaWZ5KGtleVswXSxcblx0XHRcdHtcblx0XHRcdFx0a2V5OiBrZXlbMF0sXG5cdFx0XHRcdGJpbmQ6IGtleVszXSxcblx0XHRcdH0pXG5cblxuXHRcdHJldHVybiBuZXcgdW5pdC5yZXN1bHQoJ1NlY3JldCBrZXkgcmVhZGluZyB3aXRoIHNpZ25hdHVyZSB2ZXJpZmljYXRpb24uJyxcblx0XHRcdHZlcmlmaWVkID09IHRydWUpO1xuXHR9LCBmdW5jdGlvbigpIHtcblxuXHRcdHZhciBhcm1vcmVkX21zZyA9IFxuXHRcdFx0Jy0tLS0tQkVHSU4gUEdQIE1FU1NBR0UtLS0tLVxcbicgK1xuXHRcdFx0J1ZlcnNpb246IEdudVBHIHYyLjAuMTkgKEdOVS9MaW51eClcXG4nICtcblx0XHRcdCdcXG4nICtcblx0XHRcdCdoSXdEOTVEOWFIUzVmeEVCQS80L1g0bXl2SCtqQjFIWU5lWnZkSytXc0JORE1mTHNCR09mMjA1UnhyM3ZTb2IvXFxuJyArXG5cdFx0XHQnQTA5Ym9qOC85bEZhaXBxdStBRWRRS0VqQ0I4c1orT1kwV2lRUEVQcHVoRyttVnFEcUVpUEZrZHBjcU50UzBWVlxcbicgK1xuXHRcdFx0J3B3cXBsSG82UW5IMk1IZnhwclpIWXV3Y0VDOXluSkN4SjZrU0NEOFhzOTloK1BqeE5OdzdOaE1qa0YrTjY5TEFcXG4nICtcblx0XHRcdCdOd0dQdGJMeDIvcjJuUjRnTzhnVjkyQTJSUUNPd1BQN1pWKzZmWGdXSXMrbWh5Q0hGUDN4VVA1RGFGQ05NOG1vXFxuJyArXG5cdFx0XHQnUE45N2k2NTl1Y3hGNkliT29LNTZGRWFVYk9QVEQ2eGR5aFdhbXhLZk1zSWIwVUpnVlVOaEdhcStWbHZPSnhhQlxcbicgK1xuXHRcdFx0J2lSY25ZNVV4c3lwS2d0cWZjS0lzZWIyMU1JbzR2Y05kb2d5eEJJRGxBTzQ3MlpmeG4wdWR6cjZXMmFRNzcrTktcXG4nICtcblx0XHRcdCdGRTFPMGtDWFMrRFRGT1lZVkQ3WDhyWEdTZ2xRc2RYSm1IZDg5c2RZRlFrTzdEN2JPTGRSSnVYZ2RnSDJjekNzXFxuJyArXG5cdFx0XHQnVUJHdUhaenNHYlRkeUt2cFZCdVMzcm55SEhCazZvQ25zbTFObDdlTHM2NFZrWlV4akVVYnE1cGI0ZGxyMXB3MlxcbicgK1xuXHRcdFx0J3p0cG1wQW5SY21NPVxcbicgK1xuXHRcdFx0Jz1odHJCXFxuJyArXG5cdFx0XHQnLS0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLSdcblxuXHRcdHZhciBrZXkgPSBuZXcgb3BlbnBncC5wYWNrZXQubGlzdCgpO1xuXHRcdGtleS5yZWFkKG9wZW5wZ3AuYXJtb3IuZGVjb2RlKGFybW9yZWRfa2V5KS5kYXRhKTtcblx0XHRrZXlbM10uZGVjcnlwdCgndGVzdCcpXG5cblx0XHR2YXIgbXNnID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRtc2cucmVhZChvcGVucGdwLmFybW9yLmRlY29kZShhcm1vcmVkX21zZykuZGF0YSk7XG5cblxuXHRcdG1zZ1swXS5kZWNyeXB0KGtleVszXSk7XG5cdFx0bXNnWzFdLmRlY3J5cHQobXNnWzBdLnNlc3Npb25LZXlBbGdvcml0aG0sIG1zZ1swXS5zZXNzaW9uS2V5KTtcblxuXHRcdHZhciBwYXlsb2FkID0gbXNnWzFdLnBhY2tldHNbMF0ucGFja2V0c1xuXG5cblxuXHRcdHZhciB2ZXJpZmllZCA9IHBheWxvYWRbMl0udmVyaWZ5KGtleVswXSwgcGF5bG9hZFsxXSk7XG5cblxuXG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnUmVhZGluZyBhIHNpZ25lZCwgZW5jcnlwdGVkIG1lc3NhZ2UuJyxcblx0XHRcdHZlcmlmaWVkID09IHRydWUpO1xuXHR9LCBmdW5jdGlvbigpIHtcblx0XHR2YXIga2V5ID0gbmV3IG9wZW5wZ3AucGFja2V0Lmxpc3QoKTtcblx0XHRrZXkucHVzaChuZXcgb3BlbnBncC5wYWNrZXQuc2VjcmV0X2tleSk7XG5cblx0XHR2YXIgcnNhID0gbmV3IG9wZW5wZ3AuY3J5cHRvLnB1YmxpY0tleS5yc2EoKSxcblx0XHRcdG1waSA9IHJzYS5nZW5lcmF0ZSg1MTIsIFwiMTAwMDFcIilcblxuXG5cdFx0dmFyIG1waSA9IFttcGkubiwgbXBpLmVlLCBtcGkuZCwgbXBpLnAsIG1waS5xLCBtcGkudV07XG5cblx0XHRtcGkgPSBtcGkubWFwKGZ1bmN0aW9uKGspIHtcblx0XHRcdFx0dmFyIG1waSA9IG5ldyBvcGVucGdwLm1waSgpO1xuXHRcdFx0XHRtcGkuZnJvbUJpZ0ludGVnZXIoayk7XG5cdFx0XHRcdHJldHVybiBtcGk7XG5cdFx0fSk7XG5cblx0XHRrZXlbMF0ubXBpID0gbXBpO1xuXG5cdFx0a2V5WzBdLmVuY3J5cHQoJ2hlbGxvJyk7XG5cblx0XHR2YXIgcmF3ID0ga2V5LndyaXRlKCk7XG5cblx0XHR2YXIga2V5MiA9IG5ldyBvcGVucGdwLnBhY2tldC5saXN0KCk7XG5cdFx0a2V5Mi5yZWFkKHJhdyk7XG5cdFx0a2V5MlswXS5kZWNyeXB0KCdoZWxsbycpO1xuXHRcblx0XG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnV3JpdGluZyBhbmQgZW5jcnlwdGlvIG9mIGEgc2VjcmV0IGtleSBwYWNrZXQuJyxcblx0XHRcdGtleVswXS5tcGkudG9TdHJpbmcoKSA9PSBrZXkyWzBdLm1waS50b1N0cmluZygpKTtcblx0fSwgZnVuY3Rpb24oKSB7XG5cblx0XHR2YXIga2V5ID0gbmV3IG9wZW5wZ3AucGFja2V0LnNlY3JldF9rZXkoKTtcblxuXHRcdHZhciByc2EgPSBuZXcgb3BlbnBncC5jcnlwdG8ucHVibGljS2V5LnJzYSxcblx0XHRcdG1waSA9IHJzYS5nZW5lcmF0ZSg1MTIsIFwiMTAwMDFcIilcblxuXHRcdHZhciBtcGkgPSBbbXBpLm4sIG1waS5lZSwgbXBpLmQsIG1waS5wLCBtcGkucSwgbXBpLnVdO1xuXG5cdFx0bXBpID0gbXBpLm1hcChmdW5jdGlvbihrKSB7XG5cdFx0XHRcdHZhciBtcGkgPSBuZXcgb3BlbnBncC5tcGkoKTtcblx0XHRcdFx0bXBpLmZyb21CaWdJbnRlZ2VyKGspO1xuXHRcdFx0XHRyZXR1cm4gbXBpO1xuXHRcdH0pO1xuXG5cdFx0a2V5Lm1waSA9IG1waTtcblxuXHRcdHZhciBzaWduZWQgPSBuZXcgb3BlbnBncC5wYWNrZXQubGlzdCgpLFxuXHRcdFx0bGl0ZXJhbCA9IG5ldyBvcGVucGdwLnBhY2tldC5saXRlcmFsKCksXG5cdFx0XHRzaWduYXR1cmUgPSBuZXcgb3BlbnBncC5wYWNrZXQuc2lnbmF0dXJlKCk7XG5cblx0XHRsaXRlcmFsLnNldCgnSGVsbG8gd29ybGQnLCAndXRmOCcpO1xuXG5cdFx0c2lnbmF0dXJlLmhhc2hBbGdvcml0aG0gPSAnc2hhMjU2Jztcblx0XHRzaWduYXR1cmUucHVibGljS2V5QWxnb3JpdGhtID0gJ3JzYV9zaWduJztcblx0XHRzaWduYXR1cmUuc2lnbmF0dXJlVHlwZSA9ICdiaW5hcnknO1xuXG5cdFx0c2lnbmF0dXJlLnNpZ24oa2V5LCBsaXRlcmFsKTtcblxuXHRcdHNpZ25lZC5wdXNoKGxpdGVyYWwpO1xuXHRcdHNpZ25lZC5wdXNoKHNpZ25hdHVyZSk7XG5cblx0XHR2YXIgcmF3ID0gc2lnbmVkLndyaXRlKCk7XG5cblx0XHR2YXIgc2lnbmVkMiA9IG5ldyBvcGVucGdwLnBhY2tldC5saXN0KCk7XG5cdFx0c2lnbmVkMi5yZWFkKHJhdyk7XG5cblx0XHR2YXIgdmVyaWZpZWQgPSBzaWduZWQyWzFdLnZlcmlmeShrZXksIHNpZ25lZDJbMF0pO1xuXHRcblx0XG5cdFx0cmV0dXJuIG5ldyB1bml0LnJlc3VsdCgnV3JpdGluZyBhbmQgdmVyaWZpY2F0aW9uIG9mIGEgc2lnbmF0dXJlIHBhY2tldC4nLFxuXHRcdFx0dmVyaWZpZWQgPT0gdHJ1ZSk7XG5cdH1dO1xuXG5cblxuXHR0ZXN0cy5yZXZlcnNlKCk7XG5cblx0dmFyIHJlc3VsdHMgPSBbXTtcblxuXHRmb3IodmFyIGkgaW4gdGVzdHMpIHtcblx0XHRyZXN1bHRzLnB1c2godGVzdHNbaV0oKSk7XG5cdH1cblx0XG5cdFxuXHRyZXR1cm4gcmVzdWx0cztcbn0pO1xuIiwidmFyIHVuaXQgPSByZXF1aXJlKCcuLi91bml0LmpzJyk7XG5cbnVuaXQucmVnaXN0ZXIoXCJTaWduYXR1cmUgdGVzdGluZ1wiLCBmdW5jdGlvbigpIHtcbiAgdmFyIG9wZW5wZ3AgPSByZXF1aXJlKCcuLi8uLi8nKTtcblxuICAgICAgdmFyIHByaXZfa2V5X2FybTEgPVxuICAgICAgICBbICctLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICAgICAnVmVyc2lvbjogR251UEcgdjEuNC4xMSAoR05VL0xpbnV4KScsXG4gICAgICAgICAgJycsXG4gICAgICAgICAgJ2xRSGhCRkVSbnJNUkJBRG1NMGhJZmtJM3lvc2pnYldvOXYwTG5yM0NDRSs4S3NNc3pnVlMraEJ1MFhmR3JhS20nLFxuICAgICAgICAgICdpdmNBMmFhSmltSHFWWU9QN2dFbndGQXhIQkJwZVRKY3U1d3pDRnlKd0VZcVZlUzNubmFJaEJQcGxTRjE0RHVmJyxcbiAgICAgICAgICAnaTZiQjlSVjdLeFZBZzZhdW5tTTJ0QXV0cUMrYTB5MnJEYWY3amtKb1o5Z1dKZTJ6SSt2cmFENmZpd0NneHZIbycsXG4gICAgICAgICAgJzNJZ1VMQjlScUlxcExvTWdYZmNqQytjRC8xamVKbEtSbStuNzFyeVl3VC9FQ0tzc3BGejdTMzZ6NnEzWHlTOFEnLFxuICAgICAgICAgICdRZnJzVXoycDFmYkZpY3ZKd0lPSjhCMjBKL04yL25pdDRQMGdCVVRVeHYzUUVhN1hDTS81Ni94ckdreUJ6c2NXJyxcbiAgICAgICAgICAnQXpCb3kvQUs5SzdHTjZ6MTNSb3p1QVM2MEYxeE83TVFjNllpMlZVM2VBU0RRRUtpeUwvVWJmL3MvcmtaK3NHaicsXG4gICAgICAgICAgJ3lKaXpCQUN0d0NiUXpBK3o5WEJaTlVhdDVOUGdjWno1UWVoMW53RjlOeG5yNnB5QnY3dGtyTGgvM2d4UkdIcUcnLFxuICAgICAgICAgICcwNjNkTWJVazhwbVVjSnpCVXlSc05pSVBEb0VVc0xqWTV6bVpabXAvd2FBaHBSRXNuSzI5V0xDYnFMZHBVb3JzJyxcbiAgICAgICAgICAnYzFKSkJzT2JrQTFJTThUWlk4WVVtdnNNRXZCTENDYW51S3BjbFpaWHFlUkFlT0hKMHY0REF3SzhXZnVUZTVCKycsXG4gICAgICAgICAgJ00yQk9PZVpiTjhCcGZpQTFsLy9mTU1ITFJTM1V2YkxCdjRQMSs0U3l2aHlZVFI3TTc2UTB4UGMwM01GT1dITCsnLFxuICAgICAgICAgICdTOVZ1bWJRV1ZHVnpkRElnUEhSbGMzUXlRSFJsYzNRdVkyOXRQb2hpQkJNUkFnQWlCUUpSRVo2ekFoc0RCZ3NKJyxcbiAgICAgICAgICAnQ0FjREFnWVZDQUlKQ2dzRUZnSURBUUllQVFJWGdBQUtDUkFSSjVRRHl4YWUrTVhOQUtDeldTRFIzdE1yVHJEYicsXG4gICAgICAgICAgJ1RBcmk3M04xWGIzajFBQ2ZTbDl5K1NBYWgycTdHdm1pUjErNisvZWtxSkdkQVZnRVVSR2VzeEFFQU5scE1aalcnLFxuICAgICAgICAgICczM2pNeGxLSERkeVJGWHRLT3E4UnJlWGhxMDBwbG9ySGJnejl6RkVXbTRWRjUzK0UvS0dubUhHeVk1Q3k4VEt5JyxcbiAgICAgICAgICAnWmphdWVaWjlYdUcwaHVaZzVJZjY4aXJGZk5adHhkQTI2anY4Ly9QZFowVWorWDZKM1JWYTJwZU1MRERzd1RZTCcsXG4gICAgICAgICAgJ09MMVpPMWZ4ZHRERDQwZmRBaUlaMVF5andFRzBBUHR6NDFFZkFBTUZCQUM1L2R0Z0JCUHRIZThVakRCYVVlNG4nLFxuICAgICAgICAgICdOekh1VUJCcDZYRStIN2VxSE5GQ3VaQUo3eXFKTEdWSE5JYVFSNDE5Y055MDgvT08vK1lVUTdyZzc4THhqRml2JyxcbiAgICAgICAgICAnQ0g3SXpoZlUrNnl2RUxTYmdSTWljWTZFbkFQMkdUK2IxK010Rk5hM2xCR3RCSGNKbGE1MmMyclRBSHRoWVpXaycsXG4gICAgICAgICAgJ2ZUNVI1RG5KdVEyY0pIQk1TOUhXeVA0REF3SzhXZnVUZTVCK00yQzdhL1lKU1V2NlNleGRHQ2FpYVRjQW02Zy8nLFxuICAgICAgICAgICdQdkE2aHcvRkx6SUVQNjdRY1FTU1RtaGZ0UUl3bmRkdDRTNE15SkpIM1U0ZkphRmZZUTF6Q25pWUpvaEpCQmdSJyxcbiAgICAgICAgICAnQWdBSkJRSlJFWjZ6QWhzTUFBb0pFQkVubEFQTEZwNzRRYk1BbjNWNDg1N3h3bk85Lyt2eklWbkw5M1czazAvOCcsXG4gICAgICAgICAgJ0FLQzhvbVlQUG9tTjFFL1VKRmZYZExESU1pNUxvQT09JyxcbiAgICAgICAgICAnPUxTclcnLFxuICAgICAgICAgICctLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLSdcbiAgICAgICAgXS5qb2luKFwiXFxuXCIpO1xuICAgIHZhciBwdWJfa2V5X2FybTEgPSBcbiAgICAgICAgWyAnLS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICAgICAnVmVyc2lvbjogR251UEcgdjEuNC4xMSAoR05VL0xpbnV4KScsXG4gICAgICAgICAgJycsXG4gICAgICAgICAgJ21RR2lCRkVSbHc0UkJBRDZCbWNmMncxZHRVbXRDTGtkeGVxWkxBcmszdllvUUFqZGlieEEzZ1hWeXVyN2ZzV2InLFxuICAgICAgICAgICdybzBqVmJCSHFPQ3RDNmpEeEUybDUyTlA5K3RUbFdlVk1hcXFOdlVFNDdMU2FQcTJER0k4V3gxUmo2YkYzbVRzJyxcbiAgICAgICAgICAnb2JZRXdoR2JHaC9NaEpuTUU5QUhPRGFydms4QVpiem8wK2sxRXdyQldGNmRUVUJQZnFPN3JHVTJld0NnODBXVicsXG4gICAgICAgICAgJ3g1cHQzZXZqOHJSSzNqUThTTUtUTlJzRC8xUGhUZHhkWlRkWEFSQUZ6Y1cxVmFhcnVXVzBScjErWEhLS3dEQ3onLFxuICAgICAgICAgICdpN0hFNzZTTzlxam5RZlpDWkc3NUNkUXhJMGg4R0ZlTjN6c0RxbWhvYjJpU3oyYUoxa3J0ak0raVoxRkJGZDU3JyxcbiAgICAgICAgICAnT3FDVjZ3bWs1SVQwUkJOMTJaek1TMTlZdnpOL09OWEhybVRabEtFeGQ5TWg5UktMZVZOdytiZjZKc0tRRXpjWScsXG4gICAgICAgICAgJ0p6RmtCQUNYOVgraERZY2hPLzJoaVR3eDRpT085RmhzdWg3ZUlXdW1CM2d0K2FVcG0xanJTYmFzL1FMVHltbWsnLFxuICAgICAgICAgICd1WnVRVlhJNE50bmx2emxOZ1d2NEw1czVSVTVXcU5HRzdXU2FLTmRjcnZKWlJDMmRnYlVKdDA0SjVDS3JXcDZSJyxcbiAgICAgICAgICAnYUlZYWwvODFVdDE3NzhsVTAxUEV0NTYzVGNRblVCbG5qVTVPUjI1S2hmU2VONUNaWTdRVVZHVnpkQ0E4ZEdWeicsXG4gICAgICAgICAgJ2RFQjBaWE4wTG1OdmJUNklZZ1FURVFJQUlnVUNVUkdYRGdJYkF3WUxDUWdIQXdJR0ZRZ0NDUW9MQkJZQ0F3RUMnLFxuICAgICAgICAgICdIZ0VDRjRBQUNna1Fpa0RsWksvVXZMU3NwZ0NmY05hT3BUZzFXMnVjUjFKd0JiQkd2YUVSZnVNQW5SZ3QzL3JzJyxcbiAgICAgICAgICAnRXBscUVha01ja0N0aWtFbnB4WWUnLFxuICAgICAgICAgICc9YjJMbicsXG4gICAgICAgICAgJy0tLS0tRU5EIFBHUCBQVUJMSUMgS0VZIEJMT0NLLS0tLS0nXG4gICAgICAgIF0uam9pbihcIlxcblwiKTtcbiAgICB2YXIgbXNnX2FybTEgPVxuICAgICAgICBbICctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS0nLFxuICAgICAgICAgICdWZXJzaW9uOiBHbnVQRyB2MS40LjExIChHTlUvTGludXgpJyxcbiAgICAgICAgICAnJyxcbiAgICAgICAgICAnaFFFT0ExTjRPQ1NTakVDQkVBUC9kaURKQ1FuNGU4ODE5M1BncWhiZkFrb2hrOVJRMHYwTVBuWHBKYkNSVEhLTycsXG4gICAgICAgICAgJzhyOW54aUFyL1RRdjRaT2luZ1hkQXAySlpFb0U5cFh4WjNyMVVXZXcwNGN6eG1nSjhGUDF6dFpZV1ZGQVdGVmknLFxuICAgICAgICAgICdUajkzMFRCRDdMMWZZL01ENGZLNnhqRUc3ejVHVDhrNHRuNG1MbS9QcFdNYmFySWdsZk1vcFR5MU0vcHkyY0lEJyxcbiAgICAgICAgICAnLzJTajdJa2gzVUZpRyt6bTRzVmlZYzVyb05iTXk4aXhlb0tpeHhpOTlNeDhJTmEyY3hOZnFiYWJqYmxGeWMwWicsXG4gICAgICAgICAgJ0J3bWJJYytaaVkybWVSTkk1eS90azBnUkQ3aFQ4NElYR0dsNi9tSDAwYnNYL2trV2RLR2VUdno4czVHOFJESGEnLFxuICAgICAgICAgICdaYTRIZ0xiWEl0a1gvUWFydlJTOWt2a0QwMXVqSGZqKzFadmdtT0J0dE5mUDBwOEJRTElJQ3F2ZzFlWUQ5YVBCJyxcbiAgICAgICAgICAnK0d0T1oyRjMrazVWeUJMNXlJbi9zNjVTQmpOTzhGcXMzYUwweCtwN3MxY2ZVeng4SjhhOG5XcHFxL3FJUUlxZycsXG4gICAgICAgICAgJ1pKSDZNWlJLdVF3c2N3SDZOV2dzU1Z3Y25WQ0FYbllPcGJIeEZRK2o3UmJGLyt1aXVxVStERkgvUmQ1cGlrOGInLFxuICAgICAgICAgICcwRHFucDB5ZmVmcmtqUTBudXZ1YmdCNlJ2ODltSHBudnVKZkZKUklucGc0bHJId0x2UndkcE4ySERvekZIY0tLJyxcbiAgICAgICAgICAnYU9VPScsXG4gICAgICAgICAgJz00aUd0JyxcbiAgICAgICAgICAnLS0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLSdcbiAgICAgICAgXS5qb2luKFwiXFxuXCIpO1xuXG4gICAgdmFyIHByaXZfa2V5X2FybTIgPVxuICAgICAgWyctLS0tLUJFR0lOIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpJyxcbiAgICAgICdUeXBlOiBSU0EvUlNBJyxcbiAgICAgICdQd2Q6IGhlbGxvIHdvcmxkJyxcbiAgICAgICcnLFxuICAgICAgJ2xRSCtCRkpoTDA0QkJBRGNsclVFRERzbTBQU1piUTZwbWw5RnB6VHlYaXlDeUROK3JNT3N5OUozMDBPYzEwa3QnLFxuICAgICAgJy9ueUJlajl2WlNSY2FXNVZwTk5qMGlBK2MxL3cyRlBmODR6TnNUenZEbXVNYU5IRlV6a3k0L3ZrWXVacmEvLzMnLFxuICAgICAgJytSaTdDRjhSYXdTWVEvNElSYkM5enFkQmx6bml5ZlFPVzdEcC9MWWU4ZWlibkRTcm1rUWVtMEcwandBUkFRQUInLFxuICAgICAgJy9nTURBdTdMLy9jekJwRTQwcDFacU84SzNrN1VlamVtanNRcWM3a09xbmxEWWQxWjYvM05FQS9VTTMwU2lpcHInLFxuICAgICAgJ0tqZElGWTUraHAwaGNzNkVpaU5xMFBEZm0vVzJqKzdIZnJaNWtwZVFWeERlazRpcmV6WVpybDdKUzJ4ZXphTHYnLFxuICAgICAgJ2swRnYvNmZ4YXNuRnRqT002UWJzdHU2N3M1R3BsOXkwNlp4YlAzVnBUNjIrWGVpYm4vc3dXcmZpSmp1R0VFaE0nLFxuICAgICAgJ2JnbnNNcEh0ekF6L0w4eTZLU3pWaUcvMDVoQmFxcnZrMy9HZUVBNm5FK28wKzBhNnIwTFlMVGVtbXE2RmJhQTEnLFxuICAgICAgJ1BIbyt4N2s3b0ZjQkZVVWVTemd4NzhHY2t1UHdxcjJtTmZlRitJdVNSbnJscFpsM2tjYkhBU1BBT2ZFa3lNWFMnLFxuICAgICAgJ3NXR0U3Z3JDQWpieVF5TTNPRVhUU3lxbmVodkdTLzFSZEI2a0REeEd3Z0UvUUZid055RWg2SzRlYWFBVGhXMmonLFxuICAgICAgJ0lFRUkwV0VuUmtQaTlmWHl4aEZzQ0xTSTFYaHFUYXE3aUROcUpUeEUrQVgyYjladVpYQXhJM1RjLzcrK3ZFeUwnLFxuICAgICAgJzNwMThOL01CMmt0MVdiMWF6bVhXTDJFS2xUMUJaNXlEYUp1QlE4QmhwaE0zdENSVVpYTjBJRTFqVkdWemRHbHUnLFxuICAgICAgJ1ozUnZiaUE4ZEdWemRFQmxlR0Z0Y0d4bExtTnZiVDZJdVFRVEFRSUFJd1VDVW1FdlRnSWJMd2NMQ1FnSEF3SUInLFxuICAgICAgJ0JoVUlBZ2tLQ3dRV0FnTUJBaDRCQWhlQUFBb0pFRXBqWVRwTmJrQ1VNQXdEK2dJSzA4cXBFWlNWYXM5cVcrT2snLFxuICAgICAgJzMyd3pOa3d4ZTZQUWdad2N5QnFNUVlaVWNLYWdDOCs4OXBNUVE1c0tVR3ZwSWdhdDQyVGYxS0xHUGN2RzRjREEnLFxuICAgICAgJ0paNncyUFl6OVlIUXFQaDlMQStQQW5WOG0yNVRjR21LY0tndkZVcVEzVTUzWC9ZOXNCUDhIb29ScWZ3d0hjdjknLFxuICAgICAgJ3BNZ1Ftb2ptTmJJNFZIeWRScUlCZVBhd25RSCtCRkpoTDA0QkJBRHBIOCswRVZvbHBQaU9yWFRLb0JLVGl5ckInLFxuICAgICAgJ1V5eHpvZHlKOHptVkozSE1URVUvdmlkcFF3eklTd29jL25kREZNWFFhdXE2eHFCQ0Q5bTJCUFFJM1VkUXpYbmInLFxuICAgICAgJ0xzQUk1Mm5XQ0lxT2t6TTVOQUtXb0toeVhLOVk0VUg0djlMQVlRZ2wvc3RJSVN2Q2dHNG1KOGx6ekVCV3ZSZGYnLFxuICAgICAgJ1FtMkdoYjY0LzNWNU5EZGVtd0FSQVFBQi9nTURBdTdMLy9jekJwRTQwaVBjcEx6TDdHd0JiV0ZoU1dnU0x5NTMnLFxuICAgICAgJ01kOTlLeHczY0FwV0NvazJFOFI5LzRWUzA0OTB4S1pJYTV5MkkvSzh0aFZocWs5Nlo4S2J0N01STUMxV0xIZ0MnLFxuICAgICAgJ3FKdmtlUUNJNlByRk0wUFVJUExIQVF0REpZS3RhTFh4WXVleGNBZEt6WmozRkhkdExOV0Nvb0s2bjN2SmxMMWMnLFxuICAgICAgJ1dqWmNISjFQSDdVU2xqMWp1cDRYZnhzYnppdXlzUlVTeVhram45MkdaTG0rNjR2Q0lpd2hxQVlvaXpGMk5ISEcnLFxuICAgICAgJ2hSVE40Z1F6eHJ4Z2tlVmNobCthZzdEa1FVREFOSUlWSStBNjNKZUxKZ1dKaUgxZmJZbHdFU0J5SFcrekJGTnQnLFxuICAgICAgJ3FTdGpmSU9oanJmTkljM1J2c2dnYkRkV1FMY2J4bUxaajRzQjB5ZFBTZ1JLb2FVZFJISlkwUzR2cDlvdUtPdGwnLFxuICAgICAgJzJhdS9QMUJQM2JoRDBmRFhsOTFvZWhlWXRoK01TbXNKRkRnL3ZaSnpDSmhGYVE5ZHArMkVuak41YXVOQ05iYUknLFxuICAgICAgJ2JlRkpSSEZmOWNoYThwM2hoK0FLNTROUkNUKytCMk1YWWYrVFB3cVg4OGpZTUJ2OGtrOHZZVWdvODEyOHIxelEnLFxuICAgICAgJ0V6anZpUUU5QkJnQkFnQUpCUUpTWVM5T0Foc3VBS2dKRUVwallUcE5ia0NVblNBRUdRRUNBQVlGQWxKaEwwNEEnLFxuICAgICAgJ0Nna1E0SVQzUkd3Z0xKZTZvZ1FBMmFhSkVJQklYdGdycys4V1NKNGszRE40clJYY1hhVVpmNjY3cGpkRDluRjInLFxuICAgICAgJzNCempGSDZaNzhKSUdheFJISmRNN2IwNWFFOFl1ek04ZjNOSWxUMEYwT0xxL1RJMm11WVU5Zi9VMkRRQnVmK3cnLFxuICAgICAgJ0tUQjYyK1BFTFZnaTlNc1hDMVF2L3UvbzFMWnRtbXhURkZPRDM1eEtzeFpaSTJPSmoycFFwcU9iVzI3TThObGMnLFxuICAgICAgJ0JRUUF3MllBM2ZGYzM4cVBLK1BZNHJaeVRSZGJ2anl5WCsxemVxSW84d243UUNRd1hzK09HYUgyZkdvVDM1QUknLFxuICAgICAgJ1NYdXFLY1dxb0V1TzdPQlNFRlRoQ1hCZlVZTUMwMU9ycUtFc3dQbS9WM3paa0x1MDFxMTJVTXdaYWNoMjhRd0snLFxuICAgICAgJy9ZWmx5NGlvTkQydGRhemoxN3UyclUyZHd0aUhQZTFpTXFHZ1ZNb1FpcmZMYytrPScsXG4gICAgICAnPWx3NWUnLFxuICAgICAgJy0tLS0tRU5EIFBHUCBQUklWQVRFIEtFWSBCTE9DSy0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgICB2YXIgcHViX2tleV9hcm0yID0gXG4gICAgIFsnLS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpJyxcbiAgICAgICdUeXBlOiBSU0EvUlNBJyxcbiAgICAgICcnLFxuICAgICAgJ21JMEVVbUV2VGdFRUFOeVd0UVFNT3liUTlKbHREcW1hWDBXbk5QSmVMSUxJTTM2c3c2ekwwbmZUUTV6WFNTMysnLFxuICAgICAgJ2ZJRjZQMjlsSkZ4cGJsV2swMlBTSUQ1elgvRFlVOS96ak0yeFBPOE9hNHhvMGNWVE9UTGorK1JpNW10ci8vZjUnLFxuICAgICAgJ0dMc0lYeEZyQkpoRC9naEZzTDNPcDBHWE9lTEo5QTVic09uOHRoN3g2SnVjTkt1YVJCNmJRYlNQQUJFQkFBRzAnLFxuICAgICAgJ0pGUmxjM1FnVFdOVVpYTjBhVzVuZEc5dUlEeDBaWE4wUUdWNFlXMXdiR1V1WTI5dFBvaTVCQk1CQWdBakJRSlMnLFxuICAgICAgJ1lTOU9BaHN2QndzSkNBY0RBZ0VHRlFnQ0NRb0xCQllDQXdFQ0hnRUNGNEFBQ2drUVNtTmhPazF1UUpRd0RBUDYnLFxuICAgICAgJ0FnclR5cWtSbEpWcXoycGI0NlRmYkRNMlRERjdvOUNCbkJ6SUdveEJobFJ3cHFBTHo3ejJreEJEbXdwUWEra2knLFxuICAgICAgJ0JxM2paTi9Vb3NZOXk4Ymh3TUFsbnJEWTlqUDFnZENvK0gwc0Q0OENkWHliYmxOd2FZcHdxQzhWU3BEZFRuZGYnLFxuICAgICAgJzlqMndFL3dlaWhHcC9EQWR5LzJreUJDYWlPWTFzamhVZkoxR29nRjQ5ckM0alFSU1lTOU9BUVFBNlIvUHRCRmEnLFxuICAgICAgJ0phVDRqcTEweXFBU2s0c3F3Vk1zYzZIY2lmTTVsU2R4ekV4RlA3NG5hVU1NeUVzS0hQNTNReFRGMEdycXVzYWcnLFxuICAgICAgJ1FnL1p0Z1QwQ04xSFVNMTUyeTdBQ09kcDFnaUtqcE16T1RRQ2xxQ29jbHl2V09GQitML1N3R0VJSmY3TFNDRXInLFxuICAgICAgJ3dvQnVKaWZKYzh4QVZyMFhYMEp0aG9XK3VQOTFlVFEzWHBzQUVRRUFBWWtCUFFRWUFRSUFDUVVDVW1FdlRnSWInLFxuICAgICAgJ0xnQ29DUkJLWTJFNlRXNUFsSjBnQkJrQkFnQUdCUUpTWVM5T0FBb0pFT0NFOTBSc0lDeVh1cUlFQU5tbWlSQ0EnLFxuICAgICAgJ1NGN1lLN1B2RmtpZUpOd3plSzBWM0YybEdYK3V1NlkzUS9aeGR0d2M0eFIrbWUvQ1NCbXNVUnlYVE8yOU9XaFAnLFxuICAgICAgJ0dMc3pQSDl6U0pVOUJkRGk2djB5TnBybUZQWC8xTmcwQWJuL3NDa3dldHZqeEMxWUl2VExGd3RVTC83djZOUzInLFxuICAgICAgJ2JacHNVeFJUZzkrY1NyTVdXU05qaVk5cVVLYWptMXR1elBEWlhBVUVBTU5tQU4zeFhOL0tqeXZqMk9LMmNrMFgnLFxuICAgICAgJ1c3NDhzbC90YzNxaUtQTUorMEFrTUY3UGpobWg5bnhxRTkrUUNFbDdxaW5GcXFCTGp1emdVaEJVNFFsd1gxR0QnLFxuICAgICAgJ0F0TlRxNmloTE1ENXYxZDgyWkM3dE5hdGRsRE1HV25JZHZFTUN2MkdaY3VJcURROXJYV3M0OWU3dHExTm5jTFknLFxuICAgICAgJ2h6M3RZaktob0ZUS0VJcTN5M1BwJyxcbiAgICAgICc9aC9hWCcsXG4gICAgICAnLS0tLS1FTkQgUEdQIFBVQkxJQyBLRVkgQkxPQ0stLS0tLSddLmpvaW4oJ1xcbicpO1xuXG52YXIgcHViX2tleV9hcm0zID1cbiAgICAgIFsnLS0tLS1CRUdJTiBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJyxcbiAgICAgICdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpJyxcbiAgICAgICcnLFxuICAgICAgJ21RRU5CRktWMEZVQkNBQ3RabGlBcHkwMUtCR2JHTkIzNllHSDRscHIrNUtvcUYxSThBNUlUMFllTmp5R2lzT2snLFxuICAgICAgJ1dzRHNVek9xYU52Z3pRODJJM01ZL2pRVjVyTEJoSC82TGlSbUNBMTZXa0tjcUJySGZOR0l4SitRK29mVkJIVWInLFxuICAgICAgJ2FTOUNsWFlJODhqNzQ3UWdXemlybkx1RUEwR2ZpbFJaY2V3SUkxcERBL0c3K20xSHdWNHFIc1BhdGFZTGVib3EnLFxuICAgICAgJ2hQQTNoMUVWVlFGTUFjd2xxak91Uzgrd2VIUVJmTlZSR1FkUk1tNkg3MTY2UHNlRFZSVUhka0pwVmFLRmhwdGcnLFxuICAgICAgJ3JEb05JMGxPK1V1amRxZUYxbzV0Vlowai9zN1JieUJ2ZExUWE51QmJjcHE5M2NlU1d1SlBabWkxWHp0UVhLWWUnLFxuICAgICAgJ3kwZitsdGdWdFpERWM3VEdWNVdEWDllclJFQ0NjQTMrczdKM0FCRUJBQUcwRzBwVElFTnllWEIwYnlBOFpHbG0nLFxuICAgICAgJ1ptbGxRR2h2YldVdWIzSm5Qb2tCUHdRVEFRSUFLUVVDVXBYUVZRSWJBd1VKQ1dZQmdBY0xDUWdIQXdJQkJoVUknLFxuICAgICAgJ0Fna0tDd1FXQWdNQkFoNEJBaGVBQUFvSkVOdnlJK2h3VTAzMHlSQUlBS1gvbUdFZ2kvbWlxYXNiYlFveUsvQ1MnLFxuICAgICAgJ2E3c1J4Z1p3T1dRTGRpMnh4cEU1VjRXNEhKSUROTEpzNXZHcFJONG1tY05LMmZtSkFoNzR3MFBza21WZ0pFaFAnLFxuICAgICAgJ2RGSjE0VUMzZkZQcTVuYnFrQmw3aFUwdERQNWpaeG85cnVRWmZET1dwSEt4T0N6NWd1WUowQ1c5N2J6NGZDaFonLFxuICAgICAgJ05GRHlmVTdWc0pRd1JJb1ZpVmNNQ2lwUDBmVlpRa0loaHdwelFwbVZtTjhFMGE2aldlelRadjFZcE1kbHpiRWYnLFxuICAgICAgJ0g3OWwzU3RhT2g5L1VuOUNrSXlxRVdkWWlLdklZbXM5bkVOeWVoTjdyL09LWU4zU1crcWx0NUdhTCt3cytOMXcnLFxuICAgICAgJzZrRVpqUEZ3bnNyK1k0QTNvSGNBd1hxN25mT3o3MVVTb2pTbW1vOHBnZE44amUxNkNQOTh2dzMvazZUbmNMUzUnLFxuICAgICAgJ0FRMEVVcFhRVlFFSUFNRWpITWVxZzdCMDRGbGlVRldyLzhDNnNKRGI0OTJNbEdBV2dnaElibnVKZlhBblVHZE4nLFxuICAgICAgJ29Bem4wUytuOTNZL3FIYlc2WWNqSEQ0L0cra0szTXV4dGhBRnFjVmpkSFpRWEswcmtoWE8vdTFjbzd2MWNkdGsnLFxuICAgICAgJ09URWN5T3B5TFhvbE0vMVMyVVlJbWhybWw3WXVsVEhNbldWamE3eHU2UUlSc28rN0hCRlQvdTlENDdML3hYclgnLFxuICAgICAgJ016WEZWWmZCdFZZK3lvZVRyT1kzT1g5Y0JNT0F1MGt1TjllVDE4WXYyeWk2WE16UDNpT05WSHRsNkhmRnJBQTcnLFxuICAgICAgJ2tBdHg0bmUwamdBUFdaK2E4aE15NTlvbjJaRnMvQXZTcEp0U2Mxa3cvdk1UV2t5VlAxS3kyMHZBUEhRNkVqNXEnLFxuICAgICAgJzFOR0ovSmJjRmdvbHZFZUkvM3VEdWVMamo0U2RTSWJMT1hNQUVRRUFBWWtCSlFRWUFRSUFEd1VDVXBYUVZRSWInLFxuICAgICAgJ0RBVUpDV1lCZ0FBS0NSRGI4aVBvY0ZOTjlOTGtCL3dPNGlSeGlhMHpmNEt3MlJMVlpHOHFjdW8zQnc5VVRYWVknLFxuICAgICAgJ2xJMEF1dG9MTm5TVVJNTExDcTZyY0owQkNYR2ovMmlaME5CeFpxM3Q1dmJSaDZ1VXYraHBpU3hLMW5GN0FoZU4nLFxuICAgICAgJzRhQUF6aGJXeDBVRFRGMDRlYkcvbmVFNHVEa2xSSUpMaGlmNitCd3UrRVVlVGxHYkRqN2ZxR1NzTmU4ZzkydzcnLFxuICAgICAgJzFlNDFyRi85Q01vT3N3cktnSWpYQW91M2FleG9nV2NIdktZMkQrMXE5ZXhPUmUxcklhMStzVUdsNVBHMndzRXMnLFxuICAgICAgJ3puTjZxdE41Z01sR1kxb2ZXRFkrSTAyZ080cXphWi9GeFJaZml0dEN3N3Y1ZG1RWUtvdDlxUmkyS3gzRnZ3K2gnLFxuICAgICAgJ2l2RkJwQzRUV2dwcEZCbkpKbkFzRlhaSlFjZWpNVzRuRW1PVmlSUVhZOE44UGVwUW1nc3UnLFxuICAgICAgJz11bW15JyxcbiAgICAgICctLS0tLUVORCBQR1AgUFVCTElDIEtFWSBCTE9DSy0tLS0tJ10uam9pbignXFxuJyk7XG5cblxuICB2YXIgdGVzdHMgPSBbZnVuY3Rpb24oKSB7XG4gICAgdmFyIHByaXZfa2V5ID0gb3BlbnBncC5rZXkucmVhZEFybW9yZWQocHJpdl9rZXlfYXJtMSkucGFja2V0cztcbiAgICB2YXIgcHViX2tleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHB1Yl9rZXlfYXJtMSkucGFja2V0cztcbiAgICB2YXIgbXNnID0gb3BlbnBncC5tZXNzYWdlLnJlYWRBcm1vcmVkKG1zZ19hcm0xKS5wYWNrZXRzO1xuICAgIC8vVE9ETyBuZWVkIGJvdGg/XG4gICAgcHJpdl9rZXlbMF0uZGVjcnlwdChcImFiY2RcIik7XG4gICAgcHJpdl9rZXlbM10uZGVjcnlwdChcImFiY2RcIik7XG4gICAgbXNnWzBdLmRlY3J5cHQocHJpdl9rZXlbM10pO1xuICAgIG1zZ1sxXS5kZWNyeXB0KG1zZ1swXS5zZXNzaW9uS2V5QWxnb3JpdGhtLCBtc2dbMF0uc2Vzc2lvbktleSk7XG4gICAgbXNnWzFdLnBhY2tldHNbMl0udmVyaWZ5KHB1Yl9rZXlbMF0sIG1zZ1sxXS5wYWNrZXRzWzFdKTtcbiAgICByZXR1cm4gbmV3IHVuaXQucmVzdWx0KFwiVGVzdGluZyBzaWduYXR1cmUgY2hlY2tpbmcgb24gQ0FTVDUtZW5jaXBoZXJlZCBtZXNzYWdlXCIsXG4gICAgICAgICAgICBtc2dbMV0ucGFja2V0c1syXS52ZXJpZmllZCA9PT0gdHJ1ZSk7XG5cbiAgfSwgZnVuY3Rpb24oKSB7XG5cbiAgICAvLyBleGVyY2lzZXMgdGhlIEdudVBHIHMyayB0eXBlIDEwMDEgZXh0ZW5zaW9uOlxuICAgIC8vIHRoZSBzZWNyZXRzIG9uIHRoZSBwcmltYXJ5IGtleSBoYXZlIGJlZW4gc3RyaXBwZWQuXG4gICAgdmFyIHByaXZfa2V5X2dudXBnX2V4dCA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKFtcbiAgICAgICAgICAnLS0tLS1CRUdJTiBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAgICAgJ1ZlcnNpb246IEdudVBHIHYxLjQuMTEgKEdOVS9MaW51eCknLFxuICAgICAgICAgICcnLFxuICAgICAgICAgICdsUUdxQkZFUm5yTVJCQURtTTBoSWZrSTN5b3NqZ2JXbzl2MExucjNDQ0UrOEtzTXN6Z1ZTK2hCdTBYZkdyYUttJyxcbiAgICAgICAgICAnaXZjQTJhYUppbUhxVllPUDdnRW53RkF4SEJCcGVUSmN1NXd6Q0Z5SndFWXFWZVMzbm5hSWhCUHBsU0YxNER1ZicsXG4gICAgICAgICAgJ2k2YkI5UlY3S3hWQWc2YXVubU0ydEF1dHFDK2EweTJyRGFmN2prSm9aOWdXSmUyekkrdnJhRDZmaXdDZ3h2SG8nLFxuICAgICAgICAgICczSWdVTEI5UnFJcXBMb01nWGZjakMrY0QvMWplSmxLUm0rbjcxcnlZd1QvRUNLc3NwRno3UzM2ejZxM1h5UzhRJyxcbiAgICAgICAgICAnUWZyc1V6MnAxZmJGaWN2SndJT0o4QjIwSi9OMi9uaXQ0UDBnQlVUVXh2M1FFYTdYQ00vNTYveHJHa3lCenNjVycsXG4gICAgICAgICAgJ0F6Qm95L0FLOUs3R042ejEzUm96dUFTNjBGMXhPN01RYzZZaTJWVTNlQVNEUUVLaXlML1ViZi9zL3JrWitzR2onLFxuICAgICAgICAgICd5Sml6QkFDdHdDYlF6QSt6OVhCWk5VYXQ1TlBnY1p6NVFlaDFud0Y5TnhucjZweUJ2N3RrckxoLzNneFJHSHFHJyxcbiAgICAgICAgICAnMDYzZE1iVWs4cG1VY0p6QlV5UnNOaUlQRG9FVXNMalk1em1aWm1wL3dhQWhwUkVzbksyOVdMQ2JxTGRwVW9ycycsXG4gICAgICAgICAgJ2MxSkpCc09ia0ExSU04VFpZOFlVbXZzTUV2QkxDQ2FudUtwY2xaWlhxZVJBZU9ISjB2NERaUUpIVGxVQnRCWlUnLFxuICAgICAgICAgICdaWE4wTWlBOGRHVnpkREpBZEdWemRDNWpiMjAraUdJRUV4RUNBQ0lGQWxFUm5yTUNHd01HQ3drSUJ3TUNCaFVJJyxcbiAgICAgICAgICAnQWdrS0N3UVdBZ01CQWg0QkFoZUFBQW9KRUJFbmxBUExGcDc0eGMwQW9MTlpJTkhlMHl0T3NOdE1DdUx2YzNWZCcsXG4gICAgICAgICAgJ3ZlUFVBSjlLWDNMNUlCcUhhcnNhK2FKSFg3cjc5NlNva1owQldBUlJFWjZ6RUFRQTJXa3htTmJmZU16R1VvY04nLFxuICAgICAgICAgICczSkVWZTBvNnJ4R3Q1ZUdyVFNtV2lzZHVEUDNNVVJhYmhVWG5mNFQ4b2FlWWNiSmprTEx4TXJKbU5xNTVsbjFlJyxcbiAgICAgICAgICAnNGJTRzVtRGtoL3J5S3NWODFtM0YwRGJxTy96Lzg5MW5SU1A1Zm9uZEZWcmFsNHdzTU96Qk5nczR2Vms3Vi9GMicsXG4gICAgICAgICAgJzBNUGpSOTBDSWhuVkRLUEFRYlFBKzNQalVSOEFBd1VFQUxuOTIyQUVFKzBkN3hTTU1GcFI3aWMzTWU1UUVHbnAnLFxuICAgICAgICAgICdjVDRmdDZvYzBVSzVrQW52S29rc1pVYzBocEJIalgxdzNMVHo4NDcvNWhSRHV1RHZ3dkdNV0s4SWZzak9GOVQ3JyxcbiAgICAgICAgICAncks4UXRKdUJFeUp4am9TY0EvWVpQNXZYNHkwVTFyZVVFYTBFZHdtVnJuWnphdE1BZTJGaGxhUjlQbEhrT2NtNScsXG4gICAgICAgICAgJ0Rad2tjRXhMMGRiSS9nTURBcnhaKzVON2tINHpZTHRyOWdsSlMvcEo3RjBZSnFKcE53Q2JxRDgrOERxSEQ4VXYnLFxuICAgICAgICAgICdNZ1EvcnRCeEJKSk9hRisxQWpDZDEyM2hMZ3pJa2tmZFRoOGxvVjloRFhNS2VKZ21pRWtFR0JFQ0FBa0ZBbEVSJyxcbiAgICAgICAgICAnbnJNQ0d3d0FDZ2tRRVNlVUE4c1dudmhCc3dDZmRYanpudkhDYzczLzYvTWhXY3YzZGJlVFQvd0FvTHlpWmc4KycsXG4gICAgICAgICAgJ2lZM1VUOVFrVjlkMHNNZ3lMa3VnJyxcbiAgICAgICAgICAnPUdRc1knLFxuICAgICAgICAgICctLS0tLUVORCBQR1AgUFJJVkFURSBLRVkgQkxPQ0stLS0tLScsXG4gICAgICAgIF0uam9pbihcIlxcblwiKSkucGFja2V0cztcbiAgICB2YXIgcHViX2tleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHB1Yl9rZXlfYXJtMSkucGFja2V0cztcbiAgICB2YXIgbXNnID0gb3BlbnBncC5tZXNzYWdlLnJlYWRBcm1vcmVkKG1zZ19hcm0xKS5wYWNrZXRzO1xuXG4gICAgcHJpdl9rZXlfZ251cGdfZXh0WzNdLmRlY3J5cHQoXCJhYmNkXCIpO1xuICAgIG1zZ1swXS5kZWNyeXB0KHByaXZfa2V5X2dudXBnX2V4dFszXSk7XG4gICAgbXNnWzFdLmRlY3J5cHQobXNnWzBdLnNlc3Npb25LZXlBbGdvcml0aG0sIG1zZ1swXS5zZXNzaW9uS2V5KTtcbiAgICBtc2dbMV0ucGFja2V0c1syXS52ZXJpZnkocHViX2tleVswXSwgbXNnWzFdLnBhY2tldHNbMV0pO1xuICAgIHJldHVybiBuZXcgdW5pdC5yZXN1bHQoXCJUZXN0aW5nIEdudVBHIHN0cmlwcGVkLWtleSBleHRlbnNpb25zXCIsXG4gICAgICAgICAgICBtc2dbMV0ucGFja2V0c1syXS52ZXJpZmllZCA9PT0gdHJ1ZSk7XG5cbiAgfSwgZnVuY3Rpb24oKSB7XG5cbiAgICB2YXIgc2lnbmVkQXJtb3IgPSBcbiAgICAgICBbJy0tLS0tQkVHSU4gUEdQIE1FU1NBR0UtLS0tLScsXG4gICAgICAgICdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpJyxcbiAgICAgICAgJycsXG4gICAgICAgICdvd0did012TXdNVDRvT1c3UzQ2Q3puVEdOZVpKTENXcEZTVkJVM1pHRjJma0Y1VW81S1lXRnllbXAzTGxBVVVWJyxcbiAgICAgICAgJ2NqTHpVcm5lVHAzemF1dmFOOU8yNkw5WnVPRk55NExYeXlkd2NYWE1ZV0ZnWkdKZ1kyVUNhV1hnNGhTQW1ibEsnLFxuICAgICAgICAnblBtZnNYWXhkNThLYTllVnJFblNwemlscjUyMGZYQnJKc2YyUC9vVHF6VGozaHp5TEcwbzNUVHp4RmZydE9YZicsXG4gICAgICAgICdjdzZVNTduMy9aNFgwcEVaNjhDNS9vLzZOcFBJQ0Q3ZnVFT3ozOTM2cmFaNndYR3p1ZVk4cGZQblZqWTBhakFjJyxcbiAgICAgICAgJ1B0Snp2dnFqK3ViWWFUMXNLOXdXaGQ5bEwzL1YrOVp1dWE5UWpPV0MyMmJ1Y2hzQ3JvaDhmTG9aQUE9PScsXG4gICAgICAgICc9Vkg4RicsXG4gICAgICAgICctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgICB2YXIgc01zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChzaWduZWRBcm1vcikucGFja2V0cztcbiAgICB2YXIgcHViX2tleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHB1Yl9rZXlfYXJtMikucGFja2V0cztcbiAgICBzTXNnWzBdLnBhY2tldHNbMl0udmVyaWZ5KHB1Yl9rZXlbM10sIHNNc2dbMF0ucGFja2V0c1sxXSk7XG4gICAgcmV0dXJuIG5ldyB1bml0LnJlc3VsdChcIlZlcmlmeSBWNCBzaWduYXR1cmUuIEhhc2g6IFNIQTEuIFBLOiBSU0EuIFNpZ25hdHVyZSBUeXBlOiAweDAwIChiaW5hcnkgZG9jdW1lbnQpXCIsIHNNc2dbMF0ucGFja2V0c1syXS52ZXJpZmllZCk7XG4gIH0sIGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIHNpZ25lZEFybW9yID0gXG4gICAgICAgWyctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS0nLFxuICAgICAgICAnVmVyc2lvbjogR251UEcgdjIuMC4xOSAoR05VL0xpbnV4KScsXG4gICAgICAgICcnLFxuICAgICAgICAnb3dHYndNdk15TWo0b09XN1M0NkN6blRHMDlZbExDV3BGU1ZCVTQ3eEZHZmtGNVVvNUtZV0Z5ZW1wL0p5NVFHRicsXG4gICAgICAgICdGWEl5ODRETXQxUG52TnE2OXMyMExmcHZGbTU0MDdMZzlmSUp2Rnk4WEowTVU1bFpHVUZhNGVZeHhpUXovNisvJyxcbiAgICAgICAgJ2FGdDQvNitlNzZPNnMxYWZMaTY1ZW1tSzl4c2RoN01yNjBVblQyVU4wTHdvY1duVDd0L25PTUp1Ym55cHZ6VHUnLFxuICAgICAgICAnYVBKeXZtOVRUcG9iVy9PK1AxbjJUSExTNFVDdld0MTJPYTJsSjA0R0x3ay9iREYxdSs4WnBmUENwc3hMVnpjcycsXG4gICAgICAgICdaR3RicS9mMjNYeFYvamtMNDdocjNzM0ljNHlvWlRXNG9aTzI3R1lmMzdUUHA5TDNWYm9DQUE9PScsXG4gICAgICAgICc9cGE2QicsXG4gICAgICAgICctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgICB2YXIgc01zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChzaWduZWRBcm1vcikucGFja2V0cztcbiAgICB2YXIgcHViX2tleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHB1Yl9rZXlfYXJtMikucGFja2V0cztcbiAgICBzTXNnWzBdLnBhY2tldHNbMl0udmVyaWZ5KHB1Yl9rZXlbM10sIHNNc2dbMF0ucGFja2V0c1sxXSk7XG4gICAgcmV0dXJuIG5ldyB1bml0LnJlc3VsdChcIlZlcmlmeSBWMyBzaWduYXR1cmUuIEhhc2g6IE1ENS4gUEs6IFJTQS4gU2lnbmF0dXJlIFR5cGU6IDB4MDEgKHRleHQgZG9jdW1lbnQpXCIsIHNNc2dbMF0ucGFja2V0c1syXS52ZXJpZmllZCk7XG4gIH0sIGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIG1zZ19hcm1vciA9IFxuICAgICAgIFsnLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tJyxcbiAgICAgICAgJ1ZlcnNpb246IEdudVBHIHYyLjAuMTkgKEdOVS9MaW51eCknLFxuICAgICAgICAnJyxcbiAgICAgICAgJ2hJd0Q0SVQzUkd3Z0xKY0JCQURFQmRtK0dFVzdJVjFLL0J5a2cwbkIwV1lPMDhhaTcvOC8rWS9POXh1NlJpVTAnLFxuICAgICAgICAncTcvald1S21zN2tTanc5Z3hNQ2pmMmRHbkF1VDRDZzUwNUtqNVdmZUJ1SGg2MThvdk84cW80aDBxSHlwMS95MycsXG4gICAgICAgICdvMVAwSVhQQWIrTEdKT2VPN0R5TTlYcDJBT0JpSUtPVld6RlRnK01CWk9jK1haRVZ4M0Zpb0hmbTlTU0R1ZExBJyxcbiAgICAgICAgJ1dBRWtEYWtDRzZNUkZqLzdTbU9pVjhtUUtIK1lQTUtUNjllRFpXN2hqSU5hYnJwTTJwZFJVN2M5bEM3Q01VQngnLFxuICAgICAgICAnVmo3d1pzUUJNQVNTQzhmMnJocEdBMmlLdllNc21XM2c5UjF4a3ZqMU1YV2Z0U1BVUzRqZU5UQWdFd3Z2RjZBZicsXG4gICAgICAgICdjUCtPWVNYS2xUYndmRXI3M0VTMk8zL0lGRTlzSFJqUHFXYXhXdXY0RERRNVlmSXhFNTRDMWFFOEFxNS9RYUlIJyxcbiAgICAgICAgJ3YzOFRVU2lhMHlFTUNjL3RKZDU4RGlra1QwN0FGMTYydGN4OVJvMFpqaHVkeXV2VXlYSWZQZnhBK1hXUjJwZHonLFxuICAgICAgICAnaWZ4eVY0emlhOVJ2YUNVWTh2WEdNK2dRSjNOTlh4MkxrWkEza1dVRXl4RlZMMVZsL1hVUVkwTTZVK3VjY1NrNCcsXG4gICAgICAgICdlTVhtNmV5RVdEY2owbEJSY2txS29LbzF3L3VhbjExalB1SHNuUno2ak85RHN1S0V6NzlVRGdJPScsXG4gICAgICAgICc9Y0ZpNycsXG4gICAgICAgICctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgICB2YXIgcGxhaW50ZXh0ID0gJ3Nob3J0IG1lc3NhZ2VcXG5uZXh0IGxpbmVcXG7tlZzqta3slrQv7KGw7ISg66eQJztcbiAgICB2YXIgZXNNc2cgPSBvcGVucGdwLm1lc3NhZ2UucmVhZEFybW9yZWQobXNnX2FybW9yKTtcbiAgICB2YXIgcHViS2V5ID0gb3BlbnBncC5rZXkucmVhZEFybW9yZWQocHViX2tleV9hcm0yKTtcbiAgICB2YXIgcHJpdktleSA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHByaXZfa2V5X2FybTIpO1xuXG4gICAgdmFyIGtleWlkcyA9IGVzTXNnLmdldEVuY3J5cHRpb25LZXlJZHMoKTtcbiAgICBwcml2S2V5LmRlY3J5cHRLZXlQYWNrZXQoa2V5aWRzLCAnaGVsbG8gd29ybGQnKTtcblxuICAgIHZhciBkZWNyeXB0ZWQgPSBvcGVucGdwLmRlY3J5cHRBbmRWZXJpZnlNZXNzYWdlKHByaXZLZXksIFtwdWJLZXldLCBlc01zZyk7XG4gICAgdmFyIHZlcmlmaWVkID0gZGVjcnlwdGVkLnRleHQgPT0gcGxhaW50ZXh0ICYmIGRlY3J5cHRlZC5zaWduYXR1cmVzWzBdLnN0YXR1cztcblxuICAgIHJldHVybiBuZXcgdW5pdC5yZXN1bHQoXCJWZXJpZnkgc2lnbmF0dXJlIG9mIHNpZ25lZCBhbmQgZW5jcnlwdGVkIG1lc3NhZ2UgZnJvbSBHUEcyIHdpdGggb3BlbnBncC5kZWNyeXB0QW5kVmVyaWZ5TWVzc2FnZVwiLCB2ZXJpZmllZCk7XG4gIH0sIGZ1bmN0aW9uKCkge1xuXG4gICAgdmFyIG1zZ19hcm1vciA9IFxuICAgICAgWyctLS0tLUJFR0lOIFBHUCBNRVNTQUdFLS0tLS0nLFxuICAgICAgJ1ZlcnNpb246IEVuY3J5cHRpb24gRGVza3RvcCAxMC4zLjAgKEJ1aWxkIDkzMDcpJyxcbiAgICAgICdDaGFyc2V0OiB1dGYtOCcsXG4gICAgICAnJyxcbiAgICAgICdxQU5RUjFEQmpBUGdoUGRFYkNBc2x3RUQvMlM0b052Q2pPNVRkTFVNTVV1Vk9RYzhmaTZjNVhJQnU3WTA5ZkVYJyxcbiAgICAgICdKbS9VcmtESFZnbVBvakxHQkRGMENZRU5OWk9Wck5mcGFoWTdBM3I0SFB6R3VjQnpDTzF1eHVVSUtqaHROQUFNJyxcbiAgICAgICdtakQ5Mzllcm5qb29PWnJNNnhEdVJhWDhhZEcwTFN4cE5hVkpHeFhkL0VkbG1LREpiWURJNmFKNUlOclV4ekFSJyxcbiAgICAgICdEQXF3MHNCU0FYZ1JXZ2lINklJaUFvNXk1V0ZFREVOOXNHU3RhRVFUMndkMzJrWDczTTRpWnVNdC9HTTJhZ2lCJyxcbiAgICAgICdzV2I3eUxjTkhpSi8zT25UZkRnOStUNTQza0ZxOUZsd0Zid3F5Z08vd205ZS9rZ01CcTBac0ZPZlYrR1J0WGVwJyxcbiAgICAgICczcU5iSnNtekd2ZHFpVUhiLytoa2RFMTkxamFTVmNPL3phTVc0TjBWYzFJd0lFaFo4STkrOWJLd3VzZFZoSFQ1JyxcbiAgICAgICdNeVNuaElvZ3YrMElsYWcvYVkrVWlDdCtaY2llNjlUN0VpeDQ4ZkMvVlZXNXczSU5mMVQyQ01tRG01WkxaRlJOJyxcbiAgICAgICdveXF6YjlWc2d1MWdTN1NDYjZxVGJuYlY5UGxTeVU0d0pCNnNpWDhoei9VMHVyb2tUNXNlM3VZUmppVjBLYmtBJyxcbiAgICAgICd6bDEvci93Q3Jtd1g0R2w5Vk45KzMzY1FnWVpBbEpMc1J3OE44MkdoYlZ3ZVpTOHF3djI0R1E9PScsXG4gICAgICAnPW54OTAnLFxuICAgICAgJy0tLS0tRU5EIFBHUCBNRVNTQUdFLS0tLS0nXS5qb2luKCdcXG4nKTtcblxuICAgIHZhciBwbGFpbnRleHQgPSAnc2hvcnQgbWVzc2FnZVxcbm5leHQgbGluZVxcbu2VnOq1reyWtC/sobDshKDrp5BcXG5cXG4nO1xuICAgIHZhciBlc01zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChtc2dfYXJtb3IpO1xuICAgIHZhciBwdWJLZXkgPSBvcGVucGdwLmtleS5yZWFkQXJtb3JlZChwdWJfa2V5X2FybTIpO1xuICAgIHZhciBwcml2S2V5ID0gb3BlbnBncC5rZXkucmVhZEFybW9yZWQocHJpdl9rZXlfYXJtMik7XG5cbiAgICB2YXIga2V5aWRzID0gZXNNc2cuZ2V0RW5jcnlwdGlvbktleUlkcygpO1xuICAgIHByaXZLZXkuZGVjcnlwdEtleVBhY2tldChrZXlpZHMsICdoZWxsbyB3b3JsZCcpO1xuXG4gICAgdmFyIGRlY3J5cHRlZCA9IG9wZW5wZ3AuZGVjcnlwdEFuZFZlcmlmeU1lc3NhZ2UocHJpdktleSwgW3B1YktleV0sIGVzTXNnKTtcbiAgICB2YXIgdmVyaWZpZWQgPSBkZWNyeXB0ZWQudGV4dCA9PSBwbGFpbnRleHQgJiYgZGVjcnlwdGVkLnNpZ25hdHVyZXNbMF0uc3RhdHVzO1xuXG4gICAgcmV0dXJuIG5ldyB1bml0LnJlc3VsdChcIlZlcmlmeSBzaWduYXR1cmUgb2Ygc2lnbmVkIGFuZCBlbmNyeXB0ZWQgbWVzc2FnZSBmcm9tIFBHUCAxMC4zLjAgd2l0aCBvcGVucGdwLmRlY3J5cHRBbmRWZXJpZnlNZXNzYWdlXCIsIHZlcmlmaWVkKTtcbiAgfSwgZnVuY3Rpb24oKSB7XG5cbiAgICB2YXIgbXNnX2FybW9yID0gXG4gICAgIFsnLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tJyxcbiAgICAgICdWZXJzaW9uOiBHbnVQRyB2Mi4wLjE5IChHTlUvTGludXgpJyxcbiAgICAgICcnLFxuICAgICAgJ293R2J3TXZNd01GNCs1UHlpNEpnM3k4TUU4RGNCeTNmWFhJVWRLWXpyakZOWWlsSnJTZ0ptc1hEWEp5UlgxU2knLFxuICAgICAgJ2tKdGFYSnlZbnNxVkJ4UlZ5TW5NUytWNk8zWE9xNjFyMzB6Ym92OW00WVkzTFF0ZUw1L1FNWWVGZ1pHRGdZMlYnLFxuICAgICAgJ0NhU1JnWXRUQUdaaVl4WUx3eVNiUWswN3B0WmVsNmdtanJLeUJXc3lXZGtPRzNvc2NMQmRJcFhYZkRkYjZmTnYnLFxuICAgICAgJzhVTE41TDFlZCt4Tm83OVAyZEJvdFd1ZDZ2bjdlOWR0TEo3bzEyUHVubnZFejhneXl2UDQvQXMvbG9zMHhzblonLFxuICAgICAgJ0grOHVibHJodkd0THhKVVp1VUtaTzZRZEhxMk5lcHV3OE9yZmlNWFBCRFFYWHBWMnExMVplK3JEM2xuZGd2L0MnLFxuICAgICAgJ2JKUU5PaGxsMEowSDgzOWpGdnQvMTZtMjBoL1ptRG9XcUp5d2FwbnlwamRJamNYcis3ckpGZXNzNDB5ZW5WN1EnLFxuICAgICAgJzJMU3UvRVg2QXEyOXgrZHYrR1BVTWZ1aFRORTN2aVdXVVI0UEQ2VDdYZm1kVmlVd21TZjhma1JOVW4vdDNhMm4nLFxuICAgICAgJ2NxNDZYcjM2c2VDb3IvT0xwMGF0U1p3SHJqeDJTVTV6UExoZVpuK3p3LzBkMS9ZWm5EN0FFZVA5cy9DdXljeXYnLFxuICAgICAgJ0NaNUhaTkt1ZnZCOGZzaCtkZmRTWFcwR2Zxa1BmeGszNlZ3OHVmcGphb1pEeXQybnh4Zy82RDRLUzNVdlp6djMnLFxuICAgICAgJ2F4ZExaOXlkME9KTlp2NFA1MDFJZjI0VzR2VEd6Nm5JN1NlcjhZZDJQaU92RTVNV01UMHdMWlErelBYMXN2MC8nLFxuICAgICAgJ3M4UHZreVdtVk0wTzBmQi9aU0hvdkhOTlBmZkRnL3JXaHpPbVhROS83dlRuNDc3RithV201c1l6Sjc1L0JRQT0nLFxuICAgICAgJz0rTDBTJyxcbiAgICAgICctLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tJ10uam9pbignXFxuJyk7XG5cbiAgICB2YXIgcGxhaW50ZXh0ID0gJ3Nob3J0IG1lc3NhZ2VcXG5uZXh0IGxpbmVcXG7tlZzqta3slrQv7KGw7ISg66eQJztcbiAgICB2YXIgc01zZyA9IG9wZW5wZ3AubWVzc2FnZS5yZWFkQXJtb3JlZChtc2dfYXJtb3IpO1xuICAgIHZhciBwdWJLZXkyID0gb3BlbnBncC5rZXkucmVhZEFybW9yZWQocHViX2tleV9hcm0yKTtcbiAgICB2YXIgcHViS2V5MyA9IG9wZW5wZ3Aua2V5LnJlYWRBcm1vcmVkKHB1Yl9rZXlfYXJtMyk7XG5cbiAgICB2YXIga2V5aWRzID0gc01zZy5nZXRTaWduaW5nS2V5SWRzKCk7XG5cbiAgICB2YXIgdmVyaWZpZWQgPSBwdWJLZXkyLmdldFB1YmxpY0tleVBhY2tldChrZXlpZHMpICYmIHB1YktleTMuZ2V0UHVibGljS2V5UGFja2V0KGtleWlkcyk7XG5cbiAgICB2ZXJpZmllZCA9IHZlcmlmaWVkICYmIHNNc2cuZ2V0VGV4dCgpID09IHBsYWludGV4dDtcblxuICAgIHZhciB2ZXJpZmllZFNpZyA9IHNNc2cudmVyaWZ5KFtwdWJLZXkyLCBwdWJLZXkzXSk7XG4gICAgXG4gICAgdmVyaWZpZWQgPSB2ZXJpZmllZCAmJiB2ZXJpZmllZFNpZ1swXS5zdGF0dXMgJiYgdmVyaWZpZWRTaWdbMV0uc3RhdHVzO1xuXG4gICAgcmV0dXJuIG5ldyB1bml0LnJlc3VsdChcIlZlcmlmeSBzaWduZWQgbWVzc2FnZSB3aXRoIHR3byBvbmUgcGFzcyBzaWduYXR1cmVzXCIsIHZlcmlmaWVkKTtcbiAgfV07XG5cbiAgdmFyIHJlc3VsdHMgPSBbXTtcblxuICBmb3IodmFyIGkgaW4gdGVzdHMpIHtcbiAgICByZXN1bHRzLnB1c2godGVzdHNbaV0oKSk7XG4gIH0gIFxuICBcbiAgcmV0dXJuIHJlc3VsdHM7XG5cbn0pO1xuIiwibW9kdWxlLmV4cG9ydHM9cmVxdWlyZSgnUWpQWjFxJyk7IiwidmFyIHByb2Nlc3M9cmVxdWlyZShcIl9fYnJvd3NlcmlmeV9wcm9jZXNzXCIpO1xubW9kdWxlLmV4cG9ydHMgPSB7XG5cdHRlc3RzOiBbXSxcblx0cmVnaXN0ZXI6IGZ1bmN0aW9uKHN0cl90aXRsZSwgZnVuY19ydW50ZXN0KSB7XG5cdFx0dGhpcy50ZXN0cy5wdXNoKHsgdGl0bGU6IHN0cl90aXRsZSwgcnVuOiBmdW5jX3J1bnRlc3QgfSk7XG5cdH0sXG5cdFxuXHRydW46IGZ1bmN0aW9uKCkge1xuXHRcdHZhciB0ZXN0ID0gdGhpcy50ZXN0cy5zaGlmdCgpO1xuXG5cdFx0dmFyIHJlc3VsdCA9IHtcblx0XHRcdHRpdGxlOiB0ZXN0LnRpdGxlXG5cdFx0fTtcblxuXG5cdFx0cmVzdWx0LnRlc3RzID0gdGVzdC5ydW4oKTtcblxuXHRcdHJldHVybiByZXN1bHQ7XG5cdH0sXG5cblx0cnVuX2FsbDogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIHBhc3NlZCA9IHRydWU7XG5cblx0XHR3aGlsZSh0aGlzLnRlc3RzLmxlbmd0aCA+IDApIHtcblx0XHRcdHZhciByZXN1bHQgPSB0aGlzLnJ1bigpO1xuXG5cdFx0XHRjb25zb2xlLmxvZygnVGVzdDogJyArIHJlc3VsdC50aXRsZSk7XG5cblx0XHRcdGZvcih2YXIgaSBpbiByZXN1bHQudGVzdHMpIHtcblxuXHRcdFx0XHR2YXIgcmVzID0gcmVzdWx0LnRlc3RzW2ldLnJlc3VsdCA/XG5cdFx0XHRcdFx0J1NVQ0NFU1MnIDogJ0ZBSUxFRCc7XG5cblx0XHRcdFx0Y29uc29sZS5sb2cocmVzdWx0LnRlc3RzW2ldLmRlc2NyaXB0aW9uICsgJyAnICsgcmVzKTtcblxuXHRcdFx0XHRwYXNzZWQgPSBwYXNzZWQgJiYgcmVzdWx0LnRlc3RzW2ldLnJlc3VsdDtcblx0XHRcdH1cdFx0XHRcdFxuXHRcdH1cblxuXHRcdGlmKCFwYXNzZWQpIHByb2Nlc3MuZXhpdCgxKTtcblx0fSxcblx0XHRcblx0cmVzdWx0OiBmdW5jdGlvbihzdHJfZGVzY3JpcHRpb24sIGJvb2xlYW5fcmVzdWx0KSB7XG5cdFx0dGhpcy5kZXNjcmlwdGlvbiA9IHN0cl9kZXNjcmlwdGlvbjtcblx0XHR0aGlzLnJlc3VsdCA9IGJvb2xlYW5fcmVzdWx0O1xuXHR9XG59XG5cbiJdfQ== ;