PHP WebShell
Текущая директория: /opt/BitGoJS/modules/utxo-lib/dist/src/bitgo/wallet
Просмотр файла: Psbt.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.toWalletPsbt = toWalletPsbt;
exports.signWalletPsbt = signWalletPsbt;
exports.getPsbtInputScriptType = getPsbtInputScriptType;
exports.parsePsbtInput = parsePsbtInput;
exports.toScriptType2Of3s = toScriptType2Of3s;
exports.getStrictSignatureCount = getStrictSignatureCount;
exports.getStrictSignatureCounts = getStrictSignatureCounts;
exports.isPsbtInputArray = isPsbtInputArray;
exports.isTxInputArray = isTxInputArray;
exports.isTransactionWithKeyPathSpendInput = isTransactionWithKeyPathSpendInput;
exports.addXpubsToPsbt = addXpubsToPsbt;
exports.getSignatureValidationArrayPsbt = getSignatureValidationArrayPsbt;
exports.extractP2msOnlyHalfSignedTx = extractP2msOnlyHalfSignedTx;
exports.clonePsbtWithoutNonWitnessUtxo = clonePsbtWithoutNonWitnessUtxo;
exports.isPsbtLite = isPsbtLite;
exports.deleteWitnessUtxoForNonSegwitInputs = deleteWitnessUtxoForNonSegwitInputs;
const assert = require("assert");
const utils_1 = require("bip174/src/lib/utils");
const bs58check = require("bs58check");
const UtxoPsbt_1 = require("../UtxoPsbt");
const UtxoTransaction_1 = require("../UtxoTransaction");
const outputScripts_1 = require("../outputScripts");
const WalletKeys_1 = require("./WalletKeys");
const Unspent_1 = require("../Unspent");
const transaction_1 = require("../transaction");
const Unspent_2 = require("./Unspent");
const parseInput_1 = require("../parseInput");
const Musig2_1 = require("../Musig2");
const types_1 = require("../types");
const taproot_1 = require("../../taproot");
const bitcoinjs_lib_1 = require("bitcoinjs-lib");
const index_1 = require("../../index");
const PsbtUtil_1 = require("../PsbtUtil");
function getTaprootSigners(script, walletKeys) {
const parsedPublicKeys = (0, parseInput_1.parsePubScript2Of3)(script, 'taprootScriptPathSpend').publicKeys;
const walletSigners = parsedPublicKeys.map((publicKey) => {
const index = walletKeys.publicKeys.findIndex((walletPublicKey) => (0, outputScripts_1.toXOnlyPublicKey)(walletPublicKey).equals(publicKey));
if (index >= 0) {
return { walletKey: walletKeys.triple[index], rootKey: walletKeys.parent.triple[index] };
}
throw new Error('Taproot public key is not a wallet public key');
});
return [walletSigners[0], walletSigners[1]];
}
function updatePsbtInput(psbt, inputIndex, unspent, rootWalletKeys) {
const input = (0, utils_1.checkForInput)(psbt.data.inputs, inputIndex);
const signatureCount = (0, PsbtUtil_1.getPsbtInputSignatureCount)(input);
const scriptType = (0, outputScripts_1.scriptTypeForChain)(unspent.chain);
if (signatureCount === 0 && scriptType === 'p2tr') {
return;
}
const walletKeys = rootWalletKeys.deriveForChainAndIndex(unspent.chain, unspent.index);
if (scriptType === 'p2tr') {
if (!Array.isArray(input.tapLeafScript) || input.tapLeafScript.length === 0) {
throw new Error('Invalid PSBT state. Missing required fields.');
}
if (input.tapLeafScript.length > 1) {
throw new Error('Bitgo only supports a single tap leaf script per input');
}
const [signer, cosigner] = getTaprootSigners(input.tapLeafScript[0].script, walletKeys);
const leafHash = (0, outputScripts_1.getLeafHash)({
publicKeys: walletKeys.publicKeys,
signer: signer.walletKey.publicKey,
cosigner: cosigner.walletKey.publicKey,
});
psbt.updateInput(inputIndex, {
tapBip32Derivation: [signer, cosigner].map((walletSigner) => ({
leafHashes: [leafHash],
pubkey: (0, outputScripts_1.toXOnlyPublicKey)(walletSigner.walletKey.publicKey),
path: rootWalletKeys.getDerivationPath(walletSigner.rootKey, unspent.chain, unspent.index),
masterFingerprint: walletSigner.rootKey.fingerprint,
})),
});
}
else {
if (signatureCount === 0) {
const { witnessScript, redeemScript } = (0, outputScripts_1.createOutputScript2of3)(walletKeys.publicKeys, scriptType);
if (witnessScript && psbt.data.inputs[inputIndex].witnessScript === undefined) {
psbt.updateInput(inputIndex, { witnessScript });
}
if (redeemScript && psbt.data.inputs[inputIndex].redeemScript === undefined) {
psbt.updateInput(inputIndex, { redeemScript });
}
}
psbt.updateInput(inputIndex, {
bip32Derivation: [0, 1, 2].map((idx) => ({
pubkey: walletKeys.triple[idx].publicKey,
path: walletKeys.paths[idx],
masterFingerprint: rootWalletKeys.triple[idx].fingerprint,
})),
});
}
}
/**
* @return PSBT filled with metatdata as per input params tx, unspents and rootWalletKeys.
* Unsigned PSBT for taproot input with witnessUtxo
* Unsigned PSBT for other input with witnessUtxo/nonWitnessUtxo, redeemScript/witnessScript, bip32Derivation
* Signed PSBT for taproot input with witnessUtxo, tapLeafScript, tapBip32Derivation, tapScriptSig
* Signed PSBT for other input with witnessUtxo/nonWitnessUtxo, redeemScript/witnessScript, bip32Derivation, partialSig
*/
function toWalletPsbt(tx, unspents, rootWalletKeys) {
const prevOutputs = unspents.map((u) => {
assert.notStrictEqual((0, outputScripts_1.scriptTypeForChain)(u.chain), 'p2trMusig2');
return (0, Unspent_1.toPrevOutputWithPrevTx)(u, tx.network);
});
const psbt = (0, transaction_1.createPsbtFromTransaction)(tx, prevOutputs);
unspents.forEach((u, i) => {
if ((0, Unspent_2.isWalletUnspent)(u) && u.index !== undefined) {
updatePsbtInput(psbt, i, u, rootWalletKeys);
}
});
return psbt;
}
/**
* @param psbt
* @param inputIndex
* @param signer
* @param unspent
* @return signed PSBT with signer's key for unspent
*/
function signWalletPsbt(psbt, inputIndex, signer, unspent) {
const scriptType = (0, outputScripts_1.scriptTypeForChain)(unspent.chain);
if (scriptType === 'p2tr' || scriptType === 'p2trMusig2') {
psbt.signTaprootInputHD(inputIndex, signer);
}
else {
psbt.signInputHD(inputIndex, signer);
}
}
/**
* @returns script type of the input
*/
function getPsbtInputScriptType(input) {
const isP2pk = (script) => {
try {
const chunks = bitcoinjs_lib_1.script.decompile(script);
return (chunks?.length === 2 &&
Buffer.isBuffer(chunks[0]) &&
bitcoinjs_lib_1.script.isCanonicalPubKey(chunks[0]) &&
chunks[1] === index_1.opcodes.OP_CHECKSIG);
}
catch (e) {
return false;
}
};
let scriptType;
if (Buffer.isBuffer(input.redeemScript) && Buffer.isBuffer(input.witnessScript)) {
scriptType = 'p2shP2wsh';
}
else if (Buffer.isBuffer(input.redeemScript)) {
scriptType = isP2pk(input.redeemScript) ? 'p2shP2pk' : 'p2sh';
}
else if (Buffer.isBuffer(input.witnessScript)) {
scriptType = 'p2wsh';
}
if (Array.isArray(input.tapLeafScript) && input.tapLeafScript.length > 0) {
if (scriptType) {
throw new Error(`Found both ${scriptType} and taprootScriptPath PSBT metadata.`);
}
if (input.tapLeafScript.length > 1) {
throw new Error('Bitgo only supports a single tap leaf script per input.');
}
scriptType = 'taprootScriptPathSpend';
}
if (input.tapInternalKey) {
if (scriptType) {
throw new Error(`Found both ${scriptType} and taprootKeyPath PSBT metadata.`);
}
scriptType = 'taprootKeyPathSpend';
}
if (scriptType) {
return scriptType;
}
throw new Error('could not parse input');
}
function parseTaprootKeyPathSignatures(input) {
const partialSigs = (0, Musig2_1.parsePsbtMusig2PartialSigs)(input);
if (!partialSigs) {
return { signatures: undefined, participantPublicKeys: undefined };
}
const signatures = partialSigs.map((pSig) => pSig.partialSig);
const participantPublicKeys = partialSigs.map((pSig) => pSig.participantPubKey);
return (0, types_1.isTuple)(signatures) && (0, types_1.isTuple)(participantPublicKeys)
? { signatures, participantPublicKeys }
: { signatures: [signatures[0]], participantPublicKeys: [participantPublicKeys[0]] };
}
function parsePartialOrTapScriptSignatures(sig) {
if (!sig?.length) {
return { signatures: undefined };
}
if (sig.length > 2) {
throw new Error('unexpected signature count');
}
const signatures = sig.map((tSig) => tSig.signature);
return (0, types_1.isTuple)(signatures) ? { signatures } : { signatures: [signatures[0]] };
}
function parseSignatures(input, scriptType) {
return scriptType === 'taprootKeyPathSpend'
? parseTaprootKeyPathSignatures(input)
: scriptType === 'taprootScriptPathSpend'
? parsePartialOrTapScriptSignatures(input.tapScriptSig)
: parsePartialOrTapScriptSignatures(input.partialSig);
}
function parseScript(input, scriptType) {
let pubScript;
if (scriptType === 'p2sh' || scriptType === 'p2shP2pk') {
pubScript = input.redeemScript;
}
else if (scriptType === 'p2wsh' || scriptType === 'p2shP2wsh') {
pubScript = input.witnessScript;
}
else if (scriptType === 'taprootScriptPathSpend') {
pubScript = input.tapLeafScript ? input.tapLeafScript[0].script : undefined;
}
else if (scriptType === 'taprootKeyPathSpend') {
if (input.witnessUtxo?.script) {
pubScript = input.witnessUtxo.script;
}
else if (input.tapInternalKey && input.tapMerkleRoot) {
pubScript = (0, taproot_1.createTaprootOutputScript)({ internalPubKey: input.tapInternalKey, taptreeRoot: input.tapMerkleRoot });
}
}
if (!pubScript) {
throw new Error(`Invalid PSBT state for ${scriptType}. Missing required fields.`);
}
return (0, parseInput_1.parsePubScript)(pubScript, scriptType);
}
/**
* @return psbt metadata are parsed as per below conditions.
* redeemScript/witnessScript/tapLeafScript matches BitGo.
* signature and public key count matches BitGo.
* P2SH-P2PK => scriptType, redeemScript, public key, signature.
* P2SH => scriptType, redeemScript, public keys, signatures.
* PW2SH => scriptType, witnessScript, public keys, signatures.
* P2SH-PW2SH => scriptType, redeemScript, witnessScript, public keys, signatures.
* P2TR and P2TR MUSIG2 script path => scriptType (taprootScriptPathSpend), pubScript (leaf script), controlBlock,
* scriptPathLevel, leafVersion, public keys, signatures.
* P2TR MUSIG2 kep path => scriptType (taprootKeyPathSpend), pubScript (scriptPubKey), participant pub keys (signer),
* public key (tapOutputkey), signatures (partial signer sigs).
*/
function parsePsbtInput(input) {
if ((0, PsbtUtil_1.isPsbtInputFinalized)(input)) {
throw new Error('Finalized PSBT parsing is not supported');
}
const scriptType = getPsbtInputScriptType(input);
const parsedPubScript = parseScript(input, scriptType);
const signatures = parseSignatures(input, scriptType);
if (parsedPubScript.scriptType === 'taprootKeyPathSpend' && 'participantPublicKeys' in signatures) {
return {
...parsedPubScript,
...signatures,
scriptType: parsedPubScript.scriptType,
};
}
if (parsedPubScript.scriptType === 'taprootScriptPathSpend') {
if (!input.tapLeafScript) {
throw new Error('Invalid PSBT state for taprootScriptPathSpend. Missing required fields.');
}
const controlBlock = input.tapLeafScript[0].controlBlock;
if (!(0, parseInput_1.isValidControlBock)(controlBlock)) {
throw new Error('Invalid PSBT taprootScriptPathSpend controlBlock.');
}
const scriptPathLevel = (0, parseInput_1.calculateScriptPathLevel)(controlBlock);
const leafVersion = (0, parseInput_1.getLeafVersion)(controlBlock);
return {
...parsedPubScript,
...signatures,
scriptType: parsedPubScript.scriptType,
controlBlock,
scriptPathLevel,
leafVersion,
};
}
if (parsedPubScript.scriptType === 'p2sh' ||
parsedPubScript.scriptType === 'p2wsh' ||
parsedPubScript.scriptType === 'p2shP2wsh') {
if (parsedPubScript.scriptType === 'p2shP2wsh') {
parsedPubScript.redeemScript = input.redeemScript;
}
return {
...parsedPubScript,
...signatures,
};
}
if (parsedPubScript.scriptType === 'p2shP2pk' && (!signatures.signatures || !(0, types_1.isTuple)(signatures.signatures))) {
return {
...parsedPubScript,
signatures: signatures.signatures,
};
}
throw new Error('invalid pub script');
}
/**
* Converts a parsed script type into an array of script types.
* @param parsedScriptType - The parsed script type.
* @returns An array of ScriptType2Of3 values corresponding to the parsed script type.
*/
function toScriptType2Of3s(parsedScriptType) {
return parsedScriptType === 'taprootScriptPathSpend'
? ['p2trMusig2', 'p2tr']
: parsedScriptType === 'taprootKeyPathSpend'
? ['p2trMusig2']
: [parsedScriptType];
}
/**
* @returns strictly parse the input and get signature count.
* unsigned(0), half-signed(1) or fully-signed(2)
*/
function getStrictSignatureCount(input) {
const calculateSignatureCount = (signatures) => {
const count = signatures ? signatures.filter((s) => !(0, parseInput_1.isPlaceholderSignature)(s)).length : 0;
if (count === 0 || count === 1 || count === 2) {
return count;
}
throw new Error('invalid signature count');
};
if ('hash' in input) {
if (input.script?.length || input.witness?.length) {
const parsedInput = (0, parseInput_1.parseSignatureScript)(input);
return parsedInput.scriptType === 'taprootKeyPathSpend' ? 2 : calculateSignatureCount(parsedInput.signatures);
}
return 0;
}
else {
return calculateSignatureCount(parsePsbtInput(input).signatures);
}
}
/**
* @returns strictly parse input and get signature count for all inputs.
* 0=unsigned, 1=half-signed or 2=fully-signed
*/
function getStrictSignatureCounts(tx) {
const inputs = tx instanceof UtxoPsbt_1.UtxoPsbt ? tx.data.inputs : tx instanceof UtxoTransaction_1.UtxoTransaction ? tx.ins : tx;
return inputs.map((input, _) => getStrictSignatureCount(input));
}
/**
* @return true iff inputs array is of PsbtInputType type
* */
function isPsbtInputArray(inputs) {
return !isTxInputArray(inputs);
}
/**
* @return true iff inputs array is of TxInput type
* */
function isTxInputArray(inputs) {
assert(!!inputs.length, 'empty inputs array');
return 'hash' in inputs[0];
}
/**
* @returns true iff given psbt/transaction/tx-input-array/psbt-input-array contains at least one taproot key path spend input
*/
function isTransactionWithKeyPathSpendInput(data) {
const inputs = data instanceof UtxoPsbt_1.UtxoPsbt ? data.data.inputs : data instanceof UtxoTransaction_1.UtxoTransaction ? data.ins : data;
if (!inputs.length) {
return false;
}
if (isPsbtInputArray(inputs)) {
return inputs.some((input, _) => getPsbtInputScriptType(input) === 'taprootKeyPathSpend');
}
return inputs.some((input, _) => {
// If the input is not signed, it cannot be a taprootKeyPathSpend input because you can only
// extract a fully signed psbt into a transaction with taprootKeyPathSpend inputs.
if (getStrictSignatureCount(input) === 0) {
return false;
}
return (0, parseInput_1.parseSignatureScript)(input).scriptType === 'taprootKeyPathSpend';
});
}
/**
* Set the RootWalletKeys as the globalXpubs on the psbt
*
* We do all the matching of the (tap)bip32Derivations masterFingerprint to the fingerprint of the
* extendedPubkey.
*/
function addXpubsToPsbt(psbt, rootWalletKeys) {
const safeRootWalletKeys = new WalletKeys_1.RootWalletKeys(rootWalletKeys.triple.map((bip32) => bip32.neutered()), rootWalletKeys.derivationPrefixes);
const xPubs = safeRootWalletKeys.triple.map((bip32) => ({
extendedPubkey: bs58check.decode(bip32.toBase58()),
masterFingerprint: bip32.fingerprint,
// TODO: BG-73797 - bip174 currently requires m prefix for this to be a valid globalXpub
path: 'm',
}));
psbt.updateGlobal({ globalXpub: xPubs });
}
/**
* validates signatures for each 2 of 3 input against user, backup, bitgo keys derived from rootWalletKeys.
* @returns array of input index and its [is valid user sig exist, is valid backup sig exist, is valid user bitgo exist]
* For p2shP2pk input, [false, false, false] is returned since it is not a 2 of 3 sig input.
*/
function getSignatureValidationArrayPsbt(psbt, rootWalletKeys) {
return psbt.data.inputs.map((input, i) => {
const sigValArrayForInput = getPsbtInputScriptType(input) === 'p2shP2pk'
? [false, false, false]
: psbt.getSignatureValidationArray(i, { rootNodes: rootWalletKeys.triple });
return [i, sigValArrayForInput];
});
}
/**
* Extracts the half signed transaction from the psbt for p2ms based script types - p2sh, p2wsh, and p2shP2wsh.
* The purpose is to provide backward compatibility to keyternal (KRS) that only supports network transaction and p2ms script types.
*/
function extractP2msOnlyHalfSignedTx(psbt) {
assert(!!(psbt.data.inputs.length && psbt.data.outputs.length), 'empty inputs or outputs');
const tx = psbt.getUnsignedTx();
function isP2msParsedPsbtInput(parsed) {
return ['p2sh', 'p2shP2wsh', 'p2wsh'].includes(parsed.scriptType);
}
psbt.data.inputs.forEach((input, i) => {
const parsed = parsePsbtInput(input);
assert(isP2msParsedPsbtInput(parsed), `unsupported script type ${parsed.scriptType}`);
assert(input.partialSig?.length === 1, `unexpected signature count ${input.partialSig?.length}`);
const [partialSig] = input.partialSig;
assert(input.sighashType !== undefined && input.sighashType === bitcoinjs_lib_1.script.signature.decode(partialSig.signature).hashType, 'signature sighash does not match input sighash type');
// type casting is to address the invalid type checking in payments.p2ms
const signatures = parsed.publicKeys.map((pk) => partialSig.pubkey.equals(pk) ? partialSig.signature : bitcoinjs_lib_1.opcodes.OP_0);
const isP2SH = !!parsed.redeemScript;
const isP2WSH = !!parsed.witnessScript;
const payment = index_1.payments.p2ms({ output: parsed.pubScript, signatures }, { validate: false, allowIncomplete: true });
const p2wsh = isP2WSH ? index_1.payments.p2wsh({ redeem: payment }) : undefined;
const p2sh = isP2SH ? index_1.payments.p2sh({ redeem: p2wsh || payment }) : undefined;
if (p2sh?.input) {
tx.setInputScript(i, p2sh.input);
}
if (p2wsh?.witness) {
tx.setWitness(i, p2wsh.witness);
}
});
return tx;
}
/**
* Clones the psbt without nonWitnessUtxo for non-segwit inputs and witnessUtxo is added instead.
* It is not BIP-174 compliant, so use it carefully.
*/
function clonePsbtWithoutNonWitnessUtxo(psbt) {
const newPsbt = (0, transaction_1.createPsbtFromHex)(psbt.toHex(), psbt.network);
const txInputs = psbt.txInputs;
psbt.data.inputs.forEach((input, i) => {
if (input.nonWitnessUtxo && !input.witnessUtxo) {
const tx = (0, transaction_1.createTransactionFromBuffer)(input.nonWitnessUtxo, psbt.network, { amountType: 'bigint' });
if (!txInputs[i].hash.equals(tx.getHash())) {
throw new Error(`Non-witness UTXO hash for input #${i} doesn't match the hash specified in the prevout`);
}
newPsbt.data.inputs[i].witnessUtxo = tx.outs[txInputs[i].index];
}
delete newPsbt.data.inputs[i].nonWitnessUtxo;
});
return newPsbt;
}
/**
* Returns true if there are non-segwit inputs in the PSBT that do not contain the
* nonWitnessUtxo.
*
* isPsbtLite(clonePsbtWithoutNonWitnessUtxo(psbt)) === true
*
* @param psbt
*/
function isPsbtLite(psbt) {
let isFull = true;
const nonSegwitInputTypes = ['p2shP2pk', 'p2sh'];
psbt.data.inputs.forEach((input) => {
if (isFull && nonSegwitInputTypes.includes(getPsbtInputScriptType(input))) {
isFull = !!input.nonWitnessUtxo;
}
});
return !isFull;
}
/**
* Deletes witnessUtxo for non-segwit inputs to make the PSBT BIP-174 compliant.
*/
function deleteWitnessUtxoForNonSegwitInputs(psbt) {
psbt.data.inputs.forEach((input, i) => {
const scriptType = getPsbtInputScriptType(input);
if (scriptType === 'p2sh' || scriptType === 'p2shP2pk') {
delete input.witnessUtxo;
}
});
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHNidC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9iaXRnby93YWxsZXQvUHNidC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQStMQSxvQ0FnQkM7QUFTRCx3Q0FZQztBQUtELHdEQXlDQztBQXlFRCx3Q0FzREM7QUFPRCw4Q0FNQztBQU1ELDBEQW9CQztBQU1ELDREQUtDO0FBS0QsNENBRUM7QUFLRCx3Q0FHQztBQUtELGdGQWtCQztBQVFELHdDQWNDO0FBT0QsMEVBUUM7QUFNRCxrRUF5Q0M7QUFNRCx3RUFnQkM7QUFVRCxnQ0FTQztBQUtELGtGQU9DO0FBbG5CRCxpQ0FBaUM7QUFHakMsZ0RBQXFEO0FBRXJELHVDQUF1QztBQUN2QywwQ0FBdUM7QUFDdkMsd0RBQXFEO0FBQ3JELG9EQU0wQjtBQUMxQiw2Q0FBaUU7QUFDakUsd0NBQW9EO0FBQ3BELGdEQUEyRztBQUMzRyx1Q0FBMkQ7QUFFM0QsOENBZXVCO0FBQ3ZCLHNDQUF1RDtBQUN2RCxvQ0FBMkM7QUFDM0MsMkNBQTBEO0FBQzFELGlEQUEyRTtBQUMzRSx1Q0FBZ0Q7QUFDaEQsMENBQStFO0FBcUUvRSxTQUFTLGlCQUFpQixDQUFDLE1BQWMsRUFBRSxVQUE2QjtJQUN0RSxNQUFNLGdCQUFnQixHQUFHLElBQUEsK0JBQWtCLEVBQUMsTUFBTSxFQUFFLHdCQUF3QixDQUFDLENBQUMsVUFBVSxDQUFDO0lBQ3pGLE1BQU0sYUFBYSxHQUFHLGdCQUFnQixDQUFDLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFO1FBQ3ZELE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FDaEUsSUFBQSxnQ0FBZ0IsRUFBQyxlQUFlLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQ3BELENBQUM7UUFDRixJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNmLE9BQU8sRUFBRSxT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QUMsS0FBSyxDQUFDLENBQUM7UUFDbEUsQ0FBQztRQUNELE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDO0lBQy9DLENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFnQixVQUFVLENBQUMsSUFBYztJQUN2QyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDbEIsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUNqQyxJQUFJLE1BQU0sSUFBSSxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzFFLE1BQU0sR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQztRQUNsQyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFDSCxPQUFPLENBQUMsTUFBTSxDQUFDO0FBQ2pCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLG1DQUFtQyxDQUFDLElBQWM7SUFDaEUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxFQUFFO1FBQ3BDLE1BQU0sVUFBVSxHQUFHLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pELElBQUksVUFBVSxLQUFLLE1BQU0sSUFBSSxVQUFVLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDdkQsT0FBTyxLQUFLLENBQUMsV0FBVyxDQUFDO1FBQzNCLENBQUM7SUFDSCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBhc3NlcnQgZnJvbSAnYXNzZXJ0JztcblxuaW1wb3J0IHsgR2xvYmFsWHB1YiwgUGFydGlhbFNpZywgUHNidElucHV0LCBUYXBTY3JpcHRTaWcgfSBmcm9tICdiaXAxNzQvc3JjL2xpYi9pbnRlcmZhY2VzJztcbmltcG9ydCB7IGNoZWNrRm9ySW5wdXQgfSBmcm9tICdiaXAxNzQvc3JjL2xpYi91dGlscyc7XG5pbXBvcnQgeyBCSVAzMkludGVyZmFjZSB9IGZyb20gJ2JpcDMyJztcbmltcG9ydCAqIGFzIGJzNThjaGVjayBmcm9tICdiczU4Y2hlY2snO1xuaW1wb3J0IHsgVXR4b1BzYnQgfSBmcm9tICcuLi9VdHhvUHNidCc7XG5pbXBvcnQgeyBVdHhvVHJhbnNhY3Rpb24gfSBmcm9tICcuLi9VdHhvVHJhbnNhY3Rpb24nO1xuaW1wb3J0IHtcbiAgY3JlYXRlT3V0cHV0U2NyaXB0Mm9mMyxcbiAgZ2V0TGVhZkhhc2gsXG4gIFNjcmlwdFR5cGUyT2YzLFxuICBzY3JpcHRUeXBlRm9yQ2hhaW4sXG4gIHRvWE9ubHlQdWJsaWNLZXksXG59IGZyb20gJy4uL291dHB1dFNjcmlwdHMnO1xuaW1wb3J0IHsgRGVyaXZlZFdhbGxldEtleXMsIFJvb3RXYWxsZXRLZXlzIH0gZnJvbSAnLi9XYWxsZXRLZXlzJztcbmltcG9ydCB7IHRvUHJldk91dHB1dFdpdGhQcmV2VHggfSBmcm9tICcuLi9VbnNwZW50JztcbmltcG9ydCB7IGNyZWF0ZVBzYnRGcm9tSGV4LCBjcmVhdGVQc2J0RnJvbVRyYW5zYWN0aW9uLCBjcmVhdGVUcmFuc2FjdGlvbkZyb21CdWZmZXIgfSBmcm9tICcuLi90cmFuc2FjdGlvbic7XG5pbXBvcnQgeyBpc1dhbGxldFVuc3BlbnQsIFdhbGxldFVuc3BlbnQgfSBmcm9tICcuL1Vuc3BlbnQnO1xuXG5pbXBvcnQge1xuICBnZXRMZWFmVmVyc2lvbixcbiAgY2FsY3VsYXRlU2NyaXB0UGF0aExldmVsLFxuICBpc1ZhbGlkQ29udHJvbEJvY2ssXG4gIFBhcnNlZFB1YlNjcmlwdFAybXMsXG4gIFBhcnNlZFB1YlNjcmlwdFRhcHJvb3RTY3JpcHRQYXRoLFxuICBwYXJzZVB1YlNjcmlwdDJPZjMsXG4gIFBhcnNlZFB1YlNjcmlwdFRhcHJvb3QsXG4gIFBhcnNlZFB1YlNjcmlwdFRhcHJvb3RLZXlQYXRoLFxuICBwYXJzZVB1YlNjcmlwdCxcbiAgUGFyc2VkUHViU2NyaXB0UDJzaFAycGssXG4gIFBhcnNlZFNjcmlwdFR5cGUsXG4gIGlzUGxhY2Vob2xkZXJTaWduYXR1cmUsXG4gIHBhcnNlU2lnbmF0dXJlU2NyaXB0LFxuICBQYXJzZWRTY3JpcHRUeXBlMk9mMyxcbn0gZnJvbSAnLi4vcGFyc2VJbnB1dCc7XG5pbXBvcnQgeyBwYXJzZVBzYnRNdXNpZzJQYXJ0aWFsU2lncyB9IGZyb20gJy4uL011c2lnMic7XG5pbXBvcnQgeyBpc1R1cGxlLCBUcmlwbGUgfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQgeyBjcmVhdGVUYXByb290T3V0cHV0U2NyaXB0IH0gZnJvbSAnLi4vLi4vdGFwcm9vdCc7XG5pbXBvcnQgeyBvcGNvZGVzIGFzIG9wcywgc2NyaXB0IGFzIGJzY3JpcHQsIFR4SW5wdXQgfSBmcm9tICdiaXRjb2luanMtbGliJztcbmltcG9ydCB7IG9wY29kZXMsIHBheW1lbnRzIH0gZnJvbSAnLi4vLi4vaW5kZXgnO1xuaW1wb3J0IHsgZ2V0UHNidElucHV0U2lnbmF0dXJlQ291bnQsIGlzUHNidElucHV0RmluYWxpemVkIH0gZnJvbSAnLi4vUHNidFV0aWwnO1xuXG4vLyBvbmx5IHVzZWQgZm9yIGJ1aWxkaW5nIGBTaWduYXR1cmVDb250YWluZXJgXG50eXBlIEJhc2VTaWduYXR1cmVDb250YWluZXI8VD4gPSB7XG4gIHNpZ25hdHVyZXM6IFQ7XG59O1xuXG50eXBlIFVuc2lnbmVkU2lnbmF0dXJlQ29udGFpbmVyID0gQmFzZVNpZ25hdHVyZUNvbnRhaW5lcjx1bmRlZmluZWQ+O1xudHlwZSBIYWxmU2lnbmVkU2lnbmF0dXJlQ29udGFpbmVyID0gQmFzZVNpZ25hdHVyZUNvbnRhaW5lcjxbQnVmZmVyXT47XG50eXBlIEZ1bGxTaWduZWRTaWduYXR1cmVDb250YWluZXIgPSBCYXNlU2lnbmF0dXJlQ29udGFpbmVyPFtCdWZmZXIsIEJ1ZmZlcl0+O1xuXG50eXBlIFNpZ25hdHVyZUNvbnRhaW5lciA9IFVuc2lnbmVkU2lnbmF0dXJlQ29udGFpbmVyIHwgSGFsZlNpZ25lZFNpZ25hdHVyZUNvbnRhaW5lciB8IEZ1bGxTaWduZWRTaWduYXR1cmVDb250YWluZXI7XG5cbi8qKlxuICogQ29udGVudHMgb2YgYSBwcmUtZmluYWxpemVkIFBTQlQgSW5wdXQgZm9yIHAydHJNdXNpZzIga2V5IHBhdGggaW4gdGhlIG5vbi1maW5hbGl6ZWQgc3RhdGUuXG4gKiBUIGlzIFtCdWZmZXJdIGZvciBmaXJzdCBzaWduYXR1cmUsIFtCdWZmZXIsIEJ1ZmZlcl0gZm9yIGJvdGggc2lnbmF0dXJlcyBhbmQgYHVuZGVmaW5lZGAgZm9yIG5vIHNpZ25hdHVyZXMuXG4gKi9cbnR5cGUgQmFzZVRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlQ29udGFpbmVyPFQ+ID0ge1xuICBzaWduYXR1cmVzOiBUO1xuICAvKiogT25seSBjb250YWlucyBwYXJ0aWNpcGFudHMgdGhhdCBoYXZlIGFkZGVkIGEgc2lnbmF0dXJlICovXG4gIHBhcnRpY2lwYW50UHVibGljS2V5czogVDtcbn07XG5cbnR5cGUgVW5zaWduZWRUYXByb290S2V5UGF0aFNpZ25hdHVyZUNvbnRhaW5lciA9IEJhc2VUYXByb290S2V5UGF0aFNpZ25hdHVyZUNvbnRhaW5lcjx1bmRlZmluZWQ+O1xudHlwZSBIYWxmU2lnbmVkVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXIgPSBCYXNlVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXI8W0J1ZmZlcl0+O1xudHlwZSBGdWxsU2lnbmVkVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXIgPSBCYXNlVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXI8W0J1ZmZlciwgQnVmZmVyXT47XG5cbnR5cGUgVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXIgPVxuICB8IFVuc2lnbmVkVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXJcbiAgfCBIYWxmU2lnbmVkVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXJcbiAgfCBGdWxsU2lnbmVkVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXI7XG5cbi8qKlxuICogVG8gaG9sZCBwYXJzZWQgcHNidCBkYXRhIGZvciBwMm1zIGJhc2VkIHNjcmlwdCB0eXBlcyAtIHAyc2gsIHAyd3NoLCBhbmQgcDJzaFAyd3NoXG4gKi9cbmV4cG9ydCB0eXBlIFBhcnNlZFBzYnRQMm1zID0gUGFyc2VkUHViU2NyaXB0UDJtcyAmIFNpZ25hdHVyZUNvbnRhaW5lcjtcblxuLyoqXG4gKiBUbyBob2xkIHBhcnNlZCBwc2J0IGRhdGEgZm9yIFRhcHJvb3RLZXlQYXRoU3BlbmQgc2NyaXB0IHR5cGUuXG4gKi9cbmV4cG9ydCB0eXBlIFBhcnNlZFBzYnRUYXByb290S2V5UGF0aCA9IFBhcnNlZFB1YlNjcmlwdFRhcHJvb3RLZXlQYXRoICYgVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXI7XG5cbi8qKlxuICogVG8gaG9sZCBwYXJzZWQgcHNidCBkYXRhIGZvciBUYXByb290U2NyaXB0UGF0aFNwZW5kIHNjcmlwdCBwYXRoIHNjcmlwdCB0eXBlLlxuICovXG5leHBvcnQgdHlwZSBQYXJzZWRQc2J0VGFwcm9vdFNjcmlwdFBhdGggPSBQYXJzZWRQdWJTY3JpcHRUYXByb290U2NyaXB0UGF0aCAmXG4gIFNpZ25hdHVyZUNvbnRhaW5lciAmIHtcbiAgICBjb250cm9sQmxvY2s6IEJ1ZmZlcjtcbiAgICBsZWFmVmVyc2lvbjogbnVtYmVyO1xuICAgIC8qKiBJbmRpY2F0ZXMgdGhlIGxldmVsIGluc2lkZSB0aGUgdGFwdHJlZS4gKi9cbiAgICBzY3JpcHRQYXRoTGV2ZWw6IG51bWJlcjtcbiAgfTtcblxuZXhwb3J0IHR5cGUgUGFyc2VkUHNidFRhcHJvb3QgPSBQYXJzZWRQc2J0VGFwcm9vdEtleVBhdGggfCBQYXJzZWRQc2J0VGFwcm9vdFNjcmlwdFBhdGg7XG5cbnR5cGUgUDJzaFAycGtTaWduYXR1cmVDb250YWluZXIgPSBVbnNpZ25lZFNpZ25hdHVyZUNvbnRhaW5lciB8IEhhbGZTaWduZWRTaWduYXR1cmVDb250YWluZXI7XG5cbmV4cG9ydCB0eXBlIFBhcnNlZFBzYnRQMnNoUDJwayA9IFBhcnNlZFB1YlNjcmlwdFAyc2hQMnBrICYgUDJzaFAycGtTaWduYXR1cmVDb250YWluZXI7XG5cbmludGVyZmFjZSBXYWxsZXRTaWduZXIge1xuICB3YWxsZXRLZXk6IEJJUDMySW50ZXJmYWNlO1xuICByb290S2V5OiBCSVAzMkludGVyZmFjZTtcbn1cblxuLyoqXG4gKiBwc2J0IGlucHV0IGluZGV4IGFuZCBpdHMgdXNlciwgYmFja3VwLCBiaXRnbyBzaWduYXR1cmVzIHN0YXR1c1xuICovXG5leHBvcnQgdHlwZSBTaWduYXR1cmVWYWxpZGF0aW9uID0gW2luZGV4OiBudW1iZXIsIHNpZ1RyaXBsZTogVHJpcGxlPGJvb2xlYW4+XTtcblxuZnVuY3Rpb24gZ2V0VGFwcm9vdFNpZ25lcnMoc2NyaXB0OiBCdWZmZXIsIHdhbGxldEtleXM6IERlcml2ZWRXYWxsZXRLZXlzKTogW1dhbGxldFNpZ25lciwgV2FsbGV0U2lnbmVyXSB7XG4gIGNvbnN0IHBhcnNlZFB1YmxpY0tleXMgPSBwYXJzZVB1YlNjcmlwdDJPZjMoc2NyaXB0LCAndGFwcm9vdFNjcmlwdFBhdGhTcGVuZCcpLnB1YmxpY0tleXM7XG4gIGNvbnN0IHdhbGxldFNpZ25lcnMgPSBwYXJzZWRQdWJsaWNLZXlzLm1hcCgocHVibGljS2V5KSA9PiB7XG4gICAgY29uc3QgaW5kZXggPSB3YWxsZXRLZXlzLnB1YmxpY0tleXMuZmluZEluZGV4KCh3YWxsZXRQdWJsaWNLZXkpID0+XG4gICAgICB0b1hPbmx5UHVibGljS2V5KHdhbGxldFB1YmxpY0tleSkuZXF1YWxzKHB1YmxpY0tleSlcbiAgICApO1xuICAgIGlmIChpbmRleCA+PSAwKSB7XG4gICAgICByZXR1cm4geyB3YWxsZXRLZXk6IHdhbGxldEtleXMudHJpcGxlW2luZGV4XSwgcm9vdEtleTogd2FsbGV0S2V5cy5wYXJlbnQudHJpcGxlW2luZGV4XSB9O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RhcHJvb3QgcHVibGljIGtleSBpcyBub3QgYSB3YWxsZXQgcHVibGljIGtleScpO1xuICB9KTtcbiAgcmV0dXJuIFt3YWxsZXRTaWduZXJzWzBdLCB3YWxsZXRTaWduZXJzWzFdXTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlUHNidElucHV0KFxuICBwc2J0OiBVdHhvUHNidCxcbiAgaW5wdXRJbmRleDogbnVtYmVyLFxuICB1bnNwZW50OiBXYWxsZXRVbnNwZW50PGJpZ2ludD4sXG4gIHJvb3RXYWxsZXRLZXlzOiBSb290V2FsbGV0S2V5c1xuKTogdm9pZCB7XG4gIGNvbnN0IGlucHV0ID0gY2hlY2tGb3JJbnB1dChwc2J0LmRhdGEuaW5wdXRzLCBpbnB1dEluZGV4KTtcbiAgY29uc3Qgc2lnbmF0dXJlQ291bnQgPSBnZXRQc2J0SW5wdXRTaWduYXR1cmVDb3VudChpbnB1dCk7XG4gIGNvbnN0IHNjcmlwdFR5cGUgPSBzY3JpcHRUeXBlRm9yQ2hhaW4odW5zcGVudC5jaGFpbik7XG4gIGlmIChzaWduYXR1cmVDb3VudCA9PT0gMCAmJiBzY3JpcHRUeXBlID09PSAncDJ0cicpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgY29uc3Qgd2FsbGV0S2V5cyA9IHJvb3RXYWxsZXRLZXlzLmRlcml2ZUZvckNoYWluQW5kSW5kZXgodW5zcGVudC5jaGFpbiwgdW5zcGVudC5pbmRleCk7XG5cbiAgaWYgKHNjcmlwdFR5cGUgPT09ICdwMnRyJykge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShpbnB1dC50YXBMZWFmU2NyaXB0KSB8fCBpbnB1dC50YXBMZWFmU2NyaXB0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFBTQlQgc3RhdGUuIE1pc3NpbmcgcmVxdWlyZWQgZmllbGRzLicpO1xuICAgIH1cblxuICAgIGlmIChpbnB1dC50YXBMZWFmU2NyaXB0Lmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQml0Z28gb25seSBzdXBwb3J0cyBhIHNpbmdsZSB0YXAgbGVhZiBzY3JpcHQgcGVyIGlucHV0Jyk7XG4gICAgfVxuXG4gICAgY29uc3QgW3NpZ25lciwgY29zaWduZXJdID0gZ2V0VGFwcm9vdFNpZ25lcnMoaW5wdXQudGFwTGVhZlNjcmlwdFswXS5zY3JpcHQsIHdhbGxldEtleXMpO1xuXG4gICAgY29uc3QgbGVhZkhhc2ggPSBnZXRMZWFmSGFzaCh7XG4gICAgICBwdWJsaWNLZXlzOiB3YWxsZXRLZXlzLnB1YmxpY0tleXMsXG4gICAgICBzaWduZXI6IHNpZ25lci53YWxsZXRLZXkucHVibGljS2V5LFxuICAgICAgY29zaWduZXI6IGNvc2lnbmVyLndhbGxldEtleS5wdWJsaWNLZXksXG4gICAgfSk7XG5cbiAgICBwc2J0LnVwZGF0ZUlucHV0KGlucHV0SW5kZXgsIHtcbiAgICAgIHRhcEJpcDMyRGVyaXZhdGlvbjogW3NpZ25lciwgY29zaWduZXJdLm1hcCgod2FsbGV0U2lnbmVyKSA9PiAoe1xuICAgICAgICBsZWFmSGFzaGVzOiBbbGVhZkhhc2hdLFxuICAgICAgICBwdWJrZXk6IHRvWE9ubHlQdWJsaWNLZXkod2FsbGV0U2lnbmVyLndhbGxldEtleS5wdWJsaWNLZXkpLFxuICAgICAgICBwYXRoOiByb290V2FsbGV0S2V5cy5nZXREZXJpdmF0aW9uUGF0aCh3YWxsZXRTaWduZXIucm9vdEtleSwgdW5zcGVudC5jaGFpbiwgdW5zcGVudC5pbmRleCksXG4gICAgICAgIG1hc3RlckZpbmdlcnByaW50OiB3YWxsZXRTaWduZXIucm9vdEtleS5maW5nZXJwcmludCxcbiAgICAgIH0pKSxcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoc2lnbmF0dXJlQ291bnQgPT09IDApIHtcbiAgICAgIGNvbnN0IHsgd2l0bmVzc1NjcmlwdCwgcmVkZWVtU2NyaXB0IH0gPSBjcmVhdGVPdXRwdXRTY3JpcHQyb2YzKHdhbGxldEtleXMucHVibGljS2V5cywgc2NyaXB0VHlwZSk7XG4gICAgICBpZiAod2l0bmVzc1NjcmlwdCAmJiBwc2J0LmRhdGEuaW5wdXRzW2lucHV0SW5kZXhdLndpdG5lc3NTY3JpcHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBwc2J0LnVwZGF0ZUlucHV0KGlucHV0SW5kZXgsIHsgd2l0bmVzc1NjcmlwdCB9KTtcbiAgICAgIH1cbiAgICAgIGlmIChyZWRlZW1TY3JpcHQgJiYgcHNidC5kYXRhLmlucHV0c1tpbnB1dEluZGV4XS5yZWRlZW1TY3JpcHQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBwc2J0LnVwZGF0ZUlucHV0KGlucHV0SW5kZXgsIHsgcmVkZWVtU2NyaXB0IH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHBzYnQudXBkYXRlSW5wdXQoaW5wdXRJbmRleCwge1xuICAgICAgYmlwMzJEZXJpdmF0aW9uOiBbMCwgMSwgMl0ubWFwKChpZHgpID0+ICh7XG4gICAgICAgIHB1YmtleTogd2FsbGV0S2V5cy50cmlwbGVbaWR4XS5wdWJsaWNLZXksXG4gICAgICAgIHBhdGg6IHdhbGxldEtleXMucGF0aHNbaWR4XSxcbiAgICAgICAgbWFzdGVyRmluZ2VycHJpbnQ6IHJvb3RXYWxsZXRLZXlzLnRyaXBsZVtpZHhdLmZpbmdlcnByaW50LFxuICAgICAgfSkpLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQHJldHVybiBQU0JUIGZpbGxlZCB3aXRoIG1ldGF0ZGF0YSBhcyBwZXIgaW5wdXQgcGFyYW1zIHR4LCB1bnNwZW50cyBhbmQgcm9vdFdhbGxldEtleXMuXG4gKiBVbnNpZ25lZCBQU0JUIGZvciB0YXByb290IGlucHV0IHdpdGggd2l0bmVzc1V0eG9cbiAqIFVuc2lnbmVkIFBTQlQgZm9yIG90aGVyIGlucHV0IHdpdGggd2l0bmVzc1V0eG8vbm9uV2l0bmVzc1V0eG8sIHJlZGVlbVNjcmlwdC93aXRuZXNzU2NyaXB0LCBiaXAzMkRlcml2YXRpb25cbiAqIFNpZ25lZCBQU0JUIGZvciB0YXByb290IGlucHV0IHdpdGggd2l0bmVzc1V0eG8sIHRhcExlYWZTY3JpcHQsIHRhcEJpcDMyRGVyaXZhdGlvbiwgdGFwU2NyaXB0U2lnXG4gKiBTaWduZWQgUFNCVCBmb3Igb3RoZXIgaW5wdXQgd2l0aCB3aXRuZXNzVXR4by9ub25XaXRuZXNzVXR4bywgcmVkZWVtU2NyaXB0L3dpdG5lc3NTY3JpcHQsIGJpcDMyRGVyaXZhdGlvbiwgcGFydGlhbFNpZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdG9XYWxsZXRQc2J0KFxuICB0eDogVXR4b1RyYW5zYWN0aW9uPGJpZ2ludD4sXG4gIHVuc3BlbnRzOiBXYWxsZXRVbnNwZW50PGJpZ2ludD5bXSxcbiAgcm9vdFdhbGxldEtleXM6IFJvb3RXYWxsZXRLZXlzXG4pOiBVdHhvUHNidCB7XG4gIGNvbnN0IHByZXZPdXRwdXRzID0gdW5zcGVudHMubWFwKCh1KSA9PiB7XG4gICAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKHNjcmlwdFR5cGVGb3JDaGFpbih1LmNoYWluKSwgJ3AydHJNdXNpZzInKTtcbiAgICByZXR1cm4gdG9QcmV2T3V0cHV0V2l0aFByZXZUeCh1LCB0eC5uZXR3b3JrKTtcbiAgfSk7XG4gIGNvbnN0IHBzYnQgPSBjcmVhdGVQc2J0RnJvbVRyYW5zYWN0aW9uKHR4LCBwcmV2T3V0cHV0cyk7XG4gIHVuc3BlbnRzLmZvckVhY2goKHUsIGkpID0+IHtcbiAgICBpZiAoaXNXYWxsZXRVbnNwZW50KHUpICYmIHUuaW5kZXggIT09IHVuZGVmaW5lZCkge1xuICAgICAgdXBkYXRlUHNidElucHV0KHBzYnQsIGksIHUsIHJvb3RXYWxsZXRLZXlzKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gcHNidDtcbn1cblxuLyoqXG4gKiBAcGFyYW0gcHNidFxuICogQHBhcmFtIGlucHV0SW5kZXhcbiAqIEBwYXJhbSBzaWduZXJcbiAqIEBwYXJhbSB1bnNwZW50XG4gKiBAcmV0dXJuIHNpZ25lZCBQU0JUIHdpdGggc2lnbmVyJ3Mga2V5IGZvciB1bnNwZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduV2FsbGV0UHNidChcbiAgcHNidDogVXR4b1BzYnQsXG4gIGlucHV0SW5kZXg6IG51bWJlcixcbiAgc2lnbmVyOiBCSVAzMkludGVyZmFjZSxcbiAgdW5zcGVudDogV2FsbGV0VW5zcGVudDxiaWdpbnQ+XG4pOiB2b2lkIHtcbiAgY29uc3Qgc2NyaXB0VHlwZSA9IHNjcmlwdFR5cGVGb3JDaGFpbih1bnNwZW50LmNoYWluKTtcbiAgaWYgKHNjcmlwdFR5cGUgPT09ICdwMnRyJyB8fCBzY3JpcHRUeXBlID09PSAncDJ0ck11c2lnMicpIHtcbiAgICBwc2J0LnNpZ25UYXByb290SW5wdXRIRChpbnB1dEluZGV4LCBzaWduZXIpO1xuICB9IGVsc2Uge1xuICAgIHBzYnQuc2lnbklucHV0SEQoaW5wdXRJbmRleCwgc2lnbmVyKTtcbiAgfVxufVxuXG4vKipcbiAqIEByZXR1cm5zIHNjcmlwdCB0eXBlIG9mIHRoZSBpbnB1dFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0UHNidElucHV0U2NyaXB0VHlwZShpbnB1dDogUHNidElucHV0KTogUGFyc2VkU2NyaXB0VHlwZSB7XG4gIGNvbnN0IGlzUDJwayA9IChzY3JpcHQ6IEJ1ZmZlcikgPT4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjaHVua3MgPSBic2NyaXB0LmRlY29tcGlsZShzY3JpcHQpO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgY2h1bmtzPy5sZW5ndGggPT09IDIgJiZcbiAgICAgICAgQnVmZmVyLmlzQnVmZmVyKGNodW5rc1swXSkgJiZcbiAgICAgICAgYnNjcmlwdC5pc0Nhbm9uaWNhbFB1YktleShjaHVua3NbMF0pICYmXG4gICAgICAgIGNodW5rc1sxXSA9PT0gb3Bjb2Rlcy5PUF9DSEVDS1NJR1xuICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9O1xuICBsZXQgc2NyaXB0VHlwZTogUGFyc2VkU2NyaXB0VHlwZSB8IHVuZGVmaW5lZDtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihpbnB1dC5yZWRlZW1TY3JpcHQpICYmIEJ1ZmZlci5pc0J1ZmZlcihpbnB1dC53aXRuZXNzU2NyaXB0KSkge1xuICAgIHNjcmlwdFR5cGUgPSAncDJzaFAyd3NoJztcbiAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIoaW5wdXQucmVkZWVtU2NyaXB0KSkge1xuICAgIHNjcmlwdFR5cGUgPSBpc1AycGsoaW5wdXQucmVkZWVtU2NyaXB0KSA/ICdwMnNoUDJwaycgOiAncDJzaCc7XG4gIH0gZWxzZSBpZiAoQnVmZmVyLmlzQnVmZmVyKGlucHV0LndpdG5lc3NTY3JpcHQpKSB7XG4gICAgc2NyaXB0VHlwZSA9ICdwMndzaCc7XG4gIH1cbiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQudGFwTGVhZlNjcmlwdCkgJiYgaW5wdXQudGFwTGVhZlNjcmlwdC5sZW5ndGggPiAwKSB7XG4gICAgaWYgKHNjcmlwdFR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRm91bmQgYm90aCAke3NjcmlwdFR5cGV9IGFuZCB0YXByb290U2NyaXB0UGF0aCBQU0JUIG1ldGFkYXRhLmApO1xuICAgIH1cbiAgICBpZiAoaW5wdXQudGFwTGVhZlNjcmlwdC5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0JpdGdvIG9ubHkgc3VwcG9ydHMgYSBzaW5nbGUgdGFwIGxlYWYgc2NyaXB0IHBlciBpbnB1dC4nKTtcbiAgICB9XG4gICAgc2NyaXB0VHlwZSA9ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJztcbiAgfVxuICBpZiAoaW5wdXQudGFwSW50ZXJuYWxLZXkpIHtcbiAgICBpZiAoc2NyaXB0VHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGb3VuZCBib3RoICR7c2NyaXB0VHlwZX0gYW5kIHRhcHJvb3RLZXlQYXRoIFBTQlQgbWV0YWRhdGEuYCk7XG4gICAgfVxuICAgIHNjcmlwdFR5cGUgPSAndGFwcm9vdEtleVBhdGhTcGVuZCc7XG4gIH1cbiAgaWYgKHNjcmlwdFR5cGUpIHtcbiAgICByZXR1cm4gc2NyaXB0VHlwZTtcbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoJ2NvdWxkIG5vdCBwYXJzZSBpbnB1dCcpO1xufVxuXG5mdW5jdGlvbiBwYXJzZVRhcHJvb3RLZXlQYXRoU2lnbmF0dXJlcyhpbnB1dDogUHNidElucHV0KTogVGFwcm9vdEtleVBhdGhTaWduYXR1cmVDb250YWluZXIge1xuICBjb25zdCBwYXJ0aWFsU2lncyA9IHBhcnNlUHNidE11c2lnMlBhcnRpYWxTaWdzKGlucHV0KTtcbiAgaWYgKCFwYXJ0aWFsU2lncykge1xuICAgIHJldHVybiB7IHNpZ25hdHVyZXM6IHVuZGVmaW5lZCwgcGFydGljaXBhbnRQdWJsaWNLZXlzOiB1bmRlZmluZWQgfTtcbiAgfVxuICBjb25zdCBzaWduYXR1cmVzID0gcGFydGlhbFNpZ3MubWFwKChwU2lnKSA9PiBwU2lnLnBhcnRpYWxTaWcpO1xuICBjb25zdCBwYXJ0aWNpcGFudFB1YmxpY0tleXMgPSBwYXJ0aWFsU2lncy5tYXAoKHBTaWcpID0+IHBTaWcucGFydGljaXBhbnRQdWJLZXkpO1xuICByZXR1cm4gaXNUdXBsZTxCdWZmZXI+KHNpZ25hdHVyZXMpICYmIGlzVHVwbGU8QnVmZmVyPihwYXJ0aWNpcGFudFB1YmxpY0tleXMpXG4gICAgPyB7IHNpZ25hdHVyZXMsIHBhcnRpY2lwYW50UHVibGljS2V5cyB9XG4gICAgOiB7IHNpZ25hdHVyZXM6IFtzaWduYXR1cmVzWzBdXSwgcGFydGljaXBhbnRQdWJsaWNLZXlzOiBbcGFydGljaXBhbnRQdWJsaWNLZXlzWzBdXSB9O1xufVxuXG5mdW5jdGlvbiBwYXJzZVBhcnRpYWxPclRhcFNjcmlwdFNpZ25hdHVyZXMoc2lnOiBQYXJ0aWFsU2lnW10gfCBUYXBTY3JpcHRTaWdbXSB8IHVuZGVmaW5lZCk6IFNpZ25hdHVyZUNvbnRhaW5lciB7XG4gIGlmICghc2lnPy5sZW5ndGgpIHtcbiAgICByZXR1cm4geyBzaWduYXR1cmVzOiB1bmRlZmluZWQgfTtcbiAgfVxuICBpZiAoc2lnLmxlbmd0aCA+IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VuZXhwZWN0ZWQgc2lnbmF0dXJlIGNvdW50Jyk7XG4gIH1cbiAgY29uc3Qgc2lnbmF0dXJlcyA9IHNpZy5tYXAoKHRTaWcpID0+IHRTaWcuc2lnbmF0dXJlKTtcbiAgcmV0dXJuIGlzVHVwbGU8QnVmZmVyPihzaWduYXR1cmVzKSA/IHsgc2lnbmF0dXJlcyB9IDogeyBzaWduYXR1cmVzOiBbc2lnbmF0dXJlc1swXV0gfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VTaWduYXR1cmVzKFxuICBpbnB1dDogUHNidElucHV0LFxuICBzY3JpcHRUeXBlOiBQYXJzZWRTY3JpcHRUeXBlXG4pOiBTaWduYXR1cmVDb250YWluZXIgfCBUYXByb290S2V5UGF0aFNpZ25hdHVyZUNvbnRhaW5lciB7XG4gIHJldHVybiBzY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCdcbiAgICA/IHBhcnNlVGFwcm9vdEtleVBhdGhTaWduYXR1cmVzKGlucHV0KVxuICAgIDogc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RTY3JpcHRQYXRoU3BlbmQnXG4gICAgPyBwYXJzZVBhcnRpYWxPclRhcFNjcmlwdFNpZ25hdHVyZXMoaW5wdXQudGFwU2NyaXB0U2lnKVxuICAgIDogcGFyc2VQYXJ0aWFsT3JUYXBTY3JpcHRTaWduYXR1cmVzKGlucHV0LnBhcnRpYWxTaWcpO1xufVxuXG5mdW5jdGlvbiBwYXJzZVNjcmlwdChcbiAgaW5wdXQ6IFBzYnRJbnB1dCxcbiAgc2NyaXB0VHlwZTogUGFyc2VkU2NyaXB0VHlwZVxuKTogUGFyc2VkUHViU2NyaXB0UDJtcyB8IFBhcnNlZFB1YlNjcmlwdFRhcHJvb3QgfCBQYXJzZWRQdWJTY3JpcHRQMnNoUDJwayB7XG4gIGxldCBwdWJTY3JpcHQ6IEJ1ZmZlciB8IHVuZGVmaW5lZDtcbiAgaWYgKHNjcmlwdFR5cGUgPT09ICdwMnNoJyB8fCBzY3JpcHRUeXBlID09PSAncDJzaFAycGsnKSB7XG4gICAgcHViU2NyaXB0ID0gaW5wdXQucmVkZWVtU2NyaXB0O1xuICB9IGVsc2UgaWYgKHNjcmlwdFR5cGUgPT09ICdwMndzaCcgfHwgc2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMndzaCcpIHtcbiAgICBwdWJTY3JpcHQgPSBpbnB1dC53aXRuZXNzU2NyaXB0O1xuICB9IGVsc2UgaWYgKHNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJykge1xuICAgIHB1YlNjcmlwdCA9IGlucHV0LnRhcExlYWZTY3JpcHQgPyBpbnB1dC50YXBMZWFmU2NyaXB0WzBdLnNjcmlwdCA6IHVuZGVmaW5lZDtcbiAgfSBlbHNlIGlmIChzY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCcpIHtcbiAgICBpZiAoaW5wdXQud2l0bmVzc1V0eG8/LnNjcmlwdCkge1xuICAgICAgcHViU2NyaXB0ID0gaW5wdXQud2l0bmVzc1V0eG8uc2NyaXB0O1xuICAgIH0gZWxzZSBpZiAoaW5wdXQudGFwSW50ZXJuYWxLZXkgJiYgaW5wdXQudGFwTWVya2xlUm9vdCkge1xuICAgICAgcHViU2NyaXB0ID0gY3JlYXRlVGFwcm9vdE91dHB1dFNjcmlwdCh7IGludGVybmFsUHViS2V5OiBpbnB1dC50YXBJbnRlcm5hbEtleSwgdGFwdHJlZVJvb3Q6IGlucHV0LnRhcE1lcmtsZVJvb3QgfSk7XG4gICAgfVxuICB9XG4gIGlmICghcHViU2NyaXB0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFBTQlQgc3RhdGUgZm9yICR7c2NyaXB0VHlwZX0uIE1pc3NpbmcgcmVxdWlyZWQgZmllbGRzLmApO1xuICB9XG4gIHJldHVybiBwYXJzZVB1YlNjcmlwdChwdWJTY3JpcHQsIHNjcmlwdFR5cGUpO1xufVxuXG4vKipcbiAqIEByZXR1cm4gcHNidCBtZXRhZGF0YSBhcmUgcGFyc2VkIGFzIHBlciBiZWxvdyBjb25kaXRpb25zLlxuICogcmVkZWVtU2NyaXB0L3dpdG5lc3NTY3JpcHQvdGFwTGVhZlNjcmlwdCBtYXRjaGVzIEJpdEdvLlxuICogc2lnbmF0dXJlIGFuZCBwdWJsaWMga2V5IGNvdW50IG1hdGNoZXMgQml0R28uXG4gKiBQMlNILVAyUEsgPT4gc2NyaXB0VHlwZSwgcmVkZWVtU2NyaXB0LCBwdWJsaWMga2V5LCBzaWduYXR1cmUuXG4gKiBQMlNIID0+IHNjcmlwdFR5cGUsIHJlZGVlbVNjcmlwdCwgcHVibGljIGtleXMsIHNpZ25hdHVyZXMuXG4gKiBQVzJTSCA9PiBzY3JpcHRUeXBlLCB3aXRuZXNzU2NyaXB0LCBwdWJsaWMga2V5cywgc2lnbmF0dXJlcy5cbiAqIFAyU0gtUFcyU0ggPT4gc2NyaXB0VHlwZSwgcmVkZWVtU2NyaXB0LCB3aXRuZXNzU2NyaXB0LCBwdWJsaWMga2V5cywgc2lnbmF0dXJlcy5cbiAqIFAyVFIgYW5kIFAyVFIgTVVTSUcyIHNjcmlwdCBwYXRoID0+IHNjcmlwdFR5cGUgKHRhcHJvb3RTY3JpcHRQYXRoU3BlbmQpLCBwdWJTY3JpcHQgKGxlYWYgc2NyaXB0KSwgY29udHJvbEJsb2NrLFxuICogc2NyaXB0UGF0aExldmVsLCBsZWFmVmVyc2lvbiwgcHVibGljIGtleXMsIHNpZ25hdHVyZXMuXG4gKiBQMlRSIE1VU0lHMiBrZXAgcGF0aCA9PiBzY3JpcHRUeXBlICh0YXByb290S2V5UGF0aFNwZW5kKSwgcHViU2NyaXB0IChzY3JpcHRQdWJLZXkpLCBwYXJ0aWNpcGFudCBwdWIga2V5cyAoc2lnbmVyKSxcbiAqIHB1YmxpYyBrZXkgKHRhcE91dHB1dGtleSksIHNpZ25hdHVyZXMgKHBhcnRpYWwgc2lnbmVyIHNpZ3MpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VQc2J0SW5wdXQoaW5wdXQ6IFBzYnRJbnB1dCk6IFBhcnNlZFBzYnRQMm1zIHwgUGFyc2VkUHNidFRhcHJvb3QgfCBQYXJzZWRQc2J0UDJzaFAycGsge1xuICBpZiAoaXNQc2J0SW5wdXRGaW5hbGl6ZWQoaW5wdXQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGaW5hbGl6ZWQgUFNCVCBwYXJzaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbiAgfVxuICBjb25zdCBzY3JpcHRUeXBlID0gZ2V0UHNidElucHV0U2NyaXB0VHlwZShpbnB1dCk7XG4gIGNvbnN0IHBhcnNlZFB1YlNjcmlwdCA9IHBhcnNlU2NyaXB0KGlucHV0LCBzY3JpcHRUeXBlKTtcbiAgY29uc3Qgc2lnbmF0dXJlcyA9IHBhcnNlU2lnbmF0dXJlcyhpbnB1dCwgc2NyaXB0VHlwZSk7XG5cbiAgaWYgKHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCcgJiYgJ3BhcnRpY2lwYW50UHVibGljS2V5cycgaW4gc2lnbmF0dXJlcykge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5wYXJzZWRQdWJTY3JpcHQsXG4gICAgICAuLi5zaWduYXR1cmVzLFxuICAgICAgc2NyaXB0VHlwZTogcGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUsXG4gICAgfTtcbiAgfVxuICBpZiAocGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUgPT09ICd0YXByb290U2NyaXB0UGF0aFNwZW5kJykge1xuICAgIGlmICghaW5wdXQudGFwTGVhZlNjcmlwdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIFBTQlQgc3RhdGUgZm9yIHRhcHJvb3RTY3JpcHRQYXRoU3BlbmQuIE1pc3NpbmcgcmVxdWlyZWQgZmllbGRzLicpO1xuICAgIH1cbiAgICBjb25zdCBjb250cm9sQmxvY2sgPSBpbnB1dC50YXBMZWFmU2NyaXB0WzBdLmNvbnRyb2xCbG9jaztcbiAgICBpZiAoIWlzVmFsaWRDb250cm9sQm9jayhjb250cm9sQmxvY2spKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgUFNCVCB0YXByb290U2NyaXB0UGF0aFNwZW5kIGNvbnRyb2xCbG9jay4nKTtcbiAgICB9XG4gICAgY29uc3Qgc2NyaXB0UGF0aExldmVsID0gY2FsY3VsYXRlU2NyaXB0UGF0aExldmVsKGNvbnRyb2xCbG9jayk7XG4gICAgY29uc3QgbGVhZlZlcnNpb24gPSBnZXRMZWFmVmVyc2lvbihjb250cm9sQmxvY2spO1xuICAgIHJldHVybiB7XG4gICAgICAuLi5wYXJzZWRQdWJTY3JpcHQsXG4gICAgICAuLi5zaWduYXR1cmVzLFxuICAgICAgc2NyaXB0VHlwZTogcGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUsXG4gICAgICBjb250cm9sQmxvY2ssXG4gICAgICBzY3JpcHRQYXRoTGV2ZWwsXG4gICAgICBsZWFmVmVyc2lvbixcbiAgICB9O1xuICB9XG4gIGlmIChcbiAgICBwYXJzZWRQdWJTY3JpcHQuc2NyaXB0VHlwZSA9PT0gJ3Ayc2gnIHx8XG4gICAgcGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUgPT09ICdwMndzaCcgfHxcbiAgICBwYXJzZWRQdWJTY3JpcHQuc2NyaXB0VHlwZSA9PT0gJ3Ayc2hQMndzaCdcbiAgKSB7XG4gICAgaWYgKHBhcnNlZFB1YlNjcmlwdC5zY3JpcHRUeXBlID09PSAncDJzaFAyd3NoJykge1xuICAgICAgcGFyc2VkUHViU2NyaXB0LnJlZGVlbVNjcmlwdCA9IGlucHV0LnJlZGVlbVNjcmlwdDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLnBhcnNlZFB1YlNjcmlwdCxcbiAgICAgIC4uLnNpZ25hdHVyZXMsXG4gICAgfTtcbiAgfVxuICBpZiAocGFyc2VkUHViU2NyaXB0LnNjcmlwdFR5cGUgPT09ICdwMnNoUDJwaycgJiYgKCFzaWduYXR1cmVzLnNpZ25hdHVyZXMgfHwgIWlzVHVwbGUoc2lnbmF0dXJlcy5zaWduYXR1cmVzKSkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4ucGFyc2VkUHViU2NyaXB0LFxuICAgICAgc2lnbmF0dXJlczogc2lnbmF0dXJlcy5zaWduYXR1cmVzLFxuICAgIH07XG4gIH1cbiAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHB1YiBzY3JpcHQnKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHBhcnNlZCBzY3JpcHQgdHlwZSBpbnRvIGFuIGFycmF5IG9mIHNjcmlwdCB0eXBlcy5cbiAqIEBwYXJhbSBwYXJzZWRTY3JpcHRUeXBlIC0gVGhlIHBhcnNlZCBzY3JpcHQgdHlwZS5cbiAqIEByZXR1cm5zIEFuIGFycmF5IG9mIFNjcmlwdFR5cGUyT2YzIHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBwYXJzZWQgc2NyaXB0IHR5cGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b1NjcmlwdFR5cGUyT2YzcyhwYXJzZWRTY3JpcHRUeXBlOiBQYXJzZWRTY3JpcHRUeXBlMk9mMyk6IFNjcmlwdFR5cGUyT2YzW10ge1xuICByZXR1cm4gcGFyc2VkU2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RTY3JpcHRQYXRoU3BlbmQnXG4gICAgPyBbJ3AydHJNdXNpZzInLCAncDJ0ciddXG4gICAgOiBwYXJzZWRTY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCdcbiAgICA/IFsncDJ0ck11c2lnMiddXG4gICAgOiBbcGFyc2VkU2NyaXB0VHlwZV07XG59XG5cbi8qKlxuICogQHJldHVybnMgc3RyaWN0bHkgcGFyc2UgdGhlIGlucHV0IGFuZCBnZXQgc2lnbmF0dXJlIGNvdW50LlxuICogdW5zaWduZWQoMCksIGhhbGYtc2lnbmVkKDEpIG9yIGZ1bGx5LXNpZ25lZCgyKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RyaWN0U2lnbmF0dXJlQ291bnQoaW5wdXQ6IFR4SW5wdXQgfCBQc2J0SW5wdXQpOiAwIHwgMSB8IDIge1xuICBjb25zdCBjYWxjdWxhdGVTaWduYXR1cmVDb3VudCA9IChcbiAgICBzaWduYXR1cmVzOiBbQnVmZmVyIHwgMCwgQnVmZmVyIHwgMCwgQnVmZmVyIHwgMF0gfCBbQnVmZmVyLCBCdWZmZXJdIHwgW0J1ZmZlcl0gfCB1bmRlZmluZWRcbiAgKTogMCB8IDEgfCAyID0+IHtcbiAgICBjb25zdCBjb3VudCA9IHNpZ25hdHVyZXMgPyBzaWduYXR1cmVzLmZpbHRlcigocykgPT4gIWlzUGxhY2Vob2xkZXJTaWduYXR1cmUocykpLmxlbmd0aCA6IDA7XG4gICAgaWYgKGNvdW50ID09PSAwIHx8IGNvdW50ID09PSAxIHx8IGNvdW50ID09PSAyKSB7XG4gICAgICByZXR1cm4gY291bnQ7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzaWduYXR1cmUgY291bnQnKTtcbiAgfTtcblxuICBpZiAoJ2hhc2gnIGluIGlucHV0KSB7XG4gICAgaWYgKGlucHV0LnNjcmlwdD8ubGVuZ3RoIHx8IGlucHV0LndpdG5lc3M/Lmxlbmd0aCkge1xuICAgICAgY29uc3QgcGFyc2VkSW5wdXQgPSBwYXJzZVNpZ25hdHVyZVNjcmlwdChpbnB1dCk7XG4gICAgICByZXR1cm4gcGFyc2VkSW5wdXQuc2NyaXB0VHlwZSA9PT0gJ3RhcHJvb3RLZXlQYXRoU3BlbmQnID8gMiA6IGNhbGN1bGF0ZVNpZ25hdHVyZUNvdW50KHBhcnNlZElucHV0LnNpZ25hdHVyZXMpO1xuICAgIH1cbiAgICByZXR1cm4gMDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY2FsY3VsYXRlU2lnbmF0dXJlQ291bnQocGFyc2VQc2J0SW5wdXQoaW5wdXQpLnNpZ25hdHVyZXMpO1xuICB9XG59XG5cbi8qKlxuICogQHJldHVybnMgc3RyaWN0bHkgcGFyc2UgaW5wdXQgYW5kIGdldCBzaWduYXR1cmUgY291bnQgZm9yIGFsbCBpbnB1dHMuXG4gKiAwPXVuc2lnbmVkLCAxPWhhbGYtc2lnbmVkIG9yIDI9ZnVsbHktc2lnbmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdHJpY3RTaWduYXR1cmVDb3VudHMoXG4gIHR4OiBVdHhvUHNidCB8IFV0eG9UcmFuc2FjdGlvbjxudW1iZXIgfCBiaWdpbnQ+IHwgUHNidElucHV0W10gfCBUeElucHV0W11cbik6ICgwIHwgMSB8IDIpW10ge1xuICBjb25zdCBpbnB1dHMgPSB0eCBpbnN0YW5jZW9mIFV0eG9Qc2J0ID8gdHguZGF0YS5pbnB1dHMgOiB0eCBpbnN0YW5jZW9mIFV0eG9UcmFuc2FjdGlvbiA/IHR4LmlucyA6IHR4O1xuICByZXR1cm4gaW5wdXRzLm1hcCgoaW5wdXQsIF8pID0+IGdldFN0cmljdFNpZ25hdHVyZUNvdW50KGlucHV0KSk7XG59XG5cbi8qKlxuICogQHJldHVybiB0cnVlIGlmZiBpbnB1dHMgYXJyYXkgaXMgb2YgUHNidElucHV0VHlwZSB0eXBlXG4gKiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUHNidElucHV0QXJyYXkoaW5wdXRzOiBQc2J0SW5wdXRbXSB8IFR4SW5wdXRbXSk6IGlucHV0cyBpcyBQc2J0SW5wdXRbXSB7XG4gIHJldHVybiAhaXNUeElucHV0QXJyYXkoaW5wdXRzKTtcbn1cblxuLyoqXG4gKiBAcmV0dXJuIHRydWUgaWZmIGlucHV0cyBhcnJheSBpcyBvZiBUeElucHV0IHR5cGVcbiAqICovXG5leHBvcnQgZnVuY3Rpb24gaXNUeElucHV0QXJyYXkoaW5wdXRzOiBQc2J0SW5wdXRbXSB8IFR4SW5wdXRbXSk6IGlucHV0cyBpcyBUeElucHV0W10ge1xuICBhc3NlcnQoISFpbnB1dHMubGVuZ3RoLCAnZW1wdHkgaW5wdXRzIGFycmF5Jyk7XG4gIHJldHVybiAnaGFzaCcgaW4gaW5wdXRzWzBdO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHRydWUgaWZmIGdpdmVuIHBzYnQvdHJhbnNhY3Rpb24vdHgtaW5wdXQtYXJyYXkvcHNidC1pbnB1dC1hcnJheSBjb250YWlucyBhdCBsZWFzdCBvbmUgdGFwcm9vdCBrZXkgcGF0aCBzcGVuZCBpbnB1dFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNUcmFuc2FjdGlvbldpdGhLZXlQYXRoU3BlbmRJbnB1dChcbiAgZGF0YTogVXR4b1BzYnQgfCBVdHhvVHJhbnNhY3Rpb248YmlnaW50IHwgbnVtYmVyPiB8IFBzYnRJbnB1dFtdIHwgVHhJbnB1dFtdXG4pOiBib29sZWFuIHtcbiAgY29uc3QgaW5wdXRzID0gZGF0YSBpbnN0YW5jZW9mIFV0eG9Qc2J0ID8gZGF0YS5kYXRhLmlucHV0cyA6IGRhdGEgaW5zdGFuY2VvZiBVdHhvVHJhbnNhY3Rpb24gPyBkYXRhLmlucyA6IGRhdGE7XG4gIGlmICghaW5wdXRzLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoaXNQc2J0SW5wdXRBcnJheShpbnB1dHMpKSB7XG4gICAgcmV0dXJuIGlucHV0cy5zb21lKChpbnB1dCwgXykgPT4gZ2V0UHNidElucHV0U2NyaXB0VHlwZShpbnB1dCkgPT09ICd0YXByb290S2V5UGF0aFNwZW5kJyk7XG4gIH1cbiAgcmV0dXJuIGlucHV0cy5zb21lKChpbnB1dCwgXykgPT4ge1xuICAgIC8vIElmIHRoZSBpbnB1dCBpcyBub3Qgc2lnbmVkLCBpdCBjYW5ub3QgYmUgYSB0YXByb290S2V5UGF0aFNwZW5kIGlucHV0IGJlY2F1c2UgeW91IGNhbiBvbmx5XG4gICAgLy8gZXh0cmFjdCBhIGZ1bGx5IHNpZ25lZCBwc2J0IGludG8gYSB0cmFuc2FjdGlvbiB3aXRoIHRhcHJvb3RLZXlQYXRoU3BlbmQgaW5wdXRzLlxuICAgIGlmIChnZXRTdHJpY3RTaWduYXR1cmVDb3VudChpbnB1dCkgPT09IDApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnNlU2lnbmF0dXJlU2NyaXB0KGlucHV0KS5zY3JpcHRUeXBlID09PSAndGFwcm9vdEtleVBhdGhTcGVuZCc7XG4gIH0pO1xufVxuXG4vKipcbiAqIFNldCB0aGUgUm9vdFdhbGxldEtleXMgYXMgdGhlIGdsb2JhbFhwdWJzIG9uIHRoZSBwc2J0XG4gKlxuICogV2UgZG8gYWxsIHRoZSBtYXRjaGluZyBvZiB0aGUgKHRhcCliaXAzMkRlcml2YXRpb25zIG1hc3RlckZpbmdlcnByaW50IHRvIHRoZSBmaW5nZXJwcmludCBvZiB0aGVcbiAqIGV4dGVuZGVkUHVia2V5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWRkWHB1YnNUb1BzYnQocHNidDogVXR4b1BzYnQsIHJvb3RXYWxsZXRLZXlzOiBSb290V2FsbGV0S2V5cyk6IHZvaWQge1xuICBjb25zdCBzYWZlUm9vdFdhbGxldEtleXMgPSBuZXcgUm9vdFdhbGxldEtleXMoXG4gICAgcm9vdFdhbGxldEtleXMudHJpcGxlLm1hcCgoYmlwMzIpID0+IGJpcDMyLm5ldXRlcmVkKCkpIGFzIFRyaXBsZTxCSVAzMkludGVyZmFjZT4sXG4gICAgcm9vdFdhbGxldEtleXMuZGVyaXZhdGlvblByZWZpeGVzXG4gICk7XG4gIGNvbnN0IHhQdWJzID0gc2FmZVJvb3RXYWxsZXRLZXlzLnRyaXBsZS5tYXAoXG4gICAgKGJpcDMyKTogR2xvYmFsWHB1YiA9PiAoe1xuICAgICAgZXh0ZW5kZWRQdWJrZXk6IGJzNThjaGVjay5kZWNvZGUoYmlwMzIudG9CYXNlNTgoKSksXG4gICAgICBtYXN0ZXJGaW5nZXJwcmludDogYmlwMzIuZmluZ2VycHJpbnQsXG4gICAgICAvLyBUT0RPOiBCRy03Mzc5NyAtIGJpcDE3NCBjdXJyZW50bHkgcmVxdWlyZXMgbSBwcmVmaXggZm9yIHRoaXMgdG8gYmUgYSB2YWxpZCBnbG9iYWxYcHViXG4gICAgICBwYXRoOiAnbScsXG4gICAgfSlcbiAgKTtcbiAgcHNidC51cGRhdGVHbG9iYWwoeyBnbG9iYWxYcHViOiB4UHVicyB9KTtcbn1cblxuLyoqXG4gKiB2YWxpZGF0ZXMgc2lnbmF0dXJlcyBmb3IgZWFjaCAyIG9mIDMgaW5wdXQgYWdhaW5zdCB1c2VyLCBiYWNrdXAsIGJpdGdvIGtleXMgZGVyaXZlZCBmcm9tIHJvb3RXYWxsZXRLZXlzLlxuICogQHJldHVybnMgYXJyYXkgb2YgaW5wdXQgaW5kZXggYW5kIGl0cyBbaXMgdmFsaWQgdXNlciBzaWcgZXhpc3QsIGlzIHZhbGlkIGJhY2t1cCBzaWcgZXhpc3QsIGlzIHZhbGlkIHVzZXIgYml0Z28gZXhpc3RdXG4gKiBGb3IgcDJzaFAycGsgaW5wdXQsIFtmYWxzZSwgZmFsc2UsIGZhbHNlXSBpcyByZXR1cm5lZCBzaW5jZSBpdCBpcyBub3QgYSAyIG9mIDMgc2lnIGlucHV0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2lnbmF0dXJlVmFsaWRhdGlvbkFycmF5UHNidChwc2J0OiBVdHhvUHNidCwgcm9vdFdhbGxldEtleXM6IFJvb3RXYWxsZXRLZXlzKTogU2lnbmF0dXJlVmFsaWRhdGlvbltdIHtcbiAgcmV0dXJuIHBzYnQuZGF0YS5pbnB1dHMubWFwKChpbnB1dCwgaSkgPT4ge1xuICAgIGNvbnN0IHNpZ1ZhbEFycmF5Rm9ySW5wdXQ6IFRyaXBsZTxib29sZWFuPiA9XG4gICAgICBnZXRQc2J0SW5wdXRTY3JpcHRUeXBlKGlucHV0KSA9PT0gJ3Ayc2hQMnBrJ1xuICAgICAgICA/IFtmYWxzZSwgZmFsc2UsIGZhbHNlXVxuICAgICAgICA6IHBzYnQuZ2V0U2lnbmF0dXJlVmFsaWRhdGlvbkFycmF5KGksIHsgcm9vdE5vZGVzOiByb290V2FsbGV0S2V5cy50cmlwbGUgfSk7XG4gICAgcmV0dXJuIFtpLCBzaWdWYWxBcnJheUZvcklucHV0XTtcbiAgfSk7XG59XG5cbi8qKlxuICogRXh0cmFjdHMgdGhlIGhhbGYgc2lnbmVkIHRyYW5zYWN0aW9uIGZyb20gdGhlIHBzYnQgZm9yIHAybXMgYmFzZWQgc2NyaXB0IHR5cGVzIC0gcDJzaCwgcDJ3c2gsIGFuZCBwMnNoUDJ3c2guXG4gKiBUaGUgcHVycG9zZSBpcyB0byBwcm92aWRlIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgdG8ga2V5dGVybmFsIChLUlMpIHRoYXQgb25seSBzdXBwb3J0cyBuZXR3b3JrIHRyYW5zYWN0aW9uIGFuZCBwMm1zIHNjcmlwdCB0eXBlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV4dHJhY3RQMm1zT25seUhhbGZTaWduZWRUeChwc2J0OiBVdHhvUHNidCk6IFV0eG9UcmFuc2FjdGlvbjxiaWdpbnQ+IHtcbiAgYXNzZXJ0KCEhKHBzYnQuZGF0YS5pbnB1dHMubGVuZ3RoICYmIHBzYnQuZGF0YS5vdXRwdXRzLmxlbmd0aCksICdlbXB0eSBpbnB1dHMgb3Igb3V0cHV0cycpO1xuICBjb25zdCB0eCA9IHBzYnQuZ2V0VW5zaWduZWRUeCgpO1xuXG4gIGZ1bmN0aW9uIGlzUDJtc1BhcnNlZFBzYnRJbnB1dChcbiAgICBwYXJzZWQ6IFBhcnNlZFBzYnRQMm1zIHwgUGFyc2VkUHNidFRhcHJvb3QgfCBQYXJzZWRQc2J0UDJzaFAycGtcbiAgKTogcGFyc2VkIGlzIFBhcnNlZFBzYnRQMm1zIHtcbiAgICByZXR1cm4gWydwMnNoJywgJ3Ayc2hQMndzaCcsICdwMndzaCddLmluY2x1ZGVzKHBhcnNlZC5zY3JpcHRUeXBlKTtcbiAgfVxuXG4gIHBzYnQuZGF0YS5pbnB1dHMuZm9yRWFjaCgoaW5wdXQsIGkpID0+IHtcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVBzYnRJbnB1dChpbnB1dCk7XG4gICAgYXNzZXJ0KGlzUDJtc1BhcnNlZFBzYnRJbnB1dChwYXJzZWQpLCBgdW5zdXBwb3J0ZWQgc2NyaXB0IHR5cGUgJHtwYXJzZWQuc2NyaXB0VHlwZX1gKTtcbiAgICBhc3NlcnQoaW5wdXQucGFydGlhbFNpZz8ubGVuZ3RoID09PSAxLCBgdW5leHBlY3RlZCBzaWduYXR1cmUgY291bnQgJHtpbnB1dC5wYXJ0aWFsU2lnPy5sZW5ndGh9YCk7XG4gICAgY29uc3QgW3BhcnRpYWxTaWddID0gaW5wdXQucGFydGlhbFNpZztcbiAgICBhc3NlcnQoXG4gICAgICBpbnB1dC5zaWdoYXNoVHlwZSAhPT0gdW5kZWZpbmVkICYmIGlucHV0LnNpZ2hhc2hUeXBlID09PSBic2NyaXB0LnNpZ25hdHVyZS5kZWNvZGUocGFydGlhbFNpZy5zaWduYXR1cmUpLmhhc2hUeXBlLFxuICAgICAgJ3NpZ25hdHVyZSBzaWdoYXNoIGRvZXMgbm90IG1hdGNoIGlucHV0IHNpZ2hhc2ggdHlwZSdcbiAgICApO1xuXG4gICAgLy8gdHlwZSBjYXN0aW5nIGlzIHRvIGFkZHJlc3MgdGhlIGludmFsaWQgdHlwZSBjaGVja2luZyBpbiBwYXltZW50cy5wMm1zXG4gICAgY29uc3Qgc2lnbmF0dXJlcyA9IHBhcnNlZC5wdWJsaWNLZXlzLm1hcCgocGspID0+XG4gICAgICBwYXJ0aWFsU2lnLnB1YmtleS5lcXVhbHMocGspID8gcGFydGlhbFNpZy5zaWduYXR1cmUgOiAob3BzLk9QXzAgYXMgdW5rbm93biBhcyBCdWZmZXIpXG4gICAgKTtcblxuICAgIGNvbnN0IGlzUDJTSCA9ICEhcGFyc2VkLnJlZGVlbVNjcmlwdDtcbiAgICBjb25zdCBpc1AyV1NIID0gISFwYXJzZWQud2l0bmVzc1NjcmlwdDtcblxuICAgIGNvbnN0IHBheW1lbnQgPSBwYXltZW50cy5wMm1zKHsgb3V0cHV0OiBwYXJzZWQucHViU2NyaXB0LCBzaWduYXR1cmVzIH0sIHsgdmFsaWRhdGU6IGZhbHNlLCBhbGxvd0luY29tcGxldGU6IHRydWUgfSk7XG4gICAgY29uc3QgcDJ3c2ggPSBpc1AyV1NIID8gcGF5bWVudHMucDJ3c2goeyByZWRlZW06IHBheW1lbnQgfSkgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcDJzaCA9IGlzUDJTSCA/IHBheW1lbnRzLnAyc2goeyByZWRlZW06IHAyd3NoIHx8IHBheW1lbnQgfSkgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAocDJzaD8uaW5wdXQpIHtcbiAgICAgIHR4LnNldElucHV0U2NyaXB0KGksIHAyc2guaW5wdXQpO1xuICAgIH1cbiAgICBpZiAocDJ3c2g/LndpdG5lc3MpIHtcbiAgICAgIHR4LnNldFdpdG5lc3MoaSwgcDJ3c2gud2l0bmVzcyk7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gdHg7XG59XG5cbi8qKlxuICogQ2xvbmVzIHRoZSBwc2J0IHdpdGhvdXQgbm9uV2l0bmVzc1V0eG8gZm9yIG5vbi1zZWd3aXQgaW5wdXRzIGFuZCB3aXRuZXNzVXR4byBpcyBhZGRlZCBpbnN0ZWFkLlxuICogSXQgaXMgbm90IEJJUC0xNzQgY29tcGxpYW50LCBzbyB1c2UgaXQgY2FyZWZ1bGx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2xvbmVQc2J0V2l0aG91dE5vbldpdG5lc3NVdHhvKHBzYnQ6IFV0eG9Qc2J0KTogVXR4b1BzYnQge1xuICBjb25zdCBuZXdQc2J0ID0gY3JlYXRlUHNidEZyb21IZXgocHNidC50b0hleCgpLCBwc2J0Lm5ldHdvcmspO1xuICBjb25zdCB0eElucHV0cyA9IHBzYnQudHhJbnB1dHM7XG5cbiAgcHNidC5kYXRhLmlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgIGlmIChpbnB1dC5ub25XaXRuZXNzVXR4byAmJiAhaW5wdXQud2l0bmVzc1V0eG8pIHtcbiAgICAgIGNvbnN0IHR4ID0gY3JlYXRlVHJhbnNhY3Rpb25Gcm9tQnVmZmVyKGlucHV0Lm5vbldpdG5lc3NVdHhvLCBwc2J0Lm5ldHdvcmssIHsgYW1vdW50VHlwZTogJ2JpZ2ludCcgfSk7XG4gICAgICBpZiAoIXR4SW5wdXRzW2ldLmhhc2guZXF1YWxzKHR4LmdldEhhc2goKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBOb24td2l0bmVzcyBVVFhPIGhhc2ggZm9yIGlucHV0ICMke2l9IGRvZXNuJ3QgbWF0Y2ggdGhlIGhhc2ggc3BlY2lmaWVkIGluIHRoZSBwcmV2b3V0YCk7XG4gICAgICB9XG4gICAgICBuZXdQc2J0LmRhdGEuaW5wdXRzW2ldLndpdG5lc3NVdHhvID0gdHgub3V0c1t0eElucHV0c1tpXS5pbmRleF07XG4gICAgfVxuICAgIGRlbGV0ZSBuZXdQc2J0LmRhdGEuaW5wdXRzW2ldLm5vbldpdG5lc3NVdHhvO1xuICB9KTtcblxuICByZXR1cm4gbmV3UHNidDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlcmUgYXJlIG5vbi1zZWd3aXQgaW5wdXRzIGluIHRoZSBQU0JUIHRoYXQgZG8gbm90IGNvbnRhaW4gdGhlXG4gKiBub25XaXRuZXNzVXR4by5cbiAqXG4gKiBpc1BzYnRMaXRlKGNsb25lUHNidFdpdGhvdXROb25XaXRuZXNzVXR4byhwc2J0KSkgPT09IHRydWVcbiAqXG4gKiBAcGFyYW0gcHNidFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNQc2J0TGl0ZShwc2J0OiBVdHhvUHNidCk6IGJvb2xlYW4ge1xuICBsZXQgaXNGdWxsID0gdHJ1ZTtcbiAgY29uc3Qgbm9uU2Vnd2l0SW5wdXRUeXBlcyA9IFsncDJzaFAycGsnLCAncDJzaCddO1xuICBwc2J0LmRhdGEuaW5wdXRzLmZvckVhY2goKGlucHV0KSA9PiB7XG4gICAgaWYgKGlzRnVsbCAmJiBub25TZWd3aXRJbnB1dFR5cGVzLmluY2x1ZGVzKGdldFBzYnRJbnB1dFNjcmlwdFR5cGUoaW5wdXQpKSkge1xuICAgICAgaXNGdWxsID0gISFpbnB1dC5ub25XaXRuZXNzVXR4bztcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gIWlzRnVsbDtcbn1cblxuLyoqXG4gKiBEZWxldGVzIHdpdG5lc3NVdHhvIGZvciBub24tc2Vnd2l0IGlucHV0cyB0byBtYWtlIHRoZSBQU0JUIEJJUC0xNzQgY29tcGxpYW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVsZXRlV2l0bmVzc1V0eG9Gb3JOb25TZWd3aXRJbnB1dHMocHNidDogVXR4b1BzYnQpOiB2b2lkIHtcbiAgcHNidC5kYXRhLmlucHV0cy5mb3JFYWNoKChpbnB1dCwgaSkgPT4ge1xuICAgIGNvbnN0IHNjcmlwdFR5cGUgPSBnZXRQc2J0SW5wdXRTY3JpcHRUeXBlKGlucHV0KTtcbiAgICBpZiAoc2NyaXB0VHlwZSA9PT0gJ3Ayc2gnIHx8IHNjcmlwdFR5cGUgPT09ICdwMnNoUDJwaycpIHtcbiAgICAgIGRlbGV0ZSBpbnB1dC53aXRuZXNzVXR4bztcbiAgICB9XG4gIH0pO1xufVxuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!