PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/avalanche/dist/utils

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

"use strict";
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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __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 });
/**
 * @packageDocumentation
 * @module Utils-BinTools
 */
const bn_js_1 = __importDefault(require("bn.js"));
const buffer_1 = require("buffer/");
const create_hash_1 = __importDefault(require("create-hash"));
const bech32 = __importStar(require("bech32"));
const base58_1 = require("./base58");
const errors_1 = require("../utils/errors");
const ethers_1 = require("ethers");
/**
 * A class containing tools useful in interacting with binary data cross-platform using
 * nodejs & javascript.
 *
 * This class should never be instantiated directly. Instead,
 * invoke the "BinTools.getInstance()" static * function to grab the singleton
 * instance of the tools.
 *
 * Everything in this library uses
 * the {@link https://github.com/feross/buffer|feross's Buffer class}.
 *
 * ```js
 * const bintools: BinTools = BinTools.getInstance();
 * const b58str:  = bintools.bufferToB58(Buffer.from("Wubalubadubdub!"));
 * ```
 */
class BinTools {
    constructor() {
        /**
         * Returns true if meets requirements to parse as an address as Bech32 on X-Chain or P-Chain, otherwise false
         * @param address the string to verify is address
         */
        this.isPrimaryBechAddress = (address) => {
            const parts = address.trim().split("-");
            if (parts.length !== 2) {
                return false;
            }
            try {
                bech32.bech32.fromWords(bech32.bech32.decode(parts[1]).words);
            }
            catch (err) {
                return false;
            }
            return true;
        };
        /**
         * Produces a string from a {@link https://github.com/feross/buffer|Buffer}
         * representing a string. ONLY USED IN TRANSACTION FORMATTING, ASSUMED LENGTH IS PREPENDED.
         *
         * @param buff The {@link https://github.com/feross/buffer|Buffer} to convert to a string
         */
        this.bufferToString = (buff) => this.copyFrom(buff, 2).toString("utf8");
        /**
         * Produces a {@link https://github.com/feross/buffer|Buffer} from a string. ONLY USED IN TRANSACTION FORMATTING, LENGTH IS PREPENDED.
         *
         * @param str The string to convert to a {@link https://github.com/feross/buffer|Buffer}
         */
        this.stringToBuffer = (str) => {
            const buff = buffer_1.Buffer.alloc(2 + str.length);
            buff.writeUInt16BE(str.length, 0);
            buff.write(str, 2, str.length, "utf8");
            return buff;
        };
        /**
         * Makes a copy (no reference) of a {@link https://github.com/feross/buffer|Buffer}
         * over provided indecies.
         *
         * @param buff The {@link https://github.com/feross/buffer|Buffer} to copy
         * @param start The index to start the copy
         * @param end The index to end the copy
         */
        this.copyFrom = (buff, start = 0, end = undefined) => {
            if (end === undefined) {
                end = buff.length;
            }
            return buffer_1.Buffer.from(Uint8Array.prototype.slice.call(buff.slice(start, end)));
        };
        /**
         * Takes a {@link https://github.com/feross/buffer|Buffer} and returns a base-58 string of
         * the {@link https://github.com/feross/buffer|Buffer}.
         *
         * @param buff The {@link https://github.com/feross/buffer|Buffer} to convert to base-58
         */
        this.bufferToB58 = (buff) => this.b58.encode(buff);
        /**
         * Takes a base-58 string and returns a {@link https://github.com/feross/buffer|Buffer}.
         *
         * @param b58str The base-58 string to convert
         * to a {@link https://github.com/feross/buffer|Buffer}
         */
        this.b58ToBuffer = (b58str) => this.b58.decode(b58str);
        /**
         * Takes a {@link https://github.com/feross/buffer|Buffer} and returns an ArrayBuffer.
         *
         * @param buff The {@link https://github.com/feross/buffer|Buffer} to
         * convert to an ArrayBuffer
         */
        this.fromBufferToArrayBuffer = (buff) => {
            const ab = new ArrayBuffer(buff.length);
            const view = new Uint8Array(ab);
            for (let i = 0; i < buff.length; ++i) {
                view[`${i}`] = buff[`${i}`];
            }
            return view;
        };
        /**
         * Takes an ArrayBuffer and converts it to a {@link https://github.com/feross/buffer|Buffer}.
         *
         * @param ab The ArrayBuffer to convert to a {@link https://github.com/feross/buffer|Buffer}
         */
        this.fromArrayBufferToBuffer = (ab) => {
            const buf = buffer_1.Buffer.alloc(ab.byteLength);
            for (let i = 0; i < ab.byteLength; ++i) {
                buf[`${i}`] = ab[`${i}`];
            }
            return buf;
        };
        /**
         * Takes a {@link https://github.com/feross/buffer|Buffer} and converts it
         * to a {@link https://github.com/indutny/bn.js/|BN}.
         *
         * @param buff The {@link https://github.com/feross/buffer|Buffer} to convert
         * to a {@link https://github.com/indutny/bn.js/|BN}
         */
        this.fromBufferToBN = (buff) => {
            if (typeof buff === "undefined") {
                return undefined;
            }
            return new bn_js_1.default(buff.toString("hex"), 16, "be");
        };
        /**
         * Takes a {@link https://github.com/indutny/bn.js/|BN} and converts it
         * to a {@link https://github.com/feross/buffer|Buffer}.
         *
         * @param bn The {@link https://github.com/indutny/bn.js/|BN} to convert
         * to a {@link https://github.com/feross/buffer|Buffer}
         * @param length The zero-padded length of the {@link https://github.com/feross/buffer|Buffer}
         */
        this.fromBNToBuffer = (bn, length) => {
            if (typeof bn === "undefined") {
                return undefined;
            }
            const newarr = bn.toArray("be");
            /**
             * CKC: Still unsure why bn.toArray with a "be" and a length do not work right. Bug?
             */
            if (length) {
                // bn toArray with the length parameter doesn't work correctly, need this.
                const x = length - newarr.length;
                for (let i = 0; i < x; i++) {
                    newarr.unshift(0);
                }
            }
            return buffer_1.Buffer.from(newarr);
        };
        /**
         * Takes a {@link https://github.com/feross/buffer|Buffer} and adds a checksum, returning
         * a {@link https://github.com/feross/buffer|Buffer} with the 4-byte checksum appended.
         *
         * @param buff The {@link https://github.com/feross/buffer|Buffer} to append a checksum
         */
        this.addChecksum = (buff) => {
            const hashslice = buffer_1.Buffer.from((0, create_hash_1.default)("sha256").update(buff).digest().slice(28));
            return buffer_1.Buffer.concat([buff, hashslice]);
        };
        /**
         * Takes a {@link https://github.com/feross/buffer|Buffer} with an appended 4-byte checksum
         * and returns true if the checksum is valid, otherwise false.
         *
         * @param b The {@link https://github.com/feross/buffer|Buffer} to validate the checksum
         */
        this.validateChecksum = (buff) => {
            const checkslice = buff.slice(buff.length - 4);
            const hashslice = buffer_1.Buffer.from((0, create_hash_1.default)("sha256")
                .update(buff.slice(0, buff.length - 4))
                .digest()
                .slice(28));
            return checkslice.toString("hex") === hashslice.toString("hex");
        };
        /**
         * Takes a {@link https://github.com/feross/buffer|Buffer} and returns a base-58 string with
         * checksum as per the cb58 standard.
         *
         * @param bytes A {@link https://github.com/feross/buffer|Buffer} to serialize
         *
         * @returns A serialized base-58 string of the Buffer.
         */
        this.cb58Encode = (bytes) => {
            const x = this.addChecksum(bytes);
            return this.bufferToB58(x);
        };
        /**
         * Takes a cb58 serialized {@link https://github.com/feross/buffer|Buffer} or base-58 string
         * and returns a {@link https://github.com/feross/buffer|Buffer} of the original data. Throws on error.
         *
         * @param bytes A cb58 serialized {@link https://github.com/feross/buffer|Buffer} or base-58 string
         */
        this.cb58Decode = (bytes) => {
            if (typeof bytes === "string") {
                bytes = this.b58ToBuffer(bytes);
            }
            if (this.validateChecksum(bytes)) {
                return this.copyFrom(bytes, 0, bytes.length - 4);
            }
            throw new errors_1.ChecksumError("Error - BinTools.cb58Decode: invalid checksum");
        };
        this.cb58DecodeWithChecksum = (bytes) => {
            if (typeof bytes === "string") {
                bytes = this.b58ToBuffer(bytes);
            }
            if (this.validateChecksum(bytes)) {
                return `0x${this.copyFrom(bytes, 0, bytes.length).toString("hex")}`;
            }
            throw new errors_1.ChecksumError("Error - BinTools.cb58Decode: invalid checksum");
        };
        this.addressToString = (hrp, chainid, bytes) => `${chainid}-${bech32.bech32.encode(hrp, bech32.bech32.toWords(bytes))}`;
        this.stringToAddress = (address, hrp) => {
            if (address.substring(0, 2) === "0x") {
                // ETH-style address
                if (ethers_1.utils.isAddress(address)) {
                    return buffer_1.Buffer.from(address.substring(2), "hex");
                }
                else {
                    throw new errors_1.HexError("Error - Invalid address");
                }
            }
            // Bech32 addresses
            const parts = address.trim().split("-");
            if (parts.length < 2) {
                throw new errors_1.Bech32Error("Error - Valid address should include -");
            }
            if (parts[0].length < 1) {
                throw new errors_1.Bech32Error("Error - Valid address must have prefix before -");
            }
            const split = parts[1].lastIndexOf("1");
            if (split < 0) {
                throw new errors_1.Bech32Error("Error - Valid address must include separator (1)");
            }
            const humanReadablePart = parts[1].slice(0, split);
            if (humanReadablePart.length < 1) {
                throw new errors_1.Bech32Error("Error - HRP should be at least 1 character");
            }
            if (humanReadablePart !== "avax" &&
                humanReadablePart !== "fuji" &&
                humanReadablePart != "local" &&
                humanReadablePart != "custom" &&
                humanReadablePart != hrp) {
                throw new errors_1.Bech32Error("Error - Invalid HRP");
            }
            return buffer_1.Buffer.from(bech32.bech32.fromWords(bech32.bech32.decode(parts[1]).words));
        };
        /**
         * Takes an address and returns its {@link https://github.com/feross/buffer|Buffer}
         * representation if valid. A more strict version of stringToAddress.
         *
         * @param addr A string representation of the address
         * @param blockchainID A cb58 encoded string representation of the blockchainID
         * @param alias A chainID alias, if any, that the address can also parse from.
         * @param addrlen VMs can use any addressing scheme that they like, so this is the appropriate number of address bytes. Default 20.
         *
         * @returns A {@link https://github.com/feross/buffer|Buffer} for the address if valid,
         * undefined if not valid.
         */
        this.parseAddress = (addr, blockchainID, alias = undefined, addrlen = 20) => {
            const abc = addr.split("-");
            if (abc.length === 2 &&
                ((alias && abc[0] === alias) || (blockchainID && abc[0] === blockchainID))) {
                const addrbuff = this.stringToAddress(addr);
                if ((addrlen && addrbuff.length === addrlen) || !addrlen) {
                    return addrbuff;
                }
            }
            return undefined;
        };
        this.b58 = base58_1.Base58.getInstance();
    }
    /**
     * Retrieves the BinTools singleton.
     */
    static getInstance() {
        if (!BinTools.instance) {
            BinTools.instance = new BinTools();
        }
        return BinTools.instance;
    }
    /**
     * Returns true if base64, otherwise false
     * @param str the string to verify is Base64
     */
    isBase64(str) {
        if (str === "" || str.trim() === "") {
            return false;
        }
        try {
            let b64 = buffer_1.Buffer.from(str, "base64");
            return b64.toString("base64") === str;
        }
        catch (err) {
            return false;
        }
    }
    /**
     * Returns true if cb58, otherwise false
     * @param cb58 the string to verify is cb58
     */
    isCB58(cb58) {
        return this.isBase58(cb58);
    }
    /**
     * Returns true if base58, otherwise false
     * @param base58 the string to verify is base58
     */
    isBase58(base58) {
        if (base58 === "" || base58.trim() === "") {
            return false;
        }
        try {
            return this.b58.encode(this.b58.decode(base58)) === base58;
        }
        catch (err) {
            return false;
        }
    }
    /**
     * Returns true if hexidecimal, otherwise false
     * @param hex the string to verify is hexidecimal
     */
    isHex(hex) {
        if (hex === "" || hex.trim() === "") {
            return false;
        }
        if ((hex.startsWith("0x") && hex.slice(2).match(/^[0-9A-Fa-f]/g)) ||
            hex.match(/^[0-9A-Fa-f]/g)) {
            return true;
        }
        else {
            return false;
        }
    }
    /**
     * Returns true if decimal, otherwise false
     * @param str the string to verify is hexidecimal
     */
    isDecimal(str) {
        if (str === "" || str.trim() === "") {
            return false;
        }
        try {
            return new bn_js_1.default(str, 10).toString(10) === str.trim();
        }
        catch (err) {
            return false;
        }
    }
}
exports.default = BinTools;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmludG9vbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvYmludG9vbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOzs7R0FHRztBQUNILGtEQUFzQjtBQUN0QixvQ0FBZ0M7QUFDaEMsOERBQW9DO0FBQ3BDLCtDQUFnQztBQUNoQyxxQ0FBaUM7QUFDakMsNENBQXNFO0FBQ3RFLG1DQUE4QjtBQUU5Qjs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFxQixRQUFRO0lBRzNCO1FBd0ZBOzs7V0FHRztRQUNILHlCQUFvQixHQUFHLENBQUMsT0FBZSxFQUFXLEVBQUU7WUFDbEQsTUFBTSxLQUFLLEdBQWEsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNqRCxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO2dCQUN0QixPQUFPLEtBQUssQ0FBQTthQUNiO1lBQ0QsSUFBSTtnQkFDRixNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQTthQUM5RDtZQUFDLE9BQU8sR0FBRyxFQUFFO2dCQUNaLE9BQU8sS0FBSyxDQUFBO2FBQ2I7WUFDRCxPQUFPLElBQUksQ0FBQTtRQUNiLENBQUMsQ0FBQTtRQUVEOzs7OztXQUtHO1FBQ0gsbUJBQWMsR0FBRyxDQUFDLElBQVksRUFBVSxFQUFFLENBQ3hDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUV6Qzs7OztXQUlHO1FBQ0gsbUJBQWMsR0FBRyxDQUFDLEdBQVcsRUFBVSxFQUFFO1lBQ3ZDLE1BQU0sSUFBSSxHQUFXLGVBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUNqRCxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFDakMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDdEMsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDLENBQUE7UUFFRDs7Ozs7OztXQU9HO1FBQ0gsYUFBUSxHQUFHLENBQ1QsSUFBWSxFQUNaLFFBQWdCLENBQUMsRUFDakIsTUFBYyxTQUFTLEVBQ2YsRUFBRTtZQUNWLElBQUksR0FBRyxLQUFLLFNBQVMsRUFBRTtnQkFDckIsR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUE7YUFDbEI7WUFDRCxPQUFPLGVBQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUM3RSxDQUFDLENBQUE7UUFFRDs7Ozs7V0FLRztRQUNILGdCQUFXLEdBQUcsQ0FBQyxJQUFZLEVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRTdEOzs7OztXQUtHO1FBQ0gsZ0JBQVcsR0FBRyxDQUFDLE1BQWMsRUFBVSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFakU7Ozs7O1dBS0c7UUFDSCw0QkFBdUIsR0FBRyxDQUFDLElBQVksRUFBZSxFQUFFO1lBQ3RELE1BQU0sRUFBRSxHQUFHLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUN2QyxNQUFNLElBQUksR0FBRyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUMvQixLQUFLLElBQUksQ0FBQyxHQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRTtnQkFDNUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFBO2FBQzVCO1lBQ0QsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDLENBQUE7UUFFRDs7OztXQUlHO1FBQ0gsNEJBQXVCLEdBQUcsQ0FBQyxFQUFlLEVBQVUsRUFBRTtZQUNwRCxNQUFNLEdBQUcsR0FBRyxlQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtZQUN2QyxLQUFLLElBQUksQ0FBQyxHQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsRUFBRTtnQkFDOUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFBO2FBQ3pCO1lBQ0QsT0FBTyxHQUFHLENBQUE7UUFDWixDQUFDLENBQUE7UUFFRDs7Ozs7O1dBTUc7UUFDSCxtQkFBYyxHQUFHLENBQUMsSUFBWSxFQUFNLEVBQUU7WUFDcEMsSUFBSSxPQUFPLElBQUksS0FBSyxXQUFXLEVBQUU7Z0JBQy9CLE9BQU8sU0FBUyxDQUFBO2FBQ2pCO1lBQ0QsT0FBTyxJQUFJLGVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUMvQyxDQUFDLENBQUE7UUFDRDs7Ozs7OztXQU9HO1FBQ0gsbUJBQWMsR0FBRyxDQUFDLEVBQU0sRUFBRSxNQUFlLEVBQVUsRUFBRTtZQUNuRCxJQUFJLE9BQU8sRUFBRSxLQUFLLFdBQVcsRUFBRTtnQkFDN0IsT0FBTyxTQUFTLENBQUE7YUFDakI7WUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBO1lBQy9COztlQUVHO1lBQ0gsSUFBSSxNQUFNLEVBQUU7Z0JBQ1YsMEVBQTBFO2dCQUMxRSxNQUFNLENBQUMsR0FBRyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQTtnQkFDaEMsS0FBSyxJQUFJLENBQUMsR0FBVyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDbEMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQTtpQkFDbEI7YUFDRjtZQUNELE9BQU8sZUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUM1QixDQUFDLENBQUE7UUFFRDs7Ozs7V0FLRztRQUNILGdCQUFXLEdBQUcsQ0FBQyxJQUFZLEVBQVUsRUFBRTtZQUNyQyxNQUFNLFNBQVMsR0FBVyxlQUFNLENBQUMsSUFBSSxDQUNuQyxJQUFBLHFCQUFVLEVBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FDckQsQ0FBQTtZQUNELE9BQU8sZUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFBO1FBQ3pDLENBQUMsQ0FBQTtRQUVEOzs7OztXQUtHO1FBQ0gscUJBQWdCLEdBQUcsQ0FBQyxJQUFZLEVBQVcsRUFBRTtZQUMzQyxNQUFNLFVBQVUsR0FBVyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUE7WUFDdEQsTUFBTSxTQUFTLEdBQVcsZUFBTSxDQUFDLElBQUksQ0FDbkMsSUFBQSxxQkFBVSxFQUFDLFFBQVEsQ0FBQztpQkFDakIsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7aUJBQ3RDLE1BQU0sRUFBRTtpQkFDUixLQUFLLENBQUMsRUFBRSxDQUFDLENBQ2IsQ0FBQTtZQUNELE9BQU8sVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSyxTQUFTLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2pFLENBQUMsQ0FBQTtRQUVEOzs7Ozs7O1dBT0c7UUFDSCxlQUFVLEdBQUcsQ0FBQyxLQUFhLEVBQVUsRUFBRTtZQUNyQyxNQUFNLENBQUMsR0FBVyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFBO1lBQ3pDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUM1QixDQUFDLENBQUE7UUFFRDs7Ozs7V0FLRztRQUNILGVBQVUsR0FBRyxDQUFDLEtBQXNCLEVBQVUsRUFBRTtZQUM5QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtnQkFDN0IsS0FBSyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUE7YUFDaEM7WUFDRCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDaEMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTthQUNqRDtZQUNELE1BQU0sSUFBSSxzQkFBYSxDQUFDLCtDQUErQyxDQUFDLENBQUE7UUFDMUUsQ0FBQyxDQUFBO1FBRUQsMkJBQXNCLEdBQUcsQ0FBQyxLQUFzQixFQUFVLEVBQUU7WUFDMUQsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUU7Z0JBQzdCLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFBO2FBQ2hDO1lBQ0QsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ2hDLE9BQU8sS0FBSyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFBO2FBQ3BFO1lBQ0QsTUFBTSxJQUFJLHNCQUFhLENBQUMsK0NBQStDLENBQUMsQ0FBQTtRQUMxRSxDQUFDLENBQUE7UUFFRCxvQkFBZSxHQUFHLENBQUMsR0FBVyxFQUFFLE9BQWUsRUFBRSxLQUFhLEVBQVUsRUFBRSxDQUN4RSxHQUFHLE9BQU8sSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFBO1FBRXpFLG9CQUFlLEdBQUcsQ0FBQyxPQUFlLEVBQUUsR0FBWSxFQUFVLEVBQUU7WUFDMUQsSUFBSSxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUU7Z0JBQ3BDLG9CQUFvQjtnQkFDcEIsSUFBSSxjQUFLLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFO29CQUM1QixPQUFPLGVBQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQTtpQkFDaEQ7cUJBQU07b0JBQ0wsTUFBTSxJQUFJLGlCQUFRLENBQUMseUJBQXlCLENBQUMsQ0FBQTtpQkFDOUM7YUFDRjtZQUNELG1CQUFtQjtZQUNuQixNQUFNLEtBQUssR0FBYSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBRWpELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ3BCLE1BQU0sSUFBSSxvQkFBVyxDQUFDLHdDQUF3QyxDQUFDLENBQUE7YUFDaEU7WUFFRCxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUN2QixNQUFNLElBQUksb0JBQVcsQ0FBQyxpREFBaUQsQ0FBQyxDQUFBO2FBQ3pFO1lBRUQsTUFBTSxLQUFLLEdBQVcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUMvQyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUU7Z0JBQ2IsTUFBTSxJQUFJLG9CQUFXLENBQUMsa0RBQWtELENBQUMsQ0FBQTthQUMxRTtZQUVELE1BQU0saUJBQWlCLEdBQVcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDMUQsSUFBSSxpQkFBaUIsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUNoQyxNQUFNLElBQUksb0JBQVcsQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFBO2FBQ3BFO1lBRUQsSUFDRSxpQkFBaUIsS0FBSyxNQUFNO2dCQUM1QixpQkFBaUIsS0FBSyxNQUFNO2dCQUM1QixpQkFBaUIsSUFBSSxPQUFPO2dCQUM1QixpQkFBaUIsSUFBSSxRQUFRO2dCQUM3QixpQkFBaUIsSUFBSSxHQUFHLEVBQ3hCO2dCQUNBLE1BQU0sSUFBSSxvQkFBVyxDQUFDLHFCQUFxQixDQUFDLENBQUE7YUFDN0M7WUFFRCxPQUFPLGVBQU0sQ0FBQyxJQUFJLENBQ2hCLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUM5RCxDQUFBO1FBQ0gsQ0FBQyxDQUFBO1FBRUQ7Ozs7Ozs7Ozs7O1dBV0c7UUFDSCxpQkFBWSxHQUFHLENBQ2IsSUFBWSxFQUNaLFlBQW9CLEVBQ3BCLFFBQWdCLFNBQVMsRUFDekIsVUFBa0IsRUFBRSxFQUNaLEVBQUU7WUFDVixNQUFNLEdBQUcsR0FBYSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFBO1lBQ3JDLElBQ0UsR0FBRyxDQUFDLE1BQU0sS0FBSyxDQUFDO2dCQUNoQixDQUFDLENBQUMsS0FBSyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssWUFBWSxDQUFDLENBQUMsRUFDMUU7Z0JBQ0EsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDM0MsSUFBSSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFO29CQUN4RCxPQUFPLFFBQVEsQ0FBQTtpQkFDaEI7YUFDRjtZQUNELE9BQU8sU0FBUyxDQUFBO1FBQ2xCLENBQUMsQ0FBQTtRQXJYQyxJQUFJLENBQUMsR0FBRyxHQUFHLGVBQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQTtJQUNqQyxDQUFDO0lBSUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsV0FBVztRQUNoQixJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRTtZQUN0QixRQUFRLENBQUMsUUFBUSxHQUFHLElBQUksUUFBUSxFQUFFLENBQUE7U0FDbkM7UUFDRCxPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUE7SUFDMUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILFFBQVEsQ0FBQyxHQUFXO1FBQ2xCLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ25DLE9BQU8sS0FBSyxDQUFBO1NBQ2I7UUFDRCxJQUFJO1lBQ0YsSUFBSSxHQUFHLEdBQVcsZUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUE7WUFDNUMsT0FBTyxHQUFHLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEdBQUcsQ0FBQTtTQUN0QztRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osT0FBTyxLQUFLLENBQUE7U0FDYjtJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsSUFBWTtRQUNqQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDNUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILFFBQVEsQ0FBQyxNQUFjO1FBQ3JCLElBQUksTUFBTSxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ3pDLE9BQU8sS0FBSyxDQUFBO1NBQ2I7UUFDRCxJQUFJO1lBQ0YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLE1BQU0sQ0FBQTtTQUMzRDtRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osT0FBTyxLQUFLLENBQUE7U0FDYjtJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxLQUFLLENBQUMsR0FBVztRQUNmLElBQUksR0FBRyxLQUFLLEVBQUUsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQ25DLE9BQU8sS0FBSyxDQUFBO1NBQ2I7UUFDRCxJQUNFLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUM3RCxHQUFHLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxFQUMxQjtZQUNBLE9BQU8sSUFBSSxDQUFBO1NBQ1o7YUFBTTtZQUNMLE9BQU8sS0FBSyxDQUFBO1NBQ2I7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsU0FBUyxDQUFDLEdBQVc7UUFDbkIsSUFBSSxHQUFHLEtBQUssRUFBRSxJQUFJLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDbkMsT0FBTyxLQUFLLENBQUE7U0FDYjtRQUNELElBQUk7WUFDRixPQUFPLElBQUksZUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLEtBQUssR0FBRyxDQUFDLElBQUksRUFBRSxDQUFBO1NBQ25EO1FBQUMsT0FBTyxHQUFHLEVBQUU7WUFDWixPQUFPLEtBQUssQ0FBQTtTQUNiO0lBQ0gsQ0FBQztDQWlTRjtBQTFYRCwyQkEwWEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICogQG1vZHVsZSBVdGlscy1CaW5Ub29sc1xuICovXG5pbXBvcnQgQk4gZnJvbSBcImJuLmpzXCJcbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gXCJidWZmZXIvXCJcbmltcG9ydCBjcmVhdGVIYXNoIGZyb20gXCJjcmVhdGUtaGFzaFwiXG5pbXBvcnQgKiBhcyBiZWNoMzIgZnJvbSBcImJlY2gzMlwiXG5pbXBvcnQgeyBCYXNlNTggfSBmcm9tIFwiLi9iYXNlNThcIlxuaW1wb3J0IHsgQmVjaDMyRXJyb3IsIENoZWNrc3VtRXJyb3IsIEhleEVycm9yIH0gZnJvbSBcIi4uL3V0aWxzL2Vycm9yc1wiXG5pbXBvcnQgeyB1dGlscyB9IGZyb20gXCJldGhlcnNcIlxuXG4vKipcbiAqIEEgY2xhc3MgY29udGFpbmluZyB0b29scyB1c2VmdWwgaW4gaW50ZXJhY3Rpbmcgd2l0aCBiaW5hcnkgZGF0YSBjcm9zcy1wbGF0Zm9ybSB1c2luZ1xuICogbm9kZWpzICYgamF2YXNjcmlwdC5cbiAqXG4gKiBUaGlzIGNsYXNzIHNob3VsZCBuZXZlciBiZSBpbnN0YW50aWF0ZWQgZGlyZWN0bHkuIEluc3RlYWQsXG4gKiBpbnZva2UgdGhlIFwiQmluVG9vbHMuZ2V0SW5zdGFuY2UoKVwiIHN0YXRpYyAqIGZ1bmN0aW9uIHRvIGdyYWIgdGhlIHNpbmdsZXRvblxuICogaW5zdGFuY2Ugb2YgdGhlIHRvb2xzLlxuICpcbiAqIEV2ZXJ5dGhpbmcgaW4gdGhpcyBsaWJyYXJ5IHVzZXNcbiAqIHRoZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8ZmVyb3NzJ3MgQnVmZmVyIGNsYXNzfS5cbiAqXG4gKiBgYGBqc1xuICogY29uc3QgYmludG9vbHM6IEJpblRvb2xzID0gQmluVG9vbHMuZ2V0SW5zdGFuY2UoKTtcbiAqIGNvbnN0IGI1OHN0cjogID0gYmludG9vbHMuYnVmZmVyVG9CNTgoQnVmZmVyLmZyb20oXCJXdWJhbHViYWR1YmR1YiFcIikpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJpblRvb2xzIHtcbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IEJpblRvb2xzXG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmI1OCA9IEJhc2U1OC5nZXRJbnN0YW5jZSgpXG4gIH1cblxuICBwcml2YXRlIGI1ODogQmFzZTU4XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgQmluVG9vbHMgc2luZ2xldG9uLlxuICAgKi9cbiAgc3RhdGljIGdldEluc3RhbmNlKCk6IEJpblRvb2xzIHtcbiAgICBpZiAoIUJpblRvb2xzLmluc3RhbmNlKSB7XG4gICAgICBCaW5Ub29scy5pbnN0YW5jZSA9IG5ldyBCaW5Ub29scygpXG4gICAgfVxuICAgIHJldHVybiBCaW5Ub29scy5pbnN0YW5jZVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBiYXNlNjQsIG90aGVyd2lzZSBmYWxzZVxuICAgKiBAcGFyYW0gc3RyIHRoZSBzdHJpbmcgdG8gdmVyaWZ5IGlzIEJhc2U2NFxuICAgKi9cbiAgaXNCYXNlNjQoc3RyOiBzdHJpbmcpIHtcbiAgICBpZiAoc3RyID09PSBcIlwiIHx8IHN0ci50cmltKCkgPT09IFwiXCIpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgICB0cnkge1xuICAgICAgbGV0IGI2NDogQnVmZmVyID0gQnVmZmVyLmZyb20oc3RyLCBcImJhc2U2NFwiKVxuICAgICAgcmV0dXJuIGI2NC50b1N0cmluZyhcImJhc2U2NFwiKSA9PT0gc3RyXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIGNiNTgsIG90aGVyd2lzZSBmYWxzZVxuICAgKiBAcGFyYW0gY2I1OCB0aGUgc3RyaW5nIHRvIHZlcmlmeSBpcyBjYjU4XG4gICAqL1xuICBpc0NCNTgoY2I1ODogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXNCYXNlNTgoY2I1OClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgYmFzZTU4LCBvdGhlcndpc2UgZmFsc2VcbiAgICogQHBhcmFtIGJhc2U1OCB0aGUgc3RyaW5nIHRvIHZlcmlmeSBpcyBiYXNlNThcbiAgICovXG4gIGlzQmFzZTU4KGJhc2U1ODogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgaWYgKGJhc2U1OCA9PT0gXCJcIiB8fCBiYXNlNTgudHJpbSgpID09PSBcIlwiKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiB0aGlzLmI1OC5lbmNvZGUodGhpcy5iNTguZGVjb2RlKGJhc2U1OCkpID09PSBiYXNlNThcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgaGV4aWRlY2ltYWwsIG90aGVyd2lzZSBmYWxzZVxuICAgKiBAcGFyYW0gaGV4IHRoZSBzdHJpbmcgdG8gdmVyaWZ5IGlzIGhleGlkZWNpbWFsXG4gICAqL1xuICBpc0hleChoZXg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmIChoZXggPT09IFwiXCIgfHwgaGV4LnRyaW0oKSA9PT0gXCJcIikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIGlmIChcbiAgICAgIChoZXguc3RhcnRzV2l0aChcIjB4XCIpICYmIGhleC5zbGljZSgyKS5tYXRjaCgvXlswLTlBLUZhLWZdL2cpKSB8fFxuICAgICAgaGV4Lm1hdGNoKC9eWzAtOUEtRmEtZl0vZylcbiAgICApIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgZGVjaW1hbCwgb3RoZXJ3aXNlIGZhbHNlXG4gICAqIEBwYXJhbSBzdHIgdGhlIHN0cmluZyB0byB2ZXJpZnkgaXMgaGV4aWRlY2ltYWxcbiAgICovXG4gIGlzRGVjaW1hbChzdHI6IHN0cmluZykge1xuICAgIGlmIChzdHIgPT09IFwiXCIgfHwgc3RyLnRyaW0oKSA9PT0gXCJcIikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gbmV3IEJOKHN0ciwgMTApLnRvU3RyaW5nKDEwKSA9PT0gc3RyLnRyaW0oKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiBtZWV0cyByZXF1aXJlbWVudHMgdG8gcGFyc2UgYXMgYW4gYWRkcmVzcyBhcyBCZWNoMzIgb24gWC1DaGFpbiBvciBQLUNoYWluLCBvdGhlcndpc2UgZmFsc2VcbiAgICogQHBhcmFtIGFkZHJlc3MgdGhlIHN0cmluZyB0byB2ZXJpZnkgaXMgYWRkcmVzc1xuICAgKi9cbiAgaXNQcmltYXJ5QmVjaEFkZHJlc3MgPSAoYWRkcmVzczogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gICAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gYWRkcmVzcy50cmltKCkuc3BsaXQoXCItXCIpXG4gICAgaWYgKHBhcnRzLmxlbmd0aCAhPT0gMikge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBiZWNoMzIuYmVjaDMyLmZyb21Xb3JkcyhiZWNoMzIuYmVjaDMyLmRlY29kZShwYXJ0c1sxXSkud29yZHMpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG4gICAgcmV0dXJuIHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9kdWNlcyBhIHN0cmluZyBmcm9tIGEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn1cbiAgICogcmVwcmVzZW50aW5nIGEgc3RyaW5nLiBPTkxZIFVTRUQgSU4gVFJBTlNBQ1RJT04gRk9STUFUVElORywgQVNTVU1FRCBMRU5HVEggSVMgUFJFUEVOREVELlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZiBUaGUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gdG8gY29udmVydCB0byBhIHN0cmluZ1xuICAgKi9cbiAgYnVmZmVyVG9TdHJpbmcgPSAoYnVmZjogQnVmZmVyKTogc3RyaW5nID0+XG4gICAgdGhpcy5jb3B5RnJvbShidWZmLCAyKS50b1N0cmluZyhcInV0ZjhcIilcblxuICAvKipcbiAgICogUHJvZHVjZXMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBmcm9tIGEgc3RyaW5nLiBPTkxZIFVTRUQgSU4gVFJBTlNBQ1RJT04gRk9STUFUVElORywgTEVOR1RIIElTIFBSRVBFTkRFRC5cbiAgICpcbiAgICogQHBhcmFtIHN0ciBUaGUgc3RyaW5nIHRvIGNvbnZlcnQgdG8gYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfVxuICAgKi9cbiAgc3RyaW5nVG9CdWZmZXIgPSAoc3RyOiBzdHJpbmcpOiBCdWZmZXIgPT4ge1xuICAgIGNvbnN0IGJ1ZmY6IEJ1ZmZlciA9IEJ1ZmZlci5hbGxvYygyICsgc3RyLmxlbmd0aClcbiAgICBidWZmLndyaXRlVUludDE2QkUoc3RyLmxlbmd0aCwgMClcbiAgICBidWZmLndyaXRlKHN0ciwgMiwgc3RyLmxlbmd0aCwgXCJ1dGY4XCIpXG4gICAgcmV0dXJuIGJ1ZmZcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlcyBhIGNvcHkgKG5vIHJlZmVyZW5jZSkgb2YgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfVxuICAgKiBvdmVyIHByb3ZpZGVkIGluZGVjaWVzLlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZiBUaGUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gdG8gY29weVxuICAgKiBAcGFyYW0gc3RhcnQgVGhlIGluZGV4IHRvIHN0YXJ0IHRoZSBjb3B5XG4gICAqIEBwYXJhbSBlbmQgVGhlIGluZGV4IHRvIGVuZCB0aGUgY29weVxuICAgKi9cbiAgY29weUZyb20gPSAoXG4gICAgYnVmZjogQnVmZmVyLFxuICAgIHN0YXJ0OiBudW1iZXIgPSAwLFxuICAgIGVuZDogbnVtYmVyID0gdW5kZWZpbmVkXG4gICk6IEJ1ZmZlciA9PiB7XG4gICAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBlbmQgPSBidWZmLmxlbmd0aFxuICAgIH1cbiAgICByZXR1cm4gQnVmZmVyLmZyb20oVWludDhBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChidWZmLnNsaWNlKHN0YXJ0LCBlbmQpKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBUYWtlcyBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IGFuZCByZXR1cm5zIGEgYmFzZS01OCBzdHJpbmcgb2ZcbiAgICogdGhlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9LlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZiBUaGUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gdG8gY29udmVydCB0byBiYXNlLTU4XG4gICAqL1xuICBidWZmZXJUb0I1OCA9IChidWZmOiBCdWZmZXIpOiBzdHJpbmcgPT4gdGhpcy5iNTguZW5jb2RlKGJ1ZmYpXG5cbiAgLyoqXG4gICAqIFRha2VzIGEgYmFzZS01OCBzdHJpbmcgYW5kIHJldHVybnMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfS5cbiAgICpcbiAgICogQHBhcmFtIGI1OHN0ciBUaGUgYmFzZS01OCBzdHJpbmcgdG8gY29udmVydFxuICAgKiB0byBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9XG4gICAqL1xuICBiNThUb0J1ZmZlciA9IChiNThzdHI6IHN0cmluZyk6IEJ1ZmZlciA9PiB0aGlzLmI1OC5kZWNvZGUoYjU4c3RyKVxuXG4gIC8qKlxuICAgKiBUYWtlcyBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IGFuZCByZXR1cm5zIGFuIEFycmF5QnVmZmVyLlxuICAgKlxuICAgKiBAcGFyYW0gYnVmZiBUaGUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gdG9cbiAgICogY29udmVydCB0byBhbiBBcnJheUJ1ZmZlclxuICAgKi9cbiAgZnJvbUJ1ZmZlclRvQXJyYXlCdWZmZXIgPSAoYnVmZjogQnVmZmVyKTogQXJyYXlCdWZmZXIgPT4ge1xuICAgIGNvbnN0IGFiID0gbmV3IEFycmF5QnVmZmVyKGJ1ZmYubGVuZ3RoKVxuICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDhBcnJheShhYilcbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgYnVmZi5sZW5ndGg7ICsraSkge1xuICAgICAgdmlld1tgJHtpfWBdID0gYnVmZltgJHtpfWBdXG4gICAgfVxuICAgIHJldHVybiB2aWV3XG4gIH1cblxuICAvKipcbiAgICogVGFrZXMgYW4gQXJyYXlCdWZmZXIgYW5kIGNvbnZlcnRzIGl0IHRvIGEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0uXG4gICAqXG4gICAqIEBwYXJhbSBhYiBUaGUgQXJyYXlCdWZmZXIgdG8gY29udmVydCB0byBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9XG4gICAqL1xuICBmcm9tQXJyYXlCdWZmZXJUb0J1ZmZlciA9IChhYjogQXJyYXlCdWZmZXIpOiBCdWZmZXIgPT4ge1xuICAgIGNvbnN0IGJ1ZiA9IEJ1ZmZlci5hbGxvYyhhYi5ieXRlTGVuZ3RoKVxuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCBhYi5ieXRlTGVuZ3RoOyArK2kpIHtcbiAgICAgIGJ1ZltgJHtpfWBdID0gYWJbYCR7aX1gXVxuICAgIH1cbiAgICByZXR1cm4gYnVmXG4gIH1cblxuICAvKipcbiAgICogVGFrZXMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBhbmQgY29udmVydHMgaXRcbiAgICogdG8gYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2luZHV0bnkvYm4uanMvfEJOfS5cbiAgICpcbiAgICogQHBhcmFtIGJ1ZmYgVGhlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IHRvIGNvbnZlcnRcbiAgICogdG8gYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2luZHV0bnkvYm4uanMvfEJOfVxuICAgKi9cbiAgZnJvbUJ1ZmZlclRvQk4gPSAoYnVmZjogQnVmZmVyKTogQk4gPT4ge1xuICAgIGlmICh0eXBlb2YgYnVmZiA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZFxuICAgIH1cbiAgICByZXR1cm4gbmV3IEJOKGJ1ZmYudG9TdHJpbmcoXCJoZXhcIiksIDE2LCBcImJlXCIpXG4gIH1cbiAgLyoqXG4gICAqIFRha2VzIGEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9pbmR1dG55L2JuLmpzL3xCTn0gYW5kIGNvbnZlcnRzIGl0XG4gICAqIHRvIGEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0uXG4gICAqXG4gICAqIEBwYXJhbSBibiBUaGUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9pbmR1dG55L2JuLmpzL3xCTn0gdG8gY29udmVydFxuICAgKiB0byBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9XG4gICAqIEBwYXJhbSBsZW5ndGggVGhlIHplcm8tcGFkZGVkIGxlbmd0aCBvZiB0aGUge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn1cbiAgICovXG4gIGZyb21CTlRvQnVmZmVyID0gKGJuOiBCTiwgbGVuZ3RoPzogbnVtYmVyKTogQnVmZmVyID0+IHtcbiAgICBpZiAodHlwZW9mIGJuID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkXG4gICAgfVxuICAgIGNvbnN0IG5ld2FyciA9IGJuLnRvQXJyYXkoXCJiZVwiKVxuICAgIC8qKlxuICAgICAqIENLQzogU3RpbGwgdW5zdXJlIHdoeSBibi50b0FycmF5IHdpdGggYSBcImJlXCIgYW5kIGEgbGVuZ3RoIGRvIG5vdCB3b3JrIHJpZ2h0LiBCdWc/XG4gICAgICovXG4gICAgaWYgKGxlbmd0aCkge1xuICAgICAgLy8gYm4gdG9BcnJheSB3aXRoIHRoZSBsZW5ndGggcGFyYW1ldGVyIGRvZXNuJ3Qgd29yayBjb3JyZWN0bHksIG5lZWQgdGhpcy5cbiAgICAgIGNvbnN0IHggPSBsZW5ndGggLSBuZXdhcnIubGVuZ3RoXG4gICAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgeDsgaSsrKSB7XG4gICAgICAgIG5ld2Fyci51bnNoaWZ0KDApXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBCdWZmZXIuZnJvbShuZXdhcnIpXG4gIH1cblxuICAvKipcbiAgICogVGFrZXMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBhbmQgYWRkcyBhIGNoZWNrc3VtLCByZXR1cm5pbmdcbiAgICogYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSB3aXRoIHRoZSA0LWJ5dGUgY2hlY2tzdW0gYXBwZW5kZWQuXG4gICAqXG4gICAqIEBwYXJhbSBidWZmIFRoZSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSB0byBhcHBlbmQgYSBjaGVja3N1bVxuICAgKi9cbiAgYWRkQ2hlY2tzdW0gPSAoYnVmZjogQnVmZmVyKTogQnVmZmVyID0+IHtcbiAgICBjb25zdCBoYXNoc2xpY2U6IEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFxuICAgICAgY3JlYXRlSGFzaChcInNoYTI1NlwiKS51cGRhdGUoYnVmZikuZGlnZXN0KCkuc2xpY2UoMjgpXG4gICAgKVxuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KFtidWZmLCBoYXNoc2xpY2VdKVxuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gd2l0aCBhbiBhcHBlbmRlZCA0LWJ5dGUgY2hlY2tzdW1cbiAgICogYW5kIHJldHVybnMgdHJ1ZSBpZiB0aGUgY2hlY2tzdW0gaXMgdmFsaWQsIG90aGVyd2lzZSBmYWxzZS5cbiAgICpcbiAgICogQHBhcmFtIGIgVGhlIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9IHRvIHZhbGlkYXRlIHRoZSBjaGVja3N1bVxuICAgKi9cbiAgdmFsaWRhdGVDaGVja3N1bSA9IChidWZmOiBCdWZmZXIpOiBib29sZWFuID0+IHtcbiAgICBjb25zdCBjaGVja3NsaWNlOiBCdWZmZXIgPSBidWZmLnNsaWNlKGJ1ZmYubGVuZ3RoIC0gNClcbiAgICBjb25zdCBoYXNoc2xpY2U6IEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKFxuICAgICAgY3JlYXRlSGFzaChcInNoYTI1NlwiKVxuICAgICAgICAudXBkYXRlKGJ1ZmYuc2xpY2UoMCwgYnVmZi5sZW5ndGggLSA0KSlcbiAgICAgICAgLmRpZ2VzdCgpXG4gICAgICAgIC5zbGljZSgyOClcbiAgICApXG4gICAgcmV0dXJuIGNoZWNrc2xpY2UudG9TdHJpbmcoXCJoZXhcIikgPT09IGhhc2hzbGljZS50b1N0cmluZyhcImhleFwiKVxuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gYW5kIHJldHVybnMgYSBiYXNlLTU4IHN0cmluZyB3aXRoXG4gICAqIGNoZWNrc3VtIGFzIHBlciB0aGUgY2I1OCBzdGFuZGFyZC5cbiAgICpcbiAgICogQHBhcmFtIGJ5dGVzIEEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gdG8gc2VyaWFsaXplXG4gICAqXG4gICAqIEByZXR1cm5zIEEgc2VyaWFsaXplZCBiYXNlLTU4IHN0cmluZyBvZiB0aGUgQnVmZmVyLlxuICAgKi9cbiAgY2I1OEVuY29kZSA9IChieXRlczogQnVmZmVyKTogc3RyaW5nID0+IHtcbiAgICBjb25zdCB4OiBCdWZmZXIgPSB0aGlzLmFkZENoZWNrc3VtKGJ5dGVzKVxuICAgIHJldHVybiB0aGlzLmJ1ZmZlclRvQjU4KHgpXG4gIH1cblxuICAvKipcbiAgICogVGFrZXMgYSBjYjU4IHNlcmlhbGl6ZWQge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gb3IgYmFzZS01OCBzdHJpbmdcbiAgICogYW5kIHJldHVybnMgYSB7QGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXJ8QnVmZmVyfSBvZiB0aGUgb3JpZ2luYWwgZGF0YS4gVGhyb3dzIG9uIGVycm9yLlxuICAgKlxuICAgKiBAcGFyYW0gYnl0ZXMgQSBjYjU4IHNlcmlhbGl6ZWQge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gb3IgYmFzZS01OCBzdHJpbmdcbiAgICovXG4gIGNiNThEZWNvZGUgPSAoYnl0ZXM6IEJ1ZmZlciB8IHN0cmluZyk6IEJ1ZmZlciA9PiB7XG4gICAgaWYgKHR5cGVvZiBieXRlcyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgYnl0ZXMgPSB0aGlzLmI1OFRvQnVmZmVyKGJ5dGVzKVxuICAgIH1cbiAgICBpZiAodGhpcy52YWxpZGF0ZUNoZWNrc3VtKGJ5dGVzKSkge1xuICAgICAgcmV0dXJuIHRoaXMuY29weUZyb20oYnl0ZXMsIDAsIGJ5dGVzLmxlbmd0aCAtIDQpXG4gICAgfVxuICAgIHRocm93IG5ldyBDaGVja3N1bUVycm9yKFwiRXJyb3IgLSBCaW5Ub29scy5jYjU4RGVjb2RlOiBpbnZhbGlkIGNoZWNrc3VtXCIpXG4gIH1cblxuICBjYjU4RGVjb2RlV2l0aENoZWNrc3VtID0gKGJ5dGVzOiBCdWZmZXIgfCBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICAgIGlmICh0eXBlb2YgYnl0ZXMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGJ5dGVzID0gdGhpcy5iNThUb0J1ZmZlcihieXRlcylcbiAgICB9XG4gICAgaWYgKHRoaXMudmFsaWRhdGVDaGVja3N1bShieXRlcykpIHtcbiAgICAgIHJldHVybiBgMHgke3RoaXMuY29weUZyb20oYnl0ZXMsIDAsIGJ5dGVzLmxlbmd0aCkudG9TdHJpbmcoXCJoZXhcIil9YFxuICAgIH1cbiAgICB0aHJvdyBuZXcgQ2hlY2tzdW1FcnJvcihcIkVycm9yIC0gQmluVG9vbHMuY2I1OERlY29kZTogaW52YWxpZCBjaGVja3N1bVwiKVxuICB9XG5cbiAgYWRkcmVzc1RvU3RyaW5nID0gKGhycDogc3RyaW5nLCBjaGFpbmlkOiBzdHJpbmcsIGJ5dGVzOiBCdWZmZXIpOiBzdHJpbmcgPT5cbiAgICBgJHtjaGFpbmlkfS0ke2JlY2gzMi5iZWNoMzIuZW5jb2RlKGhycCwgYmVjaDMyLmJlY2gzMi50b1dvcmRzKGJ5dGVzKSl9YFxuXG4gIHN0cmluZ1RvQWRkcmVzcyA9IChhZGRyZXNzOiBzdHJpbmcsIGhycD86IHN0cmluZyk6IEJ1ZmZlciA9PiB7XG4gICAgaWYgKGFkZHJlc3Muc3Vic3RyaW5nKDAsIDIpID09PSBcIjB4XCIpIHtcbiAgICAgIC8vIEVUSC1zdHlsZSBhZGRyZXNzXG4gICAgICBpZiAodXRpbHMuaXNBZGRyZXNzKGFkZHJlc3MpKSB7XG4gICAgICAgIHJldHVybiBCdWZmZXIuZnJvbShhZGRyZXNzLnN1YnN0cmluZygyKSwgXCJoZXhcIilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBIZXhFcnJvcihcIkVycm9yIC0gSW52YWxpZCBhZGRyZXNzXCIpXG4gICAgICB9XG4gICAgfVxuICAgIC8vIEJlY2gzMiBhZGRyZXNzZXNcbiAgICBjb25zdCBwYXJ0czogc3RyaW5nW10gPSBhZGRyZXNzLnRyaW0oKS5zcGxpdChcIi1cIilcblxuICAgIGlmIChwYXJ0cy5sZW5ndGggPCAyKSB7XG4gICAgICB0aHJvdyBuZXcgQmVjaDMyRXJyb3IoXCJFcnJvciAtIFZhbGlkIGFkZHJlc3Mgc2hvdWxkIGluY2x1ZGUgLVwiKVxuICAgIH1cblxuICAgIGlmIChwYXJ0c1swXS5sZW5ndGggPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgQmVjaDMyRXJyb3IoXCJFcnJvciAtIFZhbGlkIGFkZHJlc3MgbXVzdCBoYXZlIHByZWZpeCBiZWZvcmUgLVwiKVxuICAgIH1cblxuICAgIGNvbnN0IHNwbGl0OiBudW1iZXIgPSBwYXJ0c1sxXS5sYXN0SW5kZXhPZihcIjFcIilcbiAgICBpZiAoc3BsaXQgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgQmVjaDMyRXJyb3IoXCJFcnJvciAtIFZhbGlkIGFkZHJlc3MgbXVzdCBpbmNsdWRlIHNlcGFyYXRvciAoMSlcIilcbiAgICB9XG5cbiAgICBjb25zdCBodW1hblJlYWRhYmxlUGFydDogc3RyaW5nID0gcGFydHNbMV0uc2xpY2UoMCwgc3BsaXQpXG4gICAgaWYgKGh1bWFuUmVhZGFibGVQYXJ0Lmxlbmd0aCA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBCZWNoMzJFcnJvcihcIkVycm9yIC0gSFJQIHNob3VsZCBiZSBhdCBsZWFzdCAxIGNoYXJhY3RlclwiKVxuICAgIH1cblxuICAgIGlmIChcbiAgICAgIGh1bWFuUmVhZGFibGVQYXJ0ICE9PSBcImF2YXhcIiAmJlxuICAgICAgaHVtYW5SZWFkYWJsZVBhcnQgIT09IFwiZnVqaVwiICYmXG4gICAgICBodW1hblJlYWRhYmxlUGFydCAhPSBcImxvY2FsXCIgJiZcbiAgICAgIGh1bWFuUmVhZGFibGVQYXJ0ICE9IFwiY3VzdG9tXCIgJiZcbiAgICAgIGh1bWFuUmVhZGFibGVQYXJ0ICE9IGhycFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEJlY2gzMkVycm9yKFwiRXJyb3IgLSBJbnZhbGlkIEhSUFwiKVxuICAgIH1cblxuICAgIHJldHVybiBCdWZmZXIuZnJvbShcbiAgICAgIGJlY2gzMi5iZWNoMzIuZnJvbVdvcmRzKGJlY2gzMi5iZWNoMzIuZGVjb2RlKHBhcnRzWzFdKS53b3JkcylcbiAgICApXG4gIH1cblxuICAvKipcbiAgICogVGFrZXMgYW4gYWRkcmVzcyBhbmQgcmV0dXJucyBpdHMge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn1cbiAgICogcmVwcmVzZW50YXRpb24gaWYgdmFsaWQuIEEgbW9yZSBzdHJpY3QgdmVyc2lvbiBvZiBzdHJpbmdUb0FkZHJlc3MuXG4gICAqXG4gICAqIEBwYXJhbSBhZGRyIEEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBhZGRyZXNzXG4gICAqIEBwYXJhbSBibG9ja2NoYWluSUQgQSBjYjU4IGVuY29kZWQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBibG9ja2NoYWluSURcbiAgICogQHBhcmFtIGFsaWFzIEEgY2hhaW5JRCBhbGlhcywgaWYgYW55LCB0aGF0IHRoZSBhZGRyZXNzIGNhbiBhbHNvIHBhcnNlIGZyb20uXG4gICAqIEBwYXJhbSBhZGRybGVuIFZNcyBjYW4gdXNlIGFueSBhZGRyZXNzaW5nIHNjaGVtZSB0aGF0IHRoZXkgbGlrZSwgc28gdGhpcyBpcyB0aGUgYXBwcm9wcmlhdGUgbnVtYmVyIG9mIGFkZHJlc3MgYnl0ZXMuIERlZmF1bHQgMjAuXG4gICAqXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gZm9yIHRoZSBhZGRyZXNzIGlmIHZhbGlkLFxuICAgKiB1bmRlZmluZWQgaWYgbm90IHZhbGlkLlxuICAgKi9cbiAgcGFyc2VBZGRyZXNzID0gKFxuICAgIGFkZHI6IHN0cmluZyxcbiAgICBibG9ja2NoYWluSUQ6IHN0cmluZyxcbiAgICBhbGlhczogc3RyaW5nID0gdW5kZWZpbmVkLFxuICAgIGFkZHJsZW46IG51bWJlciA9IDIwXG4gICk6IEJ1ZmZlciA9PiB7XG4gICAgY29uc3QgYWJjOiBzdHJpbmdbXSA9IGFkZHIuc3BsaXQoXCItXCIpXG4gICAgaWYgKFxuICAgICAgYWJjLmxlbmd0aCA9PT0gMiAmJlxuICAgICAgKChhbGlhcyAmJiBhYmNbMF0gPT09IGFsaWFzKSB8fCAoYmxvY2tjaGFpbklEICYmIGFiY1swXSA9PT0gYmxvY2tjaGFpbklEKSlcbiAgICApIHtcbiAgICAgIGNvbnN0IGFkZHJidWZmID0gdGhpcy5zdHJpbmdUb0FkZHJlc3MoYWRkcilcbiAgICAgIGlmICgoYWRkcmxlbiAmJiBhZGRyYnVmZi5sZW5ndGggPT09IGFkZHJsZW4pIHx8ICFhZGRybGVuKSB7XG4gICAgICAgIHJldHVybiBhZGRyYnVmZlxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbn1cbiJdfQ==

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


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