PageSourceSearch

https://centercityteam.com/wp-content/plugins/hji-membership/resou…/scripts/build/accessibility.js?ver=6.5.12

js centercityteam.com collected 2026-10-02 13:19:56 UTC 267,512 bytes, 3,580 lines download raw bytes

1/*
2*   This content is licensed according to the W3C Software License at
3*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
4*
5*   Simple accordion pattern example
6*/
7
8'use strict';
9
10var accordionObject = {};
11var accordionArray = [];
12var mobileViewFlag = false;
13
14function allyAccordionInit(cssClass, dynamic) {
15    document.querySelectorAll(cssClass).forEach(function (accordion) {
16        accordionObject = {
17            trigger: '',
18            mouseClick: '',
19            keydown: '',
20            focus: '',
21            blur: ''
22        };
23
24        // Allow for multiple accordion sections to be expanded at the same time
25        var allowMultiple = accordion.hasAttribute('data-allow-multiple');
26        // Allow for each toggle to both open and close individually
27        var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');
28
29        // Create the array of toggle elements for the accordion group
30        var triggers = Array.prototype.slice.call(accordion.querySelectorAll('.accordion-trigger'));
31        var panels = Array.prototype.slice.call(accordion.querySelectorAll('.accordion-panel'));
32
33        Array.prototype.forEach.call(accordion.getElementsByClassName('accordion-trigger'), function(element) {
34            function accordionClick(target) {
35                // Check if the current toggle is expanded.
36                var isExpanded = target.getAttribute('aria-expanded') == 'true';
37                var active = accordion.querySelector('[aria-expanded="true"]');
38
39                // without allowMultiple, close the open accordion
40                if (!allowMultiple && active && active !== target) {
41                    // Set the expanded state on the triggering element
42                    active.setAttribute('aria-expanded', 'false');
43                    // Hide the accordion sections, using aria-controls to specify the desired section
44                    document.getElementById(active.getAttribute('aria-controls')).setAttribute('hidden', '');
45
46                    // When toggling is not allowed, clean up disabled state
47                    if (!allowToggle) {
48                        active.removeAttribute('aria-disabled');
49                    }
50                }
51
52                if (!isExpanded) {
53                    // Set the expanded state on the triggering element
54                    target.setAttribute('aria-expanded', 'true');
55                    // Hide the accordion sections, using aria-controls to specify the desired section
56                    document.getElementById(target.getAttribute('aria-controls')).removeAttribute('hidden');
57
58                    // If toggling is not allowed, set disabled state on trigger
59                    if (!allowToggle) {
60                        target.setAttribute('aria-disabled', 'true');
61                    }
62                } else if (allowToggle && isExpanded) {
63                    // Set the expanded state on the triggering element
64                    target.setAttribute('aria-expanded', 'false');
65                    // Hide the accordion sections, using aria-controls to specify the desired section
66                    document.getElementById(target.getAttribute('aria-controls')).setAttribute('hidden', '');
67                }
68            }
69
70            var mouseClick = function (event) {
71                var target = this;
72                event.preventDefault();
73                event.stopPropagation();
74
75
76                accordionClick(target);
77            };
78            element.addEventListener('click', mouseClick);
79
80
81            // Bind keyboard behaviors on the main accordion container
82            var keyDown = function (event) {
83                var target = this;
84                var key = event.which.toString();
85                var isExpanded = target.getAttribute('aria-expanded') == 'true';
86                var allowToggle = (allowMultiple) ? allowMultiple : accordion.hasAttribute('data-allow-toggle');
87
88                // 33 = Page Up, 34 = Page Down
89                var ctrlModifier = (event.ctrlKey && key.match(/33|34/));
90
91                // Is this coming from an accordion header?
92                if (target.classList.contains('accordion-trigger')) {
93                    // Up/ Down arrow and Control + Page Up/ Page Down keyboard operations
94                    // 38 = Up, 40 = Down
95                    if (key.match(/38|40/) || ctrlModifier) {
96                        var index = triggers.indexOf(target);
97                        var direction = (key.match(/34|40/)) ? 1 : -1;
98                        var length = triggers.length;
99                        var newIndex = (index + length + direction) % length;
100
101                        triggers[newIndex].focus();
102
103                        event.preventDefault();
104                    }
105                    else if (key.match(/35|36/)) {
106                        // 35 = End, 36 = Home keyboard operations
107                        switch (key) {
108                            // Go to first accordion
109                            case '36':
110                                triggers[0].focus();
111                                break;
112                            // Go to last accordion
113                            case '35':
114                                triggers[triggers.length - 1].focus();
115                                break;
116                        }
117                        event.preventDefault();
118
119                    } else if (key.match(/13|32/)) {
120                        accordionClick(target);
121                        event.preventDefault();
122                    }
123
124                }
125            };
126            element.addEventListener('keydown', keyDown);
127
128        // These are used to style the accordion when one of the buttons has focus
129            var focus = function (event) {
130                accordion.classList.add('focus');
131                if (this.getAttribute('aria-expanded') === 'false') {
132                    this.setAttribute('tabindex', '0');
133                }
134            };
135            element.addEventListener('focus', focus);
136
137            var blur = function (event) {
138                accordion.classList.remove('focus');
139                if (this.getAttribute('aria-expanded') === 'false') {
140                    this.setAttribute('tabindex', '-1');
141                }
142            };
143            element.addEventListener('blur', blur);
144
145
146        // Minor setup: will set disabled state, via aria-disabled, to an
147        // expanded/ active accordion which is not allowed to be toggled close
148            if (!allowToggle) {
149                // Get the first expanded/ active accordion
150                var expanded = accordion.querySelector('[aria-expanded="true"]');
151
152                // If an expanded/ active accordion is found, disable
153                if (expanded) {
154                    expanded.setAttribute('aria-disabled', 'true');
155                }
156            }
157
158
159            if (dynamic) {
160                accordionObject.trigger = element;
161                accordionObject.keydown = keyDown;
162                accordionObject.mouseClick = mouseClick;
163                accordionObject.blur = blur;
164                accordionObject.focus = focus;
165                accordionArray.push(accordionObject);
166            }
167        });
168    });
169}
170
171allyAccordionInit('.accordion', false);
172
173function allyDesktopAccordionInit() {
174    jQuery(document).find('[data-accordion]').each(function () {
175        jQuery(this).addClass('accordion');
176        jQuery('.accordion-panel').each(function(index) {
177            var $this = jQuery(this);
178
179            $this
180                .attr('role', 'region')
181                .attr('aria-labelledby', $this.data('labelledby'))
182            ;
183            if (index !== 0) {
184                $this.attr('hidden', '');
185            }
186        });
187        jQuery('.accordion-trigger')
188            .addClass('cursor-pointer')
189            .attr('role', 'button')
190            .each(function(index) {
191                var $this = jQuery(this);
192                $this.attr('aria-controls', $this.data('controls'));
193
194                if (index === 0) {
195                    $this.attr('tabindex', '0');
196
197                    if (!$this.hasClass('is-mobile')) {
198                        $this
199                            .attr('aria-expanded', 'true')
200                            .attr('aria-disabled', 'true')
201                        ;
202                    } else {
203                        $this
204                            .attr('aria-expanded', 'false')
205                            .attr('aria-disabled', 'false')
206                        ;
207                    }
208                } else {
209                    $this
210                        .attr('aria-expanded', 'false')
211                        .attr('aria-disabled', 'false')
212                        .attr('tabindex', '-1')
213                    ;
214                }
215            })
216        ;
217    });
218}
219
220function displayWindowSize() {
221    // Get width and height of the window excluding scrollbars
222    var w = document.documentElement.clientWidth;
223
224    if ((w < 768) && !mobileViewFlag) {
225        allyDesktopAccordionInit();
226        allyAccordionInit('.accordion', true);
227        mobileViewFlag = true;
228    } else if ((w > 768) && mobileViewFlag) {
229        jQuery(document).find('[data-accordion]').each(function () {
230            var $this = jQuery(this);
231            $this.removeClass('accordion');
232
233            $this.find('.accordion-trigger').each(function() {
234                jQuery(this)
235                    .removeClass('cursor-pointer')
236                    .removeAttr('role')
237                    .removeAttr('aria-expanded')
238                    .removeAttr('aria-disabled')
239                    .removeAttr('aria-controls')
240                ;
241            });
242
243            $this.find('.accordion-panel').each(function() {
244                jQuery(this)
245                    .prop('hidden', false)
246                    .removeAttr('role')
247                    .removeAttr('aria-labelledby')
248                ;
249            });
250        });
251
252        var $element;
253        for (var i = 0; i < accordionArray.length; i++) {
254            $element = accordionArray[i];
255            $element.trigger.removeEventListener('mouseClick', $element.mouseClick);
256            $element.trigger.removeEventListener('keyDown', $element.keydown);
257            $element.trigger.removeEventListener('focus', $element.focus);
258            $element.trigger.removeEventListener('blur', $element.blur);
259        }
260        accordionArray = [];
261
262        mobileViewFlag = false;
263    }
264}
265
266// Attaching the event listener function to window's resize event
267window.addEventListener("resize", displayWindowSize);
268
269jQuery(function($) {
270    var w = document.documentElement.clientWidth;
271    if (w < 768) {
272        mobileViewFlag = true;
273        allyDesktopAccordionInit();
274        allyAccordionInit('.accordion', true);
275    }
276});
277
278/**
279 * @namespace aria
280 */
281
282var aria = aria || {};
283
284/**
285 * @desc
286 *  Key code constants
287 */
288aria.KeyCode = {
289    BACKSPACE: 8,
290    TAB: 9,
291    RETURN: 13,
292    ESC: 27,
293    SPACE: 32,
294    PAGE_UP: 33,
295    PAGE_DOWN: 34,
296    END: 35,
297    HOME: 36,
298    LEFT: 37,
299    UP: 38,
300    RIGHT: 39,
301    DOWN: 40,
302    DELETE: 46
303};
304
305aria.Utils = aria.Utils || {};
306
307// Polyfill src https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
308aria.Utils.matches = function (element, selector) {
309    if (!Element.prototype.matches) {
310        Element.prototype.matches =
311            Element.prototype.matchesSelector ||
312            Element.prototype.mozMatchesSelector ||
313            Element.prototype.msMatchesSelector ||
314            Element.prototype.oMatchesSelector ||
315            Element.prototype.webkitMatchesSelector ||
316            function (s) {
317                var matches = element.parentNode.querySelectorAll(s);
318                var i = matches.length;
319                while (--i >= 0 && matches.item(i) !== this) {}
320                return i > -1;
321            };
322    }
323
324    return element.matches(selector);
325};
326
327aria.Utils.remove = function (item) {
328    if (item.remove && typeof item.remove === 'function') {
329        return item.remove();
330    }
331    if (item.parentNode &&
332        item.parentNode.removeChild &&
333        typeof item.parentNode.removeChild === 'function') {
334        return item.parentNode.removeChild(item);
335    }
336    return false;
337};
338
339aria.Utils.isFocusable = function (element) {
340    if (element.tabIndex > 0 || (element.tabIndex === 0 && element.getAttribute('tabIndex') !== null)) {
341        return true;
342    }
343
344    if (element.disabled) {
345        return false;
346    }
347
348    switch (element.nodeName) {
349        case 'A':
350            return !!element.href && element.rel != 'ignore';
351        case 'INPUT':
352            return element.type != 'hidden' && element.type != 'file';
353        case 'BUTTON':
354        case 'SELECT':
355        case 'TEXTAREA':
356            return true;
357        default:
358            return false;
359    }
360};
361
362aria.Utils.getAncestorBySelector = function (element, selector) {
363    if (!aria.Utils.matches(element, selector + ' ' + element.tagName)) {
364        // Element is not inside an element that matches selector
365        return null;
366    }
367
368    // Move up the DOM tree until a parent matching the selector is found
369    var currentNode = element;
370    var ancestor = null;
371    while (ancestor === null) {
372        if (aria.Utils.matches(currentNode.parentNode, selector)) {
373            ancestor = currentNode.parentNode;
374        }
375        else {
376            currentNode = currentNode.parentNode;
377        }
378    }
379
380    return ancestor;
381};
382
383aria.Utils.hasClass = function (element, className) {
384    return (new RegExp('(\\s|^)' + className + '(\\s|$)')).test(element.className);
385};
386
387aria.Utils.addClass = function (element, className) {
388    if (!aria.Utils.hasClass(element, className)) {
389        element.className += ' ' + className;
390    }
391};
392
393aria.Utils.removeClass = function (element, className) {
394    var classRegex = new RegExp('(\\s|^)' + className + '(\\s|$)');
395    element.className = element.className.replace(classRegex, ' ').trim();
396};
397
398aria.Utils.bindMethods = function (object /* , ...methodNames */) {
399    var methodNames = Array.prototype.slice.call(arguments, 1);
400    methodNames.forEach(function (method) {
401        object[method] = object[method].bind(object);
402    });
403};
404
405/*jshint esversion: 6 */
406
407/*
408*   This content is licensed according to the W3C Software License at
409*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
410*
411*/
412
413class BlvdAccessibilityMenuButton {
414
415    constructor(domNode) {
416        this.domNode = domNode;
417        this.popupMenu = false;
418
419        this.hasFocus = false;
420        this.hasHover = false;
421
422        this.keyCode = Object.freeze({
423            'TAB': 9,
424            'RETURN': 13,
425            'ESC': 27,
426            'SPACE': 32,
427            'PAGEUP': 33,
428            'PAGEDOWN': 34,
429            'END': 35,
430            'HOME': 36,
431            'LEFT': 37,
432            'UP': 38,
433            'RIGHT': 39,
434            'DOWN': 40
435        });
436    }
437
438}
439
440BlvdAccessibilityMenuButton.prototype.init = function () {
441
442    this.domNode.setAttribute('aria-haspopup', 'true');
443    this.domNode.addEventListener('keydown',    this.handleKeydown.bind(this));
444    this.domNode.addEventListener('click',      this.handleClick.bind(this));
445    this.domNode.addEventListener('focus',      this.handleFocus.bind(this));
446    this.domNode.addEventListener('blur',       this.handleBlur.bind(this));
447    this.domNode.addEventListener('mouseover',  this.handleMouseover.bind(this));
448    this.domNode.addEventListener('mouseout',   this.handleMouseout.bind(this));
449
450    // initialize pop up menus
451
452    const popupMenu = document.getElementById(this.domNode.getAttribute('aria-controls'));
453
454    if (popupMenu) {
455        this.popupMenu = new BlvdAccessibilityPopupMenuLinks(popupMenu, this);
456        this.popupMenu.init();
457    }
458
459};
460
461BlvdAccessibilityMenuButton.prototype.handleKeydown = function (event) {
462    let flag = false;
463
464    switch (event.keyCode) {
465        case this.keyCode.SPACE:
466        case this.keyCode.RETURN:
467        case this.keyCode.DOWN:
468            if (this.popupMenu) {
469                this.popupMenu.open();
470                this.popupMenu.setFocusToFirstItem();
471            }
472            flag = true;
473            break;
474
475        case this.keyCode.UP:
476            if (this.popupMenu) {
477                this.popupMenu.open();
478                this.popupMenu.setFocusToLastItem();
479                flag = true;
480            }
481            break;
482
483        default:
484            break;
485    }
486
487    if (flag) {
488        event.stopPropagation();
489        event.preventDefault();
490    }
491};
492
493BlvdAccessibilityMenuButton.prototype.handleClick = function (event) {
494    if (this.domNode.getAttribute('aria-expanded') == 'true') {
495        this.popupMenu.close(true);
496    }
497    else {
498        this.popupMenu.open();
499        this.popupMenu.setFocusToFirstItem();
500    }
501};
502
503BlvdAccessibilityMenuButton.prototype.handleFocus = function (event) {
504    this.popupMenu.hasFocus = true;
505};
506
507BlvdAccessibilityMenuButton.prototype.handleBlur = function (event) {
508    this.popupMenu.hasFocus = false;
509};
510
511BlvdAccessibilityMenuButton.prototype.handleMouseover = function (event) {
512    this.hasHover = true;
513    this.popupMenu.open();
514};
515
516BlvdAccessibilityMenuButton.prototype.handleMouseout = function (event) {
517    this.hasHover = false;
518    setTimeout(this.popupMenu.close.bind(this.popupMenu, false), 300);
519};
520
521class BlvdAccessibilityPopupMenuLinks {
522
523    constructor(domNode, controllerObj) {
524        const  msgPrefix = 'BlvdAccessibilityPopupMenuLinks constructor argument domNode ';
525
526        // Check whether domNode is a DOM element
527        if (!(domNode instanceof Element)) {
528            throw new TypeError(msgPrefix + 'is not a DOM Element.');
529        }
530
531        // Check whether domNode has child elements
532        if (domNode.childElementCount === 0) {
533            throw new Error(msgPrefix + 'has no element children.');
534        }
535
536        // Check whether domNode descendant elements have A elements
537        let childElement = domNode.firstElementChild;
538        while (childElement) {
539            const menuitem = childElement.firstElementChild;
540            if (menuitem && menuitem.tagName !== 'A') {
541                throw new Error(msgPrefix + 'has descendant elements that are not A elements.');
542            }
543            childElement = childElement.nextElementSibling;
544        }
545
546        this.domNode = domNode;
547        this.controller = controllerObj;
548
549        this.menuitems  = [];      // see BlvdAccessibilityPopupMenuLinks init method
550        this.firstChars = [];      // see BlvdAccessibilityPopupMenuLinks init method
551
552        this.firstItem  = null;    // see BlvdAccessibilityPopupMenuLinks init method
553        this.lastItem   = null;    // see BlvdAccessibilityPopupMenuLinks init method
554
555        this.hasFocus   = false;   // see BlvdAccessibilityMenuItemLinks handleFocus, handleBlur
556        this.hasHover   = false;   // see BlvdAccessibilityPopupMenuLinks handleMouseover, handleMouseout
557    }
558
559
560}
561
562BlvdAccessibilityPopupMenuLinks.prototype.init = function () {
563    let childElement, menuElement, menuItem, textContent, numItems, label;
564
565    // Configure the domNode itself
566    this.domNode.tabIndex = -1;
567
568    this.domNode.setAttribute('role', 'menu');
569
570    if (!this.domNode.getAttribute('aria-labelledby') && !this.domNode.getAttribute('aria-label') && !this.domNode.getAttribute('title')) {
571        label = this.controller.domNode.innerHTML;
572        this.domNode.setAttribute('aria-label', label);
573    }
574
575    this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
576    this.domNode.addEventListener('mouseout',  this.handleMouseout.bind(this));
577
578    // Traverse the element children of domNode: configure each with
579    // menuitem role behavior and store reference in menuitems array.
580    childElement = this.domNode.firstElementChild;
581
582    while (childElement) {
583        menuElement = childElement.firstElementChild;
584
585        if (menuElement && menuElement.tagName === 'A') {
586            menuItem = new BlvdAccessibilityMenuItemLinks(menuElement, this);
587            menuItem.init();
588            this.menuitems.push(menuItem);
589            textContent = menuElement.textContent.trim();
590            this.firstChars.push(textContent.substring(0, 1).toLowerCase());
591        }
592        childElement = childElement.nextElementSibling;
593    }
594
595    // Use populated menuitems array to initialize firstItem and lastItem.
596    numItems = this.menuitems.length;
597    if (numItems > 0) {
598        this.firstItem = this.menuitems[0];
599        this.lastItem  = this.menuitems[numItems - 1];
600    }
601};
602
603/* EVENT HANDLERS */
604
605BlvdAccessibilityPopupMenuLinks.prototype.handleMouseover = function (event) {
606    this.hasHover = true;
607};
608
609BlvdAccessibilityPopupMenuLinks.prototype.handleMouseout = function (event) {
610    this.hasHover = false;
611    setTimeout(this.close.bind(this, false), 300);
612};
613
614/* FOCUS MANAGEMENT METHODS */
615
616BlvdAccessibilityPopupMenuLinks.prototype.setFocusToController = function (command) {
617    if (typeof command !== 'string') {
618        command = '';
619    }
620
621    if (command === 'previous') {
622        this.controller.menubar.setFocusToPreviousItem(this.controller);
623    }
624    else {
625        if (command === 'next') {
626            this.controller.menubar.setFocusToNextItem(this.controller);
627        }
628        else {
629            this.controller.domNode.focus();
630        }
631    }
632};
633
634BlvdAccessibilityPopupMenuLinks.prototype.setFocusToFirstItem = function () {
635    this.firstItem.domNode.focus();
636};
637
638BlvdAccessibilityPopupMenuLinks.prototype.setFocusToLastItem = function () {
639    this.lastItem.domNode.focus();
640};
641
642BlvdAccessibilityPopupMenuLinks.prototype.setFocusToPreviousItem = function (currentItem) {
643    let index;
644
645    if (currentItem === this.firstItem) {
646        this.lastItem.domNode.focus();
647    }
648    else {
649        index = this.menuitems.indexOf(currentItem);
650        this.menuitems[index - 1].domNode.focus();
651    }
652};
653
654BlvdAccessibilityPopupMenuLinks.prototype.setFocusToNextItem = function (currentItem) {
655    let index;
656
657    if (currentItem === this.lastItem) {
658        this.firstItem.domNode.focus();
659    }
660    else {
661        index = this.menuitems.indexOf(currentItem);
662        this.menuitems[index + 1].domNode.focus();
663    }
664};
665
666BlvdAccessibilityPopupMenuLinks.prototype.setFocusByFirstCharacter = function (currentItem, char) {
667    let start, index;
668    char = char.toLowerCase();
669
670    // Get start index for search based on position of currentItem
671    start = this.menuitems.indexOf(currentItem) + 1;
672    if (start === this.menuitems.length) {
673        start = 0;
674    }
675
676    // Check remaining slots in the menu
677    index = this.getIndexFirstChars(start, char);
678
679    // If not found in remaining slots, check from beginning
680    if (index === -1) {
681        index = this.getIndexFirstChars(0, char);
682    }
683
684    // If match was found...
685    if (index > -1) {
686        this.menuitems[index].domNode.focus();
687    }
688};
689
690BlvdAccessibilityPopupMenuLinks.prototype.getIndexFirstChars = function (startIndex, char) {
691    for (let i = startIndex; i < this.firstChars.length; i++) {
692        if (char === this.firstChars[i]) {
693            return i;
694        }
695    }
696    return -1;
697};
698
699/* MENU DISPLAY METHODS */
700
701BlvdAccessibilityPopupMenuLinks.prototype.open = function () {
702    // get position and bounding rectangle of controller object's DOM node
703    const rect = this.controller.domNode.getBoundingClientRect();
704
705    // set CSS properties
706    this.domNode.style.display = 'block';
707    this.domNode.style.position = 'absolute';
708    this.domNode.style.top  = rect.height + 'px';
709    this.domNode.style.left = '0px';
710
711    // set aria-expanded attribute
712    this.controller.domNode.setAttribute('aria-expanded', 'true');
713};
714
715BlvdAccessibilityPopupMenuLinks.prototype.close = function (force) {
716
717    if (force || (!this.hasFocus && !this.hasHover && !this.controller.hasHover)) {
718        this.domNode.style.display = 'none';
719        this.controller.domNode.removeAttribute('aria-expanded');
720    }
721};
722
723
724class BlvdAccessibilityMenuItemLinks {
725
726    constructor(domNode, menuObj) {
727        this.domNode = domNode;
728        this.menu = menuObj;
729
730        this.keyCode = Object.freeze({
731            'TAB': 9,
732            'RETURN': 13,
733            'ESC': 27,
734            'SPACE': 32,
735            'PAGEUP': 33,
736            'PAGEDOWN': 34,
737            'END': 35,
738            'HOME': 36,
739            'LEFT': 37,
740            'UP': 38,
741            'RIGHT': 39,
742            'DOWN': 40
743        });
744    }
745}
746
747BlvdAccessibilityMenuItemLinks.prototype.init = function () {
748    this.domNode.tabIndex = -1;
749
750    if (!this.domNode.getAttribute('role')) {
751        this.domNode.setAttribute('role', 'menuitem');
752    }
753
754    this.domNode.addEventListener('keydown',    this.handleKeydown.bind(this));
755    this.domNode.addEventListener('click',      this.handleClick.bind(this));
756    this.domNode.addEventListener('focus',      this.handleFocus.bind(this));
757    this.domNode.addEventListener('blur',       this.handleBlur.bind(this));
758    this.domNode.addEventListener('mouseover',  this.handleMouseover.bind(this));
759    this.domNode.addEventListener('mouseout',   this.handleMouseout.bind(this));
760
761};
762
763/* EVENT HANDLERS */
764
765BlvdAccessibilityMenuItemLinks.prototype.handleKeydown = function (event) {
766    let flag = false,
767    char = event.key;
768
769    function isPrintableCharacter (str) {
770        return str.length === 1 && str.match(/\S/);
771    }
772
773    if (event.ctrlKey || event.altKey  || event.metaKey || (event.keyCode === this.keyCode.SPACE) || (event.keyCode === this.keyCode.RETURN)) {
774        return;
775    }
776
777    if (event.shiftKey) {
778        if (isPrintableCharacter(char)) {
779            this.menu.setFocusByFirstCharacter(this, char);
780            flag = true;
781        }
782
783        if (event.keyCode === this.keyCode.TAB) {
784            this.menu.setFocusToController();
785            this.menu.close(true);
786        }
787    }
788    else {
789        switch (event.keyCode) {
790
791            case this.keyCode.ESC:
792                this.menu.setFocusToController();
793                this.menu.close(true);
794                flag = true;
795                break;
796
797            case this.keyCode.UP:
798                this.menu.setFocusToPreviousItem(this);
799                flag = true;
800                break;
801
802            case this.keyCode.DOWN:
803                this.menu.setFocusToNextItem(this);
804                flag = true;
805                break;
806
807            case this.keyCode.HOME:
808            case this.keyCode.PAGEUP:
809                this.menu.setFocusToFirstItem();
810                flag = true;
811                break;
812
813            case this.keyCode.END:
814            case this.keyCode.PAGEDOWN:
815                this.menu.setFocusToLastItem();
816                flag = true;
817                break;
818
819            case this.keyCode.TAB:
820                this.menu.setFocusToController();
821                this.menu.close(true);
822                break;
823
824            default:
825                if (isPrintableCharacter(char)) {
826                    this.menu.setFocusByFirstCharacter(this, char);
827                }
828                break;
829        }
830    }
831
832    if (flag) {
833        event.stopPropagation();
834        event.preventDefault();
835    }
836};
837
838BlvdAccessibilityMenuItemLinks.prototype.handleClick = function (event) {
839    this.menu.setFocusToController();
840    this.menu.close(true);
841};
842
843BlvdAccessibilityMenuItemLinks.prototype.handleFocus = function (event) {
844    this.menu.hasFocus = true;
845};
846
847BlvdAccessibilityMenuItemLinks.prototype.handleBlur = function (event) {
848    this.menu.hasFocus = false;
849    setTimeout(this.menu.close.bind(this.menu, false), 300);
850};
851
852BlvdAccessibilityMenuItemLinks.prototype.handleMouseover = function (event) {
853    this.menu.hasHover = true;
854    this.menu.open();
855
856};
857
858BlvdAccessibilityMenuItemLinks.prototype.handleMouseout = function (event) {
859    this.menu.hasHover = false;
860    setTimeout(this.menu.close.bind(this.menu, false), 300);
861};
862
863let listingCards = document.querySelectorAll('[data-card]');
864const keysCode = Object.freeze({
865  'TAB': 9,
866  'RETURN': 13,
867  'ESC': 27,
868  'SPACE': 32,
869  'PAGEUP': 33,
870  'PAGEDOWN': 34,
871  'END': 35,
872  'HOME': 36,
873  'LEFT': 37,
874  'UP': 38,
875  'RIGHT': 39,
876  'DOWN': 40
877});
878
879listingCards.forEach((listingCard, index, arr) => {
880  let title = listingCard.querySelector('.listing-title--link'),
881      favorite = listingCard.querySelector('.favorite-toggle-wrap'),
882      previousFavorite,
883      isShift
884  ;
885
886  if (title && favorite) {
887    title.addEventListener('keydown', function (event) {
888      event.stopPropagation();
889
890      isShift = !!event.shiftKey;
891
892      if (event.keyCode === keysCode.TAB && isShift) {
893        if ((index - 1) >= 0) {
894          previousFavorite = arr[index - 1].querySelector('.favorite-toggle-wrap');
895          previousFavorite.setAttribute('tabindex', 0);
896
897        }
898      } else if (event.keyCode === keysCode.TAB) {
899        favorite.setAttribute('tabindex', '0');
900      }
901    });
902  }
903
904  if (favorite) {
905    favorite.addEventListener('blur', function(e) {
906      this.setAttribute('tabindex', '-1');
907    });
908  }
909});
910
911
912jQuery(function($) {
913
914    let modalCaller;
915
916    $('[data-init="colorbox"], .cboxElement').on('click', function(event) {
917        modalCaller = event.target;
918});
919
920    $(document).bind('cbox_complete', function(){
921        window.modal = $('#colorbox');
922        window.modalId = new Date().getTime();
923        window.modal.attr('data-modal-id', window.modalId);
924
925        let $parent = window.modal;
926        const excluseTagNames = [
927            'script',
928            'style',
929            'noscript'
930        ];
931
932        do {
933            let $siblings = $parent.siblings();
934
935            if ($siblings.length > 0) {
936                $siblings.each(function(index, elem) {
937                    if (!excluseTagNames.includes(elem.tagName.toLowerCase())) {
938                        if (elem.hasAttribute('aria-hidden')) {
939                            elem.setAttribute('data-arhide', elem.getAttribute('aria-hidden'));
940                        }
941
942                        elem.setAttribute('aria-hidden', 'true');
943                    }
944                });
945            }
946
947            $parent = $parent.parent();
948
949        }  while ($parent[0].tagName.toLowerCase() !== 'body')
950
951        window.setFocusInModalWindow();
952    })
953        .bind('cbox_closed ', function() {
954            modalCaller.focus();
955            window.modal = null;
956            window.focusableContent = null;
957
958            let $elems = document.querySelectorAll('[aria-hidden="true"]');
959
960            for (let elem of $elems) {
961                if (elem.hasAttribute('data-arhide')) {
962                    elem.setAttribute('aria-hidden', elem.getAttribute('data-arhide'));
963                    elem.removeAttribute('data-arhide');
964                } else {
965                    elem.removeAttribute('aria-hidden');
966                }
967            }
968        })
969    ;
970});
971
972/*
973*   This content is licensed according to the W3C Software License at
974*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
975*/
976
977/**
978 * @namespace aria
979 */
980var aria = aria || {};
981
982/**
983 * @desc
984 *  Values for aria-sort
985 */
986aria.SortType = {
987    ASCENDING: 'ascending',
988    DESCENDING: 'descending',
989    NONE: 'none'
990};
991
992/**
993 * @desc
994 *  DOM Selectors to find the grid components
995 */
996aria.GridSelector = {
997    ROW: 'tr, [role="row"]',
998    CELL: 'th, td, [role="gridcell"]',
999    SCROLL_ROW: 'tr:not([data-fixed]), [role="row"]',
1000    SORT_HEADER: 'th[aria-sort]',
1001    TABBABLE: '[tabindex="0"]'
1002};
1003
1004/**
1005 * @desc
1006 *  CSS Class names
1007 */
1008aria.CSSClass = {
1009    HIDDEN: 'hidden'
1010};
1011
1012/**
1013 * @constructor
1014 *
1015 * @desc
1016 *  Grid object representing the state and interactions for a grid widget
1017 *
1018 *  Assumptions:
1019 *  All focusable cells initially have tabindex="-1"
1020 *  Produces a fully filled in mxn grid (with no holes)
1021 *
1022 * @param gridNode
1023 *  The DOM node pointing to the grid
1024 */
1025aria.Grid = function (gridNode) {
1026    this.navigationDisabled = false;
1027    this.gridNode = gridNode;
1028    this.paginationEnabled = false; //this.gridNode.hasAttribute('data-per-page');
1029    this.shouldWrapCols = null; //this.gridNode.hasAttribute('data-wrap-cols');
1030    this.shouldWrapRows = null; //this.gridNode.hasAttribute('data-wrap-rows');
1031    this.shouldRestructure = null; //this.gridNode.hasAttribute('data-restructure');
1032    this.topIndex = 0;
1033
1034    this.keysIndicator = document.getElementById('arrow-keys-indicator');
1035
1036    aria.Utils.bindMethods(this,
1037        'checkFocusChange', 'checkPageChange', 'checkRestructureGrid',
1038        'delegateButtonHandler', 'focusClickedCell', 'restructureGrid',
1039        'showKeysIndicator', 'hideKeysIndicator');
1040    this.setupFocusGrid();
1041    this.setFocusPointer(0, 0);
1042
1043    if (this.paginationEnabled) {
1044        this.setupPagination();
1045    }
1046    else {
1047        this.perPage = this.grid.length;
1048    }
1049
1050    this.registerEvents();
1051};
1052
1053/**
1054 * @desc
1055 *  Creates a 2D array of the focusable cells in the grid.
1056 */
1057aria.Grid.prototype.setupFocusGrid = function () {
1058    this.grid = [];
1059    Array.prototype.forEach.call(
1060        this.gridNode.querySelectorAll(aria.GridSelector.ROW),
1061        (function (row) {
1062            var rowCells = [];
1063
1064            Array.prototype.forEach.call(
1065                row.querySelectorAll(aria.GridSelector.CELL),
1066                (function (cell) {
1067                    var focusableSelector = '[tabindex]';
1068
1069                    if (aria.Utils.matches(cell, focusableSelector)) {
1070                        rowCells.push(cell);
1071                    }
1072                    else {
1073                        var focusableCell = cell.querySelector(focusableSelector);
1074
1075                        if (focusableCell) {
1076                            rowCells.push(focusableCell);
1077                        }
1078                    }
1079                }).bind(this)
1080            );
1081
1082            if (rowCells.length) {
1083                this.grid.push(rowCells);
1084            }
1085        }).bind(this)
1086    );
1087
1088    if (this.paginationEnabled) {
1089        this.setupIndices();
1090    }
1091};
1092
1093/**
1094 * @desc
1095 *  If possible, set focus pointer to the cell with the specified coordinates
1096 *
1097 * @param row
1098 *  The index of the cell's row
1099 *
1100 * @param col
1101 *  The index of the cell's column
1102 *
1103 * @returns
1104 *  Returns whether or not the focus could be set on the cell.
1105 */
1106aria.Grid.prototype.setFocusPointer = function (row, col) {
1107    if (!this.isValidCell(row, col)) {
1108        return false;
1109    }
1110
1111    if (this.isHidden(row, col)) {
1112        return false;
1113    }
1114
1115    if (!isNaN(this.focusedRow) && !isNaN(this.focusedCol)) {
1116        this.grid[this.focusedRow][this.focusedCol].setAttribute('tabindex', -1);
1117    }
1118
1119    this.grid[row][col]
1120        .removeEventListener('focus', this.showKeysIndicator);
1121    this.grid[row][col]
1122        .removeEventListener('blur', this.hideKeysIndicator);
1123
1124    // Disable navigation if focused on an input
1125    this.navigationDisabled = aria.Utils.matches(this.grid[row][col], 'input');
1126
1127    this.grid[row][col].setAttribute('tabindex', 0);
1128    this.focusedRow = row;
1129    this.focusedCol = col;
1130
1131    this.grid[row][col]
1132        .addEventListener('focus', this.showKeysIndicator);
1133    this.grid[row][col]
1134        .addEventListener('blur', this.hideKeysIndicator);
1135
1136    return true;
1137};
1138
1139/**
1140 * @param row
1141 *  The index of the cell's row
1142 *
1143 * @param col
1144 *  The index of the cell's column
1145 *
1146 * @returns
1147 *  Returns whether or not the coordinates are within the grid's boundaries.
1148 */
1149aria.Grid.prototype.isValidCell = function (row, col) {
1150    return (
1151        !isNaN(row) &&
1152        !isNaN(col) &&
1153        row >= 0 &&
1154        col >= 0 &&
1155        this.grid &&
1156        this.grid.length &&
1157        row < this.grid.length &&
1158        col < this.grid[row].length
1159    );
1160};
1161
1162/**
1163 * @param row
1164 *  The index of the cell's row
1165 *
1166 * @param col
1167 *  The index of the cell's column
1168 *
1169 * @returns
1170 *  Returns whether or not the cell has been hidden.
1171 */
1172aria.Grid.prototype.isHidden = function (row, col) {
1173    var cell = this.gridNode.querySelectorAll(aria.GridSelector.ROW)[row]
1174        .querySelectorAll(aria.GridSelector.CELL)[col];
1175    return aria.Utils.hasClass(cell, aria.CSSClass.HIDDEN);
1176};
1177
1178/**
1179 * @desc
1180 *  Clean up grid events
1181 */
1182aria.Grid.prototype.clearEvents = function () {
1183    this.gridNode.removeEventListener('keydown', this.checkFocusChange);
1184    this.gridNode.removeEventListener('keydown', this.delegateButtonHandler);
1185    this.gridNode.removeEventListener('click', this.focusClickedCell);
1186    this.gridNode.removeEventListener('click', this.delegateButtonHandler);
1187
1188    if (this.paginationEnabled) {
1189        this.gridNode.removeEventListener('keydown', this.checkPageChange);
1190    }
1191
1192    if (this.shouldRestructure) {
1193        window.removeEventListener('resize', this.checkRestructureGrid);
1194    }
1195
1196    this.grid[this.focusedRow][this.focusedCol]
1197        .removeEventListener('focus', this.showKeysIndicator);
1198    this.grid[this.focusedRow][this.focusedCol]
1199        .removeEventListener('blur', this.hideKeysIndicator);
1200};
1201
1202/**
1203 * @desc
1204 *  Register grid events
1205 */
1206aria.Grid.prototype.registerEvents = function () {
1207    this.clearEvents();
1208
1209    this.gridNode.addEventListener('keydown', this.checkFocusChange);
1210    this.gridNode.addEventListener('keydown', this.delegateButtonHandler);
1211    this.gridNode.addEventListener('click', this.focusClickedCell);
1212    this.gridNode.addEventListener('click', this.delegateButtonHandler);
1213
1214    if (this.paginationEnabled) {
1215        this.gridNode.addEventListener('keydown', this.checkPageChange);
1216    }
1217
1218    if (this.shouldRestructure) {
1219        window.addEventListener('resize', this.checkRestructureGrid);
1220    }
1221};
1222
1223/**
1224 * @desc
1225 *  Focus on the cell in the specified row and column
1226 *
1227 * @param row
1228 *  The index of the cell's row
1229 *
1230 * @param col
1231 *  The index of the cell's column
1232 */
1233aria.Grid.prototype.focusCell = function (row, col) {
1234    if (this.setFocusPointer(row, col)) {
1235        this.grid[row][col].focus();
1236    }
1237};
1238
1239aria.Grid.prototype.showKeysIndicator = function () {
1240    if (this.keysIndicator) {
1241        aria.Utils.removeClass(this.keysIndicator, 'hidden');
1242    }
1243};
1244
1245aria.Grid.prototype.hideKeysIndicator = function () {
1246    if (this.keysIndicator &&
1247        this.grid[this.focusedRow][this.focusedCol].tabIndex === 0) {
1248        aria.Utils.addClass(this.keysIndicator, 'hidden');
1249    }
1250};
1251
1252/**
1253 * @desc
1254 *  Triggered on keydown. Checks if an arrow key was pressed, and (if possible)
1255 *  moves focus to the next valid cell in the direction of the arrow key.
1256 *
1257 * @param event
1258 *  Keydown event
1259 */
1260aria.Grid.prototype.checkFocusChange = function (event) {
1261    if (!event || this.navigationDisabled) {
1262        return;
1263    }
1264
1265    this.findFocusedItem(event.target);
1266
1267    var key = event.which || event.keyCode;
1268    var rowCaret = this.focusedRow;
1269    var colCaret = this.focusedCol;
1270    var nextCell;
1271
1272    switch (key) {
1273        case aria.KeyCode.UP:
1274            nextCell = this.getNextVisibleCell(0, -1);
1275            rowCaret = nextCell.row;
1276            colCaret = nextCell.col;
1277            break;
1278        case aria.KeyCode.DOWN:
1279            nextCell = this.getNextVisibleCell(0, 1);
1280            rowCaret = nextCell.row;
1281            colCaret = nextCell.col;
1282            break;
1283        case aria.KeyCode.LEFT:
1284            nextCell = this.getNextVisibleCell(-1, 0);
1285            rowCaret = nextCell.row;
1286            colCaret = nextCell.col;
1287            break;
1288        case aria.KeyCode.RIGHT:
1289            nextCell = this.getNextVisibleCell(1, 0);
1290            rowCaret = nextCell.row;
1291            colCaret = nextCell.col;
1292            break;
1293        case aria.KeyCode.HOME:
1294            if (event.ctrlKey) {
1295                rowCaret = 0;
1296            }
1297            colCaret = 0;
1298            break;
1299        case aria.KeyCode.END:
1300            if (event.ctrlKey) {
1301                rowCaret = this.grid.length - 1;
1302            }
1303            colCaret = this.grid[this.focusedRow].length - 1;
1304            break;
1305        default:
1306            return;
1307    }
1308
1309    if (this.paginationEnabled) {
1310        if (rowCaret < this.topIndex) {
1311            this.showFromRow(rowCaret, true);
1312        }
1313
1314        if (rowCaret >= this.topIndex + this.perPage) {
1315            this.showFromRow(rowCaret, false);
1316        }
1317    }
1318
1319    this.focusCell(rowCaret, colCaret);
1320    event.preventDefault();
1321};
1322
1323/**
1324 * @desc
1325 *  Reset focused row and col if it doesn't match focusedRow and focusedCol
1326 *
1327 * @param focusedTarget
1328 *  Element that is currently focused by browser
1329 */
1330aria.Grid.prototype.findFocusedItem = function (focusedTarget) {
1331    var focusedCell = this.grid[this.focusedRow][this.focusedCol];
1332
1333    if (focusedCell === focusedTarget ||
1334        focusedCell.contains(focusedTarget)) {
1335        return;
1336    }
1337
1338    for (var i = 0; i < this.grid.length; i++) {
1339        for (var j = 0; j < this.grid[i].length; j++) {
1340            if (this.grid[i][j] === focusedTarget ||
1341                this.grid[i][j].contains(focusedTarget)) {
1342                this.setFocusPointer(i, j);
1343                return;
1344            }
1345        }
1346    }
1347};
1348
1349/**
1350 * @desc
1351 *  Triggered on click. Finds the cell that was clicked on and focuses on it.
1352 *
1353 * @param event
1354 *  Keydown event
1355 */
1356aria.Grid.prototype.focusClickedCell = function (event) {
1357    var clickedGridCell = this.findClosest(event.target, '[tabindex]');
1358
1359    for (var row = 0; row < this.grid.length; row++) {
1360        for (var col = 0; col < this.grid[row].length; col++) {
1361            if (this.grid[row][col] === clickedGridCell) {
1362                this.setFocusPointer(row, col);
1363
1364                if (!aria.Utils.matches(clickedGridCell, 'button[aria-haspopup]')) {
1365                    // Don't focus if it's a menu button (focus should be set to menu)
1366                    this.focusCell(row, col);
1367                }
1368
1369                return;
1370            }
1371        }
1372    }
1373};
1374
1375/**
1376 * @desc
1377 *  Triggered on click. Checks if user clicked on a header with aria-sort.
1378 *  If so, it sorts the column based on the aria-sort attribute.
1379 *
1380 * @param event
1381 *  Keydown event
1382 */
1383aria.Grid.prototype.delegateButtonHandler = function (event) {
1384    var key = event.which || event.keyCode;
1385    var target = event.target;
1386    var isClickEvent = (event.type === 'click');
1387
1388    if (!target) {
1389        return;
1390    }
1391
1392    if (
1393        target.parentNode &&
1394        target.parentNode.matches('th[aria-sort]') &&
1395        (
1396            isClickEvent ||
1397            key === aria.KeyCode.SPACE ||
1398            key === aria.KeyCode.RETURN
1399        )
1400    ) {
1401        event.preventDefault();
1402        this.handleSort(target.parentNode);
1403    }
1404
1405    if (
1406        aria.Utils.matches(target, '.editable-text, .edit-text-button') &&
1407        (
1408            isClickEvent ||
1409            key === aria.KeyCode.RETURN
1410        )
1411    ) {
1412        event.preventDefault();
1413        this.toggleEditMode(
1414            this.findClosest(target, '.editable-text'),
1415            true,
1416            true
1417        );
1418    }
1419
1420    if (
1421        aria.Utils.matches(target, '.edit-text-input') &&
1422        (
1423            key === aria.KeyCode.RETURN ||
1424            key === aria.KeyCode.ESC
1425        )
1426    ) {
1427        event.preventDefault();
1428        this.toggleEditMode(
1429            this.findClosest(target, '.editable-text'),
1430            false,
1431            key === aria.KeyCode.RETURN
1432        );
1433    }
1434};
1435
1436/**
1437 * @desc
1438 *  Toggles the mode of an editable cell between displaying the edit button
1439 *  and displaying the editable input.
1440 *
1441 * @param editCell
1442 *  Cell to toggle
1443 *
1444 * @param toggleOn
1445 *  Whether to show or hide edit input
1446 *
1447 * @param updateText
1448 *  Whether or not to update the button text with the input text
1449 */
1450aria.Grid.prototype.toggleEditMode = function (editCell, toggleOn, updateText) {
1451    var onClassName = toggleOn ? 'edit-text-input' : 'edit-text-button';
1452    var offClassName = toggleOn ? 'edit-text-button' : 'edit-text-input';
1453    var onNode = editCell.querySelector('.' + onClassName);
1454    var offNode = editCell.querySelector('.' + offClassName);
1455
1456    if (toggleOn) {
1457        onNode.value = offNode.innerText;
1458    }
1459    else if (updateText) {
1460        onNode.innerText = offNode.value;
1461    }
1462
1463    aria.Utils.addClass(offNode, aria.CSSClass.HIDDEN);
1464    aria.Utils.removeClass(onNode, aria.CSSClass.HIDDEN);
1465    offNode.setAttribute('tabindex', -1);
1466    onNode.setAttribute('tabindex', 0);
1467    onNode.focus();
1468    this.grid[this.focusedRow][this.focusedCol] = onNode;
1469    this.navigationDisabled = toggleOn;
1470};
1471
1472/**
1473 * @desc
1474 *  Sorts the column below the header node, based on the aria-sort attribute.
1475 *  aria-sort="none" => aria-sort="ascending"
1476 *  aria-sort="ascending" => aria-sort="descending"
1477 *  All other headers with aria-sort are reset to "none"
1478 *
1479 *  Note: This implementation assumes that there is no pagination on the grid.
1480 *
1481 * @param headerNode
1482 *  Header DOM node
1483 */
1484aria.Grid.prototype.handleSort = function (headerNode) {
1485    var columnIndex = headerNode.cellIndex;
1486    var sortType = headerNode.getAttribute('aria-sort');
1487
1488    if (sortType === aria.SortType.ASCENDING) {
1489        sortType = aria.SortType.DESCENDING;
1490    }
1491    else {
1492        sortType = aria.SortType.ASCENDING;
1493    }
1494
1495    var comparator = function (row1, row2) {
1496        var row1Text = row1.children[columnIndex].innerText;
1497        var row2Text = row2.children[columnIndex].innerText;
1498        var row1Value = parseInt(row1Text.replace(/[^0-9\.]+/g, ''));
1499        var row2Value = parseInt(row2Text.replace(/[^0-9\.]+/g, ''));
1500
1501        if (sortType === aria.SortType.ASCENDING) {
1502            return row1Value - row2Value;
1503        }
1504        else {
1505            return row2Value - row1Value;
1506        }
1507    };
1508
1509    this.sortRows(comparator);
1510    this.setupFocusGrid();
1511
1512    Array.prototype.forEach.call(
1513        this.gridNode.querySelectorAll(aria.GridSelector.SORT_HEADER),
1514        function (headerCell) {
1515            headerCell.setAttribute('aria-sort', aria.SortType.NONE);
1516        }
1517    );
1518
1519    headerNode.setAttribute('aria-sort', sortType);
1520};
1521
1522/**
1523 * @desc
1524 *  Sorts the grid's rows according to the specified compareFn
1525 *
1526 * @param compareFn
1527 *  Comparison function to sort the rows
1528 */
1529aria.Grid.prototype.sortRows = function (compareFn) {
1530    var rows = this.gridNode.querySelectorAll(aria.GridSelector.ROW);
1531    var rowWrapper = rows[0].parentNode;
1532    var dataRows = Array.prototype.slice.call(rows, 1);
1533
1534    dataRows.sort(compareFn);
1535
1536    dataRows.forEach((function (row) {
1537        rowWrapper.appendChild(row);
1538    }).bind(this));
1539};
1540
1541/**
1542 * @desc
1543 *  Adds aria-rowindex and aria-colindex to the cells in the grid
1544 */
1545aria.Grid.prototype.setupIndices = function () {
1546    var rows = this.gridNode.querySelectorAll(aria.GridSelector.ROW);
1547
1548    for (var row = 0; row < rows.length; row++) {
1549        var cols = rows[row].querySelectorAll(aria.GridSelector.CELL);
1550        rows[row].setAttribute('aria-rowindex', row + 1);
1551
1552        for (var col = 0; col < cols.length; col++) {
1553            cols[col].setAttribute('aria-colindex', col + 1);
1554        }
1555
1556    }
1557};
1558
1559/**
1560 * @desc
1561 *  Determines the per page attribute of the grid, and shows/hides rows
1562 *  accordingly.
1563 */
1564aria.Grid.prototype.setupPagination = function () {
1565    this.onPaginationChange = this.onPaginationChange || function () {};
1566    this.perPage = parseInt(this.gridNode.getAttribute('data-per-page'));
1567    this.showFromRow(0, true);
1568};
1569
1570aria.Grid.prototype.setPaginationChangeHandler = function (onPaginationChange) {
1571    this.onPaginationChange = onPaginationChange;
1572};
1573
1574/**
1575 * @desc
1576 *  Check if page up or page down was pressed, and show the next page if so.
1577 *
1578 * @param event
1579 *  Keydown event
1580 */
1581aria.Grid.prototype.checkPageChange = function (event) {
1582    if (!event) {
1583        return;
1584    }
1585
1586    var key = event.which || event.keyCode;
1587
1588    if (key === aria.KeyCode.PAGE_UP) {
1589        event.preventDefault();
1590        this.movePageUp();
1591    }
1592    else if (key === aria.KeyCode.PAGE_DOWN) {
1593        event.preventDefault();
1594        this.movePageDown();
1595    }
1596};
1597
1598aria.Grid.prototype.movePageUp = function () {
1599    var startIndex = Math.max(this.perPage - 1, this.topIndex - 1);
1600    this.showFromRow(startIndex, false);
1601    this.focusCell(startIndex, this.focusedCol);
1602};
1603
1604aria.Grid.prototype.movePageDown = function () {
1605    var startIndex = this.topIndex + this.perPage;
1606    this.showFromRow(startIndex, true);
1607    this.focusCell(startIndex, this.focusedCol);
1608};
1609
1610/**
1611 * @desc
1612 *  Scroll the specified row into view in the specified direction
1613 *
1614 * @param startIndex
1615 *  Row index to use as the start index
1616 *
1617 * @param scrollDown
1618 *  Whether to scroll the new page above or below the row index
1619 */
1620aria.Grid.prototype.showFromRow = function (startIndex, scrollDown) {
1621    var dataRows =
1622        this.gridNode.querySelectorAll(aria.GridSelector.SCROLL_ROW);
1623    var reachedTop = false;
1624    var firstIndex = -1;
1625    var endIndex = -1;
1626
1627    if (startIndex < 0 || startIndex >= dataRows.length) {
1628        return;
1629    }
1630
1631    for (var i = 0; i < dataRows.length; i++) {
1632
1633        if (
1634            (
1635                scrollDown &&
1636                i >= startIndex &&
1637                i < startIndex + this.perPage) ||
1638            (
1639                !scrollDown &&
1640                i <= startIndex &&
1641                i > startIndex - this.perPage
1642            )
1643        ) {
1644            aria.Utils.removeClass(dataRows[i], aria.CSSClass.HIDDEN);
1645
1646            if (!reachedTop) {
1647                this.topIndex = i;
1648                reachedTop = true;
1649            }
1650
1651            if (firstIndex < 0) {
1652                firstIndex = i;
1653            }
1654            endIndex = i;
1655        }
1656        else {
1657            aria.Utils.addClass(dataRows[i], aria.CSSClass.HIDDEN);
1658        }
1659    }
1660    this.onPaginationChange(firstIndex, endIndex);
1661};
1662
1663/**
1664 * @desc
1665 *  Throttle restructuring to only happen every 300ms
1666 */
1667aria.Grid.prototype.checkRestructureGrid = function () {
1668    if (this.waitingToRestructure) {
1669        return;
1670    }
1671
1672    this.waitingToRestructure = true;
1673
1674    setTimeout(this.restructureGrid, 300);
1675};
1676
1677/**
1678 * @desc
1679 *  Restructure grid based on the size.
1680 */
1681aria.Grid.prototype.restructureGrid = function () {
1682    this.waitingToRestructure = false;
1683
1684    var gridWidth = this.gridNode.offsetWidth;
1685    var cells = this.gridNode.querySelectorAll(aria.GridSelector.CELL);
1686    var currentWidth = 0;
1687
1688    var focusedElement = this.gridNode.querySelector(aria.GridSelector.TABBABLE);
1689    var shouldRefocus = (document.activeElement === focusedElement);
1690    var focusedIndex = (this.focusedRow * this.grid[0].length + this.focusedCol);
1691
1692    var newRow = document.createElement('div');
1693    newRow.setAttribute('role', 'row');
1694    this.gridNode.innerHTML = '';
1695    this.gridNode.append(newRow);
1696
1697    cells.forEach(function (cell, index) {
1698        var cellWidth = cell.offsetWidth;
1699
1700        if (currentWidth > 0 && currentWidth >= (gridWidth - cellWidth)) {
1701            newRow = document.createElement('div');
1702            newRow.setAttribute('role', 'row');
1703            this.gridNode.append(newRow);
1704            currentWidth = 0;
1705        }
1706
1707        newRow.append(cell);
1708        currentWidth += cellWidth;
1709    });
1710
1711    this.setupFocusGrid();
1712
1713    this.focusedRow = Math.floor(focusedIndex / this.grid[0].length);
1714    this.focusedCol = focusedIndex % this.grid[0].length;
1715
1716    if (shouldRefocus) {
1717        this.focusCell(this.focusedRow, this.focusedCol);
1718    }
1719};
1720
1721/**
1722 * @desc
1723 *  Get next cell to the right or left (direction) of the focused
1724 *  cell.
1725 *
1726 * @param currRow
1727 *  Row index to start searching from
1728 *
1729 * @param currCol
1730 *  Column index to start searching from
1731 *
1732 * @param directionX
1733 *  X direction for where to check for cells. +1 to check to the right, -1 to
1734 *  check to the left
1735 *
1736 * @return
1737 *  Indices of the next cell in the specified direction. Returns the focused
1738 *  cell if none are found.
1739 */
1740aria.Grid.prototype.getNextCell = function (
1741    currRow,
1742    currCol,
1743    directionX,
1744    directionY
1745) {
1746    var row = currRow + directionY;
1747    var col = currCol + directionX;
1748    var rowCount = this.grid.length;
1749    var isLeftRight = directionX !== 0;
1750
1751    if (!rowCount) {
1752        return false;
1753    }
1754
1755    var colCount = this.grid[0].length;
1756
1757    if (this.shouldWrapCols && isLeftRight) {
1758        if (col < 0) {
1759            col = colCount - 1;
1760            row--;
1761        }
1762
1763        if (col >= colCount) {
1764            col = 0;
1765            row++;
1766        }
1767    }
1768
1769    if (this.shouldWrapRows && !isLeftRight) {
1770        if (row < 0) {
1771            col--;
1772            row = rowCount - 1;
1773            if (this.grid[row] && col >= 0 && !this.grid[row][col]) {
1774                // Sometimes the bottom row is not completely filled in. In this case,
1775                // jump to the next filled in cell.
1776                row--;
1777            }
1778        }
1779        else if (row >= rowCount || !this.grid[row][col]) {
1780            row = 0;
1781            col++;
1782        }
1783    }
1784
1785    if (this.isValidCell(row, col)) {
1786        return {
1787            row: row,
1788            col: col
1789        };
1790    }
1791    else if (this.isValidCell(currRow, currCol)) {
1792        return {
1793            row: currRow,
1794            col: currCol
1795        };
1796    }
1797    else {
1798        return false;
1799    }
1800};
1801
1802/**
1803 * @desc
1804 *  Get next visible column to the right or left (direction) of the focused
1805 *  cell.
1806 *
1807 * @param direction
1808 *  Direction for where to check for cells. +1 to check to the right, -1 to
1809 *  check to the left
1810 *
1811 * @return
1812 *  Indices of the next visible cell in the specified direction. If no visible
1813 *  cells are found, returns false if the current cell is hidden and returns
1814 *  the current cell if it is not hidden.
1815 */
1816aria.Grid.prototype.getNextVisibleCell = function (directionX, directionY) {
1817    var nextCell = this.getNextCell(
1818        this.focusedRow,
1819        this.focusedCol,
1820        directionX,
1821        directionY
1822    );
1823
1824    if (!nextCell) {
1825        return false;
1826    }
1827
1828    var rowCount = this.grid.length;
1829    var colCount = this.grid[nextCell.row].length;
1830
1831    while (this.isHidden(nextCell.row, nextCell.col)) {
1832        var currRow = nextCell.row;
1833        var currCol = nextCell.col;
1834
1835        nextCell = this.getNextCell(currRow, currCol, directionX, directionY);
1836
1837        if (currRow === nextCell.row && currCol === nextCell.col) {
1838            // There are no more cells to try if getNextCell returns the current cell
1839            return false;
1840        }
1841    }
1842
1843    return nextCell;
1844};
1845
1846/**
1847 * @desc
1848 *  Show or hide the cells in the specified column
1849 *
1850 * @param columnIndex
1851 *  Index of the column to toggle
1852 *
1853 * @param isShown
1854 *  Whether or not to show the column
1855 */
1856aria.Grid.prototype.toggleColumn = function (columnIndex, isShown) {
1857    var cellSelector = '[aria-colindex="' + columnIndex + '"]';
1858    var columnCells = this.gridNode.querySelectorAll(cellSelector);
1859
1860    Array.prototype.forEach.call(
1861        columnCells,
1862        function (cell) {
1863            if (isShown) {
1864                aria.Utils.removeClass(cell, aria.CSSClass.HIDDEN);
1865            }
1866            else {
1867                aria.Utils.addClass(cell, aria.CSSClass.HIDDEN);
1868            }
1869        }
1870    );
1871
1872    if (!isShown && this.focusedCol === (columnIndex - 1)) {
1873        // If focus was set on the hidden column, shift focus to the right
1874        var nextCell = this.getNextVisibleCell(1, 0);
1875        if (nextCell) {
1876            this.setFocusPointer(nextCell.row, nextCell.col);
1877        }
1878    }
1879};
1880
1881/**
1882 * @desc
1883 *  Find the closest element matching the selector. Only checks parent and
1884 *  direct children.
1885 *
1886 * @param element
1887 *  Element to start searching from
1888 *
1889 * @param selector
1890 *  Index of the column to toggle
1891 */
1892aria.Grid.prototype.findClosest = function (element, selector) {
1893    if (aria.Utils.matches(element, selector)) {
1894        return element;
1895    }
1896
1897    if (aria.Utils.matches(element.parentNode, selector)) {
1898        return element.parentNode;
1899    }
1900
1901    return element.querySelector(selector);
1902};
1903
1904(function() {
1905  const hiddenContainerSelector = '.single__map .hji-areas-mapbox a, ' +
1906    '.single__map .hji-areas-mapbox  input, ' +
1907    '.single__map .hji-areas-mapbox  button, ' +
1908    '.single__map .hji-areas-mapbox  select, ' +
1909    '.single__map .hji-areas-mapbox  textarea '
1910  ;
1911
1912  function accessibilityHideContainerElement() {
1913    setTimeout(function() {
1914      document.querySelectorAll(hiddenContainerSelector).forEach(function (item) {
1915        item.setAttribute('tabindex', '-1');
1916      });
1917    }, 700);
1918  }
1919
1920
1921  var target = document.querySelector('.single__map .hji-areas-mapbox ');
1922
1923  if (typeof target !== 'undefined' && null !== target) {
1924    // create an observer instance
1925    var observer = new MutationObserver(function(mutations) {
1926      accessibilityHideContainerElement();
1927    });
1928    // configuration of the observer:
1929    var config = { attributes: true, childList: true, characterData: true };
1930    // pass in the target node, as well as the observer options
1931    observer.observe(target, config);
1932  }
1933
1934  accessibilityHideContainerElement();
1935
1936})();
1937
1938
1939/*jshint esversion: 6 */
1940const makeFocusOnTargetAfterGoOnLink = function (link) {
1941    const href = jQuery(link).attr('href');
1942    if (href && href.indexOf('#') === 0) {
1943        jQuery(link).on('click', function(){
1944            jQuery(href).focus();
1945        });
1946    }
1947};
1948
1949jQuery(function($){
1950    $('body').on('click', 'a[data-anchor="true"]', function() {
1951        makeFocusOnTargetAfterGoOnLink($(this));
1952    });
1953
1954    $('body').on('click', 'a[data-anchor="form"]', function() {
1955        const href = $(this).attr('href');
1956        if (href && href.indexOf('#') === 0) {
1957            var $this = $(href);
1958            var $form = $this.find('form');
1959            if ($form.length > 0) {
1960                $form = $($form[0]);
1961            }
1962            var $formParent = $this;
1963            while ($form.length < 1) {
1964                $formParent = $formParent.parent();
1965                $form = $formParent.find('form');
1966                if ($form.length > 0) {
1967                    $form = $($form[0]);
1968                }
1969            }
1970            if ($form.find('input:visible') > 0) {
1971                $($form.find('input:visible')[0]).focus();
1972            }
1973        }
1974    });
1975});
1976
1977window.mapBoxA11y = function(elem) {
1978    if (elem === null || 'undefined' === typeof elem) {
1979        return;
1980    }
1981
1982    let observer = new MutationObserver(mutationRecords => {
1983        for (let mRecod of mutationRecords) {
1984            if (
1985                mRecod.type === 'childList' &&
1986                mRecod.target.classList.contains('leaflet-marker-pane') &&
1987                mRecod.addedNodes.length > 0
1988            ) {
1989                for (let tileItem of mRecod.addedNodes) {
1990                    if (tileItem.tagName.toLowerCase() === 'img') {
1991                        tileItem.setAttribute('alt', 'Property Marker');
1992                    }
1993                }
1994            } else if (
1995                mRecod.type === 'childList' &&
1996                mRecod.target.classList.contains('leaflet-tile-container') &&
1997                mRecod.addedNodes.length > 0
1998            ) {
1999                for (let tileItem of mRecod.addedNodes) {
2000                    if (tileItem.tagName.toLowerCase() === 'img') {
2001                        tileItem.setAttribute('role', 'none');
2002                    }
2003                }
2004            }
2005        }
2006    });
2007
2008    observer.observe(elem, {
2009        childList: true,
2010        subtree: true
2011    });
2012};
2013
2014/*
2015*   This content is licensed according to the W3C Software License at
2016*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
2017*/
2018var MenubarItem = function (domNode, menuObj) {
2019
2020    this.menu = menuObj;
2021    this.domNode = domNode;
2022    this.popupMenu = false;
2023
2024    this.hasFocus = false;
2025    this.hasHover = false;
2026
2027    this.isMenubarItem = true;
2028
2029    this.keyCode = Object.freeze({
2030        'TAB': 9,
2031        'ESC': 27,
2032        'SPACE': 32,
2033        'PAGEUP': 33,
2034        'PAGEDOWN': 34,
2035        'END': 35,
2036        'HOME': 36,
2037        'LEFT': 37,
2038        'UP': 38,
2039        'RIGHT': 39,
2040        'DOWN': 40
2041    });
2042};
2043
2044MenubarItem.prototype.init = function () {
2045    this.domNode.tabIndex = -1;
2046
2047    this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
2048    this.domNode.addEventListener('focus', this.handleFocus.bind(this));
2049    this.domNode.addEventListener('blur', this.handleBlur.bind(this));
2050    this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
2051    this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
2052
2053    // Initialize pop up menus
2054
2055    var nextElement = this.domNode.nextElementSibling;
2056
2057    if (nextElement && nextElement.tagName === 'UL') {
2058        this.popupMenu = new PopupMenu(nextElement, this);
2059        this.popupMenu.init();
2060    }
2061
2062};
2063
2064MenubarItem.prototype.handleKeydown = function (event) {
2065    var tgt = event.currentTarget,
2066        char = event.key,
2067        flag = false,
2068        clickEvent;
2069
2070    function isPrintableCharacter (str) {
2071        return str.length === 1 && str.match(/\S/);
2072    }
2073
2074    switch (event.keyCode) {
2075        case this.keyCode.DOWN:
2076            if (this.popupMenu) {
2077                this.popupMenu.open();
2078                this.popupMenu.setFocusToFirstItem();
2079                flag = true;
2080            }
2081            break;
2082
2083        case this.keyCode.LEFT:
2084            this.menu.setFocusToPreviousItem(this);
2085            flag = true;
2086            break;
2087
2088        case this.keyCode.RIGHT:
2089            this.menu.setFocusToNextItem(this);
2090            flag = true;
2091            break;
2092
2093        case this.keyCode.UP:
2094            if (this.popupMenu) {
2095                this.popupMenu.open();
2096                this.popupMenu.setFocusToLastItem();
2097                flag = true;
2098            }
2099            break;
2100
2101        case this.keyCode.HOME:
2102        case this.keyCode.PAGEUP:
2103            this.menu.setFocusToFirstItem();
2104            flag = true;
2105            break;
2106
2107        case this.keyCode.END:
2108        case this.keyCode.PAGEDOWN:
2109            this.menu.setFocusToLastItem();
2110            flag = true;
2111            break;
2112
2113        case this.keyCode.TAB:
2114            if (this.popupMenu) {
2115                this.popupMenu.close(true);
2116            }
2117
2118            break;
2119
2120        case this.keyCode.ESC:
2121            if (this.popupMenu) {
2122                this.popupMenu.close(true);
2123            }
2124            break;
2125
2126        case this.keyCode.SPACE:
2127            flag = true;
2128            this.domNode.click();
2129            break;
2130
2131        default:
2132            if (isPrintableCharacter(char)) {
2133                this.menu.setFocusByFirstCharacter(this, char);
2134                flag = true;
2135            }
2136            break;
2137    }
2138
2139    if (flag) {
2140        event.stopPropagation();
2141        event.preventDefault();
2142    }
2143};
2144
2145MenubarItem.prototype.setExpanded = function (value) {
2146    if (value) {
2147        this.domNode.setAttribute('aria-expanded', 'true');
2148    }
2149    else {
2150        this.domNode.setAttribute('aria-expanded', 'false');
2151    }
2152};
2153
2154MenubarItem.prototype.handleFocus = function (event) {
2155    this.menu.hasFocus = true;
2156};
2157
2158MenubarItem.prototype.handleBlur = function (event) {
2159    this.menu.hasFocus = false;
2160};
2161
2162MenubarItem.prototype.handleMouseover = function (event) {
2163    this.hasHover = true;
2164    if (this.popupMenu) {
2165        this.popupMenu.open();
2166    }
2167};
2168
2169MenubarItem.prototype.handleMouseout = function (event) {
2170    this.hasHover = false;
2171    if (this.popupMenu) {
2172        setTimeout(this.popupMenu.close.bind(this.popupMenu, false), 300);
2173    }
2174};
2175
2176/*
2177*   This content is licensed according to the W3C Software License at
2178*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
2179*/
2180
2181var Menubar = function (domNode) {
2182    var elementChildren,
2183        msgPrefix = 'Menubar constructor argument menubarNode ';
2184
2185    // Check whether menubarNode is a DOM element
2186    if (!domNode instanceof Element) {
2187        throw new TypeError(msgPrefix + 'is not a DOM Element.');
2188    }
2189
2190    // Check whether menubarNode has descendant elements
2191    if (null === domNode || domNode.childElementCount === 0) {
2192        throw new Error(msgPrefix + 'has no element children.');
2193    }
2194
2195    // Check whether menubarNode has A elements
2196    var e = domNode.firstElementChild;
2197    while (e) {
2198        var menubarItem = e.firstElementChild;
2199        if (e && menubarItem && menubarItem.tagName !== 'A') {
2200            throw new Error(msgPrefix + 'has child elements are not A elements.');
2201        }
2202        e = e.nextElementSibling;
2203    }
2204
2205    this.isMenubar = true;
2206
2207    this.domNode = domNode;
2208
2209    this.menubarItems = []; // See Menubar init method
2210    this.firstChars = []; // See Menubar init method
2211
2212    this.firstItem = null; // See Menubar init method
2213    this.lastItem = null; // See Menubar init method
2214
2215    this.hasFocus = false; // See MenubarItem handleFocus, handleBlur
2216    this.hasHover = false; // See Menubar handleMouseover, handleMouseout
2217};
2218
2219/*
2220*   @method Menubar.prototype.init
2221*
2222*   @desc
2223*       Adds ARIA role to the menubar node
2224*       Traverse menubar children for A elements to configure each A element as a ARIA menuitem
2225*       and populate menuitems array. Initialize firstItem and lastItem properties.
2226*/
2227Menubar.prototype.init = function () {
2228    var menubarItem, childElement, menuElement, textContent, numItems;
2229
2230
2231    // Traverse the element children of menubarNode: configure each with
2232    // menuitem role behavior and store reference in menuitems array.
2233    var elem = this.domNode.firstElementChild;
2234
2235    while (elem) {
2236        var menuElement = elem.firstElementChild;
2237
2238        if (elem && menuElement && menuElement.tagName === 'A') {
2239            menubarItem = new MenubarItem(menuElement, this);
2240            menubarItem.init();
2241            this.menubarItems.push(menubarItem);
2242            textContent = menuElement.textContent.trim();
2243            this.firstChars.push(textContent.substring(0, 1).toLowerCase());
2244        }
2245
2246        elem = elem.nextElementSibling;
2247    }
2248
2249    // Use populated menuitems array to initialize firstItem and lastItem.
2250    numItems = this.menubarItems.length;
2251    if (numItems > 0) {
2252        this.firstItem = this.menubarItems[ 0 ];
2253        this.lastItem = this.menubarItems[ numItems - 1 ];
2254    }
2255    this.firstItem.domNode.tabIndex = 0;
2256};
2257
2258/* FOCUS MANAGEMENT METHODS */
2259
2260Menubar.prototype.setFocusToItem = function (newItem) {
2261
2262    var flag = false;
2263
2264    for (var i = 0; i < this.menubarItems.length; i++) {
2265        var mbi = this.menubarItems[i];
2266
2267        if (mbi.domNode.tabIndex == 0) {
2268            flag = mbi.domNode.getAttribute('aria-expanded') === 'true';
2269        }
2270
2271        mbi.domNode.tabIndex = -1;
2272        if (mbi.popupMenu) {
2273            mbi.popupMenu.close();
2274        }
2275    }
2276
2277    newItem.domNode.focus();
2278    newItem.domNode.tabIndex = 0;
2279
2280    if (flag && newItem.popupMenu) {
2281        newItem.popupMenu.open();
2282    }
2283};
2284
2285Menubar.prototype.setFocusToFirstItem = function (flag) {
2286    this.setFocusToItem(this.firstItem);
2287};
2288
2289Menubar.prototype.setFocusToLastItem = function (flag) {
2290    this.setFocusToItem(this.lastItem);
2291};
2292
2293Menubar.prototype.setFocusToPreviousItem = function (currentItem) {
2294    var index,
2295      newItem
2296    ;
2297
2298    if (currentItem === this.firstItem) {
2299        newItem = this.lastItem;
2300    }
2301    else {
2302        index = this.menubarItems.indexOf(currentItem);
2303        newItem = this.menubarItems[ index - 1 ];
2304    }
2305
2306    this.setFocusToItem(newItem);
2307
2308};
2309
2310Menubar.prototype.setFocusToNextItem = function (currentItem) {
2311    var index,
2312      newItem
2313    ;
2314
2315    if (currentItem === this.lastItem) {
2316        newItem = this.firstItem;
2317    }
2318    else {
2319        index = this.menubarItems.indexOf(currentItem);
2320        newItem = this.menubarItems[ index + 1 ];
2321    }
2322
2323    this.setFocusToItem(newItem);
2324
2325};
2326
2327Menubar.prototype.setFocusByFirstCharacter = function (currentItem, char) {
2328    var start, index, char = char.toLowerCase();
2329    var flag = currentItem.domNode.getAttribute('aria-expanded') === 'true';
2330
2331    // Get start index for search based on position of currentItem
2332    start = this.menubarItems.indexOf(currentItem) + 1;
2333    if (start === this.menubarItems.length) {
2334        start = 0;
2335    }
2336
2337    // Check remaining slots in the menu
2338    index = this.getIndexFirstChars(start, char);
2339
2340    // If not found in remaining slots, check from beginning
2341    if (index === -1) {
2342        index = this.getIndexFirstChars(0, char);
2343    }
2344
2345    // If match was found...
2346    if (index > -1) {
2347        this.setFocusToItem(this.menubarItems[ index ]);
2348    }
2349};
2350
2351Menubar.prototype.getIndexFirstChars = function (startIndex, char) {
2352    for (var i = startIndex; i < this.firstChars.length; i++) {
2353        if (char === this.firstChars[ i ]) {
2354            return i;
2355        }
2356    }
2357    return -1;
2358};
2359
2360jQuery(function($) {
2361    window.focusableContent = [];
2362    const focusableElements =
2363        'button, [href], input, select, textarea, [tabindex]:not
2363([tabindex="-1"])'
2364    ;
2365
2366    window.getModalFocusableElements = function($modalWindow = null) {
2367        if (typeof window.modal === 'undefined' && (typeof $modalWindow === 'undefined' || $modalWindow === null)) {
2368            return [];
2369        }
2370
2371        if ((typeof window.modal === 'undefined' && typeof $modalWindow === 'object' && $modalWindow !== null) ||
2372            (typeof window.modal === 'object' && typeof $modalWindow === 'object' && $modalWindow !== null)
2373        ) {
2374            window.modal = $modalWindow;
2375        }
2376
2377        let focusableContent = [],
2378            modalFocusableContent = window.modal.find(focusableElements)
2379        ;
2380
2381        modalFocusableContent.each(function() {
2382            let $this = $(this);
2383
2384            if (
2385                $this.attr('type') === 'hidden' ||
2386                $this.closest('.gfield_visibility_hidden').length !== 0 ||
2387                $this.closest('.gform_hidden').length !== 0
2388            ) {
2389                $this.attr('aria-hidden', 'true');
2390                $this.attr('tabindex', '-1');
2391
2392            } else if ($this.is(':visible')) {
2393                focusableContent.push($(this));
2394            }
2395        });
2396
2397        return focusableContent;
2398    };
2399
2400    window.setFocusInModalWindow = function(clearFocusableContent = false) {
2401        if (clearFocusableContent === true) {
2402            window.modal = $('[data-modal-id="' + window.modalId + '"]');
2403        }
2404
2405        if (clearFocusableContent === true || window.focusableContent === null || window.focusableContent.length === 0) {
2406            window.focusableContent = window.getModalFocusableElements();
2407        }
2408
2409        if (window.focusableContent === null || window.focusableContent.length === 0) {
2410            return;
2411        }
2412
2413        let lastFocusableElement = window.focusableContent[window.focusableContent.length - 1]; // get last element to be focused inside modal
2414        let firstModalFocusableElement = window.focusableContent[0];
2415
2416        $(document)
2417            .off('keydown.modalTab')
2418            .on('keydown.modalTab', function(event) {
2419                let isTabPressed = event.key === 'Tab' || event.keyCode === 9;
2420
2421                if (!isTabPressed) {
2422                    return;
2423                }
2424
2425                if (event.shiftKey) { // if shift key pressed for shift + tab combination
2426                    if (document.activeElement === firstModalFocusableElement[0]) {
2427                        lastFocusableElement.focus();
2427 // add focus for the last focusable element
2428                        event.preventDefault();
2429                    }
2430                } else { // if tab key is pressed
2431                    if (document.activeElement === lastFocusableElement[0])  { // if focused has reached to last focusable element then focus first focusable element after pressing tab
2432                        firstModalFocusableElement.focus(); // add focus for the first focusable element
2433                        event.preventDefault();
2434                    }
2435                }
2436            })
2437        ;
2438
2439        let $gfFromFocus = window.modal.find('#gf_form_focus');
2440        if ($gfFromFocus.length === 0) {
2441            firstModalFocusableElement.focus();
2442        } else {
2443            setFocusToErrorField($gfFromFocus, firstModalFocusableElement);
2444        }
2445    };
2446
2447    $(document)
2448        .on('shown.bs.modal', '.modal', function (event) {
2449            let $that = $(this);
2450            $(document.body).addClass('modal-open');
2451            window.modal = $that;
2452            window.modalId = new Date().getTime();
2453            window.modal.attr('data-modal-id', window.modalId);
2454
2455            if (typeof window.modalCaller === "undefined" || window.modalCaller === null) {
2456                if (typeof event.relatedTarget !== "undefined" && event.relatedTarget !== null) {
2457                    window.modalCaller = event.relatedTarget;
2458                } else if (typeof window.modalCallerClick !== "undefined" && window.modalCallerClick !== null) {
2459                    window.modalCaller = window.modalCallerClick;
2460                }
2461
2462            }
2463
2464            let $parent = $that;
2465            const excludeTagNames = [
2466                'script',
2467                'style',
2468                'noscript'
2469            ];
2470            do {
2471                let $siblings = $parent.siblings();
2472
2473                if ($siblings.length > 0) {
2474                    $siblings.each(function(index, elem) {
2475                        if (!excludeTagNames.includes(elem.tagName.toLowerCase())) {
2476                            if (elem.hasAttribute('aria-hidden')) {
2477                                elem.setAttribute('data-arhide', elem.getAttribute('aria-hidden'));
2478                            }
2479
2480                            elem.setAttribute('aria-hidden', 'true');
2481                        }
2482                    });
2483                }
2484
2485                $parent = $parent.parent();
2486
2487            }  while ($parent[0].tagName.toLowerCase() !== 'body')
2488
2489        window.setFocusInModalWindow(true);
2490        })
2491        .on('hidden.bs.modal', '.modal', function () {
2492            $(document.body).removeClass('modal-open');
2493
2494            if (window.modalCaller !== null && typeof window.modalCaller !== "undefined") {
2495                setTimeout(function() {
2496                    window.modalCaller.focus();
2497                    window.modalCaller = null;
2498                }, 300);
2499            }
2500
2501            window.modal = null;
2502            window.focusableContent = null;
2503
2504            let $elems = document.querySelectorAll('[aria-hidden="true"]');
2505
2506            $elems.forEach(elem => {
2507                if (elem.hasAttribute('data-arhide')) {
2508                    elem.setAttribute('aria-hidden', elem.getAttribute('data-arhide'));
2509                    elem.removeAttribute('data-arhide');
2510                } else {
2511                    elem.removeAttribute('aria-hidden');
2512                }
2513            });
2514        })
2515    ;
2516
2517    function setFocusToErrorField($element, firstModalFocusableElement) {
2518        let formWrapper = $element.parent();
2519        let errorFieldWrapper = $(formWrapper.find('.gfield_error')[0]);
2520
2521        if (errorFieldWrapper) {
2522            let $elemWithError = errorFieldWrapper.find('[aria-invalid="true"]:first');
2523
2524            if ($elemWithError.length > 0) {
2525                setTimeout(function() {$elemWithError.focus();}, 100);
2526            } else {
2527                setTimeout(function() {firstModalFocusableElement.focus();}, 100);
2528            }
2529        }
2530    }
2531
2532    $(document).on('gform_confirmation_loaded', function(event, form_id){
2533        window.focusableContent = null;
2534        window.setFocusInModalWindow(true);
2535    });
2536
2537    $('#gf_form_focus').on('focus', function () {
2538        setFocusToErrorField($(this));
2539    });
2540
2541    $(document).on('gform_page_loaded', function(){
2542        window.focusableContent = null;
2543        window.setFocusInModalWindow(true);
2544    });
2545
2546});
2547
2548/*
2549*   This content is licensed according to the W3C Software License at
2550*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
2551*/
2552var MenuItem = function (domNode, menuObj) {
2553
2554    var popupObj;
2555    if (typeof popupObj !== 'object') {
2556        popupObj = false;
2557    }
2558
2559    this.domNode = domNode;
2560    this.menu = menuObj;
2561    this.popupMenu = false;
2562    this.isMenubarItem = false;
2563
2564    this.keyCode = Object.freeze({
2565        'TAB': 9,
2566        'ESC': 27,
2567        'SPACE': 32,
2568        'PAGEUP': 33,
2569        'PAGEDOWN': 34,
2570        'END': 35,
2571        'HOME': 36,
2572        'LEFT': 37,
2573        'UP': 38,
2574        'RIGHT': 39,
2575        'DOWN': 40
2576    });
2577};
2578
2579MenuItem.prototype.init = function () {
2580    this.domNode.tabIndex = -1;
2581
2582    this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
2583    this.domNode.addEventListener('click', this.handleClick.bind(this));
2584    this.domNode.addEventListener('focus', this.handleFocus.bind(this));
2585    this.domNode.addEventListener('blur', this.handleBlur.bind(this));
2586    this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
2587    this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
2588
2589    // Initialize flyout menu
2590
2591    var nextElement = this.domNode.nextElementSibling;
2592
2593    if (nextElement && nextElement.tagName === 'UL') {
2594        this.popupMenu = new PopupMenu(nextElement, this);
2595        this.popupMenu.init();
2596    }
2597
2598};
2599
2600MenuItem.prototype.isExpanded = function () {
2601    return this.domNode.getAttribute('aria-expanded') === 'true';
2602};
2603
2604/* EVENT HANDLERS */
2605
2606MenuItem.prototype.handleKeydown = function (event) {
2607    var tgt  = event.currentTarget,
2608        char = event.key,
2609        flag = false,
2610        clickEvent;
2611
2612    function isPrintableCharacter (str) {
2613        return str.length === 1 && str.match(/\S/);
2614    }
2615
2616    switch (event.keyCode) {
2617        case this.keyCode.UP:
2618            this.menu.setFocusToPreviousItem(this);
2619            flag = true;
2620            break;
2621
2622        case this.keyCode.DOWN:
2623            this.menu.setFocusToNextItem(this);
2624            flag = true;
2625            break;
2626
2627        case this.keyCode.LEFT:
2628            this.menu.setFocusToController('previous', true);
2629            this.menu.close(true);
2630            flag = true;
2631            break;
2632
2633        case this.keyCode.RIGHT:
2634            if (this.popupMenu) {
2635                this.popupMenu.open();
2636                this.popupMenu.setFocusToFirstItem();
2637            }
2638            else {
2639                this.menu.setFocusToController('next', true);
2640                this.menu.close(true);
2641            }
2642            flag = true;
2643            break;
2644
2645        case this.keyCode.HOME:
2646        case this.keyCode.PAGEUP:
2647            this.menu.setFocusToFirstItem();
2648            flag = true;
2649            break;
2650
2651        case this.keyCode.END:
2652        case this.keyCode.PAGEDOWN:
2653            this.menu.setFocusToLastItem();
2654            flag = true;
2655            break;
2656
2657        case this.keyCode.ESC:
2658            this.menu.setFocusToController();
2659            this.menu.close(true);
2660            flag = true;
2661            break;
2662
2663        case this.keyCode.SPACE:
2664            flag = true;
2665            this.domNode.click();
2666            break;
2667
2668        case this.keyCode.TAB:
2669            this.menu.setFocusToController();
2670            break;
2671
2672        default:
2673            if (isPrintableCharacter(char)) {
2674                this.menu.setFocusByFirstCharacter(this, char);
2675                flag = true;
2676            }
2677            break;
2678    }
2679
2680    if (flag) {
2681        event.stopPropagation();
2682        event.preventDefault();
2683    }
2684};
2685
2686MenuItem.prototype.setExpanded = function (value) {
2687    if (value) {
2688        this.domNode.setAttribute('aria-expanded', 'true');
2689    }
2690    else {
2691        this.domNode.setAttribute('aria-expanded', 'false');
2692    }
2693};
2694
2695MenuItem.prototype.handleClick = function (event) {
2696    this.menu.setFocusToController();
2697    this.menu.close(true);
2698};
2699
2700MenuItem.prototype.handleFocus = function (event) {
2701    this.menu.hasFocus = true;
2702};
2703
2704MenuItem.prototype.handleBlur = function (event) {
2705    this.menu.hasFocus = false;
2706    setTimeout(this.menu.close.bind(this.menu, false), 300);
2707};
2708
2709MenuItem.prototype.handleMouseover = function (event) {
2710    this.menu.hasHover = true;
2711    this.menu.open();
2712    if (this.popupMenu) {
2713        this.popupMenu.hasHover = true;
2714        this.popupMenu.open();
2715    }
2716};
2717
2718MenuItem.prototype.handleMouseout = function (event) {
2719    if (this.popupMenu) {
2720        this.popupMenu.hasHover = false;
2721        this.popupMenu.close(true);
2722    }
2723
2724    this.menu.hasHover = false;
2725    setTimeout(this.menu.close.bind(this.menu, false), 300);
2726};
2727
2728/*
2729*   This content is licensed according to the W3C Software License at
2730*   https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
2731*/
2732var PopupMenu = function (domNode, controllerObj) {
2733    var elementChildren,
2734        msgPrefix = 'PopupMenu constructor argument domNode ';
2735
2736    // Check whether domNode is a DOM element
2737    if (!domNode instanceof Element) {
2738        throw new TypeError(msgPrefix + 'is not a DOM Element.');
2739    }
2740    // Check whether domNode has child elements
2741    if (domNode.childElementCount === 0) {
2742        throw new Error(msgPrefix + 'has no element children.');
2743    }
2744    // Check whether domNode descendant elements have A elements
2745    var childElement = domNode.firstElementChild;
2746    while (childElement) {
2747        var menuitem = childElement.firstElementChild;
2748        if (menuitem && menuitem === 'A') {
2749            throw new Error(msgPrefix + 'has descendant elements that are not A elements.');
2750        }
2751        childElement = childElement.nextElementSibling;
2752    }
2753
2754    this.isMenubar = false;
2755
2756    this.domNode    = domNode;
2757    this.controller = controllerObj;
2758
2759    this.menuitems = []; // See PopupMenu init method
2760    this.firstChars = []; // See PopupMenu init method
2761
2762    this.firstItem = null; // See PopupMenu init method
2763    this.lastItem = null; // See PopupMenu init method
2764
2765    this.hasFocus = false; // See MenuItem handleFocus, handleBlur
2766    this.hasHover = false; // See PopupMenu handleMouseover, handleMouseout
2767};
2768
2769/*
2770*   @method PopupMenu.prototype.init
2771*
2772*   @desc
2773*       Add domNode event listeners for mouseover and mouseout. Traverse
2774*       domNode children to configure each menuitem and populate menuitems
2775*       array. Initialize firstItem and lastItem properties.
2776*/
2777PopupMenu.prototype.init = function () {
2778    var childElement, menuElement, menuItem, textContent, numItems, label;
2779
2780    // Configure the domNode itself
2781
2782    this.domNode.addEventListener('mouseover', this.handleMouseover.bind(this));
2783    this.domNode.addEventListener('mouseout', this.handleMouseout.bind(this));
2784
2785    // Traverse the element children of domNode: configure each with
2786    // menuitem role behavior and store reference in menuitems array.
2787    childElement = this.domNode.firstElementChild;
2788
2789    while (childElement) {
2790        menuElement = childElement.firstElementChild;
2791
2792        if (menuElement && menuElement.tagName === 'A') {
2793            menuItem = new MenuItem(menuElement, this);
2794            menuItem.init();
2795            this.menuitems.push(menuItem);
2796            textContent = menuElement.textContent.trim();
2797            this.firstChars.push(textContent.substring(0, 1).toLowerCase());
2798        }
2799        childElement = childElement.nextElementSibling;
2800    }
2801
2802    // Use populated menuitems array to initialize firstItem and lastItem.
2803    numItems = this.menuitems.length;
2804    if (numItems > 0) {
2805        this.firstItem = this.menuitems[ 0 ];
2806        this.lastItem = this.menuitems[ numItems - 1 ];
2807    }
2808};
2809
2810/* EVENT HANDLERS */
2811
2812PopupMenu.prototype.handleMouseover = function (event) {
2813    this.hasHover = true;
2814};
2815
2816PopupMenu.prototype.handleMouseout = function (event) {
2817    this.hasHover = false;
2818    setTimeout(this.close.bind(this, false), 1);
2819};
2820
2821/* FOCUS MANAGEMENT METHODS */
2822
2823PopupMenu.prototype.setFocusToController = function (command, flag) {
2824
2825    if (typeof command !== 'string') {
2826        command = '';
2827    }
2828
2829    function setFocusToMenubarItem (controller, close) {
2830        while (controller) {
2831            if (controller.isMenubarItem) {
2832                controller.domNode.focus();
2833                return controller;
2834            }
2835            else {
2836                if (close) {
2837                    controller.menu.close(true);
2838                }
2839                controller.hasFocus = false;
2840            }
2841            controller = controller.menu.controller;
2842        }
2843        return false;
2844    }
2845
2846    if (command === '') {
2847        if (this.controller && this.controller.domNode) {
2848            this.controller.domNode.focus();
2849        }
2850        return;
2851    }
2852
2853    if (!this.controller.isMenubarItem) {
2854        this.controller.domNode.focus();
2855        this.close();
2856
2857        if (command === 'next') {
2858            var menubarItem = setFocusToMenubarItem(this.controller, false);
2859            if (menubarItem) {
2860                menubarItem.menu.setFocusToNextItem(menubarItem, flag);
2861            }
2862        }
2863    }
2864    else {
2865        if (command === 'previous') {
2866            this.controller.menu.setFocusToPreviousItem(this.controller, flag);
2867        }
2868        else if (command === 'next') {
2869            this.controller.menu.setFocusToNextItem(this.controller, flag);
2870        }
2871    }
2872
2873};
2874
2875PopupMenu.prototype.setFocusToFirstItem = function () {
2876    this.firstItem.domNode.focus();
2877};
2878
2879PopupMenu.prototype.setFocusToLastItem = function () {
2880    this.lastItem.domNode.focus();
2881};
2882
2883PopupMenu.prototype.setFocusToPreviousItem = function (currentItem) {
2884    var index;
2885
2886    if (currentItem === this.firstItem) {
2887        this.lastItem.domNode.focus();
2888    }
2889    else {
2890        index = this.menuitems.indexOf(currentItem);
2891        this.menuitems[ index - 1 ].domNode.focus();
2892    }
2893};
2894
2895PopupMenu.prototype.setFocusToNextItem = function (currentItem) {
2896    var index;
2897
2898    if (currentItem === this.lastItem) {
2899        this.firstItem.domNode.focus();
2900    }
2901    else {
2902        index = this.menuitems.indexOf(currentItem);
2903        this.menuitems[ index + 1 ].domNode.focus();
2904    }
2905};
2906
2907PopupMenu.prototype.setFocusByFirstCharacter = function (currentItem, char) {
2908    var start, index, char = char.toLowerCase();
2909
2910    // Get start index for search based on position of currentItem
2911    start = this.menuitems.indexOf(currentItem) + 1;
2912    if (start === this.menuitems.length) {
2913        start = 0;
2914    }
2915
2916    // Check remaining slots in the menu
2917    index = this.getIndexFirstChars(start, char);
2918
2919    // If not found in remaining slots, check from beginning
2920    if (index === -1) {
2921        index = this.getIndexFirstChars(0, char);
2922    }
2923
2924    // If match was found...
2925    if (index > -1) {
2926        this.menuitems[ index ].domNode.focus();
2927    }
2928};
2929
2930PopupMenu.prototype.getIndexFirstChars = function (startIndex, char) {
2931    for (var i = startIndex; i < this.firstChars.length; i++) {
2932        if (char === this.firstChars[ i ]) {
2933            return i;
2934        }
2935    }
2936    return -1;
2937};
2938
2939/* MENU DISPLAY METHODS */
2940
2941PopupMenu.prototype.open = function () {
2942    if (this.domNode.parentElement.classList.contains('mega-menu-col')) {
2943        return;
2944    }
2945    // Get position and bounding rectangle of controller object's DOM node
2946    var rect = this.controller.domNode.getBoundingClientRect();
2947
2948    // Set CSS properties
2949    if (!this.controller.isMenubarItem) {
2950        this.domNode.parentNode.style.position = 'relative';
2951        this.domNode.style.display = 'block';
2952        this.domNode.style.position = 'absolute';
2953        this.domNode.style.left = rect.width + 'px';
2954        this.domNode.style.zIndex = 100;
2955    }
2956    else {
2957        if (this.domNode.classList.contains('grid--flex')) {
2958            this.domNode.style.display = 'flex';
2959        } else {
2960            this.domNode.style.display = 'block';
2961        }
2962
2963        this.domNode.style.position = 'absolute';
2964        this.domNode.style.top = (rect.height - 1) + 'px';
2965
2966        if (this.domNode.classList.contains('grid--flex')) {
2967            this.domNode.style.top = (rect.height - 1 + this.domNode.parentNode.offsetTop) + 'px';
2968        }
2969        this.domNode.style.zIndex = 100;
2970    }
2971
2972    this.controller.setExpanded(true);
2973
2974};
2975
2976PopupMenu.prototype.close = function (force) {
2977    if (this.domNode.parentElement.classList.contains('mega-menu-col')) {
2978        return;
2979    }
2980
2981    var controllerHasHover = this.controller.hasHover;
2982    var hasFocus = this.hasFocus;
2983
2984    for (var i = 0; i < this.menuitems.length; i++) {
2985        var mi = this.menuitems[i];
2986        if (mi.popupMenu) {
2987            hasFocus = hasFocus | mi.popupMenu.hasFocus;
2988        }
2989    }
2990
2991    if (!this.controller.isMenubarItem) {
2992        controllerHasHover = false;
2993    }
2994
2995    if (force || (!hasFocus && !this.hasHover && !controllerHasHover)) {
2996        this.domNode.style.display = 'none';
2997        this.domNode.style.zIndex = 0;
2998        this.controller.setExpanded(false);
2999    }
3000};
3001
3002
3003var RadioButton = function (domNode, groupObj) {
3004
3005  this.domNode = domNode;
3006  this.radioGroup = groupObj;
3007
3008  this.keyCode = Object.freeze({
3009    'RETURN': 13,
3010    'SPACE': 32,
3011    'END': 35,
3012    'HOME': 36,
3013    'LEFT': 37,
3014    'UP': 38,
3015    'RIGHT': 39,
3016    'DOWN': 40
3017  });
3018};
3019
3020RadioButton.prototype.init = function () {
3021  if (!this.domNode.classList.contains('active')) {
3022    this.domNode.tabIndex = -1;
3023    this.domNode.setAttribute('aria-checked', 'false');
3024  }
3025
3026  this.domNode.addEventListener('keydown', this.handleKeydown.bind(this));
3027  this.domNode.addEventListener('click', this.handleClick.bind(this));
3028  this.domNode.addEventListener('focus', this.handleFocus.bind(this));
3029  this.domNode.addEventListener('blur', this.handleBlur.bind(this));
3030
3031};
3032
3033/* EVENT HANDLERS */
3034
3035RadioButton.prototype.handleKeydown = function (event) {
3036  var tgt = event.currentTarget,
3037    flag = false,
3038    clickEvent;
3039
3040  switch (event.keyCode) {
3041    case this.keyCode.SPACE:
3042    case this.keyCode.RETURN:
3043      this.radioGroup.setChecked(this);
3044      flag = true;
3045      break;
3046
3047    case this.keyCode.UP:
3048      this.radioGroup.setCheckedToPreviousItem(this);
3049      flag = true;
3050      break;
3051
3052    case this.keyCode.DOWN:
3053      this.radioGroup.setCheckedToNextItem(this);
3054      flag = true;
3055      break;
3056
3057    case this.keyCode.LEFT:
3058      this.radioGroup.setCheckedToPreviousItem(this);
3059      flag = true;
3060      break;
3061
3062    case this.keyCode.RIGHT:
3063      this.radioGroup.setCheckedToNextItem(this);
3064      flag = true;
3065      break;
3066
3067    default:
3068      break;
3069  }
3070
3071  if (flag) {
3072    event.stopPropagation();
3073    event.preventDefault();
3074  }
3075};
3076
3077RadioButton.prototype.handleClick = function (event) {
3078  this.radioGroup.setChecked(this);
3079};
3080
3081RadioButton.prototype.handleFocus = function (event) {
3082  this.domNode.classList.add('focus');
3083};
3084
3085RadioButton.prototype.handleBlur = function (event) {
3086  this.domNode.classList.remove('focus');
3087};
3088
3089var RadioGroup = function (domNode) {
3090
3091  this.domNode = domNode;
3092
3093  this.radioButtons = [];
3094
3095  this.firstRadioButton = null;
3096  this.lastRadioButton = null;
3097
3098};
3099
3100RadioGroup.prototype.init = function () {
3101
3102  // initialize pop up menus
3103  if (!this.domNode.getAttribute('role')) {
3104    this.domNode.setAttribute('role', 'radiogroup');
3105  }
3106
3107  var rbs = this.domNode.querySelectorAll('[role=radio]');
3108
3109  for (var i = 0; i < rbs.length; i++) {
3110    var rb = new RadioButton(rbs[i], this);
3111    rb.init();
3112    this.radioButtons.push(rb);
3113
3114    if (!this.firstRadioButton) {
3115      this.firstRadioButton = rb;
3116    }
3117    this.lastRadioButton = rb;
3118  }
3119
3120  if (this.firstRadioButton.domNode.classList.contains('active')) {
3121    this.firstRadioButton.domNode.tabIndex = 0;
3122  }
3123};
3124
3125RadioGroup.prototype.setChecked = function (currentItem) {
3126  for (var i = 0; i < this.radioButtons.length; i++) {
3127    var rb = this.radioButtons[i];
3128    rb.domNode.setAttribute('aria-checked', 'false');
3129    rb.domNode.tabIndex = -1;
3130  }
3131  currentItem.domNode.setAttribute('aria-checked', 'true');
3132  currentItem.domNode.tabIndex = 0;
3133  currentItem.domNode.focus();
3134  currentItem.domNode.click();
3135};
3136
3137RadioGroup.prototype.setCheckedToPreviousItem = function (currentItem) {
3138  var index;
3139
3140  if (currentItem === this.firstRadioButton) {
3141    this.setChecked(this.lastRadioButton);
3142  } else {
3143    index = this.radioButtons.indexOf(currentItem);
3144    this.setChecked(this.radioButtons[index - 1]);
3145  }
3146};
3147
3148RadioGroup.prototype.setCheckedToNextItem = function (currentItem) {
3149  var index;
3150
3151  if (currentItem === this.lastRadioButton) {
3152    this.setChecked(this.firstRadioButton);
3153  } else {
3154    index = this.radioButtons.indexOf(currentItem);
3155    this.setChecked(this.radioButtons[index + 1]);
3156  }
3157};
3158
3159
3160(function () {
3161  var radios = function () {
3162    var components = document.querySelectorAll('.hji-polygon-wrap'),
3163      selectors = ['.for-polygon', '.for-circle'];
3164
3165    components.forEach(component => {
3166      var radios = component.querySelectorAll(selectors);
3167
3168      radios.forEach(radio => {
3169        radio.setAttribute('role', 'radio');
3170
3171        if (radio.classList.contains('active')) {
3172          radio.setAttribute('aria-checked', 'true');
3173          radio.setAttribute('tabindex', '0');
3174        } else {
3175          radio.setAttribute('aria-checked', 'false');
3176          radio.setAttribute('tabindex', '-1');
3177        }
3178      });
3179
3180      component.setAttribute('role', 'radiogroup');
3181
3182      const radioGroup = new RadioGroup(component);
3183      radioGroup.init();
3184    });
3185  };
3186
3187  var highlightLabelForFocusedFormTypeRadio = function() {
3188    jQuery(".property_type_selector_wrapper label input[type='radio']").focus(function() {
3189      jQuery(this).closest('label').addClass("labelfocus");
3190    }).blur(function() {
3191      jQuery(this).closest('label').removeClass("labelfocus");
3192    });
3193  };
3194
3195  window.onload = () => {
3196    highlightLabelForFocusedFormTypeRadio();
3197    setTimeout(radios, 1000);
3198  };
3199})();
3200
3201/*jshint esversion: 6 */
3202
3203Array.from(document.getElementsByClassName("share-buttons-menu-button")).forEac
3203h(
3204    function(element, index, array) {
3205        const shareButtonsMenuButton = new BlvdAccessibilityMenuButton(element);
3206        shareButtonsMenuButton.init();
3207    }
3208);
3209
3210
3211
3212
3213
3214class W3cTab
3215{
3216  constructor(tabContainer)
3217  {
3218    this.tabContainer = tabContainer;
3219    this.tablist = this.tabContainer.querySelectorAll('[role="tablist"]')[0];
3220    this.tabs = [];
3221    this.panels = [];
3222    this.delay = this.determineDelay();
3223    this.activeTab = this.tablist.querySelector(':scope > [role="tab"][aria-selected="true"]');
3224    this.activePanel = null;
3225    this.beforeActivatePanel = function(currentPanel, nextPanel){};
3226    this.afterActivatePanel = function(currentPanel, prevPanel){};
3227
3228    this.generateElementsLists();
3229
3230    // For easy reference
3231    this.keys = {
3232      end: 35,
3233      home: 36,
3234      left: 37,
3235      up: 38,
3236      right: 39,
3237      down: 40,
3238      delete: 46
3239    };
3240
3241    // Add or substract depending on key pressed
3242    this.direction = {
3243      37: -1,
3244      38: -1,
3245      39: 1,
3246      40: 1
3247    };
3248
3249    for (let i = 0; i < this.tabs.length; ++i) {
3250      this.addListeners(i);
3251    }
3252  }
3253
3254  /**
3255   * Get delay value
3256   *
3257   * @returns {number}
3258   */
3259  determineDelay ()
3260  {
3261    let hasDelay = this.tablist.hasAttribute('data-delay');
3262    let delay = 0;
3263
3264    if (hasDelay) {
3265        let delayValue = this.tablist.getAttribute('data-delay');
3266
3267        if (delayValue) {
3268          delay = delayValue;
3269        } else {
3270          // If no value is specified, default to 300ms
3271          delay = 300;
3272        }
3273    }
3274
3275    return delay;
3276  }
3277
3278  /**
3279   * Add tabs listeners
3280   *
3281   * @param index
3282   */
3283  addListeners (index)
3284  {
3285    this.tabs[index].addEventListener('click', (event) => this.clickEventListener(event));
3286    this.tabs[index].addEventListener('keydown', (event) => this.keydownEventListener(event));
3287    this.tabs[index].addEventListener('keyup', (event) => this.keyupEventListener(event));
3288
3289    // Build an array with all tabs (<button>s) in it
3290    this.tabs[index].index = index;
3291  }
3292
3293  // When a tab is clicked, activateTab is fired to activate it
3294  clickEventListener (event)
3295  {
3296    let tab = event.target;
3297    this.activateTab(tab, false);
3298  }
3299
3300  /**
3301   * Handle keydown on tabs
3302   *
3303   * @param event
3304   */
3305  keydownEventListener (event)
3306  {
3307    let key = event.keyCode;
3308
3309    switch (key) {
3310      case this.keys.end:
3311        event.preventDefault();
3312        // Activate last tab
3313        this.focusLastTab();
3314        break;
3315
3316      case this.keys.home:
3317        event.preventDefault();
3318        // Activate first tab
3319        this.focusFirstTab();
3320        break;
3321
3322      // Up and down are in keydown
3323      // because we need to prevent page scroll >:)
3324      case this.keys.up:
3325      case this.keys.down:
3326        this.determineOrientation(event);
3327        break;
3328    }
3329  }
3330
3331  /**
3332   * Handle keyup on tabs
3333   *
3334   * @param event
3335   */
3336  keyupEventListener (event)
3337  {
3338    let key = event.keyCode;
3339
3340    switch (key) {
3341      case this.keys.left:
3342      case this.keys.right:
3343        this.determineOrientation(event);
3344        break;
3345      case this.keys.delete:
3346        this.determineDeletable(event);
3347        break;
3348    }
3349  }
3350
3351  /**
3352   * When a tablist’s aria-orientation is set to vertical,
3353   * only up and down arrow should function.
3354   * In all other cases only left and right arrow function.
3355   *
3356   * @param event
3357   */
3358  determineOrientation (event)
3359  {
3360    let key = event.keyCode;
3361    let vertical = this.tablist.getAttribute('aria-orientation') === 'vertical';
3362    let proceed = false;
3363
3364    if (vertical) {
3365      if (key === this.keys.up || key === this.keys.down) {
3366        event.preventDefault();
3367        proceed = true;
3368      }
3369    } else {
3370      if (key === this.keys.left || key === this.keys.right) {
3371        event.preventDefault();
3372        proceed = true;
3373      }
3374    }
3375
3376    if (proceed) {
3377      this.switchTabOnArrowPress(event);
3378    }
3379  }
3380
3381  /**
3382   * Either focus the next, previous, first, or last tab
3383   * depening on key pressed
3384   *
3385   * @param event
3386   */
3387  switchTabOnArrowPress (event)
3388  {
3389    let pressed = event.keyCode;
3390
3391    for (let i = 0; i < this.tabs.length; i++) {
3392      this.tabs[i].addEventListener('focus', this.focusEventHandler);
3393    }
3394
3395    if (this.direction[pressed]) {
3396      let target = event.target;
3397
3398      if (target.index !== undefined) {
3399        if (this.tabs[target.index + this.direction[pressed]]) {
3400          this.tabs[target.index + this.direction[pressed]].dispatchEvent(new MouseEvent('click'));
3401          this.tabs[target.index + this.direction[pressed]].focus();
3402        }
3403        else if (pressed === this.keys.left || pressed === this.keys.up) {
3404          this.focusLastTab();
3405        }
3406        else if (pressed === this.keys.right || pressed === this.keys.down) {
3407          this.focusFirstTab();
3408        }
3409      }
3410    }
3411  }
3412
3413  /**
3414   * Activates any given tab panel
3415   *
3416   * @param tab
3417   * @param setFocus
3418   */
3419  activateTab (tab, setFocus)
3420  {
3421    this.activeTab = tab;
3422    setFocus = setFocus || true;
3423    // Get the value of aria-controls (which is an ID)
3424    let controls = tab.getAttribute('aria-controls');
3425    let activePanel = this.tabContainer.querySelector('#' + controls);
3426
3427    this.beforeActivatePanel(this.activePanel, activePanel);
3428    this.deactivateTabs();
3429    tab.setAttribute('tabindex', 0);
3430    tab.setAttribute('aria-selected', 'true');
3431
3432    // Set focus when required
3433    if (setFocus) {
3434      tab.focus();
3435    }
3436
3437    this.afterActivatePanel(activePanel, this.activePanel);
3438
3439    this.activePanel = activePanel;
3440  }
3441
3442  /**
3443   * Deactivate all tabs and tab panels
3444   */
3445  deactivateTabs ()
3446  {
3447    for (let i = 0; i < this.tabs.length; i++) {
3448      this.tabs[i].setAttribute('tabindex', '-1');
3449      this.tabs[i].setAttribute('aria-selected', 'false');
3450      this.tabs[i].removeEventListener('focus', this.focusEventHandler);
3451    }
3452  }
3453
3454  /**
3455   * Make a guess
3456   */
3457  focusFirstTab ()
3458  {
3459    this.tabs[0].dispatchEvent(new MouseEvent('click'));
3460    this.tabs[0].focus();
3461  }
3462
3463  /**
3464   * Make a guess
3465   */
3466  focusLastTab ()
3467  {
3468    this.tabs[this.tabs.length - 1].dispatchEvent(new MouseEvent('click'));
3469    this.tabs[this.tabs.length - 1].focus();
3470  }
3471
3472  /**
3473   * Detect if a tab is deletable
3474   *
3475   * @param event
3476   */
3477  determineDeletable (event)
3478  {
3479    let target = event.target;
3480
3481    if (target.getAttribute('data-deletable') !== null) {
3482      // Delete target tab
3483      this.deleteTab(event, target);
3484
3485      // Update arrays related to tabs widget
3486      this.generateElementsLists();
3487
3488      // Activate the closest tab to the one that was just deleted
3489      if (target.index - 1 < 0) {
3490        this.activateTab(this.tabs[0]);
3491      } else {
3492        this.activateTab(this.tabs[target.index - 1]);
3493      }
3494    }
3495  }
3496
3497  /**
3498   * Deletes a tab and its panel
3499   *
3500   * @param event
3501   */
3502   deleteTab (event)
3503  {
3504    let target = event.target;
3505    let panel = this.tabContainer.querySelector('#' + target.getAttribute('aria-controls'));
3506
3507    target.parentElement.removeChild(target);
3508    panel.parentElement.removeChild(panel);
3509  }
3510
3511  /**
3512   * Focus element
3513   *
3514   * @param event
3515   */
3516  focusEventHandler (event)
3517  {
3518    let target = event.target;
3519    target.dispatchEvent(new MouseEvent('click'));
3520
3521    setTimeout(this.checkTabFocus, this.delay, target);
3522  }
3523
3524  /**
3525   * Only activate tab on focus if it still has focus after the delay
3526   *
3527   * @param target
3528   */
3529  checkTabFocus (target)
3530  {
3531    let focused = document.activeElement;
3532
3533    if (target === focused) {
3534      this.activateTab(target, false);
3535    }
3536  }
3537
3538  /**
3539   * Get all tabs and panels on container
3540   */
3541  generateElementsLists ()
3542  {
3543    this.tabs = this.tablist.querySelectorAll('[role="tab"]');
3544    this.panels = this.tabContainer.querySelectorAll('  [role="tabpanel"]');
3545  }
3546}
3547
3548
3549class W3cTabs
3550{
3551  constructor(selector, options) {
3552    this.tabs = document.querySelectorAll(selector);
3553
3554    if (this.tabs.length <= 0) {
3555      return;
3556    }
3557
3558    this.createTabsInstances(options);
3559
3560  }
3561
3562  createTabsInstances(options)
3563  {
3564    this.tabs.forEach(function(tabContainer) {
3565      let tab = new W3cTab(tabContainer);
3566
3567      if ('undefined' !== typeof options) {
3568        if(null !== options.beforeActivatePanel) {
3569          tab.beforeActivatePanel = options.beforeActivatePanel;
3570        }
3571
3572        if(null !== options.afterActivatePanel) {
3573          tab.afterActivatePanel = options.afterActivatePanel;
3574        }
3575      }
3576    });
3577  }
3578}
3579
3580//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImFjY29yZGlvbi5qcyIsImFyaWEtdXRpbHMuanMiLCJibHZkQWNjZXNzaWJpbGl0eU1lbnVCdXR0b24uanMiLCJjYXJkcy5qcyIsImNvbG9yYm94LmpzIiwiZGF0YS1ncmlkLmpzIiwiaGlkZW5NYXBBcmVhLmpzIiwibWFrZUZvY3VzT25UYXJnZXRBZnRlckdvT25MaW5rLmpzIiwibWFwYm94LmpzIiwibWVudWJhckl0ZW1MaW5rcy5qcyIsIm1lbnViYXJMaW5rcy5qcyIsIm1vZGFsLmpzIiwicG9wdXBNZW51SXRlbUxpbmtzLmpzIiwicG9wdXBNZW51TGlua3MuanMiLCJyYWRpb0J1dHRvbnMuanMiLCJzaGFyZUJ1dHRvbnMuanMiLCJ0YWJzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDcFJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDOUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN6Y0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNuNkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3BDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0
3580FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN2TEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNuTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2xSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNyTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiYWNjZXNzaWJpbGl0eS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4qICAgVGhpcyBjb250ZW50IGlzIGxpY2Vuc2VkIGFjY29yZGluZyB0byB0aGUgVzNDIFNvZnR3YXJlIExpY2Vuc2UgYXRcbiogICBodHRwczovL3d3dy53My5vcmcvQ29uc29ydGl1bS9MZWdhbC8yMDE1L2NvcHlyaWdodC1zb2Z0d2FyZS1hbmQtZG9jdW1lbnRcbipcbiogICBTaW1wbGUgYW
3580Njb3JkaW9uIHBhdHRlcm4gZXhhbXBsZVxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgYWNjb3JkaW9uT2JqZWN0ID0ge307XG52YXIgYWNjb3JkaW9uQXJyYXkgPSBbXTtcbnZhciBtb2JpbGVWaWV3RmxhZyA9IGZhbHNlO1xuXG5mdW5jdGlvbiBhbGx5QWNjb3JkaW9uSW5pdChjc3NDbGFzcywgZHluYW1pYykge1xuICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoY3NzQ2xhc3MpLmZvckVhY2goZnVuY3Rpb24gKGFjY29yZGlvbikge1xuICAgICAgICBhY2NvcmRpb25PYmplY3QgPSB7XG4gICAgICAgICAgICB0cmlnZ2VyOiAnJyxcbiAgICAgICAgICAgIG1vdXNlQ2xpY2s6ICcnLFxuICAgICAgICAgICAga2V5ZG93bjogJycsXG4gICAgICAgICAgICBmb2N1czogJycsXG4gICAgICAgICAgICBibHVyOiAnJ1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEFsbG93IGZvciBtdWx0aXBsZSBhY2NvcmRpb24gc2VjdGlvbnMgdG8gYmUgZXhwYW5kZWQgYXQgdGhlIHNhbWUgdGltZVxuICAgICAgICB2YXIgYWxsb3dNdWx0aXBsZSA9IGFjY29yZGlvbi5oYXNBdHRyaWJ1dGUoJ2RhdGEtYWxsb3ctbXVsdGlwbGUnKTtcbiAgICAgICAgLy8gQWxsb3cgZm9yIGVhY2ggdG9nZ2xlIHRvIGJvdGggb3BlbiBhbmQgY2xvc2UgaW5kaXZpZHVhbGx5XG4gICAgICAgIHZhciBhbGxvd1RvZ2dsZSA9IChhbGxvd011bHRpcGxlKSA/IGFsbG93TXVsdGlwbGUgOiBhY2NvcmRpb24uaGFzQXR0cmlidXRlKCdkYXRhLWFsbG93LXRvZ2dsZScpO1xuXG4gICAgICAgIC8vIENyZWF0ZSB0aGUgYXJyYXkgb2YgdG9nZ2xlIGVsZW1lbnRzIGZvciB0aGUgYWNjb3JkaW9uIGdyb3VwXG4gICAgICAgIHZhciB0cmlnZ2VycyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFjY29yZGlvbi5xdWVyeVNlbGVjdG9yQWxsKCcuYWNjb3JkaW9uLXRyaWdnZXInKSk7XG4gICAgICAgIHZhciBwYW5lbHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhY2NvcmRpb24ucXVlcnlTZWxlY3RvckFsbCgnLmFjY29yZGlvbi1wYW5lbCcpKTtcblxuICAgICAgICBBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGFjY29yZGlvbi5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCdhY2NvcmRpb24tdHJpZ2dlcicpLCBmdW5jdGlvbihlbGVtZW50KSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBhY2NvcmRpb25DbGljayh0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgY3VycmVudCB0b2dnbGUgaXMgZXhwYW5kZWQuXG4gICAgICAgICAgICAgICAgdmFyIGlzRXhwYW5kZWQgPSB0YXJnZXQuZ2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJykgPT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgIHZhciBhY3RpdmUgPSBhY2NvcmRpb24ucXVlcnlTZWxlY3RvcignW2FyaWEtZXhwYW5kZWQ9XCJ0cnVlXCJdJyk7XG5cbiAgICAgICAgICAgICAgICAvLyB3aXRob3V0IGFsbG93TXVsdGlwbGUsIGNsb3NlIHRoZSBvcGVuIGFjY29yZGlvblxuICAgICAgICAgICAgICAgIGlmICghYWxsb3dNdWx0aXBsZSAmJiBhY3RpdmUgJiYgYWN0aXZlICE9PSB0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBleHBhbmRlZCBzdGF0ZSBvbiB0aGUgdHJpZ2dlcmluZyBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGlkZSB0aGUgYWNjb3JkaW9uIHNlY3Rpb25zLCB1c2luZyBhcmlhLWNvbnRyb2xzIHRvIHNwZWNpZnkgdGhlIGRlc2lyZWQgc2VjdGlvblxuICAgICAgICAgICAgICAgICAgICBkb2
3580N1bWVudC5nZXRFbGVtZW50QnlJZChhY3RpdmUuZ2V0QXR0cmlidXRlKCdhcmlhLWNvbnRyb2xzJykpLnNldEF0dHJpYnV0ZSgnaGlkZGVuJywgJycpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW4gdG9nZ2xpbmcgaXMgbm90IGFsbG93ZWQsIGNsZWFuIHVwIGRpc2FibGVkIHN0YXRlXG4gICAgICAgICAgICAgICAgICAgIGlmICghYWxsb3dUb2dnbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZS5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNFeHBhbmRlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGV4cGFuZGVkIHN0YXRlIG9uIHRoZSB0cmlnZ2VyaW5nIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICd0cnVlJyk7XG4gICAgICAgICAgICAgICAgICAgIC8vIEhpZGUgdGhlIGFjY29yZGlvbiBzZWN0aW9ucywgdXNpbmcgYXJpYS1jb250cm9scyB0byBzcGVjaWZ5IHRoZSBkZXNpcmVkIHNlY3Rpb25cbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0LmdldEF0dHJpYnV0ZSgnYXJpYS1jb250cm9scycpKS5yZW1vdmVBdHRyaWJ1dGUoJ2hpZGRlbicpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRvZ2dsaW5nIGlzIG5vdCBhbGxvd2VkLCBzZXQgZGlzYWJsZWQgc3RhdGUgb24gdHJpZ2dlclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWFsbG93VG9nZ2xlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQuc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYWxsb3dUb2dnbGUgJiYgaXNFeHBhbmRlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIGV4cGFuZGVkIHN0YXRlIG9uIHRoZSB0cmlnZ2VyaW5nIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuICAgICAgICAgICAgICAgICAgICAvLyBIaWRlIHRoZSBhY2NvcmRpb24gc2VjdGlvbnMsIHVzaW5nIGFyaWEtY29udHJvbHMgdG8gc3BlY2lmeSB0aGUgZGVzaXJlZCBzZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRhcmdldC5nZXRBdHRyaWJ1dGUoJ2FyaWEtY29udHJvbHMnKSkuc2V0QXR0cmlidXRlKCdoaWRkZW4nLCAnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2Y
3580XIgbW91c2VDbGljayA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIHZhciB0YXJnZXQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblxuICAgICAgICAgICAgICAgIGFjY29yZGlvbkNsaWNrKHRhcmdldCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIG1vdXNlQ2xpY2spO1xuXG5cbiAgICAgICAgICAgIC8vIEJpbmQga2V5Ym9hcmQgYmVoYXZpb3JzIG9uIHRoZSBtYWluIGFjY29yZGlvbiBjb250YWluZXJcbiAgICAgICAgICAgIHZhciBrZXlEb3duID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhcmdldCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IGV2ZW50LndoaWNoLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgdmFyIGlzRXhwYW5kZWQgPSB0YXJnZXQuZ2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJykgPT0gJ3RydWUnO1xuICAgICAgICAgICAgICAgIHZhciBhbGxvd1RvZ2dsZSA9IChhbGxvd011bHRpcGxlKSA/IGFsbG93TXVsdGlwbGUgOiBhY2NvcmRpb24uaGFzQXR0cmlidXRlKCdkYXRhLWFsbG93LXRvZ2dsZScpO1xuXG4gICAgICAgICAgICAgICAgLy8gMzMgPSBQYWdlIFVwLCAzNCA9IFBhZ2UgRG93blxuICAgICAgICAgICAgICAgIHZhciBjdHJsTW9kaWZpZXIgPSAoZXZlbnQuY3RybEtleSAmJiBrZXkubWF0Y2goLzMzfDM0LykpO1xuXG4gICAgICAgICAgICAgICAgLy8gSXMgdGhpcyBjb21pbmcgZnJvbSBhbiBhY2NvcmRpb24gaGVhZGVyP1xuICAgICAgICAgICAgICAgIGlmICh0YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKCdhY2NvcmRpb24tdHJpZ2dlcicpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFVwLyBEb3duIGFycm93IGFuZCBDb250cm9sICsgUGFnZSBVcC8gUGFnZSBEb3duIGtleWJvYXJkIG9wZXJhdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgLy8gMzggPSBVcCwgNDAgPSBEb3duXG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkubWF0Y2goLzM4fDQwLykgfHwgY3RybE1vZGlmaWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2Y
3580XIgaW5kZXggPSB0cmlnZ2Vycy5pbmRleE9mKHRhcmdldCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZGlyZWN0aW9uID0gKGtleS5tYXRjaCgvMzR8NDAvKSkgPyAxIDogLTE7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gdHJpZ2dlcnMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0luZGV4ID0gKGluZGV4ICsgbGVuZ3RoICsgZGlyZWN0aW9uKSAlIGxlbmd0aDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcnNbbmV3SW5kZXhdLmZvY3VzKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoa2V5Lm1hdGNoKC8zNXwzNi8pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAzNSA9IEVuZCwgMzYgPSBIb21lIGtleWJvYXJkIG9wZXJhdGlvbnNcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR28gdG8gZmlyc3QgYWNjb3JkaW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnMzYnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2Vyc1swXS5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHbyB0byBsYXN0IGFjY29yZGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJzM1JzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcnNbdHJpZ2dlcnMubGVuZ3RoIC0gMV0uZm9jdXMoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5Lm1hdGNoKC8xM3wzMi8pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2NvcmRpb25DbGljayh0YXJnZXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGtleURvd24pO1xuXG4gICAgICAgIC8vIFRoZXNlIGFyZSB1c2VkIHRvIHN0eWxlIHRoZSBhY2NvcmRpb24gd2hlbiBvbmUgb2YgdGhlIGJ1dHRvbnMgaGFzIGZvY3VzXG4gICAgICAgICAgICB2Y
3580XIgZm9jdXMgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBhY2NvcmRpb24uY2xhc3NMaXN0LmFkZCgnZm9jdXMnKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5nZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnKSA9PT0gJ2ZhbHNlJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEF0dHJpYnV0ZSgndGFiaW5kZXgnLCAnMCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgZm9jdXMpO1xuXG4gICAgICAgICAgICB2YXIgYmx1ciA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIGFjY29yZGlvbi5jbGFzc0xpc3QucmVtb3ZlKCdmb2N1cycpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmdldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcpID09PSAnZmFsc2UnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICctMScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCBibHVyKTtcblxuXG4gICAgICAgIC8vIE1pbm9yIHNldHVwOiB3aWxsIHNldCBkaXNhYmxlZCBzdGF0ZSwgdmlhIGFyaWEtZGlzYWJsZWQsIHRvIGFuXG4gICAgICAgIC8vIGV4cGFuZGVkLyBhY3RpdmUgYWNjb3JkaW9uIHdoaWNoIGlzIG5vdCBhbGxvd2VkIHRvIGJlIHRvZ2dsZWQgY2xvc2VcbiAgICAgICAgICAgIGlmICghYWxsb3dUb2dnbGUpIHtcbiAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIGZpcnN0IGV4cGFuZGVkLyBhY3RpdmUgYWNjb3JkaW9uXG4gICAgICAgICAgICAgICAgdmFyIGV4cGFuZGVkID0gYWNjb3JkaW9uLnF1ZXJ5U2VsZWN0b3IoJ1thcmlhLWV4cGFuZGVkPVwidHJ1ZVwiXScpO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgYW4gZXhwYW5kZWQvIGFjdGl2ZSBhY2NvcmRpb24gaXMgZm91bmQsIGRpc2FibGVcbiAgICAgICAgICAgICAgICBpZiAoZXhwYW5kZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhwYW5kZWQuc2V0QXR0cmlidXRlKCdhcmlhLWRpc2FibGVkJywgJ3RydWUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cblxuICAgICAgICAgICAgaWYgKGR5bmFtaWMpIHtcbiAgICAgICAgICAgICAgICBhY2NvcmRpb25PYmplY3QudHJpZ2dlciA9IGVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgYWNjb3JkaW9uT2JqZWN0LmtleWRvd24gPSBrZXlEb3duO1xuICAgICAgICAgICAgICAgIGFjY29yZGlvbk9iamVjdC5tb3VzZUNsaWNrID0gbW91c2VDbGljaztcbiAgICAgICAgICAgICAgICBhY2NvcmRpb25PYmplY3QuYmx1ciA9IGJsdXI7XG4gICAgICAgICAgICAgICAgYWNjb3JkaW9uT2JqZWN0LmZvY3VzID0gZm9jdXM7XG4gICAgICAgICAgICAgICAgYWNjb3JkaW9uQXJyYXkucHVzaChhY2NvcmRpb25PYmplY3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuYWxseUFjY29yZGlvbkluaXQoJy5hY2NvcmRpb24nLCBmYWxzZSk7XG5cbmZ1bmN0aW9uIGFsbHlEZXNrdG9wQWNjb3JkaW9uSW5pdCgpIHtcbiAgICBqUXVlcnkoZG9jdW1lbnQpLmZpbmQoJ1tkYXRhLWFjY29yZGlvbl0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgalF1ZXJ5KHRoaXMpLmFkZENsYXNzKCdhY2NvcmRpb24nKTtcbiAgICAgICAgalF1ZXJ5KCcuYWNjb3JkaW9uLXBhbmVsJykuZWFjaChmdW5jdGlvbihpbmRleCkge1xuICAgICAgICAgICAgdmFyICR0aGlzID0galF1ZXJ5KHRoaXMpO1xuXG4gICAgICAgICAgICAkdGhpc1xuICAgICAgICAgICAgICAgIC5hdHRyKCdyb2xlJywgJ3JlZ2lvbicpXG4gICAgICAgICAgICAgICAgLmF0dHIoJ2FyaWEtbGFiZWxsZWRieScsICR0aGlzLmRhdGEoJ2xhYmVsbGVkYnknKSlcbiAgICAgICAgICAgIDtcbiAgICAgICAgICAgIGlmIChpbmRleCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICR0aGlzLmF0dHIoJ2hpZGRlbicsICcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGpRdWVyeSgnLmFjY29yZGlvbi10cmlnZ2VyJylcbiAgICAgICAgICAgIC5hZGRDbGFzcygnY3Vyc29yLXBvaW50ZXInKVxuICAgICAgICAgICAgLmF0dHIoJ3JvbGUnLCAnYnV0dG9uJylcbiAgICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyICR0aGlzID0galF1ZXJ5KHRoaXMpO1xuICAgICAgICAgICAgICAgICR0aGlzLmF0dHIoJ2FyaWEtY29udHJvbHMnLCAkdGhpcy5kYXRhKCdjb250cm9scycpKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5hdHRyKCd0YWJpbmRleCcsICcwJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdGhpcy5oYXNDbGFzcygnaXMtbW9iaWxlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAndHJ1ZScpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCAndHJ1ZScpXG4gICAgICAgICAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkdGhpc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hdHRyKCdhcmlhLWV4cGFuZGVkJywgJ2ZhbHNlJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXR0cignYXJpYS1kaXNhYmxlZCcsICdmYWxzZScpXG4gICAgICAgICAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkdGhpc1xuICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ2FyaWEtZGlzYWJsZWQnLCAnZmFsc2UnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLmF0dHIoJ3RhYmluZGV4JywgJy0xJylcbiAgICAgICAgICAgICAgICAgICAgO1xuICAgICAgICAgICAgICAgI
3580H1cbiAgICAgICAgICAgIH0pXG4gICAgICAgIDtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gZGlzcGxheVdpbmRvd1NpemUoKSB7XG4gICAgLy8gR2V0IHdpZHRoIGFuZCBoZWlnaHQgb2YgdGhlIHdpbmRvdyBleGNsdWRpbmcgc2Nyb2xsYmFyc1xuICAgIHZhciB3ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoO1xuXG4gICAgaWYgKCh3IDwgNzY4KSAmJiAhbW9iaWxlVmlld0ZsYWcpIHtcbiAgICAgICAgYWxseURlc2t0b3BBY2NvcmRpb25Jbml0KCk7XG4gICAgICAgIGFsbHlBY2NvcmRpb25Jbml0KCcuYWNjb3JkaW9uJywgdHJ1ZSk7XG4gICAgICAgIG1vYmlsZVZpZXdGbGFnID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKCh3ID4gNzY4KSAmJiBtb2JpbGVWaWV3RmxhZykge1xuICAgICAgICBqUXVlcnkoZG9jdW1lbnQpLmZpbmQoJ1tkYXRhLWFjY29yZGlvbl0nKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciAkdGhpcyA9IGpRdWVyeSh0aGlzKTtcbiAgICAgICAgICAgICR0aGlzLnJlbW92ZUNsYXNzKCdhY2NvcmRpb24nKTtcblxuICAgICAgICAgICAgJHRoaXMuZmluZCgnLmFjY29yZGlvbi10cmlnZ2VyJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBqUXVlcnkodGhpcylcbiAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUNsYXNzKCdjdXJzb3ItcG9pbnRlcicpXG4gICAgICAgICAgICAgICAgICAgIC5yZW1vdmVBdHRyKCdyb2xlJylcbiAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUF0dHIoJ2FyaWEtZXhwYW5kZWQnKVxuICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQXR0cignYXJpYS1kaXNhYmxlZCcpXG4gICAgICAgICAgICAgICAgICAgIC5yZW1vdmVBdHRyKCdhcmlhLWNvbnRyb2xzJylcbiAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgJHRoaXMuZmluZCgnLmFjY29yZGlvbi1wYW5lbCcpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgalF1ZXJ5KHRoaXMpXG4gICAgICAgICAgICAgICAgICAgIC5wcm9wKCdoaWRkZW4nLCBmYWxzZSlcbiAgICAgICAgICAgICAgICAgICAgLnJlbW92ZUF0dHIoJ3JvbGUnKVxuICAgICAgICAgICAgICAgICAgICAucmVtb3ZlQXR0cignYXJpYS1sYWJlbGxlZGJ5JylcbiAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyICRlbGVtZW50O1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFjY29yZGlvbkFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAkZWxlbWVudCA9IGFjY29yZGlvbkFycmF5W2ldO1xuICAgICAgICAgICAgJGVsZW1lbnQudHJpZ2dlci5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZUNsaWNrJywgJGVsZW1lbnQubW91c2VDbGljayk7XG4gICAgICAgICAgICAkZWxlbWVudC50cmlnZ2VyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleURvd24nLCAkZWxlbWVudC5rZXlkb3duKTtcbiAgICAgICAgICAgICRlbGVtZW50LnRyaWdnZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCAkZWxlbWVudC5mb2N1cyk7XG4gICAgICAgICAgICAkZWxlbWVudC50cmlnZ2VyLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2JsdXInLCAkZWxlbWVudC5ibHVyKTtcbiAgICAgICAgfVxuICAgICAgICBhY2NvcmRpb25BcnJheSA9IFtdO1xuXG4gICAgICAgIG1vYmlsZVZpZXdGbGFnID0gZmFsc2U7XG4gICAgfVxufVxuXG4vLyBBdHRhY2hpbmcgdGhlIGV2ZW50IGxpc3RlbmVyIGZ1bmN0aW9uIHRvIHdpbmRvdydzIHJlc2l6ZSBldmVudFxud2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIiwgZGlzcGxheVdpbmRvd1NpemUpO1xuXG5qUXVlcnkoZnVuY3Rpb24oJCkge1xuICAgIHZhciB3ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoO1xuICAgIGlmICh3IDwgNzY4KSB7XG4gICAgICAgIG1vYmlsZVZpZXdGbGFnID0gdHJ1ZTtcbiAgICAgICAgYWxseURlc2t0b3BBY2NvcmRpb25Jbml0KCk7XG4gICAgICAgIGFsbHlBY2NvcmRpb25Jbml0KCcuYWNjb3JkaW9uJywgdHJ1ZSk7XG4gICAgfVxufSk7XG4iLCIvKipcbiAqIEBuYW1lc3BhY2UgYXJpYVxuICovXG5cbnZhciBhcmlhID0gYXJpYSB8fCB7fTtcblxuLyoqXG4gKiBAZGVzY1xuICogIEtleSBjb2RlIGNvbnN0YW50c1xuICovXG5hcmlhLktleUNvZGUgPSB7XG4gICAgQkFDS1NQQUNFOiA4LFxuICAgIFRBQjogOSxcbiAgICBSRVRVUk46IDEzLFxuICAgIEVTQzogMjcsXG4gICAgU1BBQ0U6IDMyLFxuICAgIFBBR0VfVVA6IDMzLFxuICAgIFBBR0VfRE9XTjogMzQsXG4gICAgRU5EOiAzNSxcbiAgICBIT01FOiAzNixcbiAgICBMRUZUOiAzNyxcbiAgICBVUDogMzgsXG4gICAgUklHSFQ6IDM5LFxuICAgIERPV046IDQwLFxuICAgIERFTEVURTogNDZcbn07XG5cbmFyaWEuVXRpbHMgPSBhcmlhLlV0aWxzIHx8IHt9O1xuXG4vLyBQb2x5ZmlsbCBzcmMgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0VsZW1lbnQvbWF0Y2hlc1xuYXJpYS5VdGlscy5tYXRjaGVzID0gZnVuY3Rpb24gKGVsZW1lbnQsIHNlbGVjdG9yKSB7XG4gICAgaWYgKCFFbGVtZW50LnByb3RvdHlwZS5tYXRjaGVzKSB7XG4gICAgICAgIEVsZW1lbnQucHJvdG90eXBlLm1hdGNoZXMgPVxuICAgICAgICAgICAgRWxlbWVudC5wcm90b3R5cGUubWF0Y2hlc1NlbGVjdG9yIHx8XG4gICAgICAgICAgICBFbGVtZW50LnByb3RvdHlwZS5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcbiAgICAgICAgICAgIEVsZW1lbnQucHJvdG90eXBlLm1zTWF0Y2hlc1NlbGVjdG9yIHx8XG4gICAgICAgICAgICBFbGVtZW50LnByb3RvdHlwZS5vTWF0Y2hlc1NlbGVjdG9yIHx8XG4gICAgICAgICAgICBFbGVtZW50LnByb3RvdHlwZS53ZWJraXRNYXRjaGVzU2VsZWN0b3IgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoZXMgPSBlbGVtZW50LnBhcmVudE5vZGUucXVlcnlTZWxlY3RvckFsbChzKTtcbiAgICAgICAgICAgICAgICB2Y
3580XIgaSA9IG1hdGNoZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHdoaWxlICgtLWkgPj0gMCAmJiBtYXRjaGVzLml0ZW0oaSkgIT09IHRoaXMpIHt9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGkgPiAtMTtcbiAgICAgICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnQubWF0Y2hlcyhzZWxlY3Rvcik7XG59O1xuXG5hcmlhLlV0aWxzLnJlbW92ZSA9IGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgaWYgKGl0ZW0ucmVtb3ZlICYmIHR5cGVvZiBpdGVtLnJlbW92ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gaXRlbS5yZW1vdmUoKTtcbiAgICB9XG4gICAgaWYgKGl0ZW0ucGFyZW50Tm9kZSAmJlxuICAgICAgICBpdGVtLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQgJiZcbiAgICAgICAgdHlwZW9mIGl0ZW0ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gaXRlbS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGl0ZW0pO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59O1xuXG5hcmlhLlV0aWxzLmlzRm9jdXNhYmxlID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICBpZiAoZWxlbWVudC50YWJJbmRleCA+IDAgfHwgKGVsZW1lbnQudGFiSW5kZXggPT09IDAgJiYgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3RhYkluZGV4JykgIT09IG51bGwpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChlbGVtZW50LmRpc2FibGVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGVsZW1lbnQubm9kZU5hbWUpIHtcbiAgICAgICAgY2FzZSAnQSc6XG4gICAgICAgICAgICByZXR1cm4gISFlbGVtZW50LmhyZWYgJiYgZWxlbWVudC5yZWwgIT0gJ2lnbm9yZSc7XG4gICAgICAgIGNhc2UgJ0lOUFVUJzpcbiAgICAgICAgICAgIHJldHVybiBlbGVtZW50LnR5cGUgIT0gJ2hpZGRlbicgJiYgZWxlbWVudC50eXBlICE9ICdmaWxlJztcbiAgICAgICAgY2FzZSAnQlVUVE9OJzpcbiAgICAgICAgY2FzZSAnU0VMRUNUJzpcbiAgICAgICAgY2FzZSAnVEVYVEFSRUEnOlxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxufTtcblxuYXJpYS5VdGlscy5nZXRBbmNlc3RvckJ5U2VsZWN0b3IgPSBmdW5jdGlvbiAoZWxlbWVudCwgc2VsZWN0b3IpIHtcbiAgICBpZiAoIWFyaWEuVXRpbHMubWF0Y2hlcyhlbGVtZW50LCBzZWxlY3RvciArICcgJyArIGVsZW1lbnQudGFnTmFtZSkpIHtcbiAgICAgICAgLy8gRWxlbWVudCBpcyBub3QgaW5zaWRlIGFuIGVsZW1lbnQgdGhhdCBtYXRjaGVzIHNlbGVjdG9yXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIE1vdmUgdXAgdGhlIERPTSB0cmVlIHVudGlsIGEgcGFyZW50IG1hdGNoaW5nIHRoZSBzZWxlY3RvciBpcyBmb3VuZFxuICAgIHZhciBjdXJyZW50Tm9kZSA9IGVsZW1lbnQ7XG4gICAgdmFyIGFuY2VzdG9yID0gbnVsbDtcbiAgICB3aGlsZSAoYW5jZXN0b3IgPT09IG51bGwpIHtcbiAgICAgICAgaWYgKGFyaWEuVXRpbHMubWF0Y2hlcyhjdXJyZW50Tm9kZS5wYXJlbnROb2RlLCBzZWxlY3RvcikpIHtcbiAgICAgICAgICAgIGFuY2VzdG9yID0gY3VycmVudE5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGN1cnJlbnROb2RlID0gY3VycmVudE5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBhbmNlc3Rvcjtcbn07XG5cbmFyaWEuVXRpbHMuaGFzQ2xhc3MgPSBmdW5jdGlvbiAoZWxlbWVudCwgY2xhc3NOYW1lKSB7XG4gICAgcmV0dXJuIChuZXcgUmVnRXhwKCcoXFxcXHN8XiknICsgY2xhc3NOYW1lICsgJyhcXFxcc3wkKScpKS50ZXN0KGVsZW1lbnQuY2xhc3NOYW1lKTtcbn07XG5cbmFyaWEuVXRpbHMuYWRkQ2xhc3MgPSBmdW5jdGlvbiAoZWxlbWVudCwgY2xhc3NOYW1lKSB7XG4gICAgaWYgKCFhcmlhLlV0aWxzLmhhc0NsYXNzKGVsZW1lbnQsIGNsYXNzTmFtZSkpIHtcbiAgICAgICAgZWxlbWVudC5jbGFzc05hbWUgKz0gJyAnICsgY2xhc3NOYW1lO1xuICAgIH1cbn07XG5cbmFyaWEuVXRpbHMucmVtb3ZlQ2xhc3MgPSBmdW5jdGlvbiAoZWxlbWVudCwgY2xhc3NOYW1lKSB7XG4gICAgdmFyIGNsYXNzUmVnZXggPSBuZXcgUmVnRXhwKCcoXFxcXHN8XiknICsgY2xhc3NOYW1lICsgJyhcXFxcc3wkKScpO1xuICAgIGVsZW1lbnQuY2xhc3NOYW1lID0gZWxlbWVudC5jbGFzc05hbWUucmVwbGFjZShjbGFzc1JlZ2V4LCAnICcpLnRyaW0oKTtcbn07XG5cbmFyaWEuVXRpbHMuYmluZE1ldGhvZHMgPSBmdW5jdGlvbiAob2JqZWN0IC8qICwgLi4ubWV0aG9kTmFtZXMgKi8pIHtcbiAgICB2YXIgbWV0aG9kTmFtZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIG1ldGhvZE5hbWVzLmZvckVhY2goZnVuY3Rpb24gKG1ldGhvZCkge1xuICAgICAgICBvYmplY3RbbWV0aG9kXSA9IG9iamVjdFttZXRob2RdLmJpbmQob2JqZWN0KTtcbiAgICB9KTtcbn07XG4iLCIvKmpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuLypcbiogICBUaGlzIGNvbnRlbnQgaXMgbGljZW5zZWQgYWNjb3JkaW5nIHRvIHRoZSBXM0MgU29mdHdhcmUgTGljZW5zZSBhdFxuKiAgIGh0dHBzOi8vd3d3LnczLm9yZy9Db25zb3J0aXVtL0xlZ2FsLzIwMTUvY29weXJpZ2h0LXNvZnR3YXJlLWFuZC1kb2N1bWVudFxuKlxuKi9cblxuY2xhc3MgQmx2ZEFjY2Vzc2liaWxpdHlNZW51QnV0dG9uIHtcblxuICAgIGNvbnN0cnVjdG9yKGRvbU5vZGUpIHtcbiAgICAgICAgdGhpcy5kb21Ob2RlID0gZG9tTm9kZTtcbiAgICAgICAgdGhpcy5wb3B1cE1lbnUgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLmhhc0ZvY3VzID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaGFzSG92ZXIgPSBmYWxzZTtcblxuICAgICAgICB0aGlzLmtleUNvZGUgPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgICAgICdUQUInOiA5LFxuICAgICAgICAgICAgJ1JFVFVSTic6IDEzLFxuICAgICAgICAgICAgJ0VTQyc6IDI3LFxuICAgICAgICAgICAgJ1NQQUNFJzogMzIsXG4gICAgICAgICAgICAnUEFHRVVQJzogMzMsXG4gICAgICAgICAgICAnUEFHRURPV04nOiAzNCxcbiAgICAgICAgICAgICdFTkQnOiAzNSxcbiAgICAgICAgICAgICdIT01FJzogMzYsXG4gICAgICAgICAgICAnTEVGVCc6IDM3LFxuICAgICAgICAgICAgJ1VQJzogMzgsXG4gICAgICAgICAgICAnUklHSFQnOiAzOSxcbiAgICAgICAgICAgICdET1dOJzogNDBcbiAgICAgICAgfSk7XG4gICAgfVxuXG59XG5cbkJsdmRBY2Nlc3NpYmlsaXR5TWVudUJ1dHRvbi5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcblxuICAgI
3580HRoaXMuZG9tTm9kZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGFzcG9wdXAnLCAndHJ1ZScpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgICAgdGhpcy5oYW5kbGVLZXlkb3duLmJpbmQodGhpcykpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICAgICAgdGhpcy5oYW5kbGVDbGljay5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCAgICAgIHRoaXMuaGFuZGxlRm9jdXMuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCAgICAgICB0aGlzLmhhbmRsZUJsdXIuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsICB0aGlzLmhhbmRsZU1vdXNlb3Zlci5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCAgIHRoaXMuaGFuZGxlTW91c2VvdXQuYmluZCh0aGlzKSk7XG5cbiAgICAvLyBpbml0aWFsaXplIHBvcCB1cCBtZW51c1xuXG4gICAgY29uc3QgcG9wdXBNZW51ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5kb21Ob2RlLmdldEF0dHJpYnV0ZSgnYXJpYS1jb250cm9scycpKTtcblxuICAgIGlmIChwb3B1cE1lbnUpIHtcbiAgICAgICAgdGhpcy5wb3B1cE1lbnUgPSBuZXcgQmx2ZEFjY2Vzc2liaWxpdHlQb3B1cE1lbnVMaW5rcyhwb3B1cE1lbnUsIHRoaXMpO1xuICAgICAgICB0aGlzLnBvcHVwTWVudS5pbml0KCk7XG4gICAgfVxuXG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eU1lbnVCdXR0b24ucHJvdG90eXBlLmhhbmRsZUtleWRvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBsZXQgZmxhZyA9IGZhbHNlO1xuXG4gICAgc3dpdGNoIChldmVudC5rZXlDb2RlKSB7XG4gICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLlNQQUNFOlxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5SRVRVUk46XG4gICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLkRPV046XG4gICAgICAgICAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBvcHVwTWVudS5vcGVuKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3B1cE1lbnUuc2V0Rm9jdXNUb0ZpcnN0SXRlbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5VUDpcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcHVwTWVudSkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9wdXBNZW51Lm9wZW4oKTtcbiAgICAgICAgICAgICAgICB0aGlzLnBvcHVwTWVudS5zZXRGb2N1c1RvTGFzdEl0ZW0oKTtcbiAgICAgICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoZmxhZykge1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eU1lbnVCdXR0b24ucHJvdG90eXBlLmhhbmRsZUNsaWNrID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMuZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnKSA9PSAndHJ1ZScpIHtcbiAgICAgICAgdGhpcy5wb3B1cE1lbnUuY2xvc2UodHJ1ZSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0aGlzLnBvcHVwTWVudS5vcGVuKCk7XG4gICAgICAgIHRoaXMucG9wdXBNZW51LnNldEZvY3VzVG9GaXJzdEl0ZW0oKTtcbiAgICB9XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eU1lbnVCdXR0b24ucHJvdG90eXBlLmhhbmRsZUZvY3VzID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5wb3B1cE1lbnUuaGFzRm9jdXMgPSB0cnVlO1xufTtcblxuQmx2ZEFjY2Vzc2liaWxpdHlNZW51QnV0dG9uLnByb3RvdHlwZS5oYW5kbGVCbHVyID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5wb3B1cE1lbnUuaGFzRm9jdXMgPSBmYWxzZTtcbn07XG5cbkJsdmRBY2Nlc3NpYmlsaXR5TWVudUJ1dHRvbi5wcm90b3R5cGUuaGFuZGxlTW91c2VvdmVyID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5oYXNIb3ZlciA9IHRydWU7XG4gICAgdGhpcy5wb3B1cE1lbnUub3BlbigpO1xufTtcblxuQmx2ZEFjY2Vzc2liaWxpdHlNZW51QnV0dG9uLnByb3RvdHlwZS5oYW5kbGVNb3VzZW91dCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHRoaXMuaGFzSG92ZXIgPSBmYWxzZTtcbiAgICBzZXRUaW1lb3V0KHRoaXMucG9wdXBNZW51LmNsb3NlLmJpbmQodGhpcy5wb3B1cE1lbnUsIGZhbHNlKSwgMzAwKTtcbn07XG5cbmNsYXNzIEJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3Mge1xuXG4gICAgY29uc3RydWN0b3IoZG9tTm9kZSwgY29udHJvbGxlck9iaikge1xuICAgICAgICBjb25zdCAgbXNnUHJlZml4ID0gJ0JsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MgY29uc3RydWN0b3IgYXJndW1lbnQgZG9tTm9kZSAnO1xuXG4gICAgICAgIC8vIENoZWNrIHdoZXRoZXIgZG9tTm9kZSBpcyBhIERPTSBlbGVtZW50XG4gICAgICAgIGlmICghKGRvbU5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihtc2dQcmVmaXggKyAnaXMgbm90IGEgRE9NIEVsZW1lbnQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayB3aGV0aGVyIGRvbU5vZGUgaGFzIGNoaWxkIGVsZW1lbnRzXG4gICAgICAgIGlmIChkb21Ob2RlLmNoaWxkRWxlbWVudENvdW50ID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnUHJlZml4ICsgJ2hhcyBubyBlbGVtZW50IGNoaWxkcmVuLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgd2hldGhlciBkb21Ob2RlIGRlc2NlbmRhbnQgZWxlbWVudHMgaGF2ZSBBIGVsZW1lbnRzXG4gICAgICAgIGxldCBjaGlsZEVsZW1lbnQgPSBkb21Ob2RlLmZpcnN0RWxlbWVudENoaWxkO1xuICAgICAgICB3aGlsZSAoY2hpbGRFbGVtZW50KSB7XG4gICAgICAgICAgICBjb25zdCBtZW51aXRlbSA9IGNoaWxkRWxlbWVudC5maXJzdEVsZW1lbnRDaGlsZDtcbiAgICAgICAgICAgIGlmIChtZW51aXRlbSAmJiBtZW51aXRlbS50YWdOYW1lICE9PSAnQScpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnUHJlZml4ICsgJ2hhcyBkZXNjZW5kYW50IGVsZW1lbnRzIHRoYXQgYXJlIG5vdCBBIGVsZW1lbnRzLicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2hpbGRFbGVtZW50ID0gY2hpbGRFbGVtZW50Lm5leHRFbGVtZW50U2libGluZztcbiAgICAgICAgfVxuXG4gICAgICAgI
3580HRoaXMuZG9tTm9kZSA9IGRvbU5vZGU7XG4gICAgICAgIHRoaXMuY29udHJvbGxlciA9IGNvbnRyb2xsZXJPYmo7XG5cbiAgICAgICAgdGhpcy5tZW51aXRlbXMgID0gW107ICAgICAgLy8gc2VlIEJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MgaW5pdCBtZXRob2RcbiAgICAgICAgdGhpcy5maXJzdENoYXJzID0gW107ICAgICAgLy8gc2VlIEJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MgaW5pdCBtZXRob2RcblxuICAgICAgICB0aGlzLmZpcnN0SXRlbSAgPSBudWxsOyAgICAvLyBzZWUgQmx2ZEFjY2Vzc2liaWxpdHlQb3B1cE1lbnVMaW5rcyBpbml0IG1ldGhvZFxuICAgICAgICB0aGlzLmxhc3RJdGVtICAgPSBudWxsOyAgICAvLyBzZWUgQmx2ZEFjY2Vzc2liaWxpdHlQb3B1cE1lbnVMaW5rcyBpbml0IG1ldGhvZFxuXG4gICAgICAgIHRoaXMuaGFzRm9jdXMgICA9IGZhbHNlOyAgIC8vIHNlZSBCbHZkQWNjZXNzaWJpbGl0eU1lbnVJdGVtTGlua3MgaGFuZGxlRm9jdXMsIGhhbmRsZUJsdXJcbiAgICAgICAgdGhpcy5oYXNIb3ZlciAgID0gZmFsc2U7ICAgLy8gc2VlIEJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MgaGFuZGxlTW91c2VvdmVyLCBoYW5kbGVNb3VzZW91dFxuICAgIH1cblxuXG59XG5cbkJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgbGV0IGNoaWxkRWxlbWVudCwgbWVudUVsZW1lbnQsIG1lbnVJdGVtLCB0ZXh0Q29udGVudCwgbnVtSXRlbXMsIGxhYmVsO1xuXG4gICAgLy8gQ29uZmlndXJlIHRoZSBkb21Ob2RlIGl0c2VsZlxuICAgIHRoaXMuZG9tTm9kZS50YWJJbmRleCA9IC0xO1xuXG4gICAgdGhpcy5kb21Ob2RlLnNldEF0dHJpYnV0ZSgncm9sZScsICdtZW51Jyk7XG5cbiAgICBpZiAoIXRoaXMuZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWxsZWRieScpICYmICF0aGlzLmRvbU5vZGUuZ2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJykgJiYgIXRoaXMuZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykpIHtcbiAgICAgICAgbGFiZWwgPSB0aGlzLmNvbnRyb2xsZXIuZG9tTm9kZS5pbm5lckhUTUw7XG4gICAgICAgIHRoaXMuZG9tTm9kZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCBsYWJlbCk7XG4gICAgfVxuXG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsIHRoaXMuaGFuZGxlTW91c2VvdmVyLmJpbmQodGhpcykpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsICB0aGlzLmhhbmRsZU1vdXNlb3V0LmJpbmQodGhpcykpO1xuXG4gICAgLy8gVHJhdmVyc2UgdGhlIGVsZW1lbnQgY2hpbGRyZW4gb2YgZG9tTm9kZTogY29uZmlndXJlIGVhY2ggd2l0aFxuICAgIC8vIG1lbnVpdGVtIHJvbGUgYmVoYXZpb3IgYW5kIHN0b3JlIHJlZmVyZW5jZSBpbiBtZW51aXRlbXMgYXJyYXkuXG4gICAgY2hpbGRFbGVtZW50ID0gdGhpcy5kb21Ob2RlLmZpcnN0RWxlbWVudENoaWxkO1xuXG4gICAgd2hpbGUgKGNoaWxkRWxlbWVudCkge1xuICAgICAgICBtZW51RWxlbWVudCA9IGNoaWxkRWxlbWVudC5maXJzdEVsZW1lbnRDaGlsZDtcblxuICAgICAgICBpZiAobWVudUVsZW1lbnQgJiYgbWVudUVsZW1lbnQudGFnTmFtZSA9PT0gJ0EnKSB7XG4gICAgICAgICAgICBtZW51SXRlbSA9IG5ldyBCbHZkQWNjZXNzaWJpbGl0eU1lbnVJdGVtTGlua3MobWVudUVsZW1lbnQsIHRoaXMpO1xuICAgICAgICAgICAgbWVudUl0ZW0uaW5pdCgpO1xuICAgICAgICAgICAgdGhpcy5tZW51aXRlbXMucHVzaChtZW51SXRlbSk7XG4gICAgICAgICAgICB0ZXh0Q29udGVudCA9IG1lbnVFbGVtZW50LnRleHRDb250ZW50LnRyaW0oKTtcbiAgICAgICAgICAgIHRoaXMuZmlyc3RDaGFycy5wdXNoKHRleHRDb250ZW50LnN1YnN0cmluZygwLCAxKS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgfVxuICAgICAgICBjaGlsZEVsZW1lbnQgPSBjaGlsZEVsZW1lbnQubmV4dEVsZW1lbnRTaWJsaW5nO1xuICAgIH1cblxuICAgIC8vIFVzZSBwb3B1bGF0ZWQgbWVudWl0ZW1zIGFycmF5IHRvIGluaXRpYWxpemUgZmlyc3RJdGVtIGFuZCBsYXN0SXRlbS5cbiAgICBudW1JdGVtcyA9IHRoaXMubWVudWl0ZW1zLmxlbmd0aDtcbiAgICBpZiAobnVtSXRlbXMgPiAwKSB7XG4gICAgICAgIHRoaXMuZmlyc3RJdGVtID0gdGhpcy5tZW51aXRlbXNbMF07XG4gICAgICAgIHRoaXMubGFzdEl0ZW0gID0gdGhpcy5tZW51aXRlbXNbbnVtSXRlbXMgLSAxXTtcbiAgICB9XG59O1xuXG4vKiBFVkVOVCBIQU5ETEVSUyAqL1xuXG5CbHZkQWNjZXNzaWJpbGl0eVBvcHVwTWVudUxpbmtzLnByb3RvdHlwZS5oYW5kbGVNb3VzZW92ZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLmhhc0hvdmVyID0gdHJ1ZTtcbn07XG5cbkJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MucHJvdG90eXBlLmhhbmRsZU1vdXNlb3V0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5oYXNIb3ZlciA9IGZhbHNlO1xuICAgIHNldFRpbWVvdXQodGhpcy5jbG9zZS5iaW5kKHRoaXMsIGZhbHNlKSwgMzAwKTtcbn07XG5cbi8qIEZPQ1VTIE1BTkFHRU1FTlQgTUVUSE9EUyAqL1xuXG5CbHZkQWNjZXNzaWJpbGl0eVBvcHVwTWVudUxpbmtzLnByb3RvdHlwZS5zZXRGb2N1c1RvQ29udHJvbGxlciA9IGZ1bmN0aW9uIChjb21tYW5kKSB7XG4gICAgaWYgKHR5cGVvZiBjb21tYW5kICE9PSAnc3RyaW5nJykge1xuICAgICAgICBjb21tYW5kID0gJyc7XG4gICAgfVxuXG4gICAgaWYgKGNvbW1hbmQgPT09ICdwcmV2aW91cycpIHtcbiAgICAgICAgdGhpcy5jb250cm9sbGVyLm1lbnViYXIuc2V0Rm9jdXNUb1ByZXZpb3VzSXRlbSh0aGlzLmNvbnRyb2xsZXIpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYgKGNvbW1hbmQgPT09ICduZXh0Jykge1xuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyLm1lbnViYXIuc2V0Rm9jdXNUb05leHRJdGVtKHRoaXMuY29udHJvbGxlcik7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZG9tTm9kZS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuQmx2ZEFjY2Vzc2liaWxpdHlQb3B1cE1lbnVMaW5rcy5wcm90b3R5cGUuc2V0Rm9jdXNUb0ZpcnN0SXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZpcnN0SXRlbS5kb21Ob2RlLmZvY3VzKCk7XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eVBvcHVwTWVudUxpbmtzLnByb3RvdHlwZS5zZXRGb2N1c1RvTGFzdEl0ZW0gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5sYXN0SXRlbS5kb21Ob2RlLmZvY3VzKCk7XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eVBvcHVwTWVudUxpbmtzLnByb3RvdHlwZS5zZXRGb2N1c1RvUHJldmlvdXNJdGVtID0gZnVuY3Rpb24gKGN1cnJlbnRJdGVtKSB7XG4gICAgbGV0IGluZGV4O1xuXG4gICAgaWYgKGN1cnJlbnRJdGVtID09PSB0aGlzLmZpcnN0SXRlbSkge1xuICAgICAgICB0aGlzLmxhc3RJdGVtLmRvbU5vZGUuZm9jdXMoKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGluZGV4ID0gdGhpcy5tZW51aXRlbXMuaW5kZXhPZihjdXJyZW50SXRlbSk7XG4gICAgICAgI
3580HRoaXMubWVudWl0ZW1zW2luZGV4IC0gMV0uZG9tTm9kZS5mb2N1cygpO1xuICAgIH1cbn07XG5cbkJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MucHJvdG90eXBlLnNldEZvY3VzVG9OZXh0SXRlbSA9IGZ1bmN0aW9uIChjdXJyZW50SXRlbSkge1xuICAgIGxldCBpbmRleDtcblxuICAgIGlmIChjdXJyZW50SXRlbSA9PT0gdGhpcy5sYXN0SXRlbSkge1xuICAgICAgICB0aGlzLmZpcnN0SXRlbS5kb21Ob2RlLmZvY3VzKCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpbmRleCA9IHRoaXMubWVudWl0ZW1zLmluZGV4T2YoY3VycmVudEl0ZW0pO1xuICAgICAgICB0aGlzLm1lbnVpdGVtc1tpbmRleCArIDFdLmRvbU5vZGUuZm9jdXMoKTtcbiAgICB9XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eVBvcHVwTWVudUxpbmtzLnByb3RvdHlwZS5zZXRGb2N1c0J5Rmlyc3RDaGFyYWN0ZXIgPSBmdW5jdGlvbiAoY3VycmVudEl0ZW0sIGNoYXIpIHtcbiAgICBsZXQgc3RhcnQsIGluZGV4O1xuICAgIGNoYXIgPSBjaGFyLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBHZXQgc3RhcnQgaW5kZXggZm9yIHNlYXJjaCBiYXNlZCBvbiBwb3NpdGlvbiBvZiBjdXJyZW50SXRlbVxuICAgIHN0YXJ0ID0gdGhpcy5tZW51aXRlbXMuaW5kZXhPZihjdXJyZW50SXRlbSkgKyAxO1xuICAgIGlmIChzdGFydCA9PT0gdGhpcy5tZW51aXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDaGVjayByZW1haW5pbmcgc2xvdHMgaW4gdGhlIG1lbnVcbiAgICBpbmRleCA9IHRoaXMuZ2V0SW5kZXhGaXJzdENoYXJzKHN0YXJ0LCBjaGFyKTtcblxuICAgIC8vIElmIG5vdCBmb3VuZCBpbiByZW1haW5pbmcgc2xvdHMsIGNoZWNrIGZyb20gYmVnaW5uaW5nXG4gICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICBpbmRleCA9IHRoaXMuZ2V0SW5kZXhGaXJzdENoYXJzKDAsIGNoYXIpO1xuICAgIH1cblxuICAgIC8vIElmIG1hdGNoIHdhcyBmb3VuZC4uLlxuICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgIHRoaXMubWVudWl0ZW1zW2luZGV4XS5kb21Ob2RlLmZvY3VzKCk7XG4gICAgfVxufTtcblxuQmx2ZEFjY2Vzc2liaWxpdHlQb3B1cE1lbnVMaW5rcy5wcm90b3R5cGUuZ2V0SW5kZXhGaXJzdENoYXJzID0gZnVuY3Rpb24gKHN0YXJ0SW5kZXgsIGNoYXIpIHtcbiAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleDsgaSA8IHRoaXMuZmlyc3RDaGFycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoY2hhciA9PT0gdGhpcy5maXJzdENoYXJzW2ldKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG59O1xuXG4vKiBNRU5VIERJU1BMQVkgTUVUSE9EUyAqL1xuXG5CbHZkQWNjZXNzaWJpbGl0eVBvcHVwTWVudUxpbmtzLnByb3RvdHlwZS5vcGVuID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIGdldCBwb3NpdGlvbiBhbmQgYm91bmRpbmcgcmVjdGFuZ2xlIG9mIGNvbnRyb2xsZXIgb2JqZWN0J3MgRE9NIG5vZGVcbiAgICBjb25zdCByZWN0ID0gdGhpcy5jb250cm9sbGVyLmRvbU5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAvLyBzZXQgQ1NTIHByb3BlcnRpZXNcbiAgICB0aGlzLmRvbU5vZGUuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgdGhpcy5kb21Ob2RlLnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICB0aGlzLmRvbU5vZGUuc3R5bGUudG9wICA9IHJlY3QuaGVpZ2h0ICsgJ3B4JztcbiAgICB0aGlzLmRvbU5vZGUuc3R5bGUubGVmdCA9ICcwcHgnO1xuXG4gICAgLy8gc2V0IGFyaWEtZXhwYW5kZWQgYXR0cmlidXRlXG4gICAgdGhpcy5jb250cm9sbGVyLmRvbU5vZGUuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ3RydWUnKTtcbn07XG5cbkJsdmRBY2Nlc3NpYmlsaXR5UG9wdXBNZW51TGlua3MucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKGZvcmNlKSB7XG5cbiAgICBpZiAoZm9yY2UgfHwgKCF0aGlzLmhhc0ZvY3VzICYmICF0aGlzLmhhc0hvdmVyICYmICF0aGlzLmNvbnRyb2xsZXIuaGFzSG92ZXIpKSB7XG4gICAgICAgIHRoaXMuZG9tTm9kZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZG9tTm9kZS5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnKTtcbiAgICB9XG59O1xuXG5cbmNsYXNzIEJsdmRBY2Nlc3NpYmlsaXR5TWVudUl0ZW1MaW5rcyB7XG5cbiAgICBjb25zdHJ1Y3Rvcihkb21Ob2RlLCBtZW51T2JqKSB7XG4gICAgICAgIHRoaXMuZG9tTm9kZSA9IGRvbU5vZGU7XG4gICAgICAgIHRoaXMubWVudSA9IG1lbnVPYmo7XG5cbiAgICAgICAgdGhpcy5rZXlDb2RlID0gT2JqZWN0LmZyZWV6ZSh7XG4gICAgICAgICAgICAnVEFCJzogOSxcbiAgICAgICAgICAgICdSRVRVUk4nOiAxMyxcbiAgICAgICAgICAgICdFU0MnOiAyNyxcbiAgICAgICAgICAgICdTUEFDRSc6IDMyLFxuICAgICAgICAgICAgJ1BBR0VVUCc6IDMzLFxuICAgICAgICAgICAgJ1BBR0VET1dOJzogMzQsXG4gICAgICAgICAgICAnRU5EJzogMzUsXG4gICAgICAgICAgICAnSE9NRSc6IDM2LFxuICAgICAgICAgICAgJ0xFRlQnOiAzNyxcbiAgICAgICAgICAgICdVUCc6IDM4LFxuICAgICAgICAgICAgJ1JJR0hUJzogMzksXG4gICAgICAgICAgICAnRE9XTic6IDQwXG4gICAgICAgIH0pO1xuICAgIH1cbn1cblxuQmx2ZEFjY2Vzc2liaWxpdHlNZW51SXRlbUxpbmtzLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZG9tTm9kZS50YWJJbmRleCA9IC0xO1xuXG4gICAgaWYgKCF0aGlzLmRvbU5vZGUuZ2V0QXR0cmlidXRlKCdyb2xlJykpIHtcbiAgICAgICAgdGhpcy5kb21Ob2RlLnNldEF0dHJpYnV0ZSgncm9sZScsICdtZW51aXRlbScpO1xuICAgIH1cblxuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgICAgdGhpcy5oYW5kbGVLZXlkb3duLmJpbmQodGhpcykpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICAgICAgdGhpcy5oYW5kbGVDbGljay5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCAgICAgI
3580HRoaXMuaGFuZGxlRm9jdXMuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCAgICAgICB0aGlzLmhhbmRsZUJsdXIuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsICB0aGlzLmhhbmRsZU1vdXNlb3Zlci5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCAgIHRoaXMuaGFuZGxlTW91c2VvdXQuYmluZCh0aGlzKSk7XG5cbn07XG5cbi8qIEVWRU5UIEhBTkRMRVJTICovXG5cbkJsdmRBY2Nlc3NpYmlsaXR5TWVudUl0ZW1MaW5rcy5wcm90b3R5cGUuaGFuZGxlS2V5ZG93biA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIGxldCBmbGFnID0gZmFsc2UsXG4gICAgY2hhciA9IGV2ZW50LmtleTtcblxuICAgIGZ1bmN0aW9uIGlzUHJpbnRhYmxlQ2hhcmFjdGVyIChzdHIpIHtcbiAgICAgICAgcmV0dXJuIHN0ci5sZW5ndGggPT09IDEgJiYgc3RyLm1hdGNoKC9cXFMvKTtcbiAgICB9XG5cbiAgICBpZiAoZXZlbnQuY3RybEtleSB8fCBldmVudC5hbHRLZXkgIHx8IGV2ZW50Lm1ldGFLZXkgfHwgKGV2ZW50LmtleUNvZGUgPT09IHRoaXMua2V5Q29kZS5TUEFDRSkgfHwgKGV2ZW50LmtleUNvZGUgPT09IHRoaXMua2V5Q29kZS5SRVRVUk4pKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZXZlbnQuc2hpZnRLZXkpIHtcbiAgICAgICAgaWYgKGlzUHJpbnRhYmxlQ2hhcmFjdGVyKGNoYXIpKSB7XG4gICAgICAgICAgICB0aGlzLm1lbnUuc2V0Rm9jdXNCeUZpcnN0Q2hhcmFjdGVyKHRoaXMsIGNoYXIpO1xuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gdGhpcy5rZXlDb2RlLlRBQikge1xuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9Db250cm9sbGVyKCk7XG4gICAgICAgICAgICB0aGlzLm1lbnUuY2xvc2UodHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHN3aXRjaCAoZXZlbnQua2V5Q29kZSkge1xuXG4gICAgICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5FU0M6XG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9Db250cm9sbGVyKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LmNsb3NlKHRydWUpO1xuICAgICAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5VUDpcbiAgICAgICAgICAgICAgICB0aGlzLm1lbnUuc2V0Rm9jdXNUb1ByZXZpb3VzSXRlbSh0aGlzKTtcbiAgICAgICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuRE9XTjpcbiAgICAgICAgICAgICAgICB0aGlzLm1lbnUuc2V0Rm9jdXNUb05leHRJdGVtKHRoaXMpO1xuICAgICAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5IT01FOlxuICAgICAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuUEFHRVVQOlxuICAgICAgICAgICAgICAgIHRoaXMubWVudS5zZXRGb2N1c1RvRmlyc3RJdGVtKCk7XG4gICAgICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLkVORDpcbiAgICAgICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLlBBR0VET1dOOlxuICAgICAgICAgICAgICAgIHRoaXMubWVudS5zZXRGb2N1c1RvTGFzdEl0ZW0oKTtcbiAgICAgICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuVEFCOlxuICAgICAgICAgICAgICAgIHRoaXMubWVudS5zZXRGb2N1c1RvQ29udHJvbGxlcigpO1xuICAgICAgICAgICAgICAgIHRoaXMubWVudS5jbG9zZSh0cnVlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBpZiAoaXNQcmludGFibGVDaGFyYWN0ZXIoY2hhcikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzQnlGaXJzdENoYXJhY3Rlcih0aGlzLCBjaGFyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZmxhZykge1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eU1lbnVJdGVtTGlua3MucHJvdG90eXBlLmhhbmRsZUNsaWNrID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5tZW51LnNldEZvY3VzVG9Db250cm9sbGVyKCk7XG4gICAgdGhpcy5tZW51LmNsb3NlKHRydWUpO1xufTtcblxuQmx2ZEFjY2Vzc2liaWxpdHlNZW51SXRlbUxpbmtzLnByb3RvdHlwZS5oYW5kbGVGb2N1cyA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHRoaXMubWVudS5
3580oYXNGb2N1cyA9IHRydWU7XG59O1xuXG5CbHZkQWNjZXNzaWJpbGl0eU1lbnVJdGVtTGlua3MucHJvdG90eXBlLmhhbmRsZUJsdXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzRm9jdXMgPSBmYWxzZTtcbiAgICBzZXRUaW1lb3V0KHRoaXMubWVudS5jbG9zZS5iaW5kKHRoaXMubWVudSwgZmFsc2UpLCAzMDApO1xufTtcblxuQmx2ZEFjY2Vzc2liaWxpdHlNZW51SXRlbUxpbmtzLnByb3RvdHlwZS5oYW5kbGVNb3VzZW92ZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzSG92ZXIgPSB0cnVlO1xuICAgIHRoaXMubWVudS5vcGVuKCk7XG5cbn07XG5cbkJsdmRBY2Nlc3NpYmlsaXR5TWVudUl0ZW1MaW5rcy5wcm90b3R5cGUuaGFuZGxlTW91c2VvdXQgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzSG92ZXIgPSBmYWxzZTtcbiAgICBzZXRUaW1lb3V0KHRoaXMubWVudS5jbG9zZS5iaW5kKHRoaXMubWVudSwgZmFsc2UpLCAzMDApO1xufTtcbiIsImxldCBsaXN0aW5nQ2FyZHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbZGF0YS1jYXJkXScpO1xuY29uc3Qga2V5c0NvZGUgPSBPYmplY3QuZnJlZXplKHtcbiAgJ1RBQic6IDksXG4gICdSRVRVUk4nOiAxMyxcbiAgJ0VTQyc6IDI3LFxuICAnU1BBQ0UnOiAzMixcbiAgJ1BBR0VVUCc6IDMzLFxuICAnUEFHRURPV04nOiAzNCxcbiAgJ0VORCc6IDM1LFxuICAnSE9NRSc6IDM2LFxuICAnTEVGVCc6IDM3LFxuICAnVVAnOiAzOCxcbiAgJ1JJR0hUJzogMzksXG4gICdET1dOJzogNDBcbn0pO1xuXG5saXN0aW5nQ2FyZHMuZm9yRWFjaCgobGlzdGluZ0NhcmQsIGluZGV4LCBhcnIpID0+IHtcbiAgbGV0IHRpdGxlID0gbGlzdGluZ0NhcmQucXVlcnlTZWxlY3RvcignLmxpc3RpbmctdGl0bGUtLWxpbmsnKSxcbiAgICAgIGZhdm9yaXRlID0gbGlzdGluZ0NhcmQucXVlcnlTZWxlY3RvcignLmZhdm9yaXRlLXRvZ2dsZS13cmFwJyksXG4gICAgICBwcmV2aW91c0Zhdm9yaXRlLFxuICAgICAgaXNTaGlmdFxuICA7XG5cbiAgaWYgKHRpdGxlICYmIGZhdm9yaXRlKSB7XG4gICAgdGl0bGUuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIGlzU2hpZnQgPSAhIWV2ZW50LnNoaWZ0S2V5O1xuXG4gICAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0ga2V5c0NvZGUuVEFCICYmIGlzU2hpZnQpIHtcbiAgICAgICAgaWYgKChpbmRleCAtIDEpID49IDApIHtcbiAgICAgICAgICBwcmV2aW91c0Zhdm9yaXRlID0gYXJyW2luZGV4IC0gMV0ucXVlcnlTZWxlY3RvcignLmZhdm9yaXRlLXRvZ2dsZS13cmFwJyk7XG4gICAgICAgICAgcHJldmlvdXNGYXZvcml0ZS5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgMCk7XG5cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChldmVudC5rZXlDb2RlID09PSBrZXlzQ29kZS5UQUIpIHtcbiAgICAgICAgZmF2b3JpdGUuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICcwJyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBpZiAoZmF2b3JpdGUpIHtcbiAgICBmYXZvcml0ZS5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgZnVuY3Rpb24oZSkge1xuICAgICAgdGhpcy5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJy0xJyk7XG4gICAgfSk7XG4gIH1cbn0pO1xuXG4iLCJqUXVlcnkoZnVuY3Rpb24oJCkge1xuXG4gICAgbGV0IG1vZGFsQ2FsbGVyO1xuXG4gICAgJCgnW2RhdGEtaW5pdD1cImNvbG9yYm94XCJdLCAuY2JveEVsZW1lbnQnKS5vbignY2xpY2snLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICBtb2RhbENhbGxlciA9IGV2ZW50LnRhcmdldDtcbn0pO1xuXG4gICAgJChkb2N1bWVudCkuYmluZCgnY2JveF9jb21wbGV0ZScsIGZ1bmN0aW9uKCl7XG4gICAgICAgIHdpbmRvdy5tb2RhbCA9ICQoJyNjb2xvcmJveCcpO1xuICAgICAgICB3aW5kb3cubW9kYWxJZCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICB3aW5kb3cubW9kYWwuYXR0cignZGF0YS1tb2RhbC1pZCcsIHdpbmRvdy5tb2RhbElkKTtcblxuICAgICAgICBsZXQgJHBhcmVudCA9IHdpbmRvdy5tb2RhbDtcbiAgICAgICAgY29uc3QgZXhjbHVzZVRhZ05hbWVzID0gW1xuICAgICAgICAgICAgJ3NjcmlwdCcsXG4gICAgICAgICAgICAnc3R5bGUnLFxuICAgICAgICAgICAgJ25vc2NyaXB0J1xuICAgICAgICBdO1xuXG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIGxldCAkc2libGluZ3MgPSAkcGFyZW50LnNpYmxpbmdzKCk7XG5cbiAgICAgICAgICAgIGlmICgkc2libGluZ3MubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICRzaWJsaW5ncy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhjbHVzZVRhZ05hbWVzLmluY2x1ZGVzKGVsZW0udGFnTmFtZS50b0xvd2VyQ2FzZSgpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW0uaGFzQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXJoaWRlJywgZWxlbS5nZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCAndHJ1ZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICRwYXJlbnQgPSAkcGFyZW50LnBhcmVudCgpO1xuXG4gICAgICAgIH0gIHdoaWxlICgkcGFyZW50WzBdLnRhZ05hbWUudG9Mb3dlckNhc2UoKSAhPT0gJ2JvZHknKVxuXG4gICAgICAgIHdpbmRvdy5zZXRGb2N1c0luTW9kYWxXaW5kb3coKTtcbiAgICB9KVxuICAgICAgICAuYmluZCgnY2JveF9jbG9zZWQgJywgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBtb2RhbENhbGxlci5mb2N1cygpO1xuICAgICAgICAgICAgd2luZG93Lm1vZGFsID0gbnVsbDtcbiAgICAgICAgICAgI
3580HdpbmRvdy5mb2N1c2FibGVDb250ZW50ID0gbnVsbDtcblxuICAgICAgICAgICAgbGV0ICRlbGVtcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ1thcmlhLWhpZGRlbj1cInRydWVcIl0nKTtcblxuICAgICAgICAgICAgZm9yIChsZXQgZWxlbSBvZiAkZWxlbXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbS5oYXNBdHRyaWJ1dGUoJ2RhdGEtYXJoaWRlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgZWxlbS5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgZWxlbS5nZXRBdHRyaWJ1dGUoJ2RhdGEtYXJoaWRlJykpO1xuICAgICAgICAgICAgICAgICAgICBlbGVtLnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1hcmhpZGUnKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlbGVtLnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgO1xufSk7XG4iLCIvKlxuKiAgIFRoaXMgY29udGVudCBpcyBsaWNlbnNlZCBhY2NvcmRpbmcgdG8gdGhlIFczQyBTb2Z0d2FyZSBMaWNlbnNlIGF0XG4qICAgaHR0cHM6Ly93d3cudzMub3JnL0NvbnNvcnRpdW0vTGVnYWwvMjAxNS9jb3B5cmlnaHQtc29mdHdhcmUtYW5kLWRvY3VtZW50XG4qL1xuXG4vKipcbiAqIEBuYW1lc3BhY2UgYXJpYVxuICovXG52YXIgYXJpYSA9IGFyaWEgfHwge307XG5cbi8qKlxuICogQGRlc2NcbiAqICBWYWx1ZXMgZm9yIGFyaWEtc29ydFxuICovXG5hcmlhLlNvcnRUeXBlID0ge1xuICAgIEFTQ0VORElORzogJ2FzY2VuZGluZycsXG4gICAgREVTQ0VORElORzogJ2Rlc2NlbmRpbmcnLFxuICAgIE5PTkU6ICdub25lJ1xufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIERPTSBTZWxlY3RvcnMgdG8gZmluZCB0aGUgZ3JpZCBjb21wb25lbnRzXG4gKi9cbmFyaWEuR3JpZFNlbGVjdG9yID0ge1xuICAgIFJPVzogJ3RyLCBbcm9sZT1cInJvd1wiXScsXG4gICAgQ0VMTDogJ3RoLCB0ZCwgW3JvbGU9XCJncmlkY2VsbFwiXScsXG4gICAgU0NST0xMX1JPVzogJ3RyOm5vdChbZGF0YS1maXhlZF0pLCBbcm9sZT1cInJvd1wiXScsXG4gICAgU09SVF9IRUFERVI6ICd0aFthcmlhLXNvcnRdJyxcbiAgICBUQUJCQUJMRTogJ1t0YWJpbmRleD1cIjBcIl0nXG59O1xuXG4vKipcbiAqIEBkZXNjXG4gKiAgQ1NTIENsYXNzIG5hbWVzXG4gKi9cbmFyaWEuQ1NTQ2xhc3MgPSB7XG4gICAgSElEREVOOiAnaGlkZGVuJ1xufTtcblxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqXG4gKiBAZGVzY1xuICogIEdyaWQgb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgc3RhdGUgYW5kIGludGVyYWN0aW9ucyBmb3IgYSBncmlkIHdpZGdldFxuICpcbiAqICBBc3N1bXB0aW9uczpcbiAqICBBbGwgZm9jdXNhYmxlIGNlbGxzIGluaXRpYWxseSBoYXZlIHRhYmluZGV4PVwiLTFcIlxuICogIFByb2R1Y2VzIGEgZnVsbHkgZmlsbGVkIGluIG14biBncmlkICh3aXRoIG5vIGhvbGVzKVxuICpcbiAqIEBwYXJhbSBncmlkTm9kZVxuICogIFRoZSBET00gbm9kZSBwb2ludGluZyB0byB0aGUgZ3JpZFxuICovXG5hcmlhLkdyaWQgPSBmdW5jdGlvbiAoZ3JpZE5vZGUpIHtcbiAgICB0aGlzLm5hdmlnYXRpb25EaXNhYmxlZCA9IGZhbHNlO1xuICAgIHRoaXMuZ3JpZE5vZGUgPSBncmlkTm9kZTtcbiAgICB0aGlzLnBhZ2luYXRpb25FbmFibGVkID0gZmFsc2U7IC8vdGhpcy5ncmlkTm9kZS5oYXNBdHRyaWJ1dGUoJ2RhdGEtcGVyLXBhZ2UnKTtcbiAgICB0aGlzLnNob3VsZFdyYXBDb2xzID0gbnVsbDsgLy90aGlzLmdyaWROb2RlLmhhc0F0dHJpYnV0ZSgnZGF0YS13cmFwLWNvbHMnKTtcbiAgICB0aGlzLnNob3VsZFdyYXBSb3dzID0gbnVsbDsgLy90aGlzLmdyaWROb2RlLmhhc0F0dHJpYnV0ZSgnZGF0YS13cmFwLXJvd3MnKTtcbiAgICB0aGlzLnNob3VsZFJlc3RydWN0dXJlID0gbnVsbDsgLy90aGlzLmdyaWROb2RlLmhhc0F0dHJpYnV0ZSgnZGF0YS1yZXN0cnVjdHVyZScpO1xuICAgIHRoaXMudG9wSW5kZXggPSAwO1xuXG4gICAgdGhpcy5rZXlzSW5kaWNhdG9yID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2Fycm93LWtleXMtaW5kaWNhdG9yJyk7XG5cbiAgICBhcmlhLlV0aWxzLmJpbmRNZXRob2RzKHRoaXMsXG4gICAgICAgICdjaGVja0ZvY3VzQ2hhbmdlJywgJ2NoZWNrUGFnZUNoYW5nZScsICdjaGVja1Jlc3RydWN0dXJlR3JpZCcsXG4gICAgICAgICdkZWxlZ2F0ZUJ1dHRvbkhhbmRsZXInLCAnZm9jdXNDbGlja2VkQ2VsbCcsICdyZXN0cnVjdHVyZUdyaWQnLFxuICAgICAgICAnc2hvd0tleXNJbmRpY2F0b3InLCAnaGlkZUtleXNJbmRpY2F0b3InKTtcbiAgICB0aGlzLnNldHVwRm9jdXNHcmlkKCk7XG4gICAgdGhpcy5zZXRGb2N1c1BvaW50ZXIoMCwgMCk7XG5cbiAgICBpZiAodGhpcy5wYWdpbmF0aW9uRW5hYmxlZCkge1xuICAgICAgICB0aGlzLnNldHVwUGFnaW5hdGlvbigpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5wZXJQYWdlID0gdGhpcy5ncmlkLmxlbmd0aDtcbiAgICB9XG5cbiAgICB0aGlzLnJlZ2lzdGVyRXZlbnRzKCk7XG59O1xuXG4vKipcbiAqIEBkZXNjXG4gKiAgQ3JlYXRlcyBhIDJEIGFycmF5IG9mIHRoZSBmb2N1c2FibGUgY2VsbHMgaW4gdGhlIGdyaWQuXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuc2V0dXBGb2N1c0dyaWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5ncmlkID0gW107XG4gICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbChcbiAgICAgICAgdGhpcy5ncmlkTm9kZS5xdWVyeVNlbGVjdG9yQWxsKGFyaWEuR3JpZFNlbGVjdG9yLlJPVyksXG4gICAgICAgIChmdW5jdGlvbiAocm93KSB7XG4gICAgICAgICAgICB2Y
3580XIgcm93Q2VsbHMgPSBbXTtcblxuICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbChcbiAgICAgICAgICAgICAgICByb3cucXVlcnlTZWxlY3RvckFsbChhcmlhLkdyaWRTZWxlY3Rvci5DRUxMKSxcbiAgICAgICAgICAgICAgICAoZnVuY3Rpb24gKGNlbGwpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZvY3VzYWJsZVNlbGVjdG9yID0gJ1t0YWJpbmRleF0nO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmlhLlV0aWxzLm1hdGNoZXMoY2VsbCwgZm9jdXNhYmxlU2VsZWN0b3IpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb3dDZWxscy5wdXNoKGNlbGwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGZvY3VzYWJsZUNlbGwgPSBjZWxsLnF1ZXJ5U2VsZWN0b3IoZm9jdXNhYmxlU2VsZWN0b3IpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9jdXNhYmxlQ2VsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd0NlbGxzLnB1c2goZm9jdXNhYmxlQ2VsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KS5iaW5kKHRoaXMpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBpZiAocm93Q2VsbHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ncmlkLnB1c2gocm93Q2VsbHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpXG4gICAgKTtcblxuICAgIGlmICh0aGlzLnBhZ2luYXRpb25FbmFibGVkKSB7XG4gICAgICAgIHRoaXMuc2V0dXBJbmRpY2VzKCk7XG4gICAgfVxufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIElmIHBvc3NpYmxlLCBzZXQgZm9jdXMgcG9pbnRlciB0byB0aGUgY2VsbCB3aXRoIHRoZSBzcGVjaWZpZWQgY29vcmRpbmF0ZXNcbiAqXG4gKiBAcGFyYW0gcm93XG4gKiAgVGhlIGluZGV4IG9mIHRoZSBjZWxsJ3Mgcm93XG4gKlxuICogQHBhcmFtIGNvbFxuICogIFRoZSBpbmRleCBvZiB0aGUgY2VsbCdzIGNvbHVtblxuICpcbiAqIEByZXR1cm5zXG4gKiAgUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgZm9jdXMgY291bGQgYmUgc2V0IG9uIHRoZSBjZWxsLlxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLnNldEZvY3VzUG9pbnRlciA9IGZ1bmN0aW9uIChyb3csIGNvbCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkQ2VsbChyb3csIGNvbCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmlzSGlkZGVuKHJvdywgY29sKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKCFpc05hTih0aGlzLmZvY3VzZWRSb3cpICYmICFpc05hTih0aGlzLmZvY3VzZWRDb2wpKSB7XG4gICAgICAgIHRoaXMuZ3JpZFt0aGlzLmZvY3VzZWRSb3ddW3RoaXMuZm9jdXNlZENvbF0uc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIC0xKTtcbiAgICB9XG5cbiAgICB0aGlzLmdyaWRbcm93XVtjb2xdXG4gICAgICAgIC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuc2hvd0tleXNJbmRpY2F0b3IpO1xuICAgIHRoaXMuZ3JpZFtyb3ddW2NvbF1cbiAgICAgICAgLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLmhpZGVLZXlzSW5kaWNhdG9yKTtcblxuICAgIC8vIERpc2FibGUgbmF2aWdhdGlvbiBpZiBmb2N1c2VkIG9uIGFuIGlucHV0XG4gICAgdGhpcy5uYXZpZ2F0aW9uRGlzYWJsZWQgPSBhcmlhLlV0aWxzLm1hdGNoZXModGhpcy5ncmlkW3Jvd11bY29sXSwgJ2lucHV0Jyk7XG5cbiAgICB0aGlzLmdyaWRbcm93XVtjb2xdLnNldEF0dHJpYnV0ZSgndGFiaW5kZXgnLCAwKTtcbiAgICB0aGlzLmZvY3VzZWRSb3cgPSByb3c7XG4gICAgdGhpcy5mb2N1c2VkQ29sID0gY29sO1xuXG4gICAgdGhpcy5ncmlkW3Jvd11bY29sXVxuICAgICAgICAuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLnNob3dLZXlzSW5kaWNhdG9yKTtcbiAgICB0aGlzLmdyaWRbcm93XVtjb2xdXG4gICAgICAgIC5hZGRFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5oaWRlS2V5c0luZGljYXRvcik7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHJvd1xuICogIFRoZSBpbmRleCBvZiB0aGUgY2VsbCdzIHJvd1xuICpcbiAqIEBwYXJhbSBjb2xcbiAqICBUaGUgaW5kZXggb2YgdGhlIGNlbGwncyBjb2x1bW5cbiAqXG4gKiBAcmV0dXJuc1xuICogIFJldHVybnMgd2hldGhlciBvciBub3QgdGhlIGNvb3JkaW5hdGVzIGFyZSB3aXRoaW4gdGhlIGdyaWQncyBib3VuZGFyaWVzLlxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLmlzVmFsaWRDZWxsID0gZnVuY3Rpb24gKHJvdywgY29sKSB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgIWlzTmFOKHJvdykgJiZcbiAgICAgICAgIWlzTmFOKGNvbCkgJiZcbiAgICAgICAgcm93ID49IDAgJiZcbiAgICAgICAgY29sID49IDAgJiZcbiAgICAgICAgdGhpcy5ncmlkICYmXG4gICAgICAgIHRoaXMuZ3JpZC5sZW5ndGggJiZcbiAgICAgICAgcm93IDwgdGhpcy5ncmlkLmxlbmd0aCAmJlxuICAgICAgICBjb2wgPCB0aGlzLmdyaWRbcm93XS5sZW5ndGhcbiAgICApO1xufTtcblxuLyoqXG4gKiBAcGFyYW0gcm93XG4gKiAgVGhlIGluZGV4IG9mIHRoZSBjZWxsJ3Mgcm93XG4gKlxuICogQHBhcmFtIGNvbFxuICogIFRoZSBpbmRleCBvZiB0aGUgY2VsbCdzIGNvbHVtblxuICpcbiAqIEByZXR1cm5zXG4gKiAgUmV0dXJucyB3aGV0aGVyIG9yIG5vdCB0aGUgY2VsbCBoYXMgYmVlbiBoaWRkZW4uXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuaXNIaWRkZW4gPSBmdW5jdGlvbiAocm93LCBjb2wpIHtcbiAgICB2YXIgY2VsbCA9IHRoaXMuZ3JpZE5vZGUucXVlcnlTZWxlY3RvckFsbChhcmlhLkdyaWRTZWxlY3Rvci5ST1cpW3Jvd11cbiAgICAgICAgLnF1ZXJ5U2VsZWN0b3JBbGwoYXJpYS5HcmlkU2VsZWN0b3IuQ0VMTClbY29sXTtcbiAgICByZXR1cm4gYXJpYS5VdGlscy5oYXNDbGFzcyhjZWxsLCBhcmlhLkNTU0NsYXNzLkhJRERFTik7XG59O1xuXG4vKipcbiAqIEBkZXNjXG4gKiAgQ2xlYW4gdXAgZ3JpZCBldmVudHNcbiAqL1xuYXJpYS5HcmlkLnByb3RvdHlwZS5jbGVhckV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmdyaWROb2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmNoZWNrRm9jdXNDaGFuZ2UpO1xuICAgIHRoaXMuZ3JpZE5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuZGVsZWdhdGVCdXR0b25IYW5kbGVyKTtcbiAgICB0aGlzLmdyaWROb2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5mb2N1c0NsaWNrZWRDZWxsKTtcbiAgICB0aGlzLmdyaWROb2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5kZWxlZ2F0ZUJ1dHRvbkhhbmRsZXIpO1xuXG4gICAgaWYgKHRoaXMucGFnaW5hdGlvbkVuYWJsZWQpIHtcbiAgICAgICAgdGhpcy5ncmlkTm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5jaGVja1BhZ2VDaGFuZ2UpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNob3VsZFJlc3RydWN0dXJlKSB7XG4gICAgICAgI
3580HdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdyZXNpemUnLCB0aGlzLmNoZWNrUmVzdHJ1Y3R1cmVHcmlkKTtcbiAgICB9XG5cbiAgICB0aGlzLmdyaWRbdGhpcy5mb2N1c2VkUm93XVt0aGlzLmZvY3VzZWRDb2xdXG4gICAgICAgIC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuc2hvd0tleXNJbmRpY2F0b3IpO1xuICAgIHRoaXMuZ3JpZFt0aGlzLmZvY3VzZWRSb3ddW3RoaXMuZm9jdXNlZENvbF1cbiAgICAgICAgLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLmhpZGVLZXlzSW5kaWNhdG9yKTtcbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBSZWdpc3RlciBncmlkIGV2ZW50c1xuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLnJlZ2lzdGVyRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuY2xlYXJFdmVudHMoKTtcblxuICAgIHRoaXMuZ3JpZE5vZGUuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuY2hlY2tGb2N1c0NoYW5nZSk7XG4gICAgdGhpcy5ncmlkTm9kZS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5kZWxlZ2F0ZUJ1dHRvbkhhbmRsZXIpO1xuICAgIHRoaXMuZ3JpZE5vZGUuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmZvY3VzQ2xpY2tlZENlbGwpO1xuICAgIHRoaXMuZ3JpZE5vZGUuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmRlbGVnYXRlQnV0dG9uSGFuZGxlcik7XG5cbiAgICBpZiAodGhpcy5wYWdpbmF0aW9uRW5hYmxlZCkge1xuICAgICAgICB0aGlzLmdyaWROb2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmNoZWNrUGFnZUNoYW5nZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2hvdWxkUmVzdHJ1Y3R1cmUpIHtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsIHRoaXMuY2hlY2tSZXN0cnVjdHVyZUdyaWQpO1xuICAgIH1cbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBGb2N1cyBvbiB0aGUgY2VsbCBpbiB0aGUgc3BlY2lmaWVkIHJvdyBhbmQgY29sdW1uXG4gKlxuICogQHBhcmFtIHJvd1xuICogIFRoZSBpbmRleCBvZiB0aGUgY2VsbCdzIHJvd1xuICpcbiAqIEBwYXJhbSBjb2xcbiAqICBUaGUgaW5kZXggb2YgdGhlIGNlbGwncyBjb2x1bW5cbiAqL1xuYXJpYS5HcmlkLnByb3RvdHlwZS5mb2N1c0NlbGwgPSBmdW5jdGlvbiAocm93LCBjb2wpIHtcbiAgICBpZiAodGhpcy5zZXRGb2N1c1BvaW50ZXIocm93LCBjb2wpKSB7XG4gICAgICAgIHRoaXMuZ3JpZFtyb3ddW2NvbF0uZm9jdXMoKTtcbiAgICB9XG59O1xuXG5hcmlhLkdyaWQucHJvdG90eXBlLnNob3dLZXlzSW5kaWNhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmtleXNJbmRpY2F0b3IpIHtcbiAgICAgICAgYXJpYS5VdGlscy5yZW1vdmVDbGFzcyh0aGlzLmtleXNJbmRpY2F0b3IsICdoaWRkZW4nKTtcbiAgICB9XG59O1xuXG5hcmlhLkdyaWQucHJvdG90eXBlLmhpZGVLZXlzSW5kaWNhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmtleXNJbmRpY2F0b3IgJiZcbiAgICAgICAgdGhpcy5ncmlkW3RoaXMuZm9jdXNlZFJvd11bdGhpcy5mb2N1c2VkQ29sXS50YWJJbmRleCA9PT0gMCkge1xuICAgICAgICBhcmlhLlV0aWxzLmFkZENsYXNzKHRoaXMua2V5c0luZGljYXRvciwgJ2hpZGRlbicpO1xuICAgIH1cbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBUcmlnZ2VyZWQgb24ga2V5ZG93bi4gQ2hlY2tzIGlmIGFuIGFycm93IGtleSB3YXMgcHJlc3NlZCwgYW5kIChpZiBwb3NzaWJsZSlcbiAqICBtb3ZlcyBmb2N1cyB0byB0aGUgbmV4dCB2YWxpZCBjZWxsIGluIHRoZSBkaXJlY3Rpb24gb2YgdGhlIGFycm93IGtleS5cbiAqXG4gKiBAcGFyYW0gZXZlbnRcbiAqICBLZXlkb3duIGV2ZW50XG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuY2hlY2tGb2N1c0NoYW5nZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmICghZXZlbnQgfHwgdGhpcy5uYXZpZ2F0aW9uRGlzYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuZmluZEZvY3VzZWRJdGVtKGV2ZW50LnRhcmdldCk7XG5cbiAgICB2YXIga2V5ID0gZXZlbnQud2hpY2ggfHwgZXZlbnQua2V5Q29kZTtcbiAgICB2YXIgcm93Q2FyZXQgPSB0aGlzLmZvY3VzZWRSb3c7XG4gICAgdmFyIGNvbENhcmV0ID0gdGhpcy5mb2N1c2VkQ29sO1xuICAgIHZhciBuZXh0Q2VsbDtcblxuICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgYXJpYS5LZXlDb2RlLlVQOlxuICAgICAgICAgICAgbmV4dENlbGwgPSB0aGlzLmdldE5leHRWaXNpYmxlQ2VsbCgwLCAtMSk7XG4gICAgICAgICAgICByb3dDYXJldCA9IG5leHRDZWxsLnJvdztcbiAgICAgICAgICAgIGNvbENhcmV0ID0gbmV4dENlbGwuY29sO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgYXJpYS5LZXlDb2RlLkRPV046XG4gICAgICAgICAgICBuZXh0Q2VsbCA9IHRoaXMuZ2V0TmV4dFZpc2libGVDZWxsKDAsIDEpO1xuICAgICAgICAgICAgcm93Q2FyZXQgPSBuZXh0Q2VsbC5yb3c7XG4gICAgICAgICAgICBjb2xDYXJldCA9IG5leHRDZWxsLmNvbDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIGFyaWEuS2V5Q29kZS5MRUZUOlxuICAgICAgICAgICAgbmV4dENlbGwgPSB0aGlzLmdldE5leHRWaXNpYmxlQ2VsbCgtMSwgMCk7XG4gICAgICAgICAgICByb3dDYXJldCA9IG5leHRDZWxsLnJvdztcbiAgICAgICAgICAgIGNvbENhcmV0ID0gbmV4dENlbGwuY29sO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgYXJpYS5LZXlDb2RlLlJJR0hUOlxuICAgICAgICAgICAgbmV4dENlbGwgPSB0aGlzLmdldE5leHRWaXNpYmxlQ2VsbCgxLCAwKTtcbiAgICAgICAgICAgIHJvd0NhcmV0ID0gbmV4dENlbGwucm93O1xuICAgICAgICAgICAgY29sQ2FyZXQgPSBuZXh0Q2VsbC5jb2w7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBhcmlhLktleUNvZGUuSE9NRTpcbiAgICAgICAgICAgIGlmIChldmVudC5jdHJsS2V5KSB7XG4gICAgICAgICAgICAgICAgcm93Q2FyZXQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29sQ2FyZXQgPSAwO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgYXJpYS5LZXlDb2RlLkVORDpcbiAgICAgICAgICAgIGlmIChldmVudC5jdHJsS2V5KSB7XG4gICAgICAgICAgICAgICAgcm93Q2FyZXQgPSB0aGlzLmdyaWQubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgI
3580H1cbiAgICAgICAgICAgIGNvbENhcmV0ID0gdGhpcy5ncmlkW3RoaXMuZm9jdXNlZFJvd10ubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnBhZ2luYXRpb25FbmFibGVkKSB7XG4gICAgICAgIGlmIChyb3dDYXJldCA8IHRoaXMudG9wSW5kZXgpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0Zyb21Sb3cocm93Q2FyZXQsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJvd0NhcmV0ID49IHRoaXMudG9wSW5kZXggKyB0aGlzLnBlclBhZ2UpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvd0Zyb21Sb3cocm93Q2FyZXQsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZm9jdXNDZWxsKHJvd0NhcmV0LCBjb2xDYXJldCk7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBSZXNldCBmb2N1c2VkIHJvdyBhbmQgY29sIGlmIGl0IGRvZXNuJ3QgbWF0Y2ggZm9jdXNlZFJvdyBhbmQgZm9jdXNlZENvbFxuICpcbiAqIEBwYXJhbSBmb2N1c2VkVGFyZ2V0XG4gKiAgRWxlbWVudCB0aGF0IGlzIGN1cnJlbnRseSBmb2N1c2VkIGJ5IGJyb3dzZXJcbiAqL1xuYXJpYS5HcmlkLnByb3RvdHlwZS5maW5kRm9jdXNlZEl0ZW0gPSBmdW5jdGlvbiAoZm9jdXNlZFRhcmdldCkge1xuICAgIHZhciBmb2N1c2VkQ2VsbCA9IHRoaXMuZ3JpZFt0aGlzLmZvY3VzZWRSb3ddW3RoaXMuZm9jdXNlZENvbF07XG5cbiAgICBpZiAoZm9jdXNlZENlbGwgPT09IGZvY3VzZWRUYXJnZXQgfHxcbiAgICAgICAgZm9jdXNlZENlbGwuY29udGFpbnMoZm9jdXNlZFRhcmdldCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5ncmlkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdGhpcy5ncmlkW2ldLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkW2ldW2pdID09PSBmb2N1c2VkVGFyZ2V0IHx8XG4gICAgICAgICAgICAgICAgdGhpcy5ncmlkW2ldW2pdLmNvbnRhaW5zKGZvY3VzZWRUYXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRGb2N1c1BvaW50ZXIoaSwgaik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIFRyaWdnZXJlZCBvbiBjbGljay4gRmluZHMgdGhlIGNlbGwgdGhhdCB3YXMgY2xpY2tlZCBvbiBhbmQgZm9jdXNlcyBvbiBpdC5cbiAqXG4gKiBAcGFyYW0gZXZlbnRcbiAqICBLZXlkb3duIGV2ZW50XG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuZm9jdXNDbGlja2VkQ2VsbCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciBjbGlja2VkR3JpZENlbGwgPSB0aGlzLmZpbmRDbG9zZXN0KGV2ZW50LnRhcmdldCwgJ1t0YWJpbmRleF0nKTtcblxuICAgIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IHRoaXMuZ3JpZC5sZW5ndGg7IHJvdysrKSB7XG4gICAgICAgIGZvciAodmFyIGNvbCA9IDA7IGNvbCA8IHRoaXMuZ3JpZFtyb3ddLmxlbmd0aDsgY29sKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdyaWRbcm93XVtjb2xdID09PSBjbGlja2VkR3JpZENlbGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEZvY3VzUG9pbnRlcihyb3csIGNvbCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWFyaWEuVXRpbHMubWF0Y2hlcyhjbGlja2VkR3JpZENlbGwsICdidXR0b25bYXJpYS1oYXNwb3B1cF0nKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBEb24ndCBmb2N1cyBpZiBpdCdzIGEgbWVudSBidXR0b24gKGZvY3VzIHNob3VsZCBiZSBzZXQgdG8gbWVudSlcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb2N1c0NlbGwocm93LCBjb2wpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBUcmlnZ2VyZWQgb24gY2xpY2suIENoZWNrcyBpZiB1c2VyIGNsaWNrZWQgb24gYSBoZWFkZXIgd2l0aCBhcmlhLXNvcnQuXG4gKiAgSWYgc28sIGl0IHNvcnRzIHRoZSBjb2x1bW4gYmFzZWQgb24gdGhlIGFyaWEtc29ydCBhdHRyaWJ1dGUuXG4gKlxuICogQHBhcmFtIGV2ZW50XG4gKiAgS2V5ZG93biBldmVudFxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLmRlbGVnYXRlQnV0dG9uSGFuZGxlciA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciBrZXkgPSBldmVudC53aGljaCB8fCBldmVudC5rZXlDb2RlO1xuICAgIHZhciB0YXJnZXQgPSBldmVudC50YXJnZXQ7XG4gICAgdmFyIGlzQ2xpY2tFdmVudCA9IChldmVudC50eXBlID09PSAnY2xpY2snKTtcblxuICAgIGlmICghdGFyZ2V0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICAgIHRhcmdldC5wYXJlbnROb2RlICYmXG4gICAgICAgIHRhcmdldC5wYXJlbnROb2RlLm1hdGNoZXMoJ3RoW2FyaWEtc29ydF0nKSAmJlxuICAgICAgICAoXG4gICAgICAgICAgICBpc0NsaWNrRXZlbnQgfHxcbiAgICAgICAgICAgIGtleSA9PT0gYXJpYS5LZXlDb2RlLlNQQUNFIHx8XG4gICAgICAgICAgICBrZXkgPT09IGFyaWEuS2V5Q29kZS5SRVRVUk5cbiAgICAgICAgKVxuICAgICkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmhhbmRsZVNvcnQodGFyZ2V0LnBhcmVudE5vZGUpO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgICAgYXJpYS5VdGlscy5tYXRjaGVzKHRhcmdldCwgJy5lZGl0YWJsZS10ZXh0LCAuZWRpdC10ZXh0LWJ1dHRvbicpICYmXG4gICAgICAgIChcbiAgICAgICAgICAgIGlzQ2xpY2tFdmVudCB8fFxuICAgICAgICAgICAga2V5ID09PSBhcmlhLktleUNvZGUuUkVUVVJOXG4gICAgICAgIClcbiAgICApIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy50b2dnbGVFZGl0TW9kZShcbiAgICAgICAgICAgIHRoaXMuZmluZENsb3Nlc3QodGFyZ2V0LCAnLmVkaXRhYmxlLXRleHQnKSxcbiAgICAgICAgICAgI
3580HRydWUsXG4gICAgICAgICAgICB0cnVlXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgICBhcmlhLlV0aWxzLm1hdGNoZXModGFyZ2V0LCAnLmVkaXQtdGV4dC1pbnB1dCcpICYmXG4gICAgICAgIChcbiAgICAgICAgICAgIGtleSA9PT0gYXJpYS5LZXlDb2RlLlJFVFVSTiB8fFxuICAgICAgICAgICAga2V5ID09PSBhcmlhLktleUNvZGUuRVNDXG4gICAgICAgIClcbiAgICApIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy50b2dnbGVFZGl0TW9kZShcbiAgICAgICAgICAgIHRoaXMuZmluZENsb3Nlc3QodGFyZ2V0LCAnLmVkaXRhYmxlLXRleHQnKSxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAga2V5ID09PSBhcmlhLktleUNvZGUuUkVUVVJOXG4gICAgICAgICk7XG4gICAgfVxufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIFRvZ2dsZXMgdGhlIG1vZGUgb2YgYW4gZWRpdGFibGUgY2VsbCBiZXR3ZWVuIGRpc3BsYXlpbmcgdGhlIGVkaXQgYnV0dG9uXG4gKiAgYW5kIGRpc3BsYXlpbmcgdGhlIGVkaXRhYmxlIGlucHV0LlxuICpcbiAqIEBwYXJhbSBlZGl0Q2VsbFxuICogIENlbGwgdG8gdG9nZ2xlXG4gKlxuICogQHBhcmFtIHRvZ2dsZU9uXG4gKiAgV2hldGhlciB0byBzaG93IG9yIGhpZGUgZWRpdCBpbnB1dFxuICpcbiAqIEBwYXJhbSB1cGRhdGVUZXh0XG4gKiAgV2hldGhlciBvciBub3QgdG8gdXBkYXRlIHRoZSBidXR0b24gdGV4dCB3aXRoIHRoZSBpbnB1dCB0ZXh0XG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUudG9nZ2xlRWRpdE1vZGUgPSBmdW5jdGlvbiAoZWRpdENlbGwsIHRvZ2dsZU9uLCB1cGRhdGVUZXh0KSB7XG4gICAgdmFyIG9uQ2xhc3NOYW1lID0gdG9nZ2xlT24gPyAnZWRpdC10ZXh0LWlucHV0JyA6ICdlZGl0LXRleHQtYnV0dG9uJztcbiAgICB2YXIgb2ZmQ2xhc3NOYW1lID0gdG9nZ2xlT24gPyAnZWRpdC10ZXh0LWJ1dHRvbicgOiAnZWRpdC10ZXh0LWlucHV0JztcbiAgICB2YXIgb25Ob2RlID0gZWRpdENlbGwucXVlcnlTZWxlY3RvcignLicgKyBvbkNsYXNzTmFtZSk7XG4gICAgdmFyIG9mZk5vZGUgPSBlZGl0Q2VsbC5xdWVyeVNlbGVjdG9yKCcuJyArIG9mZkNsYXNzTmFtZSk7XG5cbiAgICBpZiAodG9nZ2xlT24pIHtcbiAgICAgICAgb25Ob2RlLnZhbHVlID0gb2ZmTm9kZS5pbm5lclRleHQ7XG4gICAgfVxuICAgIGVsc2UgaWYgKHVwZGF0ZVRleHQpIHtcbiAgICAgICAgb25Ob2RlLmlubmVyVGV4dCA9IG9mZk5vZGUudmFsdWU7XG4gICAgfVxuXG4gICAgYXJpYS5VdGlscy5hZGRDbGFzcyhvZmZOb2RlLCBhcmlhLkNTU0NsYXNzLkhJRERFTik7XG4gICAgYXJpYS5VdGlscy5yZW1vdmVDbGFzcyhvbk5vZGUsIGFyaWEuQ1NTQ2xhc3MuSElEREVOKTtcbiAgICBvZmZOb2RlLnNldEF0dHJpYnV0ZSgndGFiaW5kZXgnLCAtMSk7XG4gICAgb25Ob2RlLnNldEF0dHJpYnV0ZSgndGFiaW5kZXgnLCAwKTtcbiAgICBvbk5vZGUuZm9jdXMoKTtcbiAgICB0aGlzLmdyaWRbdGhpcy5mb2N1c2VkUm93XVt0aGlzLmZvY3VzZWRDb2xdID0gb25Ob2RlO1xuICAgIHRoaXMubmF2aWdhdGlvbkRpc2FibGVkID0gdG9nZ2xlT247XG59O1xuXG4vKipcbiAqIEBkZXNjXG4gKiAgU29ydHMgdGhlIGNvbHVtbiBiZWxvdyB0aGUgaGVhZGVyIG5vZGUsIGJhc2VkIG9uIHRoZSBhcmlhLXNvcnQgYXR0cmlidXRlLlxuICogIGFyaWEtc29ydD1cIm5vbmVcIiA9PiBhcmlhLXNvcnQ9XCJhc2NlbmRpbmdcIlxuICogIGFyaWEtc29ydD1cImFzY2VuZGluZ1wiID0+IGFyaWEtc29ydD1cImRlc2NlbmRpbmdcIlxuICogIEFsbCBvdGhlciBoZWFkZXJzIHdpdGggYXJpYS1zb3J0IGFyZSByZXNldCB0byBcIm5vbmVcIlxuICpcbiAqICBOb3RlOiBUaGlzIGltcGxlbWVudGF0aW9uIGFzc3VtZXMgdGhhdCB0aGVyZSBpcyBubyBwYWdpbmF0aW9uIG9uIHRoZSBncmlkLlxuICpcbiAqIEBwYXJhbSBoZWFkZXJOb2RlXG4gKiAgSGVhZGVyIERPTSBub2RlXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuaGFuZGxlU29ydCA9IGZ1bmN0aW9uIChoZWFkZXJOb2RlKSB7XG4gICAgdmFyIGNvbHVtbkluZGV4ID0gaGVhZGVyTm9kZS5jZWxsSW5kZXg7XG4gICAgdmFyIHNvcnRUeXBlID0gaGVhZGVyTm9kZS5nZXRBdHRyaWJ1dGUoJ2FyaWEtc29ydCcpO1xuXG4gICAgaWYgKHNvcnRUeXBlID09PSBhcmlhLlNvcnRUeXBlLkFTQ0VORElORykge1xuICAgICAgICBzb3J0VHlwZSA9IGFyaWEuU29ydFR5cGUuREVTQ0VORElORztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNvcnRUeXBlID0gYXJpYS5Tb3J0VHlwZS5BU0NFTkRJTkc7XG4gICAgfVxuXG4gICAgdmFyIGNvbXBhcmF0b3IgPSBmdW5jdGlvbiAocm93MSwgcm93Mikge1xuICAgICAgICB2Y
3580XIgcm93MVRleHQgPSByb3cxLmNoaWxkcmVuW2NvbHVtbkluZGV4XS5pbm5lclRleHQ7XG4gICAgICAgIHZhciByb3cyVGV4dCA9IHJvdzIuY2hpbGRyZW5bY29sdW1uSW5kZXhdLmlubmVyVGV4dDtcbiAgICAgICAgdmFyIHJvdzFWYWx1ZSA9IHBhcnNlSW50KHJvdzFUZXh0LnJlcGxhY2UoL1teMC05XFwuXSsvZywgJycpKTtcbiAgICAgICAgdmFyIHJvdzJWYWx1ZSA9IHBhcnNlSW50KHJvdzJUZXh0LnJlcGxhY2UoL1teMC05XFwuXSsvZywgJycpKTtcblxuICAgICAgICBpZiAoc29ydFR5cGUgPT09IGFyaWEuU29ydFR5cGUuQVNDRU5ESU5HKSB7XG4gICAgICAgICAgICByZXR1cm4gcm93MVZhbHVlIC0gcm93MlZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHJvdzJWYWx1ZSAtIHJvdzFWYWx1ZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB0aGlzLnNvcnRSb3dzKGNvbXBhcmF0b3IpO1xuICAgIHRoaXMuc2V0dXBGb2N1c0dyaWQoKTtcblxuICAgIEFycmF5LnByb3RvdHlwZS5mb3JFYWNoLmNhbGwoXG4gICAgICAgIHRoaXMuZ3JpZE5vZGUucXVlcnlTZWxlY3RvckFsbChhcmlhLkdyaWRTZWxlY3Rvci5TT1JUX0hFQURFUiksXG4gICAgICAgIGZ1bmN0aW9uIChoZWFkZXJDZWxsKSB7XG4gICAgICAgICAgICBoZWFkZXJDZWxsLnNldEF0dHJpYnV0ZSgnYXJpYS1zb3J0JywgYXJpYS5Tb3J0VHlwZS5OT05FKTtcbiAgICAgICAgfVxuICAgICk7XG5cbiAgICBoZWFkZXJOb2RlLnNldEF0dHJpYnV0ZSgnYXJpYS1zb3J0Jywgc29ydFR5cGUpO1xufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIFNvcnRzIHRoZSBncmlkJ3Mgcm93cyBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCBjb21wYXJlRm5cbiAqXG4gKiBAcGFyYW0gY29tcGFyZUZuXG4gKiAgQ29tcGFyaXNvbiBmdW5jdGlvbiB0byBzb3J0IHRoZSByb3dzXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuc29ydFJvd3MgPSBmdW5jdGlvbiAoY29tcGFyZUZuKSB7XG4gICAgdmFyIHJvd3MgPSB0aGlzLmdyaWROb2RlLnF1ZXJ5U2VsZWN0b3JBbGwoYXJpYS5HcmlkU2VsZWN0b3IuUk9XKTtcbiAgICB2YXIgcm93V3JhcHBlciA9IHJvd3NbMF0ucGFyZW50Tm9kZTtcbiAgICB2YXIgZGF0YVJvd3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChyb3dzLCAxKTtcblxuICAgIGRhdGFSb3dzLnNvcnQoY29tcGFyZUZuKTtcblxuICAgIGRhdGFSb3dzLmZvckVhY2goKGZ1bmN0aW9uIChyb3cpIHtcbiAgICAgICAgcm93V3JhcHBlci5hcHBlbmRDaGlsZChyb3cpO1xuICAgIH0pLmJpbmQodGhpcykpO1xufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIEFkZHMgYXJpYS1yb3dpbmRleCBhbmQgYXJpYS1jb2xpbmRleCB0byB0aGUgY2VsbHMgaW4gdGhlIGdyaWRcbiAqL1xuYXJpYS5HcmlkLnByb3RvdHlwZS5zZXR1cEluZGljZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHJvd3MgPSB0aGlzLmdyaWROb2RlLnF1ZXJ5U2VsZWN0b3JBbGwoYXJpYS5HcmlkU2VsZWN0b3IuUk9XKTtcblxuICAgIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IHJvd3MubGVuZ3RoOyByb3crKykge1xuICAgICAgICB2Y
3580XIgY29scyA9IHJvd3Nbcm93XS5xdWVyeVNlbGVjdG9yQWxsKGFyaWEuR3JpZFNlbGVjdG9yLkNFTEwpO1xuICAgICAgICByb3dzW3Jvd10uc2V0QXR0cmlidXRlKCdhcmlhLXJvd2luZGV4Jywgcm93ICsgMSk7XG5cbiAgICAgICAgZm9yICh2YXIgY29sID0gMDsgY29sIDwgY29scy5sZW5ndGg7IGNvbCsrKSB7XG4gICAgICAgICAgICBjb2xzW2NvbF0uc2V0QXR0cmlidXRlKCdhcmlhLWNvbGluZGV4JywgY29sICsgMSk7XG4gICAgICAgIH1cblxuICAgIH1cbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBEZXRlcm1pbmVzIHRoZSBwZXIgcGFnZSBhdHRyaWJ1dGUgb2YgdGhlIGdyaWQsIGFuZCBzaG93cy9oaWRlcyByb3dzXG4gKiAgYWNjb3JkaW5nbHkuXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuc2V0dXBQYWdpbmF0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMub25QYWdpbmF0aW9uQ2hhbmdlID0gdGhpcy5vblBhZ2luYXRpb25DaGFuZ2UgfHwgZnVuY3Rpb24gKCkge307XG4gICAgdGhpcy5wZXJQYWdlID0gcGFyc2VJbnQodGhpcy5ncmlkTm9kZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtcGVyLXBhZ2UnKSk7XG4gICAgdGhpcy5zaG93RnJvbVJvdygwLCB0cnVlKTtcbn07XG5cbmFyaWEuR3JpZC5wcm90b3R5cGUuc2V0UGFnaW5hdGlvbkNoYW5nZUhhbmRsZXIgPSBmdW5jdGlvbiAob25QYWdpbmF0aW9uQ2hhbmdlKSB7XG4gICAgdGhpcy5vblBhZ2luYXRpb25DaGFuZ2UgPSBvblBhZ2luYXRpb25DaGFuZ2U7XG59O1xuXG4vKipcbiAqIEBkZXNjXG4gKiAgQ2hlY2sgaWYgcGFnZSB1cCBvciBwYWdlIGRvd24gd2FzIHByZXNzZWQsIGFuZCBzaG93IHRoZSBuZXh0IHBhZ2UgaWYgc28uXG4gKlxuICogQHBhcmFtIGV2ZW50XG4gKiAgS2V5ZG93biBldmVudFxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLmNoZWNrUGFnZUNoYW5nZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBrZXkgPSBldmVudC53aGljaCB8fCBldmVudC5rZXlDb2RlO1xuXG4gICAgaWYgKGtleSA9PT0gYXJpYS5LZXlDb2RlLlBBR0VfVVApIHtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5tb3ZlUGFnZVVwKCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGtleSA9PT0gYXJpYS5LZXlDb2RlLlBBR0VfRE9XTikge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLm1vdmVQYWdlRG93bigpO1xuICAgIH1cbn07XG5cbmFyaWEuR3JpZC5wcm90b3R5cGUubW92ZVBhZ2VVcCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc3RhcnRJbmRleCA9IE1hdGgubWF4KHRoaXMucGVyUGFnZSAtIDEsIHRoaXMudG9wSW5kZXggLSAxKTtcbiAgICB0aGlzLnNob3dGcm9tUm93KHN0YXJ0SW5kZXgsIGZhbHNlKTtcbiAgICB0aGlzLmZvY3VzQ2VsbChzdGFydEluZGV4LCB0aGlzLmZvY3VzZWRDb2wpO1xufTtcblxuYXJpYS5HcmlkLnByb3RvdHlwZS5tb3ZlUGFnZURvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN0YXJ0SW5kZXggPSB0aGlzLnRvcEluZGV4ICsgdGhpcy5wZXJQYWdlO1xuICAgIHRoaXMuc2hvd0Zyb21Sb3coc3RhcnRJbmRleCwgdHJ1ZSk7XG4gICAgdGhpcy5mb2N1c0NlbGwoc3RhcnRJbmRleCwgdGhpcy5mb2N1c2VkQ29sKTtcbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBTY3JvbGwgdGhlIHNwZWNpZmllZCByb3cgaW50byB2aWV3IGluIHRoZSBzcGVjaWZpZWQgZGlyZWN0aW9uXG4gKlxuICogQHBhcmFtIHN0YXJ0SW5kZXhcbiAqICBSb3cgaW5kZXggdG8gdXNlIGFzIHRoZSBzdGFydCBpbmRleFxuICpcbiAqIEBwYXJhbSBzY3JvbGxEb3duXG4gKiAgV2hldGhlciB0byBzY3JvbGwgdGhlIG5ldyBwYWdlIGFib3ZlIG9yIGJlbG93IHRoZSByb3cgaW5kZXhcbiAqL1xuYXJpYS5HcmlkLnByb3RvdHlwZS5zaG93RnJvbVJvdyA9IGZ1bmN0aW9uIChzdGFydEluZGV4LCBzY3JvbGxEb3duKSB7XG4gICAgdmFyIGRhdGFSb3dzID1cbiAgICAgICAgdGhpcy5ncmlkTm9kZS5xdWVyeVNlbGVjdG9yQWxsKGFyaWEuR3JpZFNlbGVjdG9yLlNDUk9MTF9ST1cpO1xuICAgIHZhciByZWFjaGVkVG9wID0gZmFsc2U7XG4gICAgdmFyIGZpcnN0SW5kZXggPSAtMTtcbiAgICB2YXIgZW5kSW5kZXggPSAtMTtcblxuICAgIGlmIChzdGFydEluZGV4IDwgMCB8fCBzdGFydEluZGV4ID49IGRhdGFSb3dzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkYXRhUm93cy5sZW5ndGg7IGkrKykge1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIChcbiAgICAgICAgICAgICAgICBzY3JvbGxEb3duICYmXG4gICAgICAgICAgICAgICAgaSA+PSBzdGFydEluZGV4ICYmXG4gICAgICAgICAgICAgICAgaSA8IHN0YXJ0SW5kZXggKyB0aGlzLnBlclBhZ2UpIHx8XG4gICAgICAgICAgICAoXG4gICAgICAgICAgICAgICAgIXNjcm9sbERvd24gJiZcbiAgICAgICAgICAgICAgICBpIDw9IHN0YXJ0SW5kZXggJiZcbiAgICAgICAgICAgICAgICBpID4gc3RhcnRJbmRleCAtIHRoaXMucGVyUGFnZVxuICAgICAgICAgICAgKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGFyaWEuVXRpbHMucmVtb3ZlQ2xhc3MoZGF0YVJvd3NbaV0sIGFyaWEuQ1NTQ2xhc3MuSElEREVOKTtcblxuICAgICAgICAgICAgaWYgKCFyZWFjaGVkVG9wKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50b3BJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgcmVhY2hlZFRvcCA9IHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChmaXJzdEluZGV4IDwgMCkge1xuICAgICAgICAgICAgICAgIGZpcnN0SW5kZXggPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZW5kSW5kZXggPSBpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXJpYS5VdGlscy5hZGRDbGFzcyhkYXRhUm93c1tpXSwgYXJpYS5DU1NDbGFzcy5ISURERU4pO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRoaXMub25QYWdpbmF0aW9uQ2hhbmdlKGZpcnN0SW5kZXgsIGVuZEluZGV4KTtcbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBUaHJvdHRsZSByZXN0cnVjdHVyaW5nIHRvIG9ubHkgaGFwcGVuIGV2ZXJ5IDMwMG1zXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuY2hlY2tSZXN0cnVjdHVyZUdyaWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMud2FpdGluZ1RvUmVzdHJ1Y3R1cmUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgI
3580HRoaXMud2FpdGluZ1RvUmVzdHJ1Y3R1cmUgPSB0cnVlO1xuXG4gICAgc2V0VGltZW91dCh0aGlzLnJlc3RydWN0dXJlR3JpZCwgMzAwKTtcbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBSZXN0cnVjdHVyZSBncmlkIGJhc2VkIG9uIHRoZSBzaXplLlxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLnJlc3RydWN0dXJlR3JpZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLndhaXRpbmdUb1Jlc3RydWN0dXJlID0gZmFsc2U7XG5cbiAgICB2YXIgZ3JpZFdpZHRoID0gdGhpcy5ncmlkTm9kZS5vZmZzZXRXaWR0aDtcbiAgICB2YXIgY2VsbHMgPSB0aGlzLmdyaWROb2RlLnF1ZXJ5U2VsZWN0b3JBbGwoYXJpYS5HcmlkU2VsZWN0b3IuQ0VMTCk7XG4gICAgdmFyIGN1cnJlbnRXaWR0aCA9IDA7XG5cbiAgICB2YXIgZm9jdXNlZEVsZW1lbnQgPSB0aGlzLmdyaWROb2RlLnF1ZXJ5U2VsZWN0b3IoYXJpYS5HcmlkU2VsZWN0b3IuVEFCQkFCTEUpO1xuICAgIHZhciBzaG91bGRSZWZvY3VzID0gKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGZvY3VzZWRFbGVtZW50KTtcbiAgICB2YXIgZm9jdXNlZEluZGV4ID0gKHRoaXMuZm9jdXNlZFJvdyAqIHRoaXMuZ3JpZFswXS5sZW5ndGggKyB0aGlzLmZvY3VzZWRDb2wpO1xuXG4gICAgdmFyIG5ld1JvdyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIG5ld1Jvdy5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAncm93Jyk7XG4gICAgdGhpcy5ncmlkTm9kZS5pbm5lckhUTUwgPSAnJztcbiAgICB0aGlzLmdyaWROb2RlLmFwcGVuZChuZXdSb3cpO1xuXG4gICAgY2VsbHMuZm9yRWFjaChmdW5jdGlvbiAoY2VsbCwgaW5kZXgpIHtcbiAgICAgICAgdmFyIGNlbGxXaWR0aCA9IGNlbGwub2Zmc2V0V2lkdGg7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRXaWR0aCA+IDAgJiYgY3VycmVudFdpZHRoID49IChncmlkV2lkdGggLSBjZWxsV2lkdGgpKSB7XG4gICAgICAgICAgICBuZXdSb3cgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgICAgIG5ld1Jvdy5zZXRBdHRyaWJ1dGUoJ3JvbGUnLCAncm93Jyk7XG4gICAgICAgICAgICB0aGlzLmdyaWROb2RlLmFwcGVuZChuZXdSb3cpO1xuICAgICAgICAgICAgY3VycmVudFdpZHRoID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIG5ld1Jvdy5hcHBlbmQoY2VsbCk7XG4gICAgICAgIGN1cnJlbnRXaWR0aCArPSBjZWxsV2lkdGg7XG4gICAgfSk7XG5cbiAgICB0aGlzLnNldHVwRm9jdXNHcmlkKCk7XG5cbiAgICB0aGlzLmZvY3VzZWRSb3cgPSBNYXRoLmZsb29yKGZvY3VzZWRJbmRleCAvIHRoaXMuZ3JpZFswXS5sZW5ndGgpO1xuICAgIHRoaXMuZm9jdXNlZENvbCA9IGZvY3VzZWRJbmRleCAlIHRoaXMuZ3JpZFswXS5sZW5ndGg7XG5cbiAgICBpZiAoc2hvdWxkUmVmb2N1cykge1xuICAgICAgICB0aGlzLmZvY3VzQ2VsbCh0aGlzLmZvY3VzZWRSb3csIHRoaXMuZm9jdXNlZENvbCk7XG4gICAgfVxufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIEdldCBuZXh0IGNlbGwgdG8gdGhlIHJpZ2h0IG9yIGxlZnQgKGRpcmVjdGlvbikgb2YgdGhlIGZvY3VzZWRcbiAqICBjZWxsLlxuICpcbiAqIEBwYXJhbSBjdXJyUm93XG4gKiAgUm93IGluZGV4IHRvIHN0YXJ0IHNlYXJjaGluZyBmcm9tXG4gKlxuICogQHBhcmFtIGN1cnJDb2xcbiAqICBDb2x1bW4gaW5kZXggdG8gc3RhcnQgc2VhcmNoaW5nIGZyb21cbiAqXG4gKiBAcGFyYW0gZGlyZWN0aW9uWFxuICogIFggZGlyZWN0aW9uIGZvciB3aGVyZSB0byBjaGVjayBmb3IgY2VsbHMuICsxIHRvIGNoZWNrIHRvIHRoZSByaWdodCwgLTEgdG9cbiAqICBjaGVjayB0byB0aGUgbGVmdFxuICpcbiAqIEByZXR1cm5cbiAqICBJbmRpY2VzIG9mIHRoZSBuZXh0IGNlbGwgaW4gdGhlIHNwZWNpZmllZCBkaXJlY3Rpb24uIFJldHVybnMgdGhlIGZvY3VzZWRcbiAqICBjZWxsIGlmIG5vbmUgYXJlIGZvdW5kLlxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLmdldE5leHRDZWxsID0gZnVuY3Rpb24gKFxuICAgIGN1cnJSb3csXG4gICAgY3VyckNvbCxcbiAgICBkaXJlY3Rpb25YLFxuICAgIGRpcmVjdGlvbllcbikge1xuICAgIHZhciByb3cgPSBjdXJyUm93ICsgZGlyZWN0aW9uWTtcbiAgICB2YXIgY29sID0gY3VyckNvbCArIGRpcmVjdGlvblg7XG4gICAgdmFyIHJvd0NvdW50ID0gdGhpcy5ncmlkLmxlbmd0aDtcbiAgICB2YXIgaXNMZWZ0UmlnaHQgPSBkaXJlY3Rpb25YICE9PSAwO1xuXG4gICAgaWYgKCFyb3dDb3VudCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIGNvbENvdW50ID0gdGhpcy5ncmlkWzBdLmxlbmd0aDtcblxuICAgIGlmICh0aGlzLnNob3VsZFdyYXBDb2xzICYmIGlzTGVmdFJpZ2h0KSB7XG4gICAgICAgIGlmIChjb2wgPCAwKSB7XG4gICAgICAgICAgICBjb2wgPSBjb2xDb3VudCAtIDE7XG4gICAgICAgICAgICByb3ctLTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjb2wgPj0gY29sQ291bnQpIHtcbiAgICAgICAgICAgIGNvbCA9IDA7XG4gICAgICAgICAgICByb3crKztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnNob3VsZFdyYXBSb3dzICYmICFpc0xlZnRSaWdodCkge1xuICAgICAgICBpZiAocm93IDwgMCkge1xuICAgICAgICAgICAgY29sLS07XG4gICAgICAgICAgICByb3cgPSByb3dDb3VudCAtIDE7XG4gICAgICAgICAgICBpZiAodGhpcy5ncmlkW3Jvd10gJiYgY29sID49IDAgJiYgIXRoaXMuZ3JpZFtyb3ddW2NvbF0pIHtcbiAgICAgICAgICAgICAgICAvLyBTb21ldGltZXMgdGhlIGJvdHRvbSByb3cgaXMgbm90IGNvbXBsZXRlbHkgZmlsbGVkIGluLiBJbiB0aGlzIGNhc2UsXG4gICAgICAgICAgICAgICAgLy8ganVtcCB0byB0aGUgbmV4dCBmaWxsZWQgaW4gY2VsbC5cbiAgICAgICAgICAgICAgICByb3ctLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChyb3cgPj0gcm93Q291bnQgfHwgIXRoaXMuZ3JpZFtyb3ddW2NvbF0pIHtcbiAgICAgICAgICAgIHJvdyA9IDA7XG4gICAgICAgICAgICBjb2wrKztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLmlzVmFsaWRDZWxsKHJvdywgY29sKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICBjb2w6IGNvbFxuICAgICAgICB9O1xuICAgIH1cbiAgICBlbHNlIGlmICh0aGlzLmlzVmFsaWRDZWxsKGN1cnJSb3csIGN1cnJDb2wpKSB7XG4gICAgICAgI
3580HJldHVybiB7XG4gICAgICAgICAgICByb3c6IGN1cnJSb3csXG4gICAgICAgICAgICBjb2w6IGN1cnJDb2xcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59O1xuXG4vKipcbiAqIEBkZXNjXG4gKiAgR2V0IG5leHQgdmlzaWJsZSBjb2x1bW4gdG8gdGhlIHJpZ2h0IG9yIGxlZnQgKGRpcmVjdGlvbikgb2YgdGhlIGZvY3VzZWRcbiAqICBjZWxsLlxuICpcbiAqIEBwYXJhbSBkaXJlY3Rpb25cbiAqICBEaXJlY3Rpb24gZm9yIHdoZXJlIHRvIGNoZWNrIGZvciBjZWxscy4gKzEgdG8gY2hlY2sgdG8gdGhlIHJpZ2h0LCAtMSB0b1xuICogIGNoZWNrIHRvIHRoZSBsZWZ0XG4gKlxuICogQHJldHVyblxuICogIEluZGljZXMgb2YgdGhlIG5leHQgdmlzaWJsZSBjZWxsIGluIHRoZSBzcGVjaWZpZWQgZGlyZWN0aW9uLiBJZiBubyB2aXNpYmxlXG4gKiAgY2VsbHMgYXJlIGZvdW5kLCByZXR1cm5zIGZhbHNlIGlmIHRoZSBjdXJyZW50IGNlbGwgaXMgaGlkZGVuIGFuZCByZXR1cm5zXG4gKiAgdGhlIGN1cnJlbnQgY2VsbCBpZiBpdCBpcyBub3QgaGlkZGVuLlxuICovXG5hcmlhLkdyaWQucHJvdG90eXBlLmdldE5leHRWaXNpYmxlQ2VsbCA9IGZ1bmN0aW9uIChkaXJlY3Rpb25YLCBkaXJlY3Rpb25ZKSB7XG4gICAgdmFyIG5leHRDZWxsID0gdGhpcy5nZXROZXh0Q2VsbChcbiAgICAgICAgdGhpcy5mb2N1c2VkUm93LFxuICAgICAgICB0aGlzLmZvY3VzZWRDb2wsXG4gICAgICAgIGRpcmVjdGlvblgsXG4gICAgICAgIGRpcmVjdGlvbllcbiAgICApO1xuXG4gICAgaWYgKCFuZXh0Q2VsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIHJvd0NvdW50ID0gdGhpcy5ncmlkLmxlbmd0aDtcbiAgICB2YXIgY29sQ291bnQgPSB0aGlzLmdyaWRbbmV4dENlbGwucm93XS5sZW5ndGg7XG5cbiAgICB3aGlsZSAodGhpcy5pc0hpZGRlbihuZXh0Q2VsbC5yb3csIG5leHRDZWxsLmNvbCkpIHtcbiAgICAgICAgdmFyIGN1cnJSb3cgPSBuZXh0Q2VsbC5yb3c7XG4gICAgICAgIHZhciBjdXJyQ29sID0gbmV4dENlbGwuY29sO1xuXG4gICAgICAgIG5leHRDZWxsID0gdGhpcy5nZXROZXh0Q2VsbChjdXJyUm93LCBjdXJyQ29sLCBkaXJlY3Rpb25YLCBkaXJlY3Rpb25ZKTtcblxuICAgICAgICBpZiAoY3VyclJvdyA9PT0gbmV4dENlbGwucm93ICYmIGN1cnJDb2wgPT09IG5leHRDZWxsLmNvbCkge1xuICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIG1vcmUgY2VsbHMgdG8gdHJ5IGlmIGdldE5leHRDZWxsIHJldHVybnMgdGhlIGN1cnJlbnQgY2VsbFxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5leHRDZWxsO1xufTtcblxuLyoqXG4gKiBAZGVzY1xuICogIFNob3cgb3IgaGlkZSB0aGUgY2VsbHMgaW4gdGhlIHNwZWNpZmllZCBjb2x1bW5cbiAqXG4gKiBAcGFyYW0gY29sdW1uSW5kZXhcbiAqICBJbmRleCBvZiB0aGUgY29sdW1uIHRvIHRvZ2dsZVxuICpcbiAqIEBwYXJhbSBpc1Nob3duXG4gKiAgV2hldGhlciBvciBub3QgdG8gc2hvdyB0aGUgY29sdW1uXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUudG9nZ2xlQ29sdW1uID0gZnVuY3Rpb24gKGNvbHVtbkluZGV4LCBpc1Nob3duKSB7XG4gICAgdmFyIGNlbGxTZWxlY3RvciA9ICdbYXJpYS1jb2xpbmRleD1cIicgKyBjb2x1bW5JbmRleCArICdcIl0nO1xuICAgIHZhciBjb2x1bW5DZWxscyA9IHRoaXMuZ3JpZE5vZGUucXVlcnlTZWxlY3RvckFsbChjZWxsU2VsZWN0b3IpO1xuXG4gICAgQXJyYXkucHJvdG90eXBlLmZvckVhY2guY2FsbChcbiAgICAgICAgY29sdW1uQ2VsbHMsXG4gICAgICAgIGZ1bmN0aW9uIChjZWxsKSB7XG4gICAgICAgICAgICBpZiAoaXNTaG93bikge1xuICAgICAgICAgICAgICAgIGFyaWEuVXRpbHMucmVtb3ZlQ2xhc3MoY2VsbCwgYXJpYS5DU1NDbGFzcy5ISURERU4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgYXJpYS5VdGlscy5hZGRDbGFzcyhjZWxsLCBhcmlhLkNTU0NsYXNzLkhJRERFTik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICApO1xuXG4gICAgaWYgKCFpc1Nob3duICYmIHRoaXMuZm9jdXNlZENvbCA9PT0gKGNvbHVtbkluZGV4IC0gMSkpIHtcbiAgICAgICAgLy8gSWYgZm9jdXMgd2FzIHNldCBvbiB0aGUgaGlkZGVuIGNvbHVtbiwgc2hpZnQgZm9jdXMgdG8gdGhlIHJpZ2h0XG4gICAgICAgIHZhciBuZXh0Q2VsbCA9IHRoaXMuZ2V0TmV4dFZpc2libGVDZWxsKDEsIDApO1xuICAgICAgICBpZiAobmV4dENlbGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0Rm9jdXNQb2ludGVyKG5leHRDZWxsLnJvdywgbmV4dENlbGwuY29sKTtcbiAgICAgICAgfVxuICAgIH1cbn07XG5cbi8qKlxuICogQGRlc2NcbiAqICBGaW5kIHRoZSBjbG9zZXN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIHNlbGVjdG9yLiBPbmx5IGNoZWNrcyBwYXJlbnQgYW5kXG4gKiAgZGlyZWN0IGNoaWxkcmVuLlxuICpcbiAqIEBwYXJhbSBlbGVtZW50XG4gKiAgRWxlbWVudCB0byBzdGFydCBzZWFyY2hpbmcgZnJvbVxuICpcbiAqIEBwYXJhbSBzZWxlY3RvclxuICogIEluZGV4IG9mIHRoZSBjb2x1bW4gdG8gdG9nZ2xlXG4gKi9cbmFyaWEuR3JpZC5wcm90b3R5cGUuZmluZENsb3Nlc3QgPSBmdW5jdGlvbiAoZWxlbWVudCwgc2VsZWN0b3IpIHtcbiAgICBpZiAoYXJpYS5VdGlscy5tYXRjaGVzKGVsZW1lbnQsIHNlbGVjdG9yKSkge1xuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9XG5cbiAgICBpZiAoYXJpYS5VdGlscy5tYXRjaGVzKGVsZW1lbnQucGFyZW50Tm9kZSwgc2VsZWN0b3IpKSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50LnBhcmVudE5vZGU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGVsZW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvcik7XG59O1xuIiwiKGZ1bmN0aW9uKCkge1xuICBjb25zdCBoaWRkZW5Db250YWluZXJTZWxlY3RvciA9ICcuc2luZ2xlX19tYXAgLmhqaS1hcmVhcy1tYXBib3ggYSwgJyArXG4gICAgJy5zaW5nbGVfX21hcCAuaGppLWFyZWFzLW1hcGJveCAgaW5wdXQsICcgK1xuICAgICcuc2luZ2xlX19tYXAgLmhqaS1hcmVhcy1tYXBib3ggIGJ1dHRvbiwgJyArXG4gICAgJy5zaW5nbGVfX21hcCAuaGppLWFyZWFzLW1hcGJveCAgc2VsZWN0LCAnICtcbiAgICAnLnNpbmdsZV9fbWFwIC5oamktYXJlYXMtbWFwYm94ICB0ZXh0YXJlYSAnXG4gIDtcblxuICBmdW5jdGlvbiBhY2Nlc3NpYmlsaXR5SGlkZUNvb
3580nRhaW5lckVsZW1lbnQoKSB7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoaGlkZGVuQ29udGFpbmVyU2VsZWN0b3IpLmZvckVhY2goZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgaXRlbS5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJy0xJyk7XG4gICAgICB9KTtcbiAgICB9LCA3MDApO1xuICB9XG5cblxuICB2YXIgdGFyZ2V0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLnNpbmdsZV9fbWFwIC5oamktYXJlYXMtbWFwYm94ICcpO1xuXG4gIGlmICh0eXBlb2YgdGFyZ2V0ICE9PSAndW5kZWZpbmVkJyAmJiBudWxsICE9PSB0YXJnZXQpIHtcbiAgICAvLyBjcmVhdGUgYW4gb2JzZXJ2ZXIgaW5zdGFuY2VcbiAgICB2YXIgb2JzZXJ2ZXIgPSBuZXcgTXV0YXRpb25PYnNlcnZlcihmdW5jdGlvbihtdXRhdGlvbnMpIHtcbiAgICAgIGFjY2Vzc2liaWxpdHlIaWRlQ29udGFpbmVyRWxlbWVudCgpO1xuICAgIH0pO1xuICAgIC8vIGNvbmZpZ3VyYXRpb24gb2YgdGhlIG9ic2VydmVyOlxuICAgIHZhciBjb25maWcgPSB7IGF0dHJpYnV0ZXM6IHRydWUsIGNoaWxkTGlzdDogdHJ1ZSwgY2hhcmFjdGVyRGF0YTogdHJ1ZSB9O1xuICAgIC8vIHBhc3MgaW4gdGhlIHRhcmdldCBub2RlLCBhcyB3ZWxsIGFzIHRoZSBvYnNlcnZlciBvcHRpb25zXG4gICAgb2JzZXJ2ZXIub2JzZXJ2ZSh0YXJnZXQsIGNvbmZpZyk7XG4gIH1cblxuICBhY2Nlc3NpYmlsaXR5SGlkZUNvbnRhaW5lckVsZW1lbnQoKTtcblxufSkoKTtcblxuIiwiLypqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5jb25zdCBtYWtlRm9jdXNPblRhcmdldEFmdGVyR29PbkxpbmsgPSBmdW5jdGlvbiAobGluaykge1xuICAgIGNvbnN0IGhyZWYgPSBqUXVlcnkobGluaykuYXR0cignaHJlZicpO1xuICAgIGlmIChocmVmICYmIGhyZWYuaW5kZXhPZignIycpID09PSAwKSB7XG4gICAgICAgIGpRdWVyeShsaW5rKS5vbignY2xpY2snLCBmdW5jdGlvbigpe1xuICAgICAgICAgICAgalF1ZXJ5KGhyZWYpLmZvY3VzKCk7XG4gICAgICAgIH0pO1xuICAgIH1cbn07XG5cbmpRdWVyeShmdW5jdGlvbigkKXtcbiAgICAkKCdib2R5Jykub24oJ2NsaWNrJywgJ2FbZGF0YS1hbmNob3I9XCJ0cnVlXCJdJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIG1ha2VGb2N1c09uVGFyZ2V0QWZ0ZXJHb09uTGluaygkKHRoaXMpKTtcbiAgICB9KTtcblxuICAgICQoJ2JvZHknKS5vbignY2xpY2snLCAnYVtkYXRhLWFuY2hvcj1cImZvcm1cIl0nLCBmdW5jdGlvbigpIHtcbiAgICAgICAgY29uc3QgaHJlZiA9ICQodGhpcykuYXR0cignaHJlZicpO1xuICAgICAgICBpZiAoaHJlZiAmJi
3580BocmVmLmluZGV4T2YoJyMnKSA9PT0gMCkge1xuICAgICAgICAgICAgdmFyICR0aGlzID0gJChocmVmKTtcbiAgICAgICAgICAgIHZhciAkZm9ybSA9ICR0aGlzLmZpbmQoJ2Zvcm0nKTtcbiAgICAgICAgICAgIGlmICgkZm9ybS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgJGZvcm0gPSAkKCRmb3JtWzBdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciAkZm9ybVBhcmVudCA9ICR0aGlzO1xuICAgICAgICAgICAgd2hpbGUgKCRmb3JtLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgICAgICAgICAkZm9ybVBhcmVudCA9ICRmb3JtUGFyZW50LnBhcmVudCgpO1xuICAgICAgICAgICAgICAgICRmb3JtID0gJGZvcm1QYXJlbnQuZmluZCgnZm9ybScpO1xuICAgICAgICAgICAgICAgIGlmICgkZm9ybS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICRmb3JtID0gJCgkZm9ybVswXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCRmb3JtLmZpbmQoJ2lucHV0OnZpc2libGUnKSA+IDApIHtcbiAgICAgICAgICAgICAgICAkKCRmb3JtLmZpbmQoJ2lucHV0OnZpc2libGUnKVswXSkuZm9jdXMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0pO1xufSk7XG4iLCJ3aW5kb3cubWFwQm94QTExeSA9IGZ1bmN0aW9uKGVsZW0pIHtcbiAgICBpZiAoZWxlbSA9PT0gbnVsbCB8fCAndW5kZWZpbmVkJyA9PT0gdHlwZW9mIGVsZW0pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBvYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKG11dGF0aW9uUmVjb3JkcyA9PiB7XG4gICAgICAgIGZvciAobGV0IG1SZWNvZCBvZiBtdXRhdGlvblJlY29yZHMpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBtUmVjb2QudHlwZSA9PT0gJ2NoaWxkTGlzdCcgJiZcbiAgICAgICAgICAgICAgICBtUmVjb2QudGFyZ2V0LmNsYXNzTGlzdC5jb250YWlucygnbGVhZmxldC1tYXJrZXItcGFuZScpICYmXG4gICAgICAgICAgICAgICAgbVJlY29kLmFkZGVkTm9kZXMubGVuZ3RoID4gMFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgdGlsZUl0ZW0gb2YgbVJlY29kLmFkZGVkTm9kZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRpbGVJdGVtLnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2ltZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVJdGVtLnNldEF0dHJpYnV0ZSgnYWx0JywgJ1Byb3BlcnR5IE1hcmtlcicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBtUmVjb2QudHlwZSA9PT0gJ2NoaWxkTGlzdCcgJiZcbiAgICAgICAgICAgICAgICBtUmVjb2QudGFyZ2V0LmNsYXNzTGlzdC5jb250YWlucygnbGVhZmxldC10aWxlLWNvbnRhaW5lcicpICYmXG4gICAgICAgICAgICAgICAgbVJlY29kLmFkZGVkTm9kZXMubGVuZ3RoID4gMFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgdGlsZUl0ZW0gb2YgbVJlY29kLmFkZGVkTm9kZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRpbGVJdGVtLnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2ltZycpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbGVJdGVtLnNldEF0dHJpYnV0ZSgncm9sZScsICdub25lJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIG9ic2VydmVyLm9ic2VydmUoZWxlbSwge1xuICAgICAgICBjaGlsZExpc3Q6IHRydWUsXG4gICAgICAgIHN1YnRyZWU6IHRydWVcbiAgICB9KTtcbn07XG4iLCIvKlxuKiAgIFRoaXMgY29udGVudCBpcyBsaWNlbnNlZCBhY2NvcmRpbmcgdG8gdGhlIFczQyBTb2Z0d2FyZSBMaWNlbnNlIGF0XG4qICAgaHR0cHM6Ly93d3cudzMub3JnL0NvbnNvcnRpdW0vTGVnYWwvMjAxNS9jb3B5cmlnaHQtc29mdHdhcmUtYW5kLWRvY3VtZW50XG4qL1xudmFyIE1lbnViYXJJdGVtID0gZnVuY3Rpb24gKGRvbU5vZGUsIG1lbnVPYmopIHtcblxuICAgIHRoaXMubWVudSA9IG1lbnVPYmo7XG4gICAgdGhpcy5kb21Ob2RlID0gZG9tTm9kZTtcbiAgICB0aGlzLnBvcHVwTWVudSA9IGZhbHNlO1xuXG4gICAgdGhpcy5oYXNGb2N1cyA9IGZhbHNlO1xuICAgIHRoaXMuaGFzSG92ZXIgPSBmYWxzZTtcblxuICAgIHRoaXMuaXNNZW51YmFySXRlbSA9IHRydWU7XG5cbiAgICB0aGlzLmtleUNvZGUgPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgJ1RBQic6IDksXG4gICAgICAgICdFU0MnOiAyNyxcbiAgICAgICAgJ1NQQUNFJzogMzIsXG4gICAgICAgICdQQUdFVVAnOiAzMyxcbiAgICAgICAgJ1BBR0VET1dOJzogMzQsXG4gICAgICAgICdFTkQnOiAzNSxcbiAgICAgICAgJ0hPTUUnOiAzNixcbiAgICAgICAgJ0xFRlQnOiAzNyxcbiAgICAgICAgJ1VQJzogMzgsXG4gICAgICAgICdSSUdIVCc6IDM5LFxuICAgICAgICAnRE9XTic6IDQwXG4gICAgfSk7XG59O1xuXG5NZW51YmFySXRlbS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRvbU5vZGUudGFiSW5kZXggPSAtMTtcblxuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVLZXlkb3duLmJpbmQodGhpcykpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuaGFuZGxlRm9jdXMuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLmhhbmRsZUJsdXIuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3ZlcicsIHRoaXMuaGFuZGxlTW91c2VvdmVyLmJpbmQodGhpcykpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW91dCcsIHRoaXMuaGFuZGxlTW91c2VvdXQuYmluZCh0aGlzKSk7XG5cbiAgICAvLyBJbml0aWFsaXplIHBvcCB1cCBtZW51c1xuXG4gICAgdmFyIG5leHRFbGVtZW50ID0gdGhpcy5kb21Ob2RlLm5leHRFbGVtZW50U2libGluZztcblxuICAgIGlmIChuZXh0RWxlbWVudCAmJiBuZXh0RWxlbWVudC50YWdOYW1lID09PSAnVUwnKSB7XG4gICAgICAgI
3580HRoaXMucG9wdXBNZW51ID0gbmV3IFBvcHVwTWVudShuZXh0RWxlbWVudCwgdGhpcyk7XG4gICAgICAgIHRoaXMucG9wdXBNZW51LmluaXQoKTtcbiAgICB9XG5cbn07XG5cbk1lbnViYXJJdGVtLnByb3RvdHlwZS5oYW5kbGVLZXlkb3duID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdmFyIHRndCA9IGV2ZW50LmN1cnJlbnRUYXJnZXQsXG4gICAgICAgIGNoYXIgPSBldmVudC5rZXksXG4gICAgICAgIGZsYWcgPSBmYWxzZSxcbiAgICAgICAgY2xpY2tFdmVudDtcblxuICAgIGZ1bmN0aW9uIGlzUHJpbnRhYmxlQ2hhcmFjdGVyIChzdHIpIHtcbiAgICAgICAgcmV0dXJuIHN0ci5sZW5ndGggPT09IDEgJiYgc3RyLm1hdGNoKC9cXFMvKTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGV2ZW50LmtleUNvZGUpIHtcbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuRE9XTjpcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcHVwTWVudSkge1xuICAgICAgICAgICAgICAgIHRoaXMucG9wdXBNZW51Lm9wZW4oKTtcbiAgICAgICAgICAgICAgICB0aGlzLnBvcHVwTWVudS5zZXRGb2N1c1RvRmlyc3RJdGVtKCk7XG4gICAgICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5MRUZUOlxuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9QcmV2aW91c0l0ZW0odGhpcyk7XG4gICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLlJJR0hUOlxuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9OZXh0SXRlbSh0aGlzKTtcbiAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuVVA6XG4gICAgICAgICAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBvcHVwTWVudS5vcGVuKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3B1cE1lbnUuc2V0Rm9jdXNUb0xhc3RJdGVtKCk7XG4gICAgICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5IT01FOlxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5QQUdFVVA6XG4gICAgICAgICAgICB0aGlzLm1lbnUuc2V0Rm9jdXNUb0ZpcnN0SXRlbSgpO1xuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5FTkQ6XG4gICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLlBBR0VET1dOOlxuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9MYXN0SXRlbSgpO1xuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5UQUI6XG4gICAgICAgICAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBvcHVwTWVudS5jbG9zZSh0cnVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuRVNDOlxuICAgICAgICAgICAgaWYgKHRoaXMucG9wdXBNZW51KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3B1cE1lbnUuY2xvc2UodHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5TUEFDRTpcbiAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5kb21Ob2RlLmNsaWNrKCk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgaWYgKGlzUHJpbnRhYmxlQ2hhcmFjdGVyKGNoYXIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzQnlGaXJzdENoYXJhY3Rlcih0aGlzLCBjaGFyKTtcbiAgICAgICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGlmIChmbGFnKSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn07XG5cbk1lbnViYXJJdGVtLnByb3RvdHlwZS5zZXRFeHBhbmRlZCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB0aGlzLmRvbU5vZGUuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ3RydWUnKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHRoaXMuZG9tTm9kZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgICB9XG59O1xuXG5NZW51YmFySXRlbS5wcm90b3R5cGUuaGFuZGxlRm9jdXMgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzRm9jdXMgPSB0cnVlO1xufTtcblxuTWVudWJhckl0ZW0ucHJvdG90eXBlLmhhbmRsZUJsdXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzRm9jdXMgPSBmYWxzZTtcbn07XG5cbk1lbnViYXJJdGVtLnByb3RvdHlwZS5oYW5kbGVNb3VzZW92ZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLmhhc0hvdmVyID0gdHJ1ZTtcbiAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgdGhpcy5wb3B1cE1lbnUub3BlbigpO1xuICAgIH1cbn07XG5cbk1lbnViYXJJdGVtLnByb3RvdHlwZS5oYW5kbGVNb3VzZW91dCA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHRoaXMuaGFzSG92ZXIgPSBmYWxzZTtcbiAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgc2V0VGltZW91dCh0aGlzLnBvcHVwTWVudS5jbG9zZS5iaW5kKHRoaXMucG9wdXBNZW51LCBmYWxzZSksIDMwMCk7XG4gICAgfVxufTtcbiIsIi8qXG4qICAgVGhpcyBjb250ZW50IGlzIGxpY2Vuc2VkIGFjY29yZGluZyB0byB0aGUgVzNDIFNvZnR3YXJlIExpY2Vuc2UgYXRcbiogICBodHRwczovL3d3dy53My5vcmcvQ29uc29ydGl1bS9MZWdhbC8yMDE1L2NvcHlyaWdodC1zb2Z0d2FyZS1hbmQtZG9jdW1lbnRcbiovXG5cbnZhciBNZW51YmFyID0gZnVuY3Rpb24gKGRvbU5vZGUp
3580IHtcbiAgICB2YXIgZWxlbWVudENoaWxkcmVuLFxuICAgICAgICBtc2dQcmVmaXggPSAnTWVudWJhciBjb25zdHJ1Y3RvciBhcmd1bWVudCBtZW51YmFyTm9kZSAnO1xuXG4gICAgLy8gQ2hlY2sgd2hldGhlciBtZW51YmFyTm9kZSBpcyBhIERPTSBlbGVtZW50XG4gICAgaWYgKCFkb21Ob2RlIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKG1zZ1ByZWZpeCArICdpcyBub3QgYSBET00gRWxlbWVudC4nKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayB3aGV0aGVyIG1lbnViYXJOb2RlIGhhcyBkZXNjZW5kYW50IGVsZW1lbnRzXG4gICAgaWYgKG51bGwgPT09IGRvbU5vZGUgfHwgZG9tTm9kZS5jaGlsZEVsZW1lbnRDb3VudCA9PT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnUHJlZml4ICsgJ2hhcyBubyBlbGVtZW50IGNoaWxkcmVuLicpO1xuICAgIH1cblxuICAgIC8vIENoZWNrIHdoZXRoZXIgbWVudWJhck5vZGUgaGFzIEEgZWxlbWVudHNcbiAgICB2YXIgZSA9IGRvbU5vZGUuZmlyc3RFbGVtZW50Q2hpbGQ7XG4gICAgd2hpbGUgKGUpIHtcbiAgICAgICAgdmFyIG1lbnViYXJJdGVtID0gZS5maXJzdEVsZW1lbnRDaGlsZDtcbiAgICAgICAgaWYgKGUgJiYgbWVudWJhckl0ZW0gJiYgbWVudWJhckl0ZW0udGFnTmFtZSAhPT0gJ0EnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnUHJlZml4ICsgJ2hhcyBjaGlsZCBlbGVtZW50cyBhcmUgbm90IEEgZWxlbWVudHMuJyk7XG4gICAgICAgIH1cbiAgICAgICAgZSA9IGUubmV4dEVsZW1lbnRTaWJsaW5nO1xuICAgIH1cblxuICAgIHRoaXMuaXNNZW51YmFyID0gdHJ1ZTtcblxuICAgIHRoaXMuZG9tTm9kZSA9IGRvbU5vZGU7XG5cbiAgICB0aGlzLm1lbnViYXJJdGVtcyA9IFtdOyAvLyBTZWUgTWVudWJhciBpbml0IG1ldGhvZFxuICAgIHRoaXMuZmlyc3RDaGFycyA9IFtdOyAvLyBTZWUgTWVudWJhciBpbml0IG1ldGhvZFxuXG4gICAgdGhpcy5maXJzdEl0ZW0gPSBudWxsOyAvLyBTZWUgTWVudWJhciBpbml0IG1ldGhvZFxuICAgIHRoaXMubGFzdEl0ZW0gPSBudWxsOyAvLyBTZWUgTWVudWJhciBpbml0IG1ldGhvZFxuXG4gICAgdGhpcy5oYXNGb2N1cyA9IGZhbHNlOyAvLyBTZWUgTWVudWJhckl0ZW0gaGFuZGxlRm9jdXMsIGhhbmRsZUJsdXJcbiAgICB0aGlzLmhhc0hvdmVyID0gZmFsc2U7IC8vIFNlZSBNZW51YmFyIGhhbmRsZU1vdXNlb3ZlciwgaGFuZGxlTW91c2VvdXRcbn07XG5cbi8qXG4qICAgQG1ldGhvZCBNZW51YmFyLnByb3RvdHlwZS5pbml0XG4qXG4qICAgQGRlc2NcbiogICAgICAgQWRkcyBBUklBIHJvbGUgdG8gdGhlIG1lbnViYXIgbm9kZVxuKiAgICAgICBUcmF2ZXJzZSBtZW51YmFyIGNoaWxkcmVuIGZvciBBIGVsZW1lbnRzIHRvIGNvbmZpZ3VyZSBlYWNoIEEgZWxlbWVudCBhcyBhIEFSSUEgbWVudWl0ZW1cbiogICAgICAgYW5kIHBvcHVsYXRlIG1lbnVpdGVtcyBhcnJheS4gSW5pdGlhbGl6ZSBmaXJzdEl0ZW0gYW5kIGxhc3RJdGVtIHByb3BlcnRpZXMuXG4qL1xuTWVudWJhci5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbWVudWJhckl0ZW0sIGNoaWxkRWxlbWVudCwgbWVudUVsZW1lbnQsIHRleHRDb250ZW50LCBudW1JdGVtcztcblxuXG4gICAgLy8gVHJhdmVyc2UgdGhlIGVsZW1lbnQgY2hpbGRyZW4gb2YgbWVudWJhck5vZGU6IGNvbmZpZ3VyZSBlYWNoIHdpdGhcbiAgICAvLyBtZW51aXRlbSByb2xlIGJlaGF2aW9yIGFuZCBzdG9yZSByZWZlcmVuY2UgaW4gbWVudWl0ZW1zIGFycmF5LlxuICAgIHZhciBlbGVtID0gdGhpcy5kb21Ob2RlLmZpcnN0RWxlbWVudENoaWxkO1xuXG4gICAgd2hpbGUgKGVsZW0pIHtcbiAgICAgICAgdmFyIG1lbnVFbGVtZW50ID0gZWxlbS5maXJzdEVsZW1lbnRDaGlsZDtcblxuICAgICAgICBpZiAoZWxlbSAmJiBtZW51RWxlbWVudCAmJiBtZW51RWxlbWVudC50YWdOYW1lID09PSAnQScpIHtcbiAgICAgICAgICAgIG1lbnViYXJJdGVtID0gbmV3IE1lbnViYXJJdGVtKG1lbnVFbGVtZW50LCB0aGlzKTtcbiAgICAgICAgICAgIG1lbnViYXJJdGVtLmluaXQoKTtcbiAgICAgICAgICAgIHRoaXMubWVudWJhckl0ZW1zLnB1c2gobWVudWJhckl0ZW0pO1xuICAgICAgICAgICAgdGV4dENvbnRlbnQgPSBtZW51RWxlbWVudC50ZXh0Q29udGVudC50cmltKCk7XG4gICAgICAgICAgICB0aGlzLmZpcnN0Q2hhcnMucHVzaCh0ZXh0Q29udGVudC5zdWJzdHJpbmcoMCwgMSkudG9Mb3dlckNhc2UoKSk7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtID0gZWxlbS5uZXh0RWxlbWVudFNpYmxpbmc7XG4gICAgfVxuXG4gICAgLy8gVXNlIHBvcHVsYXRlZCBtZW51aXRlbXMgYXJyYXkgdG8gaW5pdGlhbGl6ZSBmaXJzdEl0ZW0gYW5kIGxhc3RJdGVtLlxuICAgIG51bUl0ZW1zID0gdGhpcy5tZW51YmFySXRlbXMubGVuZ3RoO1xuICAgIGlmIChudW1JdGVtcyA+IDApIHtcbiAgICAgICAgdGhpcy5maXJzdEl0ZW0gPSB0aGlzLm1lbnViYXJJdGVtc1sgMCBdO1xuICAgICAgICB0aGlzLmxhc3RJdGVtID0gdGhpcy5tZW51YmFySXRlbXNbIG51bUl0ZW1zIC0gMSBdO1xuICAgIH1cbiAgICB0aGlzLmZpcnN0SXRlbS5kb21Ob2RlLnRhYkluZGV4ID0gMDtcbn07XG5cbi8qIEZPQ1VTIE1BTkFHRU1FTlQgTUVUSE9EUyAqL1xuXG5NZW51YmFyLnByb3RvdHlwZS5zZXRGb2N1c1RvSXRlbSA9IGZ1bmN0aW9uIChuZXdJdGVtKSB7XG5cbiAgICB2YXIgZmxhZyA9IGZhbHNlO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLm1lbnViYXJJdGVtcy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2Y
3580XIgbWJpID0gdGhpcy5tZW51YmFySXRlbXNbaV07XG5cbiAgICAgICAgaWYgKG1iaS5kb21Ob2RlLnRhYkluZGV4ID09IDApIHtcbiAgICAgICAgICAgIGZsYWcgPSBtYmkuZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnKSA9PT0gJ3RydWUnO1xuICAgICAgICB9XG5cbiAgICAgICAgbWJpLmRvbU5vZGUudGFiSW5kZXggPSAtMTtcbiAgICAgICAgaWYgKG1iaS5wb3B1cE1lbnUpIHtcbiAgICAgICAgICAgIG1iaS5wb3B1cE1lbnUuY2xvc2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5ld0l0ZW0uZG9tTm9kZS5mb2N1cygpO1xuICAgIG5ld0l0ZW0uZG9tTm9kZS50YWJJbmRleCA9IDA7XG5cbiAgICBpZiAoZmxhZyAmJiBuZXdJdGVtLnBvcHVwTWVudSkge1xuICAgICAgICBuZXdJdGVtLnBvcHVwTWVudS5vcGVuKCk7XG4gICAgfVxufTtcblxuTWVudWJhci5wcm90b3R5cGUuc2V0Rm9jdXNUb0ZpcnN0SXRlbSA9IGZ1bmN0aW9uIChmbGFnKSB7XG4gICAgdGhpcy5zZXRGb2N1c1RvSXRlbSh0aGlzLmZpcnN0SXRlbSk7XG59O1xuXG5NZW51YmFyLnByb3RvdHlwZS5zZXRGb2N1c1RvTGFzdEl0ZW0gPSBmdW5jdGlvbiAoZmxhZykge1xuICAgIHRoaXMuc2V0Rm9jdXNUb0l0ZW0odGhpcy5sYXN0SXRlbSk7XG59O1xuXG5NZW51YmFyLnByb3RvdHlwZS5zZXRGb2N1c1RvUHJldmlvdXNJdGVtID0gZnVuY3Rpb24gKGN1cnJlbnRJdGVtKSB7XG4gICAgdmFyIGluZGV4LFxuICAgICAgbmV3SXRlbVxuICAgIDtcblxuICAgIGlmIChjdXJyZW50SXRlbSA9PT0gdGhpcy5maXJzdEl0ZW0pIHtcbiAgICAgICAgbmV3SXRlbSA9IHRoaXMubGFzdEl0ZW07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpbmRleCA9IHRoaXMubWVudWJhckl0ZW1zLmluZGV4T2YoY3VycmVudEl0ZW0pO1xuICAgICAgICBuZXdJdGVtID0gdGhpcy5tZW51YmFySXRlbXNbIGluZGV4IC0gMSBdO1xuICAgIH1cblxuICAgIHRoaXMuc2V0Rm9jdXNUb0l0ZW0obmV3SXRlbSk7XG5cbn07XG5cbk1lbnViYXIucHJvdG90eXBlLnNldEZvY3VzVG9OZXh0SXRlbSA9IGZ1bmN0aW9uIChjdXJyZW50SXRlbSkge1xuICAgIHZhciBpbmRleCxcbiAgICAgIG5ld0l0ZW1cbiAgICA7XG5cbiAgICBpZiAoY3VycmVudEl0ZW0gPT09IHRoaXMubGFzdEl0ZW0pIHtcbiAgICAgICAgbmV3SXRlbSA9IHRoaXMuZmlyc3RJdGVtO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaW5kZXggPSB0aGlzLm1lbnViYXJJdGVtcy5pbmRleE9mKGN1cnJlbnRJdGVtKTtcbiAgICAgICAgbmV3SXRlbSA9IHRoaXMubWVudWJhckl0ZW1zWyBpbmRleCArIDEgXTtcbiAgICB9XG5cbiAgICB0aGlzLnNldEZvY3VzVG9JdGVtKG5ld0l0ZW0pO1xuXG59O1xuXG5NZW51YmFyLnByb3RvdHlwZS5zZXRGb2N1c0J5Rmlyc3RDaGFyYWN0ZXIgPSBmdW5jdGlvbiAoY3VycmVudEl0ZW0sIGNoYXIpIHtcbiAgICB2YXIgc3RhcnQsIGluZGV4LCBjaGFyID0gY2hhci50b0xvd2VyQ2FzZSgpO1xuICAgIHZhciBmbGFnID0gY3VycmVudEl0ZW0uZG9tTm9kZS5nZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnKSA9PT0gJ3RydWUnO1xuXG4gICAgLy8gR2V0IHN0YXJ0IGluZGV4IGZvciBzZWFyY2ggYmFzZWQgb24gcG9zaXRpb24gb2YgY3VycmVudEl0ZW1cbiAgICBzdGFydCA9IHRoaXMubWVudWJhckl0ZW1zLmluZGV4T2YoY3VycmVudEl0ZW0pICsgMTtcbiAgICBpZiAoc3RhcnQgPT09IHRoaXMubWVudWJhckl0ZW1zLmxlbmd0aCkge1xuICAgICAgICBzdGFydCA9IDA7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgcmVtYWluaW5nIHNsb3RzIGluIHRoZSBtZW51XG4gICAgaW5kZXggPSB0aGlzLmdldEluZGV4Rmlyc3RDaGFycyhzdGFydCwgY2hhcik7XG5cbiAgICAvLyBJZiBub3QgZm91bmQgaW4gcmVtYWluaW5nIHNsb3RzLCBjaGVjayBmcm9tIGJlZ2lubmluZ1xuICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgaW5kZXggPSB0aGlzLmdldEluZGV4Rmlyc3RDaGFycygwLCBjaGFyKTtcbiAgICB9XG5cbiAgICAvLyBJZiBtYXRjaCB3YXMgZm91bmQuLi5cbiAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICB0aGlzLnNldEZvY3VzVG9JdGVtKHRoaXMubWVudWJhckl0ZW1zWyBpbmRleCBdKTtcbiAgICB9XG59O1xuXG5NZW51YmFyLnByb3RvdHlwZS5nZXRJbmRleEZpcnN0Q2hhcnMgPSBmdW5jdGlvbiAoc3RhcnRJbmRleCwgY2hhcikge1xuICAgIGZvciAodmFyIGkgPSBzdGFydEluZGV4OyBpIDwgdGhpcy5maXJzdENoYXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChjaGFyID09PSB0aGlzLmZpcnN0Q2hhcnNbIGkgXSkge1xuICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIC0xO1xufTtcbiIsImpRdWVyeShmdW5jdGlvbigkKSB7XG4gICAgd2luZG93LmZvY3VzYWJsZUNvbnRlbnQgPSBbXTtcbiAgICBjb25zdCBmb2N1c2FibGVFbGVtZW50cyA9XG4gICAgICAgICdidXR0b24sIFtocmVmXSwgaW5wdXQsIHNlbGVjdCwgdGV4dGFyZWEsIFt0YWJpbmRleF06bm90KFt0YWJpbmRleD1cIi0xXCJdKSdcbiAgICA7XG5cbiAgICB3aW5kb3cuZ2V0TW9kYWxGb2N1c2FibGVFbGVtZW50cyA9IGZ1bmN0aW9uKCRtb2RhbFdpbmRvdyA9IG51bGwpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cubW9kYWwgPT09ICd1bmRlZmluZWQnICYmICh0eXBlb2YgJG1vZGFsV2luZG93ID09PSAndW5kZWZpbmVkJyB8fCAkbW9kYWxXaW5kb3cgPT09IG51bGwpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHR5cGVvZiB3aW5kb3cubW9kYWwgPT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiAkbW9kYWxXaW5kb3cgPT09ICdvYmplY3QnICYmICRtb2RhbFdpbmRvdyAhPT0gbnVsbCkgfHxcbiAgICAgICAgICAgICh0eXBlb2Ygd2luZG93Lm1vZGFsID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgJG1vZGFsV2luZG93ID09PSAnb2JqZWN0JyAmJiAkbW9kYWxXaW5kb3cgIT09IG51bGwpXG4gICAgICAgICkge1xuICAgICAgICAgICAgd2luZG93Lm1vZGFsID0gJG1vZGFsV2luZG93O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGZvY3VzYWJsZUNvbnRlbnQgPSBbXSxcbiAgICAgICAgICAgIG1vZGFsRm9jdXNhYmxlQ29udGVudCA9IHdpbmRvdy5tb2R
3580hbC5maW5kKGZvY3VzYWJsZUVsZW1lbnRzKVxuICAgICAgICA7XG5cbiAgICAgICAgbW9kYWxGb2N1c2FibGVDb250ZW50LmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBsZXQgJHRoaXMgPSAkKHRoaXMpO1xuXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgJHRoaXMuYXR0cigndHlwZScpID09PSAnaGlkZGVuJyB8fFxuICAgICAgICAgICAgICAgICR0aGlzLmNsb3Nlc3QoJy5nZmllbGRfdmlzaWJpbGl0eV9oaWRkZW4nKS5sZW5ndGggIT09IDAgfHxcbiAgICAgICAgICAgICAgICAkdGhpcy5jbG9zZXN0KCcuZ2Zvcm1faGlkZGVuJykubGVuZ3RoICE9PSAwXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5hdHRyKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG4gICAgICAgICAgICAgICAgJHRoaXMuYXR0cigndGFiaW5kZXgnLCAnLTEnKTtcblxuICAgICAgICAgICAgfSBlbHNlIGlmICgkdGhpcy5pcygnOnZpc2libGUnKSkge1xuICAgICAgICAgICAgICAgIGZvY3VzYWJsZUNvbnRlbnQucHVzaCgkKHRoaXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGZvY3VzYWJsZUNvbnRlbnQ7XG4gICAgfTtcblxuICAgIHdpbmRvdy5zZXRGb2N1c0luTW9kYWxXaW5kb3cgPSBmdW5jdGlvbihjbGVhckZvY3VzYWJsZUNvbnRlbnQgPSBmYWxzZSkge1xuICAgICAgICBpZiAoY2xlYXJGb2N1c2FibGVDb250ZW50ID09PSB0cnVlKSB7XG4gICAgICAgICAgICB3aW5kb3cubW9kYWwgPSAkKCdbZGF0YS1tb2RhbC1pZD1cIicgKyB3aW5kb3cubW9kYWxJZCArICdcIl0nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjbGVhckZvY3VzYWJsZUNvbnRlbnQgPT09IHRydWUgfHwgd2luZG93LmZvY3VzYWJsZUNvbnRlbnQgPT09IG51bGwgfHwgd2luZG93LmZvY3VzYWJsZUNvbnRlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB3aW5kb3cuZm9jdXNhYmxlQ29udGVudCA9IHdpbmRvdy5nZXRNb2RhbEZvY3VzYWJsZUVsZW1lbnRzKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAod2luZG93LmZvY3VzYWJsZUNvbnRlbnQgPT09IG51bGwgfHwgd2luZG93LmZvY3VzYWJsZUNvbnRlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbGFzdEZvY3VzYWJsZUVsZW1lbnQgPSB3aW5kb3cuZm9jdXNhYmxlQ29udGVudFt3aW5kb3cuZm9jdXNhYmxlQ29udGVudC5sZW5ndGggLSAxXTsgLy8gZ2V0IGxhc3QgZWxlbWVudCB0byBiZSBmb2N1c2VkIGluc2lkZSBtb2RhbFxuICAgICAgICBsZXQgZmlyc3RNb2RhbEZvY3VzYWJsZUVsZW1lbnQgPSB3aW5kb3cuZm9jdXNhYmxlQ29udGVudFswXTtcblxuICAgICAgICAkKGRvY3VtZW50KVxuICAgICAgICAgICAgLm9mZigna2V5ZG93bi5tb2RhbFRhYicpXG4gICAgICAgICAgICAub24oJ2tleWRvd24ubW9kYWxUYWInLCBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgICAgICAgIGxldCBpc1RhYlByZXNzZWQgPSBldmVudC5rZXkgPT09ICdUYWInIHx8IGV2ZW50LmtleUNvZGUgPT09IDk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzVGFiUHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5KSB7IC8vIGlmIHNoaWZ0IGtleSBwcmVzc2VkIGZvciBzaGlmdCArIHRhYiBjb21iaW5hdGlvblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PT0gZmlyc3RNb2RhbEZvY3VzYWJsZUVsZW1lbnRbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RGb2N1c2FibGVFbGVtZW50LmZvY3VzKCk7IC8vIGFkZCBmb2N1cyBmb3IgdGhlIGxhc3QgZm9jdXNhYmxlIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAvLyBpZiB0YWIga2V5IGlzIHByZXNzZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgPT09IGxhc3RGb2N1c2FibGVFbGVtZW50WzBdKSAgeyAvLyBpZiBmb2N1c2VkIGhhcyByZWFjaGVkIHRvIGxhc3QgZm9jdXNhYmxlIGVsZW1lbnQgdGhlbiBmb2N1cyBmaXJzdCBmb2N1c2FibGUgZWxlbWVudCBhZnRlciBwcmVzc2luZyB0YWJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0TW9kYWxGb2N1c2FibGVFbGVtZW50LmZvY3VzKCk7IC8vIGFkZCBmb2N1cyBmb3IgdGhlIGZpcnN0IGZvY3VzYWJsZSBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSlcbiAgICAgICAgO1xuXG4gICAgICAgIGxldCAkZ2ZGcm9tRm9jdXMgPSB3aW5kb3cubW9kYWwuZmluZCgnI2dmX2Zvcm1fZm9jdXMnKTtcbiAgICAgICAgaWYgKCRnZkZyb21Gb2N1cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGZpcnN0TW9kYWxGb2N1c2FibGVFbGVtZW50LmZvY3VzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRGb2N1c1RvRXJyb3JGaWVsZCgkZ2ZGcm9tRm9jdXMsIGZpcnN0TW9kYWxGb2N1c2FibGVFbGVtZW50KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAkKGRvY3VtZW50KVxuICAgICAgICAub24oJ3Nob3duLmJzLm1vZGFsJywgJy5tb2RhbCcsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgbGV0ICR0aGF0ID0gJCh0aGlzKTtcbiAgICAgICAgICAgICQoZG9jdW1lbnQuYm9keSkuYWRkQ2xhc3MoJ21vZGFsLW9wZW4nKTtcbiAgICAgICAgICAgIHdpbmRvdy5tb2RhbCA9ICR0aGF0O1xuICAgICAgICAgICAgd2luZG93Lm1vZGFsSWQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIHdpbmRvdy5tb2RhbC5hdHRyKCdkYXRhLW1vZGFsLWlkJywgd2luZG93Lm1vZGFsSWQpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHdpbmRvdy5tb2R
3580hbENhbGxlciA9PT0gXCJ1bmRlZmluZWRcIiB8fCB3aW5kb3cubW9kYWxDYWxsZXIgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGV2ZW50LnJlbGF0ZWRUYXJnZXQgIT09IFwidW5kZWZpbmVkXCIgJiYgZXZlbnQucmVsYXRlZFRhcmdldCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubW9kYWxDYWxsZXIgPSBldmVudC5yZWxhdGVkVGFyZ2V0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdy5tb2RhbENhbGxlckNsaWNrICE9PSBcInVuZGVmaW5lZFwiICYmIHdpbmRvdy5tb2RhbENhbGxlckNsaWNrICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tb2RhbENhbGxlciA9IHdpbmRvdy5tb2RhbENhbGxlckNsaWNrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgJHBhcmVudCA9ICR0aGF0O1xuICAgICAgICAgICAgY29uc3QgZXhjbHVkZVRhZ05hbWVzID0gW1xuICAgICAgICAgICAgICAgICdzY3JpcHQnLFxuICAgICAgICAgICAgICAgICdzdHlsZScsXG4gICAgICAgICAgICAgICAgJ25vc2NyaXB0J1xuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICBsZXQgJHNpYmxpbmdzID0gJHBhcmVudC5zaWJsaW5ncygpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCRzaWJsaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICRzaWJsaW5ncy5lYWNoKGZ1bmN0aW9uKGluZGV4LCBlbGVtKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWV4Y2x1ZGVUYWdOYW1lcy5pbmNsdWRlcyhlbGVtLnRhZ05hbWUudG9Mb3dlckNhc2UoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbS5oYXNBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbS5zZXRBdHRyaWJ1dGUoJ2RhdGEtYXJoaWRlJywgZWxlbS5nZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW0uc2V0QXR0cmlidXRlKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICRwYXJlbnQgPSAkcGFyZW50LnBhcmVudCgpO1xuXG4gICAgICAgICAgICB9ICB3aGlsZSAoJHBhcmVudFswXS50YWdOYW1lLnRvTG93ZXJDYXNlKCkgIT09ICdib2R5JylcblxuICAgICAgICB3aW5kb3cuc2V0Rm9jdXNJbk1vZGFsV2luZG93KHRydWUpO1xuICAgICAgICB9KVxuICAgICAgICAub24oJ2hpZGRlbi5icy5tb2RhbCcsICcubW9kYWwnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkKGRvY3VtZW50LmJvZHkpLnJlbW92ZUNsYXNzKCdtb2RhbC1vcGVuJyk7XG5cbiAgICAgICAgICAgIGlmICh3aW5kb3cubW9kYWxDYWxsZXIgIT09IG51bGwgJiYgdHlwZW9mIHdpbmRvdy5tb2RhbENhbGxlciAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5tb2RhbENhbGxlci5mb2N1cygpO1xuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubW9kYWxDYWxsZXIgPSBudWxsO1xuICAgICAgICAgICAgICAgIH0sIDMwMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHdpbmRvdy5tb2RhbCA9IG51bGw7XG4gICAgICAgICAgICB3aW5kb3cuZm9jdXNhYmxlQ29udGVudCA9IG51bGw7XG5cbiAgICAgICAgICAgIGxldCAkZWxlbXMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCdbYXJpYS1oaWRkZW49XCJ0cnVlXCJdJyk7XG5cbiAgICAgICAgICAgICRlbGVtcy5mb3JFYWNoKGVsZW0gPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlbGVtLmhhc0F0dHJpYnV0ZSgnZGF0YS1hcmhpZGUnKSkge1xuICAgICAgICAgICAgICAgICAgICBlbGVtLnNldEF0dHJpYnV0ZSgnYXJpYS1oaWRkZW4nLCBlbGVtLmdldEF0dHJpYnV0ZSgnZGF0YS1hcmhpZGUnKSk7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0ucmVtb3ZlQXR0cmlidXRlKCdkYXRhLWFyaGlkZScpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVsZW0ucmVtb3ZlQXR0cmlidXRlKCdhcmlhLWhpZGRlbicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgIDtcblxuICAgIGZ1bmN0aW9uIHNldEZvY3VzVG9FcnJvckZpZWxkKCRlbGVtZW50LCBmaXJzdE1vZGFsRm9jdXNhYmxlRWxlbWVudCkge1xuICAgICAgICBsZXQgZm9ybVdyYXBwZXIgPSAkZWxlbWVudC5wYXJlbnQoKTtcbiAgICAgICAgbGV0IGVycm9yRmllbGRXcmFwcGVyID0gJChmb3JtV3JhcHBlci5maW5kKCcuZ2ZpZWxkX2Vycm9yJylbMF0pO1xuXG4gICAgICAgIGlmIChlcnJvckZpZWxkV3JhcHBlcikge1xuICAgICAgICAgICAgbGV0ICRlbGVtV2l0aEVycm9yID0gZXJyb3JGaWVsZFdyYXBwZXIuZmluZCgnW2FyaWEtaW52YWxpZD1cInRydWVcIl06Zmlyc3QnKTtcblxuICAgICAgICAgICAgaWYgKCRlbGVtV2l0aEVycm9yLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyRlbGVtV2l0aEVycm9yLmZvY3VzKCk7fSwgMTAwKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtmaXJzdE1vZGFsRm9jdXNhYmxlRWxlbWVudC5mb2N1cygpO30sIDEwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAkKGRvY3VtZW50KS5vbignZ2Zvcm1fY29uZmlybWF0aW9uX2xvYWRlZCcsIGZ1bmN0aW9uKGV2ZW50LCBmb3JtX2lkKXtcbiAgICAgICAgd2luZG93LmZvY3VzYWJsZUNvbnRlbnQgPSBudWxsO1xuICAgICAgICB3aW5kb3cuc2V0Rm9jdXNJbk1vZGFsV2luZG93KHRydWUpO1xuICAgIH0pO1xuXG4gICAgJCgnI2dmX2Zvcm1fZm9jdXMnKS5vbignZm9jdXMnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgI
3580HNldEZvY3VzVG9FcnJvckZpZWxkKCQodGhpcykpO1xuICAgIH0pO1xuXG4gICAgJChkb2N1bWVudCkub24oJ2dmb3JtX3BhZ2VfbG9hZGVkJywgZnVuY3Rpb24oKXtcbiAgICAgICAgd2luZG93LmZvY3VzYWJsZUNvbnRlbnQgPSBudWxsO1xuICAgICAgICB3aW5kb3cuc2V0Rm9jdXNJbk1vZGFsV2luZG93KHRydWUpO1xuICAgIH0pO1xuXG59KTtcbiIsIi8qXG4qICAgVGhpcyBjb250ZW50IGlzIGxpY2Vuc2VkIGFjY29yZGluZyB0byB0aGUgVzNDIFNvZnR3YXJlIExpY2Vuc2UgYXRcbiogICBodHRwczovL3d3dy53My5vcmcvQ29uc29ydGl1bS9MZWdhbC8yMDE1L2NvcHlyaWdodC1zb2Z0d2FyZS1hbmQtZG9jdW1lbnRcbiovXG52YXIgTWVudUl0ZW0gPSBmdW5jdGlvbiAoZG9tTm9kZSwgbWVudU9iaikge1xuXG4gICAgdmFyIHBvcHVwT2JqO1xuICAgIGlmICh0eXBlb2YgcG9wdXBPYmogIT09ICdvYmplY3QnKSB7XG4gICAgICAgIHBvcHVwT2JqID0gZmFsc2U7XG4gICAgfVxuXG4gICAgdGhpcy5kb21Ob2RlID0gZG9tTm9kZTtcbiAgICB0aGlzLm1lbnUgPSBtZW51T2JqO1xuICAgIHRoaXMucG9wdXBNZW51ID0gZmFsc2U7XG4gICAgdGhpcy5pc01lbnViYXJJdGVtID0gZmFsc2U7XG5cbiAgICB0aGlzLmtleUNvZGUgPSBPYmplY3QuZnJlZXplKHtcbiAgICAgICAgJ1RBQic6IDksXG4gICAgICAgICdFU0MnOiAyNyxcbiAgICAgICAgJ1NQQUNFJzogMzIsXG4gICAgICAgICdQQUdFVVAnOiAzMyxcbiAgICAgICAgJ1BBR0VET1dOJzogMzQsXG4gICAgICAgICdFTkQnOiAzNSxcbiAgICAgICAgJ0hPTUUnOiAzNixcbiAgICAgICAgJ0xFRlQnOiAzNyxcbiAgICAgICAgJ1VQJzogMzgsXG4gICAgICAgICdSSUdIVCc6IDM5LFxuICAgICAgICAnRE9XTic6IDQwXG4gICAgfSk7XG59O1xuXG5NZW51SXRlbS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRvbU5vZGUudGFiSW5kZXggPSAtMTtcblxuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVLZXlkb3duLmJpbmQodGhpcykpO1xuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMuaGFuZGxlQ2xpY2suYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ2ZvY3VzJywgdGhpcy5oYW5kbGVGb2N1cy5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHRoaXMuaGFuZGxlQmx1ci5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdmVyJywgdGhpcy5oYW5kbGVNb3VzZW92ZXIuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5kb21Ob2RlLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlb3V0JywgdGhpcy5oYW5kbGVNb3VzZW91dC5iaW5kKHRoaXMpKTtcblxuICAgIC8vIEluaXRpYWxpemUgZmx5b3V0IG1lbnVcblxuICAgIHZhciBuZXh0RWxlbWVudCA9IHRoaXMuZG9tTm9kZS5uZXh0RWxlbWVudFNpYmxpbmc7XG5cbiAgICBpZiAobmV4dEVsZW1lbnQgJiYgbmV4dEVsZW1lbnQudGFnTmFtZSA9PT0gJ1VMJykge1xuICAgICAgICB0aGlzLnBvcHVwTWVudSA9IG5ldyBQb3B1cE1lbnUobmV4dEVsZW1lbnQsIHRoaXMpO1xuICAgICAgICB0aGlzLnBvcHVwTWVudS5pbml0KCk7XG4gICAgfVxuXG59O1xuXG5NZW51SXRlbS5wcm90b3R5cGUuaXNFeHBhbmRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5kb21Ob2RlLmdldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcpID09PSAndHJ1ZSc7XG59O1xuXG4vKiBFVkVOVCBIQU5ETEVSUyAqL1xuXG5NZW51SXRlbS5wcm90b3R5cGUuaGFuZGxlS2V5ZG93biA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciB0Z3QgID0gZXZlbnQuY3VycmVudFRhcmdldCxcbiAgICAgICAgY2hhciA9IGV2ZW50LmtleSxcbiAgICAgICAgZmxhZyA9IGZhbHNlLFxuICAgICAgICBjbGlja0V2ZW50O1xuXG4gICAgZnVuY3Rpb24gaXNQcmludGFibGVDaGFyYWN0ZXIgKHN0cikge1xuICAgICAgICByZXR1cm4gc3RyLmxlbmd0aCA9PT0gMSAmJiBzdHIubWF0Y2goL1xcUy8pO1xuICAgIH1cblxuICAgIHN3aXRjaCAoZXZlbnQua2V5Q29kZSkge1xuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5VUDpcbiAgICAgICAgICAgIHRoaXMubWVudS5zZXRGb2N1c1RvUHJldmlvdXNJdGVtKHRoaXMpO1xuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5ET1dOOlxuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9OZXh0SXRlbSh0aGlzKTtcbiAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuTEVGVDpcbiAgICAgICAgICAgIHRoaXMubWVudS5zZXRGb2N1c1RvQ29udHJvbGxlcigncHJldmlvdXMnLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMubWVudS5jbG9zZSh0cnVlKTtcbiAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuUklHSFQ6XG4gICAgICAgICAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBvcHVwTWVudS5vcGVuKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5wb3B1cE1lbnUuc2V0Rm9jdXNUb0ZpcnN0SXRlbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9Db250cm9sbGVyKCduZXh0JywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LmNsb3NlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5IT01FOlxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5QQUdFVVA6XG4gICAgICAgICAgICB0aGlzLm1lbnUuc2V0Rm9jdXNUb0ZpcnN0SXRlbSgpO1xuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5FTkQ6XG4gICAgICAgIGNhc2UgdGhpcy5rZXlDb2RlLlBBR0VET1dOOlxuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9MYXN0SXRlbSgpO1xuICAgICAgICAgICAgZmxhZyA9IHRydWU7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIHRoaXMua2V5Q29kZS5FU0M6XG4gICAgICAgICAgICB0aGlzLm1lbnUuc2V0Rm9jdXNUb0NvbnRyb2xsZXIoKTtcbiAgICAgICAgICAgI
3580HRoaXMubWVudS5jbG9zZSh0cnVlKTtcbiAgICAgICAgICAgIGZsYWcgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuU1BBQ0U6XG4gICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuZG9tTm9kZS5jbGljaygpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSB0aGlzLmtleUNvZGUuVEFCOlxuICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzVG9Db250cm9sbGVyKCk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgaWYgKGlzUHJpbnRhYmxlQ2hhcmFjdGVyKGNoYXIpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZW51LnNldEZvY3VzQnlGaXJzdENoYXJhY3Rlcih0aGlzLCBjaGFyKTtcbiAgICAgICAgICAgICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGlmIChmbGFnKSB7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbn07XG5cbk1lbnVJdGVtLnByb3RvdHlwZS5zZXRFeHBhbmRlZCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgICB0aGlzLmRvbU5vZGUuc2V0QXR0cmlidXRlKCdhcmlhLWV4cGFuZGVkJywgJ3RydWUnKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHRoaXMuZG9tTm9kZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgICB9XG59O1xuXG5NZW51SXRlbS5wcm90b3R5cGUuaGFuZGxlQ2xpY2sgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuc2V0Rm9jdXNUb0NvbnRyb2xsZXIoKTtcbiAgICB0aGlzLm1lbnUuY2xvc2UodHJ1ZSk7XG59O1xuXG5NZW51SXRlbS5wcm90b3R5cGUuaGFuZGxlRm9jdXMgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzRm9jdXMgPSB0cnVlO1xufTtcblxuTWVudUl0ZW0ucHJvdG90eXBlLmhhbmRsZUJsdXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB0aGlzLm1lbnUuaGFzRm9jdXMgPSBmYWxzZTtcbiAgICBzZXRUaW1lb3V0KHRoaXMubWVudS5jbG9zZS5iaW5kKHRoaXMubWVudSwgZmFsc2UpLCAzMDApO1xufTtcblxuTWVudUl0ZW0ucHJvdG90eXBlLmhhbmRsZU1vdXNlb3ZlciA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgIHRoaXMubWVudS5
3580oYXNIb3ZlciA9IHRydWU7XG4gICAgdGhpcy5tZW51Lm9wZW4oKTtcbiAgICBpZiAodGhpcy5wb3B1cE1lbnUpIHtcbiAgICAgICAgdGhpcy5wb3B1cE1lbnUuaGFzSG92ZXIgPSB0cnVlO1xuICAgICAgICB0aGlzLnBvcHVwTWVudS5vcGVuKCk7XG4gICAgfVxufTtcblxuTWVudUl0ZW0ucHJvdG90eXBlLmhhbmRsZU1vdXNlb3V0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgaWYgKHRoaXMucG9wdXBNZW51KSB7XG4gICAgICAgIHRoaXMucG9wdXBNZW51Lmhhc0hvdmVyID0gZmFsc2U7XG4gICAgICAgIHRoaXMucG9wdXBNZW51LmNsb3NlKHRydWUpO1xuICAgIH1cblxuICAgIHRoaXMubWVudS5oYXNIb3ZlciA9IGZhbHNlO1xuICAgIHNldFRpbWVvdXQodGhpcy5tZW51LmNsb3NlLmJpbmQodGhpcy5tZW51LCBmYWxzZSksIDMwMCk7XG59O1xuIiwiLypcbiogICBUaGlzIGNvbnRlbnQgaXMgbGljZW5zZWQgYWNjb3JkaW5nIHRvIHRoZSBXM0MgU29mdHdhcmUgTGljZW5zZSBhdFxuKiAgIGh0dHBzOi8vd3d3LnczLm9yZy9Db25zb3J0aXVtL0xlZ2FsLzIwMTUvY29weXJpZ2h0LXNvZnR3YXJlLWFuZC1kb2N1bWVudFxuKi9cbnZhciBQb3B1cE1lbnUgPSBmdW5jdGlvbiAoZG9tTm9kZSwgY29udHJvbGxlck9iaikge1xuICAgIHZhciBlbGVtZW50Q2hpbGRyZW4sXG4gICAgICAgIG1zZ1ByZWZpeCA9ICdQb3B1cE1lbnUgY29uc3RydWN0b3IgYXJndW1lbnQgZG9tTm9kZSAnO1xuXG4gICAgLy8gQ2hlY2sgd2hldGhlciBkb21Ob2RlIGlzIGEgRE9NIGVsZW1lbnRcbiAgICBpZiAoIWRvbU5vZGUgaW5zdGFuY2VvZiBFbGVtZW50KSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IobXNnUHJlZml4ICsgJ2lzIG5vdCBhIERPTSBFbGVtZW50LicpO1xuICAgIH1cbiAgICAvLyBDaGVjayB3aGV0aGVyIGRvbU5vZGUgaGFzIGNoaWxkIGVsZW1lbnRzXG4gICAgaWYgKGRvbU5vZGUuY2hpbGRFbGVtZW50Q291bnQgPT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZ1ByZWZpeCArICdoYXMgbm8gZWxlbWVudCBjaGlsZHJlbi4nKTtcbiAgICB9XG4gICAgLy8gQ2hlY2sgd2hldGhlciBkb21Ob2RlIGRlc2NlbmRhbnQgZWxlbWVudHMgaGF2ZSBBIGVsZW1lbnRzXG4gICAgdmFyIGNoaWxkRWxlbWVudCA9IGRvbU5vZGUuZmlyc3RFbGVtZW50Q2hpbGQ7XG4gICAgd2hpbGUgKGNoaWxkRWxlbWVudCkge1xuICAgICAgICB2Y
3580XIgbWVudWl0ZW0gPSBjaGlsZEVsZW1lbnQuZmlyc3RFbGVtZW50Q2hpbGQ7XG4gICAgICAgIGlmIChtZW51aXRlbSAmJiBtZW51aXRlbSA9PT0gJ0EnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnUHJlZml4ICsgJ2hhcyBkZXNjZW5kYW50IGVsZW1lbnRzIHRoYXQgYXJlIG5vdCBBIGVsZW1lbnRzLicpO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkRWxlbWVudCA9IGNoaWxkRWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmc7XG4gICAgfVxuXG4gICAgdGhpcy5pc01lbnViYXIgPSBmYWxzZTtcblxuICAgIHRoaXMuZG9tTm9kZSAgICA9IGRvbU5vZGU7XG4gICAgdGhpcy5jb250cm9sbGVyID0gY29udHJvbGxlck9iajtcblxuICAgIHRoaXMubWVudWl0ZW1zID0gW107IC8vIFNlZSBQb3B1cE1lbnUgaW5pdCBtZXRob2RcbiAgICB0aGlzLmZpcnN0Q2hhcnMgPSBbXTsgLy8gU2VlIFBvcHVwTWVudSBpbml0IG1ldGhvZFxuXG4gICAgdGhpcy5maXJzdEl0ZW0gPSBudWxsOyAvLyBTZWUgUG9wdXBNZW51IGluaXQgbWV0aG9kXG4gICAgdGhpcy5sYXN0SXRlbSA9IG51bGw7IC8vIFNlZSBQb3B1cE1lbnUgaW5pdCBtZXRob2RcblxuICAgIHRoaXMuaGFzRm9jdXMgPSBmYWxzZTsgLy8gU2VlIE1lbnVJdGVtIGhhbmRsZUZvY3VzLCBoYW5kbGVCbHVyXG4gICAgdGhpcy5oYXNIb3ZlciA9IGZhbHNlOyAvLyBTZWUgUG9wdXBNZW51IGhhbmRsZU1vdXNlb3ZlciwgaGFuZGxlTW91c2VvdXRcbn07XG5cbi8qXG4qICAgQG1ldGhvZCBQb3B1cE1lbnUucHJvdG90eXBlLmluaXRcbipcbiogICBAZGVzY1xuKiAgICAgICBBZGQgZG9tTm9kZSBldmVudCBsaXN0ZW5lcnMgZm9yIG1vdXNlb3ZlciBhbmQgbW91c2VvdXQuIFRyYXZlcnNlXG4qICAgICAgIGRvbU5vZGUgY2hpbGRyZW4gdG8gY29uZmlndXJlIGVhY2ggbWVudWl0ZW0gYW5kIHBvcHVsYXRlIG1lbnVpdGVtc1xuKiAgICAgICBhcnJheS4gSW5pdGlhbGl6ZSBmaXJzdEl0ZW0gYW5kIGxhc3RJdGVtIHByb3BlcnRpZXMuXG4qL1xuUG9wdXBNZW51LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBjaGlsZEVsZW1lbnQsIG1lbnVFbGVtZW50LCBtZW51SXRlbSwgdGV4dENvbnRlbnQsIG51bUl0ZW1zLCBsYWJlbDtcblxuICAgIC8vIENvbmZpZ3VyZSB0aGUgZG9tTm9kZSBpdHNlbGZcblxuICAgIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW92ZXInLCB0aGlzLmhhbmRsZU1vdXNlb3Zlci5iaW5kKHRoaXMpKTtcbiAgICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VvdXQnLCB0aGlzLmhhbmRsZU1vdXNlb3V0LmJpbmQodGhpcykpO1xuXG4gICAgLy8gVHJhdmVyc2UgdGhlIGVsZW1lbnQgY2hpbGRyZW4gb2YgZG9tTm9kZTogY29uZmlndXJlIGVhY2ggd2l0aFxuICAgIC8vIG1lbnVpdGVtIHJvbGUgYmVoYXZpb3IgYW5kIHN0b3JlIHJlZmVyZW5jZSBpbiBtZW51aXRlbXMgYXJyYXkuXG4gICAgY2hpbGRFbGVtZW50ID0gdGhpcy5kb21Ob2RlLmZpcnN0RWxlbWVudENoaWxkO1xuXG4gICAgd2hpbGUgKGNoaWxkRWxlbWVudCkge1xuICAgICAgICBtZW51RWxlbWVudCA9IGNoaWxkRWxlbWVudC5maXJzdEVsZW1lbnRDaGlsZDtcblxuICAgICAgICBpZiAobWVudUVsZW1lbnQgJiYgbWVudUVsZW1lbnQudGFnTmFtZSA9PT0gJ0EnKSB7XG4gICAgICAgICAgICBtZW51SXRlbSA9IG5ldyBNZW51SXRlbShtZW51RWxlbWVudCwgdGhpcyk7XG4gICAgICAgICAgICBtZW51SXRlbS5pbml0KCk7XG4gICAgICAgICAgICB0aGlzLm1lbnVpdGVtcy5wdXNoKG1lbnVJdGVtKTtcbiAgICAgICAgICAgIHRleHRDb250ZW50ID0gbWVudUVsZW1lbnQudGV4dENvbnRlbnQudHJpbSgpO1xuICAgICAgICAgICAgdGhpcy5maXJzdENoYXJzLnB1c2godGV4dENvbnRlbnQuc3Vic3RyaW5nKDAsIDEpLnRvTG93ZXJDYXNlKCkpO1xuICAgICAgICB9XG4gICAgICAgIGNoaWxkRWxlbWVudCA9IGNoaWxkRWxlbWVudC5uZXh0RWxlbWVudFNpYmxpbmc7XG4gICAgfVxuXG4gICAgLy8gVXNlIHBvcHVsYXRlZCBtZW51aXRlbXMgYXJyYXkgdG8gaW5pdGlhbGl6ZSBmaXJzdEl0ZW0gYW5kIGxhc3RJdGVtLlxuICAgIG51bUl0ZW1zID0gdGhpcy5tZW51aXRlbXMubGVuZ3RoO1xuICAgIGlmIChudW1JdGVtcyA+IDApIHtcbiAgICAgICAgdGhpcy5maXJzdEl0ZW0gPSB0aGlzLm1lbnVpdGVtc1sgMCBdO1xuICAgICAgICB0aGlzLmxhc3RJdGVtID0gdGhpcy5tZW51aXRlbXNbIG51bUl0ZW1zIC0gMSBdO1xuICAgIH1cbn07XG5cbi8qIEVWRU5UIEhBTkRMRVJTICovXG5cblBvcHVwTWVudS5wcm90b3R5cGUuaGFuZGxlTW91c2VvdmVyID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5oYXNIb3ZlciA9IHRydWU7XG59O1xuXG5Qb3B1cE1lbnUucHJvdG90eXBlLmhhbmRsZU1vdXNlb3V0ID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdGhpcy5oYXNIb3ZlciA9IGZhbHNlO1xuICAgIHNldFRpbWVvdXQodGhpcy5jbG9zZS5iaW5kKHRoaXMsIGZhbHNlKSwgMSk7XG59O1xuXG4vKiBGT0NVUyBNQU5BR0VNRU5UIE1FVEhPRFMgKi9cblxuUG9wdXBNZW51LnByb3RvdHlwZS5zZXRGb2N1c1RvQ29udHJvbGxlciA9IGZ1bmN0aW9uIChjb21tYW5kLCBmbGFnKSB7XG5cbiAgICBpZiAodHlwZW9mIGNvbW1hbmQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbW1hbmQgPSAnJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRGb2N1c1RvTWVudWJhckl0ZW0gKGNvbnRyb2xsZXIsIGNsb3NlKSB7XG4gICAgICAgIHdoaWxlIChjb250cm9sbGVyKSB7XG4gICAgICAgICAgICBpZiAoY29udHJvbGxlci5pc01lbnViYXJJdGVtKSB7XG4gICAgICAgICAgICAgICAgY29udHJvbGxlci5kb21Ob2RlLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRyb2xsZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoY2xvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlci5tZW51LmNsb3NlKHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb250cm9sbGVyLmhhc0ZvY3VzID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb250cm9sbGVyID0gY29udHJvbGxlci5tZW51LmNvbnRyb2xsZXI7XG4gICAgICAgI
3580H1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChjb21tYW5kID09PSAnJykge1xuICAgICAgICBpZiAodGhpcy5jb250cm9sbGVyICYmIHRoaXMuY29udHJvbGxlci5kb21Ob2RlKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIuZG9tTm9kZS5mb2N1cygpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY29udHJvbGxlci5pc01lbnViYXJJdGVtKSB7XG4gICAgICAgIHRoaXMuY29udHJvbGxlci5kb21Ob2RlLmZvY3VzKCk7XG4gICAgICAgIHRoaXMuY2xvc2UoKTtcblxuICAgICAgICBpZiAoY29tbWFuZCA9PT0gJ25leHQnKSB7XG4gICAgICAgICAgICB2YXIgbWVudWJhckl0ZW0gPSBzZXRGb2N1c1RvTWVudWJhckl0ZW0odGhpcy5jb250cm9sbGVyLCBmYWxzZSk7XG4gICAgICAgICAgICBpZiAobWVudWJhckl0ZW0pIHtcbiAgICAgICAgICAgICAgICBtZW51YmFySXRlbS5tZW51LnNldEZvY3VzVG9OZXh0SXRlbShtZW51YmFySXRlbSwgZmxhZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmIChjb21tYW5kID09PSAncHJldmlvdXMnKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIubWVudS5zZXRGb2N1c1RvUHJldmlvdXNJdGVtKHRoaXMuY29udHJvbGxlciwgZmxhZyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29tbWFuZCA9PT0gJ25leHQnKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXIubWVudS5zZXRGb2N1c1RvTmV4dEl0ZW0odGhpcy5jb250cm9sbGVyLCBmbGFnKTtcbiAgICAgICAgfVxuICAgIH1cblxufTtcblxuUG9wdXBNZW51LnByb3RvdHlwZS5zZXRGb2N1c1RvRmlyc3RJdGVtID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZmlyc3RJdGVtLmRvbU5vZGUuZm9jdXMoKTtcbn07XG5cblBvcHVwTWVudS5wcm90b3R5cGUuc2V0Rm9jdXNUb0xhc3RJdGVtID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMubGFzdEl0ZW0uZG9tTm9kZS5mb2N1cygpO1xufTtcblxuUG9wdXBNZW51LnByb3RvdHlwZS5zZXRGb2N1c1RvUHJldmlvdXNJdGVtID0gZnVuY3Rpb24gKGN1cnJlbnRJdGVtKSB7XG4gICAgdmFyIGluZGV4O1xuXG4gICAgaWYgKGN1cnJlbnRJdGVtID09PSB0aGlzLmZpcnN0SXRlbSkge1xuICAgICAgICB0aGlzLmxhc3RJdGVtLmRvbU5vZGUuZm9jdXMoKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGluZGV4ID0gdGhpcy5tZW51aXRlbXMuaW5kZXhPZihjdXJyZW50SXRlbSk7XG4gICAgICAgIHRoaXMubWVudWl0ZW1zWyBpbmRleCAtIDEgXS5kb21Ob2RlLmZvY3VzKCk7XG4gICAgfVxufTtcblxuUG9wdXBNZW51LnByb3RvdHlwZS5zZXRGb2N1c1RvTmV4dEl0ZW0gPSBmdW5jdGlvbiAoY3VycmVudEl0ZW0pIHtcbiAgICB2YXIgaW5kZXg7XG5cbiAgICBpZiAoY3VycmVudEl0ZW0gPT09IHRoaXMubGFzdEl0ZW0pIHtcbiAgICAgICAgdGhpcy5maXJzdEl0ZW0uZG9tTm9kZS5mb2N1cygpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaW5kZXggPSB0aGlzLm1lbnVpdGVtcy5pbmRleE9mKGN1cnJlbnRJdGVtKTtcbiAgICAgICAgdGhpcy5tZW51aXRlbXNbIGluZGV4ICsgMSBdLmRvbU5vZGUuZm9jdXMoKTtcbiAgICB9XG59O1xuXG5Qb3B1cE1lbnUucHJvdG90eXBlLnNldEZvY3VzQnlGaXJzdENoYXJhY3RlciA9IGZ1bmN0aW9uIChjdXJyZW50SXRlbSwgY2hhcikge1xuICAgIHZhciBzdGFydCwgaW5kZXgsIGNoYXIgPSBjaGFyLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAvLyBHZXQgc3RhcnQgaW5kZXggZm9yIHNlYXJjaCBiYXNlZCBvbiBwb3NpdGlvbiBvZiBjdXJyZW50SXRlbVxuICAgIHN0YXJ0ID0gdGhpcy5tZW51aXRlbXMuaW5kZXhPZihjdXJyZW50SXRlbSkgKyAxO1xuICAgIGlmIChzdGFydCA9PT0gdGhpcy5tZW51aXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHN0YXJ0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDaGVjayByZW1haW5pbmcgc2xvdHMgaW4gdGhlIG1lbnVcbiAgICBpbmRleCA9IHRoaXMuZ2V0SW5kZXhGaXJzdENoYXJzKHN0YXJ0LCBjaGFyKTtcblxuICAgIC8vIElmIG5vdCBmb3VuZCBpbiByZW1haW5pbmcgc2xvdHMsIGNoZWNrIGZyb20gYmVnaW5uaW5nXG4gICAgaWYgKGluZGV4ID09PSAtMSkge1xuICAgICAgICBpbmRleCA9IHRoaXMuZ2V0SW5kZXhGaXJzdENoYXJzKDAsIGNoYXIpO1xuICAgIH1cblxuICAgIC8vIElmIG1hdGNoIHdhcyBmb3VuZC4uLlxuICAgIGlmIChpbmRleCA+IC0xKSB7XG4gICAgICAgIHRoaXMubWVudWl0ZW1zWyBpbmRleCBdLmRvbU5vZGUuZm9jdXMoKTtcbiAgICB9XG59O1xuXG5Qb3B1cE1lbnUucHJvdG90eXBlLmdldEluZGV4Rmlyc3RDaGFycyA9IGZ1bmN0aW9uIChzdGFydEluZGV4LCBjaGFyKSB7XG4gICAgZm9yICh2YXIgaSA9IHN0YXJ0SW5kZXg7IGkgPCB0aGlzLmZpcnN0Q2hhcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGNoYXIgPT09IHRoaXMuZmlyc3RDaGFyc1sgaSBdKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG59O1xuXG4vKiBNRU5VIERJU1BMQVkgTUVUSE9EUyAqL1xuXG5Qb3B1cE1lbnUucHJvdG90eXBlLm9wZW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuZG9tTm9kZS5wYXJlbnRFbGVtZW50LmNsYXNzTGlzdC5jb250YWlucygnbWVnYS1tZW51LWNvbCcpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gR2V0IHBvc2l0aW9uIGFuZCBib3VuZGluZyByZWN0YW5nbGUgb2YgY29udHJvbGxlciBvYmplY3QncyBET00gbm9kZVxuICAgIHZhciByZWN0ID0gdGhpcy5jb250cm9sbGVyLmRvbU5vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAvLyBTZXQgQ1NTIHByb3BlcnRpZXNcbiAgICBpZiAoIXRoaXMuY29udHJvbGxlci5pc01lbnViYXJJdGVtKSB7XG4gICAgICAgIHRoaXMuZG9tTm9kZS5wYXJlbnROb2RlLnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJztcbiAgICAgICAgdGhpcy5kb21Ob2RlLnN0eWxlLmRpc3BsYXkgPSAnYmxvY2snO1xuICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUubGVmdCA9IHJlY3Qud2lkdGggKyAncHgnO1xuICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUuekluZGV4ID0gMTAwO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuZG9tTm9kZS5jbGFzc0xpc3QuY29udGFpbnMoJ2dyaWQtLWZsZXgnKSkge1xuICAgICAgICAgICAgdGhpcy5kb21Ob2RlLnN0eWxlLmRpc3BsYXkgPSAnZmxleCc7XG4gICAgICAgI
3580H0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUudG9wID0gKHJlY3QuaGVpZ2h0IC0gMSkgKyAncHgnO1xuXG4gICAgICAgIGlmICh0aGlzLmRvbU5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdncmlkLS1mbGV4JykpIHtcbiAgICAgICAgICAgIHRoaXMuZG9tTm9kZS5zdHlsZS50b3AgPSAocmVjdC5oZWlnaHQgLSAxICsgdGhpcy5kb21Ob2RlLnBhcmVudE5vZGUub2Zmc2V0VG9wKSArICdweCc7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kb21Ob2RlLnN0eWxlLnpJbmRleCA9IDEwMDtcbiAgICB9XG5cbiAgICB0aGlzLmNvbnRyb2xsZXIuc2V0RXhwYW5kZWQodHJ1ZSk7XG5cbn07XG5cblBvcHVwTWVudS5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbiAoZm9yY2UpIHtcbiAgICBpZiAodGhpcy5kb21Ob2RlLnBhcmVudEVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdtZWdhLW1lbnUtY29sJykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBjb250cm9sbGVySGFzSG92ZXIgPSB0aGlzLmNvbnRyb2xsZXIuaGFzSG92ZXI7XG4gICAgdmFyIGhhc0ZvY3VzID0gdGhpcy5oYXNGb2N1cztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5tZW51aXRlbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG1pID0gdGhpcy5tZW51aXRlbXNbaV07XG4gICAgICAgIGlmIChtaS5wb3B1cE1lbnUpIHtcbiAgICAgICAgICAgIGhhc0ZvY3VzID0gaGFzRm9jdXMgfCBtaS5wb3B1cE1lbnUuaGFzRm9jdXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY29udHJvbGxlci5pc01lbnViYXJJdGVtKSB7XG4gICAgICAgIGNvbnRyb2xsZXJIYXNIb3ZlciA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChmb3JjZSB8fCAoIWhhc0ZvY3VzICYmICF0aGlzLmhhc0hvdmVyICYmICFjb250cm9sbGVySGFzSG92ZXIpKSB7XG4gICAgICAgIHRoaXMuZG9tTm9kZS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICB0aGlzLmRvbU5vZGUuc3R5bGUuekluZGV4ID0gMDtcbiAgICAgICAgdGhpcy5jb250cm9sbGVyLnNldEV4cGFuZGVkKGZhbHNlKTtcbiAgICB9XG59O1xuXG4iLCJ2YXIgUmFkaW9CdXR0b24gPSBmdW5jdGlvbiAoZG9tTm9kZSwgZ3JvdXBPYmopIHtcblxuICB0aGlzLmRvbU5vZGUgPSBkb21Ob2RlO1xuICB0aGlzLnJhZGlvR3JvdXAgPSBncm91cE9iajtcblxuICB0aGlzLmtleUNvZGUgPSBPYmplY3QuZnJlZXplKHtcbiAgICAnUkVUVVJOJzogMTMsXG4gICAgJ1NQQUNFJzogMzIsXG4gICAgJ0VORCc6IDM1LFxuICAgICdIT01FJzogMzYsXG4gICAgJ0xFRlQnOiAzNyxcbiAgICAnVVAnOiAzOCxcbiAgICAnUklHSFQnOiAzOSxcbiAgICAnRE9XTic6IDQwXG4gIH0pO1xufTtcblxuUmFkaW9CdXR0b24ucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gIGlmICghdGhpcy5kb21Ob2RlLmNsYXNzTGlzdC5jb250YWlucygnYWN0aXZlJykpIHtcbiAgICB0aGlzLmRvbU5vZGUudGFiSW5kZXggPSAtMTtcbiAgICB0aGlzLmRvbU5vZGUuc2V0QXR0cmlidXRlKCdhcmlhLWNoZWNrZWQnLCAnZmFsc2UnKTtcbiAgfVxuXG4gIHRoaXMuZG9tTm9kZS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5oYW5kbGVLZXlkb3duLmJpbmQodGhpcykpO1xuICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCB0aGlzLmhhbmRsZUNsaWNrLmJpbmQodGhpcykpO1xuICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmhhbmRsZUZvY3VzLmJpbmQodGhpcykpO1xuICB0aGlzLmRvbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHRoaXMuaGFuZGxlQmx1ci5iaW5kKHRoaXMpKTtcblxufTtcblxuLyogRVZFTlQgSEFORExFUlMgKi9cblxuUmFkaW9CdXR0b24ucHJvdG90eXBlLmhhbmRsZUtleWRvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgdmFyIHRndCA9IGV2ZW50LmN1cnJlbnRUYXJnZXQsXG4gICAgZmxhZyA9IGZhbHNlLFxuICAgIGNsaWNrRXZlbnQ7XG5cbiAgc3dpdGNoIChldmVudC5rZXlDb2RlKSB7XG4gICAgY2FzZSB0aGlzLmtleUNvZGUuU1BBQ0U6XG4gICAgY2FzZSB0aGlzLmtleUNvZGUuUkVUVVJOOlxuICAgICAgdGhpcy5yYWRpb0dyb3VwLnNldENoZWNrZWQodGhpcyk7XG4gICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSB0aGlzLmtleUNvZGUuVVA6XG4gICAgICB0aGlzLnJhZGlvR3JvdXAuc2V0Q2hlY2tlZFRvUHJldmlvdXNJdGVtKHRoaXMpO1xuICAgICAgZmxhZyA9IHRydWU7XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgdGhpcy5rZXlDb2RlLkRPV046XG4gICAgICB0aGlzLnJhZGlvR3JvdXAuc2V0Q2hlY2tlZFRvTmV4dEl0ZW0odGhpcyk7XG4gICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSB0aGlzLmtleUNvZGUuTEVGVDpcbiAgICAgIHRoaXMucmFkaW9Hcm91cC5zZXRDaGVja2VkVG9QcmV2aW91c0l0ZW0odGhpcyk7XG4gICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSB0aGlzLmtleUNvZGUuUklHSFQ6XG4gICAgICB0aGlzLnJhZGlvR3JvdXAuc2V0Q2hlY2tlZFRvTmV4dEl0ZW0odGhpcyk7XG4gICAgICBmbGFnID0gdHJ1ZTtcbiAgICAgIGJyZWFrO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIGJyZWFrO1xuICB9XG5cbiAgaWYgKGZsYWcpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG59O1xuXG5SYWRpb0J1dHRvbi5wcm90b3R5cGUuaGFuZGxlQ2xpY2sgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgdGhpcy5yYWRpb0dyb3VwLnNldENoZWNrZWQodGhpcyk7XG59O1xuXG5SYWRpb0J1dHRvbi5wcm90b3R5cGUuaGFuZGxlRm9jdXMgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgdGhpcy5kb21Ob2RlLmNsYXNzTGlzdC5hZGQoJ2ZvY3VzJyk7XG59O1xuXG5SYWRpb0J1dHRvbi5wcm90b3R5cGUuaGFuZGxlQmx1ciA9IGZ1bmN0aW9uIChldmVudCkge1xuICB0aGlzLmRvbU5vZGUuY2xhc3NMaXN0LnJlbW92ZSgnZm9jdXMnKTtcbn07XG5cbnZhciBSYWRpb0dyb3VwID0gZnVuY3Rpb24gKGRvbU5vZGUp
3580IHtcblxuICB0aGlzLmRvbU5vZGUgPSBkb21Ob2RlO1xuXG4gIHRoaXMucmFkaW9CdXR0b25zID0gW107XG5cbiAgdGhpcy5maXJzdFJhZGlvQnV0dG9uID0gbnVsbDtcbiAgdGhpcy5sYXN0UmFkaW9CdXR0b24gPSBudWxsO1xuXG59O1xuXG5SYWRpb0dyb3VwLnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuXG4gIC8vIGluaXRpYWxpemUgcG9wIHVwIG1lbnVzXG4gIGlmICghdGhpcy5kb21Ob2RlLmdldEF0dHJpYnV0ZSgncm9sZScpKSB7XG4gICAgdGhpcy5kb21Ob2RlLnNldEF0dHJpYnV0ZSgncm9sZScsICdyYWRpb2dyb3VwJyk7XG4gIH1cblxuICB2YXIgcmJzID0gdGhpcy5kb21Ob2RlLnF1ZXJ5U2VsZWN0b3JBbGwoJ1tyb2xlPXJhZGlvXScpO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcmJzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHJiID0gbmV3IFJhZGlvQnV0dG9uKHJic1tpXSwgdGhpcyk7XG4gICAgcmIuaW5pdCgpO1xuICAgIHRoaXMucmFkaW9CdXR0b25zLnB1c2gocmIpO1xuXG4gICAgaWYgKCF0aGlzLmZpcnN0UmFkaW9CdXR0b24pIHtcbiAgICAgIHRoaXMuZmlyc3RSYWRpb0J1dHRvbiA9IHJiO1xuICAgIH1cbiAgICB0aGlzLmxhc3RSYWRpb0J1dHRvbiA9IHJiO1xuICB9XG5cbiAgaWYgKHRoaXMuZmlyc3RSYWRpb0J1dHRvbi5kb21Ob2RlLmNsYXNzTGlzdC5jb250YWlucygnYWN0aXZlJykpIHtcbiAgICB0aGlzLmZpcnN0UmFkaW9CdXR0b24uZG9tTm9kZS50YWJJbmRleCA9IDA7XG4gIH1cbn07XG5cblJhZGlvR3JvdXAucHJvdG90eXBlLnNldENoZWNrZWQgPSBmdW5jdGlvbiAoY3VycmVudEl0ZW0pIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnJhZGlvQnV0dG9ucy5sZW5ndGg7IGkrKykge1xuICAgIHZhciByYiA9IHRoaXMucmFkaW9CdXR0b25zW2ldO1xuICAgIHJiLmRvbU5vZGUuc2V0QXR0cmlidXRlKCdhcmlhLWNoZWNrZWQnLCAnZmFsc2UnKTtcbiAgICByYi5kb21Ob2RlLnRhYkluZGV4ID0gLTE7XG4gIH1cbiAgY3VycmVudEl0ZW0uZG9tTm9kZS5zZXRBdHRyaWJ1dGUoJ2FyaWEtY2hlY2tlZCcsICd0cnVlJyk7XG4gIGN1cnJlbnRJdGVtLmRvbU5vZGUudGFiSW5kZXggPSAwO1xuICBjdXJyZW50SXRlbS5kb21Ob2RlLmZvY3VzKCk7XG4gIGN1cnJlbnRJdGVtLmRvbU5vZGUuY2xpY2soKTtcbn07XG5cblJhZGlvR3JvdXAucHJvdG90eXBlLnNldENoZWNrZWRUb1ByZXZpb3VzSXRlbSA9IGZ1bmN0aW9uIChjdXJyZW50SXRlbSkge1xuICB2YXIgaW5kZXg7XG5cbiAgaWYgKGN1cnJlbnRJdGVtID09PSB0aGlzLmZpcnN0UmFkaW9CdXR0b24pIHtcbiAgICB0aGlzLnNldENoZWNrZWQodGhpcy5sYXN0UmFkaW9CdXR0b24pO1xuICB9IGVsc2Uge1xuICAgIGluZGV4ID0gdGhpcy5yYWRpb0J1dHRvbnMuaW5kZXhPZihjdXJyZW50SXRlbSk7XG4gICAgdGhpcy5zZXRDaGVja2VkKHRoaXMucmFkaW9CdXR0b25zW2luZGV4IC0gMV0pO1xuICB9XG59O1xuXG5SYWRpb0dyb3VwLnByb3RvdHlwZS5zZXRDaGVja2VkVG9OZXh0SXRlbSA9IGZ1bmN0aW9uIChjdXJyZW50SXRlbSkge1xuICB2YXIgaW5kZXg7XG5cbiAgaWYgKGN1cnJlbnRJdGVtID09PSB0aGlzLmxhc3RSYWRpb0J1dHRvbikge1xuICAgIHRoaXMuc2V0Q2hlY2tlZCh0aGlzLmZpcnN0UmFkaW9CdXR0b24pO1xuICB9IGVsc2Uge1xuICAgIGluZGV4ID0gdGhpcy5yYWRpb0J1dHRvbnMuaW5kZXhPZihjdXJyZW50SXRlbSk7XG4gICAgdGhpcy5zZXRDaGVja2VkKHRoaXMucmFkaW9CdXR0b25zW2luZGV4ICsgMV0pO1xuICB9XG59O1xuXG5cbihmdW5jdGlvbiAoKSB7XG4gIHZhciByYWRpb3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNvbXBvbmVudHMgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuaGppLXBvbHlnb24td3JhcCcpLFxuICAgICAgc2VsZWN0b3JzID0gWycuZm9yLXBvbHlnb24nLCAnLmZvci1jaXJjbGUnXTtcblxuICAgIGNvbXBvbmVudHMuZm9yRWFjaChjb21wb25lbnQgPT4ge1xuICAgICAgdmFyIHJhZGlvcyA9IGNvbXBvbmVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9ycyk7XG5cbiAgICAgIHJhZGlvcy5mb3JFYWNoKHJhZGlvID0+IHtcbiAgICAgICAgcmFkaW8uc2V0QXR0cmlidXRlKCdyb2xlJywgJ3JhZGlvJyk7XG5cbiAgICAgICAgaWYgKHJhZGlvLmNsYXNzTGlzdC5jb250YWlucygnYWN0aXZlJykpIHtcbiAgICAgICAgICByYWRpby5zZXRBdHRyaWJ1dGUoJ2FyaWEtY2hlY2tlZCcsICd0cnVlJyk7XG4gICAgICAgICAgcmFkaW8uc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsICcwJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmFkaW8uc2V0QXR0cmlidXRlKCdhcmlhLWNoZWNrZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgICByYWRpby5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJy0xJyk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICBjb21wb25lbnQuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3JhZGlvZ3JvdXAnKTtcblxuICAgICAgY29uc3QgcmFkaW9Hcm91cCA9IG5ldyBSYWRpb0dyb3VwKGNvbXBvbmVudCk7XG4gICAgICByYWRpb0dyb3VwLmluaXQoKTtcbiAgICB9KTtcbiAgfTtcblxuICB2YXIgaGlnaGxpZ2h0TGFiZWxGb3JGb2N1c2VkRm9ybVR5cGVSYWRpbyA9IGZ1bmN0aW9uKCkge1xuICAgIGpRdWVyeShcIi5wcm9wZXJ0eV90eXBlX3NlbGVjdG9yX3dyYXBwZXIgbGFiZWwgaW5wdXRbdHlwZT0ncmFkaW8nXVwiKS5mb2N1cyhmdW5jdGlvbigpIHtcbiAgICAgIGpRdWVyeSh0aGlzKS5jbG9zZXN0KCdsYWJlbCcpLmFkZENsYXNzKFwibGFiZWxmb2N1c1wiKTtcbiAgICB9KS5ibHVyKGZ1bmN0aW9uKCkge1xuICAgICAgalF1ZXJ5KHRoaXMpLmNsb3Nlc3QoJ2xhYmVsJykucmVtb3ZlQ2xhc3MoXCJsYWJlbGZvY3VzXCIpO1xuICAgIH0pO1xuICB9O1xuXG4gIHdpbmRvdy5vbmxvYWQgPSAoKSA9PiB7XG4gICAgaGlnaGxpZ2h0TGFiZWxGb3JGb2N1c2VkRm9ybVR5cGVSYWRpbygpO1xuICAgIHNldFRpbWVvdXQocmFkaW9zLCAxMDAwKTtcbiAgfTtcbn0pKCk7XG4iLCIvKmpzaGludCBlc3ZlcnNpb246IDYgKi9cblxuQXJyYXkuZnJvbShkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKFwic2h
3580hcmUtYnV0dG9ucy1tZW51LWJ1dHRvblwiKSkuZm9yRWFjaChcbiAgICBmdW5jdGlvbihlbGVtZW50LCBpbmRleCwgYXJyYXkpIHtcbiAgICAgICAgY29uc3Qgc2hhcmVCdXR0b25zTWVudUJ1dHRvbiA9IG5ldyBCbHZkQWNjZXNzaWJpbGl0eU1lbnVCdXR0b24oZWxlbWVudCk7XG4gICAgICAgIHNoYXJlQnV0dG9uc01lbnVCdXR0b24uaW5pdCgpO1xuICAgIH1cbik7XG5cblxuXG5cbiIsImNsYXNzIFczY1RhYlxue1xuICBjb25zdHJ1Y3Rvcih0YWJDb250YWluZXIpXG4gIHtcbiAgICB0aGlzLnRhYkNvbnRhaW5lciA9IHRhYkNvbnRhaW5lcjtcbiAgICB0aGlzLnRhYmxpc3QgPSB0aGlzLnRhYkNvbnRhaW5lci5xdWVyeVNlbGVjdG9yQWxsKCdbcm9sZT1cInRhYmxpc3RcIl0nKVswXTtcbiAgICB0aGlzLnRhYnMgPSBbXTtcbiAgICB0aGlzLnBhbmVscyA9IFtdO1xuICAgIHRoaXMuZGVsYXkgPSB0aGlzLmRldGVybWluZURlbGF5KCk7XG4gICAgdGhpcy5hY3RpdmVUYWIgPSB0aGlzLnRhYmxpc3QucXVlcnlTZWxlY3RvcignOnNjb3BlID4gW3JvbGU9XCJ0YWJcIl1bYXJpYS1zZWxlY3RlZD1cInRydWVcIl0nKTtcbiAgICB0aGlzLmFjdGl2ZVBhbmVsID0gbnVsbDtcbiAgICB0aGlzLmJlZm9yZUFjdGl2YXRlUGFuZWwgPSBmdW5jdGlvbihjdXJyZW50UGFuZWwsIG5leHRQYW5lbCl7fTtcbiAgICB0aGlzLmFmdGVyQWN0aXZhdGVQYW5lbCA9IGZ1bmN0aW9uKGN1cnJlbnRQYW5lbCwgcHJldlBhbmVsKXt9O1xuXG4gICAgdGhpcy5nZW5lcmF0ZUVsZW1lbnRzTGlzdHMoKTtcblxuICAgIC8vIEZvciBlYXN5IHJlZmVyZW5jZVxuICAgIHRoaXMua2V5cyA9IHtcbiAgICAgIGVuZDogMzUsXG4gICAgICBob21lOiAzNixcbiAgICAgIGxlZnQ6IDM3LFxuICAgICAgdXA6IDM4LFxuICAgICAgcmlnaHQ6IDM5LFxuICAgICAgZG93bjogNDAsXG4gICAgICBkZWxldGU6IDQ2XG4gICAgfTtcblxuICAgIC8vIEFkZCBvciBzdWJzdHJhY3QgZGVwZW5kaW5nIG9uIGtleSBwcmVzc2VkXG4gICAgdGhpcy5kaXJlY3Rpb24gPSB7XG4gICAgICAzNzogLTEsXG4gICAgICAzODogLTEsXG4gICAgICAzOTogMSxcbiAgICAgIDQwOiAxXG4gICAgfTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy50YWJzLmxlbmd0aDsgKytpKSB7XG4gICAgICB0aGlzLmFkZExpc3RlbmVycyhpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IGRlbGF5IHZhbHVlXG4gICAqXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAqL1xuICBkZXRlcm1pbmVEZWxheSAoKVxuICB7XG4gICAgbGV0IGhhc0RlbGF5ID0gdGhpcy50YWJsaXN0Lmhhc0F0dHJpYnV0ZSgnZGF0YS1kZWxheScpO1xuICAgIGxldCBkZWxheSA9IDA7XG5cbiAgICBpZiAoaGFzRGVsYXkpIHtcbiAgICAgICAgbGV0IGRlbGF5VmFsdWUgPSB0aGlzLnRhYmxpc3QuZ2V0QXR0cmlidXRlKCdkYXRhLWRlbGF5Jyk7XG5cbiAgICAgICAgaWYgKGRlbGF5VmFsdWUpIHtcbiAgICAgICAgICBkZWxheSA9IGRlbGF5VmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gSWYgbm8gdmFsdWUgaXMgc3BlY2lmaWVkLCBkZWZhdWx0IHRvIDMwMG1zXG4gICAgICAgICAgZGVsYXkgPSAzMDA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZGVsYXk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHRhYnMgbGlzdGVuZXJzXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleFxuICAgKi9cbiAgYWRkTGlzdGVuZXJzIChpbmRleClcbiAge1xuICAgIHRoaXMudGFic1tpbmRleF0uYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoZXZlbnQpID0+IHRoaXMuY2xpY2tFdmVudExpc3RlbmVyKGV2ZW50KSk7XG4gICAgdGhpcy50YWJzW2luZGV4XS5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgKGV2ZW50KSA9PiB0aGlzLmtleWRvd25FdmVudExpc3RlbmVyKGV2ZW50KSk7XG4gICAgdGhpcy50YWJzW2luZGV4XS5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIChldmVudCkgPT4gdGhpcy5rZXl1cEV2ZW50TGlzdGVuZXIoZXZlbnQpKTtcblxuICAgIC8vIEJ1aWxkIGFuIGFycmF5IHdpdGggYWxsIHRhYnMgKDxidXR0b24+cykgaW4gaXRcbiAgICB0aGlzLnRhYnNbaW5kZXhdLmluZGV4ID0gaW5kZXg7XG4gIH1cblxuICAvLyBXaGVuIGEgdGFiIGlzIGNsaWNrZWQsIGFjdGl2YXRlVGFiIGlzIGZpcmVkIHRvIGFjdGl2YXRlIGl0XG4gIGNsaWNrRXZlbnRMaXN0ZW5lciAoZXZlbnQpXG4gIHtcbiAgICBsZXQgdGFiID0gZXZlbnQudGFyZ2V0O1xuICAgIHRoaXMuYWN0aXZhdGVUYWIodGFiLCBmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlIGtleWRvd24gb24gdGFic1xuICAgKlxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICovXG4gIGtleWRvd25FdmVudExpc3RlbmVyIChldmVudClcbiAge1xuICAgIGxldCBrZXkgPSBldmVudC5rZXlDb2RlO1xuXG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgIGNhc2UgdGhpcy5rZXlzLmVuZDpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgLy8gQWN0aXZhdGUgbGFzdCB0YWJcbiAgICAgICAgdGhpcy5mb2N1c0xhc3RUYWIoKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgdGhpcy5rZXlzLmhvbWU6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIC8vIEFjdGl2YXRlIGZpcnN0IHRhYlxuICAgICAgICB0aGlzLmZvY3VzRmlyc3RUYWIoKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIC8vIFVwIGFuZCBkb3duIGFyZSBpbiBrZXlkb3duXG4gICAgICAvLyBiZWNhdXNlIHdlIG5lZWQgdG8gcHJldmVudCBwYWdlIHNjcm9sbCA+OilcbiAgICAgIGNhc2UgdGhpcy5rZXlzLnVwOlxuICAgICAgY2FzZSB0aGlzLmtleXMuZG93bjpcbiAgICAgICAgdGhpcy5kZXRlcm1pbmVPcmllbnRhdGlvbihldmVudCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUga2V5dXAgb24gdGFic1xuICAgKlxuICAgKiBAcGFyYW0gZXZlbnRcbiAgICovXG4gIGtleXVwRXZlbnRMaXN0ZW5lciAoZXZlbnQpXG4gIHtcbiAgICBsZXQga2V5ID0gZXZlbnQua2V5Q29kZTtcblxuICAgI
3580HN3aXRjaCAoa2V5KSB7XG4gICAgICBjYXNlIHRoaXMua2V5cy5sZWZ0OlxuICAgICAgY2FzZSB0aGlzLmtleXMucmlnaHQ6XG4gICAgICAgIHRoaXMuZGV0ZXJtaW5lT3JpZW50YXRpb24oZXZlbnQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgdGhpcy5rZXlzLmRlbGV0ZTpcbiAgICAgICAgdGhpcy5kZXRlcm1pbmVEZWxldGFibGUoZXZlbnQpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogV2hlbiBhIHRhYmxpc3TigJlzIGFyaWEtb3JpZW50YXRpb24gaXMgc2V0IHRvIHZlcnRpY2FsLFxuICAgKiBvbmx5IHVwIGFuZCBkb3duIGFycm93IHNob3VsZCBmdW5jdGlvbi5cbiAgICogSW4gYWxsIG90aGVyIGNhc2VzIG9ubHkgbGVmdCBhbmQgcmlnaHQgYXJyb3cgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBldmVudFxuICAgKi9cbiAgZGV0ZXJtaW5lT3JpZW50YXRpb24gKGV2ZW50KVxuICB7XG4gICAgbGV0IGtleSA9IGV2ZW50LmtleUNvZGU7XG4gICAgbGV0IHZlcnRpY2FsID0gdGhpcy50YWJsaXN0LmdldEF0dHJpYnV0ZSgnYXJpYS1vcmllbnRhdGlvbicpID09PSAndmVydGljYWwnO1xuICAgIGxldCBwcm9jZWVkID0gZmFsc2U7XG5cbiAgICBpZiAodmVydGljYWwpIHtcbiAgICAgIGlmIChrZXkgPT09IHRoaXMua2V5cy51cCB8fCBrZXkgPT09IHRoaXMua2V5cy5kb3duKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHByb2NlZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoa2V5ID09PSB0aGlzLmtleXMubGVmdCB8fCBrZXkgPT09IHRoaXMua2V5cy5yaWdodCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBwcm9jZWVkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocHJvY2VlZCkge1xuICAgICAgdGhpcy5zd2l0Y2hUYWJPbkFycm93UHJlc3MoZXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFaXRoZXIgZm9jdXMgdGhlIG5leHQsIHByZXZpb3VzLCBmaXJzdCwgb3IgbGFzdCB0YWJcbiAgICogZGVwZW5pbmcgb24ga2V5IHByZXNzZWRcbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqL1xuICBzd2l0Y2hUYWJPbkFycm93UHJlc3MgKGV2ZW50KVxuICB7XG4gICAgbGV0IHByZXNzZWQgPSBldmVudC5rZXlDb2RlO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnRhYnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMudGFic1tpXS5hZGRFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuZm9jdXNFdmVudEhhbmRsZXIpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRpcmVjdGlvbltwcmVzc2VkXSkge1xuICAgICAgbGV0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcblxuICAgICAgaWYgKHRhcmdldC5pbmRleCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmICh0aGlzLnRhYnNbdGFyZ2V0LmluZGV4ICsgdGhpcy5kaXJlY3Rpb25bcHJlc3NlZF1dKSB7XG4gICAgICAgICAgdGhpcy50YWJzW3RhcmdldC5pbmRleCArIHRoaXMuZGlyZWN0aW9uW3ByZXNzZWRdXS5kaXNwYXRjaEV2ZW50KG5ldyBNb3VzZUV2ZW50KCdjbGljaycpKTtcbiAgICAgICAgICB0aGlzLnRhYnNbdGFyZ2V0LmluZGV4ICsgdGhpcy5kaXJlY3Rpb25bcHJlc3NlZF1dLmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAocHJlc3NlZCA9PT0gdGhpcy5rZXlzLmxlZnQgfHwgcHJlc3NlZCA9PT0gdGhpcy5rZXlzLnVwKSB7XG4gICAgICAgICAgdGhpcy5mb2N1c0xhc3RUYWIoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChwcmVzc2VkID09PSB0aGlzLmtleXMucmlnaHQgfHwgcHJlc3NlZCA9PT0gdGhpcy5rZXlzLmRvd24pIHtcbiAgICAgICAgICB0aGlzLmZvY3VzRmlyc3RUYWIoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBY3RpdmF0ZXMgYW55IGdpdmVuIHRhYiBwYW5lbFxuICAgKlxuICAgKiBAcGFyYW0gdGFiXG4gICAqIEBwYXJhbSBzZXRGb2N1c1xuICAgKi9cbiAgYWN0aXZhdGVUYWIgKHRhYiwgc2V0Rm9jdXMpXG4gIHtcbiAgICB0aGlzLmFjdGl2ZVRhYiA9IHRhYjtcbiAgICBzZXRGb2N1cyA9IHNldEZvY3VzIHx8IHRydWU7XG4gICAgLy8gR2V0IHRoZSB2YWx1ZSBvZiBhcmlhLWNvbnRyb2xzICh3aGljaCBpcyBhbiBJRClcbiAgICBsZXQgY29udHJvbHMgPSB0YWIuZ2V0QXR0cmlidXRlKCdhcmlhLWNvbnRyb2xzJyk7XG4gICAgbGV0IGFjdGl2ZVBhbmVsID0gdGhpcy50YWJDb250YWluZXIucXVlcnlTZWxlY3RvcignIycgKyBjb250cm9scyk7XG5cbiAgICB0aGlzLmJlZm9yZUFjdGl2YXRlUGFuZWwodGhpcy5hY3RpdmVQYW5lbCwgYWN0aXZlUGFuZWwpO1xuICAgIHRoaXMuZGVhY3RpdmF0ZVRhYnMoKTtcbiAgICB0YWIuc2V0QXR0cmlidXRlKCd0YWJpbmRleCcsIDApO1xuICAgIHRhYi5zZXRBdHRyaWJ1dGUoJ2FyaWEtc2VsZWN0ZWQnLCAndHJ1ZScpO1xuXG4gICAgLy8gU2V0IGZvY3VzIHdoZW4gcmVxdWlyZWRcbiAgICBpZiAoc2V0Rm9jdXMpIHtcbiAgICAgIHRhYi5mb2N1cygpO1xuICAgIH1cblxuICAgIHRoaXMuYWZ0ZXJBY3RpdmF0ZVBhbmVsKGFjdGl2ZVBhbmVsLCB0aGlzLmFjdGl2ZVBhbmVsKTtcblxuICAgIHRoaXMuYWN0aXZlUGFuZWwgPSBhY3RpdmVQYW5lbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWFjdGl2YXRlIGFsbCB0YWJzIGFuZCB0YWIgcGFuZWxzXG4gICAqL1xuICBkZWFjdGl2YXRlVGFicyAoKVxuICB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnRhYnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMudGFic1tpXS5zZXRBdHRyaWJ1dGUoJ3RhYmluZGV4JywgJy0xJyk7XG4gICAgICB0aGlzLnRhYnNbaV0uc2V0QXR0cmlidXRlKCdhcmlhLXNlbGVjdGVkJywgJ2ZhbHNlJyk7XG4gICAgICB0aGlzLnRhYnNbaV0ucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLmZvY3VzRXZlbnRIYW5kbGVyKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFrZSBhIGd1ZXNzXG4gICAqL1xuICBmb2N1c0ZpcnN0VGFiICgpXG4gIHtcbiAgICB0aGlzLnRhYnNbMF0uZGlzcGF0Y2hFdmVudChuZXcgTW91c2VFdmVudCgnY2xpY2snKSk7XG4gICAgdGhpcy50YWJzWzBdLmZvY3VzKCk7XG4gIH1cblxuICAvKipcbiAgICogTWFrZSBhIGd1ZXNzXG4gICAqL1xuICBmb2N1c0xhc3RUYWIgKClcbiAge1xuICAgIHRoaXMudGFic1t0aGlzLnRhYnMubGVuZ3RoIC0gMV0uZGlzcGF0Y2hFdmVudChuZXcgTW91c2VFdmVudCgnY2xpY2snKSk7XG4gICAgdGhpcy50YWJzW3RoaXMudGFicy5sZW5ndGggLSAxXS5mb2N1cygpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVjdCBpZiBhIHRhYiBpcyBkZWxldGFibGVcbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqL1xuICBkZXRlcm1pbmVEZWxldGFibGUgKGV2ZW50KVxuICB7XG4gICAgbGV0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcblxuICAgIGlmICh0YXJnZXQuZ2V0QXR0cmlidXRlKCdkYXRhLWRlbGV0YWJsZScpICE9PSBudWxsKSB7XG4gICAgICAvLyBEZWxldGUgdGFyZ2V0IHRhYlxuICAgICAgdGhpcy5kZWxldGVUYWIoZXZlbnQsIHRhcmdldCk7XG5cbiAgICAgIC8vIFVwZGF0ZSBhcnJheXMgcmVsYXRlZCB0byB0YWJzIHdpZGdldFxuICAgICAgdGhpcy5nZW5lcmF0ZUVsZW1lbnRzTGlzdHMoKTtcblxuICAgICAgLy8gQWN0aXZhdGUgdGhlIGNsb3Nlc3QgdGFiIHRvIHRoZSBvbmUgdGhhdCB3YXMganVzdCBk
3580ZWxldGVkXG4gICAgICBpZiAodGFyZ2V0LmluZGV4IC0gMSA8IDApIHtcbiAgICAgICAgdGhpcy5hY3RpdmF0ZVRhYih0aGlzLnRhYnNbMF0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hY3RpdmF0ZVRhYih0aGlzLnRhYnNbdGFyZ2V0LmluZGV4IC0gMV0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIGEgdGFiIGFuZCBpdHMgcGFuZWxcbiAgICpcbiAgICogQHBhcmFtIGV2ZW50XG4gICAqL1xuICAgZGVsZXRlVGFiIChldmVudClcbiAge1xuICAgIGxldCB0YXJnZXQgPSBldmVudC50YXJnZXQ7XG4gICAgbGV0IHBhbmVsID0gdGhpcy50YWJDb250YWluZXIucXVlcnlTZWxlY3RvcignIycgKyB0YXJnZXQuZ2V0QXR0cmlidXRlKCdhcmlhLWNvbnRyb2xzJykpO1xuXG4gICAgdGFyZ2V0LnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQodGFyZ2V0KTtcbiAgICBwYW5lbC5wYXJlbnRFbGVtZW50LnJlbW92ZUNoaWxkKHBhbmVsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb2N1cyBlbGVtZW50XG4gICAqXG4gICAqIEBwYXJhbSBldmVudFxuICAgKi9cbiAgZm9jdXNFdmVudEhhbmRsZXIgKGV2ZW50KVxuICB7XG4gICAgbGV0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICB0YXJnZXQuZGlzcGF0Y2hFdmVudChuZXcgTW91c2VFdmVudCgnY2xpY2snKSk7XG5cbiAgICBzZXRUaW1lb3V0KHRoaXMuY2hlY2tUYWJGb2N1cywgdGhpcy5kZWxheSwgdGFyZ2V0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPbmx5IGFjdGl2YXRlIHRhYiBvbiBmb2N1cyBpZiBpdCBzdGlsbCB
3580oYXMgZm9jdXMgYWZ0ZXIgdGhlIGRlbGF5XG4gICAqXG4gICAqIEBwYXJhbSB0YXJnZXRcbiAgICovXG4gIGNoZWNrVGFiRm9jdXMgKHRhcmdldClcbiAge1xuICAgIGxldCBmb2N1c2VkID0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblxuICAgIGlmICh0YXJnZXQgPT09IGZvY3VzZWQpIHtcbiAgICAgIHRoaXMuYWN0aXZhdGVUYWIodGFyZ2V0LCBmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgdGFicyBhbmQgcGFuZWxzIG9uIGNvbnRhaW5lclxuICAgKi9cbiAgZ2VuZXJhdGVFbGVtZW50c0xpc3RzICgpXG4gIHtcbiAgICB0aGlzLnRhYnMgPSB0aGlzLnRhYmxpc3QucXVlcnlTZWxlY3RvckFsbCgnW3JvbGU9XCJ0YWJcIl0nKTtcbiAgICB0aGlzLnBhbmVscyA9IHRoaXMudGFiQ29udGFpbmVyLnF1ZXJ5U2VsZWN0b3JBbGwoJyAgW3JvbGU9XCJ0YWJwYW5lbFwiXScpO1xuICB9XG59XG5cblxuY2xhc3MgVzNjVGFic1xue1xuICBjb25zdHJ1Y3RvcihzZWxlY3Rvciwgb3B0aW9ucykge1xuICAgIHRoaXMudGFicyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuXG4gICAgaWYgKHRoaXMudGFicy5sZW5ndGggPD0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY3JlYXRlVGFic0luc3RhbmNlcyhvcHRpb25zKTtcblxuICB9XG5cbiAgY3JlYXRlVGFic0luc3RhbmNlcyhvcHRpb25zKVxuICB7XG4gICAgdGhpcy50YWJzLmZvckVhY2goZnVuY3Rpb24odGFiQ29udGFpbmVyKSB7XG4gICAgICBsZXQgdGFiID0gbmV3IFczY1RhYih0YWJDb250YWluZXIpO1xuXG4gICAgICBpZiAoJ3VuZGVmaW5lZCcgIT09IHR5cGVvZiBvcHRpb25zKSB7XG4gICAgICAgIGlmKG51bGwgIT09IG9wdGlvbnMuYmVmb3JlQWN0aXZhdGVQYW5lbCkge1xuICAgICAgICAgIHRhYi5iZWZvcmVBY3RpdmF0ZVBhbmVsID0gb3B0aW9ucy5iZWZvcmVBY3RpdmF0ZVBhbmVsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobnVsbCAhPT0gb3B0aW9ucy5hZnRlckFjdGl2YXRlUGFuZWwpIHtcbiAgICAgICAgICB0YWIuYWZ0ZXJBY3RpdmF0ZVBhbmVsID0gb3B0aW9ucy5hZnRlckFjdGl2YXRlUGFuZWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.