403Webshell
Server IP : 85.158.181.41  /  Your IP : 216.73.217.12
Web Server : Apache
System : Linux cloud9-vm129 6.1.178+1-ph #ph SMP PREEMPT_DYNAMIC Wed Jul 29 09:00:54 UTC 2026 x86_64
User : moncbefd ( 1024)
PHP Version : 7.3.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/moncbefd/www.moneta.at/themes/Honeygrid/javascripts/system/widgets/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/moncbefd/www.moneta.at/themes/Honeygrid/javascripts/system/widgets/product_cart_handler.js
'use strict';

var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };

/* --------------------------------------------------------------
 product_cart_handler.js 2019-05-23
 Gambio GmbH
 http://www.gambio.de
 Copyright (c) 2018 Gambio GmbH
 Released under the GNU General Public License (Version 2)
 [http://www.gnu.org/licenses/gpl-2.0.html]
 --------------------------------------------------------------
 */

/**
 * Component that includes the functionality for
 * the add-to-cart, refresh and delete buttons
 * on the wishlist and cart
 */
gambio.widgets.module('product_cart_handler', ['form', 'xhr', gambio.source + '/libs/events', gambio.source + '/libs/modal.ext-magnific', gambio.source + '/libs/modal'], function (data) {

    'use strict';

    // ########## VARIABLE INITIALIZATION ##########

    var $this = $(this),
        $window = $(window),
        $body = $('body'),
        $form = null,
        $updateTarget = null,
        $deleteField = null,
        $cartEmpty = null,
        $cartNotEmpty = null,
        deleteFieldName = null,
        action = null,
        busy = null,
        updateList = false,
        transition = null,
        active = {},
        isChanged = false,
        defaults = {
        // Use an AJAX to update the form
        ajax: true,
        // Show an confirm-layer on deletion of an item
        confirmDelete: false,
        // Selector of the hidden field for the deletion entries
        deleteInput: '#field_cart_delete_products_id',
        // Trigger an event to that item on an successfull ajax (e.g. the shipping costs element)
        updateTarget: '.shipping-calculation',
        // The URL for the quantity check of the item
        checkUrl: 'shop.php?do=CheckQuantity',
        // If an URL is set, this one will be requests for status updates on tab focus
        updateUrl: 'shop.php?do=Cart',

        changeClass: 'has-changed', // Class that gets added if an input has changed
        errorClass: 'error', // Class that gets added to the row if an error has occured
        cartEmpty: '.cart-empty', // Show this selection if the cart is empty or hide it else
        cartNotEmpty: '.cart-not-empty', // Show this selection if the cart is not empty or hide it else
        classLoading: 'loading', // The class that gets added to an currently updating row
        actions: { // The actions that getting appended to the submit url on the different type of updates
            add: 'wishlist_to_cart',
            delete: 'update_product',
            refresh: 'update_wishlist'
        },
        ajaxActions: { // URLs for the ajax updates on the different actions
            add: 'shop.php?do=WishList/AddToCart',
            delete: 'shop.php?do=Cart/Delete',
            refresh: 'shop.php?do=Cart/Update'
        },
        selectorMapping: {
            buttons: '.shopping-cart-button',
            giftContent: '.gift-cart-content-wrapper',
            giftLayer: '.gift-cart-layer',
            shareContent: '.share-cart-content-wrapper',
            shareLayer: '.share-cart-layer',
            hiddenOptions: '#cart_quantity .hidden-options',
            message: '.global-error-messages',
            infoMessage: '.info-message',
            shippingInformation: '#shipping-information-layer',
            totals: '#cart_quantity .total-box',
            errorMsg: '.error-msg',
            submit: '.button-submit'
        }
    },
        options = $.extend(false, {}, defaults, data),
        module = {};

    // ########## HELPER FUNCTIONS ##########

    /**
     * Updates the form action to the type given
     * in the options.actions object
     * @param       {string}        type        The action name
     * @private
     */
    var _setAction = function _setAction(type) {
        if (options.ajax) {
            action = options.ajaxActions[type];
        } else if (options.actions && options.actions[type]) {
            action = action.replace(/(action=)[^\&]+/, '$1' + options.actions[type]);
            $form.attr('action', action);
        }
    };

    /**
     * Helper function that updates the
     * hidden data attributes with the current
     * values of the input fields
     * @param       {object}        $target     jQuery selection of the topmost container
     * @private
     */
    var _updateDataValues = function _updateDataValues($target) {
        $target.find('input[type="text"]').each(function () {
            var $self = $(this),
                value = $self.val();

            $self.data('oldValue', value);
        });
    };

    /**
     * Helper function that restores the values
     * stored by the _updateDataValues function
     * @param       {object}        dataset     The data object of all targets that needs to be reset
     * @private
     */
    var _restoreDataValues = function _restoreDataValues(dataset) {
        // Reset each changed field given
        // by the dataset target
        $.each(dataset, function () {
            var value = this;

            value.target.find('.' + options.changeClass).each(function () {
                var $self = $(this),
                    name = $self.attr('name').replace('[]', ''),
                    val = $self.data().oldValue;

                value[name][0] = val;
                $self.val(val).removeClass(options.changeClass);
            });
        });
    };

    /**
     * Helper function that generates an array of  datasets from the form. Each array item
     * contains the data of one row (inclusive the attributes data from the form head belonging
     * to the row). Additionally it adds the target-parameter to each dataset which contains
     * the selection of the row,the current dataset belongs to.
     *
     * @param {object} $row The optional row selection the data gets from. If no selection is given, the form
     * gets selected.
     * @return {Array} The array with the datasets of each row
     *
     * @private
     */
    var _generateFormdataObject = function _generateFormdataObject($row) {
        var $target = $row && $row.length ? $row : $form,
            $rows = $row && $row.length ? $row : $form.find('.order-wishlist .item:gt(0)'),
            $hiddens = $form.find('.hidden-options input[type="hidden"]'),
            dataset = jse.libs.form.getData($target),
            result = [],
            tmpResult = null;

        $.each(dataset.products_id, function (i, v) {
            tmpResult = {};
            tmpResult.target = $rows.eq(i);

            // Store the data from the current row as a json
            $.each(dataset, function (key, value) {
                if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value[i] !== undefined) {
                    // Store the value as an array to be compliant with the old API
                    tmpResult[key] = [value[i]];
                }
            });

            // Get the hidden fields for the attributes
            // belonging to this row from the form head
            $hiddens.filter('[name^="id[' + v + '"], .force').each(function () {
                var $self = $(this),
                    name = $self.attr('name');

                tmpResult[name] = $self.val();
            });

            // Push the generated json to the final result array
            result.push(tmpResult);
        });

        return result;
    };

    /**
     * Function that checks the form / the row if the combination
     * and quantity is valid. It returns an promise which gets rejected
     * if in the scope was an invalid value. In other cases it gets
     * resolved. If it is detecting changes inside the form it can
     * show an info layer to the user and / or revert the changes
     * (depending on the caller parameters)
     * @param       {boolean}       showChanges         Show an info-layer if changes would be refused
     * @param       {boolean}       revertChanges       Resets the form values with the one from the data attributes if true
     * @param       {object}        formdata            Json that contains the data to check
     * @return     {*}                                 Returns a promise
     * @private
     */
    var _checkForm = function _checkForm(showChanges, revertChanges, formdata) {

        var promises = [],
            hasChanged = false;

        // Get the complete form data if no row data is given
        formdata = formdata || _generateFormdataObject();

        // Check the formdata for changed values
        $.each(formdata, function () {
            var $changed = this.target.find('.' + options.changeClass);
            hasChanged = hasChanged || !!$changed.length;
            return !hasChanged;
        });

        return $.when.apply(undefined, promises).promise();
    };

    /**
     * Helper function that cleans up the process state
     * (Needed especially after ajax requests, to be able
     * to make further requests)
     * @param       {string}        id              The product id that needs to be reseted
     * @return     {Array.<T>}                     Returns an array without empty fields
     * @private
     */
    var _cleanupArray = function _cleanupArray(id, $row) {
        delete active['product_' + id];
        $row.removeClass('loading');
        return active;
    };

    /**
     * Helper function that does the general form update
     * after an ajax request
     * @param       {object}    $target         The jQuery selection of the target elements.
     * @param       {object}    result          The result of the ajax request.
     * @param       {string}    type            The executed action type.
     * @private
     */
    var _updateForm = function _updateForm($target, result, type) {
        // Update the rest of the page
        jse.libs.theme.helpers.fill(result.content, $body, options.selectorMapping);

        // Toggle info-messages visibility.
        $('.info-message').toggleClass('hidden', $('.info-message').text() === '');

        // Inform other widgets about the update
        $updateTarget.trigger(jse.libs.theme.events.CART_UPDATED(), []);
        $body.trigger(jse.libs.theme.events.CART_UPDATE(), type === 'add');

        // Update the hidden data attributes of that row
        _updateDataValues($target);

        if ($.isEmptyObject(result.products)) {
            // Hide the table if no products are at the list
            $cartNotEmpty.addClass('hidden');
            $cartEmpty.removeClass('hidden');
        } else {
            // Show the table if there are products at it
            $cartEmpty.addClass('hidden');
            $cartNotEmpty.removeClass('hidden');
        }

        // reinitialize widgets in updated DOM
        window.gambio.widgets.init($this);
    };

    /**
     * Helper function to update product specific messages.
     * Therefor it calls AJAX-requests (in case ajax is
     * enabled) to the server to get the updated information
     * about the table state. If ajax isn't enabled, it simply
     * submits the form.
     * @param       {object}        messages            Object with articleId => message configuration object
     * @private
     */
    var _updateArticlesMessage = function _updateArticlesMessage(messages) {

        //update all messages og the request
        $.each(messages, function (product, message) {
            var messageCfg = { 'message': message };
            //let productId = product.match(/\d+/)[0];
            // Find the related product tr
            var item = $('input[value^="' + product + '"]').closest('tr');

            jse.libs.theme.helpers.fill(messageCfg, item, options.selectorMapping);
            if (item.find('.error-msg').text() !== '') {
                item.find('.error-msg').show();
            }
        });
    };

    /**
     * Helper function that processes the list updates.
     * Therefor it calls AJAX-requests (in case ajax is
     * enabled) to the server to get the updated information
     * about the table state. If ajax isn't enabled, it simply
     * submits the form.
     * @param       {object}        $target            The jQuery selection of the row that gets updated
     * @param       {object}        dataset            The data collected from the target row in JSON format
     * @param       {article}       article            The products id of the article in that row
     * @param       {article}       type               The operation type can either be "add", "delete" or "refresh".
     * @private
     */
    var _executeAction = function _executeAction($row, $target, dataset, article, type) {
        if (options.ajax) {
            // Delete the target element because ajax requests
            // will fail with a jQuery selection in the data json
            delete dataset.target;

            $row.trigger(jse.libs.theme.events.TRANSITION(), transition);

            // Perform an ajax if the data is valid and the options for ajax is set
            jse.libs.xhr.ajax({ url: action, data: dataset }, true).done(function (result) {
                // Perform hooks
                jse.libs.hooks.execute(jse.libs.hooks.keys.shop.cart.change, {
                    $target: $target,
                    dataset: dataset,
                    article: article,
                    type: type,
                    result: result
                }, 500);

                // Update the product row
                var $markup = $(result.products['product_' + article] || '');

                // Toggle error-messages visibility.
                $markup.removeClass(options.classLoading);
                $target.replaceWith($markup);

                _updateArticlesMessage(result.content.errorMessageList);
                delete result.content.errorMessageList;

                _updateForm($target, result, type);

                var productNumber = article.match(/\d+/)[0];

                // Find all items with the same product number
                var $items = $('input[value^="' + productNumber + '"]').parent('td');

                // Apply the new markup foreach item which has the same product number.
                $items.each(function () {
                    if (!$(this).find('input[value="' + article + '"]').length) {
                        var number = $(this).find('input[id="products_id[]"]').attr('value');
                        $markup = $(result.products['product_' + number] || '');
                        $target = $(this).parent('tr');
                        $target.replaceWith($markup);
                    }
                });
            }).always(function () {
                _cleanupArray(article, $row);
            });
        } else {
            // Cleanup the active array on fail / success
            // of the following submit. This is a fallback
            // if an other component would prevent the submit
            // in some cases, so that this script can perform
            // actions again
            var deferred = $.Deferred();
            deferred.always(function () {
                _cleanupArray(article, $row);
            });

            // Submit the form
            $form.trigger('submit', deferred);
        }
    };

    // ########## EVENT HANDLER ##########

    /**
     * Adds an class to the changed input
     * field, so that it's styling shows
     * that it wasn't refreshed till now
     * @private
     */
    var _inputHandler = function _inputHandler() {
        var $self = $(this),
            value = $self.val(),
            oldValue = $self.data().oldValue,
            hasNewValue = value !== oldValue;

        if (hasNewValue) {
            isChanged = hasNewValue;
            $self.addClass(options.changeClass);
        } else {
            $self.removeClass(options.changeClass);
        }

        _updateChangeState();
    };

    /**
     * Handle the blur event
     * @private
     */
    var _blurHandler = function _blurHandler() {
        var $self = $(this),
            value = $self.val(),
            oldValue = $self.data().oldValue,
            hasNewValue = value !== oldValue;

        if (hasNewValue) {
            $self.closest('.item').find('.button-refresh').first().trigger('click');
        }
    };

    /**
     * Handler that listens on click events on the
     * buttons "refresh", "delete" & "add to cart".
     * It validates the form / row and passes the
     * the data to an submit execute funciton if valid
     * @param       {object}    e       jQuery event object
     * @private
     */
    var _clickHandler = function _clickHandler(e) {
        e.preventDefault();
        e.stopPropagation();

        var $self = $(this),
            $row = $self.closest('.item'),
            type = e.data.type,
            rowdata = _generateFormdataObject($row)[0],
            article = rowdata.products_id[0],
            $target = rowdata.target,
            title = $target.find('.product-title').text();

        // Add loading class
        $row.addClass('loading');

        // Check if there is no current process for this article
        // or in case it's no ajax call there is NO other process
        if ($.isEmptyObject(active) || options.ajax && !active['product_' + article]) {
            active['product_' + article] = true;
            _setAction(type);

            switch (type) {
                case 'delete':
                    // Update the form and the dataset with
                    // the article id to delete
                    $deleteField.val(article);
                    rowdata[deleteFieldName] = [article];

                    if (options.confirmDelete) {
                        // Open a modal layer to confirm the deletion
                        var modalTitle = jse.core.lang.translate('CART_WISHLIST_DELETE_TITLE', 'general'),
                            modalMessage = jse.core.lang.translate('CART_WISHLIST_DELETE', 'general');

                        jse.libs.theme.modal.confirm({
                            content: modalMessage,
                            title: modalTitle
                        }).done(function () {
                            var deferred = $.Deferred();

                            deferred.done(function () {
                                _executeAction($row, $target, rowdata, article, type);
                            });

                            $body.trigger(jse.libs.theme.events.WISHLIST_CART_DELETE(), [{
                                'deferred': deferred,
                                'dataset': rowdata
                            }]);
                        }).fail(function () {
                            _cleanupArray(article, $row);
                        });
                    } else {
                        var deferred = $.Deferred();

                        deferred.done(function () {
                            _executeAction($row, $target, rowdata, article, type);
                        });

                        $body.trigger(jse.libs.theme.events.WISHLIST_CART_DELETE(), [{
                            'deferred': deferred,
                            'dataset': rowdata
                        }]);
                    }
                    break;

                default:
                    // In all other cases check if the form
                    // has valid values and continue with the
                    // done callback if valid
                    _checkForm(false, false, [$.extend(true, {}, rowdata)]).done(function () {
                        // Empty the delete hidden field in case it was set before
                        $deleteField.val('');

                        var event = null;

                        if (type === 'add') {
                            event = jse.libs.theme.events.WISHLIST_TO_CART();
                        }

                        if (event) {
                            var deferred = $.Deferred();

                            deferred.done(function () {
                                _executeAction($row, $target, rowdata, article, type);
                            });

                            $body.trigger(event, [{ 'deferred': deferred, 'dataset': rowdata }]);
                        } else {
                            _executeAction($row, $target, rowdata, article, type);
                        }
                    }).fail(function () {
                        _cleanupArray(article, $row);
                    });
                    break;
            }
        }
    };

    /**
     * Prevent the submit event that was triggerd
     * by user or by script. If it was triggered
     * by the user, check if it was an "Enter"-key
     * submit from an input field. If so, execute
     * the refresh functionality for that row.
     * If the event was triggered by the script
     * (identified by the data flag "d") check the
     * whole form for errors. Only in case of valid
     * data proceed the submit
     * @param       {object}        e       jQuery event object
     * @param       {boolean}       d       A flag that identifies that the submit was triggered by this script
     * @private
     */
    var _submitHandler = function _submitHandler(e, d) {

        // Prevent the default behaviour
        // in both cases
        e.preventDefault();
        e.stopPropagation();

        if (!d && e.originalEvent) {

            // Check if an input field has triggerd the submit event
            // and call the refresh handler
            var $source = $(e.originalEvent.explicitOriginalTarget);
            if ($source.length && $source.is('input[type="text"]')) {
                $source.closest('.item').find('.button-refresh').first().trigger('click');
            }
        } else if (d) {

            // Check the whole form and only submit
            // it if it's valid
            _checkForm().done(function () {
                // Remove the submit event handler
                // on a successful validation and
                // trigger a submit again, so that the
                // browser executes it's default behavior
                $form.off('submit').trigger('submit');

                // Resolve the deferred if given
                if ((typeof d === 'undefined' ? 'undefined' : _typeof(d)) === 'object') {
                    d.resolve();
                }
            }).fail(function () {
                // Reject the deferred if given
                if ((typeof d === 'undefined' ? 'undefined' : _typeof(d)) === 'object') {
                    d.reject();
                }
            });
        }
    };

    /**
     * Event handler for clicking on the proceed
     * button to get to the checkout process. It
     * checks all items again if they contain valid
     * data. Only if so, proceed
     * @param       {object}        e       jQuery event object
     * @private
     */
    var _submitButtonHandler = function _submitButtonHandler(e) {
        e.preventDefault();
        e.stopPropagation();

        if (isChanged) {
            // Get the complete form data if no row data is given
            var formdata = _generateFormdataObject();

            // Check the formdata for changed values
            $.each(formdata, function () {
                var $changedInput = this.target.find('.' + options.changeClass);

                if ($changedInput) {
                    $changedInput.closest('.item').find('.button-refresh').first().trigger('click');
                }
            });

            isChanged = false;
            _updateChangeState();
            return;
        }

        var $self = $(this),
            destination = $self.attr('href');

        // Check if there is any other process running
        if ($.isEmptyObject(active) && !busy && !updateList) {
            busy = true;

            _checkForm(true, true).done(function () {
                function callback() {
                    location.href = destination;
                }

                jse.libs.hooks.execute(jse.libs.hooks.keys.shop.cart.checkout, { event: e }, 500).then(callback).catch(callback);
            }).always(function () {
                busy = false;
            });
        }
    };

    /**
     * Event handler that checks the form and
     * resolves or rejects the delivered deferred
     * (Used for external payment modules to
     * check if the form is valid)
     * @param       {object}    e               jQuery event object
     * @param       {object}    d               JSON object with the event settings
     * @private
     */
    var _checkFormHandler = function _checkFormHandler(e, d) {
        e.stopPropagation();

        d = d || {};

        _checkForm(d.showChanges, d.revertChanges).done(function () {
            if (d.deferred) {
                d.deferred.resolve();
            }
        }).fail(function () {
            if (d.deferred) {
                d.deferred.reject();
            }
        });
    };

    /**
     * Function that updates the list on focus of
     * the window
     * @private
     */
    var _updateList = function _updateList() {
        updateList = true;
        jse.libs.xhr.ajax({ url: options.updateUrl }, true).done(function (result) {
            // Init with he first line since this ist the heading
            var $lastScanned = $form.find('.order-wishlist .item').first(),
                $target = $();

            // Iterate through the products object and search for the
            // products inside the markup. If the product was found,
            // update the values, if not add the product row at the
            // correct position
            $.each(result.products, function (key, value) {
                var articleId = key.replace('product_', ''),
                    $article = $form.find('input[name="products_id[]"][value="' + articleId + '"]'),
                    $row = null;

                if (!$article.length) {
                    // The article wasn't found on page
                    // -> add it
                    $row = $(value);
                    $row.insertAfter($lastScanned);
                } else {
                    // The article was found on page
                    // -> update it
                    $row = $article.closest('.item');

                    var $qty = $row.find('input[name="cart_quantity[]"]'),
                        oldQty = parseFloat($qty.data().oldValue),
                        currentQty = parseFloat($qty.val()),
                        newQty = parseFloat($(value).find('input[name="cart_quantity[]"]').val());

                    $qty.data('oldValue', newQty);

                    // Add or remove the changed classes depending on
                    // the quantity changes and the on page stored values
                    if (oldQty === currentQty && currentQty !== newQty) {
                        $qty.addClass(options.changeClass);
                    } else if (oldQty !== currentQty && currentQty === newQty) {
                        $qty.removeClass(options.changeClass);
                    }
                }

                $target.add($row);
                $lastScanned = $row;
            });

            // Update the rest of the form
            _updateForm($target, result);
        }).always(function () {
            updateList = false;
        });
    };

    /**
     * Update the input change state
     * @private
     */
    var _updateChangeState = function _updateChangeState() {
        $form.find(options.selectorMapping.submit).text(jse.core.lang.translate(isChanged ? 'refresh' : 'checkout', 'buttons'));
    };

    // ########## INITIALIZATION ##########

    /**
     * Init function of the widget
     * @constructor
     */
    module.init = function (done) {

        $updateTarget = $(options.updateTarget);
        $cartEmpty = $(options.cartEmpty);
        $cartNotEmpty = $(options.cartNotEmpty);
        $deleteField = $(options.deleteInput);
        $form = $this.find('form').first();
        deleteFieldName = $deleteField.attr('name');
        action = $form.attr('action');
        transition = { open: true, classOpen: options.classLoading };

        // Sets the current value of the input
        // to an hidden data attribute
        _updateDataValues($form);

        $form.on('input', 'input[type="text"]:not(.gift-coupon-code-input)', _inputHandler).on('blur', 'input[type="text"]:not(.gift-coupon-code-input)', _blurHandler).on('click.delete', '.button-delete', { 'type': 'delete' }, _clickHandler).on('click.refresh', '.button-refresh', { 'type': 'refresh' }, _clickHandler).on('click.addtocart', '.button-to-cart', { 'type': 'add' }, _clickHandler).on('click.submit', '.button-submit', { 'type': 'submit' }, _submitButtonHandler).on('submit', _submitHandler).on(jse.libs.theme.events.CHECK_CART(), _checkFormHandler);

        $('a.toggleusebalance input[name="gv_use_balance"]').on('click', function () {
            console.info('click');location = $(this).parent('a').get(0).href;
        });

        done();
    };

    // Return data to widget engine
    return module;
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndpZGdldHMvcHJvZHVjdF9jYXJ0X2hhbmRsZXIuanMiXSwibmFtZXMiOlsiZ2FtYmlvIiwid2lkZ2V0cyIsIm1vZHVsZSIsInNvdXJjZSIsImRhdGEiLCIkdGhpcyIsIiQiLCIkd2luZG93Iiwid2luZG93IiwiJGJvZHkiLCIkZm9ybSIsIiR1cGRhdGVUYXJnZXQiLCIkZGVsZXRlRmllbGQiLCIkY2FydEVtcHR5IiwiJGNhcnROb3RFbXB0eSIsImRlbGV0ZUZpZWxkTmFtZSIsImFjdGlvbiIsImJ1c3kiLCJ1cGRhdGVMaXN0IiwidHJhbnNpdGlvbiIsImFjdGl2ZSIsImlzQ2hhbmdlZCIsImRlZmF1bHRzIiwiYWpheCIsImNvbmZpcm1EZWxldGUiLCJkZWxldGVJbnB1dCIsInVwZGF0ZVRhcmdldCIsImNoZWNrVXJsIiwidXBkYXRlVXJsIiwiY2hhbmdlQ2xhc3MiLCJlcnJvckNsYXNzIiwiY2FydEVtcHR5IiwiY2FydE5vdEVtcHR5IiwiY2xhc3NMb2FkaW5nIiwiYWN0aW9ucyIsImFkZCIsImRlbGV0ZSIsInJlZnJlc2giLCJhamF4QWN0aW9ucyIsInNlbGVjdG9yTWFwcGluZyIsImJ1dHRvbnMiLCJnaWZ0Q29udGVudCIsImdpZnRMYXllciIsInNoYXJlQ29udGVudCIsInNoYXJlTGF5ZXIiLCJoaWRkZW5PcHRpb25zIiwibWVzc2FnZSIsImluZm9NZXNzYWdlIiwic2hpcHBpbmdJbmZvcm1hdGlvbiIsInRvdGFscyIsImVycm9yTXNnIiwic3VibWl0Iiwib3B0aW9ucyIsImV4dGVuZCIsIl9zZXRBY3Rpb24iLCJ0eXBlIiwicmVwbGFjZSIsImF0dHIiLCJfdXBkYXRlRGF0YVZhbHVlcyIsIiR0YXJnZXQiLCJmaW5kIiwiZWFjaCIsIiRzZWxmIiwidmFsdWUiLCJ2YWwiLCJfcmVzdG9yZURhdGFWYWx1ZXMiLCJkYXRhc2V0IiwidGFyZ2V0IiwibmFtZSIsIm9sZFZhbHVlIiwicmVtb3ZlQ2xhc3MiLCJfZ2VuZXJhdGVGb3JtZGF0YU9iamVjdCIsIiRyb3ciLCJsZW5ndGgiLCIkcm93cyIsIiRoaWRkZW5zIiwianNlIiwibGlicyIsImZvcm0iLCJnZXREYXRhIiwicmVzdWx0IiwidG1wUmVzdWx0IiwicHJvZHVjdHNfaWQiLCJpIiwidiIsImVxIiwia2V5IiwidW5kZWZpbmVkIiwiZmlsdGVyIiwicHVzaCIsIl9jaGVja0Zvcm0iLCJzaG93Q2hhbmdlcyIsInJldmVydENoYW5nZXMiLCJmb3JtZGF0YSIsInByb21pc2VzIiwiaGFzQ2hhbmdlZCIsIiRjaGFuZ2VkIiwid2hlbiIsImFwcGx5IiwicHJvbWlzZSIsIl9jbGVhbnVwQXJyYXkiLCJpZCIsIl91cGRhdGVGb3JtIiwidGhlbWUiLCJoZWxwZXJzIiwiZmlsbCIsImNvbnRlbnQiLCJ0b2dnbGVDbGFzcyIsInRleHQiLCJ0cmlnZ2VyIiwiZXZlbnRzIiwiQ0FSVF9VUERBVEVEIiwiQ0FSVF9VUERBVEUiLCJpc0VtcHR5T2JqZWN0IiwicHJvZHVjdHMiLCJhZGRDbGFzcyIsImluaXQiLCJfdXBkYXRlQXJ0aWNsZXNNZXNzYWdlIiwibWVzc2FnZXMiLCJwcm9kdWN0IiwibWVzc2FnZUNmZyIsIml0ZW0iLCJjbG9zZXN0Iiwic2hvdyIsIl9leGVjdXRlQWN0aW9uIiwiYXJ0aWNsZSIsIlRSQU5TSVRJT04iLCJ4aHIiLCJ1cmwiLCJkb25lIiwiaG9va3MiLCJleGVjdXRlIiwia2V5cyIsInNob3AiLCJjYXJ0IiwiY2hhbmdlIiwiJG1hcmt1cCIsInJlcGxhY2VXaXRoIiwiZXJyb3JNZXNzYWdlTGlzdCIsInByb2R1Y3ROdW1iZXIiLCJtYXRjaCIsIiRpdGVtcyIsInBhcmVudCIsIm51bWJlciIsImFsd2F5cyIsImRlZmVycmVkIiwiRGVmZXJyZWQiLCJfaW5wdXRIYW5kbGVyIiwiaGFzTmV3VmFsdWUiLCJfdXBkYXRlQ2hhbmdlU3RhdGUiLCJfYmx1ckhhbmRsZXIiLCJmaXJzdCIsIl9jbGlja0hhbmRsZXIiLCJlIiwicHJldmVudERlZmF1bHQiLCJzdG9wUHJvcGFnYXRpb24iLCJyb3dkYXRhIiwidGl0bGUiLCJtb2RhbFRpdGxlIiwiY29yZSIsImxhbmciLCJ0cmFuc2xhdGUiLCJtb2RhbE1lc3NhZ2UiLCJtb2RhbCIsImNvbmZpcm0iLCJXSVNITElTVF9DQVJUX0RFTEVURSIsImZhaWwiLCJldmVudCIsIldJU0hMSVNUX1RPX0NBUlQiLCJfc3VibWl0SGFuZGxlciIsImQiLCJvcmlnaW5hbEV2ZW50IiwiJHNvdXJjZSIsImV4cGxpY2l0T3JpZ2luYWxUYXJnZXQiLCJpcyIsIm9mZiIsInJlc29sdmUiLCJyZWplY3QiLCJfc3VibWl0QnV0dG9uSGFuZGxlciIsIiRjaGFuZ2VkSW5wdXQiLCJkZXN0aW5hdGlvbiIsImNhbGxiYWNrIiwibG9jYXRpb24iLCJocmVmIiwiY2hlY2tvdXQiLCJ0aGVuIiwiY2F0Y2giLCJfY2hlY2tGb3JtSGFuZGxlciIsIl91cGRhdGVMaXN0IiwiJGxhc3RTY2FubmVkIiwiYXJ0aWNsZUlkIiwiJGFydGljbGUiLCJpbnNlcnRBZnRlciIsIiRxdHkiLCJvbGRRdHkiLCJwYXJzZUZsb2F0IiwiY3VycmVudFF0eSIsIm5ld1F0eSIsIm9wZW4iLCJjbGFzc09wZW4iLCJvbiIsIkNIRUNLX0NBUlQiLCJjb25zb2xlIiwiaW5mbyIsImdldCJdLCJtYXBwaW5ncyI6Ijs7OztBQUFBOzs7Ozs7Ozs7O0FBVUE7Ozs7O0FBS0FBLE9BQU9DLE9BQVAsQ0FBZUMsTUFBZixDQUNJLHNCQURKLEVBR0ksQ0FDSSxNQURKLEVBRUksS0FGSixFQUdJRixPQUFPRyxNQUFQLEdBQWdCLGNBSHBCLEVBSUlILE9BQU9HLE1BQVAsR0FBZ0IsMEJBSnBCLEVBS0lILE9BQU9HLE1BQVAsR0FBZ0IsYUFMcEIsQ0FISixFQVdJLFVBQVVDLElBQVYsRUFBZ0I7O0FBRVo7O0FBRVI7O0FBRVEsUUFBSUMsUUFBUUMsRUFBRSxJQUFGLENBQVo7QUFBQSxRQUNJQyxVQUFVRCxFQUFFRSxNQUFGLENBRGQ7QUFBQSxRQUVJQyxRQUFRSCxFQUFFLE1BQUYsQ0FGWjtBQUFBLFFBR0lJLFFBQVEsSUFIWjtBQUFBLFFBSUlD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TCxDQUVRLE1BRlIsRUFFZ0IsaURBRmhCLEVBRW1FbEQsWUFGbkUsRUFHS2tELEVBSEwsQ0FHUSxjQUhSLEVBR3dCLGdCQUh4QixFQUcwQyxFQUFDLFFBQVEsUUFBVCxFQUgxQyxFQUc4RGhELGFBSDlELEVBSUtnRCxFQUpMLENBSVEsZUFKUixFQUl5QixpQkFKekIsRUFJNEMsRUFBQyxRQUFRLFNBQVQsRUFKNUMsRUFJaUVoRCxhQUpqRSxFQUtLZ0QsRUFMTCxDQUtRLGlCQUxSLEVBSzJCLGlCQUwzQixFQUs4QyxFQUFDLFFBQVEsS0FBVCxFQUw5QyxFQUsrRGhELGFBTC9ELEVBTUtnRCxFQU5MLENBTVEsY0FOUixFQU13QixnQkFOeEIsRUFNMEMsRUFBQyxRQUFRLFFBQVQsRUFOMUMsRUFNOER0QixvQkFOOUQsRUFPS3NCLEVBUEwsQ0FPUSxRQVBSLEVBT2tCL0IsY0FQbEIsRUFRSytCLEVBUkwsQ0FRUTVILElBQUlDLElBQUosQ0FBUzBCLEtBQVQsQ0FBZU8sTUFBZixDQUFzQjJGLFVBQXRCLEVBUlIsRUFRNENkLGlCQVI1Qzs7QUFVQXJMLFVBQUUsaURBQUYsRUFBcURrTSxFQUFyRCxDQUF3RCxPQUF4RCxFQUFpRSxZQUFXO0FBQzNFRSxvQkFBUUMsSUFBUixDQUFhLE9BQWIsRUFBdUJyQixXQUFXaEwsRUFBRSxJQUFGLEVBQVF3SSxNQUFSLENBQWUsR0FBZixFQUFvQjhELEdBQXBCLENBQXdCLENBQXhCLEVBQTJCckIsSUFBdEM7QUFDdkIsU0FGRDs7QUFJQXREO0FBQ0gsS0E5QkQ7O0FBZ0NBO0FBQ0EsV0FBTy9ILE1BQVA7QUFDSCxDQTl3QkwiLCJmaWxlIjoid2lkZ2V0cy9wcm9kdWN0X2NhcnRfaGFuZGxlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gcHJvZHVjdF9jYXJ0X2hhbmRsZXIuanMgMjAxOS0wNS0yM1xuIEdhbWJpbyBHbWJIXG4gaHR0cDovL3d3dy5nYW1iaW8uZGVcbiBDb3B5cmlnaHQgKGMpIDIwMTggR2FtYmlvIEdtYkhcbiBSZWxlYXNlZCB1bmRlciB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgKFZlcnNpb24gMilcbiBbaHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzL2dwbC0yLjAuaHRtbF1cbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbi8qKlxuICogQ29tcG9uZW50IHRoYXQgaW5jbHVkZXMgdGhlIGZ1bmN0aW9uYWxpdHkgZm9yXG4gKiB0aGUgYWRkLXRvLWNhcnQsIHJlZnJlc2ggYW5kIGRlbGV0ZSBidXR0b25zXG4gKiBvbiB0aGUgd2lzaGxpc3QgYW5kIGNhcnRcbiAqL1xuZ2FtYmlvLndpZGdldHMubW9kdWxlKFxuICAgICdwcm9kdWN0X2NhcnRfaGFuZGxlcicsXG5cbiAgICBbXG4gICAgICAgICdmb3JtJyxcbiAgICAgICAgJ3hocicsXG4gICAgICAgIGdhbWJpby5zb3VyY2UgKyAnL2xpYnMvZXZlbnRzJyxcbiAgICAgICAgZ2FtYmlvLnNvdXJjZSArICcvbGlicy9tb2RhbC5leHQtbWFnbmlmaWMnLFxuICAgICAgICBnYW1iaW8uc291cmNlICsgJy9saWJzL21vZGFsJ1xuICAgIF0sXG5cbiAgICBmdW5jdGlvbiAoZGF0YSkge1xuXG4gICAgICAgICd1c2Ugc3RyaWN0JztcblxuLy8gIyMjIyMjIyMjIyBWQVJJQUJMRSBJTklUSUFMSVpBVElPTiAjIyMjIyMjIyMjXG5cbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcbiAgICAgICAgICAgICR3aW5kb3cgPSAkKHdpbmRvdyksXG4gICAgICAgICAgICAkYm9keSA9ICQoJ2JvZHknKSxcbiAgICAgICAgICAgICRmb3JtID0gbnVsbCxcbiAgICAgICAgICAgICR1cGRhdGVUYXJnZXQgPSBudWxsLFxuICAgICAgICAgICAgJGRlbGV0ZUZpZWxkID0gbnVsbCxcbiAgICAgICAgICAgICRjYXJ0RW1wdHkgPSBudWxsLFxuICAgICAgICAgICAgJGNhcnROb3RFbXB0eSA9IG51bGwsXG4gICAgICAgICAgICBkZWxldGVGaWVsZE5hbWUgPSBudWxsLFxuICAgICAgICAgICAgYWN0aW9uID0gbnVsbCxcbiAgICAgICAgICAgIGJ1c3kgPSBudWxsLFxuICAgICAgICAgICAgdXBkYXRlTGlzdCA9IGZhbHNlLFxuICAgICAgICAgICAgdHJhbnNpdGlvbiA9IG51bGwsXG4gICAgICAgICAgICBhY3RpdmUgPSB7fSxcbiAgICAgICAgICAgIGlzQ2hhbmdlZCA9IGZhbHNlLFxuICAgICAgICAgICAgZGVmYXVsdHMgPSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIGFuIEFKQVggdG8gdXBkYXRlIHRoZSBmb3JtXG4gICAgICAgICAgICAgICAgYWpheDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAvLyBTaG93IGFuIGNvbmZpcm0tbGF5ZXIgb24gZGVsZXRpb24gb2YgYW4gaXRlbVxuICAgICAgICAgICAgICAgIGNvbmZpcm1EZWxldGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIC8vIFNlbGVjdG9yIG9mIHRoZSBoaWRkZW4gZmllbGQgZm9yIHRoZSBkZWxldGlvbiBlbnRyaWVzXG4gICAgICAgICAgICAgICAgZGVsZXRlSW5wdXQ6ICcjZmllbGRfY2FydF9kZWxldGVfcHJvZHVjdHNfaWQnLFxuICAgICAgICAgICAgICAgIC8vIFRyaWdnZXIgYW4gZXZlbnQgdG8gdGhhdCBpdGVtIG9uIGFuIHN1Y2Nlc3NmdWxsIGFqYXggKGUuZy4gdGhlIHNoaXBwaW5nIGNvc3RzIGVsZW1lbnQpXG4gICAgICAgICAgICAgICAgdXBkYXRlVGFyZ2V0OiAnLnNoaXBwaW5nLWNhbGN1bGF0aW9uJyxcbiAgICAgICAgICAgICAgICAvLyBUaGUgVVJMIGZvciB0aGUgcXVhbnRpdHkgY2hlY2sgb2YgdGhlIGl0ZW1cbiAgICAgICAgICAgICAgICBjaGVja1VybDogJ3Nob3AucGhwP2RvPUNoZWNrUXVhbnRpdHknLFxuICAgICAgICAgICAgICAgIC8vIElmIGFuIFVSTCBpcyBzZXQsIHRoaXMgb25lIHdpbGwgYmUgcmVxdWVzdHMgZm9yIHN0YXR1cyB1cGRhdGVzIG9uIHRhYiBmb2N1c1xuICAgICAgICAgICAgICAgIHVwZGF0ZVVybDogJ3Nob3AucGhwP2RvPUNhcnQnLFxuXG4gICAgICAgICAgICAgICAgY2hhbmdlQ2xhc3M6ICdoYXMtY2hhbmdlZCcsIC8vIENsYXNzIHRoYXQgZ2V0cyBhZGRlZCBpZiBhbiBpbnB1dCBoYXMgY2hhbmdlZFxuICAgICAgICAgICAgICAgIGVycm9yQ2xhc3M6ICdlcnJvcicsIC8vIENsYXNzIHRoYXQgZ2V0cyBhZGRlZCB0byB0aGUgcm93IGlmIGFuIGVycm9yIGhhcyBvY2N1cmVkXG4gICAgICAgICAgICAgICAgY2FydEVtcHR5OiAnLmNhcnQtZW1wdHknLCAvLyBTaG93IHRoaXMgc2VsZWN0aW9uIGlmIHRoZSBjYXJ0IGlzIGVtcHR5IG9yIGhpZGUgaXQgZWxzZVxuICAgICAgICAgICAgICAgIGNhcnROb3RFbXB0eTogJy5jYXJ0LW5vdC1lbXB0eScsIC8vIFNob3cgdGhpcyBzZWxlY3Rpb24gaWYgdGhlIGNhcnQgaXMgbm90IGVtcHR5IG9yIGhpZGUgaXQgZWxzZVxuICAgICAgICAgICAgICAgIGNsYXNzTG9hZGluZzogJ2xvYWRpbmcnLCAvLyBUaGUgY2xhc3MgdGhhdCBnZXRzIGFkZGVkIHRvIGFuIGN1cnJlbnRseSB1cGRhdGluZyByb3dcbiAgICAgICAgICAgICAgICBhY3Rpb25zOiB7IC8vIFRoZSBhY3Rpb25zIHRoYXQgZ2V0dGluZyBhcHBlbmRlZCB0byB0aGUgc3VibWl0IHVybCBvbiB0aGUgZGlmZmVyZW50IHR5cGUgb2YgdXBkYXRlc1xuICAgICAgICAgICAgICAgICAgICBhZGQ6ICd3aXNobGlzdF90b19jYXJ0JyxcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlOiAndXBkYXRlX3Byb2R1Y3QnLFxuICAgICAgICAgICAgICAgICAgICByZWZyZXNoOiAndXBkYXRlX3dpc2hsaXN0J1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYWpheEFjdGlvbnM6IHsgLy8gVVJMcyBmb3IgdGhlIGFqYXggdXBkYXRlcyBvbiB0aGUgZGlmZmVyZW50IGFjdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgYWRkOiAnc2hvcC5waHA/ZG89V2lzaExpc3QvQWRkVG9DYXJ0JyxcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlOiAnc2hvcC5waHA/ZG89Q2FydC9EZWxldGUnLFxuICAgICAgICAgICAgICAgICAgICByZWZyZXNoOiAnc2hvcC5waHA/ZG89Q2FydC9VcGRhdGUnXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzZWxlY3Rvck1hcHBpbmc6IHtcbiAgICAgICAgICAgICAgICAgICAgYnV0dG9uczogJy5zaG9wcGluZy1jYXJ0LWJ1dHRvbicsXG4gICAgICAgICAgICAgICAgICAgIGdpZnRDb250ZW50OiAnLmdpZnQtY2FydC1jb250ZW50LXdyYXBwZXInLFxuICAgICAgICAgICAgICAgICAgICBnaWZ0TGF5ZXI6ICcuZ2lmdC1jYXJ0LWxheWVyJyxcbiAgICAgICAgICAgICAgICAgICAgc2hhcmVDb250ZW50OiAnLnNoYXJlLWNhcnQtY29udGVudC13cmFwcGVyJyxcbiAgICAgICAgICAgICAgICAgICAgc2hhcmVMYXllcjogJy5zaGFyZS1jYXJ0LWxheWVyJyxcbiAgICAgICAgICAgICAgICAgICAgaGlkZGVuT3B0aW9uczogJyNjYXJ0X3F1YW50aXR5IC5oaWRkZW4tb3B0aW9ucycsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6ICcuZ2xvYmFsLWVycm9yLW1lc3NhZ2VzJyxcbiAgICAgICAgICAgICAgICAgICAgaW5mb01lc3NhZ2U6ICcuaW5mby1tZXNzYWdlJyxcbiAgICAgICAgICAgICAgICAgICAgc2hpcHBpbmdJbmZvcm1hdGlvbjogJyNzaGlwcGluZy1pbmZvcm1hdGlvbi1sYXllcicsXG4gICAgICAgICAgICAgICAgICAgIHRvdGFsczogJyNjYXJ0X3F1YW50aXR5IC50b3RhbC1ib3gnLFxuICAgICAgICAgICAgICAgICAgICBlcnJvck1zZzogJy5lcnJvci1tc2cnLFxuICAgICAgICAgICAgICAgICAgICBzdWJtaXQ6ICcuYnV0dG9uLXN1Ym1pdCdcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3B0aW9ucyA9ICQuZXh0ZW5kKGZhbHNlLCB7fSwgZGVmYXVsdHMsIGRhdGEpLFxuICAgICAgICAgICAgbW9kdWxlID0ge307XG5cbi8vICMjIyMjIyMjIyMgSEVMUEVSIEZVTkNUSU9OUyAjIyMjIyMjIyMjXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFVwZGF0ZXMgdGhlIGZvcm0gYWN0aW9uIHRvIHRoZSB0eXBlIGdpdmVuXG4gICAgICAgICAqIGluIHRoZSBvcHRpb25zLmFjdGlvbnMgb2JqZWN0XG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7c3RyaW5nfSAgICAgICAgdHlwZSAgICAgICAgVGhlIGFjdGlvbiBuYW1lXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX3NldEFjdGlvbiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5hamF4KSB7XG4gICAgICAgICAgICAgICAgYWN0aW9uID0gb3B0aW9ucy5hamF4QWN0aW9uc1t0eXBlXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5hY3Rpb25zICYmIG9wdGlvbnMuYWN0aW9uc1t0eXBlXSkge1xuICAgICAgICAgICAgICAgIGFjdGlvbiA9IGFjdGlvbi5yZXBsYWNlKC8oYWN0aW9uPSlbXlxcJl0rLywgJyQxJyArIG9wdGlvbnMuYWN0aW9uc1t0eXBlXSk7XG4gICAgICAgICAgICAgICAgJGZvcm0uYXR0cignYWN0aW9uJywgYWN0aW9uKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogSGVscGVyIGZ1bmN0aW9uIHRoYXQgdXBkYXRlcyB0aGVcbiAgICAgICAgICogaGlkZGVuIGRhdGEgYXR0cmlidXRlcyB3aXRoIHRoZSBjdXJyZW50XG4gICAgICAgICAqIHZhbHVlcyBvZiB0aGUgaW5wdXQgZmllbGRzXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICAgICAgJHRhcmdldCAgICAgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgdG9wbW9zdCBjb250YWluZXJcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdXBkYXRlRGF0YVZhbHVlcyA9IGZ1bmN0aW9uICgkdGFyZ2V0KSB7XG4gICAgICAgICAgICAkdGFyZ2V0XG4gICAgICAgICAgICAgICAgLmZpbmQoJ2lucHV0W3R5cGU9XCJ0ZXh0XCJdJylcbiAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkc2VsZiA9ICQodGhpcyksXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9ICRzZWxmLnZhbCgpO1xuXG4gICAgICAgICAgICAgICAgICAgICRzZWxmLmRhdGEoJ29sZFZhbHVlJywgdmFsdWUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCByZXN0b3JlcyB0aGUgdmFsdWVzXG4gICAgICAgICAqIHN0b3JlZCBieSB0aGUgX3VwZGF0ZURhdGFWYWx1ZXMgZnVuY3Rpb25cbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgICAgICBkYXRhc2V0ICAgICBUaGUgZGF0YSBvYmplY3Qgb2YgYWxsIHRhcmdldHMgdGhhdCBuZWVkcyB0byBiZSByZXNldFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9yZXN0b3JlRGF0YVZhbHVlcyA9IGZ1bmN0aW9uIChkYXRhc2V0KSB7XG4gICAgICAgICAgICAvLyBSZXNldCBlYWNoIGNoYW5nZWQgZmllbGQgZ2l2ZW5cbiAgICAgICAgICAgIC8vIGJ5IHRoZSBkYXRhc2V0IHRhcmdldFxuICAgICAgICAgICAgJC5lYWNoKGRhdGFzZXQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSB0aGlzO1xuXG4gICAgICAgICAgICAgICAgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgLnRhcmdldFxuICAgICAgICAgICAgICAgICAgICAuZmluZCgnLicgKyBvcHRpb25zLmNoYW5nZUNsYXNzKVxuICAgICAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAkc2VsZi5hdHRyKCduYW1lJykucmVwbGFjZSgnW10nLCAnJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsID0gJHNlbGYuZGF0YSgpLm9sZFZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVtuYW1lXVswXSA9IHZhbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICRzZWxmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnZhbCh2YWwpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUNsYXNzKG9wdGlvbnMuY2hhbmdlQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCBnZW5lcmF0ZXMgYW4gYXJyYXkgb2YgIGRhdGFzZXRzIGZyb20gdGhlIGZvcm0uIEVhY2ggYXJyYXkgaXRlbVxuICAgICAgICAgKiBjb250YWlucyB0aGUgZGF0YSBvZiBvbmUgcm93IChpbmNsdXNpdmUgdGhlIGF0dHJpYnV0ZXMgZGF0YSBmcm9tIHRoZSBmb3JtIGhlYWQgYmVsb25naW5nXG4gICAgICAgICAqIHRvIHRoZSByb3cpLiBBZGRpdGlvbmFsbHkgaXQgYWRkcyB0aGUgdGFyZ2V0LXBhcmFtZXRlciB0byBlYWNoIGRhdGFzZXQgd2hpY2ggY29udGFpbnNcbiAgICAgICAgICogdGhlIHNlbGVjdGlvbiBvZiB0aGUgcm93LHRoZSBjdXJyZW50IGRhdGFzZXQgYmVsb25ncyB0by5cbiAgICAgICAgICpcbiAgICAgICAgICogQHBhcmFtIHtvYmplY3R9ICRyb3cgVGhlIG9wdGlvbmFsIHJvdyBzZWxlY3Rpb24gdGhlIGRhdGEgZ2V0cyBmcm9tLiBJZiBubyBzZWxlY3Rpb24gaXMgZ2l2ZW4sIHRoZSBmb3JtXG4gICAgICAgICAqIGdldHMgc2VsZWN0ZWQuXG4gICAgICAgICAqIEByZXR1cm4ge0FycmF5fSBUaGUgYXJyYXkgd2l0aCB0aGUgZGF0YXNldHMgb2YgZWFjaCByb3dcbiAgICAgICAgICpcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfZ2VuZXJhdGVGb3JtZGF0YU9iamVjdCA9IGZ1bmN0aW9uICgkcm93KSB7XG4gICAgICAgICAgICB2YXIgJHRhcmdldCA9ICgkcm93ICYmICRyb3cubGVuZ3RoKSA/ICRyb3cgOiAkZm9ybSxcbiAgICAgICAgICAgICAgICAkcm93cyA9ICgkcm93ICYmICRyb3cubGVuZ3RoKSA/ICRyb3cgOiAkZm9ybS5maW5kKCcub3JkZXItd2lzaGxpc3QgLml0ZW06Z3QoMCknKSxcbiAgICAgICAgICAgICAgICAkaGlkZGVucyA9ICRmb3JtLmZpbmQoJy5oaWRkZW4tb3B0aW9ucyBpbnB1dFt0eXBlPVwiaGlkZGVuXCJdJyksXG4gICAgICAgICAgICAgICAgZGF0YXNldCA9IGpzZS5saWJzLmZvcm0uZ2V0RGF0YSgkdGFyZ2V0KSxcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBbXSxcbiAgICAgICAgICAgICAgICB0bXBSZXN1bHQgPSBudWxsO1xuXG4gICAgICAgICAgICAkLmVhY2goZGF0YXNldC5wcm9kdWN0c19pZCwgZnVuY3Rpb24gKGksIHYpIHtcbiAgICAgICAgICAgICAgICB0bXBSZXN1bHQgPSB7fTtcbiAgICAgICAgICAgICAgICB0bXBSZXN1bHQudGFyZ2V0ID0gJHJvd3MuZXEoaSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTdG9yZSB0aGUgZGF0YSBmcm9tIHRoZSBjdXJyZW50IHJvdyBhcyBhIGpzb25cbiAgICAgICAgICAgICAgICAkLmVhY2goZGF0YXNldCwgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWVbaV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gU3RvcmUgdGhlIHZhbHVlIGFzIGFuIGFycmF5IHRvIGJlIGNvbXBsaWFudCB3aXRoIHRoZSBvbGQgQVBJXG4gICAgICAgICAgICAgICAgICAgICAgICB0bXBSZXN1bHRba2V5XSA9IFt2YWx1ZVtpXV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgaGlkZGVuIGZpZWxkcyBmb3IgdGhlIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICAvLyBiZWxvbmdpbmcgdG8gdGhpcyByb3cgZnJvbSB0aGUgZm9ybSBoZWFkXG4gICAgICAgICAgICAgICAgJGhpZGRlbnNcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcignW25hbWVePVwiaWRbJyArIHYgKyAnXCJdLCAuZm9yY2UnKVxuICAgICAgICAgICAgICAgICAgICAuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUgPSAkc2VsZi5hdHRyKCduYW1lJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRtcFJlc3VsdFtuYW1lXSA9ICRzZWxmLnZhbCgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIFB1c2ggdGhlIGdlbmVyYXRlZCBqc29uIHRvIHRoZSBmaW5hbCByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh0bXBSZXN1bHQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZ1bmN0aW9uIHRoYXQgY2hlY2tzIHRoZSBmb3JtIC8gdGhlIHJvdyBpZiB0aGUgY29tYmluYXRpb25cbiAgICAgICAgICogYW5kIHF1YW50aXR5IGlzIHZhbGlkLiBJdCByZXR1cm5zIGFuIHByb21pc2Ugd2hpY2ggZ2V0cyByZWplY3RlZFxuICAgICAgICAgKiBpZiBpbiB0aGUgc2NvcGUgd2FzIGFuIGludmFsaWQgdmFsdWUuIEluIG90aGVyIGNhc2VzIGl0IGdldHNcbiAgICAgICAgICogcmVzb2x2ZWQuIElmIGl0IGlzIGRldGVjdGluZyBjaGFuZ2VzIGluc2lkZSB0aGUgZm9ybSBpdCBjYW5cbiAgICAgICAgICogc2hvdyBhbiBpbmZvIGxheWVyIHRvIHRoZSB1c2VyIGFuZCAvIG9yIHJldmVydCB0aGUgY2hhbmdlc1xuICAgICAgICAgKiAoZGVwZW5kaW5nIG9uIHRoZSBjYWxsZXIgcGFyYW1ldGVycylcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtib29sZWFufSAgICAgICBzaG93Q2hhbmdlcyAgICAgICAgIFNob3cgYW4gaW5mby1sYXllciBpZiBjaGFuZ2VzIHdvdWxkIGJlIHJlZnVzZWRcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtib29sZWFufSAgICAgICByZXZlcnRDaGFuZ2VzICAgICAgIFJlc2V0cyB0aGUgZm9ybSB2YWx1ZXMgd2l0aCB0aGUgb25lIGZyb20gdGhlIGRhdGEgYXR0cmlidXRlcyBpZiB0cnVlXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICAgICAgZm9ybWRhdGEgICAgICAgICAgICBKc29uIHRoYXQgY29udGFpbnMgdGhlIGRhdGEgdG8gY2hlY2tcbiAgICAgICAgICogQHJldHVybiAgICAgeyp9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmV0dXJucyBhIHByb21pc2VcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfY2hlY2tGb3JtID0gZnVuY3Rpb24gKHNob3dDaGFuZ2VzLCByZXZlcnRDaGFuZ2VzLCBmb3JtZGF0YSkge1xuXG4gICAgICAgICAgICB2YXIgcHJvbWlzZXMgPSBbXSxcbiAgICAgICAgICAgICAgICBoYXNDaGFuZ2VkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgY29tcGxldGUgZm9ybSBkYXRhIGlmIG5vIHJvdyBkYXRhIGlzIGdpdmVuXG4gICAgICAgICAgICBmb3JtZGF0YSA9IGZvcm1kYXRhIHx8IF9nZW5lcmF0ZUZvcm1kYXRhT2JqZWN0KCk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSBmb3JtZGF0YSBmb3IgY2hhbmdlZCB2YWx1ZXNcbiAgICAgICAgICAgICQuZWFjaChmb3JtZGF0YSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkY2hhbmdlZCA9IHRoaXMudGFyZ2V0LmZpbmQoJy4nICsgb3B0aW9ucy5jaGFuZ2VDbGFzcyk7XG4gICAgICAgICAgICAgICAgaGFzQ2hhbmdlZCA9IGhhc0NoYW5nZWQgfHwgISEkY2hhbmdlZC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcmV0dXJuICFoYXNDaGFuZ2VkO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiAkLndoZW4uYXBwbHkodW5kZWZpbmVkLCBwcm9taXNlcykucHJvbWlzZSgpO1xuXG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IGNsZWFucyB1cCB0aGUgcHJvY2VzcyBzdGF0ZVxuICAgICAgICAgKiAoTmVlZGVkIGVzcGVjaWFsbHkgYWZ0ZXIgYWpheCByZXF1ZXN0cywgdG8gYmUgYWJsZVxuICAgICAgICAgKiB0byBtYWtlIGZ1cnRoZXIgcmVxdWVzdHMpXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7c3RyaW5nfSAgICAgICAgaWQgICAgICAgICAgICAgIFRoZSBwcm9kdWN0IGlkIHRoYXQgbmVlZHMgdG8gYmUgcmVzZXRlZFxuICAgICAgICAgKiBAcmV0dXJuICAgICB7QXJyYXkuPFQ+fSAgICAgICAgICAgICAgICAgICAgIFJldHVybnMgYW4gYXJyYXkgd2l0aG91dCBlbXB0eSBmaWVsZHNcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfY2xlYW51cEFycmF5ID0gZnVuY3Rpb24gKGlkLCAkcm93KSB7XG4gICAgICAgICAgICBkZWxldGUgYWN0aXZlWydwcm9kdWN0XycgKyBpZF07XG4gICAgICAgICAgICAkcm93LnJlbW92ZUNsYXNzKCdsb2FkaW5nJyk7XG4gICAgICAgICAgICByZXR1cm4gYWN0aXZlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCBkb2VzIHRoZSBnZW5lcmFsIGZvcm0gdXBkYXRlXG4gICAgICAgICAqIGFmdGVyIGFuIGFqYXggcmVxdWVzdFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgJHRhcmdldCAgICAgICAgIFRoZSBqUXVlcnkgc2VsZWN0aW9uIG9mIHRoZSB0YXJnZXQgZWxlbWVudHMuXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICByZXN1bHQgICAgICAgICAgVGhlIHJlc3VsdCBvZiB0aGUgYWpheCByZXF1ZXN0LlxuICAgICAgICAgKiBAcGFyYW0gICAgICAge3N0cmluZ30gICAgdHlwZSAgICAgICAgICAgIFRoZSBleGVjdXRlZCBhY3Rpb24gdHlwZS5cbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdXBkYXRlRm9ybSA9IGZ1bmN0aW9uICgkdGFyZ2V0LCByZXN1bHQsIHR5cGUpIHtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcmVzdCBvZiB0aGUgcGFnZVxuICAgICAgICAgICAganNlLmxpYnMudGhlbWUuaGVscGVycy5maWxsKHJlc3VsdC5jb250ZW50LCAkYm9keSwgb3B0aW9ucy5zZWxlY3Rvck1hcHBpbmcpO1xuXG4gICAgICAgICAgICAvLyBUb2dnbGUgaW5mby1tZXNzYWdlcyB2aXNpYmlsaXR5LlxuICAgICAgICAgICAgJCgnLmluZm8tbWVzc2FnZScpLnRvZ2dsZUNsYXNzKCdoaWRkZW4nLCAkKCcuaW5mby1tZXNzYWdlJykudGV4dCgpID09PSAnJyk7XG5cbiAgICAgICAgICAgIC8vIEluZm9ybSBvdGhlciB3aWRnZXRzIGFib3V0IHRoZSB1cGRhdGVcbiAgICAgICAgICAgICR1cGRhdGVUYXJnZXQudHJpZ2dlcihqc2UubGlicy50aGVtZS5ldmVudHMuQ0FSVF9VUERBVEVEKCksIFtdKTtcbiAgICAgICAgICAgICRib2R5LnRyaWdnZXIoanNlLmxpYnMudGhlbWUuZXZlbnRzLkNBUlRfVVBEQVRFKCksICh0eXBlID09PSAnYWRkJykpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGhpZGRlbiBkYXRhIGF0dHJpYnV0ZXMgb2YgdGhhdCByb3dcbiAgICAgICAgICAgIF91cGRhdGVEYXRhVmFsdWVzKCR0YXJnZXQpO1xuXG4gICAgICAgICAgICBpZiAoJC5pc0VtcHR5T2JqZWN0KHJlc3VsdC5wcm9kdWN0cykpIHtcbiAgICAgICAgICAgICAgICAvLyBIaWRlIHRoZSB0YWJsZSBpZiBubyBwcm9kdWN0cyBhcmUgYXQgdGhlIGxpc3RcbiAgICAgICAgICAgICAgICAkY2FydE5vdEVtcHR5LmFkZENsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgICAgICAgICAkY2FydEVtcHR5LnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gU2hvdyB0aGUgdGFibGUgaWYgdGhlcmUgYXJlIHByb2R1Y3RzIGF0IGl0XG4gICAgICAgICAgICAgICAgJGNhcnRFbXB0eS5hZGRDbGFzcygnaGlkZGVuJyk7XG4gICAgICAgICAgICAgICAgJGNhcnROb3RFbXB0eS5yZW1vdmVDbGFzcygnaGlkZGVuJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHJlaW5pdGlhbGl6ZSB3aWRnZXRzIGluIHVwZGF0ZWQgRE9NXG4gICAgICAgICAgICB3aW5kb3cuZ2FtYmlvLndpZGdldHMuaW5pdCgkdGhpcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byB1cGRhdGUgcHJvZHVjdCBzcGVjaWZpYyBtZXNzYWdlcy5cbiAgICAgICAgICogVGhlcmVmb3IgaXQgY2FsbHMgQUpBWC1yZXF1ZXN0cyAoaW4gY2FzZSBhamF4IGlzXG4gICAgICAgICAqIGVuYWJsZWQpIHRvIHRoZSBzZXJ2ZXIgdG8gZ2V0IHRoZSB1cGRhdGVkIGluZm9ybWF0aW9uXG4gICAgICAgICAqIGFib3V0IHRoZSB0YWJsZSBzdGF0ZS4gSWYgYWpheCBpc24ndCBlbmFibGVkLCBpdCBzaW1wbHlcbiAgICAgICAgICogc3VibWl0cyB0aGUgZm9ybS5cbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgICAgICBtZXNzYWdlcyAgICAgICAgICAgIE9iamVjdCB3aXRoIGFydGljbGVJZCA9PiBtZXNzYWdlIGNvbmZpZ3VyYXRpb24gb2JqZWN0XG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX3VwZGF0ZUFydGljbGVzTWVzc2FnZSA9IGZ1bmN0aW9uIChtZXNzYWdlcykge1xuXG4gICAgICAgICAgICAvL3VwZGF0ZSBhbGwgbWVzc2FnZXMgb2cgdGhlIHJlcXVlc3RcbiAgICAgICAgICAgICQuZWFjaChtZXNzYWdlcywgZnVuY3Rpb24gKHByb2R1Y3QsIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBsZXQgbWVzc2FnZUNmZyA9IHsnbWVzc2FnZSc6IG1lc3NhZ2V9O1xuICAgICAgICAgICAgICAgIC8vbGV0IHByb2R1Y3RJZCA9IHByb2R1Y3QubWF0Y2goL1xcZCsvKVswXTtcbiAgICAgICAgICAgICAgICAvLyBGaW5kIHRoZSByZWxhdGVkIHByb2R1Y3QgdHJcbiAgICAgICAgICAgICAgICBsZXQgaXRlbSA9ICQoJ2lucHV0W3ZhbHVlXj1cIicgKyBwcm9kdWN0ICsgJ1wiXScpLmNsb3Nlc3QoJ3RyJyk7XG5cbiAgICAgICAgICAgICAgICBqc2UubGlicy50aGVtZS5oZWxwZXJzLmZpbGwobWVzc2FnZUNmZywgaXRlbSwgb3B0aW9ucy5zZWxlY3Rvck1hcHBpbmcpO1xuICAgICAgICAgICAgICAgIGlmIChpdGVtLmZpbmQoJy5lcnJvci1tc2cnKS50ZXh0KCkgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGl0ZW0uZmluZCgnLmVycm9yLW1zZycpLnNob3coKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IHByb2Nlc3NlcyB0aGUgbGlzdCB1cGRhdGVzLlxuICAgICAgICAgKiBUaGVyZWZvciBpdCBjYWxscyBBSkFYLXJlcXVlc3RzIChpbiBjYXNlIGFqYXggaXNcbiAgICAgICAgICogZW5hYmxlZCkgdG8gdGhlIHNlcnZlciB0byBnZXQgdGhlIHVwZGF0ZWQgaW5mb3JtYXRpb25cbiAgICAgICAgICogYWJvdXQgdGhlIHRhYmxlIHN0YXRlLiBJZiBhamF4IGlzbid0IGVuYWJsZWQsIGl0IHNpbXBseVxuICAgICAgICAgKiBzdWJtaXRzIHRoZSBmb3JtLlxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgICAgICR0YXJnZXQgICAgICAgICAgICBUaGUgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgcm93IHRoYXQgZ2V0cyB1cGRhdGVkXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICAgICAgZGF0YXNldCAgICAgICAgICAgIFRoZSBkYXRhIGNvbGxlY3RlZCBmcm9tIHRoZSB0YXJnZXQgcm93IGluIEpTT04gZm9ybWF0XG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7YXJ0aWNsZX0gICAgICAgYXJ0aWNsZSAgICAgICAgICAgIFRoZSBwcm9kdWN0cyBpZCBvZiB0aGUgYXJ0aWNsZSBpbiB0aGF0IHJvd1xuICAgICAgICAgKiBAcGFyYW0gICAgICAge2FydGljbGV9ICAgICAgIHR5cGUgICAgICAgICAgICAgICBUaGUgb3BlcmF0aW9uIHR5cGUgY2FuIGVpdGhlciBiZSBcImFkZFwiLCBcImRlbGV0ZVwiIG9yIFwicmVmcmVzaFwiLlxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9leGVjdXRlQWN0aW9uID0gZnVuY3Rpb24gKCRyb3csICR0YXJnZXQsIGRhdGFzZXQsIGFydGljbGUsIHR5cGUpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFqYXgpIHtcbiAgICAgICAgICAgICAgICAvLyBEZWxldGUgdGhlIHRhcmdldCBlbGVtZW50IGJlY2F1c2UgYWpheCByZXF1ZXN0c1xuICAgICAgICAgICAgICAgIC8vIHdpbGwgZmFpbCB3aXRoIGEgalF1ZXJ5IHNlbGVjdGlvbiBpbiB0aGUgZGF0YSBqc29uXG4gICAgICAgICAgICAgICAgZGVsZXRlIGRhdGFzZXQudGFyZ2V0O1xuXG4gICAgICAgICAgICAgICAgJHJvdy50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OKCksIHRyYW5zaXRpb24pO1xuXG4gICAgICAgICAgICAgICAgLy8gUGVyZm9ybSBhbiBhamF4IGlmIHRoZSBkYXRhIGlzIHZhbGlkIGFuZCB0aGUgb3B0aW9ucyBmb3IgYWpheCBpcyBzZXRcbiAgICAgICAgICAgICAgICBqc2UubGlicy54aHIuYWpheCh7dXJsOiBhY3Rpb24sIGRhdGE6IGRhdGFzZXR9LCB0cnVlKS5kb25lKGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGVyZm9ybSBob29rc1xuICAgICAgICAgICAgICAgICAgICBqc2UubGlicy5ob29rcy5leGVjdXRlKGpzZS5saWJzLmhvb2tzLmtleXMuc2hvcC5jYXJ0LmNoYW5nZSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRhcmdldCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFzZXQsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcnRpY2xlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCxcbiAgICAgICAgICAgICAgICAgICAgfSwgNTAwKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHByb2R1Y3Qgcm93XG4gICAgICAgICAgICAgICAgICAgIHZhciAkbWFya3VwID0gJChyZXN1bHQucHJvZHVjdHNbJ3Byb2R1Y3RfJyArIGFydGljbGVdIHx8ICcnKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBUb2dnbGUgZXJyb3ItbWVzc2FnZXMgdmlzaWJpbGl0eS5cbiAgICAgICAgICAgICAgICAgICAgJG1hcmt1cC5yZW1vdmVDbGFzcyhvcHRpb25zLmNsYXNzTG9hZGluZyk7XG4gICAgICAgICAgICAgICAgICAgICR0YXJnZXQucmVwbGFjZVdpdGgoJG1hcmt1cCk7XG5cbiAgICAgICAgICAgICAgICAgICAgX3VwZGF0ZUFydGljbGVzTWVzc2FnZShyZXN1bHQuY29udGVudC5lcnJvck1lc3NhZ2VMaXN0KTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHJlc3VsdC5jb250ZW50LmVycm9yTWVzc2FnZUxpc3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgX3VwZGF0ZUZvcm0oJHRhcmdldCwgcmVzdWx0LCB0eXBlKTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvZHVjdE51bWJlciA9IGFydGljbGUubWF0Y2goL1xcZCsvKVswXTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaW5kIGFsbCBpdGVtcyB3aXRoIHRoZSBzYW1lIHByb2R1Y3QgbnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIHZhciAkaXRlbXMgPSAkKCdpbnB1dFt2YWx1ZV49XCInICsgcHJvZHVjdE51bWJlciArICdcIl0nKS5wYXJlbnQoJ3RkJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQXBwbHkgdGhlIG5ldyBtYXJrdXAgZm9yZWFjaCBpdGVtIHdoaWNoIGhhcyB0aGUgc2FtZSBwcm9kdWN0IG51bWJlci5cbiAgICAgICAgICAgICAgICAgICAgJGl0ZW1zLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCEkKHRoaXMpLmZpbmQoJ2lucHV0W3ZhbHVlPVwiJyArIGFydGljbGUgKyAnXCJdJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG51bWJlciA9ICQodGhpcykuZmluZCgnaW5wdXRbaWQ9XCJwcm9kdWN0c19pZFtdXCJdJykuYXR0cigndmFsdWUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbWFya3VwID0gJChyZXN1bHQucHJvZHVjdHNbJ3Byb2R1Y3RfJyArIG51bWJlcl0gfHwgJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0YXJnZXQgPSAkKHRoaXMpLnBhcmVudCgndHInKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGFyZ2V0LnJlcGxhY2VXaXRoKCRtYXJrdXApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIH0pLmFsd2F5cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIF9jbGVhbnVwQXJyYXkoYXJ0aWNsZSwgJHJvdyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIENsZWFudXAgdGhlIGFjdGl2ZSBhcnJheSBvbiBmYWlsIC8gc3VjY2Vzc1xuICAgICAgICAgICAgICAgIC8vIG9mIHRoZSBmb2xsb3dpbmcgc3VibWl0LiBUaGlzIGlzIGEgZmFsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyBpZiBhbiBvdGhlciBjb21wb25lbnQgd291bGQgcHJldmVudCB0aGUgc3VibWl0XG4gICAgICAgICAgICAgICAgLy8gaW4gc29tZSBjYXNlcywgc28gdGhhdCB0aGlzIHNjcmlwdCBjYW4gcGVyZm9ybVxuICAgICAgICAgICAgICAgIC8vIGFjdGlvbnMgYWdhaW5cbiAgICAgICAgICAgICAgICB2YXIgZGVmZXJyZWQgPSAkLkRlZmVycmVkKCk7XG4gICAgICAgICAgICAgICAgZGVmZXJyZWQuYWx3YXlzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgX2NsZWFudXBBcnJheShhcnRpY2xlLCAkcm93KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIFN1Ym1pdCB0aGUgZm9ybVxuICAgICAgICAgICAgICAgICRmb3JtLnRyaWdnZXIoJ3N1Ym1pdCcsIGRlZmVycmVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuXG4vLyAjIyMjIyMjIyMjIEVWRU5UIEhBTkRMRVIgIyMjIyMjIyMjI1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBZGRzIGFuIGNsYXNzIHRvIHRoZSBjaGFuZ2VkIGlucHV0XG4gICAgICAgICAqIGZpZWxkLCBzbyB0aGF0IGl0J3Mgc3R5bGluZyBzaG93c1xuICAgICAgICAgKiB0aGF0IGl0IHdhc24ndCByZWZyZXNoZWQgdGlsbCBub3dcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfaW5wdXRIYW5kbGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyICRzZWxmID0gJCh0aGlzKSxcbiAgICAgICAgICAgICAgICB2YWx1ZSA9ICRzZWxmLnZhbCgpLFxuICAgICAgICAgICAgICAgIG9sZFZhbHVlID0gJHNlbGYuZGF0YSgpLm9sZFZhbHVlLFxuICAgICAgICAgICAgICAgIGhhc05ld1ZhbHVlID0gdmFsdWUgIT09IG9sZFZhbHVlO1xuXG4gICAgICAgICAgICBpZiAoaGFzTmV3VmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpc0NoYW5nZWQgPSBoYXNOZXdWYWx1ZTtcbiAgICAgICAgICAgICAgICAkc2VsZi5hZGRDbGFzcyhvcHRpb25zLmNoYW5nZUNsYXNzKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgJHNlbGYucmVtb3ZlQ2xhc3Mob3B0aW9ucy5jaGFuZ2VDbGFzcyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF91cGRhdGVDaGFuZ2VTdGF0ZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIYW5kbGUgdGhlIGJsdXIgZXZlbnRcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfYmx1ckhhbmRsZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgIHZhbHVlID0gJHNlbGYudmFsKCksXG4gICAgICAgICAgICAgICAgb2xkVmFsdWUgPSAkc2VsZi5kYXRhKCkub2xkVmFsdWUsXG4gICAgICAgICAgICAgICAgaGFzTmV3VmFsdWUgPSB2YWx1ZSAhPT0gb2xkVmFsdWU7XG5cbiAgICAgICAgICAgIGlmIChoYXNOZXdWYWx1ZSkge1xuICAgICAgICAgICAgICAgICRzZWxmXG4gICAgICAgICAgICAgICAgICAgIC5jbG9zZXN0KCcuaXRlbScpXG4gICAgICAgICAgICAgICAgICAgIC5maW5kKCcuYnV0dG9uLXJlZnJlc2gnKVxuICAgICAgICAgICAgICAgICAgICAuZmlyc3QoKVxuICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogSGFuZGxlciB0aGF0IGxpc3RlbnMgb24gY2xpY2sgZXZlbnRzIG9uIHRoZVxuICAgICAgICAgKiBidXR0b25zIFwicmVmcmVzaFwiLCBcImRlbGV0ZVwiICYgXCJhZGQgdG8gY2FydFwiLlxuICAgICAgICAgKiBJdCB2YWxpZGF0ZXMgdGhlIGZvcm0gLyByb3cgYW5kIHBhc3NlcyB0aGVcbiAgICAgICAgICogdGhlIGRhdGEgdG8gYW4gc3VibWl0IGV4ZWN1dGUgZnVuY2l0b24gaWYgdmFsaWRcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgIGUgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9jbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICAgICAgdmFyICRzZWxmID0gJCh0aGlzKSxcbiAgICAgICAgICAgICAgICAkcm93ID0gJHNlbGYuY2xvc2VzdCgnLml0ZW0nKSxcbiAgICAgICAgICAgICAgICB0eXBlID0gZS5kYXRhLnR5cGUsXG4gICAgICAgICAgICAgICAgcm93ZGF0YSA9IF9nZW5lcmF0ZUZvcm1kYXRhT2JqZWN0KCRyb3cpWzBdLFxuICAgICAgICAgICAgICAgIGFydGljbGUgPSByb3dkYXRhLnByb2R1Y3RzX2lkWzBdLFxuICAgICAgICAgICAgICAgICR0YXJnZXQgPSByb3dkYXRhLnRhcmdldCxcbiAgICAgICAgICAgICAgICB0aXRsZSA9ICR0YXJnZXQuZmluZCgnLnByb2R1Y3QtdGl0bGUnKS50ZXh0KCk7XG5cbiAgICAgICAgICAgIC8vIEFkZCBsb2FkaW5nIGNsYXNzXG4gICAgICAgICAgICAkcm93LmFkZENsYXNzKCdsb2FkaW5nJyk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZXJlIGlzIG5vIGN1cnJlbnQgcHJvY2VzcyBmb3IgdGhpcyBhcnRpY2xlXG4gICAgICAgICAgICAvLyBvciBpbiBjYXNlIGl0J3Mgbm8gYWpheCBjYWxsIHRoZXJlIGlzIE5PIG90aGVyIHByb2Nlc3NcbiAgICAgICAgICAgIGlmICgkLmlzRW1wdHlPYmplY3QoYWN0aXZlKSB8fCAob3B0aW9ucy5hamF4ICYmICFhY3RpdmVbJ3Byb2R1Y3RfJyArIGFydGljbGVdKSkge1xuICAgICAgICAgICAgICAgIGFjdGl2ZVsncHJvZHVjdF8nICsgYXJ0aWNsZV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIF9zZXRBY3Rpb24odHlwZSk7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnZGVsZXRlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgZm9ybSBhbmQgdGhlIGRhdGFzZXQgd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGFydGljbGUgaWQgdG8gZGVsZXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAkZGVsZXRlRmllbGQudmFsKGFydGljbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcm93ZGF0YVtkZWxldGVGaWVsZE5hbWVdID0gW2FydGljbGVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5jb25maXJtRGVsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlbiBhIG1vZGFsIGxheWVyIHRvIGNvbmZpcm0gdGhlIGRlbGV0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG1vZGFsVGl0bGUgPSBqc2UuY29yZS5sYW5nLnRyYW5zbGF0ZSgnQ0FSVF9XSVNITElTVF9ERUxFVEVfVElUTEUnLCAnZ2VuZXJhbCcpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RhbE1lc3NhZ2UgPSBqc2UuY29yZS5sYW5nLnRyYW5zbGF0ZSgnQ0FSVF9XSVNITElTVF9ERUxFVEUnLCAnZ2VuZXJhbCcpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAganNlLmxpYnMudGhlbWUubW9kYWwuY29uZmlybSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IG1vZGFsTWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU6IG1vZGFsVGl0bGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KS5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmVycmVkID0gJC5EZWZlcnJlZCgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmVycmVkLmRvbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2V4ZWN1dGVBY3Rpb24oJHJvdywgJHRhcmdldCwgcm93ZGF0YSwgYXJ0aWNsZSwgdHlwZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRib2R5LnRyaWdnZXIoanNlLmxpYnMudGhlbWUuZXZlbnRzLldJU0hMSVNUX0NBUlRfREVMRVRFKCksIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGVmZXJyZWQnOiBkZWZlcnJlZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGF0YXNldCc6IHJvd2RhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuZmFpbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGVhbnVwQXJyYXkoYXJ0aWNsZSwgJHJvdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBkZWZlcnJlZCA9ICQuRGVmZXJyZWQoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmVycmVkLmRvbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZXhlY3V0ZUFjdGlvbigkcm93LCAkdGFyZ2V0LCByb3dkYXRhLCBhcnRpY2xlLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRib2R5LnRyaWdnZXIoanNlLmxpYnMudGhlbWUuZXZlbnRzLldJU0hMSVNUX0NBUlRfREVMRVRFKCksIFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2RlZmVycmVkJzogZGVmZXJyZWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGF0YXNldCc6IHJvd2RhdGFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEluIGFsbCBvdGhlciBjYXNlcyBjaGVjayBpZiB0aGUgZm9ybVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaGFzIHZhbGlkIHZhbHVlcyBhbmQgY29udGludWUgd2l0aCB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRvbmUgY2FsbGJhY2sgaWYgdmFsaWRcbiAgICAgICAgICAgICAgICAgICAgICAgIF9jaGVja0Zvcm0oZmFsc2UsIGZhbHNlLCBbJC5leHRlbmQodHJ1ZSwge30sIHJvd2RhdGEpXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVtcHR5IHRoZSBkZWxldGUgaGlkZGVuIGZpZWxkIGluIGNhc2UgaXQgd2FzIHNldCBiZWZvcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGRlbGV0ZUZpZWxkLnZhbCgnJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50ID0gbnVsbDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ2FkZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50ID0ganNlLmxpYnMudGhlbWUuZXZlbnRzLldJU0hMSVNUX1RPX0NBUlQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGRlZmVycmVkID0gJC5EZWZlcnJlZCgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZlcnJlZC5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZXhlY3V0ZUFjdGlvbigkcm93LCAkdGFyZ2V0LCByb3dkYXRhLCBhcnRpY2xlLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkYm9keS50cmlnZ2VyKGV2ZW50LCBbeydkZWZlcnJlZCc6IGRlZmVycmVkLCAnZGF0YXNldCc6IHJvd2RhdGF9XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZXhlY3V0ZUFjdGlvbigkcm93LCAkdGFyZ2V0LCByb3dkYXRhLCBhcnRpY2xlLCB0eXBlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkuZmFpbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsZWFudXBBcnJheShhcnRpY2xlLCAkcm93KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcmV2ZW50IHRoZSBzdWJtaXQgZXZlbnQgdGhhdCB3YXMgdHJpZ2dlcmRcbiAgICAgICAgICogYnkgdXNlciBvciBieSBzY3JpcHQuIElmIGl0IHdhcyB0cmlnZ2VyZWRcbiAgICAgICAgICogYnkgdGhlIHVzZXIsIGNoZWNrIGlmIGl0IHdhcyBhbiBcIkVudGVyXCIta2V5XG4gICAgICAgICAqIHN1Ym1pdCBmcm9tIGFuIGlucHV0IGZpZWxkLiBJZiBzbywgZXhlY3V0ZVxuICAgICAgICAgKiB0aGUgcmVmcmVzaCBmdW5jdGlvbmFsaXR5IGZvciB0aGF0IHJvdy5cbiAgICAgICAgICogSWYgdGhlIGV2ZW50IHdhcyB0cmlnZ2VyZWQgYnkgdGhlIHNjcmlwdFxuICAgICAgICAgKiAoaWRlbnRpZmllZCBieSB0aGUgZGF0YSBmbGFnIFwiZFwiKSBjaGVjayB0aGVcbiAgICAgICAgICogd2hvbGUgZm9ybSBmb3IgZXJyb3JzLiBPbmx5IGluIGNhc2Ugb2YgdmFsaWRcbiAgICAgICAgICogZGF0YSBwcm9jZWVkIHRoZSBzdWJtaXRcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgICAgICBlICAgICAgIGpRdWVyeSBldmVudCBvYmplY3RcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtib29sZWFufSAgICAgICBkICAgICAgIEEgZmxhZyB0aGF0IGlkZW50aWZpZXMgdGhhdCB0aGUgc3VibWl0IHdhcyB0cmlnZ2VyZWQgYnkgdGhpcyBzY3JpcHRcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfc3VibWl0SGFuZGxlciA9IGZ1bmN0aW9uIChlLCBkKSB7XG5cbiAgICAgICAgICAgIC8vIFByZXZlbnQgdGhlIGRlZmF1bHQgYmVoYXZpb3VyXG4gICAgICAgICAgICAvLyBpbiBib3RoIGNhc2VzXG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgICAgICBpZiAoIWQgJiYgZS5vcmlnaW5hbEV2ZW50KSB7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBhbiBpbnB1dCBmaWVsZCBoYXMgdHJpZ2dlcmQgdGhlIHN1Ym1pdCBldmVudFxuICAgICAgICAgICAgICAgIC8vIGFuZCBjYWxsIHRoZSByZWZyZXNoIGhhbmRsZXJcbiAgICAgICAgICAgICAgICB2YXIgJHNvdXJjZSA9ICQoZS5vcmlnaW5hbEV2ZW50LmV4cGxpY2l0T3JpZ2luYWxUYXJnZXQpO1xuICAgICAgICAgICAgICAgIGlmICgkc291cmNlLmxlbmd0aCAmJiAkc291cmNlLmlzKCdpbnB1dFt0eXBlPVwidGV4dFwiXScpKSB7XG4gICAgICAgICAgICAgICAgICAgICRzb3VyY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jbG9zZXN0KCcuaXRlbScpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgnLmJ1dHRvbi1yZWZyZXNoJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5maXJzdCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZCkge1xuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHdob2xlIGZvcm0gYW5kIG9ubHkgc3VibWl0XG4gICAgICAgICAgICAgICAgLy8gaXQgaWYgaXQncyB2YWxpZFxuICAgICAgICAgICAgICAgIF9jaGVja0Zvcm0oKS5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSBzdWJtaXQgZXZlbnQgaGFuZGxlclxuICAgICAgICAgICAgICAgICAgICAvLyBvbiBhIHN1Y2Nlc3NmdWwgdmFsaWRhdGlvbiBhbmRcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJpZ2dlciBhIHN1Ym1pdCBhZ2Fpbiwgc28gdGhhdCB0aGVcbiAgICAgICAgICAgICAgICAgICAgLy8gYnJvd3NlciBleGVjdXRlcyBpdCdzIGRlZmF1bHQgYmVoYXZpb3JcbiAgICAgICAgICAgICAgICAgICAgJGZvcm1cbiAgICAgICAgICAgICAgICAgICAgICAgIC5vZmYoJ3N1Ym1pdCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcignc3VibWl0Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSB0aGUgZGVmZXJyZWQgaWYgZ2l2ZW5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZC5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5mYWlsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVqZWN0IHRoZSBkZWZlcnJlZCBpZiBnaXZlblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkLnJlamVjdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRXZlbnQgaGFuZGxlciBmb3IgY2xpY2tpbmcgb24gdGhlIHByb2NlZWRcbiAgICAgICAgICogYnV0dG9uIHRvIGdldCB0byB0aGUgY2hlY2tvdXQgcHJvY2Vzcy4gSXRcbiAgICAgICAgICogY2hlY2tzIGFsbCBpdGVtcyBhZ2FpbiBpZiB0aGV5IGNvbnRhaW4gdmFsaWRcbiAgICAgICAgICogZGF0YS4gT25seSBpZiBzbywgcHJvY2VlZFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgICAgIGUgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9zdWJtaXRCdXR0b25IYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgICAgIGlmIChpc0NoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIGNvbXBsZXRlIGZvcm0gZGF0YSBpZiBubyByb3cgZGF0YSBpcyBnaXZlblxuICAgICAgICAgICAgICAgIHZhciBmb3JtZGF0YSA9IF9nZW5lcmF0ZUZvcm1kYXRhT2JqZWN0KCk7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayB0aGUgZm9ybWRhdGEgZm9yIGNoYW5nZWQgdmFsdWVzXG4gICAgICAgICAgICAgICAgJC5lYWNoKGZvcm1kYXRhLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkY2hhbmdlZElucHV0ID0gdGhpcy50YXJnZXQuZmluZCgnLicgKyBvcHRpb25zLmNoYW5nZUNsYXNzKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoJGNoYW5nZWRJbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGNoYW5nZWRJbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5jbG9zZXN0KCcuaXRlbScpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmQoJy5idXR0b24tcmVmcmVzaCcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZpcnN0KClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcignY2xpY2snKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgaXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgX3VwZGF0ZUNoYW5nZVN0YXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgIGRlc3RpbmF0aW9uID0gJHNlbGYuYXR0cignaHJlZicpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGVyZSBpcyBhbnkgb3RoZXIgcHJvY2VzcyBydW5uaW5nXG4gICAgICAgICAgICBpZiAoJC5pc0VtcHR5T2JqZWN0KGFjdGl2ZSkgJiYgIWJ1c3kgJiYgIXVwZGF0ZUxpc3QpIHtcbiAgICAgICAgICAgICAgICBidXN5ID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIF9jaGVja0Zvcm0odHJ1ZSwgdHJ1ZSkuZG9uZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGNhbGxiYWNrKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9IGRlc3RpbmF0aW9uO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAganNlLmxpYnMuaG9va3MuZXhlY3V0ZShqc2UubGlicy5ob29rcy5rZXlzLnNob3AuY2FydC5jaGVja291dCwge2V2ZW50OiBlfSwgNTAwKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oY2FsbGJhY2spXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH0pLmFsd2F5cyhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIGJ1c3kgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRXZlbnQgaGFuZGxlciB0aGF0IGNoZWNrcyB0aGUgZm9ybSBhbmRcbiAgICAgICAgICogcmVzb2x2ZXMgb3IgcmVqZWN0cyB0aGUgZGVsaXZlcmVkIGRlZmVycmVkXG4gICAgICAgICAqIChVc2VkIGZvciBleHRlcm5hbCBwYXltZW50IG1vZHVsZXMgdG9cbiAgICAgICAgICogY2hlY2sgaWYgdGhlIGZvcm0gaXMgdmFsaWQpXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICBlICAgICAgICAgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgZCAgICAgICAgICAgICAgIEpTT04gb2JqZWN0IHdpdGggdGhlIGV2ZW50IHNldHRpbmdzXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX2NoZWNrRm9ybUhhbmRsZXIgPSBmdW5jdGlvbiAoZSwgZCkge1xuICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICAgICAgZCA9IGQgfHwge307XG5cbiAgICAgICAgICAgIF9jaGVja0Zvcm0oZC5zaG93Q2hhbmdlcywgZC5yZXZlcnRDaGFuZ2VzKS5kb25lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoZC5kZWZlcnJlZCkge1xuICAgICAgICAgICAgICAgICAgICBkLmRlZmVycmVkLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5mYWlsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoZC5kZWZlcnJlZCkge1xuICAgICAgICAgICAgICAgICAgICBkLmRlZmVycmVkLnJlamVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBGdW5jdGlvbiB0aGF0IHVwZGF0ZXMgdGhlIGxpc3Qgb24gZm9jdXMgb2ZcbiAgICAgICAgICogdGhlIHdpbmRvd1xuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF91cGRhdGVMaXN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdXBkYXRlTGlzdCA9IHRydWU7XG4gICAgICAgICAgICBqc2UubGlicy54aHIuYWpheCh7dXJsOiBvcHRpb25zLnVwZGF0ZVVybH0sIHRydWUpLmRvbmUoZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgIC8vIEluaXQgd2l0aCBoZSBmaXJzdCBsaW5lIHNpbmNlIHRoaXMgaXN0IHRoZSBoZWFkaW5nXG4gICAgICAgICAgICAgICAgdmFyICRsYXN0U2Nhbm5lZCA9ICRmb3JtLmZpbmQoJy5vcmRlci13aXNobGlzdCAuaXRlbScpLmZpcnN0KCksXG4gICAgICAgICAgICAgICAgICAgICR0YXJnZXQgPSAkKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggdGhlIHByb2R1Y3RzIG9iamVjdCBhbmQgc2VhcmNoIGZvciB0aGVcbiAgICAgICAgICAgICAgICAvLyBwcm9kdWN0cyBpbnNpZGUgdGhlIG1hcmt1cC4gSWYgdGhlIHByb2R1Y3Qgd2FzIGZvdW5kLFxuICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgdmFsdWVzLCBpZiBub3QgYWRkIHRoZSBwcm9kdWN0IHJvdyBhdCB0aGVcbiAgICAgICAgICAgICAgICAvLyBjb3JyZWN0IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgJC5lYWNoKHJlc3VsdC5wcm9kdWN0cywgZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFydGljbGVJZCA9IGtleS5yZXBsYWNlKCdwcm9kdWN0XycsICcnKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICRhcnRpY2xlID0gJGZvcm0uZmluZCgnaW5wdXRbbmFtZT1cInByb2R1Y3RzX2lkW11cIl1bdmFsdWU9XCInICsgYXJ0aWNsZUlkICsgJ1wiXScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgJHJvdyA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkYXJ0aWNsZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBhcnRpY2xlIHdhc24ndCBmb3VuZCBvbiBwYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAtPiBhZGQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICRyb3cgPSAkKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRyb3cuaW5zZXJ0QWZ0ZXIoJGxhc3RTY2FubmVkKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBhcnRpY2xlIHdhcyBmb3VuZCBvbiBwYWdlXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAtPiB1cGRhdGUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICRyb3cgPSAkYXJ0aWNsZS5jbG9zZXN0KCcuaXRlbScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgJHF0eSA9ICRyb3cuZmluZCgnaW5wdXRbbmFtZT1cImNhcnRfcXVhbnRpdHlbXVwiXScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZFF0eSA9IHBhcnNlRmxvYXQoJHF0eS5kYXRhKCkub2xkVmFsdWUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRRdHkgPSBwYXJzZUZsb2F0KCRxdHkudmFsKCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1F0eSA9IHBhcnNlRmxvYXQoJCh2YWx1ZSkuZmluZCgnaW5wdXRbbmFtZT1cImNhcnRfcXVhbnRpdHlbXVwiXScpLnZhbCgpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgJHF0eS5kYXRhKCdvbGRWYWx1ZScsIG5ld1F0eSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBvciByZW1vdmUgdGhlIGNoYW5nZWQgY2xhc3NlcyBkZXBlbmRpbmcgb25cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBxdWFudGl0eSBjaGFuZ2VzIGFuZCB0aGUgb24gcGFnZSBzdG9yZWQgdmFsdWVzXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob2xkUXR5ID09PSBjdXJyZW50UXR5ICYmIGN1cnJlbnRRdHkgIT09IG5ld1F0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRxdHkuYWRkQ2xhc3Mob3B0aW9ucy5jaGFuZ2VDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9sZFF0eSAhPT0gY3VycmVudFF0eSAmJiBjdXJyZW50UXR5ID09PSBuZXdRdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkcXR5LnJlbW92ZUNsYXNzKG9wdGlvbnMuY2hhbmdlQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgJHRhcmdldC5hZGQoJHJvdyk7XG4gICAgICAgICAgICAgICAgICAgICRsYXN0U2Nhbm5lZCA9ICRyb3c7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJlc3Qgb2YgdGhlIGZvcm1cbiAgICAgICAgICAgICAgICBfdXBkYXRlRm9ybSgkdGFyZ2V0LCByZXN1bHQpO1xuICAgICAgICAgICAgfSkuYWx3YXlzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB1cGRhdGVMaXN0ID0gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVXBkYXRlIHRoZSBpbnB1dCBjaGFuZ2Ugc3RhdGVcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdXBkYXRlQ2hhbmdlU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkZm9ybVxuICAgICAgICAgICAgICAgIC5maW5kKG9wdGlvbnMuc2VsZWN0b3JNYXBwaW5nLnN1Ym1pdClcbiAgICAgICAgICAgICAgICAudGV4dChqc2UuY29yZS5sYW5nLnRyYW5zbGF0ZShpc0NoYW5nZWQgPyAncmVmcmVzaCcgOiAnY2hlY2tvdXQnLCAnYnV0dG9ucycpKVxuICAgICAgICB9O1xuXG5cbi8vICMjIyMjIyMjIyMgSU5JVElBTElaQVRJT04gIyMjIyMjIyMjI1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbml0IGZ1bmN0aW9uIG9mIHRoZSB3aWRnZXRcbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqL1xuICAgICAgICBtb2R1bGUuaW5pdCA9IGZ1bmN0aW9uIChkb25lKSB7XG5cbiAgICAgICAgICAgICR1cGRhdGVUYXJnZXQgPSAkKG9wdGlvbnMudXBkYXRlVGFyZ2V0KTtcbiAgICAgICAgICAgICRjYXJ0RW1wdHkgPSAkKG9wdGlvbnMuY2FydEVtcHR5KTtcbiAgICAgICAgICAgICRjYXJ0Tm90RW1wdHkgPSAkKG9wdGlvbnMuY2FydE5vdEVtcHR5KTtcbiAgICAgICAgICAgICRkZWxldGVGaWVsZCA9ICQob3B0aW9ucy5kZWxldGVJbnB1dCk7XG4gICAgICAgICAgICAkZm9ybSA9ICR0aGlzLmZpbmQoJ2Zvcm0nKS5maXJzdCgpO1xuICAgICAgICAgICAgZGVsZXRlRmllbGROYW1lID0gJGRlbGV0ZUZpZWxkLmF0dHIoJ25hbWUnKTtcbiAgICAgICAgICAgIGFjdGlvbiA9ICRmb3JtLmF0dHIoJ2FjdGlvbicpO1xuICAgICAgICAgICAgdHJhbnNpdGlvbiA9IHtvcGVuOiB0cnVlLCBjbGFzc09wZW46IG9wdGlvbnMuY2xhc3NMb2FkaW5nfTtcblxuICAgICAgICAgICAgLy8gU2V0cyB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgaW5wdXRcbiAgICAgICAgICAgIC8vIHRvIGFuIGhpZGRlbiBkYXRhIGF0dHJpYnV0ZVxuICAgICAgICAgICAgX3VwZGF0ZURhdGFWYWx1ZXMoJGZvcm0pO1xuXG4gICAgICAgICAgICAkZm9ybVxuXHRcdFx0XHQub24oJ2lucHV0JywgJ2lucHV0W3R5cGU9XCJ0ZXh0XCJdOm5vdCguZ2lmdC1jb3Vwb24tY29kZS1pbnB1dCknLCBfaW5wdXRIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignYmx1cicsICdpbnB1dFt0eXBlPVwidGV4dFwiXTpub3QoLmdpZnQtY291cG9uLWNvZGUtaW5wdXQpJywgX2JsdXJIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignY2xpY2suZGVsZXRlJywgJy5idXR0b24tZGVsZXRlJywgeyd0eXBlJzogJ2RlbGV0ZSd9LCBfY2xpY2tIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignY2xpY2sucmVmcmVzaCcsICcuYnV0dG9uLXJlZnJlc2gnLCB7J3R5cGUnOiAncmVmcmVzaCd9LCBfY2xpY2tIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignY2xpY2suYWRkdG9jYXJ0JywgJy5idXR0b24tdG8tY2FydCcsIHsndHlwZSc6ICdhZGQnfSwgX2NsaWNrSGFuZGxlcilcbiAgICAgICAgICAgICAgICAub24oJ2NsaWNrLnN1Ym1pdCcsICcuYnV0dG9uLXN1Ym1pdCcsIHsndHlwZSc6ICdzdWJtaXQnfSwgX3N1Ym1pdEJ1dHRvbkhhbmRsZXIpXG4gICAgICAgICAgICAgICAgLm9uKCdzdWJtaXQnLCBfc3VibWl0SGFuZGxlcilcbiAgICAgICAgICAgICAgICAub24oanNlLmxpYnMudGhlbWUuZXZlbnRzLkNIRUNLX0NBUlQoKSwgX2NoZWNrRm9ybUhhbmRsZXIpO1xuXG4gICAgICAgICAgICAkKCdhLnRvZ2dsZXVzZWJhbGFuY2UgaW5wdXRbbmFtZT1cImd2X3VzZV9iYWxhbmNlXCJdJykub24oJ2NsaWNrJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBcdGNvbnNvbGUuaW5mbygnY2xpY2snKTsgbG9jYXRpb24gPSAkKHRoaXMpLnBhcmVudCgnYScpLmdldCgwKS5ocmVmO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm4gZGF0YSB0byB3aWRnZXQgZW5naW5lXG4gICAgICAgIHJldHVybiBtb2R1bGU7XG4gICAgfSk7XG4iXX0=

Youez - 2016 - github.com/yon3zu
LinuXploit