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/templates/Honeygrid/assets/javascript/engine/widgets/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/moncbefd/www.moneta.at/templates/Honeygrid/assets/javascript/engine/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+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgJHBhcmVudC5hZGRDbGFzcygnZmx5b3V0LWxlZnQnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdpZHRoIDwgbGlzdFdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICRwYXJlbnQuYWRkQ2xhc3MoJ2ZseW91dC1jZW50ZXInKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkcGFyZW50LmFkZENsYXNzKCdmbHlvdXQtd29udC1maXQnKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2FsY3VsYXRlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW5cbiAgICAgICAgICogdGhlIHNpemUgb2YgdGhlIHZpc2libGUgZWxlbWVudHMgaW4gdGhlIG1lbnUgYW5kIHRoZVxuICAgICAgICAgKiBjb250YWluZXIgc2l6ZS4gSWYgdGhlcmUgaXMgc3BhY2UsIGl0IGNhbGxzIHRoZSBmdW5jdGlvblxuICAgICAgICAgKiB0byBhY3RpdmF0ZSBhbiBtZW51IGVudHJ5IGVsc2UgaXQgY2FsbHMgdGhlIGZ1bmN0aW9uIHRvXG4gICAgICAgICAqIGRlYWN0aXZhdGUgYSBtZW51IGVudHJ5XG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICBlICAgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge3N0cmluZ30gICAgZXZlbnROYW1lIEV2ZW50IG5hbWUgcGFyYW1ldGVyIG9mIHRoZSBldmVudCBvYmplY3RcbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdXBkYXRlQ2F0ZWdvcnlNZW51ID0gZnVuY3Rpb24gKGUsIGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgdmFyIGNvbnRhaW5lcldpZHRoID0gJHRoaXMuaW5uZXJXaWR0aCgpIC0gb3B0aW9ucy53aWR0aFRvbGVyYW5jZSxcbiAgICAgICAgICAgICAgICB3aWR0aCA9IDA7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBjb250YWluZXIgd2lkdGggaGFzIGNoYW5nZWQgc2luY2UgbGFzdCBjYWxsXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ2hvcml6b250YWwnXG4gICAgICAgICAgICAgICAgJiYgKGN1cnJlbnRXaWR0aCAhPT0gY29udGFpbmVyV2lkdGggfHwgZXZlbnROYW1lID09PSAnc3dpdGNoZWRUb0Rlc2t0b3AnKSkge1xuXG4gICAgICAgICAgICAgICAgJGxpc3RcbiAgICAgICAgICAgICAgICAgICAgLmNoaWxkcmVuKCc6dmlzaWJsZScpXG4gICAgICAgICAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoICs9ICQodGhpcykuZGF0YSgnd2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBBZGQgb3IgcmVtb3ZlIGVsZW1lbnRzIGRlcGVuZGluZyBvbiB0aGUgc2l6ZSBvZiB0aGVcbiAgICAgICAgICAgICAgICAvLyB2aXNpYmxlIGVsZW1lbnRzXG4gICAgICAgICAgICAgICAgaWYgKGNvbnRhaW5lcldpZHRoIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgX3JlbW92ZUVsZW1lbnQod2lkdGggLSBjb250YWluZXJXaWR0aCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgX2FkZEVsZW1lbnQoY29udGFpbmVyV2lkdGggLSB3aWR0aCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgX3JlcG9zaXRpb25PcGVuTGF5ZXIoKTtcblxuICAgICAgICAgICAgICAgIGN1cnJlbnRXaWR0aCA9IGNvbnRhaW5lcldpZHRoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBzd2l0Y2ggdG8gdGhlIG1vYmlsZVxuICAgICAgICAgKiBtb2RlIG9mIHRoZSBtZW51LlxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9zd2l0Y2hUb01vYmlsZVZpZXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBSZXNldCB0aGUgY3VycmVudCB3aWR0aCBzbyB0aGF0XG4gICAgICAgICAgICAvLyB0aGUgXCJfdXBkYXRlQ2F0ZWdvcnlNZW51XCIgd2lsbFxuICAgICAgICAgICAgLy8gcGVyZm9ybSBjb3JyZWN0bHkgb24gdGhlIG5leHQgdmlld1xuICAgICAgICAgICAgLy8gY2hhbmdlIHRvIGRlc2t0b3BcbiAgICAgICAgICAgIGN1cnJlbnRXaWR0aCA9IC0xO1xuICAgICAgICAgICAgX2FkZEVsZW1lbnQoOTk5OTk5OTkpO1xuXG4gICAgICAgICAgICAkKCcubGV2ZWwtMScpLmNzcygncGFkZGluZy1ib3R0b20nLCAnMjAwcHgnKTsgLy8gVGhpcyBwYWRkaW5nIGNvcnJlY3RzIGV4cGFuZC9jb2xsYXBzZSBiZWhhdmlvciBvZiBsb3dlciBtZW51IGl0ZW1zIGluIHZhcmlvdXMgbW9iaWxlIGJyb3dzZXJzLlxuXG4gICAgICAgICAgICAvLyBVc2UgdGhlIHZlcnRpY2FsIG1lbnUgb24gbW9iaWxlIHZpZXcuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgICAgIC8vIGZpeGVzIGRpc3BsYXkgaG9yaXpvbnRhbCBtZW51IGFmdGVyIGEgc3dpdGNoIHRvIG1vYmlsZSBhbmQgYmFjayB0byBkZXNrdG9wIGlzIHBlcmZvcm1lZFxuICAgICAgICAgICAgICAgIGlmICgkKCcjY2F0ZWdvcmllcyBuYXYubmF2YmFyLWRlZmF1bHQ6Zmlyc3QnKS5ub3QoJy5uYXYtY2F0ZWdvcmllcy1sZWZ0JykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAkKCcjY2F0ZWdvcmllcyBuYXYubmF2YmFyLWRlZmF1bHQ6Zmlyc3QnKS5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogMCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogMFxuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLmNoaWxkcmVuKCkuaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIG1vdmUgdG9wbWVudS1jb250ZW50IGl0ZW1zIGZyb20gaG9yaXpvbnRhbCBtZW51IHRvIHZlcnRpY2FsIG1lbnVcbiAgICAgICAgICAgICAgICAkdGhpc1xuICAgICAgICAgICAgICAgICAgICAuZmluZCgndWwubGV2ZWwtMSBsaS5uYXZiYXItdG9wYmFyLWl0ZW06Zmlyc3QnKVxuICAgICAgICAgICAgICAgICAgICAuYmVmb3JlKCQoJyNjYXRlZ29yaWVzIG5hdi5uYXZiYXItZGVmYXVsdCBsaS50b3BtZW51LWNvbnRlbnQnKS5kZXRhY2goKSk7XG5cbiAgICAgICAgICAgICAgICAkdGhpcy5hcHBlbmRUbygnI2NhdGVnb3JpZXMgPiAubmF2YmFyLWNvbGxhcHNlJyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuYWRkQ2xhc3MoJ25hdmJhci1kZWZhdWx0IG5hdmJhci1jYXRlZ29yaWVzJyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgndWwubGV2ZWwtMScpLmFkZENsYXNzKCduYXZiYXItbmF2Jyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnLm5hdmJhci10b3BiYXItaXRlbScpLm5vdCgnLnRvcGJhci1zZWFyY2gnKS5zaG93KCk7XG5cbiAgICAgICAgICAgICAgICBfYmluZEhvcml6b250YWxFdmVudEhhbmRsZXJzKCk7XG5cbiAgICAgICAgICAgICAgICAkYm9keS50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5NRU5VX1JFUE9TSVRJT05FRCgpLCBbJ3N3aXRjaGVkVG9Nb2JpbGUnXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBzd2l0Y2ggdG8gdGhlIGRlc2t0b3BcbiAgICAgICAgICogbW9kZSBvZiB0aGUgbWVudS4gQWRkaXRpb25hbGx5LCBpbiBjYXNlIHRoYXRcbiAgICAgICAgICogdGhlIGRlc2t0b3AgbW9kZSBpcyBzaG93biBmb3IgdGhlIGZpcnN0IHRpbWVcbiAgICAgICAgICogc2V0IHRoZSBwb3NpdGlvbiBhbmQgd2lkdGggb2YgdGhlIGVsZW1lbnRzXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX3N3aXRjaFRvRGVza3RvcFZpZXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkKCcubGV2ZWwtMScpLmNzcygncGFkZGluZy1ib3R0b20nLCAnJyk7IC8vIFJlc2V0IGRpc3BsYXkgZml4IGZvciBtb2JpbGUgYnJvd3NlcnMuXG5cbiAgICAgICAgICAgIC8vIFJldmVydCBhbGwgdGhlIGNoYW5nZXMgbWFkZSBkdXJpbmcgdGhlIHN3aXRjaCB0byBtb2JpbGUuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgICAgIC8vIGZpeGVzIGRpc3BsYXkgaG9yaXpvbnRhbCBtZW51IGFmdGVyIGEgc3dpdGNoIHRvIG1vYmlsZSBhbmQgYmFjayB0byBkZXNrdG9wIGlzIHBlcmZvcm1lZFxuICAgICAgICAgICAgICAgIGlmICgkKCcjY2F0ZWdvcmllcyBuYXYubmF2YmFyLWRlZmF1bHQ6Zmlyc3QnKS5ub3QoJy5uYXYtY2F0ZWdvcmllcy1sZWZ0JykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAkKCcjY2F0ZWdvcmllcyBuYXYubmF2YmFyLWRlZmF1bHQ6Zmlyc3QnKS5jc3Moe1xuICAgICAgICAgICAgICAgICAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogJ2F1dG8nXG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2hpbGRyZW4oKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gbW92ZSB0b3BtZW51LWNvbnRlbnQgaXRlbXMgYmFjayB0byBob3Jpem9udGFsIG1lbnVcbiAgICAgICAgICAgICAgICB2YXIgJHRvcG1lbnVDb250ZW50RWxlbWVudHMgPSAkdGhpcy5maW5kKCdsaS50b3BtZW51LWNvbnRlbnQnKS5kZXRhY2goKTtcbiAgICAgICAgICAgICAgICAkKCcjY2F0ZWdvcmllcyBuYXYubmF2YmFyLWRlZmF1bHQgdWwubGV2ZWwtMTpmaXJzdCcpLmFwcGVuZCgkdG9wbWVudUNvbnRlbnRFbGVtZW50cyk7XG5cbiAgICAgICAgICAgICAgICAkdGhpcy5hcHBlbmRUbygnLmJveC1jYXRlZ29yaWVzJyk7XG4gICAgICAgICAgICAgICAgJHRoaXMucmVtb3ZlQ2xhc3MoJ25hdmJhci1kZWZhdWx0IG5hdmJhci1jYXRlZ29yaWVzJyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgndWwubGV2ZWwtMScpLnJlbW92ZUNsYXNzKCduYXZiYXItbmF2Jyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnLm5hdmJhci10b3BiYXItaXRlbScpLmhpZGUoKTtcbiAgICAgICAgICAgICAgICBfdW5iaW5kSG9yaXpvbnRhbEV2ZW50SGFuZGxlcnMoKTtcblxuICAgICAgICAgICAgICAgICRib2R5LnRyaWdnZXIoanNlLmxpYnMudGhlbWUuZXZlbnRzLk1FTlVfUkVQT1NJVElPTkVEKCksIFsnc3dpdGNoZWRUb0Rlc2t0b3AnXSk7XG4gICAgICAgICAgICB9XG5cblxuICAgICAgICAgICAgaWYgKCFpbml0aWFsaXplZFBvcykge1xuICAgICAgICAgICAgICAgIF9pbml0RWxlbWVudFNpemVzQW5kUG9zaXRpb24oKTtcbiAgICAgICAgICAgICAgICBpbml0aWFsaXplZFBvcyA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1lbnVUeXBlID09PSAnaG9yaXpvbnRhbCcpIHtcbiAgICAgICAgICAgICAgICBfdXBkYXRlQ2F0ZWdvcnlNZW51KCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUb3VjaERldmljZSkge1xuICAgICAgICAgICAgICAgICAgICAkbGlzdC5maW5kKCcuZW50ZXItY2F0ZWdvcnknKS5zaG93KCk7XG4gICAgICAgICAgICAgICAgICAgICRsaXN0LmZpbmQoJy5kcm9wZG93biA+IGEnKS5jbGljayhmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBhZGQgdGhlIGNsYXNzIHRvIHRoZSBsaS1lbGVtZW50XG4gICAgICAgICAqIGRlcGVuZGluZyBvbiB0aGUgb3BlbiBldmVudC4gVGhpcyBjYW4gYmUgYSBcInRvdWNoXCJcbiAgICAgICAgICogb3IgYSBcIm1vdXNlXCIgY2xhc3NcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgICR0YXJnZXQgICAgICAgICBqUXVlcnkgc2VsZWN0aW9uIG9mIHRoZSBsaS1lbGVtZW50XG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7c3RyaW5nfSAgICBjbGFzc05hbWUgICAgICAgTmFtZSBvZiB0aGUgY2xhc3MgdGhhdCBnZXRzIGFkZGVkXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX3NldEV2ZW50VHlwZUNsYXNzID0gZnVuY3Rpb24gKCR0YXJnZXQsIGNsYXNzTmFtZSkge1xuICAgICAgICAgICAgJHRhcmdldFxuICAgICAgICAgICAgICAgIC5yZW1vdmVDbGFzcygndG91Y2ggbW91c2UnKVxuICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhjbGFzc05hbWUgfHwgJycpO1xuICAgICAgICB9O1xuXG5cbi8vICMjIyMjIyMjIyMgTUFJTiBGVU5DVElPTkFMSVRZICMjIyMjIyMjIyNcblxuICAgICAgICAvKipcbiAgICAgICAgICogRnVuY3Rpb24gdGhhdCBnZXRzIGNhbGxlZCBieSB0aGUgYnJlYWtwb2ludCB0cmlnZ2VyXG4gICAgICAgICAqICh3aGljaCBpcyBmaXJlZCBvbiBicm93c2VyIHJlc2l6ZSkuIEl0IGNoZWNrcyBmb3JcbiAgICAgICAgICogQ1NTIHZpZXcgY2hhbmdlcyBhbmQgcmVjb25maWd1cmVzIHRoZSB0aGUgSlMgYmVoYXZpb3VyXG4gICAgICAgICAqIG9mIHRoZSBtZW51IGluIHRoYXQgY2FzZVxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF9icmVha3BvaW50SGFuZGxlciA9IGZ1bmN0aW9uICgpIHtcblxuICAgICAgICAgICAgLy8gR2V0IHRoZSBjdXJyZW50IHZpZXdtb2RlXG4gICAgICAgICAgICB2YXIgb2xkTW9kZSA9IG1vZGUgfHwge30sXG4gICAgICAgICAgICAgICAgbmV3TW9kZSA9IGpzZS5saWJzLnRoZW1lLnJlc3BvbnNpdmUuYnJlYWtwb2ludCgpO1xuXG4gICAgICAgICAgICAvLyBPbmx5IGRvIHNvbWV0aGluZyBpZiB0aGUgdmlldyB3YXMgY2hhbmdlZFxuICAgICAgICAgICAgaWYgKG5ld01vZGUuaWQgIT09IG9sZE1vZGUuaWQpIHtcblxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGEgdmlldyBjaGFuZ2UgYmV0d2VlbiBtb2JpbGUgYW5kIGRlc2t0b3AgdmlldyB3YXMgbWFkZVxuICAgICAgICAgICAgICAgIHZhciBzd2l0Y2hUb01vYmlsZSA9IChuZXdNb2RlLmlkIDw9IG9wdGlvbnMuYnJlYWtwb2ludCAmJiAoIW1vYmlsZSB8fCBvbGRNb2RlLmlkID09PSB1bmRlZmluZWQpKSxcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoVG9EZXNrdG9wID0gKG5ld01vZGUuaWQgPiBvcHRpb25zLmJyZWFrcG9pbnQgJiYgKG1vYmlsZSB8fCBvbGRNb2RlLmlkID09PSB1bmRlZmluZWQpKTtcblxuICAgICAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBuZXcgdmlldyBzZXR0aW5nc1xuICAgICAgICAgICAgICAgIG1vYmlsZSA9IG5ld01vZGUuaWQgPD0gb3B0aW9ucy5icmVha3BvaW50O1xuICAgICAgICAgICAgICAgIG1vZGUgPSAkLmV4dGVuZCh7fSwgbmV3TW9kZSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoc3dpdGNoVG9Nb2JpbGUgfHwgc3dpdGNoVG9EZXNrdG9wKSB7XG4gICAgICAgICAgICAgICAgICAgIF9jbGVhclRpbWVvdXRzKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm1lbnVUeXBlICE9PSAndmVydGljYWwnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfY2xvc2VNZW51KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBDaGFuZ2UgdGhlIHZpc2liaWxpdHkgb2YgdGhlIG1lbnUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgLy8gaW4gY2FzZSBvZiBkZXNrdG9wIDwtPiBtb2JpbGUgdmlldyBjaGFuZ2VcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc3dpdGNoRWxlbWVudFBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc3dpdGNoVG9Nb2JpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfc3dpdGNoVG9Nb2JpbGVWaWV3KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9zd2l0Y2hUb0Rlc2t0b3BWaWV3KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfcmVwb3NpdGlvbk9wZW5MYXllcigpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFtb2JpbGUgJiYgb3B0aW9ucy5zd2l0Y2hFbGVtZW50UG9zaXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSB2aXNpYmlsaXR5IG9mIHRoZSBtZW51IGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSB2aWV3IGNoYW5nZSB3YXMgZGVza3RvcCB0byBkZXNrdG9wIG9ubHlcbiAgICAgICAgICAgICAgICAgICAgX3VwZGF0ZUNhdGVnb3J5TWVudSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIW1vYmlsZSkge1xuICAgICAgICAgICAgICAgICAgICBfcmVwb3NpdGlvbk9wZW5MYXllcigpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH07XG5cblxuLy8gIyMjIyMjIyMjIEVWRU5UIEhBTkRMRVIgIyMjIyMjIyMjI1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDaGFuZ2VzIHRoZSBlcGFuZCAvIGNvbGxhcHNlIHN0YXRlIG9mIHRoZSBtZW51LFxuICAgICAgICAgKiBpZiB0aGVyZSBpcyBhbiBzdWJtZW51LiBJbiB0aGUgb3RoZXIgY2FzZSBpdFxuICAgICAgICAgKiB3aWxsIGxldCBleGVjdXRlIHRoZSBkZWZhdWx0IGFjdGlvbiAobW9zdCB0aW1lc1xuICAgICAgICAgKiB0aGUgZXhlY3V0aW9uIG9mIGEgbGluaylcbiAgICAgICAgICogQHBhcmFtIHtvYmplY3R9ICBlICAgICAgIGpRdWVyeSBldmVudCBvYmplY3RcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9ICBtb2RlICAgIFRoZSBjdXJyZW50IHZpZXcgbW9kZSAoY2FuIGJlIFwibW9iaWxlXCIgb3IgXCJkZXNrdG9wXCJcbiAgICAgICAgICogQHBhcmFtIHtpbnRlZ2VyfSBkZWxheSAgIEN1c3RvbSBkZWxheSAoaW4gbXMpIGZvciBvcGVuaW5nIGNsb3NpbmcgdGhlIG1lbnUgKG5lZWRlZCBmb3IgY2xpY2sgLyB0b3VjaCBldmVudHMpXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX29wZW5NZW51ID0gZnVuY3Rpb24gKGUsIHR5cGUsIGRlbGF5KSB7XG5cbiAgICAgICAgICAgIHZhciAkc2VsZiA9ICQodGhpcyksXG4gICAgICAgICAgICAgICAgJHN1Ym1lbnUgPSAkc2VsZi5jaGlsZHJlbigndWwnKSxcbiAgICAgICAgICAgICAgICBsZW5ndGggPSAkc3VibWVudS5sZW5ndGgsXG4gICAgICAgICAgICAgICAgbGV2ZWwgPSAoJHN1Ym1lbnUubGVuZ3RoKSA/ICgkc3VibWVudS5kYXRhKCdsZXZlbCcpIHx8ICcwJykgOiA5OSxcbiAgICAgICAgICAgICAgICB2YWxpZFN1Ym1lbnUgPSAocGFyc2VJbnQobGV2ZWwsIDEwKSA8PSAyICYmIG1vZGUuaWQgPiBvcHRpb25zLmJyZWFrcG9pbnQpIHx8IG1vZGUuaWRcbiAgICAgICAgICAgICAgICAgICAgPD0gb3B0aW9ucy5icmVha3BvaW50O1xuXG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gJ21vYmlsZScpIHtcbiAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBPbmx5IGNoYW5nZSB0aGUgc3RhdGUgaWYgdGhlcmUgaXNcbiAgICAgICAgICAgIC8vIGEgc3VibWVudVxuICAgICAgICAgICAgaWYgKGxlbmd0aCAmJiB2YWxpZFN1Ym1lbnUpIHtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ21vYmlsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2ltcGx5IHRvZ2dsZSB0aGUgb3BlbkNsYXNzIGluIG1vYmlsZSBtb2RlXG4gICAgICAgICAgICAgICAgICAgICRzZWxmLnRvZ2dsZUNsYXNzKG9wdGlvbnMub3BlbkNsYXNzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBQZXJmb3JtIHRoZSBlbHNlIGNhc2UgZm9yIHRoZSBkZXNrdG9wIHZpZXdcblxuICAgICAgICAgICAgICAgICAgICB2YXIgdmlzaWJsZSA9ICRzZWxmLmhhc0NsYXNzKG9wdGlvbnMub3BlbkNsYXNzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlYXZlID0gJHNlbGYuaGFzQ2xhc3MoJ2xlYXZlJyksXG4gICAgICAgICAgICAgICAgICAgICAgICBhY3Rpb24gPSAoZS5kYXRhICYmIGUuZGF0YS5hY3Rpb24pID8gZS5kYXRhLmFjdGlvbiA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHZpc2libGUgJiYgbGVhdmUpID8gJ2VudGVyJyA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpc2libGUgPyAnbGVhdmUnIDogJ2VudGVyJztcblxuICAgICAgICAgICAgICAgICAgICAvLyBEZXBlbmRpbmcgb24gdGhlIHZpc2liaWxpdHkgYW5kIHRoZSBldmVudC1hY3Rpb24tcGFyYW1ldGVyXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBzdWJtZW51IGdldHMgb3BlbmVkIG9yIGNsb3NlZFxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZW50ZXInOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb25FbnRlciAmJiAhanNlLmxpYnMudGhlbWUuaW50ZXJhY3Rpb24uaXNNb3VzZURvd24oKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkVudGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2V0IGEgdGltZXIgZm9yIG9wZW5pbmcgaWYgdGhlIHN1Ym1lbnUgKGRlbGF5ZWQgb3BlbmluZylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2NsZWFyVGltZW91dHMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW50ZXJUaW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgYWxsIG9wZW5DbGFzcy1jbGFzc2VzIGZyb20gdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtZW51IGV4Y2VwdCB0aGUgZWxlbWVudCB0byBvcGVuIGFuZCBpdCdzIHBhcmVudHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZpbmQoJy4nICsgb3B0aW9ucy5vcGVuQ2xhc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm5vdCgkc2VsZilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAubm90KCRzZWxmLnBhcmVudHNVbnRpbCgkdGhpcywgJy4nICsgb3B0aW9ucy5vcGVuQ2xhc3MpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OX1NUT1AoKSwgW10pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUNsYXNzKG9wdGlvbnMub3BlbkNsYXNzKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGxpc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgnLmxlYXZlJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAudHJpZ2dlcihqc2UubGlicy50aGVtZS5ldmVudHMuVFJBTlNJVElPTl9TVE9QKCksIFtdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVDbGFzcygnbGVhdmUnKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gT3BlbiB0aGUgc3VibWVudVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNpdGlvbi5vcGVuID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2V0IGFuZCB1bnNldCB0aGUgXCJvbkVudGVyXCIgdG8gcHJldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gY2xvc2luZyB0aGUgbWVudSBpbW1lZGlhdGVseSBhZnRlciBvcGVuaW5nIGlmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgY3Vyc29yIGlzIGF0IGFuIHBsYWNlIG92ZXIgdGhlIG9wZW5pbmcgbWVudVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gKHRoaXMgY2FuIGhhcHBlbiBpZiBvdGhlciBjb21wb25lbnRzIHRyaWdnZXIgdGhlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBvcGVuIGV2ZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHNlbGZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAub2ZmKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OX0ZJTklTSEVEKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm9uZShqc2UubGlicy50aGVtZS5ldmVudHMuVFJBTlNJVElPTl9GSU5JU0hFRCgpLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uRW50ZXIgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OKCksIHRyYW5zaXRpb24pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnRyaWdnZXIoanNlLmxpYnMudGhlbWUuZXZlbnRzLk9QRU5fRkxZT1VUKCksIFskdGhpc10pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfcmVwb3NpdGlvbk9wZW5MYXllcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAodHlwZW9mIGRlbGF5ID09PSAnbnVtYmVyJykgPyBkZWxheSA6IG9wdGlvbnMuZW50ZXJEZWxheSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2xlYXZlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbkVudGVyID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gU2V0IGEgdGltZXIgZm9yIGNsb3NpbmcgaWYgdGhlIHN1Ym1lbnUgKGRlbGF5ZWQgY2xvc2luZylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfY2xlYXJUaW1lb3V0cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzZWxmLmFkZENsYXNzKCdsZWF2ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlYXZlVGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBvcGVuQ2xhc3MtY2xhc3NlcyBmcm9tIHRoZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtZW51IGV4Y2VwdCB0aGUgZWxlbWVudHMgcGFyZW50c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uLm9wZW4gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJGxpc3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5maW5kKCcuJyArIG9wdGlvbnMub3BlbkNsYXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLm5vdCgkc2VsZi5wYXJlbnRzVW50aWwoJHRoaXMsICcuJyArIG9wdGlvbnMub3BlbkNsYXNzKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5vZmYoanNlLmxpYnMudGhlbWUuZXZlbnRzLlRSQU5TSVRJT05fRklOSVNIRUQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5vbmUoanNlLmxpYnMudGhlbWUuZXZlbnRzLlRSQU5TSVRJT05fRklOSVNIRUQoKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9zZXRFdmVudFR5cGVDbGFzcygkc2VsZiwgJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICRzZWxmLnJlbW92ZUNsYXNzKCdsZWF2ZScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC50cmlnZ2VyKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5UUkFOU0lUSU9OKCksIHRyYW5zaXRpb24pO1xuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCAodHlwZW9mIGRlbGF5ID09PSAnbnVtYmVyJykgPyBkZWxheSA6IG9wdGlvbnMubGVhdmVEZWxheSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH1cblxuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFdmVudCBoYW5kbGVyIGZvciB0aGUgY2xpY2sgLyBtb3VzZWVudGVyIC8gbW91c2VsZWF2ZSBldmVudFxuICAgICAgICAgKiBvbiB0aGUgbmF2aWdhdGlvbiBsaSBlbGVtZW50cy4gSXQgY2hlY2tzIGlmIHRoZSBldmVudCB0eXBlXG4gICAgICAgICAqIGlzIHN1cHBvcnRlZCBmb3IgdGhlIGN1cnJlbnQgdmlldyB0eXBlIGFuZCBjYWxscyB0aGVcbiAgICAgICAgICogb3Blbk1lbnUtZnVuY3Rpb24gaWYgc28uXG4gICAgICAgICAqIEBwYXJhbSAgICAgICB7b2JqZWN0fSAgICBlICAgICAgICAgICBqUXVlcnkgZXZlbnQgb2JqZWN0XG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX21vdXNlSGFuZGxlciA9IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICB2YXIgJHNlbGYgPSAkKHRoaXMpLFxuICAgICAgICAgICAgICAgIHZpZXdwb3J0ID0gbW9kZS5pZCA8PSBvcHRpb25zLmJyZWFrcG9pbnQgPyAnbW9iaWxlJyA6ICdkZXNrdG9wJyxcbiAgICAgICAgICAgICAgICBldmVudHMgPSAob3B0aW9ucy5ldmVudHMgJiYgb3B0aW9ucy5ldmVudHNbdmlld3BvcnRdKSA/IG9wdGlvbnMuZXZlbnRzW3ZpZXdwb3J0XSA6IFtdO1xuXG4gICAgICAgICAgICBfc2V0RXZlbnRUeXBlQ2xhc3MoJHNlbGYsICdtb3VzZScpO1xuICAgICAgICAgICAgaWYgKCQuaW5BcnJheShlLmRhdGEuZXZlbnQsIGV2ZW50cykgPiAtMSkge1xuICAgICAgICAgICAgICAgIF9vcGVuTWVudS5jYWxsKCRzZWxmLCBlLCB2aWV3cG9ydCwgZS5kYXRhLmRlbGF5KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGVyZm9ybSBuYXZpZ2F0aW9uIGZvciBjdXN0b20gbGlua3MgYW5kIGNhdGVnb3J5IGxpbmtzIG9uIHRvdWNoIGRldmljZXMgaWYgbm8gc3ViY2F0ZWdvcmllcyBhcmUgZm91bmQuXG4gICAgICAgICAgICBpZiAoKCRzZWxmLmhhc0NsYXNzKCdjdXN0b20nKSB8fCAoaXNUb3VjaERldmljZSAmJiAkc2VsZi5jaGlsZHJlbigndWwnKS5sZW5ndGggPT0gMCkpXG4gICAgICAgICAgICAgICAgJiYgZS5kYXRhLmV2ZW50ID09PSAnY2xpY2snICYmICEkc2VsZi5maW5kKCdmb3JtJykubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoJHNlbGYuZmluZCgnYScpLmF0dHIoJ3RhcmdldCcpID09PSAnX2JsYW5rJykge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cub3Blbigkc2VsZi5maW5kKCdhJykuYXR0cignaHJlZicpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gJHNlbGYuZmluZCgnYScpLmF0dHIoJ2hyZWYnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEV2ZW50IGhhbmRsZXIgZm9yIHRoZSB0b3VjaHN0YXJ0IGV2ZW50IChvciBcInBvaW50ZXJkb3duXCJcbiAgICAgICAgICogZGVwZW5kaW5nIG9uIHRoZSBicm93c2VyKS4gSXQgcmVtb3ZlcyB0aGUgb3RoZXIgY3JpdGljYWxcbiAgICAgICAgICogZXZlbnQgaGFuZGxlciAodGhhdCB3b3VsZCBvcGVuIHRoZSBtZW51KSBmcm9tIHRoZSBsaXN0XG4gICAgICAgICAqIGVsZW1lbnQgaWYgdGhlIHRoZSBtb3VzZWVudGVyIHdhcyBleGVjdXRlZCBiZWZvcmUgYW5kXG4gICAgICAgICAqIGEgY2xpY2sgb3IgdG91Y2ggZXZlbnQgd2lsbCBiZSBwZXJmb3JtZWQgYWZ0ZXJ3YXJkcy4gVGhpc1xuICAgICAgICAgKiBpcyBuZWVkZWQgdG8gcHJldmVudCB0aGUgYnJvd3NlciBlbmdpbmUgd29ya2Fyb3VuZHMgd2hpY2hcbiAgICAgICAgICogd2lsbCBhdXRvbWF0aWNhbGx5IHBlcmZvcm0gbW91c2UgLyBjbGljay1ldmVudHMgb24gdG91Y2hcbiAgICAgICAgICogYWxzby5cbiAgICAgICAgICogQHByaXZhdGVcbiAgICAgICAgICovXG4gICAgICAgIHZhciBfdG91Y2hIYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgICAgIHZhciAkc2VsZiA9ICQodGhpcyksXG4gICAgICAgICAgICAgICAgdmlld3BvcnQgPSBtb2RlLmlkIDw9IG9wdGlvbnMuYnJlYWtwb2ludCA/ICdtb2JpbGUnIDogJ2Rlc2t0b3AnLFxuICAgICAgICAgICAgICAgIGV2ZW50cyA9IChvcHRpb25zLmV2ZW50cyAmJiBvcHRpb25zLmV2ZW50c1t2aWV3cG9ydF0pID8gb3B0aW9ucy5ldmVudHNbdmlld3BvcnRdIDogW107XG5cbiAgICAgICAgICAgICRsaXN0LmZpbmQoJy5lbnRlci1jYXRlZ29yeScpLnNob3coKTtcbiAgICAgICAgICAgICRsaXN0LmZpbmQoJy5kcm9wZG93biA+IGEnKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoZS5kYXRhLnR5cGUgPT09ICdzdGFydCcpIHtcbiAgICAgICAgICAgICAgICB0b3VjaGVTdGFydEV2ZW50ID0ge2V2ZW50OiBlLCB0aW1lc3RhbXA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpLCB0b3A6ICR3aW5kb3cuc2Nyb2xsVG9wKCl9O1xuICAgICAgICAgICAgICAgICRsaXN0Lm9mZignbW91c2VlbnRlci5tZW51IG1vdXNlbGVhdmUubWVudScpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICgkLmluQXJyYXkoJ3RvdWNoJywgZXZlbnRzKSA+IC0xICYmICFfdG91Y2hNb3ZlRGV0ZWN0KGUpKSB7XG4gICAgICAgICAgICAgICAgX3NldEV2ZW50VHlwZUNsYXNzKCRzZWxmLCAndG91Y2gnKTtcblxuICAgICAgICAgICAgICAgIGlmICgkLmluQXJyYXkoJ2hvdmVyJywgZXZlbnRzKSA9PT0gLTEgfHwgdG91Y2hFdmVudHMuc3RhcnQgIT09ICdwb2ludGVyZG93bicpIHtcbiAgICAgICAgICAgICAgICAgICAgX29wZW5NZW51LmNhbGwoJHNlbGYsIGUsIHZpZXdwb3J0KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAkbGlzdC5vbignbW91c2VsZWF2ZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgJGxpc3RcbiAgICAgICAgICAgICAgICAgICAgICAgIC5vbignbW91c2VlbnRlci5tZW51JywgJ2xpJywge2V2ZW50OiAnaG92ZXInfSwgX21vdXNlSGFuZGxlcilcbiAgICAgICAgICAgICAgICAgICAgICAgIC5vbignbW91c2VsZWF2ZS5tZW51JywgJ2xpJywge2V2ZW50OiAnaG92ZXInLCBhY3Rpb246ICdsZWF2ZSd9LCBfbW91c2VIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgfVxuXG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFN0b3JlcyB0aGUgbGFzdCB0b3VjaCBwb3NpdGlvbiBvbiB0b3VjaG1vdmVcbiAgICAgICAgICogQHBhcmFtICAgICAgIGUgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcHJpdmF0ZVxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIF90b3VjaE1vdmVIYW5kbGVyID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIHRvdWNoZUVuZEV2ZW50ID0ge2V2ZW50OiBlLCB0aW1lc3RhbXA6IG5ldyBEYXRlKCkuZ2V0VGltZSgpLCB0b3A6ICR3aW5kb3cuc2Nyb2xsVG9wKCl9O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFdmVudCBoYW5kbGVyIGZvciBjbG9zaW5nIHRoZSBtZW51IGlmXG4gICAgICAgICAqIHRoZSB1c2VyIGludGVyYWN0cyB3aXRoIHRoZSBwYWdlXG4gICAgICAgICAqIG91dHNpZGUgb2YgdGhlIG1lbnVcbiAgICAgICAgICogQHBhcmFtICAgICAgIHtvYmplY3R9ICAgIGUgICAgICAgalF1ZXJ5IGV2ZW50IG9iamVjdFxuICAgICAgICAgKiBAcGFyYW0gICAgICAge29iamVjdH0gICAgZCAgICAgICBqUXVlcnkgc2VsZWN0aW9uIG9mIHRoZSBldmVudCBlbWl0dGVyXG4gICAgICAgICAqIEBwcml2YXRlXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgX2Nsb3NlRmx5b3V0ID0gZnVuY3Rpb24gKGUsIGQpIHtcbiAgICAgICAgICAgIGlmIChkICE9PSAkdGhpcyAmJiAkdGhpcy5maW5kKCQoZS50YXJnZXQpKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb3BlbiBhbmQgY2xvc2UgdGltZXJcbiAgICAgICAgICAgICAgICBfY2xlYXJUaW1lb3V0cygpO1xuXG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCBzdGF0ZS1jbGFzc2VzIGZyb20gdGhlIG1lbnVcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgnLnRvdWNoLCAubW91c2UsIC5sZWF2ZSwgLicgKyBvcHRpb25zLm9wZW5DbGFzcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVDbGFzcygndG91Y2ggbW91c2UgbGVhdmUgJyArIG9wdGlvbnMub3BlbkNsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIF9vbkNsaWNrQWNjb3JkaW9uID0gZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgICAgIGlmICgkKHRoaXMpLnBhcmVudHMoJy5uYXZiYXItdG9wYmFyLWl0ZW0nKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoJCh0aGlzKS5oYXNDbGFzcygnZHJvcGRvd24nKSkge1xuICAgICAgICAgICAgICAgIGlmICgkKHRoaXMpLmhhc0NsYXNzKG9wdGlvbnMub3BlbkNsYXNzKSkge1xuICAgICAgICAgICAgICAgICAgICAkKHRoaXMpXG4gICAgICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3Mob3B0aW9ucy5vcGVuQ2xhc3MpXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgnLicgKyBvcHRpb25zLm9wZW5DbGFzcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5yZW1vdmVDbGFzcyhvcHRpb25zLm9wZW5DbGFzcyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJCh0aGlzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmFkZENsYXNzKG9wdGlvbnMub3BlbkNsYXNzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnBhcmVudHNVbnRpbCgkdGhpcywgJ2xpJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hZGRDbGFzcyhvcHRpb25zLm9wZW5DbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gJCh0aGlzKS5maW5kKCdhJykuYXR0cignaHJlZicpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBfYmluZEhvcml6b250YWxFdmVudEhhbmRsZXJzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJGxpc3RcbiAgICAgICAgICAgICAgICAub24odG91Y2hFdmVudHMuc3RhcnQgKyAnLm1lbnUnLCAnbGknLCB7dHlwZTogJ3N0YXJ0J30sIF90b3VjaEhhbmRsZXIpXG4gICAgICAgICAgICAgICAgLm9uKHRvdWNoRXZlbnRzLm1vdmUgKyAnLm1lbnUnLCAnbGknLCB7dHlwZTogJ3N0YXJ0J30sIF90b3VjaE1vdmVIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbih0b3VjaEV2ZW50cy5lbmQgKyAnLm1lbnUnLCAnbGknLCB7dHlwZTogJ2VuZCd9LCBfdG91Y2hIYW5kbGVyKVxuICAgICAgICAgICAgICAgIC5vbignY2xpY2subWVudScsICdsaScsIHtldmVudDogJ2NsaWNrJywgJ2RlbGF5JzogMH0sIF9tb3VzZUhhbmRsZXIpXG4gICAgICAgICAgICAgICAgLm9uKCdtb3VzZWVudGVyLm1lbnUnLCAnbGknLCB7ZXZlbnQ6ICdob3ZlcicsIGFjdGlvbjogJ2VudGVyJ30sIF9tb3VzZUhhbmRsZXIpXG4gICAgICAgICAgICAgICAgLm9uKCdtb3VzZWxlYXZlLm1lbnUnLCAnbGknLCB7ZXZlbnQ6ICdob3ZlcicsIGFjdGlvbjogJ2xlYXZlJ30sIF9tb3VzZUhhbmRsZXIpO1xuXG4gICAgICAgICAgICAkYm9keVxuICAgICAgICAgICAgICAgIC5vbihqc2UubGlicy50aGVtZS5ldmVudHMuTUVOVV9SRVBPU0lUSU9ORUQoKSwgX3VwZGF0ZUNhdGVnb3J5TWVudSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIF91bmJpbmRIb3Jpem9udGFsRXZlbnRIYW5kbGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICRsaXN0XG4gICAgICAgICAgICAgICAgLm9mZih0b3VjaEV2ZW50cy5zdGFydCArICcubWVudScsICdsaScpXG4gICAgICAgICAgICAgICAgLm9mZih0b3VjaEV2ZW50cy5tb3ZlICsgJy5tZW51JywgJ2xpJylcbiAgICAgICAgICAgICAgICAub2ZmKHRvdWNoRXZlbnRzLmVuZCArICcubWVudScsICdsaScpXG4gICAgICAgICAgICAgICAgLm9mZignY2xpY2subWVudScsICdsaScpXG4gICAgICAgICAgICAgICAgLm9mZignbW91c2VlbnRlci5tZW51JywgJ2xpJylcbiAgICAgICAgICAgICAgICAub2ZmKCdtb3VzZWxlYXZlLm1lbnUnLCAnbGknKTtcbiAgICAgICAgfTtcblxuLy8gIyMjIyMjIyMjIyBJTklUSUFMSVpBVElPTiAjIyMjIyMjIyMjXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEluaXQgZnVuY3Rpb24gb2YgdGhlIHdpZGdldFxuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICovXG4gICAgICAgIG1vZHVsZS5pbml0ID0gZnVuY3Rpb24gKGRvbmUpIHtcbiAgICAgICAgICAgIC8vIEB0b2RvIEdldHRpbmcgdGhlIFwidG91Y2hFdmVudHNcIiBjb25maWcgdmFsdWUgcHJvZHVjZXMgcHJvYmxlbXMgaW4gdGFibGV0IGRldmljZXMuXG4gICAgICAgICAgICB0b3VjaEV2ZW50cyA9IGpzZS5jb3JlLmNvbmZpZy5nZXQoJ3RvdWNoJyk7XG4gICAgICAgICAgICB0cmFuc2l0aW9uLmNsYXNzT3BlbiA9IG9wdGlvbnMub3BlbkNsYXNzO1xuXG4gICAgICAgICAgICBfZ2V0U2VsZWN0aW9ucygpO1xuICAgICAgICAgICAgX3Jlc2V0SW5pdGlhbENzcygpO1xuXG4gICAgICAgICAgICAkYm9keVxuICAgICAgICAgICAgICAgIC5vbihqc2UubGlicy50aGVtZS5ldmVudHMuQlJFQUtQT0lOVCgpLCBfYnJlYWtwb2ludEhhbmRsZXIpXG4gICAgICAgICAgICAgICAgLm9uKGpzZS5saWJzLnRoZW1lLmV2ZW50cy5PUEVOX0ZMWU9VVCgpICsgJyBjbGljayAnICsgdG91Y2hFdmVudHMuZW5kLCBfY2xvc2VGbHlvdXQpO1xuXG4gICAgICAgICAgICAkKCcuY2xvc2UtbWVudS1jb250YWluZXInKS5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfSlcblxuICAgICAgICAgICAgJCgnLmNsb3NlLWZseW91dCcpLm9uKCdjbGljaycsIF9jbG9zZU1lbnUpO1xuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ2hvcml6b250YWwnKSB7XG4gICAgICAgICAgICAgICAgX2JpbmRIb3Jpem9udGFsRXZlbnRIYW5kbGVycygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5tZW51VHlwZSA9PT0gJ3ZlcnRpY2FsJykge1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmFjY29yZGlvbiA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5vbignY2xpY2snLCAnbGknLCBfb25DbGlja0FjY29yZGlvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgbm8gdG9wIGhlYWRlciB3ZSBtdXN0IGNyZWF0ZSBkdW1teSBodG1sIGJlY2F1c2Ugb3RoZXIgbW9kdWxlcyB3aWxsIG5vdCB3b3JrIGNvcnJlY3RseVxuICAgICAgICAgICAgICAgIGlmICgkKCcjY2F0ZWdvcmllcycpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaHRtbCA9ICc8ZGl2IGlkPVwiY2F0ZWdvcmllc1wiPjxkaXYgY2xhc3M9XCJuYXZiYXItY29sbGFwc2UgY29sbGFwc2VcIj4nXG4gICAgICAgICAgICAgICAgICAgICAgICArICc8bmF2IGNsYXNzPVwibmF2YmFyLWRlZmF1bHQgbmF2YmFyLWNhdGVnb3JpZXMgaGlkZGVuXCI+PC9uYXY+PC9kaXY+PC9kaXY+JztcbiAgICAgICAgICAgICAgICAgICAgJCgnI2hlYWRlcicpLmFwcGVuZChodG1sKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF9icmVha3BvaW50SGFuZGxlcigpO1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFN0b3AgdGhlIHByb3BhZ2F0aW9uIG9mIHRoZSBldmVudHMgaW5zaWRlIHRoaXMgY29udGFpbmVyXG4gICAgICAgICAgICAgKiAoV29ya2Fyb3VuZCBmb3IgdGhlIFwibW9yZVwiLWRyb3Bkb3duKVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICAkdGhpc1xuICAgICAgICAgICAgICAgIC5maW5kKCcuJyArIG9wdGlvbnMuaWdub3JlQ2xhc3MpXG4gICAgICAgICAgICAgICAgLm9uKCdtb3VzZWxlYXZlLm1lbnUgbW91c2VlbnRlci5tZW51IGNsaWNrLm1lbnUgJyArIHRvdWNoRXZlbnRzLnN0YXJ0ICsgJyAnXG4gICAgICAgICAgICAgICAgICAgICsgdG91Y2hFdmVudHMuZW5kLCAnbGknLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5vcGVuQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgdmFyICRhY3RpdmUgPSAkdGhpcy5maW5kKCcuYWN0aXZlJyk7XG4gICAgICAgICAgICAgICAgJGFjdGl2ZVxuICAgICAgICAgICAgICAgICAgICAucGFyZW50c1VudGlsKCR0aGlzLCAnbGknKVxuICAgICAgICAgICAgICAgICAgICAuYWRkQ2xhc3MoJ29wZW4nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJCgnbGkuY3VzdG9tLWVudHJpZXMgYScpLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB2YXIgdmlld3BvcnQgPSBtb2RlLmlkIDw9IG9wdGlvbnMuYnJlYWtwb2ludCA/ICdtb2JpbGUnIDogJ2Rlc2t0b3AnO1xuXG4gICAgICAgICAgICBpZiAodmlld3BvcnQgPT0gJ21vYmlsZScpIHtcbiAgICAgICAgICAgICAgICAkKCcubGV2ZWwtMScpLmNzcygncGFkZGluZy1ib3R0b20nLCAnMjAwcHgnKTsgLy8gVGhpcyBwYWRkaW5nIGNvcnJlY3RzIGV4cGFuZC9jb2xsYXBzZSBiZWhhdmlvciBvZiBsb3dlciBtZW51IGl0ZW1zIGluIHZhcmlvdXMgbW9iaWxlIGJyb3dzZXJzLlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkb25lKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJuIGRhdGEgdG8gd2lkZ2V0IGVuZ2luZVxuICAgICAgICByZXR1cm4gbW9kdWxlO1xuICAgIH0pO1xuIl19

Youez - 2016 - github.com/yon3zu
LinuXploit