PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-api/dist/src/v1

Просмотр файла: wallets.js

"use strict";
/**
 * @hidden
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
 */
//
// Wallets Object
// BitGo accessor to a user's wallets.
//
// Copyright 2014, BitGo, Inc.  All Rights Reserved.
//
const sdk_core_1 = require("@bitgo/sdk-core");
const utxo_lib_1 = require("@bitgo/utxo-lib");
const utxolib = __importStar(require("@bitgo/utxo-lib"));
const lodash_1 = __importDefault(require("lodash"));
const Wallet = require('./wallet');
//
// Constructor
//
const Wallets = function (bitgo) {
    // @ts-expect-error - no implicit this
    this.bitgo = bitgo;
};
//
// list
// List the user's wallets
//
Wallets.prototype.list = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, [], [], callback);
    const args = [];
    if (params.skip && params.prevId) {
        throw new Error('cannot specify both skip and prevId');
    }
    if (params.limit) {
        if (!lodash_1.default.isNumber(params.limit)) {
            throw new Error('invalid limit argument, expecting number');
        }
        args.push('limit=' + params.limit);
    }
    if (params.getbalances) {
        if (!lodash_1.default.isBoolean(params.getbalances)) {
            throw new Error('invalid getbalances argument, expecting boolean');
        }
        args.push('getbalances=' + params.getbalances);
    }
    if (params.skip) {
        if (!lodash_1.default.isNumber(params.skip)) {
            throw new Error('invalid skip argument, expecting number');
        }
        args.push('skip=' + params.skip);
    }
    else if (params.prevId) {
        args.push('prevId=' + params.prevId);
    }
    let query = '';
    if (args.length) {
        query = '?' + args.join('&');
    }
    const self = this;
    return Promise.resolve(this.bitgo.get(this.bitgo.url('/wallet' + query)).result())
        .then(function (body) {
        body.wallets = body.wallets.map(function (w) {
            return new Wallet(self.bitgo, w);
        });
        return body;
    })
        .then(callback)
        .catch(callback);
};
Wallets.prototype.getWallet = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['id'], [], callback);
    const self = this;
    let query = '';
    if (params.gpk) {
        query = '?gpk=1';
    }
    return Promise.resolve(this.bitgo.get(this.bitgo.url('/wallet/' + params.id + query)).result())
        .then(function (wallet) {
        return new Wallet(self.bitgo, wallet);
    })
        .then(callback)
        .catch(callback);
};
//
// listInvites
// List the invites on a user
//
Wallets.prototype.listInvites = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, [], [], callback);
    return Promise.resolve(this.bitgo.get(this.bitgo.url('/walletinvite')).result())
        .then(callback)
        .catch(callback);
};
//
// cancelInvite
// cancel a wallet invite that a user initiated
//
Wallets.prototype.cancelInvite = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['walletInviteId'], [], callback);
    return Promise.resolve(this.bitgo.del(this.bitgo.url('/walletinvite/' + params.walletInviteId)).result())
        .then(callback)
        .catch(callback);
};
//
// listShares
// List the user's wallet shares
//
Wallets.prototype.listShares = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, [], [], callback);
    return Promise.resolve(this.bitgo.get(this.bitgo.url('/walletshare')).result())
        .then(callback)
        .catch(callback);
};
//
// resendShareInvite
// Resend the invitation email which shares a wallet with another user
// Params:
//    walletShareId - the wallet share to get information on
//
Wallets.prototype.resendShareInvite = function (params, callback) {
    return async function () {
        params = params || {};
        sdk_core_1.common.validateParams(params, ['walletShareId'], [], callback);
        const urlParts = params.walletShareId + '/resendemail';
        // @ts-expect-error - no implicit this
        return this.bitgo.post(this.bitgo.url('/walletshare/' + urlParts)).result();
    }
        .call(this)
        .then(callback)
        .catch(callback);
};
//
// getShare
// Gets a wallet share information, including the encrypted sharing keychain. requires unlock if keychain is present.
// Params:
//    walletShareId - the wallet share to get information on
//
Wallets.prototype.getShare = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['walletShareId'], [], callback);
    return Promise.resolve(this.bitgo.get(this.bitgo.url('/walletshare/' + params.walletShareId)).result())
        .then(callback)
        .catch(callback);
};
//
// updateShare
// updates a wallet share
// Params:
//    walletShareId - the wallet share to update
//    state - the new state of the wallet share
//
Wallets.prototype.updateShare = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['walletShareId'], [], callback);
    return Promise.resolve(this.bitgo
        .post(this.bitgo.url('/walletshare/' + params.walletShareId))
        .send(params)
        .result())
        .then(callback)
        .catch(callback);
};
//
// cancelShare
// cancels a wallet share
// Params:
//    walletShareId - the wallet share to update
//
Wallets.prototype.cancelShare = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['walletShareId'], [], callback);
    return Promise.resolve(this.bitgo
        .del(this.bitgo.url('/walletshare/' + params.walletShareId))
        .send()
        .result())
        .then(callback)
        .catch(callback);
};
//
// acceptShare
// Accepts a wallet share, adding the wallet to the user's list
// Needs a user's password to decrypt the shared key
// Params:
//    walletShareId - the wallet share to accept
//    userPassword - (required if more a keychain was shared) user's password to decrypt the shared wallet
//    newWalletPassphrase - new wallet passphrase for saving the shared wallet xprv.
//                          If left blank and a wallet with more than view permissions was shared, then the userpassword is used.
//    overrideEncryptedXprv - set only if the xprv was received out-of-band.
//
Wallets.prototype.acceptShare = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['walletShareId'], ['overrideEncryptedXprv'], callback);
    const self = this;
    let encryptedXprv = params.overrideEncryptedXprv;
    return this.getShare({ walletShareId: params.walletShareId })
        .then(function (walletShare) {
        // Return right away if there is no keychain to decrypt, or if explicit encryptedXprv was provided
        if (!walletShare.keychain || !walletShare.keychain.encryptedXprv || encryptedXprv) {
            return walletShare;
        }
        // More than viewing was requested, so we need to process the wallet keys using the shared ecdh scheme
        if (!params.userPassword) {
            throw new Error('userPassword param must be provided to decrypt shared key');
        }
        return self.bitgo.getECDHKeychain().then(function (sharingKeychain) {
            if (!sharingKeychain.encryptedXprv) {
                throw new Error('EncryptedXprv was not found on sharing keychain');
            }
            // Now we have the sharing keychain, we can work out the secret used for sharing the wallet with us
            sharingKeychain.xprv = self.bitgo.decrypt({
                password: params.userPassword,
                input: sharingKeychain.encryptedXprv,
            });
            // Derive key by path (which is used between these 2 users only)
            const secret = (0, sdk_core_1.getSharedSecret)(utxo_lib_1.bip32.fromBase58(sharingKeychain.xprv).derivePath((0, sdk_core_1.sanitizeLegacyPath)(walletShare.keychain.path)), Buffer.from(walletShare.keychain.fromPubKey, 'hex')).toString('hex');
            // Yes! We got the secret successfully here, now decrypt the shared wallet xprv
            const decryptedSharedWalletXprv = self.bitgo.decrypt({
                password: secret,
                input: walletShare.keychain.encryptedXprv,
            });
            // We will now re-encrypt the wallet with our own password
            const newWalletPassphrase = params.newWalletPassphrase || params.userPassword;
            encryptedXprv = self.bitgo.encrypt({ password: newWalletPassphrase, input: decryptedSharedWalletXprv });
            // Carry on to the next block where we will post the acceptance of the share with the encrypted xprv
            return walletShare;
        });
    })
        .then(function (walletShare) {
        const updateParams = {
            walletShareId: params.walletShareId,
            state: 'accepted',
        };
        if (encryptedXprv) {
            updateParams.encryptedXprv = encryptedXprv;
        }
        return self.updateShare(updateParams);
    })
        .then(callback)
        .catch(callback);
};
//
// createKey
// Create a single bitcoin key.  This runs locally.
// Returns: {
//   address: <address>
//   key: <key, in WIF format>
// }
Wallets.prototype.createKey = function (params) {
    const key = (0, sdk_core_1.makeRandomKey)();
    return {
        address: (0, sdk_core_1.getAddressP2PKH)(key),
        key: key.toWIF(),
    };
};
//
// createWalletWithKeychains
// Create a new 2-of-3 wallet and it's associated keychains.
// Returns the locally created keys with their encrypted xprvs.
// **WARNING: BE SURE TO BACKUP! NOT DOING SO CAN RESULT IN LOSS OF FUNDS!**
//
// 1. Creates the user keychain locally on the client, and encrypts it with the provided passphrase
// 2. If no xpub was provided, creates the backup keychain locally on the client, and encrypts it with the provided passphrase
// 3. Uploads the encrypted user and backup keychains to BitGo
// 4. Creates the BitGo key on the service
// 5. Creates the wallet on BitGo with the 3 public keys above
//
// Parameters include:
//   "passphrase": wallet passphrase to encrypt user and backup keys with
//   "label": wallet label, is shown in BitGo UI
//   "backupXpub": backup keychain xpub, it is HIGHLY RECOMMENDED you generate this on a separate machine!
//                 BITGO DOES NOT GUARANTEE SAFETY OF WALLETS WITH MULTIPLE KEYS CREATED ON THE SAME MACHINE **
//   "backupXpubProvider": Provision backup key from this provider (KRS), e.g. "keyternal".
//                         Setting this value will create an instant-capable wallet.
//   "passcodeEncryptionCode": the code used to encrypt the wallet passcode used in the recovery process
// Returns: {
//   wallet: newly created wallet model object
//   userKeychain: the newly created user keychain, which has an encrypted xprv stored on BitGo
//   backupKeychain: the newly created backup keychain
//
// ** BE SURE TO BACK UP THE ENCRYPTED USER AND BACKUP KEYCHAINS!**
//
// }
Wallets.prototype.createWalletWithKeychains = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['passphrase'], ['label', 'backupXpub', 'enterprise', 'passcodeEncryptionCode'], callback);
    const self = this;
    const label = params.label;
    // Create the user and backup key.
    const userKeychain = this.bitgo.keychains().create();
    userKeychain.encryptedXprv = this.bitgo.encrypt({ password: params.passphrase, input: userKeychain.xprv });
    const keychainData = {
        xpub: userKeychain.xpub,
        encryptedXprv: userKeychain.encryptedXprv,
    };
    if (params.passcodeEncryptionCode) {
        keychainData.originalPasscodeEncryptionCode = params.passcodeEncryptionCode;
    }
    const hasBackupXpub = !!params.backupXpub;
    const hasBackupXpubProvider = !!params.backupXpubProvider;
    if (hasBackupXpub && hasBackupXpubProvider) {
        throw new Error('Cannot provide more than one backupXpub or backupXpubProvider flag');
    }
    if (params.disableTransactionNotifications !== undefined && !lodash_1.default.isBoolean(params.disableTransactionNotifications)) {
        throw new Error('Expected disableTransactionNotifications to be a boolean. ');
    }
    let backupKeychain;
    let bitgoKeychain;
    // Add the user keychain
    return self.bitgo
        .keychains()
        .add(keychainData)
        .then(function () {
        // Add the backup keychain
        if (params.backupXpubProvider) {
            // If requested, use a KRS or backup key provider
            return self.bitgo
                .keychains()
                .createBackup({
                provider: params.backupXpubProvider,
                disableKRSEmail: params.disableKRSEmail,
            })
                .then(function (keychain) {
                backupKeychain = keychain;
            });
        }
        if (params.backupXpub) {
            // user provided backup xpub
            backupKeychain = { xpub: params.backupXpub };
        }
        else {
            // no provided xpub, so default to creating one here
            backupKeychain = self.bitgo.keychains().create();
        }
        return self.bitgo.keychains().add(backupKeychain);
    })
        .then(function () {
        return self.bitgo.keychains().createBitGo();
    })
        .then(function (keychain) {
        bitgoKeychain = keychain;
        const walletParams = {
            label: label,
            m: 2,
            n: 3,
            keychains: [{ xpub: userKeychain.xpub }, { xpub: backupKeychain.xpub }, { xpub: bitgoKeychain.xpub }],
        };
        if (params.enterprise) {
            walletParams.enterprise = params.enterprise;
        }
        if (params.disableTransactionNotifications) {
            walletParams.disableTransactionNotifications = params.disableTransactionNotifications;
        }
        return self.add(walletParams);
    })
        .then(function (newWallet) {
        const result = {
            wallet: newWallet,
            userKeychain: userKeychain,
            backupKeychain: backupKeychain,
            bitgoKeychain: bitgoKeychain,
        };
        if (backupKeychain.xprv) {
            result.warning = 'Be sure to backup the backup keychain -- it is not stored anywhere else!';
        }
        return result;
    })
        .then(callback)
        .catch(callback);
};
//
// createForwardWallet
// Creates a forward wallet from a single private key.
// BitGo will watch the wallet and send any incoming transactions to a destination multi-sig wallet
// WARNING: THE PRIVATE KEY WILL BE SENT TO BITGO. YOU MUST CONTACT BITGO BEFORE USING THIS FEATURE!
// WE CANNOT GUARANTEE THE SECURITY OF SINGLE-SIG WALLETS AS CUSTODY IS UNCLEAR.
//
// Params:
//    privKey - the private key on a legacy single-signature wallet to be watched (WIF format)
//    sourceAddress - the bitcoin address to forward from (corresponds to the private key)
//    destinationWallet - the wallet object to send the destination coins to (when incoming transactions are detected)
//    label - label for the wallet
//
Wallets.prototype.createForwardWallet = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['privKey', 'sourceAddress'], ['label'], callback);
    if (!lodash_1.default.isObject(params.destinationWallet) || !params.destinationWallet.id) {
        throw new Error('expecting destinationWallet object');
    }
    const self = this;
    let newDestinationAddress;
    let addressFromPrivKey;
    try {
        const key = utxolib.ECPair.fromWIF(params.privKey, (0, sdk_core_1.getNetwork)());
        addressFromPrivKey = (0, sdk_core_1.getAddressP2PKH)(key);
    }
    catch (e) {
        throw new Error('expecting a valid privKey');
    }
    if (addressFromPrivKey !== params.sourceAddress) {
        throw new Error('privKey does not match source address - got ' + addressFromPrivKey + ' expected ' + params.sourceAddress);
    }
    return params.destinationWallet.createAddress().then(function (result) {
        // Create new address on the destination wallet to receive coins
        newDestinationAddress = result.address;
        const walletParams = {
            type: 'forward',
            sourceAddress: params.sourceAddress,
            destinationAddress: newDestinationAddress,
            privKey: params.privKey,
            label: params.label,
        };
        if (params.enterprise) {
            walletParams.enterprise = params.enterprise;
        }
        return Promise.resolve(self.bitgo.post(self.bitgo.url('/wallet')).send(walletParams).result())
            .then(callback)
            .catch(callback);
    });
};
/**
 * Add a new wallet (advanced mode).
 * This allows you to manually submit the keychains, type, m and n of the wallet
 * @param {string} label label of the wallet to be shown in UI
 * @param {number} m number of keys required to unlock wallet (2)
 * @param {number} n number of keys available on the wallet (3)
 * @param {array} keychains array of keychain xpubs
 * @param {string} enterprise ID of the enterprise entity to create this wallet under.
 * @param {boolean} disableTransactionNotifications When set to true disables notifications for transactions on this wallet.
 */
