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_preview/javascripts/system/widgets/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

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

/* --------------------------------------------------------------
 menu.js 2018-02-01
 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]
 --------------------------------------------------------------
 */

/**
 * This widget handles the horizontal menu/dropdown functionality.
 *
 * It's used for the top category navigation, the cart dropdown or the top menu (for example). It is
 * able to re-order the menu entries to a special "More" submenu to save space if the entries don't
 * fit in the current view. It's also able to work with different event types for opening/closing menu
 * items in the different view types.
 */
gambio.widgets.module('menu', [gambio.source + '/libs/events', gambio.source + '/libs/responsive', gambio.source + '/libs/interaction'], function (data) {

    'use strict';

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

    var $this = $(this),
        $window = $(window),
        $body = $('body'),
        $list = null,
        $entries = null,
        $more = null,
        $moreEntries = null,
        $menuEntries = null,
        $custom = null,
        $categories = null,
        touchEvents = null,
        currentWidth = null,
        mode = null,
        mobile = false,
        enterTimer = null,
        leaveTimer = null,
        initializedPos = false,
        onEnter = false,
        toucheStartEvent = null,
        toucheEndEvent = null,
        transition = {},
        isTouchDevice = Modernizr.touchevents || navigator.userAgent.search(/Touch/i) !== -1,
        defaults = {
        // The menu type must be either 'horizontal' or 'vertical'
        menuType: 'horizontal',

        // Vertical menu options.
        unfoldLevel: 0,
        accordion: false,
        showAllLink: false,

        // Minimum breakpoint to switch to mobile view
        breakpoint: 40,
        // Delay in ms after a mouseenter the element gets shown
        enterDelay: 0,
        // Delay in ms after a mouseleave an element gets hidden
        leaveDelay: 50,
        // Tolerance in px which gets substracted from the nav-width to prevent flickering
        widthTolerance: 10,
        // Class that gets added to an opened menu list item
        openClass: 'open',
        // If true, elements get moved from/to the more menu if there isn't enough space
        switchElementPosition: true,
        // Ignore menu functionality on elements inside this selection
        ignoreClass: 'ignore-menu',
        // Tolerance in px which is allowed for a "click" event on touch
        touchMoveTolerance: 10,
        // If true, the li with the active class gets opened
        openActive: false,
        events: {
            // Event types that open the menus in desktop view.
            // Possible values: ['click']; ['hover']; ['touch', 'hover']; ['click', 'hover']
            desktop: ['touch', 'hover'],
            // Event types that open the menus in mobile view.
            // Possible values: ['click']; ['hover']; ['touch', 'hover']; ['click', 'hover']; ['touch', 'click']
            mobile: ['touch', 'click']
        }
    },
        options = $.extend({}, defaults, data),
        module = {};

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

    /**
     * Helper function to calculate the tolerance
     * between the touchstart and touchend event.
     * If the max tolarance is exceeded return true
     * @param       {object}        e       jQuery event object
     * @return     {boolean}               If true it is a move event
     * @private
     */
    var _touchMoveDetect = function _touchMoveDetect() {
        toucheEndEvent = toucheEndEvent || toucheStartEvent;
        var diff = Math.abs(toucheEndEvent.event.originalEvent.pageY - toucheStartEvent.event.originalEvent.pageY);
        toucheEndEvent = null;
        return diff > options.touchMoveTolerance;
    };

    /**
     * Updates the jQuery selection, because the
     * list elements can be moved
     *
     * @private
     */
    var _getSelections = function _getSelections() {
        $list = $this.children('ul');
        // Exclude the ".navbar-topbar-item" elements because they
        // are cloned to this menu and are only shown in mobile view
        $entries = $list.children().not('.navbar-topbar-item');
        $more = $entries.filter('.dropdown-more');
        $moreEntries = $more.children('ul');
        $custom = $entries.filter('.custom');
        $menuEntries = $entries.not($more);
        $categories = $menuEntries.not($custom);
    };

    /**
     * Helper function that detaches an element from the
     * menu and attaches it to the correct position at
     * the target
     * @param       {object}    $item       jQuery selection of the item that gets detached / attached
     * @param       {object}    $target     jQuery selection of the target container
     * @private
     */
    var _setItem = function _setItem($item, $target) {
        var positionId = $item.data('position'),
            done = false;

        // Look for the first item that has a higher
        // positionId that the item and insert it
        // before the found entry
        $target.children().each(function () {
            var $self = $(this),
                position = $self.data('position');

            if (position > positionId) {
                $self.before($item.detach());
                done = true;
                return false;
            }
        });

        // Append the item if the positionId has
        // a higher value as the last item int the
        // target
        if (!done) {
            $target.append($item);
        }
    };

    /**
     * Helper function that checks which elements needs
     * to be added to the menu. Every element that needs
     * to be added gets passed to the function
     * "_setItem"
     * @param       {integer}       diff        Amount of pixels that were free
     * @private
     */
    var _addElement = function _addElement(diff) {

        var done = false;

        /**
         * Helper function that loops through the elements
         * and tries to add the elements to the menu if
         * it would fit.
         * @param       {object}    $elements       jQuery selection of the entries inside the more-menu
         * @private
         */
        var _showElements = function _showElements($elements) {
            $elements.each(function () {
                var $self = $(this),
                    width = $self.data().width;

                if (diff > width) {
                    // Add the item to the menu
                    _setItem($self, $list);
                    diff -= width;
                } else {
                    // The next item wouldn't fit anymore',
                    // quit the loop
                    done = true;
                    return false;
                }
            });
        };

        // Update the selection of the visible menu items.
        _getSelections();

        // Add the content manager entries to the menu first.
        // If there is still space, add the "normal" category
        // items also
        _showElements($moreEntries.children('.custom'));
        if (!done) {
            _showElements($moreEntries.children());
        }

        // Check if the items still in the more menu
        // would fit inside the main menu if the more
        // menu would get hidden
        var width = 0;
        $moreEntries.children().each(function () {
            width += $(this).data().width;
        });

        if (width === 0) {
            $more.hide();
        } else if (width < $more.data().width + diff) {
            $more.hide();
            diff += $more.data().width;
            _showElements($moreEntries.children());
        }
    };

    /**
     * Helper function that checks which elements needs
     * to be removed from the menu, so that it fits
     * inside one menu line. Every element that needs
     * to be removed gets passed to the function
     * "_setItem"
     * @param       {integer}       diff        Amount of pixels that needs to be saved
     * @private
     */
    var _removeElement = function _removeElement(diff) {

        var done = false;

        /**
         * Helper function that contains the check
         * loop for determining which elements
         * needs to be removed
         * @param           {object}    $elements       jQuery selection of the menu items
         * @private
         */
        var _hideElements = function _hideElements($elements) {
            $elements.each(function () {
                var $self = $(this),
                    width = $self.data().width;

                // Remove the possibly set open state
                $self.filter('.' + options.openClass).add($self.find('.' + options.openClass)).removeClass(options.openClass);

                // Add the entry to the more-menu
                _setItem($self, $moreEntries);

                diff -= width;

                if (diff < 0) {
                    // Enough elements are removed,
                    // quit the loop
                    done = true;
                    return false;
                }
            });
        };

        // Update the selection of the visible menu items
        _getSelections();

        // Add the width of the more entry if it's not
        // visible, because it will get shown during this
        // function call
        if ($more.is(':hidden')) {
            diff += $more.data().width;
            $more.removeClass('style');
            $more.show();
        }

        // First remove "normal" category entries. If that
        // isn't enough remove the content manager entries also
        _hideElements($($categories.get().reverse()));
        if (!done) {
            _hideElements($($custom.get().reverse()));
        }
    };

    /**
     * Sets a data attribute to the menu items
     * that contains the width of the elements.
     * This is needed because if it is display
     * none the detected with will be zero. It
     * sets position id also.
     * @private
     */
    var _initElementSizesAndPosition = function _initElementSizesAndPosition() {
        $entries.each(function (i) {
            var $self = $(this),
                width = $self.outerWidth();

            $self.data({ width: width, position: i });
        });
    };

    /**
     * Helper function to close all menu entries.
     * Needed for the desktop <-> mobile view
     * change, mostly.
     * @private
     */
    var _closeMenu = function _closeMenu() {
        $this.find('li.' + options.openClass).each(function () {
            if ($(this).parents('.navbar-categories-left').length > 0) {
                return true;
            }
            $(this).removeClass(options.openClass);
        });
    };

    /**
     * Helper function to clear all pending
     * functions
     * @private
     */
    var _clearTimeouts = function _clearTimeouts() {
        enterTimer = enterTimer ? clearTimeout(enterTimer) : null;
        leaveTimer = leaveTimer ? clearTimeout(leaveTimer) : null;
    };

    /**
     * Helper function to reset the css of the menu.
     * This is needed to remove the overflow & height
     * settings of the menu of the css file. The
     * directives were set to prevent flickering on page
     * load
     * @private
     */
    var _resetInitialCss = function _resetInitialCss() {
        $this.css({
            'overflow': 'visible'
        });
    };

    /**
     * Helper function to set positioning classes
     * to the opend flyout. This is needed to keep
     * the flyout inside the boundaries of the navigation
     * @private
     */
    var _repositionOpenLayer = function _repositionOpenLayer() {
        var listWidth = $list.width(),
            $openLayer = $entries.filter('.' + options.openClass).children('ul');

        $openLayer.each(function () {
            var $self = $(this),
                $parent = $self.parent();

            // Reset the classes to prevent wrong calculation due to special styles
            $parent.removeClass('flyout-right flyout-left flyout-center flyout-wont-fit');

            var width = $self.outerWidth(),
                parentPosition = $parent.position().left,
                parentWidth = $parent.outerWidth();

            // Check witch class needs to be set
            if (listWidth > parentPosition + width) {
                $parent.addClass('flyout-right');
            } else if (parentPosition + parentWidth - width > 0) {
                $parent.addClass('flyout-left');
            } else if (width < listWidth) {
                $parent.addClass('flyout-center');
            } else {
                $parent.addClass('flyout-wont-fit');
            }
        });
    };

    /**
     * Helper function to calculate the difference between
     * the size of the visible elements in the menu and the
     * container size. If there is space, it calls the function
     * to activate an menu entry else it calls the function to
     * deactivate a menu entry
     * @param       {object}    e         jQuery event object
     * @param       {string}    eventName Event name parameter of the event object
     * @private
     */
    var _updateCategoryMenu = function _updateCategoryMenu(e, eventName) {
        var containerWidth = $this.innerWidth() - options.widthTolerance,
            width = 0;

        // Check if the container width has changed since last call
        if (options.menuType === 'horizontal' && (currentWidth !== containerWidth || eventName === 'switchedToDesktop')) {

            $list.children(':visible').each(function () {
                width += $(this).data('width');
            });

            // Add or remove elements depending on the size of the
            // visible elements
            if (containerWidth < width) {
                _removeElement(width - containerWidth);
            } else {
                _addElement(containerWidth - width);
            }

            _repositionOpenLayer();

            currentWidth = containerWidth;
        }
    };

    /**
     * Helper function to switch to the mobile
     * mode of the menu.
     * @private
     */
    var _switchToMobileView = function _switchToMobileView() {
        // Reset the current width so that
        // the "_updateCategoryMenu" will
        // perform correctly on the next view
        // change to desktop
        currentWidth = -1;
        _addElement(99999999);

        $('.level-1').css('padding-bottom', '200px'); // This padding corrects expand/collapse behavior of lower menu items in various mobile browsers. 

        // Use the vertical menu on mobile view.
        if (options.menuType === 'vertical') {
            // fixes display horizontal menu after a switch to mobile and back to desktop is performed
            if ($('#categories nav.navbar-default:first').not('.nav-categories-left').length > 0) {
                $('#categories nav.navbar-default:first').css({
                    opacity: 0,
                    height: 0
                }).children().hide();
            }

            // move topmenu-content items from horizontal menu to vertical menu
            $this.find('ul.level-1 li.navbar-topbar-item:first').before($('#categories nav.navbar-default li.topmenu-content').detach());

            $this.appendTo('#categories > .navbar-collapse');
            $this.addClass('navbar-default navbar-categories');
            $this.find('ul.level-1').addClass('navbar-nav');
            $this.find('.navbar-topbar-item').not('.topbar-search').show();

            _bindHorizontalEventHandlers();

            $body.trigger(jse.libs.theme.events.MENU_REPOSITIONED(), ['switchedToMobile']);
        }
    };

    /**
     * Helper function to switch to the desktop
     * mode of the menu. Additionally, in case that
     * the desktop mode is shown for the first time
     * set the position and width of the elements
     * @private
     */
    var _switchToDesktopView = function _switchToDesktopView() {
        $('.level-1').css('padding-bottom', ''); // Reset display fix for mobile browsers.

        // Revert all the changes made during the switch to mobile.
        if (options.menuType === 'vertical') {
            // fixes display horizontal menu after a switch to mobile and back to desktop is performed
            if ($('#categories nav.navbar-default:first').not('.nav-categories-left').length > 0) {
                $('#categories nav.navbar-default:first').css({
                    opacity: 1,
                    height: 'auto'
                }).children().show();
            }

            // move topmenu-content items back to horizontal menu
            var $topmenuContentElements = $this.find('li.topmenu-content').detach();
            $('#categories nav.navbar-default ul.level-1:first').append($topmenuContentElements);

            $this.appendTo('.box-categories');
            $this.removeClass('navbar-default navbar-categories');
            $this.find('ul.level-1').removeClass('navbar-nav');
            $this.find('.navbar-topbar-item').hide();
            _unbindHorizontalEventHandlers();

            $body.trigger(jse.libs.theme.events.MENU_REPOSITIONED(), ['switchedToDesktop']);
        }

        if (!initializedPos) {
            _initElementSizesAndPosition();
            initializedPos = true;
        }

        if (options.menuType === 'horizontal') {
            _updateCategoryMenu();

            if (isTouchDevice) {
                $list.find('.enter-category').show();
                $list.find('.dropdown > a').click(function (e) {
                    e.preventDefault();
                });
            }
        }
    };

    /**
     * Helper function to add the class to the li-element
     * depending on the open event. This can be a "touch"
     * or a "mouse" class
     * @param       {object}    $target         jQuery selection of the li-element
     * @param       {string}    className       Name of the class that gets added
     * @private
     */
    var _setEventTypeClass = function _setEventTypeClass($target, className) {
        $target.removeClass('touch mouse').addClass(className || '');
    };

    // ########## MAIN FUNCTIONALITY ##########

    /**
     * Function that gets called by the breakpoint trigger
     * (which is fired on browser resize). It checks for
     * CSS view changes and reconfigures the the JS behaviour
     * of the menu in that case
     * @private
     */
    var _breakpointHandler = function _breakpointHandler() {

        // Get the current viewmode
        var oldMode = mode || {},
            newMode = jse.libs.theme.responsive.breakpoint();

        // Only do something if the view was changed
        if (newMode.id !== oldMode.id) {

            // Check if a view change between mobile and desktop view was made
            var switchToMobile = newMode.id <= options.breakpoint && (!mobile || oldMode.id === undefined),
                switchToDesktop = newMode.id > options.breakpoint && (mobile || oldMode.id === undefined);

            // Store the new view settings
            mobile = newMode.id <= options.breakpoint;
            mode = $.extend({}, newMode);

            if (switchToMobile || switchToDesktop) {
                _clearTimeouts();
                if (options.menuType !== 'vertical') {
                    _closeMenu();
                }

                // Change the visibility of the menu items
                // in case of desktop <-> mobile view change
                if (options.switchElementPosition) {
                    if (switchToMobile) {
                        _switchToMobileView();
                    } else {
                        _switchToDesktopView();
                    }
                } else {
                    _repositionOpenLayer();
                }
            } else if (!mobile && options.switchElementPosition) {
                // Update the visibility of the menu items
                // if the view change was desktop to desktop only
                _updateCategoryMenu();
            } else if (!mobile) {
                _repositionOpenLayer();
            }
        }
    };

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

    /**
     * Changes the epand / collapse state of the menu,
     * if there is an submenu. In the other case it
     * will let execute the default action (most times
     * the execution of a link)
     * @param {object}  e       jQuery event object
     * @param {string}  mode    The current view mode (can be "mobile" or "desktop"
     * @param {integer} delay   Custom delay (in ms) for opening closing the menu (needed for click / touch events)
     * @private
     */
    var _openMenu = function _openMenu(e, type, delay) {

        var $self = $(this),
            $submenu = $self.children('ul'),
            length = $submenu.length,
            level = $submenu.length ? $submenu.data('level') || '0' : 99,
            validSubmenu = parseInt(level, 10) <= 2 && mode.id > options.breakpoint || mode.id <= options.breakpoint;

        if (type === 'mobile') {
            e.stopPropagation();
        }

        // Only change the state if there is
        // a submenu
        if (length && validSubmenu) {
            e.preventDefault();

            if (type === 'mobile') {
                // Simply toggle the openClass in mobile mode
                $self.toggleClass(options.openClass);
            } else {
                // Perform the else case for the desktop view

                var visible = $self.hasClass(options.openClass),
                    leave = $self.hasClass('leave'),
                    action = e.data && e.data.action ? e.data.action : visible && leave ? 'enter' : visible ? 'leave' : 'enter';

                // Depending on the visibility and the event-action-parameter
                // the submenu gets opened or closed
                switch (action) {
                    case 'enter':
                        if (!onEnter && !jse.libs.theme.interaction.isMouseDown()) {
                            onEnter = true;
                            // Set a timer for opening if the submenu (delayed opening)
                            _clearTimeouts();
                            enterTimer = setTimeout(function () {

                                // Remove all openClass-classes from the
                                // menu except the element to open and it's parents
                                $list.find('.' + options.openClass).not($self).not($self.parentsUntil($this, '.' + options.openClass)).trigger(jse.libs.theme.events.TRANSITION_STOP(), []).removeClass(options.openClass);

                                $list.find('.leave').trigger(jse.libs.theme.events.TRANSITION_STOP(), []).removeClass('leave');

                                // Open the submenu
                                transition.open = true;

                                // Set and unset the "onEnter" to prevent
                                // closing the menu immediately after opening if
                                // the cursor is at an place over the opening menu
                                // (this can happen if other components trigger the
                                // open event)
                                $self.off(jse.libs.theme.events.TRANSITION_FINISHED()).one(jse.libs.theme.events.TRANSITION_FINISHED(), function () {
                                    onEnter = false;
                                }).trigger(jse.libs.theme.events.TRANSITION(), transition).trigger(jse.libs.theme.events.OPEN_FLYOUT(), [$this]);

                                _repositionOpenLayer();
                            }, typeof delay === 'number' ? delay : options.enterDelay);
                        }

                        break;
                    case 'leave':
                        onEnter = false;
                        // Set a timer for closing if the submenu (delayed closing)
                        _clearTimeouts();
                        $self.addClass('leave');
                        leaveTimer = setTimeout(function () {
                            // Remove all openClass-classes from the
                            // menu except the elements parents
                            transition.open = false;
                            $list.find('.' + options.openClass).not($self.parentsUntil($this, '.' + options.openClass)).off(jse.libs.theme.events.TRANSITION_FINISHED()).one(jse.libs.theme.events.TRANSITION_FINISHED(), function () {
                                _setEventTypeClass($self, '');
                                $self.removeClass('leave');
                            }).trigger(jse.libs.theme.events.TRANSITION(), transition);
                        }, typeof delay === 'number' ? delay : options.leaveDelay);
                        break;
                    default:
                        break;
                }
            }
        }
    };

    /**
     * Event handler for the click / mouseenter / mouseleave event
     * on the navigation li elements. It checks if the event type
     * is supported for the current view type and calls the
     * openMenu-function if so.
     * @param       {object}    e           jQuery event object
     * @private
     */
    var _mouseHandler = function _mouseHandler(e) {
        var $self = $(this),
            viewport = mode.id <= options.breakpoint ? 'mobile' : 'desktop',
            events = options.events && options.events[viewport] ? options.events[viewport] : [];

        _setEventTypeClass($self, 'mouse');
        if ($.inArray(e.data.event, events) > -1) {
            _openMenu.call($self, e, viewport, e.data.delay);
        }

        // Perform navigation for custom links and category links on touch devices if no subcategories are found.
        if (($self.hasClass('custom') || isTouchDevice && $self.children('ul').length == 0) && e.data.event === 'click' && !$self.find('form').length) {
            e.preventDefault();
            e.stopPropagation();

            if ($self.find('a').attr('target') === '_blank') {
                window.open($self.find('a').attr('href'));
            } else {
                location.href = $self.find('a').attr('href');
            }
        }
    };

    /**
     * Event handler for the touchstart event (or "pointerdown"
     * depending on the browser). It removes the other critical
     * event handler (that would open the menu) from the list
     * element if the the mouseenter was executed before and
     * a click or touch event will be performed afterwards. This
     * is needed to prevent the browser engine workarounds which
     * will automatically perform mouse / click-events on touch
     * also.
     * @private
     */
    var _touchHandler = function _touchHandler(e) {
        e.stopPropagation();

        var $self = $(this),
            viewport = mode.id <= options.breakpoint ? 'mobile' : 'desktop',
            events = options.events && options.events[viewport] ? options.events[viewport] : [];

        $list.find('.enter-category').show();
        $list.find('.dropdown > a').on('click', function (e) {
            e.preventDefault();
        });

        if (e.data.type === 'start') {
            toucheStartEvent = { event: e, timestamp: new Date().getTime(), top: $window.scrollTop() };
            $list.off('mouseenter.menu mouseleave.menu');
        } else if ($.inArray('touch', events) > -1 && !_touchMoveDetect(e)) {
            _setEventTypeClass($self, 'touch');

            if ($.inArray('hover', events) === -1 || touchEvents.start !== 'pointerdown') {
                _openMenu.call($self, e, viewport);
            }

            $list.on('mouseleave', function () {
                $list.on('mouseenter.menu', 'li', { event: 'hover' }, _mouseHandler).on('mouseleave.menu', 'li', { event: 'hover', action: 'leave' }, _mouseHandler);
            });
        }
    };

    /**
     * Stores the last touch position on touchmove
     * @param       e       jQuery event object
     * @private
     */
    var _touchMoveHandler = function _touchMoveHandler(e) {
        toucheEndEvent = { event: e, timestamp: new Date().getTime(), top: $window.scrollTop() };
    };

    /**
     * Event handler for closing the menu if
     * the user interacts with the page
     * outside of the menu
     * @param       {object}    e       jQuery event object
     * @param       {object}    d       jQuery selection of the event emitter
     * @private
     */
    var _closeFlyout = function _closeFlyout(e, d) {
        if (d !== $this && $this.find($(e.target)).length === 0) {
            // Remove open and close timer
            _clearTimeouts();

            // Remove all state-classes from the menu
            if (options.menuType === 'horizontal') {
                $list.find('.touch, .mouse, .leave, .' + options.openClass).removeClass('touch mouse leave ' + options.openClass);
            }
        }
    };

    var _onClickAccordion = function _onClickAccordion(e) {
        e.preventDefault();
        e.stopPropagation();

        if ($(this).parents('.navbar-topbar-item').length > 0) {
            return;
        }

        if ($(this).hasClass('dropdown')) {
            if ($(this).hasClass(options.openClass)) {
                $(this).removeClass(options.openClass).find('.' + options.openClass).removeClass(options.openClass);
            } else {
                $(this).addClass(options.openClass).parentsUntil($this, 'li').addClass(options.openClass);
            }
        } else {
            location.href = $(this).find('a').attr('href');
        }
    };

    var _bindHorizontalEventHandlers = function _bindHorizontalEventHandlers() {
        $list.on(touchEvents.start + '.menu', 'li', { type: 'start' }, _touchHandler).on(touchEvents.move + '.menu', 'li', { type: 'start' }, _touchMoveHandler).on(touchEvents.end + '.menu', 'li', { type: 'end' }, _touchHandler).on('click.menu', 'li', { event: 'click', 'delay': 0 }, _mouseHandler).on('mouseenter.menu', 'li', { event: 'hover', action: 'enter' }, _mouseHandler).on('mouseleave.menu', 'li', { event: 'hover', action: 'leave' }, _mouseHandler);

        $body.on(jse.libs.theme.events.MENU_REPOSITIONED(), _updateCategoryMenu);
    };

    var _unbindHorizontalEventHandlers = function _unbindHorizontalEventHandlers() {
        $list.off(touchEvents.start + '.menu', 'li').off(touchEvents.move + '.menu', 'li').off(touchEvents.end + '.menu', 'li').off('click.menu', 'li').off('mouseenter.menu', 'li').off('mouseleave.menu', 'li');
    };

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

    /**
     * Init function of the widget
     * @constructor
     */
    module.init = function (done) {
        // @todo Getting the "touchEvents" config value produces problems in tablet devices.
        touchEvents = jse.core.config.get('touch');
        transition.classOpen = options.openClass;

        _getSelections();
        _resetInitialCss();

        $body.on(jse.libs.theme.events.BREAKPOINT(), _breakpointHandler).on(jse.libs.theme.events.OPEN_FLYOUT() + ' click ' + touchEvents.end, _closeFlyout);

        $('.close-menu-container').on('click', function (e) {
            e.stopPropagation();
            e.preventDefault();
        });

        $('.close-flyout').on('click', _closeMenu);

        if (options.menuType === 'horizontal') {
            _bindHorizontalEventHandlers();
        }

        if (options.menuType === 'vertical') {
            if (options.accordion === true) {
                $this.on('click', 'li', _onClickAccordion);
            }

            // if there is no top header we must create dummy html because other modules will not work correctly
            if ($('#categories').length === 0) {
                var html = '<div id="categories"><div class="navbar-collapse collapse">' + '<nav class="navbar-default navbar-categories hidden"></nav></div></div>';
                $('#header').append(html);
            }
        }

        _breakpointHandler();

        /**
         * Stop the propagation of the events inside this container
         * (Workaround for the "more"-dropdown)
         */
        $this.find('.' + options.ignoreClass).on('mouseleave.menu mouseenter.menu click.menu ' + touchEvents.start + ' ' + touchEvents.end, 'li', function (e) {
            e.stopPropagation();
        });

        if (options.openActive) {
            var $active = $this.find('.active');
            $active.parentsUntil($this, 'li').addClass('open');
        }

        $('li.custom-entries a').on('click', function (e) {
            e.stopPropagation();
        });

        var viewport = mode.id <= options.breakpoint ? 'mobile' : 'desktop';

        if (viewport == 'mobile') {
            $('.level-1').css('padding-bottom', '200px'); // This padding corrects expand/collapse behavior of lower menu items in various mobile browsers. 
        }

        done();
    };

    // Return data to widget engine
    return module;
});
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndpZGdldHMvbWVudS5qcyJdLCJuYW1lcyI6WyJnYW1iaW8iLCJ3aWRnZXRzIiwibW9kdWxlIiwic291cmNlIiwiZGF0YSIsIiR0aGlzIiwiJCIsIiR3aW5kb3ciLCJ3aW5kb3ciLCIkYm9keSIsIiRsaXN0IiwiJGVudHJpZXMiLCIkbW9yZSIsIiRtb3JlRW50cmllcyIsIiRtZW51RW50cmllcyIsIiRjdXN0b20iLCIkY2F0ZWdvcmllcyIsInRvdWNoRXZlbnRzIiwiY3VycmVudFdpZHRoIiwibW9kZSIsIm1vYmlsZSIsImVudGVyVGltZXIiLCJsZWF2ZVRpbWVyIiwiaW5pdGlhbGl6ZWRQb3MiLCJvbkVudGVyIiwidG91Y2hlU3RhcnRFdmVudCIsInRvdWNoZUVuZEV2ZW50IiwidHJhbnNpdGlvbiIsImlzVG91Y2hEZXZpY2UiLCJNb2Rlcm5penIiLCJ0b3VjaGV2ZW50cyIsIm5hdmlnYXRvciIsInVzZXJBZ2VudCIsInNlYXJjaCIsImRlZmF1bHRzIiwibWVudVR5cGUiLCJ1bmZvbGRMZXZlbCIsImFjY29yZGlvbiIsInNob3dBbGxMaW5rIiwiYnJlYWtwb2ludCIsImVudGVyRGVsYXkiLCJsZWF2ZURlbGF5Iiwid2lkdGhUb2xlcmFuY2UiLCJvcGVuQ2xhc3MiLCJzd2l0Y2hFbGVtZW50UG9zaXRpb24iLCJpZ25vcmVDbGFzcyIsInRvdWNoTW92ZVRvbGVyYW5jZSIsIm9wZW5BY3RpdmUiLCJldmVudHMiLCJkZXNrdG9wIiwib3B0aW9ucyIsImV4dGVuZCIsIl90b3VjaE1vdmVEZXRlY3QiLCJkaWZmIiwiTWF0aCIsImFicyIsImV2ZW50Iiwib3JpZ2luYWxFdmVudCIsInBhZ2VZIiwiX2dldFNlbGVjdGlvbnMiLCJjaGlsZHJlbiIsIm5vdCIsImZpbHRlciIsIl9zZXRJdGVtIiwiJGl0ZW0iLCIkdGFyZ2V0IiwicG9zaXRpb25JZCIsImRvbmUiLCJlYWNoIiwiJHNlbGYiLCJwb3NpdGlvbiIsImJlZm9yZSIsImRldGFjaCIsImFwcGVuZCIsIl9hZGRFbGVtZW50IiwiX3Nob3dFbGVtZW50cyIsIiRlbGVtZW50cyIsIndpZHRoIiwiaGlkZSIsIl9yZW1vdmVFbGVtZW50IiwiX2hpZGVFbGVtZW50cyIsImFkZCIsImZpbmQiLCJyZW1vdmVDbGFzcyIsImlzIiwic2hvdyIsImdldCIsInJldmVyc2UiLCJfaW5pdEVsZW1lbnRTaXplc0FuZFBvc2l0aW9uIiwiaSIsIm91dGVyV2lkdGgiLCJfY2xvc2VNZW51IiwicGFyZW50cyIsImxlbmd0aCIsIl9jbGVhclRpbWVvdXRzIiwiY2xlYXJUaW1lb3V0IiwiX3Jlc2V0SW5pdGlhbENzcyIsImNzcyIsIl9yZXBvc2l0aW9uT3BlbkxheWVyIiwibGlzdFdpZHRoIiwiJG9wZW5MYXllciIsIiRwYXJlbnQiLCJwYXJlbnQiLCJwYXJlbnRQb3NpdGlvbiIsImxlZnQiLCJwYXJlbnRXaWR0aCIsImFkZENsYXNzIiwiX3VwZGF0ZUNhdGVnb3J5TWVudSIsImUiLCJldmVudE5hbWUiLCJjb250YWluZXJXaWR0aCIsImlubmVyV2lkdGgiLCJfc3dpdGNoVG9Nb2JpbGVWaWV3Iiwib3BhY2l0eSIsImhlaWdodCIsImFwcGVuZFRvIiwiX2JpbmRIb3Jpem9udGFsRXZlbnRIYW5kbGVycyIsInRyaWdnZXIiLCJqc2UiLCJsaWJzIiwidGhlbWUiLCJNRU5VX1JFUE9TSVRJT05FRCIsIl9zd2l0Y2hUb0Rlc2t0b3BWaWV3IiwiJHRvcG1lbnVDb250ZW50RWxlbWVudHMiLCJfdW5iaW5kSG9yaXpvbnRhbEV2ZW50SGFuZGxlcnMiLCJjbGljayIsInByZXZlbnREZWZhdWx0IiwiX3NldEV2ZW50VHlwZUNsYXNzIiwiY2xhc3NOYW1lIiwiX2JyZWFrcG9pbnRIYW5kbGVyIiwib2xkTW9kZSIsIm5ld01vZGUiLCJyZXNwb25zaXZlIiwiaWQiLCJzd2l0Y2hUb01vYmlsZSIsInVuZGVmaW5lZCIsInN3aXRjaFRvRGVza3RvcCIsIl9vcGVuTWVudSIsInR5cGUiLCJkZWxheSIsIiRzdWJtZW51IiwibGV2ZWwiLCJ2YWxpZFN1Ym1lbnUiLCJwYXJzZUludCIsInN0b3BQcm9wYWdhdGlvbiIsInRvZ2dsZUNsYXNzIiwidmlzaWJsZSIsImhhc0NsYXNzIiwibGVhdmUiLCJhY3Rpb24iLCJpbnRlcmFjdGlvbiIsImlzTW91c2VEb3duIiwic2V0VGltZW91dCIsInBhcmVudHNVbnRpbCIsIlRSQU5TSVRJT05fU1RPUCIsIm9wZW4iLCJvZmYiLCJUUkFOU0lUSU9OX0ZJTklTSEVEIiwib25lIiwiVFJBTlNJVElPTiIsIk9QRU5fRkxZT1VUIiwiX21vdXNlSGFuZGxlciIsInZpZXdwb3J0IiwiaW5BcnJheSIsImNhbGwiLCJhdHRyIiwibG9jYXRpb24iLCJocmVmIiwiX3RvdWNoSGFuZGxlciIsIm9uIiwidGltZXN0YW1wIiwiRGF0ZSIsImdldFRpbWUiLCJ0b3AiLCJzY3JvbGxUb3AiLCJzdGFydCIsIl90b3VjaE1vdmVIYW5kbGVyIiwiX2Nsb3NlRmx5b3V0IiwiZCIsInRhcmdldCIsIl9vbkNsaWNrQWNjb3JkaW9uIiwibW92ZSIsImVuZCIsImluaXQiLCJjb3JlIiwiY29uZmlnIiwiY2xhc3NPcGVuIiwiQlJFQUtQT0lOVCIsImh0bWwiLCIkYWN0aXZlIl0sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7Ozs7O0FBVUE7Ozs7Ozs7O0FBUUFBLE9BQU9DLE9BQVAsQ0FBZUMsTUFBZixDQUNJLE1BREosRUFHSSxDQUNJRixPQUFPRyxNQUFQLEdBQWdCLGNBRHBCLEVBRUlILE9BQU9HLE1BQVAsR0FBZ0Isa0JBRnBCLEVBR0lILE9BQU9HLE1BQVAsR0FBZ0IsbUJBSHBCLENBSEosRUFTSSxVQUFVQyxJQUFWLEVBQWdCOztBQUVaOztBQUVSOztBQUVRLFFBQUlDLFFBQVFDLEVBQUUsSUFBRixDQUFaO0FBQUEsUUFDSUMsVUFBVUQsRUFBRUUsTUFBRixDQURkO0FBQUEsUUFFSUMsUUFBUUgsRUFBRSxNQUFGLENBRlo7QUFBQSxRQUdJSSxRQUFRLElBSFo7QUFBQSxRQUlJQyxXQUFXLElBSmY7QUFBQSxRQUtJQyxRQUFRLElBTFo7QUFBQSxRQU1JQyxl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SUFETCxDQUNVLE1BQU1oQyxRQUFRTCxXQUR4QixFQUVLNEgsRUFGTCxDQUVRLGdEQUFnRHhKLFlBQVk4SixLQUE1RCxHQUFvRSxHQUFwRSxHQUNFOUosWUFBWXFLLEdBSHRCLEVBRzJCLElBSDNCLEVBR2lDLFVBQVUxRSxDQUFWLEVBQWE7QUFDdENBLGNBQUVvQyxlQUFGO0FBQ0gsU0FMTDs7QUFPQSxZQUFJOUYsUUFBUUgsVUFBWixFQUF3QjtBQUNwQixnQkFBSThJLFVBQVV4TCxNQUFNNkUsSUFBTixDQUFXLFNBQVgsQ0FBZDtBQUNBMkcsb0JBQ0twQyxZQURMLENBQ2tCcEosS0FEbEIsRUFDeUIsSUFEekIsRUFFS3FHLFFBRkwsQ0FFYyxNQUZkO0FBR0g7O0FBRURwRyxVQUFFLHFCQUFGLEVBQXlCbUssRUFBekIsQ0FBNEIsT0FBNUIsRUFBcUMsVUFBVTdELENBQVYsRUFBYTtBQUM5Q0EsY0FBRW9DLGVBQUY7QUFDSCxTQUZEOztBQUlBLFlBQUlrQixXQUFXL0ksS0FBS2tILEVBQUwsSUFBV25GLFFBQVFYLFVBQW5CLEdBQWdDLFFBQWhDLEdBQTJDLFNBQTFEOztBQUVBLFlBQUkySCxZQUFZLFFBQWhCLEVBQTBCO0FBQ3RCNUosY0FBRSxVQUFGLEVBQWMyRixHQUFkLENBQWtCLGdCQUFsQixFQUFvQyxPQUFwQyxFQURzQixDQUN3QjtBQUNqRDs7QUFFRDlCO0FBQ0gsS0FuRUQ7O0FBcUVBO0FBQ0EsV0FBT2pFLE1BQVA7QUFDSCxDQWw2QkwiLCJmaWxlIjoid2lkZ2V0cy9tZW51LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiBtZW51LmpzIDIwMTgtMDItMDFcbiBHYW1iaW8gR21iSFxuIGh0dHA6Ly93d3cuZ2FtYmlvLmRlXG4gQ29weXJpZ2h0IChjKSAyMDE4IEdhbWJpbyBHbWJIXG4gUmVsZWFzZWQgdW5kZXIgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIChWZXJzaW9uIDIpXG4gW2h0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy9ncGwtMi4wLmh0bWxdXG4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG4vKipcbiAqIFRoaXMgd2lkZ2V0IGhhbmRsZXMgdGhlIGhvcml6b250YWwgbWVudS9kcm9wZG93biBmdW5jdGlvbmFsaXR5LlxuICpcbiAqIEl0J3MgdXNlZCBmb3IgdGhlIHRvcCBjYXRlZ29yeSBuYXZpZ2F0aW9uLCB0aGUgY2FydCBkcm9wZG93biBvciB0aGUgdG9wIG1lbnUgKGZvciBleGFtcGxlKS4gSXQgaXNcbiAqIGFibGUgdG8gcmUtb3JkZXIgdGhlIG1lbnUgZW50cmllcyB0byBhIHNwZWNpYWwgXCJNb3JlXCIgc3VibWVudSB0byBzYXZlIHNwYWNlIGlmIHRoZSBlbnRyaWVzIGRvbid0XG4gKiBmaXQgaW4gdGhlIGN1cnJlbnQgdmlldy4gSXQncyBhbHNvIGFibGUgdG8gd29yayB3aXRoIGRpZmZlcmVudCBldmVudCB0eXBlcyBmb3Igb3BlbmluZy9jbG9zaW5nIG1lbnVcbiAqIGl0ZW1zIGluIHRoZSBkaWZmZXJlbnQgdmlldyB0eXBlcy5cbiAqL1xuZ2FtYmlvLndpZGdldHMubW9kdWxlKFxuICAgICdtZW51JyxcblxuICAgIFtcbiAgICAgICAgZ2FtYmlvLnNvdXJjZSArICcvbGlicy9ldmVudHMnLFxuICAgICAgICBnYW1iaW8uc291cmNlICsgJy9saWJzL3Jlc3BvbnNpdmUnLFxuICAgICAgICBnYW1iaW8uc291cmNlICsgJy9saWJzL2ludGVyYWN0aW9uJ1xuICAgIF0sXG5cbiAgICBmdW5jdGlvbiAoZGF0YSkge1xuXG4gICAgICAgICd1c2Ugc3RyaWN0JztcblxuLy8gIyMjIyMjIyMjIyBWQVJJQUJMRSBJTklUSUFMSVpBVElPTiAjIyMjIyMjIyMjXG5cbiAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcbiAgICAgICAgICAgICR3aW5kb3cgPSAkKHdpbmRvdyksXG4gICAgICAgICAgICAkYm9keSA9ICQoJ2JvZHknKSxcbiAgICAgICAgICAgICRsaXN0ID0gbnVsbCxcbiAgICAgICAgICAgICRlbnRyaWVzID0gbnVsbCxcbiAgICAgICAgICAgICRtb3JlID0gbnVsbCxcbiAgICAgICAgICAgICRtb3JlRW50cmllcyA9IG51bGwsXG4gICAgICAgICAgICAkbWVudUVudHJpZXMgPSBudWxsLFxuICAgICAgICAgICAgJGN1c3RvbSA9IG51bGwsXG4gICAgICAgICAgICAkY2F0ZWdvcmllcyA9IG51bGwsXG4gICAgICAgICAgICB0b3VjaEV2ZW50cyA9IG51bGwsXG4gICAgICAgICAgICBjdXJyZW50V2lkdGggPSBudWxsLFxuICAgICAgICAgICAgbW9kZSA9IG51bGwsXG4gICAgICAgICAgICBtb2JpbGUgPSBmYWxzZSxcbiAgICAgICAgICAgIGVudGVyVGltZXIgPSBudWxsLFxuICAgICAgICAgICAgbGVhdmVUaW1lciA9IG51bGwsXG4gICAgICAgICAgICBpbml0aWFsaXplZFBvcyA9IGZhbHNlLFxuICAgICAgICAgICAgb25FbnRlciA9IGZhbHNlLFxuICAgICAgICAgICAgdG91Y2hlU3RhcnRFdmVudCA9IG51bGwsXG4gICAgICAgICAgICB0b3VjaGVFbmRFdmVudCA9IG51bGwsXG4gICAgICAgICAgICB0cmFuc2l0aW9uID0ge30sXG4gICAgICAgICAgICBpc1RvdWNoRGV2aWNlID0gTW9kZXJuaXpyLnRvdWNoZXZlbnRzIHx8IG5hdmlnYXRvci51c2VyQWdlbnQuc2VhcmNoKC9Ub3VjaC9pKSAhPT0gLTEsXG4gICAgICAgICAgICBkZWZhdWx0cyA9IHtcbiAgICAgICAgICAgICAgICAvLyBUaGUgbWVudSB0eXBlIG11c3QgYmUgZWl0aGVyICdob3Jpem9udGFsJyBvciAndmVydGljYWwnXG4gICAgICAgICAgICAgICAgbWVudVR5cGU6ICdob3Jpem9udGFsJyxcblxuICAgICAgICAgICAgICAgIC8vIFZlcnRpY2FsIG1lbnUgb3B0aW9ucy5cbiAgICAgICAgICAgICAgICB1bmZvbGRMZXZlbDogMCxcbiAgICAgICAgICAgICAgICBhY2NvcmRpb246IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNob3dBbGxMaW5rOiBmYWxzZSxcblxuICAgICAgICAgICAgICAgIC8vIE1pbmltdW0gYnJlYWtwb2ludCB0byBzd2l0Y2ggdG8gbW9iaWxlIHZpZXdcbiAgICAgICAgICAgICAgICBicmVha3BvaW50OiA0MCxcbiAgICAgICAgICAgICAgICAvLyBEZWxheSBpbiBtcyBhZnRlciBhIG1vdXNlZW50ZXIgdGhlIGVsZW1lbnQgZ2V0cyBzaG93blxuICAgICAgICAgICAgICAgIGVudGVyRGVsYXk6IDAsXG4gICAgICAgICAgICAgICAgLy8gRGVsYXkgaW4gbXMgYWZ0ZXIgYSBtb3VzZWxlYXZlIGFuIGVsZW1lbnQgZ2V0cyBoaWRkZW5cbiAgICAgICAgICAgICAgICBsZWF2ZURlbGF5OiA1MCxcbiAgICAgICAgICAgICAgICAvLyBUb2xlcmFuY2UgaW4gcHggd2hpY2ggZ2V0cyBzdWJzdHJhY3RlZCBmcm9tIHRoZSBuYXYtd2lkdGggdG8gcHJldmVudCBmbGlja2VyaW5nXG4gICAgICAgICAgICAgICAgd2lkdGhUb2xlcmFuY2U6IDEwLFxuICAgICAgICAgICAgICAgIC8vIENsYXNzIHRoYXQgZ2V0cyBhZGRlZCB0byBhbiBvcGVuZWQgbWVudSBsaXN0IGl0ZW1cbiAgICAgICAgICAgICAgICBvcGVuQ2xhc3M6ICdvcGVuJyxcbiAgICAgICAgICAgICAgICAvLyBJZiB0cnVlLCBlbGVtZW50cyBnZXQgbW92ZWQgZnJvbS90byB0aGUgbW9yZSBtZW51IGlmIHRoZXJlIGlzbid0IGVub3VnaCBzcGFjZVxuICAgICAgICAgICAgICAgIHN3aXRjaEVsZW1lbnRQb3NpdGlvbjogdHJ1ZSxcbiAgICAgICAgICAgICAgICAvLyBJZ25vcmUgbWVudSBmdW5jdGlvbmFsaXR5IG9uIGVsZW1lbnRzIGluc2lkZSB0aGlzIHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIGlnbm9yZUNsYXNzOiAnaWdub3JlLW1lbnUnLFxuICAgICAgICAgICAgICAgIC8vIFRvbGVyYW5jZSBpbiBweCB3aGljaCBpcyBhbGxvd2VkIGZvciBhIFwiY2xpY2tcIiBldmVudCBvbiB0b3VjaFxuICAgICAgICAgICAgICAgIHRvdWNoTW92ZVRvbGVyYW5jZTogMTAsXG4gICAgICAgICAgICAgICAgLy8gSWYgdHJ1ZSwgdGhlIGxpIHdpdGggdGhlIGFjdGl2ZSBjbGFzcyBnZXRzIG9wZW5lZFxuICAgICAgICAgICAgICAgIG9wZW5BY3RpdmU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGV2ZW50czoge1xuICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCB0eXBlcyB0aGF0IG9wZW4gdGhlIG1lbnVzIGluIGRlc2t0b3Agdmlldy5cbiAgICAgICAgICAgICAgICAgICAgLy8gUG9zc2libGUgdmFsdWVzOiBbJ2NsaWNrJ107IFsnaG92ZXInXTsgWyd0b3VjaCcsICdob3ZlciddOyBbJ2NsaWNrJywgJ2hvdmVyJ11cbiAgICAgICAgICAgICAgICAgICAgZGVza3RvcDogWyd0b3VjaCcsICdob3ZlciddLFxuICAgICAgICAgICAgICAgICAgICAvLyBFdmVudCB0eXBlcyB0aGF0IG9wZW4gdGhlIG1lbnVzIGluIG1vYmlsZSB2aWV3LlxuICAgICAgICAgICAgICAgICAgICAvLyBQb3NzaWJsZSB2YWx1ZXM6IFsnY2xpY2snXTsgWydob3ZlciddOyBbJ3RvdWNoJywgJ2hvdmVyJ107IFsnY2xpY2snLCAnaG92ZXInXTsgWyd0b3VjaCcsICdjbGljayddXG4gICAgICAgICAgICAgICAgICAgIG1vYmlsZTogWyd0b3VjaCcsICdjbGljayddXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh7fSwgZGVmYXVsdHMsIGRhdGEpLFxuICAgICAgICAgICAgbW9kdWxlID0ge307XG5cblxuLy8gIyMjIyMjIyMjIyBIRUxQRVIgRlVOQ1RJT05TICMjIyMjIyMjIyNcblxuICAgICAgICAvKipcbiAgICAgICAgICogSGVscGVyIGZ1bmN0aW9uIHRvIGNhbGN1bGF0ZSB0aGUgdG9sZXJhbmNlXG4gICAgICAgICAqIGJldHdlZW4gdGhlIHRvdWNoc3RhcnQgYW5kIHRvdWNoZW5kIGV2ZW50LlxuICAgICAgICAgKiBJZiB0aGUgbWF4IHRvbGFyYW5jZSBpcyBleGNlZWRlZCByZXR1cm4gdHJ1ZVxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgICAgIGUgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJuICAgICB7Ym9vbGVhbn0gICAgICAgICAgICAgICBJZiB0cnVlIGl0IGlzIGEgbW92ZSBldmVudFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF90b3VjaE1vdmVEZXRlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0b3VjaGVFbmRFdmVudCA9IHRvdWNoZUVuZEV2ZW50IHx8IHRvdWNoZVN0YXJ0RXZlbnQ7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IE1hdGguYWJzKHRvdWNoZUVuZEV2ZW50LmV2ZW50Lm9yaWdpbmFsRXZlbnQucGFnZVkgLSB0b3VjaGVTdGFydEV2ZW50LmV2ZW50Lm9yaWdpbmFsRXZlbnQucGFnZVkpO1xuICAgICAgICAgICAgdG91Y2hlRW5kRXZlbnQgPSBudWxsO1xuICAgICAgICAgICAgcmV0dXJuIGRpZmYgPiBvcHRpb25zLnRvdWNoTW92ZVRvbGVyYW5jZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVXBkYXRlcyB0aGUgalF1ZXJ5IHNlbGVjdGlvbiwgYmVjYXVzZSB0aGVcbiAgICAgICAgICogbGlzdCBlbGVtZW50cyBjYW4gYmUgbW92ZWRcbiAgICAgICAgICpcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfZ2V0U2VsZWN0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRsaXN0ID0gJHRoaXMuY2hpbGRyZW4oJ3VsJyk7XG4gICAgICAgICAgICAvLyBFeGNsdWRlIHRoZSBcIi5uYXZiYXItdG9wYmFyLWl0ZW1cIiBlbGVtZW50cyBiZWNhdXNlIHRoZXlcbiAgICAgICAgICAgIC8vIGFyZSBjbG9uZWQgdG8gdGhpcyBtZW51IGFuZCBhcmUgb25seSBzaG93biBpbiBtb2JpbGUgdmlld1xuICAgICAgICAgICAgJGVudHJpZXMgPSAkbGlzdC5jaGlsZHJlbigpLm5vdCgnLm5hdmJhci10b3BiYXItaXRlbScpO1xuICAgICAgICAgICAgJG1vcmUgPSAkZW50cmllcy5maWx0ZXIoJy5kcm9wZG93bi1tb3JlJyk7XG4gICAgICAgICAgICAkbW9yZUVudHJpZXMgPSAkbW9yZS5jaGlsZHJlbigndWwnKTtcbiAgICAgICAgICAgICRjdXN0b20gPSAkZW50cmllcy5maWx0ZXIoJy5jdXN0b20nKTtcbiAgICAgICAgICAgICRtZW51RW50cmllcyA9ICRlbnRyaWVzLm5vdCgkbW9yZSk7XG4gICAgICAgICAgICAkY2F0ZWdvcmllcyA9ICRtZW51RW50cmllcy5ub3QoJGN1c3RvbSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0aGF0IGRldGFjaGVzIGFuIGVsZW1lbnQgZnJvbSB0aGVcbiAgICAgICAgICogbWVudSBhbmQgYXR0YWNoZXMgaXQgdG8gdGhlIGNvcnJlY3QgcG9zaXRpb24gYXRcbiAgICAgICAgICogdGhlIHRhcmdldFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgJGl0ZW0gICAgICAgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgaXRlbSB0aGF0IGdldHMgZGV0YWNoZWQgLyBhdHRhY2hlZFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgJHRhcmdldCAgICAgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgdGFyZ2V0IGNvbnRhaW5lclxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9zZXRJdGVtID0gZnVuY3Rpb24gKCRpdGVtLCAkdGFyZ2V0KSB7XG4gICAgICAgICAgICB2YXIgcG9zaXRpb25JZCA9ICRpdGVtLmRhdGEoJ3Bvc2l0aW9uJyksXG4gICAgICAgICAgICAgICAgZG9uZSA9IGZhbHNlO1xuXG4gICAgICAgICAgICAvLyBMb29rIGZvciB0aGUgZmlyc3QgaXRlbSB0aGF0IGhhcyBhIGhpZ2hlclxuICAgICAgICAgICAgLy8gcG9zaXRpb25JZCB0aGF0IHRoZSBpdGVtIGFuZCBpbnNlcnQgaXRcbiAgICAgICAgICAgIC8vIGJlZm9yZSB0aGUgZm91bmQgZW50cnlcbiAgICAgICAgICAgICR0YXJnZXRcbiAgICAgICAgICAgICAgICAuY2hpbGRyZW4oKVxuICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRzZWxmID0gJCh0aGlzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gJHNlbGYuZGF0YSgncG9zaXRpb24nKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocG9zaXRpb24gPiBwb3NpdGlvbklkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkc2VsZi5iZWZvcmUoJGl0ZW0uZGV0YWNoKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gQXBwZW5kIHRoZSBpdGVtIGlmIHRoZSBwb3NpdGlvbklkIGhhc1xuICAgICAgICAgICAgLy8gYSBoaWdoZXIgdmFsdWUgYXMgdGhlIGxhc3QgaXRlbSBpbnQgdGhlXG4gICAgICAgICAgICAvLyB0YXJnZXRcbiAgICAgICAgICAgIGlmICghZG9uZSkge1xuICAgICAgICAgICAgICAgICR0YXJnZXQuYXBwZW5kKCRpdGVtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogSGVscGVyIGZ1bmN0aW9uIHRoYXQgY2hlY2tzIHdoaWNoIGVsZW1lbnRzIG5lZWRzXG4gICAgICAgICAqIHRvIGJlIGFkZGVkIHRvIHRoZSBtZW51LiBFdmVyeSBlbGVtZW50IHRoYXQgbmVlZHNcbiAgICAgICAgICogdG8gYmUgYWRkZWQgZ2V0cyBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uXG4gICAgICAgICAqIFwiX3NldEl0ZW1cIlxuICAgICAgICAgKiBAcGFyYW0gICAgICAge2ludGVnZXJ9ICAgICAgIGRpZmYgICAgICAgIEFtb3VudCBvZiBwaXhlbHMgdGhhdCB3ZXJlIGZyZWVcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfYWRkRWxlbWVudCA9IGZ1bmN0aW9uIChkaWZmKSB7XG5cbiAgICAgICAgICAgIHZhciBkb25lID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSGVscGVyIGZ1bmN0aW9uIHRoYXQgbG9vcHMgdGhyb3VnaCB0aGUgZWxlbWVudHNcbiAgICAgICAgICAgICAqIGFuZCB0cmllcyB0byBhZGQgdGhlIGVsZW1lbnRzIHRvIHRoZSBtZW51IGlmXG4gICAgICAgICAgICAgKiBpdCB3b3VsZCBmaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgJGVsZW1lbnRzICAgICAgIGpRdWVyeSBzZWxlY3Rpb24gb2YgdGhlIGVudHJpZXMgaW5zaWRlIHRoZSBtb3JlLW1lbnVcbiAgICAgICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHZhciBfc2hvd0VsZW1lbnRzID0gZnVuY3Rpb24gKCRlbGVtZW50cykge1xuICAgICAgICAgICAgICAgICRlbGVtZW50cy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRzZWxmID0gJCh0aGlzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoID0gJHNlbGYuZGF0YSgpLndpZHRoO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkaWZmID4gd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgaXRlbSB0byB0aGUgbWVudVxuICAgICAgICAgICAgICAgICAgICAgICAgX3NldEl0ZW0oJHNlbGYsICRsaXN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgLT0gd2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgbmV4dCBpdGVtIHdvdWxkbid0IGZpdCBhbnltb3JlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHF1aXQgdGhlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvbmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHNlbGVjdGlvbiBvZiB0aGUgdmlzaWJsZSBtZW51IGl0ZW1zLlxuICAgICAgICAgICAgX2dldFNlbGVjdGlvbnMoKTtcblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBjb250ZW50IG1hbmFnZXIgZW50cmllcyB0byB0aGUgbWVudSBmaXJzdC5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIHN0aWxsIHNwYWNlLCBhZGQgdGhlIFwibm9ybWFsXCIgY2F0ZWdvcnlcbiAgICAgICAgICAgIC8vIGl0ZW1zIGFsc29cbiAgICAgICAgICAgIF9zaG93RWxlbWVudHMoJG1vcmVFbnRyaWVzLmNoaWxkcmVuKCcuY3VzdG9tJykpO1xuICAgICAgICAgICAgaWYgKCFkb25lKSB7XG4gICAgICAgICAgICAgICAgX3Nob3dFbGVtZW50cygkbW9yZUVudHJpZXMuY2hpbGRyZW4oKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBpdGVtcyBzdGlsbCBpbiB0aGUgbW9yZSBtZW51XG4gICAgICAgICAgICAvLyB3b3VsZCBmaXQgaW5zaWRlIHRoZSBtYWluIG1lbnUgaWYgdGhlIG1vcmVcbiAgICAgICAgICAgIC8vIG1lbnUgd291bGQgZ2V0IGhpZGRlblxuICAgICAgICAgICAgdmFyIHdpZHRoID0gMDtcbiAgICAgICAgICAgICRtb3JlRW50cmllc1xuICAgICAgICAgICAgICAgIC5jaGlsZHJlbigpXG4gICAgICAgICAgICAgICAgLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB3aWR0aCArPSAkKHRoaXMpLmRhdGEoKS53aWR0aDtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKHdpZHRoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgJG1vcmUuaGlkZSgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh3aWR0aCA8ICgkbW9yZS5kYXRhKCkud2lkdGggKyBkaWZmKSkge1xuICAgICAgICAgICAgICAgICRtb3JlLmhpZGUoKTtcbiAgICAgICAgICAgICAgICBkaWZmICs9ICRtb3JlLmRhdGEoKS53aWR0aDtcbiAgICAgICAgICAgICAgICBfc2hvd0VsZW1lbnRzKCRtb3JlRW50cmllcy5jaGlsZHJlbigpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdGhhdCBjaGVja3Mgd2hpY2ggZWxlbWVudHMgbmVlZHNcbiAgICAgICAgICogdG8gYmUgcmVtb3ZlZCBmcm9tIHRoZSBtZW51LCBzbyB0aGF0IGl0IGZpdHNcbiAgICAgICAgICogaW5zaWRlIG9uZSBtZW51IGxpbmUuIEV2ZXJ5IGVsZW1lbnQgdGhhdCBuZWVkc1xuICAgICAgICAgKiB0byBiZSByZW1vdmVkIGdldHMgcGFzc2VkIHRvIHRoZSBmdW5jdGlvblxuICAgICAgICAgKiBcIl9zZXRJdGVtXCJcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtpbnRlZ2VyfSAgICAgICBkaWZmICAgICAgICBBbW91bnQgb2YgcGl4ZWxzIHRoYXQgbmVlZHMgdG8gYmUgc2F2ZWRcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfcmVtb3ZlRWxlbWVudCA9IGZ1bmN0aW9uIChkaWZmKSB7XG5cbiAgICAgICAgICAgIHZhciBkb25lID0gZmFsc2U7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogSGVscGVyIGZ1bmN0aW9uIHRoYXQgY29udGFpbnMgdGhlIGNoZWNrXG4gICAgICAgICAgICAgKiBsb29wIGZvciBkZXRlcm1pbmluZyB3aGljaCBlbGVtZW50c1xuICAgICAgICAgICAgICogbmVlZHMgdG8gYmUgcmVtb3ZlZFxuICAgICAgICAgICAgICogQHBhcmFtICAgICAgICAgICB7b2JqZWN0fSAgICAkZWxlbWVudHMgICAgICAgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgbWVudSBpdGVtc1xuICAgICAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdmFyIF9oaWRlRWxlbWVudHMgPSBmdW5jdGlvbiAoJGVsZW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgJGVsZW1lbnRzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggPSAkc2VsZi5kYXRhKCkud2lkdGg7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSBwb3NzaWJseSBzZXQgb3BlbiBzdGF0ZVxuICAgICAgICAgICAgICAgICAgICAkc2VsZlxuICAgICAgICAgICAgICAgICAgICAgICAgLmZpbHRlcignLicgKyBvcHRpb25zLm9wZW5DbGFzcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hZGQoJHNlbGYuZmluZCgnLicgKyBvcHRpb25zLm9wZW5DbGFzcykpXG4gICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3Mob3B0aW9ucy5vcGVuQ2xhc3MpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGUgZW50cnkgdG8gdGhlIG1vcmUtbWVudVxuICAgICAgICAgICAgICAgICAgICBfc2V0SXRlbSgkc2VsZiwgJG1vcmVFbnRyaWVzKTtcblxuICAgICAgICAgICAgICAgICAgICBkaWZmIC09IHdpZHRoO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkaWZmIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRW5vdWdoIGVsZW1lbnRzIGFyZSByZW1vdmVkLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gcXVpdCB0aGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgZG9uZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgc2VsZWN0aW9uIG9mIHRoZSB2aXNpYmxlIG1lbnUgaXRlbXNcbiAgICAgICAgICAgIF9nZXRTZWxlY3Rpb25zKCk7XG5cbiAgICAgICAgICAgIC8vIEFkZCB0aGUgd2lkdGggb2YgdGhlIG1vcmUgZW50cnkgaWYgaXQncyBub3RcbiAgICAgICAgICAgIC8vIHZpc2libGUsIGJlY2F1c2UgaXQgd2lsbCBnZXQgc2hvd24gZHVyaW5nIHRoaXNcbiAgICAgICAgICAgIC8vIGZ1bmN0aW9uIGNhbGxcbiAgICAgICAgICAgIGlmICgkbW9yZS5pcygnOmhpZGRlbicpKSB7XG4gICAgICAgICAgICAgICAgZGlmZiArPSAkbW9yZS5kYXRhKCkud2lkdGg7XG4gICAgICAgICAgICAgICAgJG1vcmUucmVtb3ZlQ2xhc3MoJ3N0eWxlJyk7XG4gICAgICAgICAgICAgICAgJG1vcmUuc2hvdygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGaXJzdCByZW1vdmUgXCJub3JtYWxcIiBjYXRlZ29yeSBlbnRyaWVzLiBJZiB0aGF0XG4gICAgICAgICAgICAvLyBpc24ndCBlbm91Z2ggcmVtb3ZlIHRoZSBjb250ZW50IG1hbmFnZXIgZW50cmllcyBhbHNvXG4gICAgICAgICAgICBfaGlkZUVsZW1lbnRzKCQoJGNhdGVnb3JpZXMuZ2V0KCkucmV2ZXJzZSgpKSk7XG4gICAgICAgICAgICBpZiAoIWRvbmUpIHtcbiAgICAgICAgICAgICAgICBfaGlkZUVsZW1lbnRzKCQoJGN1c3RvbS5nZXQoKS5yZXZlcnNlKCkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogU2V0cyBhIGRhdGEgYXR0cmlidXRlIHRvIHRoZSBtZW51IGl0ZW1zXG4gICAgICAgICAqIHRoYXQgY29udGFpbnMgdGhlIHdpZHRoIG9mIHRoZSBlbGVtZW50cy5cbiAgICAgICAgICogVGhpcyBpcyBuZWVkZWQgYmVjYXVzZSBpZiBpdCBpcyBkaXNwbGF5XG4gICAgICAgICAqIG5vbmUgdGhlIGRldGVjdGVkIHdpdGggd2lsbCBiZSB6ZXJvLiBJdFxuICAgICAgICAgKiBzZXRzIHBvc2l0aW9uIGlkIGFsc28uXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX2luaXRFbGVtZW50U2l6ZXNBbmRQb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRlbnRyaWVzLmVhY2goZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICB3aWR0aCA9ICRzZWxmLm91dGVyV2lkdGgoKTtcblxuICAgICAgICAgICAgICAgICRzZWxmLmRhdGEoe3dpZHRoOiB3aWR0aCwgcG9zaXRpb246IGl9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2xvc2UgYWxsIG1lbnUgZW50cmllcy5cbiAgICAgICAgICogTmVlZGVkIGZvciB0aGUgZGVza3RvcCA8LT4gbW9iaWxlIHZpZXdcbiAgICAgICAgICogY2hhbmdlLCBtb3N0bHkuXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX2Nsb3NlTWVudSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICR0aGlzLmZpbmQoJ2xpLicgKyBvcHRpb25zLm9wZW5DbGFzcykuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCQodGhpcykucGFyZW50cygnLm5hdmJhci1jYXRlZ29yaWVzLWxlZnQnKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkKHRoaXMpLnJlbW92ZUNsYXNzKG9wdGlvbnMub3BlbkNsYXNzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2xlYXIgYWxsIHBlbmRpbmdcbiAgICAgICAgICogZnVuY3Rpb25zXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX2NsZWFyVGltZW91dHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBlbnRlclRpbWVyID0gZW50ZXJUaW1lciA/IGNsZWFyVGltZW91dChlbnRlclRpbWVyKSA6IG51bGw7XG4gICAgICAgICAgICBsZWF2ZVRpbWVyID0gbGVhdmVUaW1lciA/IGNsZWFyVGltZW91dChsZWF2ZVRpbWVyKSA6IG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byByZXNldCB0aGUgY3NzIG9mIHRoZSBtZW51LlxuICAgICAgICAgKiBUaGlzIGlzIG5lZWRlZCB0byByZW1vdmUgdGhlIG92ZXJmbG93ICYgaGVpZ2h0XG4gICAgICAgICAqIHNldHRpbmdzIG9mIHRoZSBtZW51IG9mIHRoZSBjc3MgZmlsZS4gVGhlXG4gICAgICAgICAqIGRpcmVjdGl2ZXMgd2VyZSBzZXQgdG8gcHJldmVudCBmbGlja2VyaW5nIG9uIHBhZ2VcbiAgICAgICAgICogbG9hZFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9yZXNldEluaXRpYWxDc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkdGhpcy5jc3Moe1xuICAgICAgICAgICAgICAgICdvdmVyZmxvdyc6ICd2aXNpYmxlJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBzZXQgcG9zaXRpb25pbmcgY2xhc3Nlc1xuICAgICAgICAgKiB0byB0aGUgb3BlbmQgZmx5b3V0LiBUaGlzIGlzIG5lZWRlZCB0byBrZWVwXG4gICAgICAgICAqIHRoZSBmbHlvdXQgaW5zaWRlIHRoZSBib3VuZGFyaWVzIG9mIHRoZSBuYXZpZ2F0aW9uXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX3JlcG9zaXRpb25PcGVuTGF5ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbGlzdFdpZHRoID0gJGxpc3Qud2lkdGgoKSxcbiAgICAgICAgICAgICAgICAkb3BlbkxheWVyID0gJGVudHJpZXNcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcignLicgKyBvcHRpb25zLm9wZW5DbGFzcylcbiAgICAgICAgICAgICAgICAgICAgLmNoaWxkcmVuKCd1bCcpO1xuXG4gICAgICAgICAgICAkb3BlbkxheWVyLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciAkc2VsZiA9ICQodGhpcyksXG4gICAgICAgICAgICAgICAgICAgICRwYXJlbnQgPSAkc2VsZi5wYXJlbnQoKTtcblxuICAgICAgICAgICAgICAgIC8vIFJlc2V0IHRoZSBjbGFzc2VzIHRvIHByZXZlbnQgd3JvbmcgY2FsY3VsYXRpb24gZHVlIHRvIHNwZWNpYWwgc3R5bGVzXG4gICAgICAgICAgICAgICAgJHBhcmVudC5yZW1vdmVDbGFzcygnZmx5b3V0LXJpZ2h0IGZseW91dC1sZWZ0IGZseW91dC1jZW50ZXIgZmx5b3V0LXdvbnQtZml0Jyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgd2lkdGggPSAkc2VsZi5vdXRlcldpZHRoKCksXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudFBvc2l0aW9uID0gJHBhcmVudC5wb3NpdGlvbigpLmxlZnQsXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudFdpZHRoID0gJHBhcmVudC5vdXRlcldpZHRoKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayB3aXRjaCBjbGFzcyBuZWVkcyB0byBiZSBzZXRcbiAgICAgICAgICAgICAgICBpZiAobGlzdFdpZHRoID4gcGFyZW50UG9zaXRpb24gKyB3aWR0aCkge1xuICAgICAgICAgICAgICAgICAgICAkcGFyZW50LmFkZENsYXNzKCdmbHlvdXQtcmlnaHQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBhcmVudFBvc2l0aW9uICsgcGFyZW50V2lkdGggLSB3aWR0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgJHBhcmVudC5hZGRDbGFzcygnZmx5b3V0LWxlZnQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdpZHRoIDwgbGlzdFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICRwYXJlbnQuYWRkQ2xhc3MoJ2ZseW91dC1jZW50ZXInKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkcGFyZW50LmFkZENsYXNzKCdmbHlvdXQtd29udC1maXQnKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW5cbiAgICAgICAgICogdGhlIHNpemUgb2YgdGhlIHZpc2libGUgZWxlbWVudHMgaW4gdGhlIG1lbnUgYW5kIHRoZVxuICAgICAgICAgKiBjb250YWluZXIgc2l6ZS4gSWYgdGhlcmUgaXMgc3BhY2UsIGl0IGNhbGxzIHRoZSBmdW5jdGlvblxuICAgICAgICAgKiB0byBhY3RpdmF0ZSBhbiBtZW51IGVudHJ5IGVsc2UgaXQgY2FsbHMgdGhlIGZ1bmN0aW9uIHRvXG4gICAgICAgICAqIGRlYWN0aXZhdGUgYSBtZW51IGVudHJ5XG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICBlICAgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge3N0cmluZ30gICAgZXZlbnROYW1lIEV2ZW50IG5hbWUgcGFyYW1ldGVyIG9mIHRoZSBldmVudCBvYmplY3RcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdXBkYXRlQ2F0ZWdvcnlNZW51ID0gZnVuY3Rpb24gKGUsIGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lcldpZHRoID0gJHRoaXMuaW5uZXJXaWR0aCgpIC0gb3B0aW9ucy53aWR0aFRvbGVyYW5jZSxcbiAgICAgICAgICAgICAgICB3aWR0aCA9IDA7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBjb250YWluZXIgd2lkdGggaGFzIGNoYW5nZWQgc2luY2UgbGFzdCBjYWxsXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgICAgICAgJiYgKGN1cnJlbnRXaWR0aCAhPT0gY29udGFpbmVyV2lkdGggfHwgZXZlbnROYW1lID09PSAnc3dpdGNoZWRUb0Rlc2t0b3AnKSkge1xuXG4gICAgICAgICAgICAgICAgJGxpc3RcbiAgICAgICAgICAgICAgICAgICAgLmNoaWxkcmVuKCc6dmlzaWJsZScpXG4gICAgICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoICs9ICQodGhpcykuZGF0YSgnd2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgb3IgcmVtb3ZlIGVsZW1lbnRzIGRlcGVuZGluZyBvbiB0aGUgc2l6ZSBvZiB0aGVcbiAgICAgICAgICAgICAgICAvLyB2aXNpYmxlIGVsZW1lbnRzXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRhaW5lcldpZHRoIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3JlbW92ZUVsZW1lbnQod2lkdGggLSBjb250YWluZXJXaWR0aCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX2FkZEVsZW1lbnQoY29udGFpbmVyV2lkdGggLSB3aWR0aCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgX3JlcG9zaXRpb25PcGVuTGF5ZXIoKTtcblxuICAgICAgICAgICAgICAgIGN1cnJlbnRXaWR0aCA9IGNvbnRhaW5lcldpZHRoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBzd2l0Y2ggdG8gdGhlIG1vYmlsZVxuICAgICAgICAgKiBtb2RlIG9mIHRoZSBtZW51LlxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9zd2l0Y2hUb01vYmlsZVZpZXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBSZXNldCB0aGUgY3VycmVudCB3aWR0aCBzbyB0aGF0XG4gICAgICAgICAgICAvLyB0aGUgXCJfdXBkYXRlQ2F0ZWdvcnlNZW51XCIgd2lsbFxuICAgICAgICAgICAgLy8gcGVyZm9ybSBjb3JyZWN0bHkgb24gdGhlIG5leHQgdmlld1xuICAgICAgICAgICAgLy8gY2hhbmdlIHRvIGRlc2t0b3BcbiAgICAgICAgICAgIGN1cnJlbnRXaWR0aCA9IC0xO1xuICAgICAgICAgICAgX2FkZEVsZW1lbnQoOTk5OTk5OTkpO1xuXG4gICAgICAgICAgICAkKCcubGV2ZWwtMScpLmNzcygncGFkZGluZy1ib3R0b20nLCAnMjAwcHgnKTsgLy8gVGhpcyBwYWRkaW5nIGNvcnJlY3RzIGV4cGFuZC9jb2xsYXBzZSBiZWhhdmlvciBvZiBsb3dlciBtZW51IGl0ZW1zIGluIHZhcmlvdXMgbW9iaWxlIGJyb3dzZXJzLiBcblxuICAgICAgICAgICAgLy8gVXNlIHRoZSB2ZXJ0aWNhbCBtZW51IG9uIG1vYmlsZSB2aWV3LlxuICAgICAgICAgICAgaWYgKG9wdGlvbnMubWVudVR5cGUgPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICAgICAgICAgICAgICAvLyBmaXhlcyBkaXNwbGF5IGhvcml6b250YWwgbWVudSBhZnRlciBhIHN3aXRjaCB0byBtb2JpbGUgYW5kIGJhY2sgdG8gZGVza3RvcCBpcyBwZXJmb3JtZWRcbiAgICAgICAgICAgICAgICBpZiAoJCgnI2NhdGVnb3JpZXMgbmF2Lm5hdmJhci1kZWZhdWx0OmZpcnN0Jykubm90KCcubmF2LWNhdGVnb3JpZXMtbGVmdCcpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnI2NhdGVnb3JpZXMgbmF2Lm5hdmJhci1kZWZhdWx0OmZpcnN0JykuY3NzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IDBcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jaGlsZHJlbigpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBtb3ZlIHRvcG1lbnUtY29udGVudCBpdGVtcyBmcm9tIGhvcml6b250YWwgbWVudSB0byB2ZXJ0aWNhbCBtZW51XG4gICAgICAgICAgICAgICAgJHRoaXNcbiAgICAgICAgICAgICAgICAgICAgLmZpbmQoJ3VsLmxldmVsLTEgbGkubmF2YmFyLXRvcGJhci1pdGVtOmZpcnN0JylcbiAgICAgICAgICAgICAgICAgICAgLmJlZm9yZSgkKCcjY2F0ZWdvcmllcyBuYXYubmF2YmFyLWRlZmF1bHQgbGkudG9wbWVudS1jb250ZW50JykuZGV0YWNoKCkpO1xuXG4gICAgICAgICAgICAgICAgJHRoaXMuYXBwZW5kVG8oJyNjYXRlZ29yaWVzID4gLm5hdmJhci1jb2xsYXBzZScpO1xuICAgICAgICAgICAgICAgICR0aGlzLmFkZENsYXNzKCduYXZiYXItZGVmYXVsdCBuYXZiYXItY2F0ZWdvcmllcycpO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbmQoJ3VsLmxldmVsLTEnKS5hZGRDbGFzcygnbmF2YmFyLW5hdicpO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbmQoJy5uYXZiYXItdG9wYmFyLWl0ZW0nKS5ub3QoJy50b3BiYXItc2VhcmNoJykuc2hvdygpO1xuXG4gICAgICAgICAgICAgICAgX2JpbmRIb3Jpem9udGFsRXZlbnRIYW5kbGVycygpO1xuXG4gICAgICAgICAgICAgICAgJGJvZHkudHJpZ2dlcihqc2UubGlicy50aGVtZS5ldmVudHMuTUVOVV9SRVBPU0lUSU9ORUQoKSwgWydzd2l0Y2hlZFRvTW9iaWxlJ10pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gc3dpdGNoIHRvIHRoZSBkZXNrdG9wXG4gICAgICAgICAqIG1vZGUgb2YgdGhlIG1lbnUuIEFkZGl0aW9uYWxseSwgaW4gY2FzZSB0aGF0XG4gICAgICAgICAqIHRoZSBkZXNrdG9wIG1vZGUgaXMgc2hvd24gZm9yIHRoZSBmaXJzdCB0aW1lXG4gICAgICAgICAqIHNldCB0aGUgcG9zaXRpb24gYW5kIHdpZHRoIG9mIHRoZSBlbGVtZW50c1xuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9zd2l0Y2hUb0Rlc2t0b3BWaWV3ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJCgnLmxldmVsLTEnKS5jc3MoJ3BhZGRpbmctYm90dG9tJywgJycpOyAvLyBSZXNldCBkaXNwbGF5IGZpeCBmb3IgbW9iaWxlIGJyb3dzZXJzLlxuXG4gICAgICAgICAgICAvLyBSZXZlcnQgYWxsIHRoZSBjaGFuZ2VzIG1hZGUgZHVyaW5nIHRoZSBzd2l0Y2ggdG8gbW9iaWxlLlxuICAgICAgICAgICAgaWYgKG9wdGlvbnMubWVudVR5cGUgPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICAgICAgICAgICAgICAvLyBmaXhlcyBkaXNwbGF5IGhvcml6b250YWwgbWVudSBhZnRlciBhIHN3aXRjaCB0byBtb2JpbGUgYW5kIGJhY2sgdG8gZGVza3RvcCBpcyBwZXJmb3JtZWRcbiAgICAgICAgICAgICAgICBpZiAoJCgnI2NhdGVnb3JpZXMgbmF2Lm5hdmJhci1kZWZhdWx0OmZpcnN0Jykubm90KCcubmF2LWNhdGVnb3JpZXMtbGVmdCcpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgJCgnI2NhdGVnb3JpZXMgbmF2Lm5hdmJhci1kZWZhdWx0OmZpcnN0JykuY3NzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6ICdhdXRvJ1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNoaWxkcmVuKCkuc2hvdygpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIG1vdmUgdG9wbWVudS1jb250ZW50IGl0ZW1zIGJhY2sgdG8gaG9yaXpvbnRhbCBtZW51XG4gICAgICAgICAgICAgICAgdmFyICR0b3BtZW51Q29udGVudEVsZW1lbnRzID0gJHRoaXMuZmluZCgnbGkudG9wbWVudS1jb250ZW50JykuZGV0YWNoKCk7XG4gICAgICAgICAgICAgICAgJCgnI2NhdGVnb3JpZXMgbmF2Lm5hdmJhci1kZWZhdWx0IHVsLmxldmVsLTE6Zmlyc3QnKS5hcHBlbmQoJHRvcG1lbnVDb250ZW50RWxlbWVudHMpO1xuXG4gICAgICAgICAgICAgICAgJHRoaXMuYXBwZW5kVG8oJy5ib3gtY2F0ZWdvcmllcycpO1xuICAgICAgICAgICAgICAgICR0aGlzLnJlbW92ZUNsYXNzKCduYXZiYXItZGVmYXVsdCBuYXZiYXItY2F0ZWdvcmllcycpO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbmQoJ3VsLmxldmVsLTEnKS5yZW1vdmVDbGFzcygnbmF2YmFyLW5hdicpO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbmQoJy5uYXZiYXItdG9wYmFyLWl0ZW0nKS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgX3VuYmluZEhvcml6b250YWxFdmVudEhhbmRsZXJzKCk7XG5cbiAgICAgICAgICAgICAgICAkYm9keS50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5NRU5VX1JFUE9TSVRJT05FRCgpLCBbJ3N3aXRjaGVkVG9EZXNrdG9wJ10pO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGlmICghaW5pdGlhbGl6ZWRQb3MpIHtcbiAgICAgICAgICAgICAgICBfaW5pdEVsZW1lbnRTaXplc0FuZFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgaW5pdGlhbGl6ZWRQb3MgPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICAgICAgX3VwZGF0ZUNhdGVnb3J5TWVudSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVG91Y2hEZXZpY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgJGxpc3QuZmluZCgnLmVudGVyLWNhdGVnb3J5Jykuc2hvdygpO1xuICAgICAgICAgICAgICAgICAgICAkbGlzdC5maW5kKCcuZHJvcGRvd24gPiBhJykuY2xpY2soZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gYWRkIHRoZSBjbGFzcyB0byB0aGUgbGktZWxlbWVudFxuICAgICAgICAgKiBkZXBlbmRpbmcgb24gdGhlIG9wZW4gZXZlbnQuIFRoaXMgY2FuIGJlIGEgXCJ0b3VjaFwiXG4gICAgICAgICAqIG9yIGEgXCJtb3VzZVwiIGNsYXNzXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICAkdGFyZ2V0ICAgICAgICAgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgbGktZWxlbWVudFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge3N0cmluZ30gICAgY2xhc3NOYW1lICAgICAgIE5hbWUgb2YgdGhlIGNsYXNzIHRoYXQgZ2V0cyBhZGRlZFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9zZXRFdmVudFR5cGVDbGFzcyA9IGZ1bmN0aW9uICgkdGFyZ2V0LCBjbGFzc05hbWUpIHtcbiAgICAgICAgICAgICR0YXJnZXRcbiAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3MoJ3RvdWNoIG1vdXNlJylcbiAgICAgICAgICAgICAgICAuYWRkQ2xhc3MoY2xhc3NOYW1lIHx8ICcnKTtcbiAgICAgICAgfTtcblxuXG4vLyAjIyMjIyMjIyMjIE1BSU4gRlVOQ1RJT05BTElUWSAjIyMjIyMjIyMjXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZ1bmN0aW9uIHRoYXQgZ2V0cyBjYWxsZWQgYnkgdGhlIGJyZWFrcG9pbnQgdHJpZ2dlclxuICAgICAgICAgKiAod2hpY2ggaXMgZmlyZWQgb24gYnJvd3NlciByZXNpemUpLiBJdCBjaGVja3MgZm9yXG4gICAgICAgICAqIENTUyB2aWV3IGNoYW5nZXMgYW5kIHJlY29uZmlndXJlcyB0aGUgdGhlIEpTIGJlaGF2aW91clxuICAgICAgICAgKiBvZiB0aGUgbWVudSBpbiB0aGF0IGNhc2VcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfYnJlYWtwb2ludEhhbmRsZXIgPSBmdW5jdGlvbiAoKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCB0aGUgY3VycmVudCB2aWV3bW9kZVxuICAgICAgICAgICAgdmFyIG9sZE1vZGUgPSBtb2RlIHx8IHt9LFxuICAgICAgICAgICAgICAgIG5ld01vZGUgPSBqc2UubGlicy50aGVtZS5yZXNwb25zaXZlLmJyZWFrcG9pbnQoKTtcblxuICAgICAgICAgICAgLy8gT25seSBkbyBzb21ldGhpbmcgaWYgdGhlIHZpZXcgd2FzIGNoYW5nZWRcbiAgICAgICAgICAgIGlmIChuZXdNb2RlLmlkICE9PSBvbGRNb2RlLmlkKSB7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBhIHZpZXcgY2hhbmdlIGJldHdlZW4gbW9iaWxlIGFuZCBkZXNrdG9wIHZpZXcgd2FzIG1hZGVcbiAgICAgICAgICAgICAgICB2YXIgc3dpdGNoVG9Nb2JpbGUgPSAobmV3TW9kZS5pZCA8PSBvcHRpb25zLmJyZWFrcG9pbnQgJiYgKCFtb2JpbGUgfHwgb2xkTW9kZS5pZCA9PT0gdW5kZWZpbmVkKSksXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaFRvRGVza3RvcCA9IChuZXdNb2RlLmlkID4gb3B0aW9ucy5icmVha3BvaW50ICYmIChtb2JpbGUgfHwgb2xkTW9kZS5pZCA9PT0gdW5kZWZpbmVkKSk7XG5cbiAgICAgICAgICAgICAgICAvLyBTdG9yZSB0aGUgbmV3IHZpZXcgc2V0dGluZ3NcbiAgICAgICAgICAgICAgICBtb2JpbGUgPSBuZXdNb2RlLmlkIDw9IG9wdGlvbnMuYnJlYWtwb2ludDtcbiAgICAgICAgICAgICAgICBtb2RlID0gJC5leHRlbmQoe30sIG5ld01vZGUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHN3aXRjaFRvTW9iaWxlIHx8IHN3aXRjaFRvRGVza3RvcCkge1xuICAgICAgICAgICAgICAgICAgICBfY2xlYXJUaW1lb3V0cygpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSAhPT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2Nsb3NlTWVudSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hhbmdlIHRoZSB2aXNpYmlsaXR5IG9mIHRoZSBtZW51IGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIC8vIGluIGNhc2Ugb2YgZGVza3RvcCA8LT4gbW9iaWxlIHZpZXcgY2hhbmdlXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnN3aXRjaEVsZW1lbnRQb3NpdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN3aXRjaFRvTW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3N3aXRjaFRvTW9iaWxlVmlldygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfc3dpdGNoVG9EZXNrdG9wVmlldygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3JlcG9zaXRpb25PcGVuTGF5ZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghbW9iaWxlICYmIG9wdGlvbnMuc3dpdGNoRWxlbWVudFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgbWVudSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgdmlldyBjaGFuZ2Ugd2FzIGRlc2t0b3AgdG8gZGVza3RvcCBvbmx5XG4gICAgICAgICAgICAgICAgICAgIF91cGRhdGVDYXRlZ29yeU1lbnUoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFtb2JpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgX3JlcG9zaXRpb25PcGVuTGF5ZXIoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH1cblxuICAgICAgICB9O1xuXG5cbi8vICMjIyMjIyMjIyBFVkVOVCBIQU5ETEVSICMjIyMjIyMjIyNcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ2hhbmdlcyB0aGUgZXBhbmQgLyBjb2xsYXBzZSBzdGF0ZSBvZiB0aGUgbWVudSxcbiAgICAgICAgICogaWYgdGhlcmUgaXMgYW4gc3VibWVudS4gSW4gdGhlIG90aGVyIGNhc2UgaXRcbiAgICAgICAgICogd2lsbCBsZXQgZXhlY3V0ZSB0aGUgZGVmYXVsdCBhY3Rpb24gKG1vc3QgdGltZXNcbiAgICAgICAgICogdGhlIGV4ZWN1dGlvbiBvZiBhIGxpbmspXG4gICAgICAgICAqIEBwYXJhbSB7b2JqZWN0fSAgZSAgICAgICBqUXVlcnkgZXZlbnQgb2JqZWN0XG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSAgbW9kZSAgICBUaGUgY3VycmVudCB2aWV3IG1vZGUgKGNhbiBiZSBcIm1vYmlsZVwiIG9yIFwiZGVza3RvcFwiXG4gICAgICAgICAqIEBwYXJhbSB7aW50ZWdlcn0gZGVsYXkgICBDdXN0b20gZGVsYXkgKGluIG1zKSBmb3Igb3BlbmluZyBjbG9zaW5nIHRoZSBtZW51IChuZWVkZWQgZm9yIGNsaWNrIC8gdG91Y2ggZXZlbnRzKVxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9vcGVuTWVudSA9IGZ1bmN0aW9uIChlLCB0eXBlLCBkZWxheSkge1xuXG4gICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgICRzdWJtZW51ID0gJHNlbGYuY2hpbGRyZW4oJ3VsJyksXG4gICAgICAgICAgICAgICAgbGVuZ3RoID0gJHN1Ym1lbnUubGVuZ3RoLFxuICAgICAgICAgICAgICAgIGxldmVsID0gKCRzdWJtZW51Lmxlbmd0aCkgPyAoJHN1Ym1lbnUuZGF0YSgnbGV2ZWwnKSB8fCAnMCcpIDogOTksXG4gICAgICAgICAgICAgICAgdmFsaWRTdWJtZW51ID0gKHBhcnNlSW50KGxldmVsLCAxMCkgPD0gMiAmJiBtb2RlLmlkID4gb3B0aW9ucy5icmVha3BvaW50KSB8fCBtb2RlLmlkXG4gICAgICAgICAgICAgICAgICAgIDw9IG9wdGlvbnMuYnJlYWtwb2ludDtcblxuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdtb2JpbGUnKSB7XG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gT25seSBjaGFuZ2UgdGhlIHN0YXRlIGlmIHRoZXJlIGlzXG4gICAgICAgICAgICAvLyBhIHN1Ym1lbnVcbiAgICAgICAgICAgIGlmIChsZW5ndGggJiYgdmFsaWRTdWJtZW51KSB7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdtb2JpbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNpbXBseSB0b2dnbGUgdGhlIG9wZW5DbGFzcyBpbiBtb2JpbGUgbW9kZVxuICAgICAgICAgICAgICAgICAgICAkc2VsZi50b2dnbGVDbGFzcyhvcHRpb25zLm9wZW5DbGFzcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGVyZm9ybSB0aGUgZWxzZSBjYXNlIGZvciB0aGUgZGVza3RvcCB2aWV3XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpc2libGUgPSAkc2VsZi5oYXNDbGFzcyhvcHRpb25zLm9wZW5DbGFzcyksXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWF2ZSA9ICRzZWxmLmhhc0NsYXNzKCdsZWF2ZScpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYWN0aW9uID0gKGUuZGF0YSAmJiBlLmRhdGEuYWN0aW9uKSA/IGUuZGF0YS5hY3Rpb24gOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2aXNpYmxlICYmIGxlYXZlKSA/ICdlbnRlcicgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmxlID8gJ2xlYXZlJyA6ICdlbnRlcic7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRGVwZW5kaW5nIG9uIHRoZSB2aXNpYmlsaXR5IGFuZCB0aGUgZXZlbnQtYWN0aW9uLXBhcmFtZXRlclxuICAgICAgICAgICAgICAgICAgICAvLyB0aGUgc3VibWVudSBnZXRzIG9wZW5lZCBvciBjbG9zZWRcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2VudGVyJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW9uRW50ZXIgJiYgIWpzZS5saWJzLnRoZW1lLmludGVyYWN0aW9uLmlzTW91c2VEb3duKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25FbnRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBhIHRpbWVyIGZvciBvcGVuaW5nIGlmIHRoZSBzdWJtZW51IChkZWxheWVkIG9wZW5pbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9jbGVhclRpbWVvdXRzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudGVyVGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBvcGVuQ2xhc3MtY2xhc3NlcyBmcm9tIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVudSBleGNlcHQgdGhlIGVsZW1lbnQgdG8gb3BlbiBhbmQgaXQncyBwYXJlbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkbGlzdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5maW5kKCcuJyArIG9wdGlvbnMub3BlbkNsYXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5ub3QoJHNlbGYpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm5vdCgkc2VsZi5wYXJlbnRzVW50aWwoJHRoaXMsICcuJyArIG9wdGlvbnMub3BlbkNsYXNzKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcihqc2UubGlicy50aGVtZS5ldmVudHMuVFJBTlNJVElPTl9TVE9QKCksIFtdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVDbGFzcyhvcHRpb25zLm9wZW5DbGFzcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmQoJy5sZWF2ZScpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRyaWdnZXIoanNlLmxpYnMudGhlbWUuZXZlbnRzLlRSQU5TSVRJT05fU1RPUCgpLCBbXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3MoJ2xlYXZlJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE9wZW4gdGhlIHN1Ym1lbnVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zaXRpb24ub3BlbiA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBhbmQgdW5zZXQgdGhlIFwib25FbnRlclwiIHRvIHByZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNsb3NpbmcgdGhlIG1lbnUgaW1tZWRpYXRlbHkgYWZ0ZXIgb3BlbmluZyBpZlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGN1cnNvciBpcyBhdCBhbiBwbGFjZSBvdmVyIHRoZSBvcGVuaW5nIG1lbnVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vICh0aGlzIGNhbiBoYXBwZW4gaWYgb3RoZXIgY29tcG9uZW50cyB0cmlnZ2VyIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gb3BlbiBldmVudClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzZWxmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm9mZihqc2UubGlicy50aGVtZS5ldmVudHMuVFJBTlNJVElPTl9GSU5JU0hFRCgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5vbmUoanNlLmxpYnMudGhlbWUuZXZlbnRzLlRSQU5TSVRJT05fRklOSVNIRUQoKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkVudGVyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcihqc2UubGlicy50aGVtZS5ldmVudHMuVFJBTlNJVElPTigpLCB0cmFuc2l0aW9uKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5PUEVOX0ZMWU9VVCgpLCBbJHRoaXNdKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3JlcG9zaXRpb25PcGVuTGF5ZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgKHR5cGVvZiBkZWxheSA9PT0gJ251bWJlcicpID8gZGVsYXkgOiBvcHRpb25zLmVudGVyRGVsYXkpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdsZWF2ZSc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25FbnRlciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNldCBhIHRpbWVyIGZvciBjbG9zaW5nIGlmIHRoZSBzdWJtZW51IChkZWxheWVkIGNsb3NpbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsZWFyVGltZW91dHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2VsZi5hZGRDbGFzcygnbGVhdmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWF2ZVRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgb3BlbkNsYXNzLWNsYXNzZXMgZnJvbSB0aGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbWVudSBleGNlcHQgdGhlIGVsZW1lbnRzIHBhcmVudHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbi5vcGVuID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgnLicgKyBvcHRpb25zLm9wZW5DbGFzcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5ub3QoJHNlbGYucGFyZW50c1VudGlsKCR0aGlzLCAnLicgKyBvcHRpb25zLm9wZW5DbGFzcykpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAub2ZmKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OX0ZJTklTSEVEKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAub25lKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OX0ZJTklTSEVEKCksIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfc2V0RXZlbnRUeXBlQ2xhc3MoJHNlbGYsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAkc2VsZi5yZW1vdmVDbGFzcygnbGVhdmUnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcihqc2UubGlicy50aGVtZS5ldmVudHMuVFJBTlNJVElPTigpLCB0cmFuc2l0aW9uKTtcblxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwgKHR5cGVvZiBkZWxheSA9PT0gJ251bWJlcicpID8gZGVsYXkgOiBvcHRpb25zLmxlYXZlRGVsYXkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRXZlbnQgaGFuZGxlciBmb3IgdGhlIGNsaWNrIC8gbW91c2VlbnRlciAvIG1vdXNlbGVhdmUgZXZlbnRcbiAgICAgICAgICogb24gdGhlIG5hdmlnYXRpb24gbGkgZWxlbWVudHMuIEl0IGNoZWNrcyBpZiB0aGUgZXZlbnQgdHlwZVxuICAgICAgICAgKiBpcyBzdXBwb3J0ZWQgZm9yIHRoZSBjdXJyZW50IHZpZXcgdHlwZSBhbmQgY2FsbHMgdGhlXG4gICAgICAgICAqIG9wZW5NZW51LWZ1bmN0aW9uIGlmIHNvLlxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgZSAgICAgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9tb3VzZUhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgdmFyICRzZWxmID0gJCh0aGlzKSxcbiAgICAgICAgICAgICAgICB2aWV3cG9ydCA9IG1vZGUuaWQgPD0gb3B0aW9ucy5icmVha3BvaW50ID8gJ21vYmlsZScgOiAnZGVza3RvcCcsXG4gICAgICAgICAgICAgICAgZXZlbnRzID0gKG9wdGlvbnMuZXZlbnRzICYmIG9wdGlvbnMuZXZlbnRzW3ZpZXdwb3J0XSkgPyBvcHRpb25zLmV2ZW50c1t2aWV3cG9ydF0gOiBbXTtcblxuICAgICAgICAgICAgX3NldEV2ZW50VHlwZUNsYXNzKCRzZWxmLCAnbW91c2UnKTtcbiAgICAgICAgICAgIGlmICgkLmluQXJyYXkoZS5kYXRhLmV2ZW50LCBldmVudHMpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBfb3Blbk1lbnUuY2FsbCgkc2VsZiwgZSwgdmlld3BvcnQsIGUuZGF0YS5kZWxheSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBlcmZvcm0gbmF2aWdhdGlvbiBmb3IgY3VzdG9tIGxpbmtzIGFuZCBjYXRlZ29yeSBsaW5rcyBvbiB0b3VjaCBkZXZpY2VzIGlmIG5vIHN1YmNhdGVnb3JpZXMgYXJlIGZvdW5kLlxuICAgICAgICAgICAgaWYgKCgkc2VsZi5oYXNDbGFzcygnY3VzdG9tJykgfHwgKGlzVG91Y2hEZXZpY2UgJiYgJHNlbGYuY2hpbGRyZW4oJ3VsJykubGVuZ3RoID09IDApKVxuICAgICAgICAgICAgICAgICYmIGUuZGF0YS5ldmVudCA9PT0gJ2NsaWNrJyAmJiAhJHNlbGYuZmluZCgnZm9ybScpLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCRzZWxmLmZpbmQoJ2EnKS5hdHRyKCd0YXJnZXQnKSA9PT0gJ19ibGFuaycpIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93Lm9wZW4oJHNlbGYuZmluZCgnYScpLmF0dHIoJ2hyZWYnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9ICRzZWxmLmZpbmQoJ2EnKS5hdHRyKCdocmVmJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFdmVudCBoYW5kbGVyIGZvciB0aGUgdG91Y2hzdGFydCBldmVudCAob3IgXCJwb2ludGVyZG93blwiXG4gICAgICAgICAqIGRlcGVuZGluZyBvbiB0aGUgYnJvd3NlcikuIEl0IHJlbW92ZXMgdGhlIG90aGVyIGNyaXRpY2FsXG4gICAgICAgICAqIGV2ZW50IGhhbmRsZXIgKHRoYXQgd291bGQgb3BlbiB0aGUgbWVudSkgZnJvbSB0aGUgbGlzdFxuICAgICAgICAgKiBlbGVtZW50IGlmIHRoZSB0aGUgbW91c2VlbnRlciB3YXMgZXhlY3V0ZWQgYmVmb3JlIGFuZFxuICAgICAgICAgKiBhIGNsaWNrIG9yIHRvdWNoIGV2ZW50IHdpbGwgYmUgcGVyZm9ybWVkIGFmdGVyd2FyZHMuIFRoaXNcbiAgICAgICAgICogaXMgbmVlZGVkIHRvIHByZXZlbnQgdGhlIGJyb3dzZXIgZW5naW5lIHdvcmthcm91bmRzIHdoaWNoXG4gICAgICAgICAqIHdpbGwgYXV0b21hdGljYWxseSBwZXJmb3JtIG1vdXNlIC8gY2xpY2stZXZlbnRzIG9uIHRvdWNoXG4gICAgICAgICAqIGFsc28uXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX3RvdWNoSGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgIHZpZXdwb3J0ID0gbW9kZS5pZCA8PSBvcHRpb25zLmJyZWFrcG9pbnQgPyAnbW9iaWxlJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBldmVudHMgPSAob3B0aW9ucy5ldmVudHMgJiYgb3B0aW9ucy5ldmVudHNbdmlld3BvcnRdKSA/IG9wdGlvbnMuZXZlbnRzW3ZpZXdwb3J0XSA6IFtdO1xuXG4gICAgICAgICAgICAkbGlzdC5maW5kKCcuZW50ZXItY2F0ZWdvcnknKS5zaG93KCk7XG4gICAgICAgICAgICAkbGlzdC5maW5kKCcuZHJvcGRvd24gPiBhJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKGUuZGF0YS50eXBlID09PSAnc3RhcnQnKSB7XG4gICAgICAgICAgICAgICAgdG91Y2hlU3RhcnRFdmVudCA9IHtldmVudDogZSwgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLmdldFRpbWUoKSwgdG9wOiAkd2luZG93LnNjcm9sbFRvcCgpfTtcbiAgICAgICAgICAgICAgICAkbGlzdC5vZmYoJ21vdXNlZW50ZXIubWVudSBtb3VzZWxlYXZlLm1lbnUnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoJC5pbkFycmF5KCd0b3VjaCcsIGV2ZW50cykgPiAtMSAmJiAhX3RvdWNoTW92ZURldGVjdChlKSkge1xuICAgICAgICAgICAgICAgIF9zZXRFdmVudFR5cGVDbGFzcygkc2VsZiwgJ3RvdWNoJyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoJC5pbkFycmF5KCdob3ZlcicsIGV2ZW50cykgPT09IC0xIHx8IHRvdWNoRXZlbnRzLnN0YXJ0ICE9PSAncG9pbnRlcmRvd24nKSB7XG4gICAgICAgICAgICAgICAgICAgIF9vcGVuTWVudS5jYWxsKCRzZWxmLCBlLCB2aWV3cG9ydCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgJGxpc3Qub24oJ21vdXNlbGVhdmUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAub24oJ21vdXNlZW50ZXIubWVudScsICdsaScsIHtldmVudDogJ2hvdmVyJ30sIF9tb3VzZUhhbmRsZXIpXG4gICAgICAgICAgICAgICAgICAgICAgICAub24oJ21vdXNlbGVhdmUubWVudScsICdsaScsIHtldmVudDogJ2hvdmVyJywgYWN0aW9uOiAnbGVhdmUnfSwgX21vdXNlSGFuZGxlcik7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIH1cblxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdG9yZXMgdGhlIGxhc3QgdG91Y2ggcG9zaXRpb24gb24gdG91Y2htb3ZlXG4gICAgICAgICAqIEBwYXJhbSAgICAgICBlICAgICAgIGpRdWVyeSBldmVudCBvYmplY3RcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdG91Y2hNb3ZlSGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB0b3VjaGVFbmRFdmVudCA9IHtldmVudDogZSwgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLmdldFRpbWUoKSwgdG9wOiAkd2luZG93LnNjcm9sbFRvcCgpfTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRXZlbnQgaGFuZGxlciBmb3IgY2xvc2luZyB0aGUgbWVudSBpZlxuICAgICAgICAgKiB0aGUgdXNlciBpbnRlcmFjdHMgd2l0aCB0aGUgcGFnZVxuICAgICAgICAgKiBvdXRzaWRlIG9mIHRoZSBtZW51XG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICBlICAgICAgIGpRdWVyeSBldmVudCBvYmplY3RcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgIGQgICAgICAgalF1ZXJ5IHNlbGVjdGlvbiBvZiB0aGUgZXZlbnQgZW1pdHRlclxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9jbG9zZUZseW91dCA9IGZ1bmN0aW9uIChlLCBkKSB7XG4gICAgICAgICAgICBpZiAoZCAhPT0gJHRoaXMgJiYgJHRoaXMuZmluZCgkKGUudGFyZ2V0KSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9wZW4gYW5kIGNsb3NlIHRpbWVyXG4gICAgICAgICAgICAgICAgX2NsZWFyVGltZW91dHMoKTtcblxuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBhbGwgc3RhdGUtY2xhc3NlcyBmcm9tIHRoZSBtZW51XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMubWVudVR5cGUgPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgICAgICAgICAkbGlzdFxuICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmQoJy50b3VjaCwgLm1vdXNlLCAubGVhdmUsIC4nICsgb3B0aW9ucy5vcGVuQ2xhc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3MoJ3RvdWNoIG1vdXNlIGxlYXZlICcgKyBvcHRpb25zLm9wZW5DbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBfb25DbGlja0FjY29yZGlvbiA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgICAgICAgICBpZiAoJCh0aGlzKS5wYXJlbnRzKCcubmF2YmFyLXRvcGJhci1pdGVtJykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCQodGhpcykuaGFzQ2xhc3MoJ2Ryb3Bkb3duJykpIHtcbiAgICAgICAgICAgICAgICBpZiAoJCh0aGlzKS5oYXNDbGFzcyhvcHRpb25zLm9wZW5DbGFzcykpIHtcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUNsYXNzKG9wdGlvbnMub3BlbkNsYXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmQoJy4nICsgb3B0aW9ucy5vcGVuQ2xhc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3Mob3B0aW9ucy5vcGVuQ2xhc3MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICQodGhpcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhvcHRpb25zLm9wZW5DbGFzcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5wYXJlbnRzVW50aWwoJHRoaXMsICdsaScpXG4gICAgICAgICAgICAgICAgICAgICAgICAuYWRkQ2xhc3Mob3B0aW9ucy5vcGVuQ2xhc3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uaHJlZiA9ICQodGhpcykuZmluZCgnYScpLmF0dHIoJ2hyZWYnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgX2JpbmRIb3Jpem9udGFsRXZlbnRIYW5kbGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgLm9uKHRvdWNoRXZlbnRzLnN0YXJ0ICsgJy5tZW51JywgJ2xpJywge3R5cGU6ICdzdGFydCd9LCBfdG91Y2hIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbih0b3VjaEV2ZW50cy5tb3ZlICsgJy5tZW51JywgJ2xpJywge3R5cGU6ICdzdGFydCd9LCBfdG91Y2hNb3ZlSGFuZGxlcilcbiAgICAgICAgICAgICAgICAub24odG91Y2hFdmVudHMuZW5kICsgJy5tZW51JywgJ2xpJywge3R5cGU6ICdlbmQnfSwgX3RvdWNoSGFuZGxlcilcbiAgICAgICAgICAgICAgICAub24oJ2NsaWNrLm1lbnUnLCAnbGknLCB7ZXZlbnQ6ICdjbGljaycsICdkZWxheSc6IDB9LCBfbW91c2VIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignbW91c2VlbnRlci5tZW51JywgJ2xpJywge2V2ZW50OiAnaG92ZXInLCBhY3Rpb246ICdlbnRlcid9LCBfbW91c2VIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignbW91c2VsZWF2ZS5tZW51JywgJ2xpJywge2V2ZW50OiAnaG92ZXInLCBhY3Rpb246ICdsZWF2ZSd9LCBfbW91c2VIYW5kbGVyKTtcblxuICAgICAgICAgICAgJGJvZHlcbiAgICAgICAgICAgICAgICAub24oanNlLmxpYnMudGhlbWUuZXZlbnRzLk1FTlVfUkVQT1NJVElPTkVEKCksIF91cGRhdGVDYXRlZ29yeU1lbnUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBfdW5iaW5kSG9yaXpvbnRhbEV2ZW50SGFuZGxlcnMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkbGlzdFxuICAgICAgICAgICAgICAgIC5vZmYodG91Y2hFdmVudHMuc3RhcnQgKyAnLm1lbnUnLCAnbGknKVxuICAgICAgICAgICAgICAgIC5vZmYodG91Y2hFdmVudHMubW92ZSArICcubWVudScsICdsaScpXG4gICAgICAgICAgICAgICAgLm9mZih0b3VjaEV2ZW50cy5lbmQgKyAnLm1lbnUnLCAnbGknKVxuICAgICAgICAgICAgICAgIC5vZmYoJ2NsaWNrLm1lbnUnLCAnbGknKVxuICAgICAgICAgICAgICAgIC5vZmYoJ21vdXNlZW50ZXIubWVudScsICdsaScpXG4gICAgICAgICAgICAgICAgLm9mZignbW91c2VsZWF2ZS5tZW51JywgJ2xpJyk7XG4gICAgICAgIH07XG5cbi8vICMjIyMjIyMjIyMgSU5JVElBTElaQVRJT04gIyMjIyMjIyMjI1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBJbml0IGZ1bmN0aW9uIG9mIHRoZSB3aWRnZXRcbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqL1xuICAgICAgICBtb2R1bGUuaW5pdCA9IGZ1bmN0aW9uIChkb25lKSB7XG4gICAgICAgICAgICAvLyBAdG9kbyBHZXR0aW5nIHRoZSBcInRvdWNoRXZlbnRzXCIgY29uZmlnIHZhbHVlIHByb2R1Y2VzIHByb2JsZW1zIGluIHRhYmxldCBkZXZpY2VzLlxuICAgICAgICAgICAgdG91Y2hFdmVudHMgPSBqc2UuY29yZS5jb25maWcuZ2V0KCd0b3VjaCcpO1xuICAgICAgICAgICAgdHJhbnNpdGlvbi5jbGFzc09wZW4gPSBvcHRpb25zLm9wZW5DbGFzcztcblxuICAgICAgICAgICAgX2dldFNlbGVjdGlvbnMoKTtcbiAgICAgICAgICAgIF9yZXNldEluaXRpYWxDc3MoKTtcblxuICAgICAgICAgICAgJGJvZHlcbiAgICAgICAgICAgICAgICAub24oanNlLmxpYnMudGhlbWUuZXZlbnRzLkJSRUFLUE9JTlQoKSwgX2JyZWFrcG9pbnRIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbihqc2UubGlicy50aGVtZS5ldmVudHMuT1BFTl9GTFlPVVQoKSArICcgY2xpY2sgJyArIHRvdWNoRXZlbnRzLmVuZCwgX2Nsb3NlRmx5b3V0KTtcblxuICAgICAgICAgICAgJCgnLmNsb3NlLW1lbnUtY29udGFpbmVyJykub24oJ2NsaWNrJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgICQoJy5jbG9zZS1mbHlvdXQnKS5vbignY2xpY2snLCBfY2xvc2VNZW51KTtcblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMubWVudVR5cGUgPT09ICdob3Jpem9udGFsJykge1xuICAgICAgICAgICAgICAgIF9iaW5kSG9yaXpvbnRhbEV2ZW50SGFuZGxlcnMoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMubWVudVR5cGUgPT09ICd2ZXJ0aWNhbCcpIHtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5hY2NvcmRpb24gPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMub24oJ2NsaWNrJywgJ2xpJywgX29uQ2xpY2tBY2NvcmRpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIG5vIHRvcCBoZWFkZXIgd2UgbXVzdCBjcmVhdGUgZHVtbXkgaHRtbCBiZWNhdXNlIG90aGVyIG1vZHVsZXMgd2lsbCBub3Qgd29yayBjb3JyZWN0bHlcbiAgICAgICAgICAgICAgICBpZiAoJCgnI2NhdGVnb3JpZXMnKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGh0bWwgPSAnPGRpdiBpZD1cImNhdGVnb3JpZXNcIj48ZGl2IGNsYXNzPVwibmF2YmFyLWNvbGxhcHNlIGNvbGxhcHNlXCI+J1xuICAgICAgICAgICAgICAgICAgICAgICAgKyAnPG5hdiBjbGFzcz1cIm5hdmJhci1kZWZhdWx0IG5hdmJhci1jYXRlZ29yaWVzIGhpZGRlblwiPjwvbmF2PjwvZGl2PjwvZGl2Pic7XG4gICAgICAgICAgICAgICAgICAgICQoJyNoZWFkZXInKS5hcHBlbmQoaHRtbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBfYnJlYWtwb2ludEhhbmRsZXIoKTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTdG9wIHRoZSBwcm9wYWdhdGlvbiBvZiB0aGUgZXZlbnRzIGluc2lkZSB0aGlzIGNvbnRhaW5lclxuICAgICAgICAgICAgICogKFdvcmthcm91bmQgZm9yIHRoZSBcIm1vcmVcIi1kcm9wZG93bilcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgJHRoaXNcbiAgICAgICAgICAgICAgICAuZmluZCgnLicgKyBvcHRpb25zLmlnbm9yZUNsYXNzKVxuICAgICAgICAgICAgICAgIC5vbignbW91c2VsZWF2ZS5tZW51IG1vdXNlZW50ZXIubWVudSBjbGljay5tZW51ICcgKyB0b3VjaEV2ZW50cy5zdGFydCArICcgJ1xuICAgICAgICAgICAgICAgICAgICArIHRvdWNoRXZlbnRzLmVuZCwgJ2xpJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMub3BlbkFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIHZhciAkYWN0aXZlID0gJHRoaXMuZmluZCgnLmFjdGl2ZScpO1xuICAgICAgICAgICAgICAgICRhY3RpdmVcbiAgICAgICAgICAgICAgICAgICAgLnBhcmVudHNVbnRpbCgkdGhpcywgJ2xpJylcbiAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKCdvcGVuJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICQoJ2xpLmN1c3RvbS1lbnRyaWVzIGEnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgdmFyIHZpZXdwb3J0ID0gbW9kZS5pZCA8PSBvcHRpb25zLmJyZWFrcG9pbnQgPyAnbW9iaWxlJyA6ICdkZXNrdG9wJztcblxuICAgICAgICAgICAgaWYgKHZpZXdwb3J0ID09ICdtb2JpbGUnKSB7XG4gICAgICAgICAgICAgICAgJCgnLmxldmVsLTEnKS5jc3MoJ3BhZGRpbmctYm90dG9tJywgJzIwMHB4Jyk7IC8vIFRoaXMgcGFkZGluZyBjb3JyZWN0cyBleHBhbmQvY29sbGFwc2UgYmVoYXZpb3Igb2YgbG93ZXIgbWVudSBpdGVtcyBpbiB2YXJpb3VzIG1vYmlsZSBicm93c2Vycy4gXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRvbmUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm4gZGF0YSB0byB3aWRnZXQgZW5naW5lXG4gICAgICAgIHJldHVybiBtb2R1bGU7XG4gICAgfSk7XG4iXX0=

Youez - 2016 - github.com/yon3zu
LinuXploit