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.