Wallets.prototype.add = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, [], ['label', 'enterprise'], callback);
    if (Array.isArray(params.keychains) === false || !lodash_1.default.isNumber(params.m) || !lodash_1.default.isNumber(params.n)) {
        throw new Error('invalid argument');
    }
    // TODO: support more types of multisig
    if (params.m !== 2 || params.n !== 3) {
        throw new Error('unsupported multi-sig type');
    }
    const self = this;
    const keychains = params.keychains.map(function (k) {
        return { xpub: k.xpub };
    });
    const walletParams = {
        label: params.label,
        m: params.m,
        n: params.n,
        keychains: keychains,
    };
    if (params.enterprise) {
        walletParams.enterprise = params.enterprise;
    }
    if (params.disableTransactionNotifications) {
        walletParams.disableTransactionNotifications = params.disableTransactionNotifications;
    }
    return Promise.resolve(this.bitgo.post(this.bitgo.url('/wallet')).send(walletParams).result())
        .then(function (body) {
        return new Wallet(self.bitgo, body);
    })
        .then(callback)
        .catch(callback);
};
//
// get
// Shorthand to getWallet
// Parameters include:
//   id: the id of the wallet
//
Wallets.prototype.get = function (params, callback) {
    return this.getWallet(params, callback);
};
//
// remove
// Remove an existing wallet.
// Parameters include:
//   id: the id of the wallet
//
Wallets.prototype.remove = function (params, callback) {
    params = params || {};
    sdk_core_1.common.validateParams(params, ['id'], [], callback);
    return Promise.resolve(this.bitgo.del(this.bitgo.url('/wallet/' + params.id)).result())
        .then(callback)
        .catch(callback);
};
module.exports = Wallets;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FsbGV0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy92MS93YWxsZXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7R0FFRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFSDtHQUNHO0FBQ0gsRUFBRTtBQUNGLGlCQUFpQjtBQUNqQixzQ0FBc0M7QUFDdEMsRUFBRTtBQUNGLG9EQUFvRDtBQUNwRCxFQUFFO0FBQ0YsOENBT3lCO0FBQ3pCLDhDQUF3QztBQUN4Qyx5REFBMkM7QUFDM0Msb0RBQXVCO0FBQ3ZCLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztBQUVuQyxFQUFFO0FBQ0YsY0FBYztBQUNkLEVBQUU7QUFDRixNQUFNLE9BQU8sR0FBRyxVQUFVLEtBQUs7SUFDN0Isc0NBQXNDO0lBQ3RDLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0FBQ3JCLENBQUMsQ0FBQztBQUVGLEVBQUU7QUFDRixPQUFPO0FBQ1AsMEJBQTBCO0FBQzFCLEVBQUU7QUFDRixPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxVQUFVLE1BQU0sRUFBRSxRQUFRO0lBQ2pELE1BQU0sR0FBRyxNQUFNLElBQUksRUFBRSxDQUFDO0lBQ3RCLGlCQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBRWhELE1BQU0sSUFBSSxHQUFhLEVBQUUsQ0FBQztJQUUxQixJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2pDLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDakIsSUFBSSxDQUFDLGdCQUFDLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENB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QUFDTix5QkFBeUI7QUFDekIsc0JBQXNCO0FBQ3RCLDZCQUE2QjtBQUM3QixFQUFFO0FBQ0YsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsVUFBVSxNQUFNLEVBQUUsUUFBUTtJQUNoRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzFDLENBQUMsQ0FBQztBQUVGLEVBQUU7QUFDRixTQUFTO0FBQ1QsNkJBQTZCO0FBQzdCLHNCQUFzQjtBQUN0Qiw2QkFBNkI7QUFDN0IsRUFBRTtBQUNGLE9BQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxHQUFHLFVBQVUsTUFBTSxFQUFFLFFBQVE7SUFDbkQsTUFBTSxHQUFHLE1BQU0sSUFBSSxFQUFFLENBQUM7SUFDdEIsaUJBQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBRXBELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDcEYsSUFBSSxDQUFDLFFBQVEsQ0FBQztTQUNkLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUNyQixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGhpZGRlblxuICovXG5cbi8qKlxuICovXG4vL1xuLy8gV2FsbGV0cyBPYmplY3Rcbi8vIEJpdEdvIGFjY2Vzc29yIHRvIGEgdXNlcidzIHdhbGxldHMuXG4vL1xuLy8gQ29weXJpZ2h0IDIwMTQsIEJpdEdvLCBJbmMuICBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy9cbmltcG9ydCB7XG4gIGNvbW1vbixcbiAgZ2V0QWRkcmVzc1AyUEtILFxuICBnZXROZXR3b3JrLFxuICBnZXRTaGFyZWRTZWNyZXQsXG4gIG1ha2VSYW5kb21LZXksXG4gIHNhbml0aXplTGVnYWN5UGF0aCxcbn0gZnJvbSAnQGJpdGdvL3Nkay1jb3JlJztcbmltcG9ydCB7IGJpcDMyIH0gZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCAqIGFzIHV0eG9saWIgZnJvbSAnQGJpdGdvL3V0eG8tbGliJztcbmltcG9ydCBfIGZyb20gJ2xvZGFzaCc7XG5jb25zdCBXYWxsZXQgPSByZXF1aXJlKCcuL3dhbGxldCcpO1xuXG4vL1xuLy8gQ29uc3RydWN0b3Jcbi8vXG5jb25zdCBXYWxsZXRzID0gZnVuY3Rpb24gKGJpdGdvKSB7XG4gIC8vIEB0cy1leHBlY3QtZXJyb3IgLSBubyBpbXBsaWNpdCB0aGlzXG4gIHRoaXMuYml0Z28gPSBiaXRnbztcbn07XG5cbi8vXG4vLyBsaXN0XG4vLyBMaXN0IHRoZSB1c2VyJ3Mgd2FsbGV0c1xuLy9cbldhbGxldHMucHJvdG90eXBlLmxpc3QgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFtdLCBbXSwgY2FsbGJhY2spO1xuXG4gIGNvbnN0IGFyZ3M6IHN0cmluZ1tdID0gW107XG5cbiAgaWYgKHBhcmFtcy5za2lwICYmIHBhcmFtcy5wcmV2SWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBzcGVjaWZ5IGJvdGggc2tpcCBhbmQgcHJldklkJyk7XG4gIH1cblxuICBpZiAocGFyYW1zLmxpbWl0KSB7XG4gICAgaWYgKCFfLmlzTnVtYmVyKHBhcmFtcy5saW1pdCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBsaW1pdCBhcmd1bWVudCwgZXhwZWN0aW5nIG51bWJlcicpO1xuICAgIH1cbiAgICBhcmdzLnB1c2goJ2xpbWl0PScgKyBwYXJhbXMubGltaXQpO1xuICB9XG4gIGlmIChwYXJhbXMuZ2V0YmFsYW5jZXMpIHtcbiAgICBpZiAoIV8uaXNCb29sZWFuKHBhcmFtcy5nZXRiYWxhbmNlcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBnZXRiYWxhbmNlcyBhcmd1bWVudCwgZXhwZWN0aW5nIGJvb2xlYW4nKTtcbiAgICB9XG4gICAgYXJncy5wdXNoKCdnZXRiYWxhbmNlcz0nICsgcGFyYW1zLmdldGJhbGFuY2VzKTtcbiAgfVxuICBpZiAocGFyYW1zLnNraXApIHtcbiAgICBpZiAoIV8uaXNOdW1iZXIocGFyYW1zLnNraXApKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2tpcCBhcmd1bWVudCwgZXhwZWN0aW5nIG51bWJlcicpO1xuICAgIH1cbiAgICBhcmdzLnB1c2goJ3NraXA9JyArIHBhcmFtcy5za2lwKTtcbiAgfSBlbHNlIGlmIChwYXJhbXMucHJldklkKSB7XG4gICAgYXJncy5wdXNoKCdwcmV2SWQ9JyArIHBhcmFtcy5wcmV2SWQpO1xuICB9XG5cbiAgbGV0IHF1ZXJ5ID0gJyc7XG4gIGlmIChhcmdzLmxlbmd0aCkge1xuICAgIHF1ZXJ5ID0gJz8nICsgYXJncy5qb2luKCcmJyk7XG4gIH1cblxuICBjb25zdCBzZWxmID0gdGhpcztcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLmJpdGdvLmdldCh0aGlzLmJpdGdvLnVybCgnL3dhbGxldCcgKyBxdWVyeSkpLnJlc3VsdCgpKVxuICAgIC50aGVuKGZ1bmN0aW9uIChib2R5KSB7XG4gICAgICBib2R5LndhbGxldHMgPSBib2R5LndhbGxldHMubWFwKGZ1bmN0aW9uICh3KSB7XG4gICAgICAgIHJldHVybiBuZXcgV2FsbGV0KHNlbGYuYml0Z28sIHcpO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gYm9keTtcbiAgICB9KVxuICAgIC50aGVuKGNhbGxiYWNrKVxuICAgIC5jYXRjaChjYWxsYmFjayk7XG59O1xuXG5XYWxsZXRzLnByb3RvdHlwZS5nZXRXYWxsZXQgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnaWQnXSwgW10sIGNhbGxiYWNrKTtcblxuICBjb25zdCBzZWxmID0gdGhpcztcblxuICBsZXQgcXVlcnkgPSAnJztcbiAgaWYgKHBhcmFtcy5ncGspIHtcbiAgICBxdWVyeSA9ICc/Z3BrPTEnO1xuICB9XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLmJpdGdvLmdldCh0aGlzLmJpdGdvLnVybCgnL3dhbGxldC8nICsgcGFyYW1zLmlkICsgcXVlcnkpKS5yZXN1bHQoKSlcbiAgICAudGhlbihmdW5jdGlvbiAod2FsbGV0KSB7XG4gICAgICByZXR1cm4gbmV3IFdhbGxldChzZWxmLmJpdGdvLCB3YWxsZXQpO1xuICAgIH0pXG4gICAgLnRoZW4oY2FsbGJhY2spXG4gICAgLmNhdGNoKGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBsaXN0SW52aXRlc1xuLy8gTGlzdCB0aGUgaW52aXRlcyBvbiBhIHVzZXJcbi8vXG5XYWxsZXRzLnByb3RvdHlwZS5saXN0SW52aXRlcyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLmJpdGdvLmdldCh0aGlzLmJpdGdvLnVybCgnL3dhbGxldGludml0ZScpKS5yZXN1bHQoKSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGNhbmNlbEludml0ZVxuLy8gY2FuY2VsIGEgd2FsbGV0IGludml0ZSB0aGF0IGEgdXNlciBpbml0aWF0ZWRcbi8vXG5XYWxsZXRzLnByb3RvdHlwZS5jYW5jZWxJbnZpdGUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnd2FsbGV0SW52aXRlSWQnXSwgW10sIGNhbGxiYWNrKTtcblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuYml0Z28uZGVsKHRoaXMuYml0Z28udXJsKCcvd2FsbGV0aW52aXRlLycgKyBwYXJhbXMud2FsbGV0SW52aXRlSWQpKS5yZXN1bHQoKSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGxpc3RTaGFyZXNcbi8vIExpc3QgdGhlIHVzZXIncyB3YWxsZXQgc2hhcmVzXG4vL1xuV2FsbGV0cy5wcm90b3R5cGUubGlzdFNoYXJlcyA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgW10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLmJpdGdvLmdldCh0aGlzLmJpdGdvLnVybCgnL3dhbGxldHNoYXJlJykpLnJlc3VsdCgpKVxuICAgIC50aGVuKGNhbGxiYWNrKVxuICAgIC5jYXRjaChjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gcmVzZW5kU2hhcmVJbnZpdGVcbi8vIFJlc2VuZCB0aGUgaW52aXRhdGlvbiBlbWFpbCB3aGljaCBzaGFyZXMgYSB3YWxsZXQgd2l0aCBhbm90aGVyIHVzZXJcbi8vIFBhcmFtczpcbi8vICAgIHdhbGxldFNoYXJlSWQgLSB0aGUgd2FsbGV0IHNoYXJlIHRvIGdldCBpbmZvcm1hdGlvbiBvblxuLy9cbldhbGxldHMucHJvdG90eXBlLnJlc2VuZFNoYXJlSW52aXRlID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcmV0dXJuIGFzeW5jIGZ1bmN0aW9uICgpIHtcbiAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gICAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd3YWxsZXRTaGFyZUlkJ10sIFtdLCBjYWxsYmFjayk7XG5cbiAgICBjb25zdCB1cmxQYXJ0cyA9IHBhcmFtcy53YWxsZXRTaGFyZUlkICsgJy9yZXNlbmRlbWFpbCc7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciAtIG5vIGltcGxpY2l0IHRoaXNcbiAgICByZXR1cm4gdGhpcy5iaXRnby5wb3N0KHRoaXMuYml0Z28udXJsKCcvd2FsbGV0c2hhcmUvJyArIHVybFBhcnRzKSkucmVzdWx0KCk7XG4gIH1cbiAgICAuY2FsbCh0aGlzKVxuICAgIC50aGVuKGNhbGxiYWNrKVxuICAgIC5jYXRjaChjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gZ2V0U2hhcmVcbi8vIEdldHMgYSB3YWxsZXQgc2hhcmUgaW5mb3JtYXRpb24sIGluY2x1ZGluZyB0aGUgZW5jcnlwdGVkIHNoYXJpbmcga2V5Y2hhaW4uIHJlcXVpcmVzIHVubG9jayBpZiBrZXljaGFpbiBpcyBwcmVzZW50LlxuLy8gUGFyYW1zOlxuLy8gICAgd2FsbGV0U2hhcmVJZCAtIHRoZSB3YWxsZXQgc2hhcmUgdG8gZ2V0IGluZm9ybWF0aW9uIG9uXG4vL1xuV2FsbGV0cy5wcm90b3R5cGUuZ2V0U2hhcmUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnd2FsbGV0U2hhcmVJZCddLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5iaXRnby5nZXQodGhpcy5iaXRnby51cmwoJy93YWxsZXRzaGFyZS8nICsgcGFyYW1zLndhbGxldFNoYXJlSWQpKS5yZXN1bHQoKSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIHVwZGF0ZVNoYXJlXG4vLyB1cGRhdGVzIGEgd2FsbGV0IHNoYXJlXG4vLyBQYXJhbXM6XG4vLyAgICB3YWxsZXRTaGFyZUlkIC0gdGhlIHdhbGxldCBzaGFyZSB0byB1cGRhdGVcbi8vICAgIHN0YXRlIC0gdGhlIG5ldyBzdGF0ZSBvZiB0aGUgd2FsbGV0IHNoYXJlXG4vL1xuV2FsbGV0cy5wcm90b3R5cGUudXBkYXRlU2hhcmUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnd2FsbGV0U2hhcmVJZCddLCBbXSwgY2FsbGJhY2spO1xuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoXG4gICAgdGhpcy5iaXRnb1xuICAgICAgLnBvc3QodGhpcy5iaXRnby51cmwoJy93YWxsZXRzaGFyZS8nICsgcGFyYW1zLndhbGxldFNoYXJlSWQpKVxuICAgICAgLnNlbmQocGFyYW1zKVxuICAgICAgLnJlc3VsdCgpXG4gIClcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGNhbmNlbFNoYXJlXG4vLyBjYW5jZWxzIGEgd2FsbGV0IHNoYXJlXG4vLyBQYXJhbXM6XG4vLyAgICB3YWxsZXRTaGFyZUlkIC0gdGhlIHdhbGxldCBzaGFyZSB0byB1cGRhdGVcbi8vXG5XYWxsZXRzLnByb3RvdHlwZS5jYW5jZWxTaGFyZSA9IGZ1bmN0aW9uIChwYXJhbXMsIGNhbGxiYWNrKSB7XG4gIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgY29tbW9uLnZhbGlkYXRlUGFyYW1zKHBhcmFtcywgWyd3YWxsZXRTaGFyZUlkJ10sIFtdLCBjYWxsYmFjayk7XG5cbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShcbiAgICB0aGlzLmJpdGdvXG4gICAgICAuZGVsKHRoaXMuYml0Z28udXJsKCcvd2FsbGV0c2hhcmUvJyArIHBhcmFtcy53YWxsZXRTaGFyZUlkKSlcbiAgICAgIC5zZW5kKClcbiAgICAgIC5yZXN1bHQoKVxuICApXG4gICAgLnRoZW4oY2FsbGJhY2spXG4gICAgLmNhdGNoKGNhbGxiYWNrKTtcbn07XG5cbi8vXG4vLyBhY2NlcHRTaGFyZVxuLy8gQWNjZXB0cyBhIHdhbGxldCBzaGFyZSwgYWRkaW5nIHRoZSB3YWxsZXQgdG8gdGhlIHVzZXIncyBsaXN0XG4vLyBOZWVkcyBhIHVzZXIncyBwYXNzd29yZCB0byBkZWNyeXB0IHRoZSBzaGFyZWQga2V5XG4vLyBQYXJhbXM6XG4vLyAgICB3YWxsZXRTaGFyZUlkIC0gdGhlIHdhbGxldCBzaGFyZSB0byBhY2NlcHRcbi8vICAgIHVzZXJQYXNzd29yZCAtIChyZXF1aXJlZCBpZiBtb3JlIGEga2V5Y2hhaW4gd2FzIHNoYXJlZCkgdXNlcidzIHBhc3N3b3JkIHRvIGRlY3J5cHQgdGhlIHNoYXJlZCB3YWxsZXRcbi8vICAgIG5ld1dhbGxldFBhc3NwaHJhc2UgLSBuZXcgd2FsbGV0IHBhc3NwaHJhc2UgZm9yIHNhdmluZyB0aGUgc2hhcmVkIHdhbGxldCB4cHJ2LlxuLy8gICAgICAgICAgICAgICAgICAgICAgICAgIElmIGxlZnQgYmxhbmsgYW5kIGEgd2FsbGV0IHdpdGggbW9yZSB0aGFuIHZpZXcgcGVybWlzc2lvbnMgd2FzIHNoYXJlZCwgdGhlbiB0aGUgdXNlcnBhc3N3b3JkIGlzIHVzZWQuXG4vLyAgICBvdmVycmlkZUVuY3J5cHRlZFhwcnYgLSBzZXQgb25seSBpZiB0aGUgeHBydiB3YXMgcmVjZWl2ZWQgb3V0LW9mLWJhbmQuXG4vL1xuV2FsbGV0cy5wcm90b3R5cGUuYWNjZXB0U2hhcmUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnd2FsbGV0U2hhcmVJZCddLCBbJ292ZXJyaWRlRW5jcnlwdGVkWHBydiddLCBjYWxsYmFjayk7XG5cbiAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gIGxldCBlbmNyeXB0ZWRYcHJ2ID0gcGFyYW1zLm92ZXJyaWRlRW5jcnlwdGVkWHBydjtcblxuICByZXR1cm4gdGhpcy5nZXRTaGFyZSh7IHdhbGxldFNoYXJlSWQ6IHBhcmFtcy53YWxsZXRTaGFyZUlkIH0pXG4gICAgLnRoZW4oZnVuY3Rpb24gKHdhbGxldFNoYXJlKSB7XG4gICAgICAvLyBSZXR1cm4gcmlnaHQgYXdheSBpZiB0aGVyZSBpcyBubyBrZXljaGFpbiB0byBkZWNyeXB0LCBvciBpZiBleHBsaWNpdCBlbmNyeXB0ZWRYcHJ2IHdhcyBwcm92aWRlZFxuICAgICAgaWYgKCF3YWxsZXRTaGFyZS5rZXljaGFpbiB8fCAhd2FsbGV0U2hhcmUua2V5Y2hhaW4uZW5jcnlwdGVkWHBydiB8fCBlbmNyeXB0ZWRYcHJ2KSB7XG4gICAgICAgIHJldHVybiB3YWxsZXRTaGFyZTtcbiAgICAgIH1cblxuICAgICAgLy8gTW9yZSB0aGFuIHZpZXdpbmcgd2FzIHJlcXVlc3RlZCwgc28gd2UgbmVlZCB0byBwcm9jZXNzIHRoZSB3YWxsZXQga2V5cyB1c2luZyB0aGUgc2hhcmVkIGVjZGggc2NoZW1lXG4gICAgICBpZiAoIXBhcmFtcy51c2VyUGFzc3dvcmQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1c2VyUGFzc3dvcmQgcGFyYW0gbXVzdCBiZSBwcm92aWRlZCB0byBkZWNyeXB0IHNoYXJlZCBrZXknKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNlbGYuYml0Z28uZ2V0RUNESEtleWNoYWluKCkudGhlbihmdW5jdGlvbiAoc2hhcmluZ0tleWNoYWluKSB7XG4gICAgICAgIGlmICghc2hhcmluZ0tleWNoYWluLmVuY3J5cHRlZFhwcnYpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VuY3J5cHRlZFhwcnYgd2FzIG5vdCBmb3VuZCBvbiBzaGFyaW5nIGtleWNoYWluJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOb3cgd2UgaGF2ZSB0aGUgc2hhcmluZyBrZXljaGFpbiwgd2UgY2FuIHdvcmsgb3V0IHRoZSBzZWNyZXQgdXNlZCBmb3Igc2hhcmluZyB0aGUgd2FsbGV0IHdpdGggdXNcbiAgICAgICAgc2hhcmluZ0tleWNoYWluLnhwcnYgPSBzZWxmLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIHBhc3N3b3JkOiBwYXJhbXMudXNlclBhc3N3b3JkLFxuICAgICAgICAgIGlucHV0OiBzaGFyaW5nS2V5Y2hhaW4uZW5jcnlwdGVkWHBydixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRGVyaXZlIGtleSBieSBwYXRoICh3aGljaCBpcyB1c2VkIGJldHdlZW4gdGhlc2UgMiB1c2VycyBvbmx5KVxuICAgICAgICBjb25zdCBzZWNyZXQgPSBnZXRTaGFyZWRTZWNyZXQoXG4gICAgICAgICAgYmlwMzIuZnJvbUJhc2U1OChzaGFyaW5nS2V5Y2hhaW4ueHBydikuZGVyaXZlUGF0aChzYW5pdGl6ZUxlZ2FjeVBhdGgod2FsbGV0U2hhcmUua2V5Y2hhaW4ucGF0aCkpLFxuICAgICAgICAgIEJ1ZmZlci5mcm9tKHdhbGxldFNoYXJlLmtleWNoYWluLmZyb21QdWJLZXksICdoZXgnKVxuICAgICAgICApLnRvU3RyaW5nKCdoZXgnKTtcblxuICAgICAgICAvLyBZZXMhIFdlIGdvdCB0aGUgc2VjcmV0IHN1Y2Nlc3NmdWxseSBoZXJlLCBub3cgZGVjcnlwdCB0aGUgc2hhcmVkIHdhbGxldCB4cHJ2XG4gICAgICAgIGNvbnN0IGRlY3J5cHRlZFNoYXJlZFdhbGxldFhwcnYgPSBzZWxmLmJpdGdvLmRlY3J5cHQoe1xuICAgICAgICAgIHBhc3N3b3JkOiBzZWNyZXQsXG4gICAgICAgICAgaW5wdXQ6IHdhbGxldFNoYXJlLmtleWNoYWluLmVuY3J5cHRlZFhwcnYsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFdlIHdpbGwgbm93IHJlLWVuY3J5cHQgdGhlIHdhbGxldCB3aXRoIG91ciBvd24gcGFzc3dvcmRcbiAgICAgICAgY29uc3QgbmV3V2FsbGV0UGFzc3BocmFzZSA9IHBhcmFtcy5uZXdXYWxsZXRQYXNzcGhyYXNlIHx8IHBhcmFtcy51c2VyUGFzc3dvcmQ7XG4gICAgICAgIGVuY3J5cHRlZFhwcnYgPSBzZWxmLmJpdGdvLmVuY3J5cHQoeyBwYXNzd29yZDogbmV3V2FsbGV0UGFzc3BocmFzZSwgaW5wdXQ6IGRlY3J5cHRlZFNoYXJlZFdhbGxldFhwcnYgfSk7XG5cbiAgICAgICAgLy8gQ2Fycnkgb24gdG8gdGhlIG5leHQgYmxvY2sgd2hlcmUgd2Ugd2lsbCBwb3N0IHRoZSBhY2NlcHRhbmNlIG9mIHRoZSBzaGFyZSB3aXRoIHRoZSBlbmNyeXB0ZWQgeHBydlxuICAgICAgICByZXR1cm4gd2FsbGV0U2hhcmU7XG4gICAgICB9KTtcbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICh3YWxsZXRTaGFyZSkge1xuICAgICAgY29uc3QgdXBkYXRlUGFyYW1zOiBhbnkgPSB7XG4gICAgICAgIHdhbGxldFNoYXJlSWQ6IHBhcmFtcy53YWxsZXRTaGFyZUlkLFxuICAgICAgICBzdGF0ZTogJ2FjY2VwdGVkJyxcbiAgICAgIH07XG5cbiAgICAgIGlmIChlbmNyeXB0ZWRYcHJ2KSB7XG4gICAgICAgIHVwZGF0ZVBhcmFtcy5lbmNyeXB0ZWRYcHJ2ID0gZW5jcnlwdGVkWHBydjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNlbGYudXBkYXRlU2hhcmUodXBkYXRlUGFyYW1zKTtcbiAgICB9KVxuICAgIC50aGVuKGNhbGxiYWNrKVxuICAgIC5jYXRjaChjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gY3JlYXRlS2V5XG4vLyBDcmVhdGUgYSBzaW5nbGUgYml0Y29pbiBrZXkuICBUaGlzIHJ1bnMgbG9jYWxseS5cbi8vIFJldHVybnM6IHtcbi8vICAgYWRkcmVzczogPGFkZHJlc3M+XG4vLyAgIGtleTogPGtleSwgaW4gV0lGIGZvcm1hdD5cbi8vIH1cbldhbGxldHMucHJvdG90eXBlLmNyZWF0ZUtleSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgY29uc3Qga2V5ID0gbWFrZVJhbmRvbUtleSgpO1xuICByZXR1cm4ge1xuICAgIGFkZHJlc3M6IGdldEFkZHJlc3NQMlBLSChrZXkpLFxuICAgIGtleToga2V5LnRvV0lGKCksXG4gIH07XG59O1xuXG4vL1xuLy8gY3JlYXRlV2FsbGV0V2l0aEtleWNoYWluc1xuLy8gQ3JlYXRlIGEgbmV3IDItb2YtMyB3YWxsZXQgYW5kIGl0J3MgYXNzb2NpYXRlZCBrZXljaGFpbnMuXG4vLyBSZXR1cm5zIHRoZSBsb2NhbGx5IGNyZWF0ZWQga2V5cyB3aXRoIHRoZWlyIGVuY3J5cHRlZCB4cHJ2cy5cbi8vICoqV0FSTklORzogQkUgU1VSRSBUTyBCQUNLVVAhIE5PVCBET0lORyBTTyBDQU4gUkVTVUxUIElOIExPU1MgT0YgRlVORFMhKipcbi8vXG4vLyAxLiBDcmVhdGVzIHRoZSB1c2VyIGtleWNoYWluIGxvY2FsbHkgb24gdGhlIGNsaWVudCwgYW5kIGVuY3J5cHRzIGl0IHdpdGggdGhlIHByb3ZpZGVkIHBhc3NwaHJhc2Vcbi8vIDIuIElmIG5vIHhwdWIgd2FzIHByb3ZpZGVkLCBjcmVhdGVzIHRoZSBiYWNrdXAga2V5Y2hhaW4gbG9jYWxseSBvbiB0aGUgY2xpZW50LCBhbmQgZW5jcnlwdHMgaXQgd2l0aCB0aGUgcHJvdmlkZWQgcGFzc3BocmFzZVxuLy8gMy4gVXBsb2FkcyB0aGUgZW5jcnlwdGVkIHVzZXIgYW5kIGJhY2t1cCBrZXljaGFpbnMgdG8gQml0R29cbi8vIDQuIENyZWF0ZXMgdGhlIEJpdEdvIGtleSBvbiB0aGUgc2VydmljZVxuLy8gNS4gQ3JlYXRlcyB0aGUgd2FsbGV0IG9uIEJpdEdvIHdpdGggdGhlIDMgcHVibGljIGtleXMgYWJvdmVcbi8vXG4vLyBQYXJhbWV0ZXJzIGluY2x1ZGU6XG4vLyAgIFwicGFzc3BocmFzZVwiOiB3YWxsZXQgcGFzc3BocmFzZSB0byBlbmNyeXB0IHVzZXIgYW5kIGJhY2t1cCBrZXlzIHdpdGhcbi8vICAgXCJsYWJlbFwiOiB3YWxsZXQgbGFiZWwsIGlzIHNob3duIGluIEJpdEdvIFVJXG4vLyAgIFwiYmFja3VwWHB1YlwiOiBiYWNrdXAga2V5Y2hhaW4geHB1YiwgaXQgaXMgSElHSExZIFJFQ09NTUVOREVEIHlvdSBnZW5lcmF0ZSB0aGlzIG9uIGEgc2VwYXJhdGUgbWFjaGluZSFcbi8vICAgICAgICAgICAgICAgICBCSVRHTyBET0VTIE5PVCBHVUFSQU5URUUgU0FGRVRZIE9GIFdBTExFVFMgV0lUSCBNVUxUSVBMRSBLRVlTIENSRUFURUQgT04gVEhFIFNBTUUgTUFDSElORSAqKlxuLy8gICBcImJhY2t1cFhwdWJQcm92aWRlclwiOiBQcm92aXNpb24gYmFja3VwIGtleSBmcm9tIHRoaXMgcHJvdmlkZXIgKEtSUyksIGUuZy4gXCJrZXl0ZXJuYWxcIi5cbi8vICAgICAgICAgICAgICAgICAgICAgICAgIFNldHRpbmcgdGhpcyB2YWx1ZSB3aWxsIGNyZWF0ZSBhbiBpbnN0YW50LWNhcGFibGUgd2FsbGV0LlxuLy8gICBcInBhc3Njb2RlRW5jcnlwdGlvbkNvZGVcIjogdGhlIGNvZGUgdXNlZCB0byBlbmNyeXB0IHRoZSB3YWxsZXQgcGFzc2NvZGUgdXNlZCBpbiB0aGUgcmVjb3ZlcnkgcHJvY2Vzc1xuLy8gUmV0dXJuczoge1xuLy8gICB3YWxsZXQ6IG5ld2x5IGNyZWF0ZWQgd2FsbGV0IG1vZGVsIG9iamVjdFxuLy8gICB1c2VyS2V5Y2hhaW46IHRoZSBuZXdseSBjcmVhdGVkIHVzZXIga2V5Y2hhaW4sIHdoaWNoIGhhcyBhbiBlbmNyeXB0ZWQgeHBydiBzdG9yZWQgb24gQml0R29cbi8vICAgYmFja3VwS2V5Y2hhaW46IHRoZSBuZXdseSBjcmVhdGVkIGJhY2t1cCBrZXljaGFpblxuLy9cbi8vICoqIEJFIFNVUkUgVE8gQkFDSyBVUCBUSEUgRU5DUllQVEVEIFVTRVIgQU5EIEJBQ0tVUCBLRVlDSEFJTlMhKipcbi8vXG4vLyB9XG5XYWxsZXRzLnByb3RvdHlwZS5jcmVhdGVXYWxsZXRXaXRoS2V5Y2hhaW5zID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMoXG4gICAgcGFyYW1zLFxuICAgIFsncGFzc3BocmFzZSddLFxuICAgIFsnbGFiZWwnLCAnYmFja3VwWHB1YicsICdlbnRlcnByaXNlJywgJ3Bhc3Njb2RlRW5jcnlwdGlvbkNvZGUnXSxcbiAgICBjYWxsYmFja1xuICApO1xuICBjb25zdCBzZWxmID0gdGhpcztcbiAgY29uc3QgbGFiZWwgPSBwYXJhbXMubGFiZWw7XG5cbiAgLy8gQ3JlYXRlIHRoZSB1c2VyIGFuZCBiYWNrdXAga2V5LlxuICBjb25zdCB1c2VyS2V5Y2hhaW4gPSB0aGlzLmJpdGdvLmtleWNoYWlucygpLmNyZWF0ZSgpO1xuICB1c2VyS2V5Y2hhaW4uZW5jcnlwdGVkWHBydiA9IHRoaXMuYml0Z28uZW5jcnlwdCh7IHBhc3N3b3JkOiBwYXJhbXMucGFzc3BocmFzZSwgaW5wdXQ6IHVzZXJLZXljaGFpbi54cHJ2IH0pO1xuXG4gIGNvbnN0IGtleWNoYWluRGF0YTogYW55ID0ge1xuICAgIHhwdWI6IHVzZXJLZXljaGFpbi54cHViLFxuICAgIGVuY3J5cHRlZFhwcnY6IHVzZXJLZXljaGFpbi5lbmNyeXB0ZWRYcHJ2LFxuICB9O1xuXG4gIGlmIChwYXJhbXMucGFzc2NvZGVFbmNyeXB0aW9uQ29kZSkge1xuICAgIGtleWNoYWluRGF0YS5vcmlnaW5hbFBhc3Njb2RlRW5jcnlwdGlvbkNvZGUgPSBwYXJhbXMucGFzc2NvZGVFbmNyeXB0aW9uQ29kZTtcbiAgfVxuXG4gIGNvbnN0IGhhc0JhY2t1cFhwdWIgPSAhIXBhcmFtcy5iYWNrdXBYcHViO1xuICBjb25zdCBoYXNCYWNrdXBYcHViUHJvdmlkZXIgPSAhIXBhcmFtcy5iYWNrdXBYcHViUHJvdmlkZXI7XG4gIGlmIChoYXNCYWNrdXBYcHViICYmIGhhc0JhY2t1cFhwdWJQcm92aWRlcikge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IHByb3ZpZGUgbW9yZSB0aGFuIG9uZSBiYWNrdXBYcHViIG9yIGJhY2t1cFhwdWJQcm92aWRlciBmbGFnJyk7XG4gIH1cblxuICBpZiAocGFyYW1zLmRpc2FibGVUcmFuc2FjdGlvbk5vdGlmaWNhdGlvbnMgIT09IHVuZGVmaW5lZCAmJiAhXy5pc0Jvb2xlYW4ocGFyYW1zLmRpc2FibGVUcmFuc2FjdGlvbk5vdGlmaWNhdGlvbnMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBkaXNhYmxlVHJhbnNhY3Rpb25Ob3RpZmljYXRpb25zIHRvIGJlIGEgYm9vbGVhbi4gJyk7XG4gIH1cblxuICBsZXQgYmFja3VwS2V5Y2hhaW47XG4gIGxldCBiaXRnb0tleWNoYWluO1xuXG4gIC8vIEFkZCB0aGUgdXNlciBrZXljaGFpblxuICByZXR1cm4gc2VsZi5iaXRnb1xuICAgIC5rZXljaGFpbnMoKVxuICAgIC5hZGQoa2V5Y2hhaW5EYXRhKVxuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIEFkZCB0aGUgYmFja3VwIGtleWNoYWluXG4gICAgICBpZiAocGFyYW1zLmJhY2t1cFhwdWJQcm92aWRlcikge1xuICAgICAgICAvLyBJZiByZXF1ZXN0ZWQsIHVzZSBhIEtSUyBvciBiYWNrdXAga2V5IHByb3ZpZGVyXG4gICAgICAgIHJldHVybiBzZWxmLmJpdGdvXG4gICAgICAgICAgLmtleWNoYWlucygpXG4gICAgICAgICAgLmNyZWF0ZUJhY2t1cCh7XG4gICAgICAgICAgICBwcm92aWRlcjogcGFyYW1zLmJhY2t1cFhwdWJQcm92aWRlcixcbiAgICAgICAgICAgIGRpc2FibGVLUlNFbWFpbDogcGFyYW1zLmRpc2FibGVLUlNFbWFpbCxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChrZXljaGFpbikge1xuICAgICAgICAgICAgYmFja3VwS2V5Y2hhaW4gPSBrZXljaGFpbjtcbiAgICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtcy5iYWNrdXBYcHViKSB7XG4gICAgICAgIC8vIHVzZXIgcHJvdmlkZWQgYmFja3VwIHhwdWJcbiAgICAgICAgYmFja3VwS2V5Y2hhaW4gPSB7IHhwdWI6IHBhcmFtcy5iYWNrdXBYcHViIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBubyBwcm92aWRlZCB4cHViLCBzbyBkZWZhdWx0IHRvIGNyZWF0aW5nIG9uZSBoZXJlXG4gICAgICAgIGJhY2t1cEtleWNoYWluID0gc2VsZi5iaXRnby5rZXljaGFpbnMoKS5jcmVhdGUoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHNlbGYuYml0Z28ua2V5Y2hhaW5zKCkuYWRkKGJhY2t1cEtleWNoYWluKTtcbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBzZWxmLmJpdGdvLmtleWNoYWlucygpLmNyZWF0ZUJpdEdvKCk7XG4gICAgfSlcbiAgICAudGhlbihmdW5jdGlvbiAoa2V5Y2hhaW4pIHtcbiAgICAgIGJpdGdvS2V5Y2hhaW4gPSBrZXljaGFpbjtcbiAgICAgIGNvbnN0IHdhbGxldFBhcmFtczogYW55ID0ge1xuICAgICAgICBsYWJlbDogbGFiZWwsXG4gICAgICAgIG06IDIsXG4gICAgICAgIG46IDMsXG4gICAgICAgIGtleWNoYWluczogW3sgeHB1YjogdXNlcktleWNoYWluLnhwdWIgfSwgeyB4cHViOiBiYWNrdXBLZXljaGFpbi54cHViIH0sIHsgeHB1YjogYml0Z29LZXljaGFpbi54cHViIH1dLFxuICAgICAgfTtcblxuICAgICAgaWYgKHBhcmFtcy5lbnRlcnByaXNlKSB7XG4gICAgICAgIHdhbGxldFBhcmFtcy5lbnRlcnByaXNlID0gcGFyYW1zLmVudGVycHJpc2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYXJhbXMuZGlzYWJsZVRyYW5zYWN0aW9uTm90aWZpY2F0aW9ucykge1xuICAgICAgICB3YWxsZXRQYXJhbXMuZGlzYWJsZVRyYW5zYWN0aW9uTm90aWZpY2F0aW9ucyA9IHBhcmFtcy5kaXNhYmxlVHJhbnNhY3Rpb25Ob3RpZmljYXRpb25zO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VsZi5hZGQod2FsbGV0UGFyYW1zKTtcbiAgICB9KVxuICAgIC50aGVuKGZ1bmN0aW9uIChuZXdXYWxsZXQpIHtcbiAgICAgIGNvbnN0IHJlc3VsdDogYW55ID0ge1xuICAgICAgICB3YWxsZXQ6IG5ld1dhbGxldCxcbiAgICAgICAgdXNlcktleWNoYWluOiB1c2VyS2V5Y2hhaW4sXG4gICAgICAgIGJhY2t1cEtleWNoYWluOiBiYWNrdXBLZXljaGFpbixcbiAgICAgICAgYml0Z29LZXljaGFpbjogYml0Z29LZXljaGFpbixcbiAgICAgIH07XG5cbiAgICAgIGlmIChiYWNrdXBLZXljaGFpbi54cHJ2KSB7XG4gICAgICAgIHJlc3VsdC53YXJuaW5nID0gJ0JlIHN1cmUgdG8gYmFja3VwIHRoZSBiYWNrdXAga2V5Y2hhaW4gLS0gaXQgaXMgbm90IHN0b3JlZCBhbnl3aGVyZSBlbHNlISc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGNyZWF0ZUZvcndhcmRXYWxsZXRcbi8vIENyZWF0ZXMgYSBmb3J3YXJkIHdhbGxldCBmcm9tIGEgc2luZ2xlIHByaXZhdGUga2V5LlxuLy8gQml0R28gd2lsbCB3YXRjaCB0aGUgd2FsbGV0IGFuZCBzZW5kIGFueSBpbmNvbWluZyB0cmFuc2FjdGlvbnMgdG8gYSBkZXN0aW5hdGlvbiBtdWx0aS1zaWcgd2FsbGV0XG4vLyBXQVJOSU5HOiBUSEUgUFJJVkFURSBLRVkgV0lMTCBCRSBTRU5UIFRPIEJJVEdPLiBZT1UgTVVTVCBDT05UQUNUIEJJVEdPIEJFRk9SRSBVU0lORyBUSElTIEZFQVRVUkUhXG4vLyBXRSBDQU5OT1QgR1VBUkFOVEVFIFRIRSBTRUNVUklUWSBPRiBTSU5HTEUtU0lHIFdBTExFVFMgQVMgQ1VTVE9EWSBJUyBVTkNMRUFSLlxuLy9cbi8vIFBhcmFtczpcbi8vICAgIHByaXZLZXkgLSB0aGUgcHJpdmF0ZSBrZXkgb24gYSBsZWdhY3kgc2luZ2xlLXNpZ25hdHVyZSB3YWxsZXQgdG8gYmUgd2F0Y2hlZCAoV0lGIGZvcm1hdClcbi8vICAgIHNvdXJjZUFkZHJlc3MgLSB0aGUgYml0Y29pbiBhZGRyZXNzIHRvIGZvcndhcmQgZnJvbSAoY29ycmVzcG9uZHMgdG8gdGhlIHByaXZhdGUga2V5KVxuLy8gICAgZGVzdGluYXRpb25XYWxsZXQgLSB0aGUgd2FsbGV0IG9iamVjdCB0byBzZW5kIHRoZSBkZXN0aW5hdGlvbiBjb2lucyB0byAod2hlbiBpbmNvbWluZyB0cmFuc2FjdGlvbnMgYXJlIGRldGVjdGVkKVxuLy8gICAgbGFiZWwgLSBsYWJlbCBmb3IgdGhlIHdhbGxldFxuLy9cbldhbGxldHMucHJvdG90eXBlLmNyZWF0ZUZvcndhcmRXYWxsZXQgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsncHJpdktleScsICdzb3VyY2VBZGRyZXNzJ10sIFsnbGFiZWwnXSwgY2FsbGJhY2spO1xuXG4gIGlmICghXy5pc09iamVjdChwYXJhbXMuZGVzdGluYXRpb25XYWxsZXQpIHx8ICFwYXJhbXMuZGVzdGluYXRpb25XYWxsZXQuaWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGluZyBkZXN0aW5hdGlvbldhbGxldCBvYmplY3QnKTtcbiAgfVxuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuXG4gIGxldCBuZXdEZXN0aW5hdGlvbkFkZHJlc3M7XG4gIGxldCBhZGRyZXNzRnJvbVByaXZLZXk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBrZXkgPSB1dHhvbGliLkVDUGFpci5mcm9tV0lGKHBhcmFtcy5wcml2S2V5LCBnZXROZXR3b3JrKCkgYXMgdXR4b2xpYi5CaXRjb2luSlNOZXR3b3JrKTtcbiAgICBhZGRyZXNzRnJvbVByaXZLZXkgPSBnZXRBZGRyZXNzUDJQS0goa2V5KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZXhwZWN0aW5nIGEgdmFsaWQgcHJpdktleScpO1xuICB9XG5cbiAgaWYgKGFkZHJlc3NGcm9tUHJpdktleSAhPT0gcGFyYW1zLnNvdXJjZUFkZHJlc3MpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAncHJpdktleSBkb2VzIG5vdCBtYXRjaCBzb3VyY2UgYWRkcmVzcyAtIGdvdCAnICsgYWRkcmVzc0Zyb21Qcml2S2V5ICsgJyBleHBlY3RlZCAnICsgcGFyYW1zLnNvdXJjZUFkZHJlc3NcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIHBhcmFtcy5kZXN0aW5hdGlvbldhbGxldC5jcmVhdGVBZGRyZXNzKCkudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgLy8gQ3JlYXRlIG5ldyBhZGRyZXNzIG9uIHRoZSBkZXN0aW5hdGlvbiB3YWxsZXQgdG8gcmVjZWl2ZSBjb2luc1xuICAgIG5ld0Rlc3RpbmF0aW9uQWRkcmVzcyA9IHJlc3VsdC5hZGRyZXNzO1xuXG4gICAgY29uc3Qgd2FsbGV0UGFyYW1zOiBhbnkgPSB7XG4gICAgICB0eXBlOiAnZm9yd2FyZCcsXG4gICAgICBzb3VyY2VBZGRyZXNzOiBwYXJhbXMuc291cmNlQWRkcmVzcyxcbiAgICAgIGRlc3RpbmF0aW9uQWRkcmVzczogbmV3RGVzdGluYXRpb25BZGRyZXNzLFxuICAgICAgcHJpdktleTogcGFyYW1zLnByaXZLZXksXG4gICAgICBsYWJlbDogcGFyYW1zLmxhYmVsLFxuICAgIH07XG5cbiAgICBpZiAocGFyYW1zLmVudGVycHJpc2UpIHtcbiAgICAgIHdhbGxldFBhcmFtcy5lbnRlcnByaXNlID0gcGFyYW1zLmVudGVycHJpc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShzZWxmLmJpdGdvLnBvc3Qoc2VsZi5iaXRnby51cmwoJy93YWxsZXQnKSkuc2VuZCh3YWxsZXRQYXJhbXMpLnJlc3VsdCgpKVxuICAgICAgLnRoZW4oY2FsbGJhY2spXG4gICAgICAuY2F0Y2goY2FsbGJhY2spO1xuICB9KTtcbn07XG5cbi8qKlxuICogQWRkIGEgbmV3IHdhbGxldCAoYWR2YW5jZWQgbW9kZSkuXG4gKiBUaGlzIGFsbG93cyB5b3UgdG8gbWFudWFsbHkgc3VibWl0IHRoZSBrZXljaGFpbnMsIHR5cGUsIG0gYW5kIG4gb2YgdGhlIHdhbGxldFxuICogQHBhcmFtIHtzdHJpbmd9IGxhYmVsIGxhYmVsIG9mIHRoZSB3YWxsZXQgdG8gYmUgc2hvd24gaW4gVUlcbiAqIEBwYXJhbSB7bnVtYmVyfSBtIG51bWJlciBvZiBrZXlzIHJlcXVpcmVkIHRvIHVubG9jayB3YWxsZXQgKDIpXG4gKiBAcGFyYW0ge251bWJlcn0gbiBudW1iZXIgb2Yga2V5cyBhdmFpbGFibGUgb24gdGhlIHdhbGxldCAoMylcbiAqIEBwYXJhbSB7YXJyYXl9IGtleWNoYWlucyBhcnJheSBvZiBrZXljaGFpbiB4cHVic1xuICogQHBhcmFtIHtzdHJpbmd9IGVudGVycHJpc2UgSUQgb2YgdGhlIGVudGVycHJpc2UgZW50aXR5IHRvIGNyZWF0ZSB0aGlzIHdhbGxldCB1bmRlci5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZGlzYWJsZVRyYW5zYWN0aW9uTm90aWZpY2F0aW9ucyBXaGVuIHNldCB0byB0cnVlIGRpc2FibGVzIG5vdGlmaWNhdGlvbnMgZm9yIHRyYW5zYWN0aW9ucyBvbiB0aGlzIHdhbGxldC5cbiAqL1xuV2FsbGV0cy5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICBjb21tb24udmFsaWRhdGVQYXJhbXMocGFyYW1zLCBbXSwgWydsYWJlbCcsICdlbnRlcnByaXNlJ10sIGNhbGxiYWNrKTtcblxuICBpZiAoQXJyYXkuaXNBcnJheShwYXJhbXMua2V5Y2hhaW5zKSA9PT0gZmFsc2UgfHwgIV8uaXNOdW1iZXIocGFyYW1zLm0pIHx8ICFfLmlzTnVtYmVyKHBhcmFtcy5uKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhcmd1bWVudCcpO1xuICB9XG5cbiAgLy8gVE9ETzogc3VwcG9ydCBtb3JlIHR5cGVzIG9mIG11bHRpc2lnXG4gIGlmIChwYXJhbXMubSAhPT0gMiB8fCBwYXJhbXMubiAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcigndW5zdXBwb3J0ZWQgbXVsdGktc2lnIHR5cGUnKTtcbiAgfVxuXG4gIGNvbnN0IHNlbGYgPSB0aGlzO1xuICBjb25zdCBrZXljaGFpbnMgPSBwYXJhbXMua2V5Y2hhaW5zLm1hcChmdW5jdGlvbiAoaykge1xuICAgIHJldHVybiB7IHhwdWI6IGsueHB1YiB9O1xuICB9KTtcbiAgY29uc3Qgd2FsbGV0UGFyYW1zOiBhbnkgPSB7XG4gICAgbGFiZWw6IHBhcmFtcy5sYWJlbCxcbiAgICBtOiBwYXJhbXMubSxcbiAgICBuOiBwYXJhbXMubixcbiAgICBrZXljaGFpbnM6IGtleWNoYWlucyxcbiAgfTtcblxuICBpZiAocGFyYW1zLmVudGVycHJpc2UpIHtcbiAgICB3YWxsZXRQYXJhbXMuZW50ZXJwcmlzZSA9IHBhcmFtcy5lbnRlcnByaXNlO1xuICB9XG5cbiAgaWYgKHBhcmFtcy5kaXNhYmxlVHJhbnNhY3Rpb25Ob3RpZmljYXRpb25zKSB7XG4gICAgd2FsbGV0UGFyYW1zLmRpc2FibGVUcmFuc2FjdGlvbk5vdGlmaWNhdGlvbnMgPSBwYXJhbXMuZGlzYWJsZVRyYW5zYWN0aW9uTm90aWZpY2F0aW9ucztcbiAgfVxuXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5iaXRnby5wb3N0KHRoaXMuYml0Z28udXJsKCcvd2FsbGV0JykpLnNlbmQod2FsbGV0UGFyYW1zKS5yZXN1bHQoKSlcbiAgICAudGhlbihmdW5jdGlvbiAoYm9keSkge1xuICAgICAgcmV0dXJuIG5ldyBXYWxsZXQoc2VsZi5iaXRnbywgYm9keSk7XG4gICAgfSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxuLy9cbi8vIGdldFxuLy8gU2hvcnRoYW5kIHRvIGdldFdhbGxldFxuLy8gUGFyYW1ldGVycyBpbmNsdWRlOlxuLy8gICBpZDogdGhlIGlkIG9mIHRoZSB3YWxsZXRcbi8vXG5XYWxsZXRzLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICByZXR1cm4gdGhpcy5nZXRXYWxsZXQocGFyYW1zLCBjYWxsYmFjayk7XG59O1xuXG4vL1xuLy8gcmVtb3ZlXG4vLyBSZW1vdmUgYW4gZXhpc3Rpbmcgd2FsbGV0LlxuLy8gUGFyYW1ldGVycyBpbmNsdWRlOlxuLy8gICBpZDogdGhlIGlkIG9mIHRoZSB3YWxsZXRcbi8vXG5XYWxsZXRzLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gIGNvbW1vbi52YWxpZGF0ZVBhcmFtcyhwYXJhbXMsIFsnaWQnXSwgW10sIGNhbGxiYWNrKTtcblxuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuYml0Z28uZGVsKHRoaXMuYml0Z28udXJsKCcvd2FsbGV0LycgKyBwYXJhbXMuaWQpKS5yZXN1bHQoKSlcbiAgICAudGhlbihjYWxsYmFjaylcbiAgICAuY2F0Y2goY2FsbGJhY2spO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBXYWxsZXRzO1xuIl19

Выполнить команду


Для локальной разработки. Не используйте в интернете!