| @@ -138,9 +138,92 @@ | ||
| 138 | 138 | // ===================================================================================================================== |
| 139 | 139 | // == Full Screen - support functions == |
| 140 | 140 | // ===================================================================================================================== |
| 141 | 141 | |
| 142 | +/** | |
| 143 | + * Return every cookie path that can apply to the current WordPress admin URL. | |
| 144 | + * | |
| 145 | + * WordPress may run from a subdirectory. Updating the root, site, and admin | |
| 146 | + * paths prevents an older, more-specific cookie from overriding the new mode. | |
| 147 | + * | |
| 148 | + * @return {string[]} Unique absolute cookie paths. | |
| 149 | + */ | |
| 150 | +function wpbc_admin_ui__full_screen__get_cookie_paths() { | |
| 151 | + var cookie_paths = [ '/' ]; | |
| 152 | + var admin_marker = '/wp-admin/'; | |
| 153 | + var current_path = window.location && window.location.pathname ? window.location.pathname : ''; | |
| 154 | + var admin_index = current_path.indexOf( admin_marker ); | |
| 155 | + | |
| 156 | + if ( admin_index >= 0 ) { | |
| 157 | + cookie_paths.push( current_path.substring( 0, admin_index + 1 ) ); | |
| 158 | + cookie_paths.push( current_path.substring( 0, admin_index + admin_marker.length ) ); | |
| 159 | + } | |
| 160 | + | |
| 161 | + return cookie_paths.filter( function ( path, index ) { | |
| 162 | + return path && cookie_paths.indexOf( path ) === index; | |
| 163 | + } ); | |
| 164 | +} | |
| 165 | + | |
| 166 | +/** | |
| 167 | + * Save Full Screen preference in a short-lived browser cookie. | |
| 168 | + * | |
| 169 | + * This makes the next admin page load deterministic even if the asynchronous | |
| 170 | + * user-meta request is interrupted. The timestamp lets PHP distinguish this | |
| 171 | + * pending value from a stale legacy cookie. | |
| 172 | + * | |
| 173 | + * @param {string} value Fullscreen mode, either `On` or `Off`. | |
| 174 | + * | |
| 175 | + * @return {void} | |
| 176 | + */ | |
| 177 | +function wpbc_admin_ui__full_screen__set_cookie( value ) { | |
| 178 | + var max_age = 5 * 60; | |
| 179 | + var issued_at = Math.floor( Date.now() / 1000 ); | |
| 180 | + var cookie_value = encodeURIComponent( value + '|' + issued_at ); | |
| 181 | + | |
| 182 | + wpbc_admin_ui__full_screen__get_cookie_paths().forEach( function ( cookie_path ) { | |
| 183 | + document.cookie = 'wpbc_admin_full_screen=' + cookie_value + '; path=' + cookie_path + '; max-age=' + max_age + '; SameSite=Lax'; | |
| 184 | + } ); | |
| 185 | +} | |
| 186 | + | |
| 142 | 187 | /** |
| 188 | + * Apply Full Screen mode from a user click. | |
| 189 | + * | |
| 190 | + * @param HTMLElement el Clicked control. | |
| 191 | + * @param bool is_save_user_state Whether to save user preference. | |
| 192 | + */ | |
| 193 | +function wpbc_admin_ui__full_screen__do_on( el, is_save_user_state ) { | |
| 194 | + jQuery( 'body' ).addClass( 'wpbc_admin_full_screen' ); | |
| 195 | + wpbc_check_full_screen_mode(); | |
| 196 | + | |
| 197 | + if ( is_save_user_state ) { | |
| 198 | + wpbc_admin_ui__full_screen__set_cookie( 'On' ); | |
| 199 | + | |
| 200 | + if ( 'function' === typeof wpbc_save_custom_user_data_from_element ) { | |
| 201 | + wpbc_save_custom_user_data_from_element( el ); | |
| 202 | + } | |
| 203 | + } | |
| 204 | +} | |
| 205 | + | |
| 206 | +/** | |
| 207 | + * Exit Full Screen mode from a user click. | |
| 208 | + * | |
| 209 | + * @param HTMLElement el Clicked control. | |
| 210 | + * @param bool is_save_user_state Whether to save user preference. | |
| 211 | + */ | |
| 212 | +function wpbc_admin_ui__full_screen__do_off( el, is_save_user_state ) { | |
| 213 | + jQuery( 'body' ).removeClass( 'wpbc_admin_full_screen' ); | |
| 214 | + wpbc_check_full_screen_mode(); | |
| 215 | + | |
| 216 | + if ( is_save_user_state ) { | |
| 217 | + wpbc_admin_ui__full_screen__set_cookie( 'Off' ); | |
| 218 | + | |
| 219 | + if ( 'function' === typeof wpbc_save_custom_user_data_from_element ) { | |
| 220 | + wpbc_save_custom_user_data_from_element( el ); | |
| 221 | + } | |
| 222 | + } | |
| 223 | +} | |
| 224 | + | |
| 225 | +/** | |
| 143 | 226 | * Check Full screen mode, by removing top tab |
| 144 | 227 | */ |
| 145 | 228 | function wpbc_check_full_screen_mode(){ |
| 146 | 229 | if ( jQuery( 'body' ).hasClass( 'wpbc_admin_full_screen' ) ) { |
| @@ -147,12 +230,25 @@ | ||
| 147 | 230 | jQuery( 'html' ).removeClass( 'wp-toolbar' ); |
| 148 | 231 | } else { |
| 149 | 232 | jQuery( 'html' ).addClass( 'wp-toolbar' ); |
| 150 | 233 | } |
| 234 | + wpbc_check_buttons_max_min_in_full_screen_mode(); | |
| 151 | 235 | } |
| 236 | + | |
| 237 | +function wpbc_check_buttons_max_min_in_full_screen_mode() { | |
| 238 | + if ( jQuery( 'body' ).hasClass( 'wpbc_admin_full_screen' ) ) { | |
| 239 | + jQuery( '.wpbc_ui__top_nav__btn_full_screen' ).addClass( 'wpbc_ui__hide' ); | |
| 240 | + jQuery( '.wpbc_ui__top_nav__btn_normal_screen' ).removeClass( 'wpbc_ui__hide' ); | |
| 241 | + } else { | |
| 242 | + jQuery( '.wpbc_ui__top_nav__btn_full_screen' ).removeClass( 'wpbc_ui__hide' ); | |
| 243 | + jQuery( '.wpbc_ui__top_nav__btn_normal_screen' ).addClass( 'wpbc_ui__hide' ); | |
| 244 | + } | |
| 245 | +} | |
| 246 | + | |
| 152 | 247 | jQuery( document ).ready( function () { |
| 153 | 248 | wpbc_check_full_screen_mode(); |
| 154 | -} ); | |
| 249 | +} ); | |
| 250 | + | |
| 155 | 251 | /** |
| 156 | 252 | * Checkbox Selection functions for Listing. |
| 157 | 253 | */ |
| 158 | 254 | |
| @@ -340,35 +436,156 @@ | ||
| 340 | 436 | // == Left Bar - expand / colapse functions == |
| 341 | 437 | // ===================================================================================================================== |
| 342 | 438 | |
| 343 | 439 | /** |
| 440 | + * Save user's preferred left sidebar mode. | |
| 441 | + * | |
| 442 | + * @param string mode | |
| 443 | + */ | |
| 444 | +function wpbc_admin_ui__sidebar_left__save_mode( mode ) { | |
| 445 | + var allowed_modes = [ 'min', 'compact', 'max' ]; | |
| 446 | + | |
| 447 | + if ( allowed_modes.indexOf( mode ) === -1 ) { | |
| 448 | + return; | |
| 449 | + } | |
| 450 | + | |
| 451 | + var $saver = jQuery( '#wpbc_left_sidebar_view_mode_saver' ); | |
| 452 | + | |
| 453 | + if ( ! $saver.length ) { | |
| 454 | + return; | |
| 455 | + } | |
| 456 | + | |
| 457 | + if ( 'function' !== typeof wpbc_save_custom_user_data_from_element ) { | |
| 458 | + return; | |
| 459 | + } | |
| 460 | + | |
| 461 | + $saver.data( 'wpbc-u-save-value', mode ); | |
| 462 | + $saver.attr( 'data-wpbc-u-save-value', mode ); | |
| 463 | + | |
| 464 | + wpbc_save_custom_user_data_from_element( $saver.get( 0 ) ); | |
| 465 | +} | |
| 466 | + | |
| 467 | +/** | |
| 468 | + * Reveal the active item inside the scrollable left navigation. | |
| 469 | + * | |
| 470 | + * The active item itself is aligned with a small leading offset, regardless of | |
| 471 | + * its position inside a root section. Scrolling is applied only to SimpleBar's | |
| 472 | + * internal scroll element so the WordPress administration document does not | |
| 473 | + * move. | |
| 474 | + * | |
| 475 | + * @param {Object|null|undefined} simplebar_instance Optional initialized SimpleBar instance. | |
| 476 | + * @return {void} | |
| 477 | + */ | |
| 478 | +function wpbc_admin_ui__sidebar_left__scroll_to_active_item( simplebar_instance ) { | |
| 479 | + var left_navigation_element = document.querySelector( '.wpbc_ui_el__vert_left_bar__content' ); | |
| 480 | + | |
| 481 | + if ( | |
| 482 | + ! simplebar_instance | |
| 483 | + && 'undefined' !== typeof SimpleBar | |
| 484 | + && SimpleBar.instances | |
| 485 | + && left_navigation_element | |
| 486 | + ) { | |
| 487 | + simplebar_instance = SimpleBar.instances.get( left_navigation_element ); | |
| 488 | + } | |
| 489 | + | |
| 490 | + if ( | |
| 491 | + ! simplebar_instance | |
| 492 | + || 'function' !== typeof simplebar_instance.getScrollElement | |
| 493 | + || 'function' !== typeof simplebar_instance.getContentElement | |
| 494 | + ) { | |
| 495 | + return; | |
| 496 | + } | |
| 497 | + | |
| 498 | + window.requestAnimationFrame( function () { | |
| 499 | + var scroll_element = simplebar_instance.getScrollElement(); | |
| 500 | + var content_element = simplebar_instance.getContentElement(); | |
| 501 | + | |
| 502 | + if ( | |
| 503 | + ! scroll_element | |
| 504 | + || ! content_element | |
| 505 | + || ! content_element.closest( '.wpbc_ui_el__vert_left_bar__content' ) | |
| 506 | + ) { | |
| 507 | + return; | |
| 508 | + } | |
| 509 | + | |
| 510 | + simplebar_instance.recalculate(); | |
| 511 | + | |
| 512 | + var active_item = content_element.querySelector( '.wpbc_ui_el__vert_nav_item.active' ); | |
| 513 | + | |
| 514 | + if ( ! active_item || null === active_item.offsetParent || 0 >= scroll_element.clientHeight ) { | |
| 515 | + return; | |
| 516 | + } | |
| 517 | + | |
| 518 | + var scroll_rect = scroll_element.getBoundingClientRect(); | |
| 519 | + var active_rect = active_item.getBoundingClientRect(); | |
| 520 | + var current_top = scroll_element.scrollTop; | |
| 521 | + var leading_offset = 85; | |
| 522 | + var active_top = current_top + active_rect.top - scroll_rect.top; | |
| 523 | + var target_top = active_top - leading_offset; | |
| 524 | + | |
| 525 | + var maximum_top = Math.max( 0, scroll_element.scrollHeight - scroll_element.clientHeight ); | |
| 526 | + | |
| 527 | + scroll_element.scrollTop = Math.max( 0, Math.min( Math.round( target_top ), maximum_top ) ); | |
| 528 | + } ); | |
| 529 | +} | |
| 530 | + | |
| 531 | +/** | |
| 344 | 532 | * Expand Vertical Left Bar. |
| 533 | + * | |
| 534 | + * @param bool is_save_user_state Save this mode as user's preference. | |
| 345 | 535 | */ |
| 346 | -function wpbc_admin_ui__sidebar_left__do_max() { | |
| 536 | +function wpbc_admin_ui__sidebar_left__do_max( is_save_user_state ) { | |
| 347 | 537 | jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min max compact none' ); |
| 348 | 538 | jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'max' ); |
| 349 | 539 | jQuery( '.wpbc_ui__top_nav__btn_open_left_vertical_nav' ).addClass( 'wpbc_ui__hide' ); |
| 350 | 540 | jQuery( '.wpbc_ui__top_nav__btn_hide_left_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); |
| 541 | + | |
| 542 | + jQuery( '.wp-admin' ).removeClass( 'wpbc_page_wrapper_left_min wpbc_page_wrapper_left_max wpbc_page_wrapper_left_compact wpbc_page_wrapper_left_none' ); | |
| 543 | + jQuery( '.wp-admin' ).addClass( 'wpbc_page_wrapper_left_max' ); | |
| 544 | + wpbc_admin_ui__sidebar_left__scroll_to_active_item(); | |
| 545 | + | |
| 546 | + if ( is_save_user_state ) { | |
| 547 | + wpbc_admin_ui__sidebar_left__save_mode( 'max' ); | |
| 548 | + } | |
| 351 | 549 | } |
| 352 | 550 | |
| 353 | 551 | /** |
| 354 | 552 | * Hide Vertical Left Bar. |
| 553 | + * | |
| 554 | + * @param bool is_save_user_state Save this mode as user's preference. | |
| 355 | 555 | */ |
| 356 | -function wpbc_admin_ui__sidebar_left__do_min() { | |
| 556 | +function wpbc_admin_ui__sidebar_left__do_min( is_save_user_state ) { | |
| 357 | 557 | jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min max compact none' ); |
| 358 | 558 | jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'min' ); |
| 359 | 559 | jQuery( '.wpbc_ui__top_nav__btn_open_left_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); |
| 360 | 560 | jQuery( '.wpbc_ui__top_nav__btn_hide_left_vertical_nav' ).addClass( 'wpbc_ui__hide' ); |
| 561 | + | |
| 562 | + jQuery( '.wp-admin' ).removeClass( 'wpbc_page_wrapper_left_min wpbc_page_wrapper_left_max wpbc_page_wrapper_left_compact wpbc_page_wrapper_left_none' ); | |
| 563 | + jQuery( '.wp-admin' ).addClass( 'wpbc_page_wrapper_left_min' ); | |
| 564 | + | |
| 565 | + if ( is_save_user_state ) { | |
| 566 | + wpbc_admin_ui__sidebar_left__save_mode( 'min' ); | |
| 567 | + } | |
| 361 | 568 | } |
| 362 | 569 | |
| 363 | 570 | /** |
| 364 | 571 | * Colapse Vertical Left Bar. |
| 572 | + * | |
| 573 | + * @param bool is_save_user_state Save this mode as user's preference. | |
| 365 | 574 | */ |
| 366 | -function wpbc_admin_ui__sidebar_left__do_compact() { | |
| 575 | +function wpbc_admin_ui__sidebar_left__do_compact( is_save_user_state ) { | |
| 367 | 576 | jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min max compact none' ); |
| 368 | 577 | jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'compact' ); |
| 369 | 578 | jQuery( '.wpbc_ui__top_nav__btn_open_left_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); |
| 370 | 579 | jQuery( '.wpbc_ui__top_nav__btn_hide_left_vertical_nav' ).addClass( 'wpbc_ui__hide' ); |
| 580 | + | |
| 581 | + jQuery( '.wp-admin' ).removeClass( 'wpbc_page_wrapper_left_min wpbc_page_wrapper_left_max wpbc_page_wrapper_left_compact wpbc_page_wrapper_left_none' ); | |
| 582 | + jQuery( '.wp-admin' ).addClass( 'wpbc_page_wrapper_left_compact' ); | |
| 583 | + wpbc_admin_ui__sidebar_left__scroll_to_active_item(); | |
| 584 | + | |
| 585 | + if ( is_save_user_state ) { | |
| 586 | + wpbc_admin_ui__sidebar_left__save_mode( 'compact' ); | |
| 587 | + } | |
| 371 | 588 | } |
| 372 | 589 | |
| 373 | 590 | /** |
| 374 | 591 | * Completely Hide Vertical Left Bar. |
| @@ -379,8 +596,11 @@ | ||
| 379 | 596 | jQuery( '.wpbc_ui__top_nav__btn_open_left_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); |
| 380 | 597 | jQuery( '.wpbc_ui__top_nav__btn_hide_left_vertical_nav' ).addClass( 'wpbc_ui__hide' ); |
| 381 | 598 | // Hide top "Menu" button with divider. |
| 382 | 599 | jQuery( '.wpbc_ui__top_nav__btn_show_left_vertical_nav,.wpbc_ui__top_nav__btn_show_left_vertical_nav_divider' ).addClass( 'wpbc_ui__hide' ); |
| 600 | + | |
| 601 | + jQuery( '.wp-admin' ).removeClass( 'wpbc_page_wrapper_left_min wpbc_page_wrapper_left_max wpbc_page_wrapper_left_compact wpbc_page_wrapper_left_none' ); | |
| 602 | + jQuery( '.wp-admin' ).addClass( 'wpbc_page_wrapper_left_none' ); | |
| 383 | 603 | } |
| 384 | 604 | |
| 385 | 605 | /** |
| 386 | 606 | * Action on click "Go Back" - show root menu |
| @@ -392,10 +612,158 @@ | ||
| 392 | 612 | jQuery( '.wpbc_ui_el__vert_left_bar__section' ).addClass( 'wpbc_ui__hide' ) |
| 393 | 613 | jQuery( '.wpbc_ui_el__vert_left_bar__section_' + menu_to_show ).removeClass( 'wpbc_ui__hide' ); |
| 394 | 614 | } |
| 395 | 615 | |
| 616 | +// ===================================================================================================================== | |
| 617 | +// == Right Side Bar - expand / colapse functions == | |
| 618 | +// ===================================================================================================================== | |
| 396 | 619 | |
| 397 | 620 | /** |
| 621 | + * Synchronize the document body marker for the expanded right sidebar. | |
| 622 | + * | |
| 623 | + * The marker is domain-neutral so individual administration pages can adjust | |
| 624 | + * their presentation without duplicating right-sidebar state handling. | |
| 625 | + * | |
| 626 | + * @param {boolean} is_open Whether the right sidebar is fully expanded. | |
| 627 | + * @return {void} | |
| 628 | + */ | |
| 629 | +function wpbc_admin_ui__sidebar_right__set_body_open_state( is_open ) { | |
| 630 | + jQuery( 'body' ).toggleClass( 'wpbc_ui_el__vert_right_bar__wrapper_opened', !! is_open ); | |
| 631 | +} | |
| 632 | + | |
| 633 | +/** | |
| 634 | + * Expand Vertical Right Bar. | |
| 635 | + */ | |
| 636 | +function wpbc_admin_ui__sidebar_right__do_max() { | |
| 637 | + jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min_right max_right compact_right none_right' ); | |
| 638 | + jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'max_right' ); | |
| 639 | + jQuery( '.wpbc_ui__top_nav__btn_open_right_vertical_nav' ).addClass( 'wpbc_ui__hide' ); | |
| 640 | + jQuery( '.wpbc_ui__top_nav__btn_hide_right_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); | |
| 641 | + wpbc_admin_ui__sidebar_right__set_body_open_state( true ); | |
| 642 | +} | |
| 643 | + | |
| 644 | +/** | |
| 645 | + * Hide Vertical Right Bar. | |
| 646 | + */ | |
| 647 | +function wpbc_admin_ui__sidebar_right__do_min() { | |
| 648 | + jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min_right max_right compact_right none_right' ); | |
| 649 | + jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'min_right' ); | |
| 650 | + jQuery( '.wpbc_ui__top_nav__btn_open_right_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); | |
| 651 | + jQuery( '.wpbc_ui__top_nav__btn_hide_right_vertical_nav' ).addClass( 'wpbc_ui__hide' ); | |
| 652 | + wpbc_admin_ui__sidebar_right__set_body_open_state( false ); | |
| 653 | +} | |
| 654 | + | |
| 655 | +/** | |
| 656 | + * Colapse Vertical Right Bar. | |
| 657 | + */ | |
| 658 | +function wpbc_admin_ui__sidebar_right__do_compact() { | |
| 659 | + jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min_right max_right compact_right none_right' ); | |
| 660 | + jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'compact_right' ); | |
| 661 | + jQuery( '.wpbc_ui__top_nav__btn_open_right_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); | |
| 662 | + jQuery( '.wpbc_ui__top_nav__btn_hide_right_vertical_nav' ).addClass( 'wpbc_ui__hide' ); | |
| 663 | + wpbc_admin_ui__sidebar_right__set_body_open_state( false ); | |
| 664 | +} | |
| 665 | + | |
| 666 | +/** | |
| 667 | + * Completely Hide Vertical Right Bar. | |
| 668 | + */ | |
| 669 | +function wpbc_admin_ui__sidebar_right__do_hide() { | |
| 670 | + jQuery( '.wpbc_settings_page_wrapper' ).removeClass( 'min_right max_right compact_right none_right' ); | |
| 671 | + jQuery( '.wpbc_settings_page_wrapper' ).addClass( 'none_right' ); | |
| 672 | + jQuery( '.wpbc_ui__top_nav__btn_open_right_vertical_nav' ).removeClass( 'wpbc_ui__hide' ); | |
| 673 | + jQuery( '.wpbc_ui__top_nav__btn_hide_right_vertical_nav' ).addClass( 'wpbc_ui__hide' ); | |
| 674 | + // Hide top "Menu" button with divider. | |
| 675 | + jQuery( '.wpbc_ui__top_nav__btn_show_right_vertical_nav,.wpbc_ui__top_nav__btn_show_right_vertical_nav_divider' ).addClass( 'wpbc_ui__hide' ); | |
| 676 | + wpbc_admin_ui__sidebar_right__set_body_open_state( false ); | |
| 677 | +} | |
| 678 | + | |
| 679 | +/** | |
| 680 | + * Restore the body marker when a page renders with the right sidebar open. | |
| 681 | + */ | |
| 682 | +jQuery( document ).ready( function () { | |
| 683 | + wpbc_admin_ui__sidebar_right__set_body_open_state( 0 < jQuery( '.wpbc_settings_page_wrapper.max_right' ).length ); | |
| 684 | +} ); | |
| 685 | + | |
| 686 | +/** | |
| 687 | + * Collapse an expanded right sidebar after an opted-in page-content click. | |
| 688 | + * | |
| 689 | + * Pages enable this behavior through the page-structure | |
| 690 | + * right_vertical_sidebar__content_click_collapse_mode option. Interactive | |
| 691 | + * controls that open or retain sidebar content can opt out by placing the | |
| 692 | + * data-wpbc-right-sidebar-keep-open attribute on themselves or an ancestor. | |
| 693 | + * | |
| 694 | + * @param {MouseEvent} event Content click event captured before catalog rows. | |
| 695 | + * @return {void} | |
| 696 | + */ | |
| 697 | +function wpbc_admin_ui__sidebar_right__collapse_from_content_click( event ) { | |
| 698 | + var event_target = event.target && 1 === event.target.nodeType ? event.target : null; | |
| 699 | + var content_element = event_target && 'function' === typeof event_target.closest | |
| 700 | + ? event_target.closest( '.wpbc_settings_page_wrapper[data-wpbc-right-sidebar-content-click-collapse-mode] > .wpbc_settings_page_content' ) | |
| 701 | + : null; | |
| 702 | + var $content; | |
| 703 | + var $wrapper; | |
| 704 | + var collapse_mode; | |
| 705 | + var before_collapse_event; | |
| 706 | + | |
| 707 | + if ( ! content_element ) { | |
| 708 | + return; | |
| 709 | + } | |
| 710 | + | |
| 711 | + $content = jQuery( content_element ); | |
| 712 | + $wrapper = $content.closest( '.wpbc_settings_page_wrapper' ); | |
| 713 | + collapse_mode = String( $wrapper.attr( 'data-wpbc-right-sidebar-content-click-collapse-mode' ) || '' ); | |
| 714 | + | |
| 715 | + if ( ! $wrapper.hasClass( 'max_right' ) || [ 'min', 'compact', 'none' ].indexOf( collapse_mode ) === -1 ) { | |
| 716 | + return; | |
| 717 | + } | |
| 718 | + if ( jQuery( event.target ).closest( '[data-wpbc-right-sidebar-keep-open]' ).length ) { | |
| 719 | + return; | |
| 720 | + } | |
| 721 | + | |
| 722 | + /* | |
| 723 | + * This click belongs to the open-sidebar dismissal layer. Consume it before | |
| 724 | + * domain row handlers run so the same pointer action cannot close one | |
| 725 | + * inspector and immediately open another one underneath it. | |
| 726 | + */ | |
| 727 | + event.preventDefault(); | |
| 728 | + event.stopImmediatePropagation(); | |
| 729 | + | |
| 730 | + before_collapse_event = jQuery.Event( 'wpbc:right-sidebar-before-content-collapse' ); | |
| 731 | + $wrapper.trigger( before_collapse_event, [ event ] ); | |
| 732 | + if ( before_collapse_event.isDefaultPrevented() ) { | |
| 733 | + return; | |
| 734 | + } | |
| 735 | + | |
| 736 | + if ( 'compact' === collapse_mode ) { | |
| 737 | + wpbc_admin_ui__sidebar_right__do_compact(); | |
| 738 | + } else if ( 'none' === collapse_mode ) { | |
| 739 | + wpbc_admin_ui__sidebar_right__do_hide(); | |
| 740 | + } else { | |
| 741 | + wpbc_admin_ui__sidebar_right__do_min(); | |
| 742 | + } | |
| 743 | + | |
| 744 | + jQuery( document ).trigger( 'wpbc_setup_wizard_layout_changed' ); | |
| 745 | +} | |
| 746 | + | |
| 747 | +document.addEventListener( 'click', wpbc_admin_ui__sidebar_right__collapse_from_content_click, true ); | |
| 748 | + | |
| 749 | + | |
| 750 | +/** | |
| 751 | + * Action on click "Go Back" - show root menu | |
| 752 | + * or some other section in right sidebar. | |
| 753 | + * | |
| 754 | + * @param string menu_to_show - menu slug. | |
| 755 | + */ | |
| 756 | +function wpbc_admin_ui__sidebar_right__show_section( menu_to_show ) { | |
| 757 | + jQuery( '.wpbc_ui_el__vert_right_bar__section' ).addClass( 'wpbc_ui__hide' ) | |
| 758 | + jQuery( '.wpbc_ui_el__vert_right_bar__section_' + menu_to_show ).removeClass( 'wpbc_ui__hide' ); | |
| 759 | +} | |
| 760 | + | |
| 761 | +// ===================================================================================================================== | |
| 762 | +// == End Right Side Bar section == | |
| 763 | +// ===================================================================================================================== | |
| 764 | + | |
| 765 | +/** | |
| 398 | 766 | * Get anchor(s) array from URL. |
| 399 | 767 | * Doc: https://developer.mozilla.org/en-US/docs/Web/API/Location |
| 400 | 768 | * |
| 401 | 769 | * @returns {*[]} |
| @@ -416,12 +784,29 @@ | ||
| 416 | 784 | |
| 417 | 785 | /** |
| 418 | 786 | * Auto Expand Settings section based on URL anchor, after page loaded. |
| 419 | 787 | */ |
| 788 | +jQuery( document ).ready( function () { wpbc_admin_ui__redirect_legacy_general_availability_url(); } ); | |
| 420 | 789 | jQuery( document ).ready( function () { wpbc_admin_ui__do_expand_section(); setTimeout( 'wpbc_admin_ui__do_expand_section', 10 ); } ); |
| 421 | 790 | jQuery( document ).ready( function () { wpbc_admin_ui__do_expand_section(); setTimeout( 'wpbc_admin_ui__do_expand_section', 150 ); } ); |
| 422 | 791 | |
| 423 | 792 | /** |
| 793 | + * Redirect old Settings > Availability anchors to the dedicated General Availability page. | |
| 794 | + */ | |
| 795 | +function wpbc_admin_ui__redirect_legacy_general_availability_url() { | |
| 796 | + | |
| 797 | + if ( | |
| 798 | + ( window.location.href.indexOf( 'page=wpbc-settings' ) > -1 ) | |
| 799 | + && ( | |
| 800 | + ( window.location.hash.indexOf( 'wpbc_general_settings_availability_metabox' ) > -1 ) | |
| 801 | + || ( window.location.hash.indexOf( 'wpbc_general_settings_availability_tab' ) > -1 ) | |
| 802 | + ) | |
| 803 | + ) { | |
| 804 | + window.location.replace( window.location.href.split( '?' )[0] + '?page=wpbc-availability&tab=general_availability' ); | |
| 805 | + } | |
| 806 | +} | |
| 807 | + | |
| 808 | +/** | |
| 424 | 809 | * Expand section in General Settings page and select Menu item. |
| 425 | 810 | */ |
| 426 | 811 | function wpbc_admin_ui__do_expand_section() { |
| 427 | 812 | |
| @@ -481,8 +866,16 @@ | ||
| 481 | 866 | wpbc_admin_ui__do__anchor__another_actions(); |
| 482 | 867 | } |
| 483 | 868 | } |
| 484 | 869 | |
| 870 | +function wpbc_admin_ui__is_in_mobile_screen_size() { | |
| 871 | + return wpbc_admin_ui__is_in_this_screen_size( 605 ); | |
| 872 | +} | |
| 873 | + | |
| 874 | +function wpbc_admin_ui__is_in_this_screen_size(size) { | |
| 875 | + return (window.screen.width <= size); | |
| 876 | +} | |
| 877 | + | |
| 485 | 878 | /** |
| 486 | 879 | * Open settings page | Expand section | Select Menu item. |
| 487 | 880 | */ |
| 488 | 881 | function wpbc_admin_ui__do__open_url__expand_section(url, section_id) { |
| @@ -489,8 +882,12 @@ | ||
| 489 | 882 | |
| 490 | 883 | // window.location.href = url + '&do_expand=' + section_id + '#do_expand__' + section_id; //. |
| 491 | 884 | window.location.href = url + '#do_expand__' + section_id; |
| 492 | 885 | |
| 886 | + if ( wpbc_admin_ui__is_in_mobile_screen_size() ) { | |
| 887 | + wpbc_admin_ui__sidebar_left__do_min(); | |
| 888 | + } | |
| 889 | + | |
| 493 | 890 | wpbc_admin_ui__do_expand_section(); |
| 494 | 891 | } |
| 495 | 892 | |
| 496 | 893 | |
| @@ -535,9 +932,10 @@ | ||
| 535 | 932 | default: |
| 536 | 933 | } |
| 537 | 934 | } |
| 538 | 935 | } |
| 539 | -} | |
| 936 | +} | |
| 937 | + | |
| 540 | 938 | /** |
| 541 | 939 | * Copy txt to clipbrd from Text fields. |
| 542 | 940 | * |
| 543 | 941 | * @param html_element_id - e.g. 'data_field' |
| @@ -653,6 +1051,1473 @@ | ||
| 653 | 1051 | // [6] - Remove the container |
| 654 | 1052 | document.body.removeChild( container ); |
| 655 | 1053 | |
| 656 | 1054 | return result; |
| 657 | -} | |
| 658 | -//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVpX2VsZW1lbnRzLmpzIiwidWlfbG9hZGluZ19zcGluLmpzIiwidWlfcmFkaW9fY29udGFpbmVyLmpzIiwidWlfZnVsbF9zY3JlZW5fbW9kZS5qcyIsImdtYWlsX2NoZWNrYm94X3NlbGVjdGlvbi5qcyIsImJvb2tpbmdzX2NoZWNrYm94X3NlbGVjdGlvbi5qcyIsInVpX3NpZGViYXJfbGVmdF9fYWN0aW9ucy5qcyIsImNvcHlfdGV4dF90b19jbGlwYnJkLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3BEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3pNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJ3cGJjX2FsbF9hZG1pbi5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxyXG4vKipcclxuICogQmxpbmsgc3BlY2lmaWMgSFRNTCBlbGVtZW50IHRvIHNldCBhdHRlbnRpb24gdG8gdGhpcyBlbGVtZW50LlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZWxlbWVudF90b19ibGlua1x0XHQgIC0gY2xhc3Mgb3IgaWQgb2YgZWxlbWVudDogJy53cGJjX3dpZGdldF9hdmFpbGFibGVfdW5hdmFpbGFibGUnXHJcbiAqIEBwYXJhbSB7aW50fSBob3dfbWFueV90aW1lc1x0XHRcdCAgLSA0XHJcbiAqIEBwYXJhbSB7aW50fSBob3dfbG9uZ190b19ibGlua1x0XHQgIC0gMzUwXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2JsaW5rX2VsZW1lbnQoIGVsZW1lbnRfdG9fYmxpbmssIGhvd19tYW55X3RpbWVzID0gNCwgaG93X2xvbmdfdG9fYmxpbmsgPSAzNTAgKXtcclxuXHJcblx0Zm9yICggbGV0IGkgPSAwOyBpIDwgaG93X21hbnlfdGltZXM7IGkrKyApe1xyXG5cdFx0alF1ZXJ5KCBlbGVtZW50X3RvX2JsaW5rICkuZmFkZU91dCggaG93X2xvbmdfdG9fYmxpbmsgKS5mYWRlSW4oIGhvd19sb25nX3RvX2JsaW5rICk7XHJcblx0fVxyXG4gICAgalF1ZXJ5KCBlbGVtZW50X3RvX2JsaW5rICkuYW5pbWF0ZSgge29wYWNpdHk6IDF9LCA1MDAgKTtcclxufVxyXG4iLCIvKipcclxuICogICBTdXBwb3J0IEZ1bmN0aW9ucyAtIFNwaW4gSWNvbiBpbiBCdXR0b25zICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbi8qKlxyXG4gKiBSZW1vdmUgc3BpbiBpY29uIGZyb20gIGJ1dHRvbiBhbmQgRW5hYmxlIHRoaXMgYnV0dG9uLlxyXG4gKlxyXG4gKiBAcGFyYW0gYnV0dG9uX2NsaWNrZWRfZWxlbWVudF9pZFx0XHQtIEhUTUwgSUQgYXR0cmlidXRlIG9mIHRoaXMgYnV0dG9uXHJcbiAqIEByZXR1cm4gc3RyaW5nXHRcdFx0XHRcdFx0LSBDU1MgY2xhc3NlcyB0aGF0IHdhcyBwcmV2aW91c2x5IGluIGJ1dHRvbiBpY29uXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2J1dHRvbl9fcmVtb3ZlX3NwaW4oYnV0dG9uX2NsaWNrZWRfZWxlbWVudF9pZCkge1xyXG5cclxuXHR2YXIgcHJldmlvc19jbGFzc2VzID0gJyc7XHJcblx0aWYgKFxyXG5cdFx0KHVuZGVmaW5lZCAhPSBidXR0b25fY2xpY2tlZF9lbGVtZW50X2lkKVxyXG5cdFx0JiYgKCcnICE9IGJ1dHRvbl9jbGlja2VkX2VsZW1lbnRfaWQpXHJcblx0KSB7XHJcblx0XHR2YXIgakVsZW1lbnQgPSBqUXVlcnkoICcjJyArIGJ1dHRvbl9jbGlja2VkX2VsZW1lbnRfaWQgKTtcclxuXHRcdGlmICggakVsZW1lbnQubGVuZ3RoICkge1xyXG5cdFx0XHRwcmV2aW9zX2NsYXNzZXMgPSB3cGJjX2J1dHRvbl9kaXNhYmxlX2xvYWRpbmdfaWNvbiggakVsZW1lbnQuZ2V0KCAwICkgKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiBwcmV2aW9zX2NsYXNzZXM7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogU2hvdyBMb2FkaW5nIChyb3RhdGluZyBhcnJvdykgaWNvbiBmb3IgYnV0dG9uIHRoYXQgaGFzIGJlZW4gY2xpY2tlZFxyXG4gKlxyXG4gKiBAcGFyYW0gdGhpc19idXR0b25cdFx0LSB0aGlzIG9iamVjdCBvZiBzcGVjaWZpYyBidXR0b25cclxuICogQHJldHVybiBzdHJpbmdcdFx0XHQtIENTUyBjbGFzc2VzIHRoYXQgd2FzIHByZXZpb3VzbHkgaW4gYnV0dG9uIGljb25cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYnV0dG9uX2VuYWJsZV9sb2FkaW5nX2ljb24odGhpc19idXR0b24pIHtcclxuXHJcblx0dmFyIGpCdXR0b24gICAgICAgICA9IGpRdWVyeSggdGhpc19idXR0b24gKTtcclxuXHR2YXIgakljb24gICAgICAgICAgID0gakJ1dHRvbi5maW5kKCAnaScgKTtcclxuXHR2YXIgcHJldmlvc19jbGFzc2VzID0gakljb24uYXR0ciggJ2NsYXNzJyApO1xyXG5cclxuXHRqSWNvbi5yZW1vdmVDbGFzcygpLmFkZENsYXNzKCAnbWVudV9pY29uIGljb24tMXggd3BiY19pY25fcm90YXRlX3JpZ2h0IHdwYmNfc3BpbicgKTtcdC8vIFNldCBSb3RhdGUgaWNvbi5cclxuXHQvLyBqSWNvbi5hZGRDbGFzcyggJ3dwYmNfYW5pbWF0aW9uX3BhdXNlJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFBhdXNlIGFuaW1hdGlvbi5cclxuXHQvLyBqSWNvbi5hZGRDbGFzcyggJ3dwYmNfdWlfcmVkJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTZXQgaWNvbiBjb2xvciByZWQuXHJcblxyXG5cdGpJY29uLmF0dHIoICd3cGJjX3ByZXZpb3VzX2NsYXNzJywgcHJldmlvc19jbGFzc2VzIClcclxuXHJcblx0akJ1dHRvbi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIERpc2FibGUgYnV0dG9uXHJcblx0Ly8gV2UgbmVlZCB0byAgc2V0ICBoZXJlIGF0dHIgaW5zdGVhZCBvZiBwcm9wLCBiZWNhdXNlIGZvciBBIGVsZW1lbnRzLCAgYXR0cmlidXRlICdkaXNhYmxlZCcgZG8gIG5vdCBhZGRlZCB3aXRoIGpCdXR0b24ucHJvcCggXCJkaXNhYmxlZFwiLCB0cnVlICk7LlxyXG5cclxuXHRqQnV0dG9uLmF0dHIoICd3cGJjX3ByZXZpb3VzX29uY2xpY2snLCBqQnV0dG9uLmF0dHIoICdvbmNsaWNrJyApICk7XHRcdC8vIFNhdmUgdGhpcyB2YWx1ZS5cclxuXHRqQnV0dG9uLmF0dHIoICdvbmNsaWNrJywgJycgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gRGlzYWJsZSBhY3Rpb25zIFwib24gY2xpY2tcIi5cclxuXHJcblx0cmV0dXJuIHByZXZpb3NfY2xhc3NlcztcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBIaWRlIExvYWRpbmcgKHJvdGF0aW5nIGFycm93KSBpY29uIGZvciBidXR0b24gdGhhdCB3YXMgY2xpY2tlZCBhbmQgc2hvdyBwcmV2aW91cyBpY29uIGFuZCBlbmFibGUgYnV0dG9uXHJcbiAqXHJcbiAqIEBwYXJhbSB0aGlzX2J1dHRvblx0XHQtIHRoaXMgb2JqZWN0IG9mIHNwZWNpZmljIGJ1dHRvblxyXG4gKiBAcmV0dXJuIHN0cmluZ1x0XHRcdC0gQ1NTIGNsYXNzZXMgdGhhdCB3YXMgcHJldmlvdXNseSBpbiBidXR0b24gaWNvblxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19idXR0b25fZGlzYWJsZV9sb2FkaW5nX2ljb24odGhpc19idXR0b24pIHtcclxuXHJcblx0dmFyIGpCdXR0b24gPSBqUXVlcnkoIHRoaXNfYnV0dG9uICk7XHJcblx0dmFyIGpJY29uICAgPSBqQnV0dG9uLmZpbmQoICdpJyApO1xyXG5cclxuXHR2YXIgcHJldmlvc19jbGFzc2VzID0gakljb24uYXR0ciggJ3dwYmNfcHJldmlvdXNfY2xhc3MnICk7XHJcblx0aWYgKFxyXG5cdFx0KHVuZGVmaW5lZCAhPSBwcmV2aW9zX2NsYXNzZXMpXHJcblx0XHQmJiAoJycgIT0gcHJldmlvc19jbGFzc2VzKVxyXG5cdCkge1xyXG5cdFx0akljb24ucmVtb3ZlQ2xhc3MoKS5hZGRDbGFzcyggcHJldmlvc19jbGFzc2VzICk7XHJcblx0fVxyXG5cclxuXHRqQnV0dG9uLnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQnICk7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIERpc2FibGUgYnV0dG9uLlxyXG5cclxuXHR2YXIgcHJldmlvdXNfb25jbGljayA9IGpCdXR0b24uYXR0ciggJ3dwYmNfcHJldmlvdXNfb25jbGljaycgKVxyXG5cdGlmIChcclxuXHRcdCh1bmRlZmluZWQgIT0gcHJldmlvdXNfb25jbGljaylcclxuXHRcdCYmICgnJyAhPSBwcmV2aW91c19vbmNsaWNrKVxyXG5cdCkge1xyXG5cdFx0akJ1dHRvbi5hdHRyKCAnb25jbGljaycsIHByZXZpb3VzX29uY2xpY2sgKTtcclxuXHR9XHJcblxyXG5cdHJldHVybiBwcmV2aW9zX2NsYXNzZXM7XHJcbn1cclxuIiwiLyoqXHJcbiAqIE9uIHNlbGVjdGlvbiAgb2YgcmFkaW8gYnV0dG9uLCBhZGp1c3QgYXR0cmlidXRlcyBvZiByYWRpbyBjb250YWluZXJcclxuICpcclxuICogQHBhcmFtIF90aGlzXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX3VpX2VsX19yYWRpb19jb250YWluZXJfc2VsZWN0aW9uKF90aGlzKSB7XHJcblxyXG5cdGlmICggalF1ZXJ5KCBfdGhpcyApLmlzKCAnOmNoZWNrZWQnICkgKSB7XHJcblx0XHRqUXVlcnkoIF90aGlzICkucGFyZW50cyggJy53cGJjX3VpX3JhZGlvX3NlY3Rpb24nICkuZmluZCggJy53cGJjX3VpX3JhZGlvX2NvbnRhaW5lcicgKS5yZW1vdmVBdHRyKCAnZGF0YS1zZWxlY3RlZCcgKTtcclxuXHRcdGpRdWVyeSggX3RoaXMgKS5wYXJlbnRzKCAnLndwYmNfdWlfcmFkaW9fY29udGFpbmVyOm5vdCguZGlzYWJsZWQpJyApLmF0dHIoICdkYXRhLXNlbGVjdGVkJywgdHJ1ZSApO1xyXG5cdH1cclxuXHJcblx0aWYgKCBqUXVlcnkoIF90aGlzICkuaXMoICc6ZGlzYWJsZWQnICkgKSB7XHJcblx0XHRqUXVlcnkoIF90aGlzICkucGFyZW50cyggJy53cGJjX3VpX3JhZGlvX2NvbnRhaW5lcicgKS5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE9uIGNsaWNrIG9uIFJhZGlvIENvbnRhaW5lciwgd2Ugd2lsbCAgc2VsZWN0ICB0aGUgIHJhZGlvIGJ1dHRvbiAgICBhbmQgdGhlbiBhZGp1c3QgYXR0cmlidXRlcyBvZiByYWRpbyBjb250YWluZXJcclxuICpcclxuICogQHBhcmFtIF90aGlzXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX3VpX2VsX19yYWRpb19jb250YWluZXJfY2xpY2soX3RoaXMpIHtcclxuXHJcblx0aWYgKCBqUXVlcnkoIF90aGlzICkuaGFzQ2xhc3MoICdkaXNhYmxlZCcgKSApIHtcclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcblxyXG5cdHZhciBqX3JhZGlvID0galF1ZXJ5KCBfdGhpcyApLmZpbmQoICdpbnB1dFt0eXBlPXJhZGlvXTpub3QoLndwYmMtZm9ybS1yYWRpby1pbnRlcm5hbCknICk7XHJcblx0aWYgKCBqX3JhZGlvLmxlbmd0aCApIHtcclxuXHRcdGpfcmFkaW8ucHJvcCggJ2NoZWNrZWQnLCB0cnVlICkudHJpZ2dlciggJ2NoYW5nZScgKTtcclxuXHR9XHJcblxyXG59IiwiXCJ1c2Ugc3RyaWN0XCI7XHJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4vLyA9PSBGdWxsIFNjcmVlbiAgLSAgc3VwcG9ydCBmdW5jdGlvbnMgICA9PVxyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuXHJcbi8qKlxyXG4gKiBDaGVjayBGdWxsICBzY3JlZW4gbW9kZSwgIGJ5ICByZW1vdmluZyB0b3AgdGFiXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2NoZWNrX2Z1bGxfc2NyZWVuX21vZGUoKXtcclxuXHRpZiAoIGpRdWVyeSggJ2JvZHknICkuaGFzQ2xhc3MoICd3cGJjX2FkbWluX2Z1bGxfc2NyZWVuJyApICkge1xyXG5cdFx0alF1ZXJ5KCAnaHRtbCcgKS5yZW1vdmVDbGFzcyggJ3dwLXRvb2xiYXInICk7XHJcblx0fSBlbHNlIHtcclxuXHRcdGpRdWVyeSggJ2h0bWwnICkuYWRkQ2xhc3MoICd3cC10b29sYmFyJyApO1xyXG5cdH1cclxufVxyXG5qUXVlcnkoIGRvY3VtZW50ICkucmVhZHkoIGZ1bmN0aW9uICgpIHtcclxuXHR3cGJjX2NoZWNrX2Z1bGxfc2NyZWVuX21vZGUoKTtcclxufSApOyIsIi8qKlxyXG4gKiBDaGVja2JveCBTZWxlY3Rpb24gZnVuY3Rpb25zIGZvciBMaXN0aW5nLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBTZWxlY3Rpb25zIG9mIHNldmVyYWwgIGNoZWNrYm94ZXMgbGlrZSBpbiBnTWFpbCB3aXRoIHNoaWZ0IDopXHJcbiAqIE5lZWQgdG8gIGhhdmUgdGhpcyBzdHJ1Y3R1cmU6XHJcbiAqIC53cGJjX3NlbGVjdGFibGVfdGFibGVcclxuICogICAgICAud3BiY19zZWxlY3RhYmxlX2hlYWRcclxuICogICAgICAgICAgICAgIC5jaGVjay1jb2x1bW5cclxuICogICAgICAgICAgICAgICAgICA6Y2hlY2tib3hcclxuICogICAgICAud3BiY19zZWxlY3RhYmxlX2JvZHlcclxuICogICAgICAgICAgLndwYmNfcm93XHJcbiAqICAgICAgICAgICAgICAuY2hlY2stY29sdW1uXHJcbiAqICAgICAgICAgICAgICAgICAgOmNoZWNrYm94XHJcbiAqICAgICAgLndwYmNfc2VsZWN0YWJsZV9mb290XHJcbiAqICAgICAgICAgICAgICAuY2hlY2stY29sdW1uXHJcbiAqICAgICAgICAgICAgICAgICAgOmNoZWNrYm94XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2RlZmluZV9nbWFpbF9jaGVja2JveF9zZWxlY3Rpb24oICQgKXtcclxuXHJcblx0dmFyIGNoZWNrcywgZmlyc3QsIGxhc3QsIGNoZWNrZWQsIHNsaWNlZCwgbGFzdENsaWNrZWQgPSBmYWxzZTtcclxuXHJcblx0Ly8gQ2hlY2sgYWxsIGNoZWNrYm94ZXMuXHJcblx0JCggJy53cGJjX3NlbGVjdGFibGVfYm9keScgKS5maW5kKCAnLmNoZWNrLWNvbHVtbicgKS5maW5kKCAnOmNoZWNrYm94JyApLm9uKFxyXG5cdFx0J2NsaWNrJyxcclxuXHRcdGZ1bmN0aW9uIChlKSB7XHJcblx0XHRcdGlmICggJ3VuZGVmaW5lZCcgPT0gZS5zaGlmdEtleSApIHtcclxuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAoIGUuc2hpZnRLZXkgKSB7XHJcblx0XHRcdFx0aWYgKCAhIGxhc3RDbGlja2VkICkge1xyXG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGNoZWNrcyAgPSAkKCBsYXN0Q2xpY2tlZCApLmNsb3Nlc3QoICcud3BiY19zZWxlY3RhYmxlX2JvZHknICkuZmluZCggJzpjaGVja2JveCcgKS5maWx0ZXIoICc6dmlzaWJsZTplbmFibGVkJyApO1xyXG5cdFx0XHRcdGZpcnN0ICAgPSBjaGVja3MuaW5kZXgoIGxhc3RDbGlja2VkICk7XHJcblx0XHRcdFx0bGFzdCAgICA9IGNoZWNrcy5pbmRleCggdGhpcyApO1xyXG5cdFx0XHRcdGNoZWNrZWQgPSAkKCB0aGlzICkucHJvcCggJ2NoZWNrZWQnICk7XHJcblx0XHRcdFx0aWYgKCAwIDwgZmlyc3QgJiYgMCA8IGxhc3QgJiYgZmlyc3QgIT0gbGFzdCApIHtcclxuXHRcdFx0XHRcdHNsaWNlZCA9IChsYXN0ID4gZmlyc3QpID8gY2hlY2tzLnNsaWNlKCBmaXJzdCwgbGFzdCApIDogY2hlY2tzLnNsaWNlKCBsYXN0LCBmaXJzdCApO1xyXG5cdFx0XHRcdFx0c2xpY2VkLnByb3AoXHJcblx0XHRcdFx0XHRcdCdjaGVja2VkJyxcclxuXHRcdFx0XHRcdFx0ZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRcdGlmICggJCggdGhpcyApLmNsb3Nlc3QoICcud3BiY19yb3cnICkuaXMoICc6dmlzaWJsZScgKSApIHtcclxuXHRcdFx0XHRcdFx0XHRcdHJldHVybiBjaGVja2VkO1xyXG5cdFx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdCkudHJpZ2dlciggJ2NoYW5nZScgKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdH1cclxuXHRcdFx0bGFzdENsaWNrZWQgPSB0aGlzO1xyXG5cclxuXHRcdFx0Ly8gdG9nZ2xlIFwiY2hlY2sgYWxsXCIgY2hlY2tib3hlcy5cclxuXHRcdFx0dmFyIHVuY2hlY2tlZCA9ICQoIHRoaXMgKS5jbG9zZXN0KCAnLndwYmNfc2VsZWN0YWJsZV9ib2R5JyApLmZpbmQoICc6Y2hlY2tib3gnICkuZmlsdGVyKCAnOnZpc2libGU6ZW5hYmxlZCcgKS5ub3QoICc6Y2hlY2tlZCcgKTtcclxuXHRcdFx0JCggdGhpcyApLmNsb3Nlc3QoICcud3BiY19zZWxlY3RhYmxlX3RhYmxlJyApLmNoaWxkcmVuKCAnLndwYmNfc2VsZWN0YWJsZV9oZWFkLCAud3BiY19zZWxlY3RhYmxlX2Zvb3QnICkuZmluZCggJzpjaGVja2JveCcgKS5wcm9wKFxyXG5cdFx0XHRcdCdjaGVja2VkJyxcclxuXHRcdFx0XHRmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gKDAgPT09IHVuY2hlY2tlZC5sZW5ndGgpO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0KS50cmlnZ2VyKCAnY2hhbmdlJyApO1xyXG5cclxuXHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHR9XHJcblx0KTtcclxuXHJcblx0Ly8gSGVhZCB8fCBGb290IGNsaWNraW5nIHRvICBzZWxlY3QgLyBkZXNlbGVjdCBBTEwuXHJcblx0JCggJy53cGJjX3NlbGVjdGFibGVfaGVhZCwgLndwYmNfc2VsZWN0YWJsZV9mb290JyApLmZpbmQoICcuY2hlY2stY29sdW1uIDpjaGVja2JveCcgKS5vbihcclxuXHRcdCdjbGljaycsXHJcblx0XHRmdW5jdGlvbiAoZXZlbnQpIHtcclxuXHRcdFx0dmFyICR0aGlzICAgICAgICAgID0gJCggdGhpcyApLFxyXG5cdFx0XHRcdCR0YWJsZSAgICAgICAgID0gJHRoaXMuY2xvc2VzdCggJy53cGJjX3NlbGVjdGFibGVfdGFibGUnICksXHJcblx0XHRcdFx0Y29udHJvbENoZWNrZWQgPSAkdGhpcy5wcm9wKCAnY2hlY2tlZCcgKSxcclxuXHRcdFx0XHR0b2dnbGUgICAgICAgICA9IGV2ZW50LnNoaWZ0S2V5IHx8ICR0aGlzLmRhdGEoICd3cC10b2dnbGUnICk7XHJcblxyXG5cdFx0XHQkdGFibGUuY2hpbGRyZW4oICcud3BiY19zZWxlY3RhYmxlX2JvZHknICkuZmlsdGVyKCAnOnZpc2libGUnIClcclxuXHRcdFx0XHQuZmluZCggJy5jaGVjay1jb2x1bW4nICkuZmluZCggJzpjaGVja2JveCcgKVxyXG5cdFx0XHRcdC5wcm9wKFxyXG5cdFx0XHRcdFx0J2NoZWNrZWQnLFxyXG5cdFx0XHRcdFx0ZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRpZiAoICQoIHRoaXMgKS5pcyggJzpoaWRkZW4sOmRpc2FibGVkJyApICkge1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRpZiAoIHRvZ2dsZSApIHtcclxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gISAkKCB0aGlzICkucHJvcCggJ2NoZWNrZWQnICk7XHJcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIGNvbnRyb2xDaGVja2VkICkge1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHQpLnRyaWdnZXIoICdjaGFuZ2UnICk7XHJcblxyXG5cdFx0XHQkdGFibGUuY2hpbGRyZW4oICcud3BiY19zZWxlY3RhYmxlX2hlYWQsICAud3BiY19zZWxlY3RhYmxlX2Zvb3QnICkuZmlsdGVyKCAnOnZpc2libGUnIClcclxuXHRcdFx0XHQuZmluZCggJy5jaGVjay1jb2x1bW4nICkuZmluZCggJzpjaGVja2JveCcgKVxyXG5cdFx0XHRcdC5wcm9wKFxyXG5cdFx0XHRcdFx0J2NoZWNrZWQnLFxyXG5cdFx0XHRcdFx0ZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRpZiAoIHRvZ2dsZSApIHtcclxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIGNvbnRyb2xDaGVja2VkICkge1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdH1cclxuXHRcdFx0XHQpO1xyXG5cdFx0fVxyXG5cdCk7XHJcblxyXG5cclxuXHQvLyBWaXN1YWxseSAgc2hvdyBzZWxlY3RlZCBib3JkZXIuXHJcblx0JCggJy53cGJjX3NlbGVjdGFibGVfYm9keScgKS5maW5kKCAnLmNoZWNrLWNvbHVtbiA6Y2hlY2tib3gnICkub24oXHJcblx0XHQnY2hhbmdlJyxcclxuXHRcdGZ1bmN0aW9uIChldmVudCkge1xyXG5cdFx0XHRpZiAoIGpRdWVyeSggdGhpcyApLmlzKCAnOmNoZWNrZWQnICkgKSB7XHJcblx0XHRcdFx0alF1ZXJ5KCB0aGlzICkuY2xvc2VzdCggJy53cGJjX2xpc3Rfcm93JyApLmFkZENsYXNzKCAncm93X3NlbGVjdGVkX2NvbG9yJyApO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmNsb3Nlc3QoICcud3BiY19saXN0X3JvdycgKS5yZW1vdmVDbGFzcyggJ3Jvd19zZWxlY3RlZF9jb2xvcicgKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gRGlzYWJsZSB0ZXh0IHNlbGVjdGlvbiB3aGlsZSBwcmVzc2luZyAnc2hpZnQnLlxyXG5cdFx0XHRkb2N1bWVudC5nZXRTZWxlY3Rpb24oKS5yZW1vdmVBbGxSYW5nZXMoKTtcclxuXHJcblx0XHRcdC8vIFNob3cgb3IgaGlkZSBidXR0b25zIG9uIEFjdGlvbnMgdG9vbGJhciAgYXQgIEJvb2tpbmcgTGlzdGluZyAgcGFnZSwgIGlmIHdlIGhhdmUgc29tZSBzZWxlY3RlZCBib29raW5ncy5cclxuXHRcdFx0d3BiY19zaG93X2hpZGVfYWN0aW9uX2J1dHRvbnNfZm9yX3NlbGVjdGVkX2Jvb2tpbmdzKCk7XHJcblx0XHR9XHJcblx0KTtcclxuXHJcblx0d3BiY19zaG93X2hpZGVfYWN0aW9uX2J1dHRvbnNfZm9yX3NlbGVjdGVkX2Jvb2tpbmdzKCk7XHJcbn1cclxuIiwiXHJcbi8qKlxyXG4gKiBHZXQgSUQgYXJyYXkgIG9mIHNlbGVjdGVkIGVsZW1lbnRzXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2dldF9zZWxlY3RlZF9yb3dfaWQoKSB7XHJcblxyXG5cdHZhciAkdGFibGUgICAgICA9IGpRdWVyeSggJy53cGJjX193cmFwX19ib29raW5nX2xpc3RpbmcgLndwYmNfc2VsZWN0YWJsZV90YWJsZScgKTtcclxuXHR2YXIgY2hlY2tib3hlcyAgPSAkdGFibGUuY2hpbGRyZW4oICcud3BiY19zZWxlY3RhYmxlX2JvZHknICkuZmlsdGVyKCAnOnZpc2libGUnICkuZmluZCggJy5jaGVjay1jb2x1bW4nICkuZmluZCggJzpjaGVja2JveCcgKTtcclxuXHR2YXIgc2VsZWN0ZWRfaWQgPSBbXTtcclxuXHJcblx0alF1ZXJ5LmVhY2goXHJcblx0XHRjaGVja2JveGVzLFxyXG5cdFx0ZnVuY3Rpb24gKGtleSwgY2hlY2tib3gpIHtcclxuXHRcdFx0aWYgKCBqUXVlcnkoIGNoZWNrYm94ICkuaXMoICc6Y2hlY2tlZCcgKSApIHtcclxuXHRcdFx0XHR2YXIgZWxlbWVudF9pZCA9IHdwYmNfZ2V0X3Jvd19pZF9mcm9tX2VsZW1lbnQoIGNoZWNrYm94ICk7XHJcblx0XHRcdFx0c2VsZWN0ZWRfaWQucHVzaCggZWxlbWVudF9pZCApO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0KTtcclxuXHJcblx0cmV0dXJuIHNlbGVjdGVkX2lkO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIEdldCBJRCBvZiByb3csICBiYXNlZCBvbiBjbGNpa2VkIGVsZW1lbnRcclxuICpcclxuICogQHBhcmFtIHRoaXNfaW5ib3VuZF9lbGVtZW50ICAtIHVzdXNsbHkgIHRoaXNcclxuICogQHJldHVybnMge251bWJlcn1cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfZ2V0X3Jvd19pZF9mcm9tX2VsZW1lbnQodGhpc19pbmJvdW5kX2VsZW1lbnQpIHtcclxuXHJcblx0dmFyIGVsZW1lbnRfaWQgPSBqUXVlcnkoIHRoaXNfaW5ib3VuZF9lbGVtZW50ICkuY2xvc2VzdCggJy53cGJjX2xpc3RpbmdfdXN1YWxfcm93JyApLmF0dHIoICdpZCcgKTtcclxuXHJcblx0ZWxlbWVudF9pZCA9IHBhcnNlSW50KCBlbGVtZW50X2lkLnJlcGxhY2UoICdyb3dfaWRfJywgJycgKSApO1xyXG5cclxuXHRyZXR1cm4gZWxlbWVudF9pZDtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiA9PSBCb29raW5nIExpc3RpbmcgPT0gU2hvdyBvciBoaWRlIGJ1dHRvbnMgb24gQWN0aW9ucyB0b29sYmFyICBhdCAgICBwYWdlLCAgaWYgd2UgaGF2ZSBzb21lIHNlbGVjdGVkIGJvb2tpbmdzLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19zaG93X2hpZGVfYWN0aW9uX2J1dHRvbnNfZm9yX3NlbGVjdGVkX2Jvb2tpbmdzKCl7XHJcblxyXG5cdHZhciBzZWxlY3RlZF9yb3dzX2FyciA9IHdwYmNfZ2V0X3NlbGVjdGVkX3Jvd19pZCgpO1xyXG5cclxuXHRpZiAoIHNlbGVjdGVkX3Jvd3NfYXJyLmxlbmd0aCA+IDAgKSB7XHJcblx0XHRqUXVlcnkoICcuaGlkZV9idXR0b25faWZfbm9fc2VsZWN0aW9uJyApLnNob3coKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0alF1ZXJ5KCAnLmhpZGVfYnV0dG9uX2lmX25vX3NlbGVjdGlvbicgKS5oaWRlKCk7XHJcblx0fVxyXG59IiwiXCJ1c2Ugc3RyaWN0XCI7XHJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4vLyA9PSBMZWZ0IEJhciAgLSAgZXhwYW5kIC8gY29sYXBzZSBmdW5jdGlvbnMgICA9PVxyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuXHJcbi8qKlxyXG4gKiBFeHBhbmQgVmVydGljYWwgTGVmdCBCYXIuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX2RvX21heCgpIHtcclxuXHRqUXVlcnkoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICkucmVtb3ZlQ2xhc3MoICdtaW4gbWF4IGNvbXBhY3Qgbm9uZScgKTtcclxuXHRqUXVlcnkoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICkuYWRkQ2xhc3MoICdtYXgnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9vcGVuX2xlZnRfdmVydGljYWxfbmF2JyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX2hpZGVfbGVmdF92ZXJ0aWNhbF9uYXYnICkucmVtb3ZlQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG59XHJcblxyXG4vKipcclxuICogSGlkZSBWZXJ0aWNhbCBMZWZ0IEJhci5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfbGVmdF9fZG9fbWluKCkge1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5yZW1vdmVDbGFzcyggJ21pbiBtYXggY29tcGFjdCBub25lJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5hZGRDbGFzcyggJ21pbicgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX29wZW5fbGVmdF92ZXJ0aWNhbF9uYXYnICkucmVtb3ZlQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5faGlkZV9sZWZ0X3ZlcnRpY2FsX25hdicgKS5hZGRDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb2xhcHNlIFZlcnRpY2FsIExlZnQgQmFyLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9sZWZ0X19kb19jb21wYWN0KCkge1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5yZW1vdmVDbGFzcyggJ21pbiBtYXggY29tcGFjdCBub25lJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5hZGRDbGFzcyggJ2NvbXBhY3QnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9vcGVuX2xlZnRfdmVydGljYWxfbmF2JyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX2hpZGVfbGVmdF92ZXJ0aWNhbF9uYXYnICkuYWRkQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG59XHJcblxyXG4vKipcclxuICogQ29tcGxldGVseSBIaWRlIFZlcnRpY2FsIExlZnQgQmFyLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9sZWZ0X19kb19oaWRlKCkge1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5yZW1vdmVDbGFzcyggJ21pbiBtYXggY29tcGFjdCBub25lJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5hZGRDbGFzcyggJ25vbmUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9vcGVuX2xlZnRfdmVydGljYWxfbmF2JyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX2hpZGVfbGVmdF92ZXJ0aWNhbF9uYXYnICkuYWRkQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG5cdC8vIEhpZGUgdG9wIFwiTWVudVwiIGJ1dHRvbiB3aXRoIGRpdmlkZXIuXHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9zaG93X2xlZnRfdmVydGljYWxfbmF2LC53cGJjX3VpX190b3BfbmF2X19idG5fc2hvd19sZWZ0X3ZlcnRpY2FsX25hdl9kaXZpZGVyJyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEFjdGlvbiBvbiBjbGljayBcIkdvIEJhY2tcIiAtIHNob3cgcm9vdCBtZW51XHJcbiAqIG9yIHNvbWUgb3RoZXIgc2VjdGlvbiBpbiBsZWZ0IHNpZGViYXIuXHJcbiAqXHJcbiAqIEBwYXJhbSBzdHJpbmcgbWVudV90b19zaG93IC0gbWVudSBzbHVnLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9sZWZ0X19zaG93X3NlY3Rpb24oIG1lbnVfdG9fc2hvdyApIHtcclxuXHRqUXVlcnkoICcud3BiY191aV9lbF9fdmVydF9sZWZ0X2Jhcl9fc2VjdGlvbicgKS5hZGRDbGFzcyggJ3dwYmNfdWlfX2hpZGUnIClcclxuXHRqUXVlcnkoICcud3BiY191aV9lbF9fdmVydF9sZWZ0X2Jhcl9fc2VjdGlvbl8nICsgbWVudV90b19zaG93ICkucmVtb3ZlQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIEdldCBhbmNob3IocykgYXJyYXkgIGZyb20gIFVSTC5cclxuICogRG9jOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTG9jYXRpb25cclxuICpcclxuICogQHJldHVybnMgeypbXX1cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfdXJsX2dldF9hbmNob3JzX2FycigpIHtcclxuXHR2YXIgaGFzaGVzICAgICAgICAgICAgPSB3aW5kb3cubG9jYXRpb24uaGFzaC5yZXBsYWNlKCAnJTIzJywgJyMnICk7XHJcblx0dmFyIGhhc2hlc19hcnIgICAgICAgID0gaGFzaGVzLnNwbGl0KCAnIycgKTtcclxuXHR2YXIgcmVzdWx0ICAgICAgICAgICAgPSBbXTtcclxuXHR2YXIgaGFzaGVzX2Fycl9sZW5ndGggPSBoYXNoZXNfYXJyLmxlbmd0aDtcclxuXHJcblx0Zm9yICggdmFyIGkgPSAwOyBpIDwgaGFzaGVzX2Fycl9sZW5ndGg7IGkrKyApIHtcclxuXHRcdGlmICggaGFzaGVzX2FycltpXS5sZW5ndGggPiAwICkge1xyXG5cdFx0XHRyZXN1bHQucHVzaCggaGFzaGVzX2FycltpXSApO1xyXG5cdFx0fVxyXG5cdH1cclxuXHRyZXR1cm4gcmVzdWx0O1xyXG59XHJcblxyXG4vKipcclxuICogQXV0byBFeHBhbmQgU2V0dGluZ3Mgc2VjdGlvbiBiYXNlZCBvbiBVUkwgYW5jaG9yLCBhZnRlciAgcGFnZSBsb2FkZWQuXHJcbiAqL1xyXG5qUXVlcnkoIGRvY3VtZW50ICkucmVhZHkoIGZ1bmN0aW9uICgpIHsgd3BiY19hZG1pbl91aV9fZG9fZXhwYW5kX3NlY3Rpb24oKTsgc2V0VGltZW91dCggJ3dwYmNfYWRtaW5fdWlfX2RvX2V4cGFuZF9zZWN0aW9uJywgMTAgKTsgfSApO1xyXG5qUXVlcnkoIGRvY3VtZW50ICkucmVhZHkoIGZ1bmN0aW9uICgpIHsgd3BiY19hZG1pbl91aV9fZG9fZXhwYW5kX3NlY3Rpb24oKTsgc2V0VGltZW91dCggJ3dwYmNfYWRtaW5fdWlfX2RvX2V4cGFuZF9zZWN0aW9uJywgMTUwICk7IH0gKTtcclxuXHJcbi8qKlxyXG4gKiBFeHBhbmQgc2VjdGlvbiBpbiAgR2VuZXJhbCBTZXR0aW5ncyBwYWdlIGFuZCBzZWxlY3QgTWVudSBpdGVtLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fZG9fZXhwYW5kX3NlY3Rpb24oKSB7XHJcblxyXG5cdC8vIHdpbmRvdy5sb2NhdGlvbi5oYXNoICA9ICNzZWN0aW9uX2lkICAvICBkb2M6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Mb2NhdGlvbiAuXHJcblx0dmFyIGFuY2hvcnNfYXJyICAgICAgICA9IHdwYmNfdXJsX2dldF9hbmNob3JzX2FycigpO1xyXG5cdHZhciBhbmNob3JzX2Fycl9sZW5ndGggPSBhbmNob3JzX2Fyci5sZW5ndGg7XHJcblxyXG5cdGlmICggYW5jaG9yc19hcnJfbGVuZ3RoID4gMCApIHtcclxuXHRcdHZhciBvbmVfYW5jaG9yX3Byb3BfdmFsdWUgPSBhbmNob3JzX2FyclswXS5zcGxpdCggJ2RvX2V4cGFuZF9fJyApO1xyXG5cdFx0aWYgKCBvbmVfYW5jaG9yX3Byb3BfdmFsdWUubGVuZ3RoID4gMSApIHtcclxuXHJcblx0XHRcdC8vICd3cGJjX2dlbmVyYWxfc2V0dGluZ3NfY2FsZW5kYXJfbWV0YWJveCdcclxuXHRcdFx0dmFyIHNlY3Rpb25fdG9fc2hvdyAgICA9IG9uZV9hbmNob3JfcHJvcF92YWx1ZVsxXTtcclxuXHRcdFx0dmFyIHNlY3Rpb25faWRfdG9fc2hvdyA9ICcjJyArIHNlY3Rpb25fdG9fc2hvdztcclxuXHJcblxyXG5cdFx0XHQvLyAtLSBSZW1vdmUgc2VsZWN0ZWQgYmFja2dyb3VuZCBpbiBhbGwgbGVmdCAgbWVudSAgaXRlbXMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHRcdGpRdWVyeSggJy53cGJjX3VpX2VsX192ZXJ0X25hdl9pdGVtICcgKS5yZW1vdmVDbGFzcyggJ2FjdGl2ZScgKTtcclxuXHRcdFx0Ly8gU2V0IGxlZnQgbWVudSBzZWxlY3RlZC5cclxuXHRcdFx0alF1ZXJ5KCAnLmRvX2V4cGFuZF9fJyArIHNlY3Rpb25fdG9fc2hvdyArICdfbGluaycgKS5hZGRDbGFzcyggJ2FjdGl2ZScgKTtcclxuXHRcdFx0dmFyIHNlbGVjdGVkX3RpdGxlID0galF1ZXJ5KCAnLmRvX2V4cGFuZF9fJyArIHNlY3Rpb25fdG9fc2hvdyArICdfbGluayBhIC53cGJjX3VpX2VsX192ZXJ0X25hdl90aXRsZSAnICkudGV4dCgpO1xyXG5cclxuXHRcdFx0Ly8gRXhwYW5kIHNlY3Rpb24sIGlmIGl0IGNvbGFwc2VkLlxyXG5cdFx0XHRpZiAoICEgalF1ZXJ5KCAnLmRvX2V4cGFuZF9fJyArIHNlY3Rpb25fdG9fc2hvdyArICdfbGluaycgKS5wYXJlbnRzKCAnLndwYmNfdWlfZWxfX2xldmVsX19mb2xkZXInICkuaGFzQ2xhc3MoICdleHBhbmRlZCcgKSApIHtcclxuXHRcdFx0XHRqUXVlcnkoICcud3BiY191aV9lbF9fbGV2ZWxfX2ZvbGRlcicgKS5yZW1vdmVDbGFzcyggJ2V4cGFuZGVkJyApO1xyXG5cdFx0XHRcdGpRdWVyeSggJy5kb19leHBhbmRfXycgKyBzZWN0aW9uX3RvX3Nob3cgKyAnX2xpbmsnICkucGFyZW50cyggJy53cGJjX3VpX2VsX19sZXZlbF9fZm9sZGVyJyApLmFkZENsYXNzKCAnZXhwYW5kZWQnICk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIC0tIEV4cGFuZCBzZWN0aW9uIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0XHR2YXIgY29udGFpbmVyX3RvX2hpZGVfY2xhc3MgPSAnLnBvc3Rib3gnO1xyXG5cdFx0XHQvLyBIaWRlIHNlY3Rpb25zICcucG9zdGJveCcgaW4gYWRtaW4gcGFnZSBhbmQgc2hvdyBzcGVjaWZpYyBvbmUuXHJcblx0XHRcdGpRdWVyeSggJy53cGJjX2FkbWluX3BhZ2UgJyArIGNvbnRhaW5lcl90b19oaWRlX2NsYXNzICkuaGlkZSgpO1xyXG5cdFx0XHRqUXVlcnkoICcud3BiY19jb250YWluZXJfYWx3YXlzX2hpZGVfX29uX2xlZnRfbmF2X2NsaWNrJyApLmhpZGUoKTtcclxuXHRcdFx0alF1ZXJ5KCBzZWN0aW9uX2lkX3RvX3Nob3cgKS5zaG93KCk7XHJcblxyXG5cdFx0XHQvLyBTaG93IGFsbCBvdGhlciBzZWN0aW9ucywgIGlmIHByb3ZpZGVkIGluIFVSTDogLi4/cGFnZT13cGJjLXNldHRpbmdzI2RvX2V4cGFuZF9fd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhcGFjaXR5X21ldGFib3gjd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhcGFjaXR5X3VwZ3JhZGVfbWV0YWJveCAuXHJcblx0XHRcdGZvciAoIGxldCBpID0gMTsgaSA8IGFuY2hvcnNfYXJyX2xlbmd0aDsgaSsrICkge1xyXG5cdFx0XHRcdGpRdWVyeSggJyMnICsgYW5jaG9yc19hcnJbaV0gKS5zaG93KCk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdGlmICggZmFsc2UgKSB7XHJcblx0XHRcdFx0dmFyIHRhcmdldE9mZnNldCA9IHdwYmNfc2Nyb2xsX3RvKCBzZWN0aW9uX2lkX3RvX3Nob3cgKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gLS0gU2V0IFZhbHVlIHRvIElucHV0IGFib3V0IHNlbGVjdGVkIE5hdiBlbGVtZW50ICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gICAgICAgLy8gRml4SW46IDkuOC42LjEuXHJcblx0XHRcdHZhciBzZWN0aW9uX2lkX3RhYiA9IHNlY3Rpb25faWRfdG9fc2hvdy5zdWJzdHJpbmcoIDAsIHNlY3Rpb25faWRfdG9fc2hvdy5sZW5ndGggLSA4ICkgKyAnX3RhYic7XHJcblx0XHRcdGlmICggY29udGFpbmVyX3RvX2hpZGVfY2xhc3MgPT0gc2VjdGlvbl9pZF90b19zaG93ICkge1xyXG5cdFx0XHRcdHNlY3Rpb25faWRfdGFiID0gJyN3cGJjX2dlbmVyYWxfc2V0dGluZ3NfYWxsX3RhYidcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAoICcjd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhcGFjaXR5X21ldGFib3gsI3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYXBhY2l0eV91cGdyYWRlX21ldGFib3gnID09IHNlY3Rpb25faWRfdG9fc2hvdyApIHtcclxuXHRcdFx0XHRzZWN0aW9uX2lkX3RhYiA9ICcjd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhcGFjaXR5X3RhYidcclxuXHRcdFx0fVxyXG5cdFx0XHRqUXVlcnkoICcjZm9ybV92aXNpYmxlX3NlY3Rpb24nICkudmFsKCBzZWN0aW9uX2lkX3RhYiApO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIExpa2UgYmxpbmtpbmcgc29tZSBlbGVtZW50cy5cclxuXHRcdHdwYmNfYWRtaW5fdWlfX2RvX19hbmNob3JfX2Fub3RoZXJfYWN0aW9ucygpO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE9wZW4gc2V0dGluZ3MgcGFnZSAgfCAgRXhwYW5kIHNlY3Rpb24gIHwgIFNlbGVjdCBNZW51IGl0ZW0uXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19kb19fb3Blbl91cmxfX2V4cGFuZF9zZWN0aW9uKHVybCwgc2VjdGlvbl9pZCkge1xyXG5cclxuXHQvLyB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybCArICcmZG9fZXhwYW5kPScgKyBzZWN0aW9uX2lkICsgJyNkb19leHBhbmRfXycgKyBzZWN0aW9uX2lkOyAvLy5cclxuXHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybCArICcjZG9fZXhwYW5kX18nICsgc2VjdGlvbl9pZDtcclxuXHJcblx0d3BiY19hZG1pbl91aV9fZG9fZXhwYW5kX3NlY3Rpb24oKTtcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBDaGVjayAgZm9yIE90aGVyIGFjdGlvbnM6ICBMaWtlIGJsaW5raW5nIHNvbWUgZWxlbWVudHMgaW4gc2V0dGluZ3MgcGFnZS4gRS5nLiBEYXlzIHNlbGVjdGlvbiAgb3IgIGNoYW5nZS1vdmVyIGRheXMuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19kb19fYW5jaG9yX19hbm90aGVyX2FjdGlvbnMoKSB7XHJcblxyXG5cdHZhciBhbmNob3JzX2FyciAgICAgICAgPSB3cGJjX3VybF9nZXRfYW5jaG9yc19hcnIoKTtcclxuXHR2YXIgYW5jaG9yc19hcnJfbGVuZ3RoID0gYW5jaG9yc19hcnIubGVuZ3RoO1xyXG5cclxuXHQvLyBPdGhlciBhY3Rpb25zOiAgTGlrZSBibGlua2luZyBzb21lIGVsZW1lbnRzLlxyXG5cdGZvciAoIHZhciBpID0gMDsgaSA8IGFuY2hvcnNfYXJyX2xlbmd0aDsgaSsrICkge1xyXG5cclxuXHRcdHZhciB0aGlzX2FuY2hvciA9IGFuY2hvcnNfYXJyW2ldO1xyXG5cclxuXHRcdHZhciB0aGlzX2FuY2hvcl9wcm9wX3ZhbHVlID0gdGhpc19hbmNob3Iuc3BsaXQoICdkb19vdGhlcl9hY3Rpb25zX18nICk7XHJcblxyXG5cdFx0aWYgKCB0aGlzX2FuY2hvcl9wcm9wX3ZhbHVlLmxlbmd0aCA+IDEgKSB7XHJcblxyXG5cdFx0XHR2YXIgc2VjdGlvbl9hY3Rpb24gPSB0aGlzX2FuY2hvcl9wcm9wX3ZhbHVlWzFdO1xyXG5cclxuXHRcdFx0c3dpdGNoICggc2VjdGlvbl9hY3Rpb24gKSB7XHJcblxyXG5cdFx0XHRcdGNhc2UgJ2JsaW5rX2RheV9zZWxlY3Rpb25zJzpcclxuXHRcdFx0XHRcdC8vIHdwYmNfdWlfc2V0dGluZ3NfX3BhbmVsX19jbGljayggJyN3cGJjX2dlbmVyYWxfc2V0dGluZ3NfY2FsZW5kYXJfdGFiIGEnLCAnI3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYWxlbmRhcl9tZXRhYm94JywgJ0RheXMgU2VsZWN0aW9uJyApOy5cclxuXHRcdFx0XHRcdHdwYmNfYmxpbmtfZWxlbWVudCggJy53cGJjX3RyX3NldF9nZW5fYm9va2luZ190eXBlX29mX2RheV9zZWxlY3Rpb25zJywgNCwgMzUwICk7XHJcblx0XHRcdFx0XHRcdHdwYmNfc2Nyb2xsX3RvKCAnLndwYmNfdHJfc2V0X2dlbl9ib29raW5nX3R5cGVfb2ZfZGF5X3NlbGVjdGlvbnMnICk7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0Y2FzZSAnYmxpbmtfY2hhbmdlX292ZXJfZGF5cyc6XHJcblx0XHRcdFx0XHQvLyB3cGJjX3VpX3NldHRpbmdzX19wYW5lbF9fY2xpY2soICcjd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhbGVuZGFyX3RhYiBhJywgJyN3cGJjX2dlbmVyYWxfc2V0dGluZ3NfY2FsZW5kYXJfbWV0YWJveCcsICdDaGFuZ2VvdmVyIERheXMnICk7LlxyXG5cdFx0XHRcdFx0d3BiY19ibGlua19lbGVtZW50KCAnLndwYmNfdHJfc2V0X2dlbl9ib29raW5nX3JhbmdlX3NlbGVjdGlvbl90aW1lX2lzX2FjdGl2ZScsIDQsIDM1MCApO1xyXG5cdFx0XHRcdFx0XHR3cGJjX3Njcm9sbF90byggJy53cGJjX3RyX3NldF9nZW5fYm9va2luZ19yYW5nZV9zZWxlY3Rpb25fdGltZV9pc19hY3RpdmUnICk7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0Y2FzZSAnYmxpbmtfY2FwdGNoYSc6XHJcblx0XHRcdFx0XHR3cGJjX2JsaW5rX2VsZW1lbnQoICcud3BiY190cl9zZXRfZ2VuX2Jvb2tpbmdfaXNfdXNlX2NhcHRjaGEnLCA0LCAzNTAgKTtcclxuXHRcdFx0XHRcdFx0d3BiY19zY3JvbGxfdG8oICcud3BiY190cl9zZXRfZ2VuX2Jvb2tpbmdfaXNfdXNlX2NhcHRjaGEnICk7XHJcblx0XHRcdFx0XHRicmVhaztcclxuXHJcblx0XHRcdFx0ZGVmYXVsdDpcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH1cclxufSIsIi8qKlxyXG4gKiBDb3B5IHR4dCB0byBjbGlwYnJkIGZyb20gVGV4dCBmaWVsZHMuXHJcbiAqXHJcbiAqIEBwYXJhbSBodG1sX2VsZW1lbnRfaWQgIC0gZS5nLiAnZGF0YV9maWVsZCdcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2NvcHlfdGV4dF90b19jbGlwYnJkX2Zyb21fZWxlbWVudCggaHRtbF9lbGVtZW50X2lkICkge1xyXG5cdC8vIEdldCB0aGUgdGV4dCBmaWVsZC5cclxuXHR2YXIgY29weVRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggaHRtbF9lbGVtZW50X2lkICk7XHJcblxyXG5cdC8vIFNlbGVjdCB0aGUgdGV4dCBmaWVsZC5cclxuXHRjb3B5VGV4dC5zZWxlY3QoKTtcclxuXHRjb3B5VGV4dC5zZXRTZWxlY3Rpb25SYW5nZSggMCwgOTk5OTkgKTsgLy8gRm9yIG1vYmlsZSBkZXZpY2VzLlxyXG5cclxuXHQvLyBDb3B5IHRoZSB0ZXh0IGluc2lkZSB0aGUgdGV4dCBmaWVsZC5cclxuXHR2YXIgaXNfY29waWVkID0gd3BiY19jb3B5X3RleHRfdG9fY2xpcGJyZCggY29weVRleHQudmFsdWUgKTtcclxuXHRpZiAoICEgaXNfY29waWVkICkge1xyXG5cdFx0Y29uc29sZS5lcnJvciggJ09vcHMsIHVuYWJsZSB0byBjb3B5JywgY29weVRleHQudmFsdWUgKTtcclxuXHR9XHJcblx0cmV0dXJuIGlzX2NvcGllZDtcclxufVxyXG5cclxuLyoqXHJcbiAqIENvcHkgdHh0IHRvIGNsaXBicmQuXHJcbiAqXHJcbiAqIEBwYXJhbSB0ZXh0XHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jb3B5X3RleHRfdG9fY2xpcGJyZCh0ZXh0KSB7XHJcblxyXG5cdGlmICggISBuYXZpZ2F0b3IuY2xpcGJvYXJkICkge1xyXG5cdFx0cmV0dXJuIHdwYmNfZmFsbGJhY2tfY29weV90ZXh0X3RvX2NsaXBicmQoIHRleHQgKTtcclxuXHR9XHJcblxyXG5cdG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KCB0ZXh0ICkudGhlbihcclxuXHRcdGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0Ly8gY29uc29sZS5sb2coICdBc3luYzogQ29weWluZyB0byBjbGlwYm9hcmQgd2FzIHN1Y2Nlc3NmdWwhJyApOy5cclxuXHRcdFx0cmV0dXJuICB0cnVlO1xyXG5cdFx0fSxcclxuXHRcdGZ1bmN0aW9uIChlcnIpIHtcclxuXHRcdFx0Ly8gY29uc29sZS5lcnJvciggJ0FzeW5jOiBDb3VsZCBub3QgY29weSB0ZXh0OiAnLCBlcnIgKTsuXHJcblx0XHRcdHJldHVybiAgZmFsc2U7XHJcblx0XHR9XHJcblx0KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENvcHkgdHh0IHRvIGNsaXBicmQgLSBkZXByaWNhdGVkIG1ldGhvZC5cclxuICpcclxuICogQHBhcmFtIHRleHRcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2ZhbGxiYWNrX2NvcHlfdGV4dF90b19jbGlwYnJkKCB0ZXh0ICkge1xyXG5cclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIHZhciB0ZXh0QXJlYSAgID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJ0ZXh0YXJlYVwiICk7XHJcblx0Ly8gdGV4dEFyZWEudmFsdWUgPSB0ZXh0O1xyXG5cdC8vXHJcblx0Ly8gLy8gQXZvaWQgc2Nyb2xsaW5nIHRvIGJvdHRvbS5cclxuXHQvLyB0ZXh0QXJlYS5zdHlsZS50b3AgICAgICA9IFwiMFwiO1xyXG5cdC8vIHRleHRBcmVhLnN0eWxlLmxlZnQgICAgID0gXCIwXCI7XHJcblx0Ly8gdGV4dEFyZWEuc3R5bGUucG9zaXRpb24gPSBcImZpeGVkXCI7XHJcblx0Ly8gdGV4dEFyZWEuc3R5bGUuekluZGV4ICAgPSBcIjk5OTk5OTk5OVwiO1xyXG5cdC8vIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoIHRleHRBcmVhICk7XHJcblx0Ly8gdGV4dEFyZWEuZm9jdXMoKTtcclxuXHQvLyB0ZXh0QXJlYS5zZWxlY3QoKTtcclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBOb3cgZ2V0IGl0IGFzIEhUTUwgIChvcmlnaW5hbCBoZXJlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM0MTkxNzgwL2phdmFzY3JpcHQtY29weS1zdHJpbmctdG8tY2xpcGJvYXJkLWFzLXRleHQtaHRtbCApLlxyXG5cclxuXHQvLyBbMV0gLSBDcmVhdGUgY29udGFpbmVyIGZvciB0aGUgSFRNTC5cclxuXHR2YXIgY29udGFpbmVyICAgICAgID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2RpdicgKTtcclxuXHRjb250YWluZXIuaW5uZXJIVE1MID0gdGV4dDtcclxuXHJcblx0Ly8gWzJdIC0gSGlkZSBlbGVtZW50LlxyXG5cdGNvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiAgICAgID0gJ2ZpeGVkJztcclxuXHRjb250YWluZXIuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcclxuXHRjb250YWluZXIuc3R5bGUub3BhY2l0eSAgICAgICA9IDA7XHJcblxyXG5cdC8vIERldGVjdCBhbGwgc3R5bGUgc2hlZXRzIG9mIHRoZSBwYWdlLlxyXG5cdHZhciBhY3RpdmVTaGVldHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCggZG9jdW1lbnQuc3R5bGVTaGVldHMgKS5maWx0ZXIoXHJcblx0XHRmdW5jdGlvbiAoc2hlZXQpIHtcclxuXHRcdFx0cmV0dXJuICEgc2hlZXQuZGlzYWJsZWQ7XHJcblx0XHR9XHJcblx0KTtcclxuXHJcblx0Ly8gWzNdIC0gTW91bnQgdGhlIGNvbnRhaW5lciB0byB0aGUgRE9NIHRvIG1ha2UgYGNvbnRlbnRXaW5kb3dgIGF2YWlsYWJsZS5cclxuXHRkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKCBjb250YWluZXIgKTtcclxuXHJcblx0Ly8gWzRdIC0gQ29weSB0byBjbGlwYm9hcmQuXHJcblx0d2luZG93LmdldFNlbGVjdGlvbigpLnJlbW92ZUFsbFJhbmdlcygpO1xyXG5cclxuXHR2YXIgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xyXG5cdHJhbmdlLnNlbGVjdE5vZGUoIGNvbnRhaW5lciApO1xyXG5cdHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5hZGRSYW5nZSggcmFuZ2UgKTtcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHR2YXIgcmVzdWx0ID0gZmFsc2U7XHJcblxyXG5cdHRyeSB7XHJcblx0XHRyZXN1bHQgPSBkb2N1bWVudC5leGVjQ29tbWFuZCggJ2NvcHknICk7XHJcblx0XHQvLyBjb25zb2xlLmxvZyggJ0ZhbGxiYWNrOiBDb3B5aW5nIHRleHQgY29tbWFuZCB3YXMgJyArIG1zZyApOyAvLy5cclxuXHR9IGNhdGNoICggZXJyICkge1xyXG5cdFx0Ly8gY29uc29sZS5lcnJvciggJ0ZhbGxiYWNrOiBPb3BzLCB1bmFibGUgdG8gY29weScsIGVyciApOyAvLy5cclxuXHR9XHJcblx0Ly8gZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZCggdGV4dEFyZWEgKTsgLy8uXHJcblxyXG5cdC8vIFs1LjRdIC0gRW5hYmxlIENTUy5cclxuXHR2YXIgYWN0aXZlU2hlZXRzX2xlbmd0aCA9IGFjdGl2ZVNoZWV0cy5sZW5ndGg7XHJcblx0Zm9yICggdmFyIGkgPSAwOyBpIDwgYWN0aXZlU2hlZXRzX2xlbmd0aDsgaSsrICkge1xyXG5cdFx0YWN0aXZlU2hlZXRzW2ldLmRpc2FibGVkID0gZmFsc2U7XHJcblx0fVxyXG5cclxuXHQvLyBbNl0gLSBSZW1vdmUgdGhlIGNvbnRhaW5lclxyXG5cdGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoIGNvbnRhaW5lciApO1xyXG5cclxuXHRyZXR1cm4gIHJlc3VsdDtcclxufSJdfQ== | |
| 1055 | +} | |
| 1056 | +/** | |
| 1057 | + * WPBC Collapsible Groups | |
| 1058 | + * | |
| 1059 | + * Universal, dependency-free controller for expanding/collapsing grouped sections in right-side panels (Inspector/Library/Form Settings, or any other WPBC page). | |
| 1060 | + * | |
| 1061 | + * === How to use it (quick) ? === | |
| 1062 | + * | |
| 1063 | + * -- 1. Markup (independent mode: multiple open allowed) -- | |
| 1064 | + * <div class="wpbc_collapsible"> | |
| 1065 | + * <section class="wpbc_ui__collapsible_group is-open"> | |
| 1066 | + * <button type="button" class="group__header"><h3>General</h3></button> | |
| 1067 | + * <div class="group__fields">…</div> | |
| 1068 | + * </section> | |
| 1069 | + * <section class="wpbc_ui__collapsible_group"> | |
| 1070 | + * <button type="button" class="group__header"><h3>Advanced</h3></button> | |
| 1071 | + * <div class="group__fields">…</div> | |
| 1072 | + * </section> | |
| 1073 | + * </div> | |
| 1074 | + * | |
| 1075 | + * -- 2. Exclusive/accordion mode (one open at a time) -- | |
| 1076 | + * <div class="wpbc_collapsible wpbc_collapsible--exclusive">…</div> | |
| 1077 | + * | |
| 1078 | + * -- 3. Auto-init -- | |
| 1079 | + * The script auto-initializes on DOMContentLoaded. No extra code needed. | |
| 1080 | + * | |
| 1081 | + * -- 4. Programmatic control (optional) | |
| 1082 | + * const root = document.querySelector('#wpbc_bfb__inspector'); | |
| 1083 | + * const api = root.__wpbc_collapsible_instance; // set by auto-init | |
| 1084 | + * | |
| 1085 | + * api.open_by_heading('Validation'); // open by heading text | |
| 1086 | + * api.open_by_index(0); // open the first group | |
| 1087 | + * | |
| 1088 | + * -- 5.Listen to events (e.g., to persist “open group” state) -- | |
| 1089 | + * root.addEventListener('wpbc:collapsible:open', (e) => { console.log( e.detail.group ); }); | |
| 1090 | + * root.addEventListener('wpbc:collapsible:close', (e) => { console.log( e.detail.group ); }); | |
| 1091 | + * | |
| 1092 | + * | |
| 1093 | + * | |
| 1094 | + * Markup expectations (minimal): | |
| 1095 | + * <div class="wpbc_collapsible [wpbc_collapsible--exclusive]"> | |
| 1096 | + * <section class="wpbc_ui__collapsible_group [is-open]"> | |
| 1097 | + * <button type="button" class="group__header"> ... </button> | |
| 1098 | + * <div class="group__fields"> ... </div> | |
| 1099 | + * </section> | |
| 1100 | + * ... more <section> ... | |
| 1101 | + * </div> | |
| 1102 | + * | |
| 1103 | + * Notes: | |
| 1104 | + * - Add `is-open` to any section you want initially expanded. | |
| 1105 | + * - Add `wpbc_collapsible--exclusive` to the container for "open one at a time" behavior. | |
| 1106 | + * - Works with your existing BFB markup (classes used there are the defaults). | |
| 1107 | + * | |
| 1108 | + * Accessibility: | |
| 1109 | + * - Sets aria-expanded on .group__header | |
| 1110 | + * - Sets aria-hidden + [hidden] on .group__fields | |
| 1111 | + * - ArrowUp/ArrowDown move focus between headers; Enter/Space toggles | |
| 1112 | + * | |
| 1113 | + * Events (bubbles from the <section>): | |
| 1114 | + * - 'wpbc:collapsible:open' (detail: { group, root, instance }) | |
| 1115 | + * - 'wpbc:collapsible:close' (detail: { group, root, instance }) | |
| 1116 | + * | |
| 1117 | + * Public API (instance methods): | |
| 1118 | + * - init(), destroy(), refresh() | |
| 1119 | + * - expand(group, [exclusive]), collapse(group), toggle(group) | |
| 1120 | + * - open_by_index(index), open_by_heading(text) | |
| 1121 | + * - is_exclusive(), is_open(group) | |
| 1122 | + * | |
| 1123 | + * @version 2025-08-26 | |
| 1124 | + * @since 2025-08-26 | |
| 1125 | + */ | |
| 1126 | +// --------------------------------------------------------------------------------------------------------------------- | |
| 1127 | +// == File /collapsible_groups.js == Time point: 2025-08-26 14:13 | |
| 1128 | +// --------------------------------------------------------------------------------------------------------------------- | |
| 1129 | +(function (w, d) { | |
| 1130 | + 'use strict'; | |
| 1131 | + | |
| 1132 | + class WPBC_Collapsible_Groups { | |
| 1133 | + | |
| 1134 | + /** | |
| 1135 | + * Create a collapsible controller for a container. | |
| 1136 | + * | |
| 1137 | + * @param {HTMLElement|string} root_el | |
| 1138 | + * The container element (or CSS selector) that wraps collapsible groups. | |
| 1139 | + * The container usually has the class `.wpbc_collapsible`. | |
| 1140 | + * @param {Object} [opts={}] | |
| 1141 | + * @param {string} [opts.group_selector='.wpbc_ui__collapsible_group'] | |
| 1142 | + * Selector for each collapsible group inside the container. | |
| 1143 | + * @param {string} [opts.header_selector='.group__header'] | |
| 1144 | + * Selector for the clickable header inside a group. | |
| 1145 | + * @param {string} [opts.fields_selector='.group__fields'] | |
| 1146 | + * Selector for the content/panel element inside a group. | |
| 1147 | + * @param {string} [opts.open_class='is-open'] | |
| 1148 | + * Class name that indicates the group is open. | |
| 1149 | + * @param {boolean} [opts.exclusive=false] | |
| 1150 | + * If true, only one group can be open at a time in this container. | |
| 1151 | + * | |
| 1152 | + * @constructor | |
| 1153 | + * @since 2025-08-26 | |
| 1154 | + */ | |
| 1155 | + constructor(root_el, opts = {}) { | |
| 1156 | + this.root = (typeof root_el === 'string') ? d.querySelector( root_el ) : root_el; | |
| 1157 | + this.opts = Object.assign( { | |
| 1158 | + group_selector : '.wpbc_ui__collapsible_group', | |
| 1159 | + header_selector: '.group__header', | |
| 1160 | + fields_selector: '.group__fields,.group__content', | |
| 1161 | + open_class : 'is-open', | |
| 1162 | + exclusive : false | |
| 1163 | + }, opts ); | |
| 1164 | + | |
| 1165 | + // Bound handlers (for add/removeEventListener symmetry). | |
| 1166 | + /** @private */ | |
| 1167 | + this._on_click = this._on_click.bind( this ); | |
| 1168 | + /** @private */ | |
| 1169 | + this._on_keydown = this._on_keydown.bind( this ); | |
| 1170 | + | |
| 1171 | + /** @type {HTMLElement[]} @private */ | |
| 1172 | + this._groups = []; | |
| 1173 | + /** @type {MutationObserver|null} @private */ | |
| 1174 | + this._observer = null; | |
| 1175 | + } | |
| 1176 | + | |
| 1177 | + /** | |
| 1178 | + * Initialize the controller: cache groups, attach listeners, set ARIA, | |
| 1179 | + * and start observing DOM changes inside the container. | |
| 1180 | + * | |
| 1181 | + * @returns {WPBC_Collapsible_Groups} The instance (chainable). | |
| 1182 | + * @listens click | |
| 1183 | + * @listens keydown | |
| 1184 | + * @since 2025-08-26 | |
| 1185 | + */ | |
| 1186 | + init() { | |
| 1187 | + if ( !this.root ) { | |
| 1188 | + return this; | |
| 1189 | + } | |
| 1190 | + this._groups = Array.prototype.slice.call( | |
| 1191 | + this.root.querySelectorAll( this.opts.group_selector ) | |
| 1192 | + ); | |
| 1193 | + this.root.addEventListener( 'click', this._on_click, false ); | |
| 1194 | + this.root.addEventListener( 'keydown', this._on_keydown, false ); | |
| 1195 | + | |
| 1196 | + // Observe dynamic inserts/removals (Inspector re-renders). | |
| 1197 | + this._observer = new MutationObserver( () => { | |
| 1198 | + this.refresh(); | |
| 1199 | + } ); | |
| 1200 | + this._observer.observe( this.root, { childList: true, subtree: true } ); | |
| 1201 | + | |
| 1202 | + this._sync_all_aria(); | |
| 1203 | + return this; | |
| 1204 | + } | |
| 1205 | + | |
| 1206 | + /** | |
| 1207 | + * Tear down the controller: detach listeners, stop the observer, | |
| 1208 | + * and drop internal references. | |
| 1209 | + * | |
| 1210 | + * @returns {void} | |
| 1211 | + * @since 2025-08-26 | |
| 1212 | + */ | |
| 1213 | + destroy() { | |
| 1214 | + if ( !this.root ) { | |
| 1215 | + return; | |
| 1216 | + } | |
| 1217 | + this.root.removeEventListener( 'click', this._on_click, false ); | |
| 1218 | + this.root.removeEventListener( 'keydown', this._on_keydown, false ); | |
| 1219 | + if ( this._observer ) { | |
| 1220 | + this._observer.disconnect(); | |
| 1221 | + this._observer = null; | |
| 1222 | + } | |
| 1223 | + this._groups = []; | |
| 1224 | + } | |
| 1225 | + | |
| 1226 | + /** | |
| 1227 | + * Re-scan the DOM for current groups and re-apply ARIA to all of them. | |
| 1228 | + * Useful after dynamic (re)renders. | |
| 1229 | + * | |
| 1230 | + * @returns {void} | |
| 1231 | + * @since 2025-08-26 | |
| 1232 | + */ | |
| 1233 | + refresh() { | |
| 1234 | + if ( !this.root ) { | |
| 1235 | + return; | |
| 1236 | + } | |
| 1237 | + this._groups = Array.prototype.slice.call( | |
| 1238 | + this.root.querySelectorAll( this.opts.group_selector ) | |
| 1239 | + ); | |
| 1240 | + this._sync_all_aria(); | |
| 1241 | + } | |
| 1242 | + | |
| 1243 | + /** | |
| 1244 | + * Check whether the container is in exclusive (accordion) mode. | |
| 1245 | + * | |
| 1246 | + * Order of precedence: | |
| 1247 | + * 1) Explicit option `opts.exclusive` | |
| 1248 | + * 2) Container has class `.wpbc_collapsible--exclusive` | |
| 1249 | + * 3) Container matches `[data-wpbc-accordion="exclusive"]` | |
| 1250 | + * | |
| 1251 | + * @returns {boolean} True if exclusive mode is active. | |
| 1252 | + * @since 2025-08-26 | |
| 1253 | + */ | |
| 1254 | + is_exclusive() { | |
| 1255 | + return !!( | |
| 1256 | + this.opts.exclusive || | |
| 1257 | + this.root.classList.contains( 'wpbc_collapsible--exclusive' ) || | |
| 1258 | + this.root.matches( '[data-wpbc-accordion="exclusive"]' ) | |
| 1259 | + ); | |
| 1260 | + } | |
| 1261 | + | |
| 1262 | + /** | |
| 1263 | + * Determine whether a specific group is open. | |
| 1264 | + * | |
| 1265 | + * @param {HTMLElement} group The group element to test. | |
| 1266 | + * @returns {boolean} True if the group is currently open. | |
| 1267 | + * @since 2025-08-26 | |
| 1268 | + */ | |
| 1269 | + is_open(group) { | |
| 1270 | + return group.classList.contains( this.opts.open_class ); | |
| 1271 | + } | |
| 1272 | + | |
| 1273 | + /** | |
| 1274 | + * Open a group. Honors exclusive mode by collapsing all sibling groups | |
| 1275 | + * (queried from the live DOM at call-time). | |
| 1276 | + * | |
| 1277 | + * @param {HTMLElement} group The group element to open. | |
| 1278 | + * @param {boolean} [exclusive] | |
| 1279 | + * If provided, overrides container mode for this action only. | |
| 1280 | + * @returns {void} | |
| 1281 | + * @fires CustomEvent#wpbc:collapsible:open | |
| 1282 | + * @since 2025-08-26 | |
| 1283 | + */ | |
| 1284 | + expand(group, exclusive) { | |
| 1285 | + if ( !group ) { | |
| 1286 | + return; | |
| 1287 | + } | |
| 1288 | + const do_exclusive = (typeof exclusive === 'boolean') ? exclusive : this.is_exclusive(); | |
| 1289 | + if ( do_exclusive ) { | |
| 1290 | + // Always use the live DOM, not the cached list. | |
| 1291 | + Array.prototype.forEach.call( | |
| 1292 | + this.root.querySelectorAll( this.opts.group_selector ), | |
| 1293 | + (g) => { | |
| 1294 | + if ( g !== group ) { | |
| 1295 | + this._set_open( g, false ); | |
| 1296 | + } | |
| 1297 | + } | |
| 1298 | + ); | |
| 1299 | + } | |
| 1300 | + this._set_open( group, true ); | |
| 1301 | + } | |
| 1302 | + | |
| 1303 | + /** | |
| 1304 | + * Close a group. | |
| 1305 | + * | |
| 1306 | + * @param {HTMLElement} group The group element to close. | |
| 1307 | + * @returns {void} | |
| 1308 | + * @fires CustomEvent#wpbc:collapsible:close | |
| 1309 | + * @since 2025-08-26 | |
| 1310 | + */ | |
| 1311 | + collapse(group) { | |
| 1312 | + if ( !group ) { | |
| 1313 | + return; | |
| 1314 | + } | |
| 1315 | + this._set_open( group, false ); | |
| 1316 | + } | |
| 1317 | + | |
| 1318 | + /** | |
| 1319 | + * Toggle a group's open/closed state. | |
| 1320 | + * | |
| 1321 | + * @param {HTMLElement} group The group element to toggle. | |
| 1322 | + * @returns {void} | |
| 1323 | + * @since 2025-08-26 | |
| 1324 | + */ | |
| 1325 | + toggle(group) { | |
| 1326 | + if ( !group ) { | |
| 1327 | + return; | |
| 1328 | + } | |
| 1329 | + this[this.is_open( group ) ? 'collapse' : 'expand']( group ); | |
| 1330 | + } | |
| 1331 | + | |
| 1332 | + /** | |
| 1333 | + * Open a group by its index within the container (0-based). | |
| 1334 | + * | |
| 1335 | + * @param {number} index Zero-based index of the group. | |
| 1336 | + * @returns {void} | |
| 1337 | + * @since 2025-08-26 | |
| 1338 | + */ | |
| 1339 | + open_by_index(index) { | |
| 1340 | + const group = this._groups[index]; | |
| 1341 | + if ( group ) { | |
| 1342 | + this.expand( group ); | |
| 1343 | + } | |
| 1344 | + } | |
| 1345 | + | |
| 1346 | + /** | |
| 1347 | + * Open a group by matching text contained within the <h3> inside the header. | |
| 1348 | + * The comparison is case-insensitive and substring-based. | |
| 1349 | + * | |
| 1350 | + * @param {string} text Text to match against the heading contents. | |
| 1351 | + * @returns {void} | |
| 1352 | + * @since 2025-08-26 | |
| 1353 | + */ | |
| 1354 | + open_by_heading(text) { | |
| 1355 | + if ( !text ) { | |
| 1356 | + return; | |
| 1357 | + } | |
| 1358 | + const t = String( text ).toLowerCase(); | |
| 1359 | + const match = this._groups.find( (g) => { | |
| 1360 | + const h = g.querySelector( this.opts.header_selector + ' h3' ); | |
| 1361 | + return h && h.textContent.toLowerCase().indexOf( t ) !== -1; | |
| 1362 | + } ); | |
| 1363 | + if ( match ) { | |
| 1364 | + this.expand( match ); | |
| 1365 | + } | |
| 1366 | + } | |
| 1367 | + | |
| 1368 | + // ------------------------------------------------------------------------------------------------------------- | |
| 1369 | + // Internal | |
| 1370 | + // ------------------------------------------------------------------------------------------------------------- | |
| 1371 | + | |
| 1372 | + /** | |
| 1373 | + * Delegated click handler for headers. | |
| 1374 | + * | |
| 1375 | + * @private | |
| 1376 | + * @param {MouseEvent} ev The click event. | |
| 1377 | + * @returns {void} | |
| 1378 | + * @since 2025-08-26 | |
| 1379 | + */ | |
| 1380 | + _on_click(ev) { | |
| 1381 | + const btn = ev.target.closest( this.opts.header_selector ); | |
| 1382 | + if ( !btn || !this.root.contains( btn ) ) { | |
| 1383 | + return; | |
| 1384 | + } | |
| 1385 | + ev.preventDefault(); | |
| 1386 | + ev.stopPropagation(); | |
| 1387 | + const group = btn.closest( this.opts.group_selector ); | |
| 1388 | + if ( group ) { | |
| 1389 | + this.toggle( group ); | |
| 1390 | + } | |
| 1391 | + } | |
| 1392 | + | |
| 1393 | + /** | |
| 1394 | + * Keyboard handler for header interactions and roving focus: | |
| 1395 | + * - Enter/Space toggles the active group. | |
| 1396 | + * - ArrowUp/ArrowDown moves focus between group headers. | |
| 1397 | + * | |
| 1398 | + * @private | |
| 1399 | + * @param {KeyboardEvent} ev The keyboard event. | |
| 1400 | + * @returns {void} | |
| 1401 | + * @since 2025-08-26 | |
| 1402 | + */ | |
| 1403 | + _on_keydown(ev) { | |
| 1404 | + const btn = ev.target.closest( this.opts.header_selector ); | |
| 1405 | + if ( !btn ) { | |
| 1406 | + return; | |
| 1407 | + } | |
| 1408 | + | |
| 1409 | + const key = ev.key; | |
| 1410 | + | |
| 1411 | + // Toggle on Enter / Space. | |
| 1412 | + if ( key === 'Enter' || key === ' ' ) { | |
| 1413 | + ev.preventDefault(); | |
| 1414 | + const group = btn.closest( this.opts.group_selector ); | |
| 1415 | + if ( group ) { | |
| 1416 | + this.toggle( group ); | |
| 1417 | + } | |
| 1418 | + return; | |
| 1419 | + } | |
| 1420 | + | |
| 1421 | + // Move focus with ArrowUp/ArrowDown between headers in this container. | |
| 1422 | + if ( key === 'ArrowUp' || key === 'ArrowDown' ) { | |
| 1423 | + ev.preventDefault(); | |
| 1424 | + const headers = Array.prototype.map.call( | |
| 1425 | + this.root.querySelectorAll( this.opts.group_selector ), | |
| 1426 | + (g) => g.querySelector( this.opts.header_selector ) | |
| 1427 | + ).filter( Boolean ); | |
| 1428 | + const idx = headers.indexOf( btn ); | |
| 1429 | + if ( idx !== -1 ) { | |
| 1430 | + const next_idx = (key === 'ArrowDown') | |
| 1431 | + ? Math.min( headers.length - 1, idx + 1 ) | |
| 1432 | + : Math.max( 0, idx - 1 ); | |
| 1433 | + headers[next_idx].focus(); | |
| 1434 | + } | |
| 1435 | + } | |
| 1436 | + } | |
| 1437 | + | |
| 1438 | + /** | |
| 1439 | + * Apply ARIA synchronization to all known groups based on their open state. | |
| 1440 | + * | |
| 1441 | + * @private | |
| 1442 | + * @returns {void} | |
| 1443 | + * @since 2025-08-26 | |
| 1444 | + */ | |
| 1445 | + _sync_all_aria() { | |
| 1446 | + this._groups.forEach( (g) => this._sync_group_aria( g ) ); | |
| 1447 | + } | |
| 1448 | + | |
| 1449 | + /** | |
| 1450 | + * Sync ARIA attributes and visibility on a single group. | |
| 1451 | + * | |
| 1452 | + * @private | |
| 1453 | + * @param {HTMLElement} group The group element to sync. | |
| 1454 | + * @returns {void} | |
| 1455 | + * @since 2025-08-26 | |
| 1456 | + */ | |
| 1457 | + _sync_group_aria(group) { | |
| 1458 | + const is_open = this.is_open( group ); | |
| 1459 | + const header = group.querySelector( this.opts.header_selector ); | |
| 1460 | + // Only direct children that match. | |
| 1461 | + const panels = Array.prototype.filter.call( group.children, (el) => el.matches( this.opts.fields_selector ) ); | |
| 1462 | + | |
| 1463 | + // Header ARIA. | |
| 1464 | + if ( header ) { | |
| 1465 | + header.setAttribute( 'role', 'button' ); | |
| 1466 | + header.setAttribute( 'aria-expanded', is_open ? 'true' : 'false' ); | |
| 1467 | + | |
| 1468 | + if ( panels.length ) { | |
| 1469 | + // Ensure each panel has an id; then wire aria-controls with space-separated ids. | |
| 1470 | + const ids = panels.map( (p) => { | |
| 1471 | + if ( !p.id ) p.id = this._generate_id( 'wpbc_collapsible_panel' ); | |
| 1472 | + return p.id; | |
| 1473 | + } ); | |
| 1474 | + header.setAttribute( 'aria-controls', ids.join( ' ' ) ); | |
| 1475 | + } | |
| 1476 | + } | |
| 1477 | + | |
| 1478 | + // (3) Panels ARIA + visibility. | |
| 1479 | + panels.forEach( (p) => { | |
| 1480 | + p.hidden = !is_open; // actual visibility. | |
| 1481 | + p.setAttribute( 'aria-hidden', is_open ? 'false' : 'true' ); // ARIA. | |
| 1482 | + } ); | |
| 1483 | + } | |
| 1484 | + | |
| 1485 | + /** | |
| 1486 | + * Internal state change: set a group's open/closed state, sync ARIA, | |
| 1487 | + * manage focus on collapse, and emit a custom event. | |
| 1488 | + * | |
| 1489 | + * @private | |
| 1490 | + * @param {HTMLElement} group The group element to mutate. | |
| 1491 | + * @param {boolean} open Whether the group should be open. | |
| 1492 | + * @returns {void} | |
| 1493 | + * @fires CustomEvent#wpbc:collapsible:open | |
| 1494 | + * @fires CustomEvent#wpbc:collapsible:close | |
| 1495 | + * @since 2025-08-26 | |
| 1496 | + */ | |
| 1497 | + _set_open(group, open) { | |
| 1498 | + if ( !open && group.contains( document.activeElement ) ) { | |
| 1499 | + const header = group.querySelector( this.opts.header_selector ); | |
| 1500 | + header && header.focus(); | |
| 1501 | + } | |
| 1502 | + group.classList.toggle( this.opts.open_class, open ); | |
| 1503 | + this._sync_group_aria( group ); | |
| 1504 | + const ev_name = open ? 'wpbc:collapsible:open' : 'wpbc:collapsible:close'; | |
| 1505 | + group.dispatchEvent( new CustomEvent( ev_name, { | |
| 1506 | + bubbles: true, | |
| 1507 | + detail : { group, root: this.root, instance: this } | |
| 1508 | + } ) ); | |
| 1509 | + } | |
| 1510 | + | |
| 1511 | + /** | |
| 1512 | + * Generate a unique DOM id with the specified prefix. | |
| 1513 | + * | |
| 1514 | + * @private | |
| 1515 | + * @param {string} prefix The id prefix to use. | |
| 1516 | + * @returns {string} A unique element id not present in the document. | |
| 1517 | + * @since 2025-08-26 | |
| 1518 | + */ | |
| 1519 | + _generate_id(prefix) { | |
| 1520 | + let i = 1; | |
| 1521 | + let id; | |
| 1522 | + do { | |
| 1523 | + id = prefix + '_' + (i++); | |
| 1524 | + } | |
| 1525 | + while ( d.getElementById( id ) ); | |
| 1526 | + return id; | |
| 1527 | + } | |
| 1528 | + } | |
| 1529 | + | |
| 1530 | + /** | |
| 1531 | + * Auto-initialize collapsible controllers on the page. | |
| 1532 | + * Finds top-level `.wpbc_collapsible` containers (ignoring nested ones), | |
| 1533 | + * and instantiates {@link WPBC_Collapsible_Groups} on each. | |
| 1534 | + * | |
| 1535 | + * @function WPBC_Collapsible_AutoInit | |
| 1536 | + * @returns {void} | |
| 1537 | + * @since 2025-08-26 | |
| 1538 | + * @example | |
| 1539 | + * // Runs automatically on DOMContentLoaded; can also be called manually: | |
| 1540 | + * WPBC_Collapsible_AutoInit(); | |
| 1541 | + */ | |
| 1542 | + function wpbc_collapsible__auto_init() { | |
| 1543 | + var ROOT = '.wpbc_collapsible'; | |
| 1544 | + var nodes = Array.prototype.slice.call( d.querySelectorAll( ROOT ) ) | |
| 1545 | + .filter( function (n) { | |
| 1546 | + return !n.parentElement || !n.parentElement.closest( ROOT ); | |
| 1547 | + } ); | |
| 1548 | + | |
| 1549 | + nodes.forEach( function (node) { | |
| 1550 | + if ( node.__wpbc_collapsible_instance ) { | |
| 1551 | + return; | |
| 1552 | + } | |
| 1553 | + var exclusive = node.classList.contains( 'wpbc_collapsible--exclusive' ) || node.matches( '[data-wpbc-accordion="exclusive"]' ); | |
| 1554 | + | |
| 1555 | + node.__wpbc_collapsible_instance = new WPBC_Collapsible_Groups( node, { exclusive } ).init(); | |
| 1556 | + } ); | |
| 1557 | + } | |
| 1558 | + | |
| 1559 | + // Export to global for manual control if needed. | |
| 1560 | + w.WPBC_Collapsible_Groups = WPBC_Collapsible_Groups; | |
| 1561 | + w.WPBC_Collapsible_AutoInit = wpbc_collapsible__auto_init; | |
| 1562 | + | |
| 1563 | + // DOM-ready auto init. | |
| 1564 | + if ( d.readyState === 'loading' ) { | |
| 1565 | + d.addEventListener( 'DOMContentLoaded', wpbc_collapsible__auto_init, { once: true } ); | |
| 1566 | + } else { | |
| 1567 | + wpbc_collapsible__auto_init(); | |
| 1568 | + } | |
| 1569 | +})( window, document ); | |
| 1570 | + | |
| 1571 | +/* globals window, document */ | |
| 1572 | +/** | |
| 1573 | + * WPBC Slider Length Groups | |
| 1574 | + * | |
| 1575 | + * Universal, dependency-free controller that keeps a "length" control in sync: | |
| 1576 | + * - number input (data-wpbc_slider_len_value) | |
| 1577 | + * - unit select (data-wpbc_slider_len_unit) | |
| 1578 | + * - range slider (data-wpbc_slider_len_range) | |
| 1579 | + * - writer input (data-wpbc_slider_len_writer) [optional but recommended] | |
| 1580 | + * | |
| 1581 | + * The "writer" stores the combined value like: "100%", "420px", "12.5rem". | |
| 1582 | + * When number/unit/slider change -> writer updates and emits 'input' (bubbles). | |
| 1583 | + * When writer is changed externally (apply-from-JSON, etc) -> UI updates. | |
| 1584 | + * | |
| 1585 | + * Markup expectations (minimal): | |
| 1586 | + * <div class="wpbc_slider_len_group" | |
| 1587 | + * data-wpbc_slider_len_bounds_map='{"%":{"min":30,"max":100,"step":1},"px":{"min":300,"max":2000,"step":10}}' | |
| 1588 | + * data-wpbc_slider_len_default_unit="%"> | |
| 1589 | + * <input type="number" data-wpbc_slider_len_value> | |
| 1590 | + * <select data-wpbc_slider_len_unit>...</select> | |
| 1591 | + * <input type="range" data-wpbc_slider_len_range> | |
| 1592 | + * <input type="text" data-wpbc_slider_len_writer style="display:none;"> | |
| 1593 | + * </div> | |
| 1594 | + * | |
| 1595 | + * Performance notes: | |
| 1596 | + * - MutationObserver is DISABLED by default (prevents performance issues). | |
| 1597 | + * - If your UI re-renders and inserts new groups dynamically, call: | |
| 1598 | + * WPBC_Slider_Len_AutoInit(); OR instance.refresh(); | |
| 1599 | + * Or enable observer via: new WPBC_Slider_Len_Groups(root, { enable_observer:true }).init(); | |
| 1600 | + * | |
| 1601 | + * Public API (instance methods): | |
| 1602 | + * - init(), destroy(), refresh() | |
| 1603 | + * | |
| 1604 | + * @version 2026-01-25 | |
| 1605 | + * @since 2026-01-25 | |
| 1606 | + * @file ../includes/__js/admin/slider_groups/wpbc_len_groups.js | |
| 1607 | + */ | |
| 1608 | +(function (w, d) { | |
| 1609 | + 'use strict'; | |
| 1610 | + | |
| 1611 | + // ------------------------------------------------------------------------------------------------- | |
| 1612 | + // Helpers | |
| 1613 | + // ------------------------------------------------------------------------------------------------- | |
| 1614 | + function clamp_num(v, min, max) { | |
| 1615 | + if (typeof min === 'number' && !isNaN(min)) v = Math.max(min, v); | |
| 1616 | + if (typeof max === 'number' && !isNaN(max)) v = Math.min(max, v); | |
| 1617 | + return v; | |
| 1618 | + } | |
| 1619 | + | |
| 1620 | + function parse_float(v) { | |
| 1621 | + var n = parseFloat(v); | |
| 1622 | + return isNaN(n) ? null : n; | |
| 1623 | + } | |
| 1624 | + | |
| 1625 | + function safe_json_parse(str) { | |
| 1626 | + try { | |
| 1627 | + return JSON.parse(str); | |
| 1628 | + } catch (e) { | |
| 1629 | + return null; | |
| 1630 | + } | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + function parse_len_combined(raw, default_unit) { | |
| 1634 | + var s = (raw == null) ? '' : String(raw).trim(); | |
| 1635 | + if (!s) return { num: '', unit: default_unit || '%' }; | |
| 1636 | + | |
| 1637 | + var m = s.match(/^\s*([\-]?\d+(?:\.\d+)?)\s*([a-z%]*)\s*$/i); | |
| 1638 | + if (!m) { | |
| 1639 | + // If it's not parseable, treat as number and keep default unit. | |
| 1640 | + return { num: s, unit: default_unit || '%' }; | |
| 1641 | + } | |
| 1642 | + | |
| 1643 | + var num = m[1] ? String(m[1]) : ''; | |
| 1644 | + var unit = m[2] ? String(m[2]) : ''; | |
| 1645 | + if (!unit) unit = default_unit || '%'; | |
| 1646 | + | |
| 1647 | + return { num: num, unit: unit }; | |
| 1648 | + } | |
| 1649 | + | |
| 1650 | + function build_combined(num, unit) { | |
| 1651 | + if (num == null || String(num).trim() === '') return ''; | |
| 1652 | + return String(num) + String(unit || ''); | |
| 1653 | + } | |
| 1654 | + | |
| 1655 | + function emit_input(el) { | |
| 1656 | + if (!el) return; | |
| 1657 | + el.dispatchEvent(new Event('input', { bubbles: true })); | |
| 1658 | + } | |
| 1659 | + | |
| 1660 | + // ------------------------------------------------------------------------------------------------- | |
| 1661 | + // Controller | |
| 1662 | + // ------------------------------------------------------------------------------------------------- | |
| 1663 | + class WPBC_Slider_Len_Groups { | |
| 1664 | + | |
| 1665 | + /** | |
| 1666 | + * @param {HTMLElement|string} root_el Container (or selector). If omitted, uses document. | |
| 1667 | + * @param {Object} [opts={}] | |
| 1668 | + */ | |
| 1669 | + constructor(root_el, opts) { | |
| 1670 | + this.root = root_el | |
| 1671 | + ? ((typeof root_el === 'string') ? d.querySelector(root_el) : root_el) | |
| 1672 | + : d; | |
| 1673 | + | |
| 1674 | + this.opts = Object.assign({ | |
| 1675 | + // Strict selectors (NO backward compatibility). | |
| 1676 | + group_selector : '.wpbc_slider_len_group', | |
| 1677 | + value_selector : '[data-wpbc_slider_len_value]', | |
| 1678 | + unit_selector : '[data-wpbc_slider_len_unit]', | |
| 1679 | + range_selector : '[data-wpbc_slider_len_range]', | |
| 1680 | + writer_selector : '[data-wpbc_slider_len_writer]', | |
| 1681 | + | |
| 1682 | + default_unit : '%', | |
| 1683 | + | |
| 1684 | + fallback_bounds : { | |
| 1685 | + 'px' : { min: 0, max: 512, step: 1 }, | |
| 1686 | + '%' : { min: 0, max: 100, step: 1 }, | |
| 1687 | + 'rem': { min: 0, max: 10, step: 0.1 }, | |
| 1688 | + 'em' : { min: 0, max: 10, step: 0.1 } | |
| 1689 | + }, | |
| 1690 | + | |
| 1691 | + // Disabled by default for performance. | |
| 1692 | + enable_observer : false, | |
| 1693 | + observer_debounce_ms: 150 | |
| 1694 | + }, opts || {}); | |
| 1695 | + | |
| 1696 | + this._on_input = this._on_input.bind(this); | |
| 1697 | + this._on_change = this._on_change.bind(this); | |
| 1698 | + | |
| 1699 | + this._bounds_cache = new WeakMap(); // group -> bounds_map_object | |
| 1700 | + this._observer = null; | |
| 1701 | + this._refresh_tmr = null; | |
| 1702 | + } | |
| 1703 | + | |
| 1704 | + init() { | |
| 1705 | + if (!this.root) return this; | |
| 1706 | + | |
| 1707 | + this.root.addEventListener('input', this._on_input, true); | |
| 1708 | + this.root.addEventListener('change', this._on_change, true); | |
| 1709 | + | |
| 1710 | + if (this.opts.enable_observer && w.MutationObserver) { | |
| 1711 | + this._observer = new MutationObserver(() => { this._debounced_refresh(); }); | |
| 1712 | + this._observer.observe(this.root === d ? d.documentElement : this.root, { childList: true, subtree: true }); | |
| 1713 | + } | |
| 1714 | + | |
| 1715 | + this.refresh(); | |
| 1716 | + return this; | |
| 1717 | + } | |
| 1718 | + | |
| 1719 | + destroy() { | |
| 1720 | + if (!this.root) return; | |
| 1721 | + | |
| 1722 | + this.root.removeEventListener('input', this._on_input, true); | |
| 1723 | + this.root.removeEventListener('change', this._on_change, true); | |
| 1724 | + | |
| 1725 | + if (this._observer) { | |
| 1726 | + this._observer.disconnect(); | |
| 1727 | + this._observer = null; | |
| 1728 | + } | |
| 1729 | + | |
| 1730 | + if (this._refresh_tmr) { | |
| 1731 | + clearTimeout(this._refresh_tmr); | |
| 1732 | + this._refresh_tmr = null; | |
| 1733 | + } | |
| 1734 | + } | |
| 1735 | + | |
| 1736 | + refresh() { | |
| 1737 | + if (!this.root) return; | |
| 1738 | + | |
| 1739 | + var scope = (this.root === d ? d : this.root); | |
| 1740 | + var groups = Array.prototype.slice.call(scope.querySelectorAll(this.opts.group_selector)); | |
| 1741 | + | |
| 1742 | + for (var i = 0; i < groups.length; i++) { | |
| 1743 | + this._sync_group_from_writer(groups[i]); | |
| 1744 | + this._apply_bounds_for_current_unit(groups[i]); | |
| 1745 | + } | |
| 1746 | + } | |
| 1747 | + | |
| 1748 | + // ------------------------------------------------------------------------------------------------- | |
| 1749 | + // Internal | |
| 1750 | + // ------------------------------------------------------------------------------------------------- | |
| 1751 | + _debounced_refresh() { | |
| 1752 | + if (this._refresh_tmr) clearTimeout(this._refresh_tmr); | |
| 1753 | + this._refresh_tmr = setTimeout(() => { | |
| 1754 | + this._refresh_tmr = null; | |
| 1755 | + this.refresh(); | |
| 1756 | + }, Number(this.opts.observer_debounce_ms) || 0); | |
| 1757 | + } | |
| 1758 | + | |
| 1759 | + _find_group(el) { | |
| 1760 | + return (el && el.closest) ? el.closest(this.opts.group_selector) : null; | |
| 1761 | + } | |
| 1762 | + | |
| 1763 | + _get_parts(group) { | |
| 1764 | + if (!group) return null; | |
| 1765 | + return { | |
| 1766 | + group : group, | |
| 1767 | + num : group.querySelector(this.opts.value_selector), | |
| 1768 | + unit : group.querySelector(this.opts.unit_selector), | |
| 1769 | + range : group.querySelector(this.opts.range_selector), | |
| 1770 | + writer: group.querySelector(this.opts.writer_selector) | |
| 1771 | + }; | |
| 1772 | + } | |
| 1773 | + | |
| 1774 | + _get_default_unit(group) { | |
| 1775 | + var du = (group && group.getAttribute) | |
| 1776 | + ? group.getAttribute('data-wpbc_slider_len_default_unit') | |
| 1777 | + : ''; | |
| 1778 | + return du ? String(du) : this.opts.default_unit; | |
| 1779 | + } | |
| 1780 | + | |
| 1781 | + _get_bounds_map(group) { | |
| 1782 | + if (!group) return null; | |
| 1783 | + if (this._bounds_cache.has(group)) { | |
| 1784 | + return this._bounds_cache.get(group); | |
| 1785 | + } | |
| 1786 | + | |
| 1787 | + var raw = group.getAttribute('data-wpbc_slider_len_bounds_map'); | |
| 1788 | + var map = raw ? safe_json_parse(raw) : null; | |
| 1789 | + if (!map || typeof map !== 'object') map = null; | |
| 1790 | + | |
| 1791 | + this._bounds_cache.set(group, map); | |
| 1792 | + return map; | |
| 1793 | + } | |
| 1794 | + | |
| 1795 | + _get_bounds_for_unit(group, unit) { | |
| 1796 | + var map = this._get_bounds_map(group); | |
| 1797 | + if (map && unit && map[unit]) { | |
| 1798 | + return map[unit]; | |
| 1799 | + } | |
| 1800 | + return this.opts.fallback_bounds[unit] || this.opts.fallback_bounds['px']; | |
| 1801 | + } | |
| 1802 | + | |
| 1803 | + _apply_bounds(parts, bounds) { | |
| 1804 | + if (!parts || !bounds) return; | |
| 1805 | + | |
| 1806 | + var min = (bounds.min != null) ? Number(bounds.min) : null; | |
| 1807 | + var max = (bounds.max != null) ? Number(bounds.max) : null; | |
| 1808 | + var step = (bounds.step != null) ? Number(bounds.step) : null; | |
| 1809 | + | |
| 1810 | + if (parts.range) { | |
| 1811 | + if (!isNaN(min)) parts.range.min = String(min); | |
| 1812 | + if (!isNaN(max)) parts.range.max = String(max); | |
| 1813 | + if (!isNaN(step)) parts.range.step = String(step); | |
| 1814 | + } | |
| 1815 | + if (parts.num) { | |
| 1816 | + if (!isNaN(min)) parts.num.min = String(min); | |
| 1817 | + if (!isNaN(max)) parts.num.max = String(max); | |
| 1818 | + if (!isNaN(step)) parts.num.step = String(step); | |
| 1819 | + } | |
| 1820 | + } | |
| 1821 | + | |
| 1822 | + _apply_bounds_for_current_unit(group) { | |
| 1823 | + var parts = this._get_parts(group); | |
| 1824 | + if (!parts || !parts.unit) return; | |
| 1825 | + | |
| 1826 | + var unit = parts.unit.value || this._get_default_unit(group); | |
| 1827 | + var b = this._get_bounds_for_unit(group, unit); | |
| 1828 | + | |
| 1829 | + this._apply_bounds(parts, b); | |
| 1830 | + | |
| 1831 | + // Clamp current value to new bounds. | |
| 1832 | + var v = parse_float(parts.num && parts.num.value ? parts.num.value : (parts.range ? parts.range.value : '')); | |
| 1833 | + if (v == null) return; | |
| 1834 | + | |
| 1835 | + var min = (b && b.min != null) ? Number(b.min) : null; | |
| 1836 | + var max = (b && b.max != null) ? Number(b.max) : null; | |
| 1837 | + v = clamp_num(v, isNaN(min) ? null : min, isNaN(max) ? null : max); | |
| 1838 | + | |
| 1839 | + if (parts.num) parts.num.value = String(v); | |
| 1840 | + if (parts.range) parts.range.value = String(v); | |
| 1841 | + | |
| 1842 | + this._write_combined(parts, String(v), unit, /*emit*/ false); | |
| 1843 | + } | |
| 1844 | + | |
| 1845 | + _write_combined(parts, num, unit, emit) { | |
| 1846 | + if (!parts) return; | |
| 1847 | + | |
| 1848 | + var combined = build_combined(num, unit); | |
| 1849 | + | |
| 1850 | + if (parts.writer) { | |
| 1851 | + // Avoid recursion: mark as internal write. | |
| 1852 | + parts.writer.__wpbc_slider_len_internal = true; | |
| 1853 | + parts.writer.value = combined; | |
| 1854 | + if (emit) emit_input(parts.writer); | |
| 1855 | + parts.writer.__wpbc_slider_len_internal = false; | |
| 1856 | + } else if (parts.num) { | |
| 1857 | + // If writer is missing, at least notify via number input. | |
| 1858 | + if (emit) emit_input(parts.num); | |
| 1859 | + } | |
| 1860 | + } | |
| 1861 | + | |
| 1862 | + _sync_group_from_writer(group) { | |
| 1863 | + var parts = this._get_parts(group); | |
| 1864 | + if (!parts || !parts.writer) return; | |
| 1865 | + | |
| 1866 | + var raw = String(parts.writer.value || '').trim(); | |
| 1867 | + if (!raw) return; | |
| 1868 | + | |
| 1869 | + var du = this._get_default_unit(group); | |
| 1870 | + var p = parse_len_combined(raw, du); | |
| 1871 | + | |
| 1872 | + if (parts.unit) parts.unit.value = p.unit; | |
| 1873 | + if (parts.num) parts.num.value = p.num; | |
| 1874 | + if (parts.range) parts.range.value = p.num; | |
| 1875 | + } | |
| 1876 | + | |
| 1877 | + _on_input(ev) { | |
| 1878 | + var t = ev.target; | |
| 1879 | + if (!t) return; | |
| 1880 | + | |
| 1881 | + var group = this._find_group(t); | |
| 1882 | + if (!group) return; | |
| 1883 | + | |
| 1884 | + var parts = this._get_parts(group); | |
| 1885 | + if (!parts) return; | |
| 1886 | + | |
| 1887 | + // Writer changed externally -> update UI. | |
| 1888 | + if (parts.writer && t === parts.writer) { | |
| 1889 | + if (t.__wpbc_slider_len_internal) return; | |
| 1890 | + this._sync_group_from_writer(group); | |
| 1891 | + this._apply_bounds_for_current_unit(group); | |
| 1892 | + return; | |
| 1893 | + } | |
| 1894 | + | |
| 1895 | + // Slider moved -> update number + writer. | |
| 1896 | + if (t.matches && t.matches(this.opts.range_selector)) { | |
| 1897 | + if (parts.num) parts.num.value = t.value; | |
| 1898 | + | |
| 1899 | + var unit = (parts.unit && parts.unit.value) ? parts.unit.value : this._get_default_unit(group); | |
| 1900 | + this._write_combined(parts, t.value, unit, /*emit*/ true); | |
| 1901 | + return; | |
| 1902 | + } | |
| 1903 | + | |
| 1904 | + // Number typed -> update slider + writer (clamp if slider has bounds). | |
| 1905 | + if (t.matches && t.matches(this.opts.value_selector)) { | |
| 1906 | + var v = parse_float(t.value); | |
| 1907 | + | |
| 1908 | + if (v != null && parts.range) { | |
| 1909 | + var rmin = Number(parts.range.min); | |
| 1910 | + var rmax = Number(parts.range.max); | |
| 1911 | + v = clamp_num(v, isNaN(rmin) ? null : rmin, isNaN(rmax) ? null : rmax); | |
| 1912 | + | |
| 1913 | + parts.range.value = String(v); | |
| 1914 | + if (String(v) !== t.value) t.value = String(v); | |
| 1915 | + } | |
| 1916 | + | |
| 1917 | + var unit2 = (parts.unit && parts.unit.value) ? parts.unit.value : this._get_default_unit(group); | |
| 1918 | + this._write_combined(parts, t.value, unit2, /*emit*/ true); | |
| 1919 | + } | |
| 1920 | + } | |
| 1921 | + | |
| 1922 | + _on_change(ev) { | |
| 1923 | + var t = ev.target; | |
| 1924 | + if (!t) return; | |
| 1925 | + | |
| 1926 | + var group = this._find_group(t); | |
| 1927 | + if (!group) return; | |
| 1928 | + | |
| 1929 | + var parts = this._get_parts(group); | |
| 1930 | + if (!parts) return; | |
| 1931 | + | |
| 1932 | + // Unit changed -> update bounds + writer. | |
| 1933 | + if (t.matches && t.matches(this.opts.unit_selector)) { | |
| 1934 | + this._apply_bounds_for_current_unit(group); | |
| 1935 | + | |
| 1936 | + var num = parts.num ? parts.num.value : (parts.range ? parts.range.value : ''); | |
| 1937 | + var unit = t.value || this._get_default_unit(group); | |
| 1938 | + this._write_combined(parts, num, unit, /*emit*/ true); | |
| 1939 | + } | |
| 1940 | + } | |
| 1941 | + } | |
| 1942 | + | |
| 1943 | + // ------------------------------------------------------------------------------------------------- | |
| 1944 | + // Auto-init | |
| 1945 | + // ------------------------------------------------------------------------------------------------- | |
| 1946 | + function wpbc_slider_len_groups__auto_init() { | |
| 1947 | + var ROOT = '.wpbc_slider_len_groups'; | |
| 1948 | + var nodes = Array.prototype.slice.call(d.querySelectorAll(ROOT)) | |
| 1949 | + .filter(function (n) { return !n.parentElement || !n.parentElement.closest(ROOT); }); | |
| 1950 | + | |
| 1951 | + // If no explicit containers, install a single document-root instance. | |
| 1952 | + if (!nodes.length) { | |
| 1953 | + if (!d.__wpbc_slider_len_groups_global_instance) { | |
| 1954 | + d.__wpbc_slider_len_groups_global_instance = new WPBC_Slider_Len_Groups(d).init(); | |
| 1955 | + } | |
| 1956 | + return; | |
| 1957 | + } | |
| 1958 | + | |
| 1959 | + nodes.forEach(function (node) { | |
| 1960 | + if (node.__wpbc_slider_len_groups_instance) return; | |
| 1961 | + node.__wpbc_slider_len_groups_instance = new WPBC_Slider_Len_Groups(node).init(); | |
| 1962 | + }); | |
| 1963 | + } | |
| 1964 | + | |
| 1965 | + // Export globals (manual control if needed). | |
| 1966 | + w.WPBC_Slider_Len_Groups = WPBC_Slider_Len_Groups; | |
| 1967 | + w.WPBC_Slider_Len_AutoInit = wpbc_slider_len_groups__auto_init; | |
| 1968 | + | |
| 1969 | + // DOM-ready auto init. | |
| 1970 | + if (d.readyState === 'loading') { | |
| 1971 | + d.addEventListener('DOMContentLoaded', wpbc_slider_len_groups__auto_init, { once: true }); | |
| 1972 | + } else { | |
| 1973 | + wpbc_slider_len_groups__auto_init(); | |
| 1974 | + } | |
| 1975 | + | |
| 1976 | +})(window, document); | |
| 1977 | + | |
| 1978 | +/* globals window, document */ | |
| 1979 | +/** | |
| 1980 | + * WPBC Slider Range Groups | |
| 1981 | + * | |
| 1982 | + * Universal, dependency-free controller that keeps a "range + number" pair in sync: | |
| 1983 | + * - number input (data-wpbc_slider_range_value) | |
| 1984 | + * - range slider (data-wpbc_slider_range_range) | |
| 1985 | + * - writer input (data-wpbc_slider_range_writer) [optional] | |
| 1986 | + * | |
| 1987 | + * If writer exists: number/slider update writer and emit 'input' on writer (bubbles). | |
| 1988 | + * If writer is missing: emits 'input' on the number input. | |
| 1989 | + * If writer changes externally: updates number/slider. | |
| 1990 | + * | |
| 1991 | + * Markup expectations (minimal): | |
| 1992 | + * <div class="wpbc_slider_range_group"> | |
| 1993 | + * <input type="number" data-wpbc_slider_range_value> | |
| 1994 | + * <input type="range" data-wpbc_slider_range_range> | |
| 1995 | + * <!-- optional --> | |
| 1996 | + * <input type="text" data-wpbc_slider_range_writer style="display:none;"> | |
| 1997 | + * </div> | |
| 1998 | + * | |
| 1999 | + * Performance notes: | |
| 2000 | + * - MutationObserver is DISABLED by default. | |
| 2001 | + * - If your UI re-renders and inserts new groups dynamically, call: | |
| 2002 | + * WPBC_Slider_Range_AutoInit(); OR instance.refresh(); | |
| 2003 | + * Or enable observer via: new WPBC_Slider_Range_Groups(root, { enable_observer:true }).init(); | |
| 2004 | + * | |
| 2005 | + * Public API (instance methods): | |
| 2006 | + * - init(), destroy(), refresh() | |
| 2007 | + * | |
| 2008 | + * @version 2026-01-25 | |
| 2009 | + * @since 2026-01-25 | |
| 2010 | + * @file ../includes/__js/admin/slider_groups/wpbc_range_groups.js | |
| 2011 | + */ | |
| 2012 | +(function (w, d) { | |
| 2013 | + 'use strict'; | |
| 2014 | + | |
| 2015 | + // ------------------------------------------------------------------------------------------------- | |
| 2016 | + // Helpers | |
| 2017 | + // ------------------------------------------------------------------------------------------------- | |
| 2018 | + function clamp_num(v, min, max) { | |
| 2019 | + if (typeof min === 'number' && !isNaN(min)) v = Math.max(min, v); | |
| 2020 | + if (typeof max === 'number' && !isNaN(max)) v = Math.min(max, v); | |
| 2021 | + return v; | |
| 2022 | + } | |
| 2023 | + | |
| 2024 | + function parse_float(v) { | |
| 2025 | + var n = parseFloat(v); | |
| 2026 | + return isNaN(n) ? null : n; | |
| 2027 | + } | |
| 2028 | + | |
| 2029 | + function emit_input(el) { | |
| 2030 | + if (!el) return; | |
| 2031 | + el.dispatchEvent(new Event('input', { bubbles: true })); | |
| 2032 | + } | |
| 2033 | + | |
| 2034 | + // ------------------------------------------------------------------------------------------------- | |
| 2035 | + // Controller | |
| 2036 | + // ------------------------------------------------------------------------------------------------- | |
| 2037 | + class WPBC_Slider_Range_Groups { | |
| 2038 | + | |
| 2039 | + /** | |
| 2040 | + * @param {HTMLElement|string} root_el Container (or selector). If omitted, uses document. | |
| 2041 | + * @param {Object} [opts={}] | |
| 2042 | + */ | |
| 2043 | + constructor(root_el, opts) { | |
| 2044 | + this.root = root_el | |
| 2045 | + ? ((typeof root_el === 'string') ? d.querySelector(root_el) : root_el) | |
| 2046 | + : d; | |
| 2047 | + | |
| 2048 | + this.opts = Object.assign({ | |
| 2049 | + // Strict selectors (NO backward compatibility). | |
| 2050 | + group_selector : '.wpbc_slider_range_group', | |
| 2051 | + value_selector : '[data-wpbc_slider_range_value]', | |
| 2052 | + range_selector : '[data-wpbc_slider_range_range]', | |
| 2053 | + writer_selector : '[data-wpbc_slider_range_writer]', | |
| 2054 | + | |
| 2055 | + // Disabled by default for performance. | |
| 2056 | + enable_observer : false, | |
| 2057 | + observer_debounce_ms: 150 | |
| 2058 | + }, opts || {}); | |
| 2059 | + | |
| 2060 | + this._on_input = this._on_input.bind(this); | |
| 2061 | + this._on_change = this._on_change.bind(this); | |
| 2062 | + | |
| 2063 | + this._observer = null; | |
| 2064 | + this._refresh_tmr = null; | |
| 2065 | + } | |
| 2066 | + | |
| 2067 | + init() { | |
| 2068 | + if (!this.root) return this; | |
| 2069 | + | |
| 2070 | + this.root.addEventListener('input', this._on_input, true); | |
| 2071 | + this.root.addEventListener('change', this._on_change, true); | |
| 2072 | + | |
| 2073 | + if (this.opts.enable_observer && w.MutationObserver) { | |
| 2074 | + this._observer = new MutationObserver(() => { this._debounced_refresh(); }); | |
| 2075 | + this._observer.observe(this.root === d ? d.documentElement : this.root, { childList: true, subtree: true }); | |
| 2076 | + } | |
| 2077 | + | |
| 2078 | + this.refresh(); | |
| 2079 | + return this; | |
| 2080 | + } | |
| 2081 | + | |
| 2082 | + destroy() { | |
| 2083 | + if (!this.root) return; | |
| 2084 | + | |
| 2085 | + this.root.removeEventListener('input', this._on_input, true); | |
| 2086 | + this.root.removeEventListener('change', this._on_change, true); | |
| 2087 | + | |
| 2088 | + if (this._observer) { | |
| 2089 | + this._observer.disconnect(); | |
| 2090 | + this._observer = null; | |
| 2091 | + } | |
| 2092 | + | |
| 2093 | + if (this._refresh_tmr) { | |
| 2094 | + clearTimeout(this._refresh_tmr); | |
| 2095 | + this._refresh_tmr = null; | |
| 2096 | + } | |
| 2097 | + } | |
| 2098 | + | |
| 2099 | + refresh() { | |
| 2100 | + if (!this.root) return; | |
| 2101 | + | |
| 2102 | + var scope = (this.root === d ? d : this.root); | |
| 2103 | + var groups = Array.prototype.slice.call(scope.querySelectorAll(this.opts.group_selector)); | |
| 2104 | + | |
| 2105 | + for (var i = 0; i < groups.length; i++) { | |
| 2106 | + this._sync_from_writer(groups[i]); | |
| 2107 | + this._clamp_to_range(groups[i]); | |
| 2108 | + } | |
| 2109 | + } | |
| 2110 | + | |
| 2111 | + // ------------------------------------------------------------------------------------------------- | |
| 2112 | + // Internal | |
| 2113 | + // ------------------------------------------------------------------------------------------------- | |
| 2114 | + _debounced_refresh() { | |
| 2115 | + if (this._refresh_tmr) clearTimeout(this._refresh_tmr); | |
| 2116 | + this._refresh_tmr = setTimeout(() => { | |
| 2117 | + this._refresh_tmr = null; | |
| 2118 | + this.refresh(); | |
| 2119 | + }, Number(this.opts.observer_debounce_ms) || 0); | |
| 2120 | + } | |
| 2121 | + | |
| 2122 | + _find_group(el) { | |
| 2123 | + return (el && el.closest) ? el.closest(this.opts.group_selector) : null; | |
| 2124 | + } | |
| 2125 | + | |
| 2126 | + _get_parts(group) { | |
| 2127 | + if (!group) return null; | |
| 2128 | + return { | |
| 2129 | + group : group, | |
| 2130 | + num : group.querySelector(this.opts.value_selector), | |
| 2131 | + range : group.querySelector(this.opts.range_selector), | |
| 2132 | + writer: group.querySelector(this.opts.writer_selector) | |
| 2133 | + }; | |
| 2134 | + } | |
| 2135 | + | |
| 2136 | + _write(parts, value, emit) { | |
| 2137 | + if (!parts) return; | |
| 2138 | + | |
| 2139 | + if (parts.writer) { | |
| 2140 | + parts.writer.__wpbc_slider_range_internal = true; | |
| 2141 | + parts.writer.value = String(value); | |
| 2142 | + if (emit) emit_input(parts.writer); | |
| 2143 | + parts.writer.__wpbc_slider_range_internal = false; | |
| 2144 | + } else if (parts.num) { | |
| 2145 | + // If writer is missing, at least notify via number input. | |
| 2146 | + if (emit) emit_input(parts.num); | |
| 2147 | + } | |
| 2148 | + } | |
| 2149 | + | |
| 2150 | + _sync_from_writer(group) { | |
| 2151 | + var parts = this._get_parts(group); | |
| 2152 | + if (!parts || !parts.writer) return; | |
| 2153 | + | |
| 2154 | + var raw = String(parts.writer.value || '').trim(); | |
| 2155 | + if (!raw) return; | |
| 2156 | + | |
| 2157 | + if (parts.num) parts.num.value = raw; | |
| 2158 | + if (parts.range) parts.range.value = raw; | |
| 2159 | + } | |
| 2160 | + | |
| 2161 | + _clamp_to_range(group) { | |
| 2162 | + var parts = this._get_parts(group); | |
| 2163 | + if (!parts || !parts.range || !parts.num) return; | |
| 2164 | + | |
| 2165 | + var v = parse_float(parts.num.value); | |
| 2166 | + if (v == null) return; | |
| 2167 | + | |
| 2168 | + var min = Number(parts.range.min); | |
| 2169 | + var max = Number(parts.range.max); | |
| 2170 | + var vv = clamp_num(v, isNaN(min) ? null : min, isNaN(max) ? null : max); | |
| 2171 | + | |
| 2172 | + if (String(vv) !== parts.num.value) parts.num.value = String(vv); | |
| 2173 | + parts.range.value = String(vv); | |
| 2174 | + } | |
| 2175 | + | |
| 2176 | + _on_input(ev) { | |
| 2177 | + var t = ev.target; | |
| 2178 | + if (!t) return; | |
| 2179 | + | |
| 2180 | + var group = this._find_group(t); | |
| 2181 | + if (!group) return; | |
| 2182 | + | |
| 2183 | + var parts = this._get_parts(group); | |
| 2184 | + if (!parts) return; | |
| 2185 | + | |
| 2186 | + // Writer changed externally -> update UI. | |
| 2187 | + if (parts.writer && t === parts.writer) { | |
| 2188 | + if (t.__wpbc_slider_range_internal) return; | |
| 2189 | + this._sync_from_writer(group); | |
| 2190 | + this._clamp_to_range(group); | |
| 2191 | + return; | |
| 2192 | + } | |
| 2193 | + | |
| 2194 | + // Range moved -> update number + writer. | |
| 2195 | + if (t.matches && t.matches(this.opts.range_selector)) { | |
| 2196 | + if (parts.num) parts.num.value = t.value; | |
| 2197 | + this._write(parts, t.value, /*emit*/ true); | |
| 2198 | + return; | |
| 2199 | + } | |
| 2200 | + | |
| 2201 | + // Number typed -> update range + writer (clamp by slider bounds). | |
| 2202 | + if (t.matches && t.matches(this.opts.value_selector)) { | |
| 2203 | + if (parts.range) { | |
| 2204 | + var v = parse_float(t.value); | |
| 2205 | + if (v != null) { | |
| 2206 | + var min = Number(parts.range.min); | |
| 2207 | + var max = Number(parts.range.max); | |
| 2208 | + v = clamp_num(v, isNaN(min) ? null : min, isNaN(max) ? null : max); | |
| 2209 | + | |
| 2210 | + parts.range.value = String(v); | |
| 2211 | + if (String(v) !== t.value) t.value = String(v); | |
| 2212 | + } | |
| 2213 | + } | |
| 2214 | + this._write(parts, t.value, /*emit*/ true); | |
| 2215 | + } | |
| 2216 | + } | |
| 2217 | + | |
| 2218 | + _on_change(ev) { | |
| 2219 | + // No special "change" handling needed currently; kept for symmetry/future. | |
| 2220 | + } | |
| 2221 | + } | |
| 2222 | + | |
| 2223 | + // ------------------------------------------------------------------------------------------------- | |
| 2224 | + // Auto-init | |
| 2225 | + // ------------------------------------------------------------------------------------------------- | |
| 2226 | + function wpbc_slider_range_groups__auto_init() { | |
| 2227 | + var ROOT = '.wpbc_slider_range_groups'; | |
| 2228 | + var nodes = Array.prototype.slice.call(d.querySelectorAll(ROOT)) | |
| 2229 | + .filter(function (n) { return !n.parentElement || !n.parentElement.closest(ROOT); }); | |
| 2230 | + | |
| 2231 | + if (!nodes.length) { | |
| 2232 | + if (!d.__wpbc_slider_range_groups_global_instance) { | |
| 2233 | + d.__wpbc_slider_range_groups_global_instance = new WPBC_Slider_Range_Groups(d).init(); | |
| 2234 | + } | |
| 2235 | + return; | |
| 2236 | + } | |
| 2237 | + | |
| 2238 | + nodes.forEach(function (node) { | |
| 2239 | + if (node.__wpbc_slider_range_groups_instance) return; | |
| 2240 | + node.__wpbc_slider_range_groups_instance = new WPBC_Slider_Range_Groups(node).init(); | |
| 2241 | + }); | |
| 2242 | + } | |
| 2243 | + | |
| 2244 | + // Export globals. | |
| 2245 | + w.WPBC_Slider_Range_Groups = WPBC_Slider_Range_Groups; | |
| 2246 | + w.WPBC_Slider_Range_AutoInit = wpbc_slider_range_groups__auto_init; | |
| 2247 | + | |
| 2248 | + if (d.readyState === 'loading') { | |
| 2249 | + d.addEventListener('DOMContentLoaded', wpbc_slider_range_groups__auto_init, { once: true }); | |
| 2250 | + } else { | |
| 2251 | + wpbc_slider_range_groups__auto_init(); | |
| 2252 | + } | |
| 2253 | + | |
| 2254 | +})(window, document); | |
| 2255 | + | |
| 2256 | +/** | |
| 2257 | + * Booking Calendar — Generic UI Tabs Utility (JS) | |
| 2258 | + * | |
| 2259 | + * Purpose: Lightweight, dependency-free tabs controller for any small tab group in admin UIs. | |
| 2260 | + * - Auto-initializes groups marked with data-wpbc-tabs. | |
| 2261 | + * - Assigns ARIA roles and toggles aria-selected/aria-hidden/tabindex. | |
| 2262 | + * - Supports keyboard navigation (Left/Right/Home/End). | |
| 2263 | + * - Public API: window.wpbc_ui_tabs.{init_on, init_group, set_active} | |
| 2264 | + * - Emits 'wpbc:tabs:change' on the group root when the active tab changes. | |
| 2265 | + * | |
| 2266 | + * Markup contract: | |
| 2267 | + * - Root: [data-wpbc-tabs] | |
| 2268 | + * - Tabs: [data-wpbc-tab-key="K"] | |
| 2269 | + * - Panels: [data-wpbc-tab-panel="K"] | |
| 2270 | + * | |
| 2271 | + * @package Booking Calendar | |
| 2272 | + * @subpackage Admin\UI | |
| 2273 | + * @since 11.0.0 | |
| 2274 | + * @version 1.0.0 | |
| 2275 | + * @see /includes/__js/admin/ui_tabs/ui_tabs.js | |
| 2276 | + * | |
| 2277 | + * | |
| 2278 | + * How it works: | |
| 2279 | + * - Root node must have [data-wpbc-tabs] attribute (any value). | |
| 2280 | + * - Tab buttons must carry [data-wpbc-tab-key="..."] (unique per group). | |
| 2281 | + * - Panels must carry [data-wpbc-tab-panel="..."] with matching keys. | |
| 2282 | + * - Adds WAI-ARIA roles and aria-selected/hidden wiring. | |
| 2283 | + * | |
| 2284 | + * <div data-wpbc-tabs="column-styles" data-wpbc-tab-active="1" class="wpbc_ui_tabs_root" > | |
| 2285 | + * <!-- Top Tabs --> | |
| 2286 | + * <div data-wpbc-tablist="" role="tablist" class=" wpbc_ui_el__horis_top_bar__wrapper" > | |
| 2287 | + * <div class="wpbc_ui_el__horis_top_bar__content"> | |
| 2288 | + * <h2 class="wpbc_ui_el__horis_nav_label">Column:</h2> | |
| 2289 | + * | |
| 2290 | + * <div class="wpbc_ui_el__horis_nav_item wpbc_ui_el__horis_nav_item__1"> | |
| 2291 | + * <a | |
| 2292 | + * data-wpbc-tab-key="1" | |
| 2293 | + * aria-selected="true" role="tab" tabindex="0" aria-controls="wpbc_tab_panel_col_1" | |
| 2294 | + * | |
| 2295 | + * href="javascript:void(0);" | |
| 2296 | + * class="wpbc_ui_el__horis_nav_item__a wpbc_ui_el__horis_nav_item__single" | |
| 2297 | + * id="wpbc_tab_col_1" | |
| 2298 | + * title="Column 1" | |
| 2299 | + * ><span class="wpbc_ui_el__horis_nav_title">Title 1</span></a> | |
| 2300 | + * </div> | |
| 2301 | + * ... | |
| 2302 | + * </div> | |
| 2303 | + * </div> | |
| 2304 | + * <!-- Tabs Content --> | |
| 2305 | + * <div class="wpbc_tab__panel group__fields" data-wpbc-tab-panel="1" id="wpbc_tab_panel_col_1" role="tabpanel" aria-labelledby="wpbc_tab_col_1"> | |
| 2306 | + * ... | |
| 2307 | + * </div> | |
| 2308 | + * ... | |
| 2309 | + * </div> | |
| 2310 | + * | |
| 2311 | + * Public API: | |
| 2312 | + * - wpbc_ui_tabs.init_on(root_or_selector) // find and init groups within a container | |
| 2313 | + * - wpbc_ui_tabs.init_group(root_el) // init a single group root | |
| 2314 | + * - wpbc_ui_tabs.set_active(root_el, key) // programmatically change active tab | |
| 2315 | + * | |
| 2316 | + * Events: | |
| 2317 | + * - Dispatches CustomEvent 'wpbc:tabs:change' on root when tab changes: | |
| 2318 | + * detail: { active_key: '2', prev_key: '1' } | |
| 2319 | + * | |
| 2320 | + * Switch a local (generic) tabs group to tab 3: var group = document.querySelector('[data-wpbc-tabs="column-styles"]'); if ( group ) { wpbc_ui_tabs.set_active(group, '3'); } | |
| 2321 | + */ | |
| 2322 | +(function ( w ) { | |
| 2323 | + 'use strict'; | |
| 2324 | + | |
| 2325 | + if ( w.wpbc_ui_tabs ) { | |
| 2326 | + return; | |
| 2327 | + } | |
| 2328 | + | |
| 2329 | + /** | |
| 2330 | + * Internal: toggle active state. | |
| 2331 | + * | |
| 2332 | + * @param {HTMLElement} root_el | |
| 2333 | + * @param {string} key | |
| 2334 | + * @param {boolean} should_emit | |
| 2335 | + */ | |
| 2336 | + function set_active_internal( root_el, key, should_emit ) { | |
| 2337 | + var tab_btns = root_el.querySelectorAll( '[data-wpbc-tab-key]' ); | |
| 2338 | + var panels = root_el.querySelectorAll( '[data-wpbc-tab-panel]' ); | |
| 2339 | + | |
| 2340 | + var prev_key = root_el.getAttribute( 'data-wpbc-tab-active' ) || null; | |
| 2341 | + if ( String( prev_key ) === String( key ) ) { | |
| 2342 | + return; | |
| 2343 | + } | |
| 2344 | + | |
| 2345 | + // Buttons: aria + class | |
| 2346 | + for ( var i = 0; i < tab_btns.length; i++ ) { | |
| 2347 | + var btn = tab_btns[i]; | |
| 2348 | + var b_key = btn.getAttribute( 'data-wpbc-tab-key' ); | |
| 2349 | + var is_on = String( b_key ) === String( key ); | |
| 2350 | + | |
| 2351 | + btn.setAttribute( 'role', 'tab' ); | |
| 2352 | + btn.setAttribute( 'aria-selected', is_on ? 'true' : 'false' ); | |
| 2353 | + btn.setAttribute( 'tabindex', is_on ? '0' : '-1' ); | |
| 2354 | + | |
| 2355 | + if ( is_on ) { | |
| 2356 | + btn.classList.add( 'active' ); | |
| 2357 | + } else { | |
| 2358 | + btn.classList.remove( 'active' ); | |
| 2359 | + } | |
| 2360 | + } | |
| 2361 | + | |
| 2362 | + // Panels: aria + visibility | |
| 2363 | + for ( var j = 0; j < panels.length; j++ ) { | |
| 2364 | + var pn = panels[j]; | |
| 2365 | + var pkey = pn.getAttribute( 'data-wpbc-tab-panel' ); | |
| 2366 | + var show = String( pkey ) === String( key ); | |
| 2367 | + | |
| 2368 | + pn.setAttribute( 'role', 'tabpanel' ); | |
| 2369 | + pn.setAttribute( 'aria-hidden', show ? 'false' : 'true' ); | |
| 2370 | + if ( show ) { | |
| 2371 | + pn.removeAttribute( 'hidden' ); | |
| 2372 | + } else { | |
| 2373 | + pn.setAttribute( 'hidden', '' ); | |
| 2374 | + } | |
| 2375 | + } | |
| 2376 | + | |
| 2377 | + root_el.setAttribute( 'data-wpbc-tab-active', String( key ) ); | |
| 2378 | + | |
| 2379 | + if ( should_emit ) { | |
| 2380 | + try { | |
| 2381 | + var ev = new w.CustomEvent( 'wpbc:tabs:change', { | |
| 2382 | + bubbles : true, | |
| 2383 | + detail : { active_key : String( key ), prev_key : prev_key } | |
| 2384 | + } ); | |
| 2385 | + root_el.dispatchEvent( ev ); | |
| 2386 | + } catch ( _e ) {} | |
| 2387 | + } | |
| 2388 | + } | |
| 2389 | + | |
| 2390 | + /** | |
| 2391 | + * Internal: get ordered keys from buttons. | |
| 2392 | + * | |
| 2393 | + * @param {HTMLElement} root_el | |
| 2394 | + * @returns {string[]} | |
| 2395 | + */ | |
| 2396 | + function get_keys( root_el ) { | |
| 2397 | + var list = []; | |
| 2398 | + var btns = root_el.querySelectorAll( '[data-wpbc-tab-key]' ); | |
| 2399 | + for ( var i = 0; i < btns.length; i++ ) { | |
| 2400 | + var k = btns[i].getAttribute( 'data-wpbc-tab-key' ); | |
| 2401 | + if ( k != null && k !== '' ) { | |
| 2402 | + list.push( String( k ) ); | |
| 2403 | + } | |
| 2404 | + } | |
| 2405 | + return list; | |
| 2406 | + } | |
| 2407 | + | |
| 2408 | + /** | |
| 2409 | + * Internal: move focus between tabs using keyboard. | |
| 2410 | + * | |
| 2411 | + * @param {HTMLElement} root_el | |
| 2412 | + * @param {number} dir +1 (next) / -1 (prev) | |
| 2413 | + */ | |
| 2414 | + function focus_relative( root_el, dir ) { | |
| 2415 | + var keys = get_keys( root_el ); | |
| 2416 | + var current = root_el.getAttribute( 'data-wpbc-tab-active' ) || keys[0] || null; | |
| 2417 | + var idx = Math.max( 0, keys.indexOf( String( current ) ) ); | |
| 2418 | + var next = keys[ ( idx + ( dir > 0 ? 1 : keys.length - 1 ) ) % keys.length ]; | |
| 2419 | + | |
| 2420 | + var next_btn = root_el.querySelector( '[data-wpbc-tab-key="' + next + '"]' ); | |
| 2421 | + if ( next_btn ) { | |
| 2422 | + next_btn.focus(); | |
| 2423 | + set_active_internal( root_el, next, true ); | |
| 2424 | + } | |
| 2425 | + } | |
| 2426 | + | |
| 2427 | + /** | |
| 2428 | + * Initialize a single tabs group root. | |
| 2429 | + * | |
| 2430 | + * @param {HTMLElement} root_el | |
| 2431 | + */ | |
| 2432 | + function init_group( root_el ) { | |
| 2433 | + if ( ! root_el || root_el.__wpbc_tabs_inited ) { | |
| 2434 | + return; | |
| 2435 | + } | |
| 2436 | + root_el.__wpbc_tabs_inited = true; | |
| 2437 | + | |
| 2438 | + // Roles | |
| 2439 | + var tablist = root_el.querySelector( '[data-wpbc-tablist]' ) || root_el; | |
| 2440 | + tablist.setAttribute( 'role', 'tablist' ); | |
| 2441 | + | |
| 2442 | + // Default active: from attribute or first button | |
| 2443 | + var keys = get_keys( root_el ); | |
| 2444 | + var def = root_el.getAttribute( 'data-wpbc-tab-active' ) || ( keys[0] || '1' ); | |
| 2445 | + set_active_internal( root_el, def, false ); | |
| 2446 | + | |
| 2447 | + // Clicks | |
| 2448 | + root_el.addEventListener( 'click', function ( e ) { | |
| 2449 | + var btn = e.target.closest ? e.target.closest( '[data-wpbc-tab-key]' ) : null; | |
| 2450 | + if ( ! btn || ! root_el.contains( btn ) ) { | |
| 2451 | + return; | |
| 2452 | + } | |
| 2453 | + e.preventDefault(); | |
| 2454 | + var key = btn.getAttribute( 'data-wpbc-tab-key' ); | |
| 2455 | + if ( key != null ) { | |
| 2456 | + set_active_internal( root_el, key, true ); | |
| 2457 | + } | |
| 2458 | + }, true ); | |
| 2459 | + | |
| 2460 | + // Keyboard (Left/Right/Home/End) | |
| 2461 | + root_el.addEventListener( 'keydown', function ( e ) { | |
| 2462 | + var tgt = e.target; | |
| 2463 | + if ( ! tgt || ! tgt.hasAttribute || ! tgt.hasAttribute( 'data-wpbc-tab-key' ) ) { | |
| 2464 | + return; | |
| 2465 | + } | |
| 2466 | + switch ( e.key ) { | |
| 2467 | + case 'ArrowLeft': | |
| 2468 | + e.preventDefault(); focus_relative( root_el, -1 ); break; | |
| 2469 | + case 'ArrowRight': | |
| 2470 | + e.preventDefault(); focus_relative( root_el, +1 ); break; | |
| 2471 | + case 'Home': | |
| 2472 | + e.preventDefault(); set_active_internal( root_el, ( get_keys( root_el )[0] || '1' ), true ); break; | |
| 2473 | + case 'End': | |
| 2474 | + e.preventDefault(); var ks = get_keys( root_el ); set_active_internal( root_el, ( ks[ ks.length - 1 ] || '1' ), true ); break; | |
| 2475 | + } | |
| 2476 | + }, true ); | |
| 2477 | + } | |
| 2478 | + | |
| 2479 | + /** | |
| 2480 | + * Initialize all groups within a container (or document). | |
| 2481 | + * | |
| 2482 | + * @param {HTMLElement|string|null} container | |
| 2483 | + */ | |
| 2484 | + function init_on( container ) { | |
| 2485 | + var ctx = container ? ( typeof container === 'string' ? document.querySelector( container ) : container ) : document; | |
| 2486 | + if ( ! ctx ) { | |
| 2487 | + return; | |
| 2488 | + } | |
| 2489 | + var groups = ctx.querySelectorAll( '[data-wpbc-tabs]' ); | |
| 2490 | + for ( var i = 0; i < groups.length; i++ ) { | |
| 2491 | + init_group( groups[i] ); | |
| 2492 | + } | |
| 2493 | + } | |
| 2494 | + | |
| 2495 | + /** | |
| 2496 | + * Programmatically set active tab by key. | |
| 2497 | + * | |
| 2498 | + * @param {HTMLElement} root_el | |
| 2499 | + * @param {string|number} key | |
| 2500 | + */ | |
| 2501 | + function set_active( root_el, key ) { | |
| 2502 | + if ( root_el && root_el.hasAttribute && root_el.hasAttribute( 'data-wpbc-tabs' ) ) { | |
| 2503 | + set_active_internal( root_el, String( key ), true ); | |
| 2504 | + } | |
| 2505 | + } | |
| 2506 | + | |
| 2507 | + // Public API (snake_case) | |
| 2508 | + w.wpbc_ui_tabs = { | |
| 2509 | + init_on : init_on, | |
| 2510 | + init_group : init_group, | |
| 2511 | + set_active : set_active | |
| 2512 | + }; | |
| 2513 | + | |
| 2514 | + // Auto-init on DOM ready | |
| 2515 | + if ( document.readyState === 'loading' ) { | |
| 2516 | + document.addEventListener( 'DOMContentLoaded', function () { init_on( document ); } ); | |
| 2517 | + } else { | |
| 2518 | + init_on( document ); | |
| 2519 | + } | |
| 2520 | + | |
| 2521 | +})( window ); | |
| 2522 | + | |
| 2523 | +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInVpX2VsZW1lbnRzLmpzIiwidWlfbG9hZGluZ19zcGluLmpzIiwidWlfcmFkaW9fY29udGFpbmVyLmpzIiwidWlfZnVsbF9zY3JlZW5fbW9kZS5qcyIsImdtYWlsX2NoZWNrYm94X3NlbGVjdGlvbi5qcyIsImJvb2tpbmdzX2NoZWNrYm94X3NlbGVjdGlvbi5qcyIsInVpX3NpZGViYXJfbGVmdF9fYWN0aW9ucy5qcyIsImNvcHlfdGV4dF90b19jbGlwYnJkLmpzIiwiY29sbGFwc2libGVfZ3JvdXBzLmpzIiwid3BiY19sZW5fZ3JvdXBzLmpzIiwid3BiY19yYW5nZV9ncm91cHMuanMiLCJ1aV90YWJzLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNqSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3BEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN2ZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNySEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2xnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3RaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDclJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJ3cGJjX2FsbF9hZG1pbi5qcyIsInNvdXJjZXNDb250ZW50IjpbIlxyXG4vKipcclxuICogQmxpbmsgc3BlY2lmaWMgSFRNTCBlbGVtZW50IHRvIHNldCBhdHRlbnRpb24gdG8gdGhpcyBlbGVtZW50LlxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZWxlbWVudF90b19ibGlua1x0XHQgIC0gY2xhc3Mgb3IgaWQgb2YgZWxlbWVudDogJy53cGJjX3dpZGdldF9hdmFpbGFibGVfdW5hdmFpbGFibGUnXHJcbiAqIEBwYXJhbSB7aW50fSBob3dfbWFueV90aW1lc1x0XHRcdCAgLSA0XHJcbiAqIEBwYXJhbSB7aW50fSBob3dfbG9uZ190b19ibGlua1x0XHQgIC0gMzUwXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2JsaW5rX2VsZW1lbnQoIGVsZW1lbnRfdG9fYmxpbmssIGhvd19tYW55X3RpbWVzID0gNCwgaG93X2xvbmdfdG9fYmxpbmsgPSAzNTAgKXtcclxuXHJcblx0Zm9yICggbGV0IGkgPSAwOyBpIDwgaG93X21hbnlfdGltZXM7IGkrKyApe1xyXG5cdFx0alF1ZXJ5KCBlbGVtZW50X3RvX2JsaW5rICkuZmFkZU91dCggaG93X2xvbmdfdG9fYmxpbmsgKS5mYWRlSW4oIGhvd19sb25nX3RvX2JsaW5rICk7XHJcblx0fVxyXG4gICAgalF1ZXJ5KCBlbGVtZW50X3RvX2JsaW5rICkuYW5pbWF0ZSgge29wYWNpdHk6IDF9LCA1MDAgKTtcclxufVxyXG4iLCIvKipcclxuICogICBTdXBwb3J0IEZ1bmN0aW9ucyAtIFNwaW4gSWNvbiBpbiBCdXR0b25zICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cclxuXHJcbi8qKlxyXG4gKiBSZW1vdmUgc3BpbiBpY29uIGZyb20gIGJ1dHRvbiBhbmQgRW5hYmxlIHRoaXMgYnV0dG9uLlxyXG4gKlxyXG4gKiBAcGFyYW0gYnV0dG9uX2NsaWNrZWRfZWxlbWVudF9pZFx0XHQtIEhUTUwgSUQgYXR0cmlidXRlIG9mIHRoaXMgYnV0dG9uXHJcbiAqIEByZXR1cm4gc3RyaW5nXHRcdFx0XHRcdFx0LSBDU1MgY2xhc3NlcyB0aGF0IHdhcyBwcmV2aW91c2x5IGluIGJ1dHRvbiBpY29uXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2J1dHRvbl9fcmVtb3ZlX3NwaW4oYnV0dG9uX2NsaWNrZWRfZWxlbWVudF9pZCkge1xyXG5cclxuXHR2YXIgcHJldmlvc19jbGFzc2VzID0gJyc7XHJcblx0aWYgKFxyXG5cdFx0KHVuZGVmaW5lZCAhPSBidXR0b25fY2xpY2tlZF9lbGVtZW50X2lkKVxyXG5cdFx0JiYgKCcnICE9IGJ1dHRvbl9jbGlja2VkX2VsZW1lbnRfaWQpXHJcblx0KSB7XHJcblx0XHR2YXIgakVsZW1lbnQgPSBqUXVlcnkoICcjJyArIGJ1dHRvbl9jbGlja2VkX2VsZW1lbnRfaWQgKTtcclxuXHRcdGlmICggakVsZW1lbnQubGVuZ3RoICkge1xyXG5cdFx0XHRwcmV2aW9zX2NsYXNzZXMgPSB3cGJjX2J1dHRvbl9kaXNhYmxlX2xvYWRpbmdfaWNvbiggakVsZW1lbnQuZ2V0KCAwICkgKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdHJldHVybiBwcmV2aW9zX2NsYXNzZXM7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogU2hvdyBMb2FkaW5nIChyb3RhdGluZyBhcnJvdykgaWNvbiBmb3IgYnV0dG9uIHRoYXQgaGFzIGJlZW4gY2xpY2tlZFxyXG4gKlxyXG4gKiBAcGFyYW0gdGhpc19idXR0b25cdFx0LSB0aGlzIG9iamVjdCBvZiBzcGVjaWZpYyBidXR0b25cclxuICogQHJldHVybiBzdHJpbmdcdFx0XHQtIENTUyBjbGFzc2VzIHRoYXQgd2FzIHByZXZpb3VzbHkgaW4gYnV0dG9uIGljb25cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYnV0dG9uX2VuYWJsZV9sb2FkaW5nX2ljb24odGhpc19idXR0b24pIHtcclxuXHJcblx0dmFyIGpCdXR0b24gICAgICAgICA9IGpRdWVyeSggdGhpc19idXR0b24gKTtcclxuXHR2YXIgakljb24gICAgICAgICAgID0gakJ1dHRvbi5maW5kKCAnaScgKTtcclxuXHR2YXIgcHJldmlvc19jbGFzc2VzID0gakljb24uYXR0ciggJ2NsYXNzJyApO1xyXG5cclxuXHRqSWNvbi5yZW1vdmVDbGFzcygpLmFkZENsYXNzKCAnbWVudV9pY29uIGljb24tMXggd3BiY19pY25fcm90YXRlX3JpZ2h0IHdwYmNfc3BpbicgKTtcdC8vIFNldCBSb3RhdGUgaWNvbi5cclxuXHQvLyBqSWNvbi5hZGRDbGFzcyggJ3dwYmNfYW5pbWF0aW9uX3BhdXNlJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFBhdXNlIGFuaW1hdGlvbi5cclxuXHQvLyBqSWNvbi5hZGRDbGFzcyggJ3dwYmNfdWlfcmVkJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTZXQgaWNvbiBjb2xvciByZWQuXHJcblxyXG5cdGpJY29uLmF0dHIoICd3cGJjX3ByZXZpb3VzX2NsYXNzJywgcHJldmlvc19jbGFzc2VzIClcclxuXHJcblx0akJ1dHRvbi5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIERpc2FibGUgYnV0dG9uXHJcblx0Ly8gV2UgbmVlZCB0byAgc2V0ICBoZXJlIGF0dHIgaW5zdGVhZCBvZiBwcm9wLCBiZWNhdXNlIGZvciBBIGVsZW1lbnRzLCAgYXR0cmlidXRlICdkaXNhYmxlZCcgZG8gIG5vdCBhZGRlZCB3aXRoIGpCdXR0b24ucHJvcCggXCJkaXNhYmxlZFwiLCB0cnVlICk7LlxyXG5cclxuXHRqQnV0dG9uLmF0dHIoICd3cGJjX3ByZXZpb3VzX29uY2xpY2snLCBqQnV0dG9uLmF0dHIoICdvbmNsaWNrJyApICk7XHRcdC8vIFNhdmUgdGhpcyB2YWx1ZS5cclxuXHRqQnV0dG9uLmF0dHIoICdvbmNsaWNrJywgJycgKTtcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gRGlzYWJsZSBhY3Rpb25zIFwib24gY2xpY2tcIi5cclxuXHJcblx0cmV0dXJuIHByZXZpb3NfY2xhc3NlcztcclxufVxyXG5cclxuXHJcbi8qKlxyXG4gKiBIaWRlIExvYWRpbmcgKHJvdGF0aW5nIGFycm93KSBpY29uIGZvciBidXR0b24gdGhhdCB3YXMgY2xpY2tlZCBhbmQgc2hvdyBwcmV2aW91cyBpY29uIGFuZCBlbmFibGUgYnV0dG9uXHJcbiAqXHJcbiAqIEBwYXJhbSB0aGlzX2J1dHRvblx0XHQtIHRoaXMgb2JqZWN0IG9mIHNwZWNpZmljIGJ1dHRvblxyXG4gKiBAcmV0dXJuIHN0cmluZ1x0XHRcdC0gQ1NTIGNsYXNzZXMgdGhhdCB3YXMgcHJldmlvdXNseSBpbiBidXR0b24gaWNvblxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19idXR0b25fZGlzYWJsZV9sb2FkaW5nX2ljb24odGhpc19idXR0b24pIHtcclxuXHJcblx0dmFyIGpCdXR0b24gPSBqUXVlcnkoIHRoaXNfYnV0dG9uICk7XHJcblx0dmFyIGpJY29uICAgPSBqQnV0dG9uLmZpbmQoICdpJyApO1xyXG5cclxuXHR2YXIgcHJldmlvc19jbGFzc2VzID0gakljb24uYXR0ciggJ3dwYmNfcHJldmlvdXNfY2xhc3MnICk7XHJcblx0aWYgKFxyXG5cdFx0KHVuZGVmaW5lZCAhPSBwcmV2aW9zX2NsYXNzZXMpXHJcblx0XHQmJiAoJycgIT0gcHJldmlvc19jbGFzc2VzKVxyXG5cdCkge1xyXG5cdFx0akljb24ucmVtb3ZlQ2xhc3MoKS5hZGRDbGFzcyggcHJldmlvc19jbGFzc2VzICk7XHJcblx0fVxyXG5cclxuXHRqQnV0dG9uLnJlbW92ZUNsYXNzKCAnZGlzYWJsZWQnICk7XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIERpc2FibGUgYnV0dG9uLlxyXG5cclxuXHR2YXIgcHJldmlvdXNfb25jbGljayA9IGpCdXR0b24uYXR0ciggJ3dwYmNfcHJldmlvdXNfb25jbGljaycgKVxyXG5cdGlmIChcclxuXHRcdCh1bmRlZmluZWQgIT0gcHJldmlvdXNfb25jbGljaylcclxuXHRcdCYmICgnJyAhPSBwcmV2aW91c19vbmNsaWNrKVxyXG5cdCkge1xyXG5cdFx0akJ1dHRvbi5hdHRyKCAnb25jbGljaycsIHByZXZpb3VzX29uY2xpY2sgKTtcclxuXHR9XHJcblxyXG5cdHJldHVybiBwcmV2aW9zX2NsYXNzZXM7XHJcbn1cclxuIiwiLyoqXHJcbiAqIE9uIHNlbGVjdGlvbiAgb2YgcmFkaW8gYnV0dG9uLCBhZGp1c3QgYXR0cmlidXRlcyBvZiByYWRpbyBjb250YWluZXJcclxuICpcclxuICogQHBhcmFtIF90aGlzXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX3VpX2VsX19yYWRpb19jb250YWluZXJfc2VsZWN0aW9uKF90aGlzKSB7XHJcblxyXG5cdGlmICggalF1ZXJ5KCBfdGhpcyApLmlzKCAnOmNoZWNrZWQnICkgKSB7XHJcblx0XHRqUXVlcnkoIF90aGlzICkucGFyZW50cyggJy53cGJjX3VpX3JhZGlvX3NlY3Rpb24nICkuZmluZCggJy53cGJjX3VpX3JhZGlvX2NvbnRhaW5lcicgKS5yZW1vdmVBdHRyKCAnZGF0YS1zZWxlY3RlZCcgKTtcclxuXHRcdGpRdWVyeSggX3RoaXMgKS5wYXJlbnRzKCAnLndwYmNfdWlfcmFkaW9fY29udGFpbmVyOm5vdCguZGlzYWJsZWQpJyApLmF0dHIoICdkYXRhLXNlbGVjdGVkJywgdHJ1ZSApO1xyXG5cdH1cclxuXHJcblx0aWYgKCBqUXVlcnkoIF90aGlzICkuaXMoICc6ZGlzYWJsZWQnICkgKSB7XHJcblx0XHRqUXVlcnkoIF90aGlzICkucGFyZW50cyggJy53cGJjX3VpX3JhZGlvX2NvbnRhaW5lcicgKS5hZGRDbGFzcyggJ2Rpc2FibGVkJyApO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE9uIGNsaWNrIG9uIFJhZGlvIENvbnRhaW5lciwgd2Ugd2lsbCAgc2VsZWN0ICB0aGUgIHJhZGlvIGJ1dHRvbiAgICBhbmQgdGhlbiBhZGp1c3QgYXR0cmlidXRlcyBvZiByYWRpbyBjb250YWluZXJcclxuICpcclxuICogQHBhcmFtIF90aGlzXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX3VpX2VsX19yYWRpb19jb250YWluZXJfY2xpY2soX3RoaXMpIHtcclxuXHJcblx0aWYgKCBqUXVlcnkoIF90aGlzICkuaGFzQ2xhc3MoICdkaXNhYmxlZCcgKSApIHtcclxuXHRcdHJldHVybiBmYWxzZTtcclxuXHR9XHJcblxyXG5cdHZhciBqX3JhZGlvID0galF1ZXJ5KCBfdGhpcyApLmZpbmQoICdpbnB1dFt0eXBlPXJhZGlvXTpub3QoLndwYmMtZm9ybS1yYWRpby1pbnRlcm5hbCknICk7XHJcblx0aWYgKCBqX3JhZGlvLmxlbmd0aCApIHtcclxuXHRcdGpfcmFkaW8ucHJvcCggJ2NoZWNrZWQnLCB0cnVlICkudHJpZ2dlciggJ2NoYW5nZScgKTtcclxuXHR9XHJcblxyXG59IiwiXCJ1c2Ugc3RyaWN0XCI7XHJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4vLyA9PSBGdWxsIFNjcmVlbiAgLSAgc3VwcG9ydCBmdW5jdGlvbnMgICA9PVxyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuXHJcbi8qKlxuICogUmV0dXJuIGV2ZXJ5IGNvb2tpZSBwYXRoIHRoYXQgY2FuIGFwcGx5IHRvIHRoZSBjdXJyZW50IFdvcmRQcmVzcyBhZG1pbiBVUkwuXG4gKlxuICogV29yZFByZXNzIG1heSBydW4gZnJvbSBhIHN1YmRpcmVjdG9yeS4gVXBkYXRpbmcgdGhlIHJvb3QsIHNpdGUsIGFuZCBhZG1pblxuICogcGF0aHMgcHJldmVudHMgYW4gb2xkZXIsIG1vcmUtc3BlY2lmaWMgY29va2llIGZyb20gb3ZlcnJpZGluZyB0aGUgbmV3IG1vZGUuXG4gKlxuICogQHJldHVybiB7c3RyaW5nW119IFVuaXF1ZSBhYnNvbHV0ZSBjb29raWUgcGF0aHMuXG4gKi9cbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX2Z1bGxfc2NyZWVuX19nZXRfY29va2llX3BhdGhzKCkge1xuXHR2YXIgY29va2llX3BhdGhzID0gWyAnLycgXTtcblx0dmFyIGFkbWluX21hcmtlciA9ICcvd3AtYWRtaW4vJztcblx0dmFyIGN1cnJlbnRfcGF0aCA9IHdpbmRvdy5sb2NhdGlvbiAmJiB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUgPyB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUgOiAnJztcblx0dmFyIGFkbWluX2luZGV4ICA9IGN1cnJlbnRfcGF0aC5pbmRleE9mKCBhZG1pbl9tYXJrZXIgKTtcblxuXHRpZiAoIGFkbWluX2luZGV4ID49IDAgKSB7XG5cdFx0Y29va2llX3BhdGhzLnB1c2goIGN1cnJlbnRfcGF0aC5zdWJzdHJpbmcoIDAsIGFkbWluX2luZGV4ICsgMSApICk7XG5cdFx0Y29va2llX3BhdGhzLnB1c2goIGN1cnJlbnRfcGF0aC5zdWJzdHJpbmcoIDAsIGFkbWluX2luZGV4ICsgYWRtaW5fbWFya2VyLmxlbmd0aCApICk7XG5cdH1cblxuXHRyZXR1cm4gY29va2llX3BhdGhzLmZpbHRlciggZnVuY3Rpb24gKCBwYXRoLCBpbmRleCApIHtcblx0XHRyZXR1cm4gcGF0aCAmJiBjb29raWVfcGF0aHMuaW5kZXhPZiggcGF0aCApID09PSBpbmRleDtcblx0fSApO1xufVxuXG4vKipcbiAqIFNhdmUgRnVsbCBTY3JlZW4gcHJlZmVyZW5jZSBpbiBhIHNob3J0LWxpdmVkIGJyb3dzZXIgY29va2llLlxuICpcbiAqIFRoaXMgbWFrZXMgdGhlIG5leHQgYWRtaW4gcGFnZSBsb2FkIGRldGVybWluaXN0aWMgZXZlbiBpZiB0aGUgYXN5bmNocm9ub3VzXG4gKiB1c2VyLW1ldGEgcmVxdWVzdCBpcyBpbnRlcnJ1cHRlZC4gVGhlIHRpbWVzdGFtcCBsZXRzIFBIUCBkaXN0aW5ndWlzaCB0aGlzXG4gKiBwZW5kaW5nIHZhbHVlIGZyb20gYSBzdGFsZSBsZWdhY3kgY29va2llLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSBGdWxsc2NyZWVuIG1vZGUsIGVpdGhlciBgT25gIG9yIGBPZmZgLlxuICpcbiAqIEByZXR1cm4ge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX2Z1bGxfc2NyZWVuX19zZXRfY29va2llKCB2YWx1ZSApIHtcblx0dmFyIG1heF9hZ2UgICAgICA9IDUgKiA2MDtcblx0dmFyIGlzc3VlZF9hdCAgICA9IE1hdGguZmxvb3IoIERhdGUubm93KCkgLyAxMDAwICk7XG5cdHZhciBjb29raWVfdmFsdWUgPSBlbmNvZGVVUklDb21wb25lbnQoIHZhbHVlICsgJ3wnICsgaXNzdWVkX2F0ICk7XG5cblx0d3BiY19hZG1pbl91aV9fZnVsbF9zY3JlZW5fX2dldF9jb29raWVfcGF0aHMoKS5mb3JFYWNoKCBmdW5jdGlvbiAoIGNvb2tpZV9wYXRoICkge1xuXHRcdGRvY3VtZW50LmNvb2tpZSA9ICd3cGJjX2FkbWluX2Z1bGxfc2NyZWVuPScgKyBjb29raWVfdmFsdWUgKyAnOyBwYXRoPScgKyBjb29raWVfcGF0aCArICc7IG1heC1hZ2U9JyArIG1heF9hZ2UgKyAnOyBTYW1lU2l0ZT1MYXgnO1xuXHR9ICk7XG59XG5cclxuLyoqXHJcbiAqIEFwcGx5IEZ1bGwgU2NyZWVuIG1vZGUgZnJvbSBhIHVzZXIgY2xpY2suXHJcbiAqXHJcbiAqIEBwYXJhbSBIVE1MRWxlbWVudCBlbCAgICAgICAgICAgICAgICAgQ2xpY2tlZCBjb250cm9sLlxyXG4gKiBAcGFyYW0gYm9vbCAgICAgICAgaXNfc2F2ZV91c2VyX3N0YXRlIFdoZXRoZXIgdG8gc2F2ZSB1c2VyIHByZWZlcmVuY2UuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19mdWxsX3NjcmVlbl9fZG9fb24oIGVsLCBpc19zYXZlX3VzZXJfc3RhdGUgKSB7XHJcblx0alF1ZXJ5KCAnYm9keScgKS5hZGRDbGFzcyggJ3dwYmNfYWRtaW5fZnVsbF9zY3JlZW4nICk7XHJcblx0d3BiY19jaGVja19mdWxsX3NjcmVlbl9tb2RlKCk7XHJcblxyXG5cdGlmICggaXNfc2F2ZV91c2VyX3N0YXRlICkge1xyXG5cdFx0d3BiY19hZG1pbl91aV9fZnVsbF9zY3JlZW5fX3NldF9jb29raWUoICdPbicgKTtcclxuXHJcblx0XHRpZiAoICdmdW5jdGlvbicgPT09IHR5cGVvZiB3cGJjX3NhdmVfY3VzdG9tX3VzZXJfZGF0YV9mcm9tX2VsZW1lbnQgKSB7XHJcblx0XHRcdHdwYmNfc2F2ZV9jdXN0b21fdXNlcl9kYXRhX2Zyb21fZWxlbWVudCggZWwgKTtcclxuXHRcdH1cclxuXHR9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeGl0IEZ1bGwgU2NyZWVuIG1vZGUgZnJvbSBhIHVzZXIgY2xpY2suXHJcbiAqXHJcbiAqIEBwYXJhbSBIVE1MRWxlbWVudCBlbCAgICAgICAgICAgICAgICAgQ2xpY2tlZCBjb250cm9sLlxyXG4gKiBAcGFyYW0gYm9vbCAgICAgICAgaXNfc2F2ZV91c2VyX3N0YXRlIFdoZXRoZXIgdG8gc2F2ZSB1c2VyIHByZWZlcmVuY2UuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19mdWxsX3NjcmVlbl9fZG9fb2ZmKCBlbCwgaXNfc2F2ZV91c2VyX3N0YXRlICkge1xyXG5cdGpRdWVyeSggJ2JvZHknICkucmVtb3ZlQ2xhc3MoICd3cGJjX2FkbWluX2Z1bGxfc2NyZWVuJyApO1xyXG5cdHdwYmNfY2hlY2tfZnVsbF9zY3JlZW5fbW9kZSgpO1xyXG5cclxuXHRpZiAoIGlzX3NhdmVfdXNlcl9zdGF0ZSApIHtcclxuXHRcdHdwYmNfYWRtaW5fdWlfX2Z1bGxfc2NyZWVuX19zZXRfY29va2llKCAnT2ZmJyApO1xyXG5cclxuXHRcdGlmICggJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIHdwYmNfc2F2ZV9jdXN0b21fdXNlcl9kYXRhX2Zyb21fZWxlbWVudCApIHtcclxuXHRcdFx0d3BiY19zYXZlX2N1c3RvbV91c2VyX2RhdGFfZnJvbV9lbGVtZW50KCBlbCApO1xyXG5cdFx0fVxyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIENoZWNrIEZ1bGwgIHNjcmVlbiBtb2RlLCAgYnkgIHJlbW92aW5nIHRvcCB0YWJcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfY2hlY2tfZnVsbF9zY3JlZW5fbW9kZSgpe1xyXG5cdGlmICggalF1ZXJ5KCAnYm9keScgKS5oYXNDbGFzcyggJ3dwYmNfYWRtaW5fZnVsbF9zY3JlZW4nICkgKSB7XHJcblx0XHRqUXVlcnkoICdodG1sJyApLnJlbW92ZUNsYXNzKCAnd3AtdG9vbGJhcicgKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0alF1ZXJ5KCAnaHRtbCcgKS5hZGRDbGFzcyggJ3dwLXRvb2xiYXInICk7XHJcblx0fVxyXG5cdHdwYmNfY2hlY2tfYnV0dG9uc19tYXhfbWluX2luX2Z1bGxfc2NyZWVuX21vZGUoKTtcclxufVxyXG5cclxuZnVuY3Rpb24gd3BiY19jaGVja19idXR0b25zX21heF9taW5faW5fZnVsbF9zY3JlZW5fbW9kZSgpIHtcclxuXHRpZiAoIGpRdWVyeSggJ2JvZHknICkuaGFzQ2xhc3MoICd3cGJjX2FkbWluX2Z1bGxfc2NyZWVuJyApICkge1xyXG5cdFx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9mdWxsX3NjcmVlbicgICApLmFkZENsYXNzKCAgICAnd3BiY191aV9faGlkZScgKTtcclxuXHRcdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fbm9ybWFsX3NjcmVlbicgKS5yZW1vdmVDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0fSBlbHNlIHtcclxuXHRcdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fZnVsbF9zY3JlZW4nICAgKS5yZW1vdmVDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0XHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX25vcm1hbF9zY3JlZW4nICkuYWRkQ2xhc3MoICAgICd3cGJjX3VpX19oaWRlJyApO1xyXG5cdH1cclxufVxyXG5cclxualF1ZXJ5KCBkb2N1bWVudCApLnJlYWR5KCBmdW5jdGlvbiAoKSB7XHJcblx0d3BiY19jaGVja19mdWxsX3NjcmVlbl9tb2RlKCk7XHJcbn0gKTtcclxuIiwiLyoqXHJcbiAqIENoZWNrYm94IFNlbGVjdGlvbiBmdW5jdGlvbnMgZm9yIExpc3RpbmcuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFNlbGVjdGlvbnMgb2Ygc2V2ZXJhbCAgY2hlY2tib3hlcyBsaWtlIGluIGdNYWlsIHdpdGggc2hpZnQgOilcclxuICogTmVlZCB0byAgaGF2ZSB0aGlzIHN0cnVjdHVyZTpcclxuICogLndwYmNfc2VsZWN0YWJsZV90YWJsZVxyXG4gKiAgICAgIC53cGJjX3NlbGVjdGFibGVfaGVhZFxyXG4gKiAgICAgICAgICAgICAgLmNoZWNrLWNvbHVtblxyXG4gKiAgICAgICAgICAgICAgICAgIDpjaGVja2JveFxyXG4gKiAgICAgIC53cGJjX3NlbGVjdGFibGVfYm9keVxyXG4gKiAgICAgICAgICAud3BiY19yb3dcclxuICogICAgICAgICAgICAgIC5jaGVjay1jb2x1bW5cclxuICogICAgICAgICAgICAgICAgICA6Y2hlY2tib3hcclxuICogICAgICAud3BiY19zZWxlY3RhYmxlX2Zvb3RcclxuICogICAgICAgICAgICAgIC5jaGVjay1jb2x1bW5cclxuICogICAgICAgICAgICAgICAgICA6Y2hlY2tib3hcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfZGVmaW5lX2dtYWlsX2NoZWNrYm94X3NlbGVjdGlvbiggJCApe1xyXG5cclxuXHR2YXIgY2hlY2tzLCBmaXJzdCwgbGFzdCwgY2hlY2tlZCwgc2xpY2VkLCBsYXN0Q2xpY2tlZCA9IGZhbHNlO1xyXG5cclxuXHQvLyBDaGVjayBhbGwgY2hlY2tib3hlcy5cclxuXHQkKCAnLndwYmNfc2VsZWN0YWJsZV9ib2R5JyApLmZpbmQoICcuY2hlY2stY29sdW1uJyApLmZpbmQoICc6Y2hlY2tib3gnICkub24oXHJcblx0XHQnY2xpY2snLFxyXG5cdFx0ZnVuY3Rpb24gKGUpIHtcclxuXHRcdFx0aWYgKCAndW5kZWZpbmVkJyA9PSBlLnNoaWZ0S2V5ICkge1xyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmICggZS5zaGlmdEtleSApIHtcclxuXHRcdFx0XHRpZiAoICEgbGFzdENsaWNrZWQgKSB7XHJcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Y2hlY2tzICA9ICQoIGxhc3RDbGlja2VkICkuY2xvc2VzdCggJy53cGJjX3NlbGVjdGFibGVfYm9keScgKS5maW5kKCAnOmNoZWNrYm94JyApLmZpbHRlciggJzp2aXNpYmxlOmVuYWJsZWQnICk7XHJcblx0XHRcdFx0Zmlyc3QgICA9IGNoZWNrcy5pbmRleCggbGFzdENsaWNrZWQgKTtcclxuXHRcdFx0XHRsYXN0ICAgID0gY2hlY2tzLmluZGV4KCB0aGlzICk7XHJcblx0XHRcdFx0Y2hlY2tlZCA9ICQoIHRoaXMgKS5wcm9wKCAnY2hlY2tlZCcgKTtcclxuXHRcdFx0XHRpZiAoIDAgPCBmaXJzdCAmJiAwIDwgbGFzdCAmJiBmaXJzdCAhPSBsYXN0ICkge1xyXG5cdFx0XHRcdFx0c2xpY2VkID0gKGxhc3QgPiBmaXJzdCkgPyBjaGVja3Muc2xpY2UoIGZpcnN0LCBsYXN0ICkgOiBjaGVja3Muc2xpY2UoIGxhc3QsIGZpcnN0ICk7XHJcblx0XHRcdFx0XHRzbGljZWQucHJvcChcclxuXHRcdFx0XHRcdFx0J2NoZWNrZWQnLFxyXG5cdFx0XHRcdFx0XHRmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdFx0aWYgKCAkKCB0aGlzICkuY2xvc2VzdCggJy53cGJjX3JvdycgKS5pcyggJzp2aXNpYmxlJyApICkge1xyXG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGNoZWNrZWQ7XHJcblx0XHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0KS50cmlnZ2VyKCAnY2hhbmdlJyApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cdFx0XHRsYXN0Q2xpY2tlZCA9IHRoaXM7XHJcblxyXG5cdFx0XHQvLyB0b2dnbGUgXCJjaGVjayBhbGxcIiBjaGVja2JveGVzLlxyXG5cdFx0XHR2YXIgdW5jaGVja2VkID0gJCggdGhpcyApLmNsb3Nlc3QoICcud3BiY19zZWxlY3RhYmxlX2JvZHknICkuZmluZCggJzpjaGVja2JveCcgKS5maWx0ZXIoICc6dmlzaWJsZTplbmFibGVkJyApLm5vdCggJzpjaGVja2VkJyApO1xyXG5cdFx0XHQkKCB0aGlzICkuY2xvc2VzdCggJy53cGJjX3NlbGVjdGFibGVfdGFibGUnICkuY2hpbGRyZW4oICcud3BiY19zZWxlY3RhYmxlX2hlYWQsIC53cGJjX3NlbGVjdGFibGVfZm9vdCcgKS5maW5kKCAnOmNoZWNrYm94JyApLnByb3AoXHJcblx0XHRcdFx0J2NoZWNrZWQnLFxyXG5cdFx0XHRcdGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0XHRcdHJldHVybiAoMCA9PT0gdW5jaGVja2VkLmxlbmd0aCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHQpLnRyaWdnZXIoICdjaGFuZ2UnICk7XHJcblxyXG5cdFx0XHRyZXR1cm4gdHJ1ZTtcclxuXHRcdH1cclxuXHQpO1xyXG5cclxuXHQvLyBIZWFkIHx8IEZvb3QgY2xpY2tpbmcgdG8gIHNlbGVjdCAvIGRlc2VsZWN0IEFMTC5cclxuXHQkKCAnLndwYmNfc2VsZWN0YWJsZV9oZWFkLCAud3BiY19zZWxlY3RhYmxlX2Zvb3QnICkuZmluZCggJy5jaGVjay1jb2x1bW4gOmNoZWNrYm94JyApLm9uKFxyXG5cdFx0J2NsaWNrJyxcclxuXHRcdGZ1bmN0aW9uIChldmVudCkge1xyXG5cdFx0XHR2YXIgJHRoaXMgICAgICAgICAgPSAkKCB0aGlzICksXHJcblx0XHRcdFx0JHRhYmxlICAgICAgICAgPSAkdGhpcy5jbG9zZXN0KCAnLndwYmNfc2VsZWN0YWJsZV90YWJsZScgKSxcclxuXHRcdFx0XHRjb250cm9sQ2hlY2tlZCA9ICR0aGlzLnByb3AoICdjaGVja2VkJyApLFxyXG5cdFx0XHRcdHRvZ2dsZSAgICAgICAgID0gZXZlbnQuc2hpZnRLZXkgfHwgJHRoaXMuZGF0YSggJ3dwLXRvZ2dsZScgKTtcclxuXHJcblx0XHRcdCR0YWJsZS5jaGlsZHJlbiggJy53cGJjX3NlbGVjdGFibGVfYm9keScgKS5maWx0ZXIoICc6dmlzaWJsZScgKVxyXG5cdFx0XHRcdC5maW5kKCAnLmNoZWNrLWNvbHVtbicgKS5maW5kKCAnOmNoZWNrYm94JyApXHJcblx0XHRcdFx0LnByb3AoXHJcblx0XHRcdFx0XHQnY2hlY2tlZCcsXHJcblx0XHRcdFx0XHRmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdGlmICggJCggdGhpcyApLmlzKCAnOmhpZGRlbiw6ZGlzYWJsZWQnICkgKSB7XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0XHR9XHJcblx0XHRcdFx0XHRcdGlmICggdG9nZ2xlICkge1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiAhICQoIHRoaXMgKS5wcm9wKCAnY2hlY2tlZCcgKTtcclxuXHRcdFx0XHRcdFx0fSBlbHNlIGlmICggY29udHJvbENoZWNrZWQgKSB7XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdCkudHJpZ2dlciggJ2NoYW5nZScgKTtcclxuXHJcblx0XHRcdCR0YWJsZS5jaGlsZHJlbiggJy53cGJjX3NlbGVjdGFibGVfaGVhZCwgIC53cGJjX3NlbGVjdGFibGVfZm9vdCcgKS5maWx0ZXIoICc6dmlzaWJsZScgKVxyXG5cdFx0XHRcdC5maW5kKCAnLmNoZWNrLWNvbHVtbicgKS5maW5kKCAnOmNoZWNrYm94JyApXHJcblx0XHRcdFx0LnByb3AoXHJcblx0XHRcdFx0XHQnY2hlY2tlZCcsXHJcblx0XHRcdFx0XHRmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0XHRcdGlmICggdG9nZ2xlICkge1xyXG5cdFx0XHRcdFx0XHRcdHJldHVybiBmYWxzZTtcclxuXHRcdFx0XHRcdFx0fSBlbHNlIGlmICggY29udHJvbENoZWNrZWQgKSB7XHJcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XHJcblx0XHRcdFx0XHRcdH1cclxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdCk7XHJcblx0XHR9XHJcblx0KTtcclxuXHJcblxyXG5cdC8vIFZpc3VhbGx5ICBzaG93IHNlbGVjdGVkIGJvcmRlci5cclxuXHQkKCAnLndwYmNfc2VsZWN0YWJsZV9ib2R5JyApLmZpbmQoICcuY2hlY2stY29sdW1uIDpjaGVja2JveCcgKS5vbihcclxuXHRcdCdjaGFuZ2UnLFxyXG5cdFx0ZnVuY3Rpb24gKGV2ZW50KSB7XHJcblx0XHRcdGlmICggalF1ZXJ5KCB0aGlzICkuaXMoICc6Y2hlY2tlZCcgKSApIHtcclxuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5jbG9zZXN0KCAnLndwYmNfbGlzdF9yb3cnICkuYWRkQ2xhc3MoICdyb3dfc2VsZWN0ZWRfY29sb3InICk7XHJcblx0XHRcdH0gZWxzZSB7XHJcblx0XHRcdFx0alF1ZXJ5KCB0aGlzICkuY2xvc2VzdCggJy53cGJjX2xpc3Rfcm93JyApLnJlbW92ZUNsYXNzKCAncm93X3NlbGVjdGVkX2NvbG9yJyApO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyBEaXNhYmxlIHRleHQgc2VsZWN0aW9uIHdoaWxlIHByZXNzaW5nICdzaGlmdCcuXHJcblx0XHRcdGRvY3VtZW50LmdldFNlbGVjdGlvbigpLnJlbW92ZUFsbFJhbmdlcygpO1xyXG5cclxuXHRcdFx0Ly8gU2hvdyBvciBoaWRlIGJ1dHRvbnMgb24gQWN0aW9ucyB0b29sYmFyICBhdCAgQm9va2luZyBMaXN0aW5nICBwYWdlLCAgaWYgd2UgaGF2ZSBzb21lIHNlbGVjdGVkIGJvb2tpbmdzLlxyXG5cdFx0XHR3cGJjX3Nob3dfaGlkZV9hY3Rpb25fYnV0dG9uc19mb3Jfc2VsZWN0ZWRfYm9va2luZ3MoKTtcclxuXHRcdH1cclxuXHQpO1xyXG5cclxuXHR3cGJjX3Nob3dfaGlkZV9hY3Rpb25fYnV0dG9uc19mb3Jfc2VsZWN0ZWRfYm9va2luZ3MoKTtcclxufVxyXG4iLCJcclxuLyoqXHJcbiAqIEdldCBJRCBhcnJheSAgb2Ygc2VsZWN0ZWQgZWxlbWVudHNcclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfZ2V0X3NlbGVjdGVkX3Jvd19pZCgpIHtcclxuXHJcblx0dmFyICR0YWJsZSAgICAgID0galF1ZXJ5KCAnLndwYmNfX3dyYXBfX2Jvb2tpbmdfbGlzdGluZyAud3BiY19zZWxlY3RhYmxlX3RhYmxlJyApO1xyXG5cdHZhciBjaGVja2JveGVzICA9ICR0YWJsZS5jaGlsZHJlbiggJy53cGJjX3NlbGVjdGFibGVfYm9keScgKS5maWx0ZXIoICc6dmlzaWJsZScgKS5maW5kKCAnLmNoZWNrLWNvbHVtbicgKS5maW5kKCAnOmNoZWNrYm94JyApO1xyXG5cdHZhciBzZWxlY3RlZF9pZCA9IFtdO1xyXG5cclxuXHRqUXVlcnkuZWFjaChcclxuXHRcdGNoZWNrYm94ZXMsXHJcblx0XHRmdW5jdGlvbiAoa2V5LCBjaGVja2JveCkge1xyXG5cdFx0XHRpZiAoIGpRdWVyeSggY2hlY2tib3ggKS5pcyggJzpjaGVja2VkJyApICkge1xyXG5cdFx0XHRcdHZhciBlbGVtZW50X2lkID0gd3BiY19nZXRfcm93X2lkX2Zyb21fZWxlbWVudCggY2hlY2tib3ggKTtcclxuXHRcdFx0XHRzZWxlY3RlZF9pZC5wdXNoKCBlbGVtZW50X2lkICk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHQpO1xyXG5cclxuXHRyZXR1cm4gc2VsZWN0ZWRfaWQ7XHJcbn1cclxuXHJcblxyXG4vKipcclxuICogR2V0IElEIG9mIHJvdywgIGJhc2VkIG9uIGNsY2lrZWQgZWxlbWVudFxyXG4gKlxyXG4gKiBAcGFyYW0gdGhpc19pbmJvdW5kX2VsZW1lbnQgIC0gdXN1c2xseSAgdGhpc1xyXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19nZXRfcm93X2lkX2Zyb21fZWxlbWVudCh0aGlzX2luYm91bmRfZWxlbWVudCkge1xyXG5cclxuXHR2YXIgZWxlbWVudF9pZCA9IGpRdWVyeSggdGhpc19pbmJvdW5kX2VsZW1lbnQgKS5jbG9zZXN0KCAnLndwYmNfbGlzdGluZ191c3VhbF9yb3cnICkuYXR0ciggJ2lkJyApO1xyXG5cclxuXHRlbGVtZW50X2lkID0gcGFyc2VJbnQoIGVsZW1lbnRfaWQucmVwbGFjZSggJ3Jvd19pZF8nLCAnJyApICk7XHJcblxyXG5cdHJldHVybiBlbGVtZW50X2lkO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqID09IEJvb2tpbmcgTGlzdGluZyA9PSBTaG93IG9yIGhpZGUgYnV0dG9ucyBvbiBBY3Rpb25zIHRvb2xiYXIgIGF0ICAgIHBhZ2UsICBpZiB3ZSBoYXZlIHNvbWUgc2VsZWN0ZWQgYm9va2luZ3MuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX3Nob3dfaGlkZV9hY3Rpb25fYnV0dG9uc19mb3Jfc2VsZWN0ZWRfYm9va2luZ3MoKXtcclxuXHJcblx0dmFyIHNlbGVjdGVkX3Jvd3NfYXJyID0gd3BiY19nZXRfc2VsZWN0ZWRfcm93X2lkKCk7XHJcblxyXG5cdGlmICggc2VsZWN0ZWRfcm93c19hcnIubGVuZ3RoID4gMCApIHtcclxuXHRcdGpRdWVyeSggJy5oaWRlX2J1dHRvbl9pZl9ub19zZWxlY3Rpb24nICkuc2hvdygpO1xyXG5cdH0gZWxzZSB7XHJcblx0XHRqUXVlcnkoICcuaGlkZV9idXR0b25faWZfbm9fc2VsZWN0aW9uJyApLmhpZGUoKTtcclxuXHR9XHJcbn0iLCJcInVzZSBzdHJpY3RcIjtcclxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbi8vID09IExlZnQgQmFyICAtICBleHBhbmQgLyBjb2xhcHNlIGZ1bmN0aW9ucyAgID09XHJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG5cclxuLyoqXHJcbiAqIFNhdmUgdXNlcidzIHByZWZlcnJlZCBsZWZ0IHNpZGViYXIgbW9kZS5cclxuICpcclxuICogQHBhcmFtIHN0cmluZyBtb2RlXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX3NhdmVfbW9kZSggbW9kZSApIHtcclxuXHR2YXIgYWxsb3dlZF9tb2RlcyA9IFsgJ21pbicsICdjb21wYWN0JywgJ21heCcgXTtcclxuXHJcblx0aWYgKCBhbGxvd2VkX21vZGVzLmluZGV4T2YoIG1vZGUgKSA9PT0gLTEgKSB7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHR2YXIgJHNhdmVyID0galF1ZXJ5KCAnI3dwYmNfbGVmdF9zaWRlYmFyX3ZpZXdfbW9kZV9zYXZlcicgKTtcclxuXHJcblx0aWYgKCAhICRzYXZlci5sZW5ndGggKSB7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHRpZiAoICdmdW5jdGlvbicgIT09IHR5cGVvZiB3cGJjX3NhdmVfY3VzdG9tX3VzZXJfZGF0YV9mcm9tX2VsZW1lbnQgKSB7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHQkc2F2ZXIuZGF0YSggJ3dwYmMtdS1zYXZlLXZhbHVlJywgbW9kZSApO1xyXG5cdCRzYXZlci5hdHRyKCAnZGF0YS13cGJjLXUtc2F2ZS12YWx1ZScsIG1vZGUgKTtcclxuXHJcblx0d3BiY19zYXZlX2N1c3RvbV91c2VyX2RhdGFfZnJvbV9lbGVtZW50KCAkc2F2ZXIuZ2V0KCAwICkgKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldmVhbCB0aGUgYWN0aXZlIGl0ZW0gaW5zaWRlIHRoZSBzY3JvbGxhYmxlIGxlZnQgbmF2aWdhdGlvbi5cclxuICpcclxuICogVGhlIGFjdGl2ZSBpdGVtIGl0c2VsZiBpcyBhbGlnbmVkIHdpdGggYSBzbWFsbCBsZWFkaW5nIG9mZnNldCwgcmVnYXJkbGVzcyBvZlxyXG4gKiBpdHMgcG9zaXRpb24gaW5zaWRlIGEgcm9vdCBzZWN0aW9uLiBTY3JvbGxpbmcgaXMgYXBwbGllZCBvbmx5IHRvIFNpbXBsZUJhcidzXHJcbiAqIGludGVybmFsIHNjcm9sbCBlbGVtZW50IHNvIHRoZSBXb3JkUHJlc3MgYWRtaW5pc3RyYXRpb24gZG9jdW1lbnQgZG9lcyBub3RcclxuICogbW92ZS5cclxuICpcclxuICogQHBhcmFtIHtPYmplY3R8bnVsbHx1bmRlZmluZWR9IHNpbXBsZWJhcl9pbnN0YW5jZSBPcHRpb25hbCBpbml0aWFsaXplZCBTaW1wbGVCYXIgaW5zdGFuY2UuXHJcbiAqIEByZXR1cm4ge3ZvaWR9XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX3Njcm9sbF90b19hY3RpdmVfaXRlbSggc2ltcGxlYmFyX2luc3RhbmNlICkge1xyXG5cdHZhciBsZWZ0X25hdmlnYXRpb25fZWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoICcud3BiY191aV9lbF9fdmVydF9sZWZ0X2Jhcl9fY29udGVudCcgKTtcclxuXHJcblx0aWYgKFxyXG5cdFx0ISBzaW1wbGViYXJfaW5zdGFuY2VcclxuXHRcdCYmICd1bmRlZmluZWQnICE9PSB0eXBlb2YgU2ltcGxlQmFyXHJcblx0XHQmJiBTaW1wbGVCYXIuaW5zdGFuY2VzXHJcblx0XHQmJiBsZWZ0X25hdmlnYXRpb25fZWxlbWVudFxyXG5cdCkge1xyXG5cdFx0c2ltcGxlYmFyX2luc3RhbmNlID0gU2ltcGxlQmFyLmluc3RhbmNlcy5nZXQoIGxlZnRfbmF2aWdhdGlvbl9lbGVtZW50ICk7XHJcblx0fVxyXG5cclxuXHRpZiAoXHJcblx0XHQhIHNpbXBsZWJhcl9pbnN0YW5jZVxyXG5cdFx0fHwgJ2Z1bmN0aW9uJyAhPT0gdHlwZW9mIHNpbXBsZWJhcl9pbnN0YW5jZS5nZXRTY3JvbGxFbGVtZW50XHJcblx0XHR8fCAnZnVuY3Rpb24nICE9PSB0eXBlb2Ygc2ltcGxlYmFyX2luc3RhbmNlLmdldENvbnRlbnRFbGVtZW50XHJcblx0KSB7XHJcblx0XHRyZXR1cm47XHJcblx0fVxyXG5cclxuXHR3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCBmdW5jdGlvbiAoKSB7XHJcblx0XHR2YXIgc2Nyb2xsX2VsZW1lbnQgID0gc2ltcGxlYmFyX2luc3RhbmNlLmdldFNjcm9sbEVsZW1lbnQoKTtcclxuXHRcdHZhciBjb250ZW50X2VsZW1lbnQgPSBzaW1wbGViYXJfaW5zdGFuY2UuZ2V0Q29udGVudEVsZW1lbnQoKTtcclxuXHJcblx0XHRpZiAoXHJcblx0XHRcdCEgc2Nyb2xsX2VsZW1lbnRcclxuXHRcdFx0fHwgISBjb250ZW50X2VsZW1lbnRcclxuXHRcdFx0fHwgISBjb250ZW50X2VsZW1lbnQuY2xvc2VzdCggJy53cGJjX3VpX2VsX192ZXJ0X2xlZnRfYmFyX19jb250ZW50JyApXHJcblx0XHQpIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cclxuXHRcdHNpbXBsZWJhcl9pbnN0YW5jZS5yZWNhbGN1bGF0ZSgpO1xyXG5cclxuXHRcdHZhciBhY3RpdmVfaXRlbSA9IGNvbnRlbnRfZWxlbWVudC5xdWVyeVNlbGVjdG9yKCAnLndwYmNfdWlfZWxfX3ZlcnRfbmF2X2l0ZW0uYWN0aXZlJyApO1xyXG5cclxuXHRcdGlmICggISBhY3RpdmVfaXRlbSB8fCBudWxsID09PSBhY3RpdmVfaXRlbS5vZmZzZXRQYXJlbnQgfHwgMCA+PSBzY3JvbGxfZWxlbWVudC5jbGllbnRIZWlnaHQgKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHR2YXIgc2Nyb2xsX3JlY3QgICAgPSBzY3JvbGxfZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuXHRcdHZhciBhY3RpdmVfcmVjdCAgICA9IGFjdGl2ZV9pdGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG5cdFx0dmFyIGN1cnJlbnRfdG9wICAgID0gc2Nyb2xsX2VsZW1lbnQuc2Nyb2xsVG9wO1xyXG5cdFx0dmFyIGxlYWRpbmdfb2Zmc2V0ID0gODU7XHJcblx0XHR2YXIgYWN0aXZlX3RvcCAgICAgPSBjdXJyZW50X3RvcCArIGFjdGl2ZV9yZWN0LnRvcCAtIHNjcm9sbF9yZWN0LnRvcDtcclxuXHRcdHZhciB0YXJnZXRfdG9wICAgICA9IGFjdGl2ZV90b3AgLSBsZWFkaW5nX29mZnNldDtcclxuXHJcblx0XHR2YXIgbWF4aW11bV90b3AgPSBNYXRoLm1heCggMCwgc2Nyb2xsX2VsZW1lbnQuc2Nyb2xsSGVpZ2h0IC0gc2Nyb2xsX2VsZW1lbnQuY2xpZW50SGVpZ2h0ICk7XHJcblxyXG5cdFx0c2Nyb2xsX2VsZW1lbnQuc2Nyb2xsVG9wID0gTWF0aC5tYXgoIDAsIE1hdGgubWluKCBNYXRoLnJvdW5kKCB0YXJnZXRfdG9wICksIG1heGltdW1fdG9wICkgKTtcclxuXHR9ICk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFeHBhbmQgVmVydGljYWwgTGVmdCBCYXIuXHJcbiAqXHJcbiAqIEBwYXJhbSBib29sIGlzX3NhdmVfdXNlcl9zdGF0ZSBTYXZlIHRoaXMgbW9kZSBhcyB1c2VyJ3MgcHJlZmVyZW5jZS5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfbGVmdF9fZG9fbWF4KCBpc19zYXZlX3VzZXJfc3RhdGUgKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLnJlbW92ZUNsYXNzKCAnbWluIG1heCBjb21wYWN0IG5vbmUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLmFkZENsYXNzKCAnbWF4JyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fb3Blbl9sZWZ0X3ZlcnRpY2FsX25hdicgKS5hZGRDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9oaWRlX2xlZnRfdmVydGljYWxfbmF2JyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHJcblx0alF1ZXJ5KCAnLndwLWFkbWluJyApLnJlbW92ZUNsYXNzKCAnd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9taW4gd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9tYXggd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9jb21wYWN0IHdwYmNfcGFnZV93cmFwcGVyX2xlZnRfbm9uZScgKTtcclxuXHRqUXVlcnkoICcud3AtYWRtaW4nICkuYWRkQ2xhc3MoICd3cGJjX3BhZ2Vfd3JhcHBlcl9sZWZ0X21heCcgKTtcclxuXHR3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX3Njcm9sbF90b19hY3RpdmVfaXRlbSgpO1xyXG5cclxuXHRpZiAoIGlzX3NhdmVfdXNlcl9zdGF0ZSApIHtcclxuXHRcdHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfbGVmdF9fc2F2ZV9tb2RlKCAnbWF4JyApO1xyXG5cdH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEhpZGUgVmVydGljYWwgTGVmdCBCYXIuXHJcbiAqXHJcbiAqIEBwYXJhbSBib29sIGlzX3NhdmVfdXNlcl9zdGF0ZSBTYXZlIHRoaXMgbW9kZSBhcyB1c2VyJ3MgcHJlZmVyZW5jZS5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfbGVmdF9fZG9fbWluKCBpc19zYXZlX3VzZXJfc3RhdGUgKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLnJlbW92ZUNsYXNzKCAnbWluIG1heCBjb21wYWN0IG5vbmUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLmFkZENsYXNzKCAnbWluJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fb3Blbl9sZWZ0X3ZlcnRpY2FsX25hdicgKS5yZW1vdmVDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9oaWRlX2xlZnRfdmVydGljYWxfbmF2JyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHJcblx0alF1ZXJ5KCAnLndwLWFkbWluJyApLnJlbW92ZUNsYXNzKCAnd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9taW4gd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9tYXggd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9jb21wYWN0IHdwYmNfcGFnZV93cmFwcGVyX2xlZnRfbm9uZScgKTtcclxuXHRqUXVlcnkoICcud3AtYWRtaW4nICkuYWRkQ2xhc3MoICd3cGJjX3BhZ2Vfd3JhcHBlcl9sZWZ0X21pbicgKTtcclxuXHJcblx0aWYgKCBpc19zYXZlX3VzZXJfc3RhdGUgKSB7XHJcblx0XHR3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX3NhdmVfbW9kZSggJ21pbicgKTtcclxuXHR9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb2xhcHNlIFZlcnRpY2FsIExlZnQgQmFyLlxyXG4gKlxyXG4gKiBAcGFyYW0gYm9vbCBpc19zYXZlX3VzZXJfc3RhdGUgU2F2ZSB0aGlzIG1vZGUgYXMgdXNlcidzIHByZWZlcmVuY2UuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX2RvX2NvbXBhY3QoIGlzX3NhdmVfdXNlcl9zdGF0ZSApIHtcclxuXHRqUXVlcnkoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICkucmVtb3ZlQ2xhc3MoICdtaW4gbWF4IGNvbXBhY3Qgbm9uZScgKTtcclxuXHRqUXVlcnkoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICkuYWRkQ2xhc3MoICdjb21wYWN0JyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fb3Blbl9sZWZ0X3ZlcnRpY2FsX25hdicgKS5yZW1vdmVDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9oaWRlX2xlZnRfdmVydGljYWxfbmF2JyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHJcblx0alF1ZXJ5KCAnLndwLWFkbWluJyApLnJlbW92ZUNsYXNzKCAnd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9taW4gd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9tYXggd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9jb21wYWN0IHdwYmNfcGFnZV93cmFwcGVyX2xlZnRfbm9uZScgKTtcclxuXHRqUXVlcnkoICcud3AtYWRtaW4nICkuYWRkQ2xhc3MoICd3cGJjX3BhZ2Vfd3JhcHBlcl9sZWZ0X2NvbXBhY3QnICk7XHJcblx0d3BiY19hZG1pbl91aV9fc2lkZWJhcl9sZWZ0X19zY3JvbGxfdG9fYWN0aXZlX2l0ZW0oKTtcclxuXHJcblx0aWYgKCBpc19zYXZlX3VzZXJfc3RhdGUgKSB7XHJcblx0XHR3cGJjX2FkbWluX3VpX19zaWRlYmFyX2xlZnRfX3NhdmVfbW9kZSggJ2NvbXBhY3QnICk7XHJcblx0fVxyXG59XHJcblxyXG4vKipcclxuICogQ29tcGxldGVseSBIaWRlIFZlcnRpY2FsIExlZnQgQmFyLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9sZWZ0X19kb19oaWRlKCkge1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5yZW1vdmVDbGFzcyggJ21pbiBtYXggY29tcGFjdCBub25lJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3NldHRpbmdzX3BhZ2Vfd3JhcHBlcicgKS5hZGRDbGFzcyggJ25vbmUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9vcGVuX2xlZnRfdmVydGljYWxfbmF2JyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX2hpZGVfbGVmdF92ZXJ0aWNhbF9uYXYnICkuYWRkQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG5cdC8vIEhpZGUgdG9wIFwiTWVudVwiIGJ1dHRvbiB3aXRoIGRpdmlkZXIuXHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9zaG93X2xlZnRfdmVydGljYWxfbmF2LC53cGJjX3VpX190b3BfbmF2X19idG5fc2hvd19sZWZ0X3ZlcnRpY2FsX25hdl9kaXZpZGVyJyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHJcblx0alF1ZXJ5KCAnLndwLWFkbWluJyApLnJlbW92ZUNsYXNzKCAnd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9taW4gd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9tYXggd3BiY19wYWdlX3dyYXBwZXJfbGVmdF9jb21wYWN0IHdwYmNfcGFnZV93cmFwcGVyX2xlZnRfbm9uZScgKTtcclxuXHRqUXVlcnkoICcud3AtYWRtaW4nICkuYWRkQ2xhc3MoICd3cGJjX3BhZ2Vfd3JhcHBlcl9sZWZ0X25vbmUnICk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBY3Rpb24gb24gY2xpY2sgXCJHbyBCYWNrXCIgLSBzaG93IHJvb3QgbWVudVxyXG4gKiBvciBzb21lIG90aGVyIHNlY3Rpb24gaW4gbGVmdCBzaWRlYmFyLlxyXG4gKlxyXG4gKiBAcGFyYW0gc3RyaW5nIG1lbnVfdG9fc2hvdyAtIG1lbnUgc2x1Zy5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfbGVmdF9fc2hvd19zZWN0aW9uKCBtZW51X3RvX3Nob3cgKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfZWxfX3ZlcnRfbGVmdF9iYXJfX3NlY3Rpb24nICkuYWRkQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApXHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfZWxfX3ZlcnRfbGVmdF9iYXJfX3NlY3Rpb25fJyArIG1lbnVfdG9fc2hvdyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxufVxyXG5cclxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcbi8vID09IFJpZ2h0IFNpZGUgQmFyICAtICBleHBhbmQgLyBjb2xhcHNlIGZ1bmN0aW9ucyAgID09XHJcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG5cclxuLyoqXHJcbiAqIFN5bmNocm9uaXplIHRoZSBkb2N1bWVudCBib2R5IG1hcmtlciBmb3IgdGhlIGV4cGFuZGVkIHJpZ2h0IHNpZGViYXIuXHJcbiAqXHJcbiAqIFRoZSBtYXJrZXIgaXMgZG9tYWluLW5ldXRyYWwgc28gaW5kaXZpZHVhbCBhZG1pbmlzdHJhdGlvbiBwYWdlcyBjYW4gYWRqdXN0XHJcbiAqIHRoZWlyIHByZXNlbnRhdGlvbiB3aXRob3V0IGR1cGxpY2F0aW5nIHJpZ2h0LXNpZGViYXIgc3RhdGUgaGFuZGxpbmcuXHJcbiAqXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNfb3BlbiBXaGV0aGVyIHRoZSByaWdodCBzaWRlYmFyIGlzIGZ1bGx5IGV4cGFuZGVkLlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9yaWdodF9fc2V0X2JvZHlfb3Blbl9zdGF0ZSggaXNfb3BlbiApIHtcclxuXHRqUXVlcnkoICdib2R5JyApLnRvZ2dsZUNsYXNzKCAnd3BiY191aV9lbF9fdmVydF9yaWdodF9iYXJfX3dyYXBwZXJfb3BlbmVkJywgISEgaXNfb3BlbiApO1xyXG59XHJcblxyXG4vKipcclxuICogRXhwYW5kIFZlcnRpY2FsIFJpZ2h0IEJhci5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfcmlnaHRfX2RvX21heCgpIHtcclxuXHRqUXVlcnkoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICkucmVtb3ZlQ2xhc3MoICdtaW5fcmlnaHQgbWF4X3JpZ2h0IGNvbXBhY3RfcmlnaHQgbm9uZV9yaWdodCcgKTtcclxuXHRqUXVlcnkoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICkuYWRkQ2xhc3MoICdtYXhfcmlnaHQnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9vcGVuX3JpZ2h0X3ZlcnRpY2FsX25hdicgKS5hZGRDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9oaWRlX3JpZ2h0X3ZlcnRpY2FsX25hdicgKS5yZW1vdmVDbGFzcyggJ3dwYmNfdWlfX2hpZGUnICk7XHJcblx0d3BiY19hZG1pbl91aV9fc2lkZWJhcl9yaWdodF9fc2V0X2JvZHlfb3Blbl9zdGF0ZSggdHJ1ZSApO1xyXG59XHJcblxyXG4vKipcclxuICogSGlkZSBWZXJ0aWNhbCBSaWdodCBCYXIuXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19zaWRlYmFyX3JpZ2h0X19kb19taW4oKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLnJlbW92ZUNsYXNzKCAnbWluX3JpZ2h0IG1heF9yaWdodCBjb21wYWN0X3JpZ2h0IG5vbmVfcmlnaHQnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLmFkZENsYXNzKCAnbWluX3JpZ2h0JyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fb3Blbl9yaWdodF92ZXJ0aWNhbF9uYXYnICkucmVtb3ZlQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5faGlkZV9yaWdodF92ZXJ0aWNhbF9uYXYnICkuYWRkQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG5cdHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfcmlnaHRfX3NldF9ib2R5X29wZW5fc3RhdGUoIGZhbHNlICk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBDb2xhcHNlIFZlcnRpY2FsIFJpZ2h0IEJhci5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfcmlnaHRfX2RvX2NvbXBhY3QoKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLnJlbW92ZUNsYXNzKCAnbWluX3JpZ2h0IG1heF9yaWdodCBjb21wYWN0X3JpZ2h0IG5vbmVfcmlnaHQnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLmFkZENsYXNzKCAnY29tcGFjdF9yaWdodCcgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX29wZW5fcmlnaHRfdmVydGljYWxfbmF2JyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX2hpZGVfcmlnaHRfdmVydGljYWxfbmF2JyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHR3cGJjX2FkbWluX3VpX19zaWRlYmFyX3JpZ2h0X19zZXRfYm9keV9vcGVuX3N0YXRlKCBmYWxzZSApO1xyXG59XHJcblxyXG4vKipcclxuICogQ29tcGxldGVseSBIaWRlIFZlcnRpY2FsIFJpZ2h0IEJhci5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfcmlnaHRfX2RvX2hpZGUoKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLnJlbW92ZUNsYXNzKCAnbWluX3JpZ2h0IG1heF9yaWdodCBjb21wYWN0X3JpZ2h0IG5vbmVfcmlnaHQnICk7XHJcblx0alF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyJyApLmFkZENsYXNzKCAnbm9uZV9yaWdodCcgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX29wZW5fcmlnaHRfdmVydGljYWxfbmF2JyApLnJlbW92ZUNsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHRqUXVlcnkoICcud3BiY191aV9fdG9wX25hdl9fYnRuX2hpZGVfcmlnaHRfdmVydGljYWxfbmF2JyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHQvLyBIaWRlIHRvcCBcIk1lbnVcIiBidXR0b24gd2l0aCBkaXZpZGVyLlxyXG5cdGpRdWVyeSggJy53cGJjX3VpX190b3BfbmF2X19idG5fc2hvd19yaWdodF92ZXJ0aWNhbF9uYXYsLndwYmNfdWlfX3RvcF9uYXZfX2J0bl9zaG93X3JpZ2h0X3ZlcnRpY2FsX25hdl9kaXZpZGVyJyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKTtcclxuXHR3cGJjX2FkbWluX3VpX19zaWRlYmFyX3JpZ2h0X19zZXRfYm9keV9vcGVuX3N0YXRlKCBmYWxzZSApO1xyXG59XHJcblxyXG4vKipcclxuICogUmVzdG9yZSB0aGUgYm9keSBtYXJrZXIgd2hlbiBhIHBhZ2UgcmVuZGVycyB3aXRoIHRoZSByaWdodCBzaWRlYmFyIG9wZW4uXHJcbiAqL1xyXG5qUXVlcnkoIGRvY3VtZW50ICkucmVhZHkoIGZ1bmN0aW9uICgpIHtcclxuXHR3cGJjX2FkbWluX3VpX19zaWRlYmFyX3JpZ2h0X19zZXRfYm9keV9vcGVuX3N0YXRlKCAwIDwgalF1ZXJ5KCAnLndwYmNfc2V0dGluZ3NfcGFnZV93cmFwcGVyLm1heF9yaWdodCcgKS5sZW5ndGggKTtcclxufSApO1xyXG5cclxuLyoqXHJcbiAqIENvbGxhcHNlIGFuIGV4cGFuZGVkIHJpZ2h0IHNpZGViYXIgYWZ0ZXIgYW4gb3B0ZWQtaW4gcGFnZS1jb250ZW50IGNsaWNrLlxyXG4gKlxyXG4gKiBQYWdlcyBlbmFibGUgdGhpcyBiZWhhdmlvciB0aHJvdWdoIHRoZSBwYWdlLXN0cnVjdHVyZVxyXG4gKiByaWdodF92ZXJ0aWNhbF9zaWRlYmFyX19jb250ZW50X2NsaWNrX2NvbGxhcHNlX21vZGUgb3B0aW9uLiBJbnRlcmFjdGl2ZVxyXG4gKiBjb250cm9scyB0aGF0IG9wZW4gb3IgcmV0YWluIHNpZGViYXIgY29udGVudCBjYW4gb3B0IG91dCBieSBwbGFjaW5nIHRoZVxyXG4gKiBkYXRhLXdwYmMtcmlnaHQtc2lkZWJhci1rZWVwLW9wZW4gYXR0cmlidXRlIG9uIHRoZW1zZWx2ZXMgb3IgYW4gYW5jZXN0b3IuXHJcbiAqXHJcbiAqIEBwYXJhbSB7TW91c2VFdmVudH0gZXZlbnQgQ29udGVudCBjbGljayBldmVudCBjYXB0dXJlZCBiZWZvcmUgY2F0YWxvZyByb3dzLlxyXG4gKiBAcmV0dXJuIHt2b2lkfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9yaWdodF9fY29sbGFwc2VfZnJvbV9jb250ZW50X2NsaWNrKCBldmVudCApIHtcclxuXHR2YXIgZXZlbnRfdGFyZ2V0ID0gZXZlbnQudGFyZ2V0ICYmIDEgPT09IGV2ZW50LnRhcmdldC5ub2RlVHlwZSA/IGV2ZW50LnRhcmdldCA6IG51bGw7XHJcblx0dmFyIGNvbnRlbnRfZWxlbWVudCA9IGV2ZW50X3RhcmdldCAmJiAnZnVuY3Rpb24nID09PSB0eXBlb2YgZXZlbnRfdGFyZ2V0LmNsb3Nlc3RcclxuXHRcdD8gZXZlbnRfdGFyZ2V0LmNsb3Nlc3QoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXJbZGF0YS13cGJjLXJpZ2h0LXNpZGViYXItY29udGVudC1jbGljay1jb2xsYXBzZS1tb2RlXSA+IC53cGJjX3NldHRpbmdzX3BhZ2VfY29udGVudCcgKVxyXG5cdFx0OiBudWxsO1xyXG5cdHZhciAkY29udGVudDtcclxuXHR2YXIgJHdyYXBwZXI7XHJcblx0dmFyIGNvbGxhcHNlX21vZGU7XHJcblx0dmFyIGJlZm9yZV9jb2xsYXBzZV9ldmVudDtcclxuXHJcblx0aWYgKCAhIGNvbnRlbnRfZWxlbWVudCApIHtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdCRjb250ZW50ID0galF1ZXJ5KCBjb250ZW50X2VsZW1lbnQgKTtcclxuXHQkd3JhcHBlciA9ICRjb250ZW50LmNsb3Nlc3QoICcud3BiY19zZXR0aW5nc19wYWdlX3dyYXBwZXInICk7XHJcblx0Y29sbGFwc2VfbW9kZSA9IFN0cmluZyggJHdyYXBwZXIuYXR0ciggJ2RhdGEtd3BiYy1yaWdodC1zaWRlYmFyLWNvbnRlbnQtY2xpY2stY29sbGFwc2UtbW9kZScgKSB8fCAnJyApO1xyXG5cclxuXHRpZiAoICEgJHdyYXBwZXIuaGFzQ2xhc3MoICdtYXhfcmlnaHQnICkgfHwgWyAnbWluJywgJ2NvbXBhY3QnLCAnbm9uZScgXS5pbmRleE9mKCBjb2xsYXBzZV9tb2RlICkgPT09IC0xICkge1xyXG5cdFx0cmV0dXJuO1xyXG5cdH1cclxuXHRpZiAoIGpRdWVyeSggZXZlbnQudGFyZ2V0ICkuY2xvc2VzdCggJ1tkYXRhLXdwYmMtcmlnaHQtc2lkZWJhci1rZWVwLW9wZW5dJyApLmxlbmd0aCApIHtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdC8qXHJcblx0ICogVGhpcyBjbGljayBiZWxvbmdzIHRvIHRoZSBvcGVuLXNpZGViYXIgZGlzbWlzc2FsIGxheWVyLiBDb25zdW1lIGl0IGJlZm9yZVxyXG5cdCAqIGRvbWFpbiByb3cgaGFuZGxlcnMgcnVuIHNvIHRoZSBzYW1lIHBvaW50ZXIgYWN0aW9uIGNhbm5vdCBjbG9zZSBvbmVcclxuXHQgKiBpbnNwZWN0b3IgYW5kIGltbWVkaWF0ZWx5IG9wZW4gYW5vdGhlciBvbmUgdW5kZXJuZWF0aCBpdC5cclxuXHQgKi9cclxuXHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xyXG5cclxuXHRiZWZvcmVfY29sbGFwc2VfZXZlbnQgPSBqUXVlcnkuRXZlbnQoICd3cGJjOnJpZ2h0LXNpZGViYXItYmVmb3JlLWNvbnRlbnQtY29sbGFwc2UnICk7XHJcblx0JHdyYXBwZXIudHJpZ2dlciggYmVmb3JlX2NvbGxhcHNlX2V2ZW50LCBbIGV2ZW50IF0gKTtcclxuXHRpZiAoIGJlZm9yZV9jb2xsYXBzZV9ldmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSApIHtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdGlmICggJ2NvbXBhY3QnID09PSBjb2xsYXBzZV9tb2RlICkge1xyXG5cdFx0d3BiY19hZG1pbl91aV9fc2lkZWJhcl9yaWdodF9fZG9fY29tcGFjdCgpO1xyXG5cdH0gZWxzZSBpZiAoICdub25lJyA9PT0gY29sbGFwc2VfbW9kZSApIHtcclxuXHRcdHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfcmlnaHRfX2RvX2hpZGUoKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0d3BiY19hZG1pbl91aV9fc2lkZWJhcl9yaWdodF9fZG9fbWluKCk7XHJcblx0fVxyXG5cclxuXHRqUXVlcnkoIGRvY3VtZW50ICkudHJpZ2dlciggJ3dwYmNfc2V0dXBfd2l6YXJkX2xheW91dF9jaGFuZ2VkJyApO1xyXG59XHJcblxyXG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCAnY2xpY2snLCB3cGJjX2FkbWluX3VpX19zaWRlYmFyX3JpZ2h0X19jb2xsYXBzZV9mcm9tX2NvbnRlbnRfY2xpY2ssIHRydWUgKTtcclxuXHJcblxyXG4vKipcclxuICogQWN0aW9uIG9uIGNsaWNrIFwiR28gQmFja1wiIC0gc2hvdyByb290IG1lbnVcclxuICogb3Igc29tZSBvdGhlciBzZWN0aW9uIGluIHJpZ2h0IHNpZGViYXIuXHJcbiAqXHJcbiAqIEBwYXJhbSBzdHJpbmcgbWVudV90b19zaG93IC0gbWVudSBzbHVnLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fc2lkZWJhcl9yaWdodF9fc2hvd19zZWN0aW9uKCBtZW51X3RvX3Nob3cgKSB7XHJcblx0alF1ZXJ5KCAnLndwYmNfdWlfZWxfX3ZlcnRfcmlnaHRfYmFyX19zZWN0aW9uJyApLmFkZENsYXNzKCAnd3BiY191aV9faGlkZScgKVxyXG5cdGpRdWVyeSggJy53cGJjX3VpX2VsX192ZXJ0X3JpZ2h0X2Jhcl9fc2VjdGlvbl8nICsgbWVudV90b19zaG93ICkucmVtb3ZlQ2xhc3MoICd3cGJjX3VpX19oaWRlJyApO1xyXG59XHJcblxyXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuLy8gPT0gRW5kIFJpZ2h0IFNpZGUgQmFyICBzZWN0aW9uICAgPT1cclxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XHJcblxyXG4vKipcclxuICogR2V0IGFuY2hvcihzKSBhcnJheSAgZnJvbSAgVVJMLlxyXG4gKiBEb2M6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Mb2NhdGlvblxyXG4gKlxyXG4gKiBAcmV0dXJucyB7KltdfVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY191cmxfZ2V0X2FuY2hvcnNfYXJyKCkge1xyXG5cdHZhciBoYXNoZXMgICAgICAgICAgICA9IHdpbmRvdy5sb2NhdGlvbi5oYXNoLnJlcGxhY2UoICclMjMnLCAnIycgKTtcclxuXHR2YXIgaGFzaGVzX2FyciAgICAgICAgPSBoYXNoZXMuc3BsaXQoICcjJyApO1xyXG5cdHZhciByZXN1bHQgICAgICAgICAgICA9IFtdO1xyXG5cdHZhciBoYXNoZXNfYXJyX2xlbmd0aCA9IGhhc2hlc19hcnIubGVuZ3RoO1xyXG5cclxuXHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBoYXNoZXNfYXJyX2xlbmd0aDsgaSsrICkge1xyXG5cdFx0aWYgKCBoYXNoZXNfYXJyW2ldLmxlbmd0aCA+IDAgKSB7XHJcblx0XHRcdHJlc3VsdC5wdXNoKCBoYXNoZXNfYXJyW2ldICk7XHJcblx0XHR9XHJcblx0fVxyXG5cdHJldHVybiByZXN1bHQ7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBBdXRvIEV4cGFuZCBTZXR0aW5ncyBzZWN0aW9uIGJhc2VkIG9uIFVSTCBhbmNob3IsIGFmdGVyICBwYWdlIGxvYWRlZC5cclxuICovXHJcbmpRdWVyeSggZG9jdW1lbnQgKS5yZWFkeSggZnVuY3Rpb24gKCkgeyB3cGJjX2FkbWluX3VpX19yZWRpcmVjdF9sZWdhY3lfZ2VuZXJhbF9hdmFpbGFiaWxpdHlfdXJsKCk7IH0gKTtcclxualF1ZXJ5KCBkb2N1bWVudCApLnJlYWR5KCBmdW5jdGlvbiAoKSB7IHdwYmNfYWRtaW5fdWlfX2RvX2V4cGFuZF9zZWN0aW9uKCk7IHNldFRpbWVvdXQoICd3cGJjX2FkbWluX3VpX19kb19leHBhbmRfc2VjdGlvbicsIDEwICk7IH0gKTtcclxualF1ZXJ5KCBkb2N1bWVudCApLnJlYWR5KCBmdW5jdGlvbiAoKSB7IHdwYmNfYWRtaW5fdWlfX2RvX2V4cGFuZF9zZWN0aW9uKCk7IHNldFRpbWVvdXQoICd3cGJjX2FkbWluX3VpX19kb19leHBhbmRfc2VjdGlvbicsIDE1MCApOyB9ICk7XHJcblxyXG4vKipcclxuICogUmVkaXJlY3Qgb2xkIFNldHRpbmdzID4gQXZhaWxhYmlsaXR5IGFuY2hvcnMgdG8gdGhlIGRlZGljYXRlZCBHZW5lcmFsIEF2YWlsYWJpbGl0eSBwYWdlLlxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19hZG1pbl91aV9fcmVkaXJlY3RfbGVnYWN5X2dlbmVyYWxfYXZhaWxhYmlsaXR5X3VybCgpIHtcclxuXHJcblx0aWYgKFxyXG5cdFx0ICAgKCB3aW5kb3cubG9jYXRpb24uaHJlZi5pbmRleE9mKCAncGFnZT13cGJjLXNldHRpbmdzJyApID4gLTEgKVxyXG5cdFx0JiYgKFxyXG5cdFx0XHQgICAoIHdpbmRvdy5sb2NhdGlvbi5oYXNoLmluZGV4T2YoICd3cGJjX2dlbmVyYWxfc2V0dGluZ3NfYXZhaWxhYmlsaXR5X21ldGFib3gnICkgPiAtMSApXHJcblx0XHRcdHx8ICggd2luZG93LmxvY2F0aW9uLmhhc2guaW5kZXhPZiggJ3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19hdmFpbGFiaWxpdHlfdGFiJyApID4gLTEgKVxyXG5cdFx0KVxyXG5cdCkge1xyXG5cdFx0d2luZG93LmxvY2F0aW9uLnJlcGxhY2UoIHdpbmRvdy5sb2NhdGlvbi5ocmVmLnNwbGl0KCAnPycgKVswXSArICc/cGFnZT13cGJjLWF2YWlsYWJpbGl0eSZ0YWI9Z2VuZXJhbF9hdmFpbGFiaWxpdHknICk7XHJcblx0fVxyXG59XHJcblxyXG4vKipcclxuICogRXhwYW5kIHNlY3Rpb24gaW4gIEdlbmVyYWwgU2V0dGluZ3MgcGFnZSBhbmQgc2VsZWN0IE1lbnUgaXRlbS5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX2RvX2V4cGFuZF9zZWN0aW9uKCkge1xyXG5cclxuXHQvLyB3aW5kb3cubG9jYXRpb24uaGFzaCAgPSAjc2VjdGlvbl9pZCAgLyAgZG9jOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvTG9jYXRpb24gLlxyXG5cdHZhciBhbmNob3JzX2FyciAgICAgICAgPSB3cGJjX3VybF9nZXRfYW5jaG9yc19hcnIoKTtcclxuXHR2YXIgYW5jaG9yc19hcnJfbGVuZ3RoID0gYW5jaG9yc19hcnIubGVuZ3RoO1xyXG5cclxuXHRpZiAoIGFuY2hvcnNfYXJyX2xlbmd0aCA+IDAgKSB7XHJcblx0XHR2YXIgb25lX2FuY2hvcl9wcm9wX3ZhbHVlID0gYW5jaG9yc19hcnJbMF0uc3BsaXQoICdkb19leHBhbmRfXycgKTtcclxuXHRcdGlmICggb25lX2FuY2hvcl9wcm9wX3ZhbHVlLmxlbmd0aCA+IDEgKSB7XHJcblxyXG5cdFx0XHQvLyAnd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhbGVuZGFyX21ldGFib3gnXHJcblx0XHRcdHZhciBzZWN0aW9uX3RvX3Nob3cgICAgPSBvbmVfYW5jaG9yX3Byb3BfdmFsdWVbMV07XHJcblx0XHRcdHZhciBzZWN0aW9uX2lkX3RvX3Nob3cgPSAnIycgKyBzZWN0aW9uX3RvX3Nob3c7XHJcblxyXG5cclxuXHRcdFx0Ly8gLS0gUmVtb3ZlIHNlbGVjdGVkIGJhY2tncm91bmQgaW4gYWxsIGxlZnQgIG1lbnUgIGl0ZW1zIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0XHRqUXVlcnkoICcud3BiY191aV9lbF9fdmVydF9uYXZfaXRlbSAnICkucmVtb3ZlQ2xhc3MoICdhY3RpdmUnICk7XHJcblx0XHRcdC8vIFNldCBsZWZ0IG1lbnUgc2VsZWN0ZWQuXHJcblx0XHRcdGpRdWVyeSggJy5kb19leHBhbmRfXycgKyBzZWN0aW9uX3RvX3Nob3cgKyAnX2xpbmsnICkuYWRkQ2xhc3MoICdhY3RpdmUnICk7XHJcblx0XHRcdHZhciBzZWxlY3RlZF90aXRsZSA9IGpRdWVyeSggJy5kb19leHBhbmRfXycgKyBzZWN0aW9uX3RvX3Nob3cgKyAnX2xpbmsgYSAud3BiY191aV9lbF9fdmVydF9uYXZfdGl0bGUgJyApLnRleHQoKTtcclxuXHJcblx0XHRcdC8vIEV4cGFuZCBzZWN0aW9uLCBpZiBpdCBjb2xhcHNlZC5cclxuXHRcdFx0aWYgKCAhIGpRdWVyeSggJy5kb19leHBhbmRfXycgKyBzZWN0aW9uX3RvX3Nob3cgKyAnX2xpbmsnICkucGFyZW50cyggJy53cGJjX3VpX2VsX19sZXZlbF9fZm9sZGVyJyApLmhhc0NsYXNzKCAnZXhwYW5kZWQnICkgKSB7XHJcblx0XHRcdFx0alF1ZXJ5KCAnLndwYmNfdWlfZWxfX2xldmVsX19mb2xkZXInICkucmVtb3ZlQ2xhc3MoICdleHBhbmRlZCcgKTtcclxuXHRcdFx0XHRqUXVlcnkoICcuZG9fZXhwYW5kX18nICsgc2VjdGlvbl90b19zaG93ICsgJ19saW5rJyApLnBhcmVudHMoICcud3BiY191aV9lbF9fbGV2ZWxfX2ZvbGRlcicgKS5hZGRDbGFzcyggJ2V4cGFuZGVkJyApO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHQvLyAtLSBFeHBhbmQgc2VjdGlvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdFx0dmFyIGNvbnRhaW5lcl90b19oaWRlX2NsYXNzID0gJy5wb3N0Ym94JztcclxuXHRcdFx0Ly8gSGlkZSBzZWN0aW9ucyAnLnBvc3Rib3gnIGluIGFkbWluIHBhZ2UgYW5kIHNob3cgc3BlY2lmaWMgb25lLlxyXG5cdFx0XHRqUXVlcnkoICcud3BiY19hZG1pbl9wYWdlICcgKyBjb250YWluZXJfdG9faGlkZV9jbGFzcyApLmhpZGUoKTtcclxuXHRcdFx0alF1ZXJ5KCAnLndwYmNfY29udGFpbmVyX2Fsd2F5c19oaWRlX19vbl9sZWZ0X25hdl9jbGljaycgKS5oaWRlKCk7XHJcblx0XHRcdGpRdWVyeSggc2VjdGlvbl9pZF90b19zaG93ICkuc2hvdygpO1xyXG5cclxuXHRcdFx0Ly8gU2hvdyBhbGwgb3RoZXIgc2VjdGlvbnMsICBpZiBwcm92aWRlZCBpbiBVUkw6IC4uP3BhZ2U9d3BiYy1zZXR0aW5ncyNkb19leHBhbmRfX3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYXBhY2l0eV9tZXRhYm94I3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYXBhY2l0eV91cGdyYWRlX21ldGFib3ggLlxyXG5cdFx0XHRmb3IgKCBsZXQgaSA9IDE7IGkgPCBhbmNob3JzX2Fycl9sZW5ndGg7IGkrKyApIHtcclxuXHRcdFx0XHRqUXVlcnkoICcjJyArIGFuY2hvcnNfYXJyW2ldICkuc2hvdygpO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAoIGZhbHNlICkge1xyXG5cdFx0XHRcdHZhciB0YXJnZXRPZmZzZXQgPSB3cGJjX3Njcm9sbF90byggc2VjdGlvbl9pZF90b19zaG93ICk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIC0tIFNldCBWYWx1ZSB0byBJbnB1dCBhYm91dCBzZWxlY3RlZCBOYXYgZWxlbWVudCAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICAgICAgIC8vIEZpeEluOiA5LjguNi4xLlxyXG5cdFx0XHR2YXIgc2VjdGlvbl9pZF90YWIgPSBzZWN0aW9uX2lkX3RvX3Nob3cuc3Vic3RyaW5nKCAwLCBzZWN0aW9uX2lkX3RvX3Nob3cubGVuZ3RoIC0gOCApICsgJ190YWInO1xyXG5cdFx0XHRpZiAoIGNvbnRhaW5lcl90b19oaWRlX2NsYXNzID09IHNlY3Rpb25faWRfdG9fc2hvdyApIHtcclxuXHRcdFx0XHRzZWN0aW9uX2lkX3RhYiA9ICcjd3BiY19nZW5lcmFsX3NldHRpbmdzX2FsbF90YWInXHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKCAnI3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYXBhY2l0eV9tZXRhYm94LCN3cGJjX2dlbmVyYWxfc2V0dGluZ3NfY2FwYWNpdHlfdXBncmFkZV9tZXRhYm94JyA9PSBzZWN0aW9uX2lkX3RvX3Nob3cgKSB7XHJcblx0XHRcdFx0c2VjdGlvbl9pZF90YWIgPSAnI3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYXBhY2l0eV90YWInXHJcblx0XHRcdH1cclxuXHRcdFx0alF1ZXJ5KCAnI2Zvcm1fdmlzaWJsZV9zZWN0aW9uJyApLnZhbCggc2VjdGlvbl9pZF90YWIgKTtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBMaWtlIGJsaW5raW5nIHNvbWUgZWxlbWVudHMuXHJcblx0XHR3cGJjX2FkbWluX3VpX19kb19fYW5jaG9yX19hbm90aGVyX2FjdGlvbnMoKTtcclxuXHR9XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX2lzX2luX21vYmlsZV9zY3JlZW5fc2l6ZSgpIHtcclxuXHRyZXR1cm4gd3BiY19hZG1pbl91aV9faXNfaW5fdGhpc19zY3JlZW5fc2l6ZSggNjA1ICk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX2lzX2luX3RoaXNfc2NyZWVuX3NpemUoc2l6ZSkge1xyXG5cdHJldHVybiAod2luZG93LnNjcmVlbi53aWR0aCA8PSBzaXplKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE9wZW4gc2V0dGluZ3MgcGFnZSAgfCAgRXhwYW5kIHNlY3Rpb24gIHwgIFNlbGVjdCBNZW51IGl0ZW0uXHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2FkbWluX3VpX19kb19fb3Blbl91cmxfX2V4cGFuZF9zZWN0aW9uKHVybCwgc2VjdGlvbl9pZCkge1xyXG5cclxuXHQvLyB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybCArICcmZG9fZXhwYW5kPScgKyBzZWN0aW9uX2lkICsgJyNkb19leHBhbmRfXycgKyBzZWN0aW9uX2lkOyAvLy5cclxuXHR3aW5kb3cubG9jYXRpb24uaHJlZiA9IHVybCArICcjZG9fZXhwYW5kX18nICsgc2VjdGlvbl9pZDtcclxuXHJcblx0aWYgKCB3cGJjX2FkbWluX3VpX19pc19pbl9tb2JpbGVfc2NyZWVuX3NpemUoKSApIHtcclxuXHRcdHdwYmNfYWRtaW5fdWlfX3NpZGViYXJfbGVmdF9fZG9fbWluKCk7XHJcblx0fVxyXG5cclxuXHR3cGJjX2FkbWluX3VpX19kb19leHBhbmRfc2VjdGlvbigpO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIENoZWNrICBmb3IgT3RoZXIgYWN0aW9uczogIExpa2UgYmxpbmtpbmcgc29tZSBlbGVtZW50cyBpbiBzZXR0aW5ncyBwYWdlLiBFLmcuIERheXMgc2VsZWN0aW9uICBvciAgY2hhbmdlLW92ZXIgZGF5cy5cclxuICovXHJcbmZ1bmN0aW9uIHdwYmNfYWRtaW5fdWlfX2RvX19hbmNob3JfX2Fub3RoZXJfYWN0aW9ucygpIHtcclxuXHJcblx0dmFyIGFuY2hvcnNfYXJyICAgICAgICA9IHdwYmNfdXJsX2dldF9hbmNob3JzX2FycigpO1xyXG5cdHZhciBhbmNob3JzX2Fycl9sZW5ndGggPSBhbmNob3JzX2Fyci5sZW5ndGg7XHJcblxyXG5cdC8vIE90aGVyIGFjdGlvbnM6ICBMaWtlIGJsaW5raW5nIHNvbWUgZWxlbWVudHMuXHJcblx0Zm9yICggdmFyIGkgPSAwOyBpIDwgYW5jaG9yc19hcnJfbGVuZ3RoOyBpKysgKSB7XHJcblxyXG5cdFx0dmFyIHRoaXNfYW5jaG9yID0gYW5jaG9yc19hcnJbaV07XHJcblxyXG5cdFx0dmFyIHRoaXNfYW5jaG9yX3Byb3BfdmFsdWUgPSB0aGlzX2FuY2hvci5zcGxpdCggJ2RvX290aGVyX2FjdGlvbnNfXycgKTtcclxuXHJcblx0XHRpZiAoIHRoaXNfYW5jaG9yX3Byb3BfdmFsdWUubGVuZ3RoID4gMSApIHtcclxuXHJcblx0XHRcdHZhciBzZWN0aW9uX2FjdGlvbiA9IHRoaXNfYW5jaG9yX3Byb3BfdmFsdWVbMV07XHJcblxyXG5cdFx0XHRzd2l0Y2ggKCBzZWN0aW9uX2FjdGlvbiApIHtcclxuXHJcblx0XHRcdFx0Y2FzZSAnYmxpbmtfZGF5X3NlbGVjdGlvbnMnOlxyXG5cdFx0XHRcdFx0Ly8gd3BiY191aV9zZXR0aW5nc19fcGFuZWxfX2NsaWNrKCAnI3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYWxlbmRhcl90YWIgYScsICcjd3BiY19nZW5lcmFsX3NldHRpbmdzX2NhbGVuZGFyX21ldGFib3gnLCAnRGF5cyBTZWxlY3Rpb24nICk7LlxyXG5cdFx0XHRcdFx0d3BiY19ibGlua19lbGVtZW50KCAnLndwYmNfdHJfc2V0X2dlbl9ib29raW5nX3R5cGVfb2ZfZGF5X3NlbGVjdGlvbnMnLCA0LCAzNTAgKTtcclxuXHRcdFx0XHRcdFx0d3BiY19zY3JvbGxfdG8oICcud3BiY190cl9zZXRfZ2VuX2Jvb2tpbmdfdHlwZV9vZl9kYXlfc2VsZWN0aW9ucycgKTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0XHRjYXNlICdibGlua19jaGFuZ2Vfb3Zlcl9kYXlzJzpcclxuXHRcdFx0XHRcdC8vIHdwYmNfdWlfc2V0dGluZ3NfX3BhbmVsX19jbGljayggJyN3cGJjX2dlbmVyYWxfc2V0dGluZ3NfY2FsZW5kYXJfdGFiIGEnLCAnI3dwYmNfZ2VuZXJhbF9zZXR0aW5nc19jYWxlbmRhcl9tZXRhYm94JywgJ0NoYW5nZW92ZXIgRGF5cycgKTsuXHJcblx0XHRcdFx0XHR3cGJjX2JsaW5rX2VsZW1lbnQoICcud3BiY190cl9zZXRfZ2VuX2Jvb2tpbmdfcmFuZ2Vfc2VsZWN0aW9uX3RpbWVfaXNfYWN0aXZlJywgNCwgMzUwICk7XHJcblx0XHRcdFx0XHRcdHdwYmNfc2Nyb2xsX3RvKCAnLndwYmNfdHJfc2V0X2dlbl9ib29raW5nX3JhbmdlX3NlbGVjdGlvbl90aW1lX2lzX2FjdGl2ZScgKTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0XHRjYXNlICdibGlua19jYXB0Y2hhJzpcclxuXHRcdFx0XHRcdHdwYmNfYmxpbmtfZWxlbWVudCggJy53cGJjX3RyX3NldF9nZW5fYm9va2luZ19pc191c2VfY2FwdGNoYScsIDQsIDM1MCApO1xyXG5cdFx0XHRcdFx0XHR3cGJjX3Njcm9sbF90byggJy53cGJjX3RyX3NldF9nZW5fYm9va2luZ19pc191c2VfY2FwdGNoYScgKTtcclxuXHRcdFx0XHRcdGJyZWFrO1xyXG5cclxuXHRcdFx0XHRkZWZhdWx0OlxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG59XHJcbiIsIi8qKlxyXG4gKiBDb3B5IHR4dCB0byBjbGlwYnJkIGZyb20gVGV4dCBmaWVsZHMuXHJcbiAqXHJcbiAqIEBwYXJhbSBodG1sX2VsZW1lbnRfaWQgIC0gZS5nLiAnZGF0YV9maWVsZCdcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2NvcHlfdGV4dF90b19jbGlwYnJkX2Zyb21fZWxlbWVudCggaHRtbF9lbGVtZW50X2lkICkge1xyXG5cdC8vIEdldCB0aGUgdGV4dCBmaWVsZC5cclxuXHR2YXIgY29weVRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggaHRtbF9lbGVtZW50X2lkICk7XHJcblxyXG5cdC8vIFNlbGVjdCB0aGUgdGV4dCBmaWVsZC5cclxuXHRjb3B5VGV4dC5zZWxlY3QoKTtcclxuXHRjb3B5VGV4dC5zZXRTZWxlY3Rpb25SYW5nZSggMCwgOTk5OTkgKTsgLy8gRm9yIG1vYmlsZSBkZXZpY2VzLlxyXG5cclxuXHQvLyBDb3B5IHRoZSB0ZXh0IGluc2lkZSB0aGUgdGV4dCBmaWVsZC5cclxuXHR2YXIgaXNfY29waWVkID0gd3BiY19jb3B5X3RleHRfdG9fY2xpcGJyZCggY29weVRleHQudmFsdWUgKTtcclxuXHRpZiAoICEgaXNfY29waWVkICkge1xyXG5cdFx0Y29uc29sZS5lcnJvciggJ09vcHMsIHVuYWJsZSB0byBjb3B5JywgY29weVRleHQudmFsdWUgKTtcclxuXHR9XHJcblx0cmV0dXJuIGlzX2NvcGllZDtcclxufVxyXG5cclxuLyoqXHJcbiAqIENvcHkgdHh0IHRvIGNsaXBicmQuXHJcbiAqXHJcbiAqIEBwYXJhbSB0ZXh0XHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuZnVuY3Rpb24gd3BiY19jb3B5X3RleHRfdG9fY2xpcGJyZCh0ZXh0KSB7XHJcblxyXG5cdGlmICggISBuYXZpZ2F0b3IuY2xpcGJvYXJkICkge1xyXG5cdFx0cmV0dXJuIHdwYmNfZmFsbGJhY2tfY29weV90ZXh0X3RvX2NsaXBicmQoIHRleHQgKTtcclxuXHR9XHJcblxyXG5cdG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KCB0ZXh0ICkudGhlbihcclxuXHRcdGZ1bmN0aW9uICgpIHtcclxuXHRcdFx0Ly8gY29uc29sZS5sb2coICdBc3luYzogQ29weWluZyB0byBjbGlwYm9hcmQgd2FzIHN1Y2Nlc3NmdWwhJyApOy5cclxuXHRcdFx0cmV0dXJuICB0cnVlO1xyXG5cdFx0fSxcclxuXHRcdGZ1bmN0aW9uIChlcnIpIHtcclxuXHRcdFx0Ly8gY29uc29sZS5lcnJvciggJ0FzeW5jOiBDb3VsZCBub3QgY29weSB0ZXh0OiAnLCBlcnIgKTsuXHJcblx0XHRcdHJldHVybiAgZmFsc2U7XHJcblx0XHR9XHJcblx0KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIENvcHkgdHh0IHRvIGNsaXBicmQgLSBkZXByaWNhdGVkIG1ldGhvZC5cclxuICpcclxuICogQHBhcmFtIHRleHRcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5mdW5jdGlvbiB3cGJjX2ZhbGxiYWNrX2NvcHlfdGV4dF90b19jbGlwYnJkKCB0ZXh0ICkge1xyXG5cclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIHZhciB0ZXh0QXJlYSAgID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJ0ZXh0YXJlYVwiICk7XHJcblx0Ly8gdGV4dEFyZWEudmFsdWUgPSB0ZXh0O1xyXG5cdC8vXHJcblx0Ly8gLy8gQXZvaWQgc2Nyb2xsaW5nIHRvIGJvdHRvbS5cclxuXHQvLyB0ZXh0QXJlYS5zdHlsZS50b3AgICAgICA9IFwiMFwiO1xyXG5cdC8vIHRleHRBcmVhLnN0eWxlLmxlZnQgICAgID0gXCIwXCI7XHJcblx0Ly8gdGV4dEFyZWEuc3R5bGUucG9zaXRpb24gPSBcImZpeGVkXCI7XHJcblx0Ly8gdGV4dEFyZWEuc3R5bGUuekluZGV4ICAgPSBcIjk5OTk5OTk5OVwiO1xyXG5cdC8vIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoIHRleHRBcmVhICk7XHJcblx0Ly8gdGV4dEFyZWEuZm9jdXMoKTtcclxuXHQvLyB0ZXh0QXJlYS5zZWxlY3QoKTtcclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBOb3cgZ2V0IGl0IGFzIEhUTUwgIChvcmlnaW5hbCBoZXJlIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM0MTkxNzgwL2phdmFzY3JpcHQtY29weS1zdHJpbmctdG8tY2xpcGJvYXJkLWFzLXRleHQtaHRtbCApLlxyXG5cclxuXHQvLyBbMV0gLSBDcmVhdGUgY29udGFpbmVyIGZvciB0aGUgSFRNTC5cclxuXHR2YXIgY29udGFpbmVyICAgICAgID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggJ2RpdicgKTtcclxuXHRjb250YWluZXIuaW5uZXJIVE1MID0gdGV4dDtcclxuXHJcblx0Ly8gWzJdIC0gSGlkZSBlbGVtZW50LlxyXG5cdGNvbnRhaW5lci5zdHlsZS5wb3NpdGlvbiAgICAgID0gJ2ZpeGVkJztcclxuXHRjb250YWluZXIuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcclxuXHRjb250YWluZXIuc3R5bGUub3BhY2l0eSAgICAgICA9IDA7XHJcblxyXG5cdC8vIERldGVjdCBhbGwgc3R5bGUgc2hlZXRzIG9mIHRoZSBwYWdlLlxyXG5cdHZhciBhY3RpdmVTaGVldHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCggZG9jdW1lbnQuc3R5bGVTaGVldHMgKS5maWx0ZXIoXHJcblx0XHRmdW5jdGlvbiAoc2hlZXQpIHtcclxuXHRcdFx0cmV0dXJuICEgc2hlZXQuZGlzYWJsZWQ7XHJcblx0XHR9XHJcblx0KTtcclxuXHJcblx0Ly8gWzNdIC0gTW91bnQgdGhlIGNvbnRhaW5lciB0byB0aGUgRE9NIHRvIG1ha2UgYGNvbnRlbnRXaW5kb3dgIGF2YWlsYWJsZS5cclxuXHRkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKCBjb250YWluZXIgKTtcclxuXHJcblx0Ly8gWzRdIC0gQ29weSB0byBjbGlwYm9hcmQuXHJcblx0d2luZG93LmdldFNlbGVjdGlvbigpLnJlbW92ZUFsbFJhbmdlcygpO1xyXG5cclxuXHR2YXIgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xyXG5cdHJhbmdlLnNlbGVjdE5vZGUoIGNvbnRhaW5lciApO1xyXG5cdHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5hZGRSYW5nZSggcmFuZ2UgKTtcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cclxuXHR2YXIgcmVzdWx0ID0gZmFsc2U7XHJcblxyXG5cdHRyeSB7XHJcblx0XHRyZXN1bHQgPSBkb2N1bWVudC5leGVjQ29tbWFuZCggJ2NvcHknICk7XHJcblx0XHQvLyBjb25zb2xlLmxvZyggJ0ZhbGxiYWNrOiBDb3B5aW5nIHRleHQgY29tbWFuZCB3YXMgJyArIG1zZyApOyAvLy5cclxuXHR9IGNhdGNoICggZXJyICkge1xyXG5cdFx0Ly8gY29uc29sZS5lcnJvciggJ0ZhbGxiYWNrOiBPb3BzLCB1bmFibGUgdG8gY29weScsIGVyciApOyAvLy5cclxuXHR9XHJcblx0Ly8gZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZCggdGV4dEFyZWEgKTsgLy8uXHJcblxyXG5cdC8vIFs1LjRdIC0gRW5hYmxlIENTUy5cclxuXHR2YXIgYWN0aXZlU2hlZXRzX2xlbmd0aCA9IGFjdGl2ZVNoZWV0cy5sZW5ndGg7XHJcblx0Zm9yICggdmFyIGkgPSAwOyBpIDwgYWN0aXZlU2hlZXRzX2xlbmd0aDsgaSsrICkge1xyXG5cdFx0YWN0aXZlU2hlZXRzW2ldLmRpc2FibGVkID0gZmFsc2U7XHJcblx0fVxyXG5cclxuXHQvLyBbNl0gLSBSZW1vdmUgdGhlIGNvbnRhaW5lclxyXG5cdGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoIGNvbnRhaW5lciApO1xyXG5cclxuXHRyZXR1cm4gIHJlc3VsdDtcclxufSIsIi8qKlxyXG4gKiBXUEJDIENvbGxhcHNpYmxlIEdyb3Vwc1xyXG4gKlxyXG4gKiBVbml2ZXJzYWwsIGRlcGVuZGVuY3ktZnJlZSBjb250cm9sbGVyIGZvciBleHBhbmRpbmcvY29sbGFwc2luZyBncm91cGVkIHNlY3Rpb25zIGluIHJpZ2h0LXNpZGUgcGFuZWxzIChJbnNwZWN0b3IvTGlicmFyeS9Gb3JtIFNldHRpbmdzLCBvciBhbnkgb3RoZXIgV1BCQyBwYWdlKS5cclxuICpcclxuICogXHRcdD09PSBIb3cgdG8gdXNlIGl0IChxdWljaykgPyA9PT1cclxuICpcclxuICpcdFx0LS0gMS4gTWFya3VwIChpbmRlcGVuZGVudCBtb2RlOiBtdWx0aXBsZSBvcGVuIGFsbG93ZWQpIC0tXHJcbiAqXHRcdFx0PGRpdiBjbGFzcz1cIndwYmNfY29sbGFwc2libGVcIj5cclxuICpcdFx0XHQgIDxzZWN0aW9uIGNsYXNzPVwid3BiY191aV9fY29sbGFwc2libGVfZ3JvdXAgaXMtb3BlblwiPlxyXG4gKlx0XHRcdFx0PGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJncm91cF9faGVhZGVyXCI+PGgzPkdlbmVyYWw8L2gzPjwvYnV0dG9uPlxyXG4gKlx0XHRcdFx0PGRpdiBjbGFzcz1cImdyb3VwX19maWVsZHNcIj7igKY8L2Rpdj5cclxuICpcdFx0XHQgIDwvc2VjdGlvbj5cclxuICpcdFx0XHQgIDxzZWN0aW9uIGNsYXNzPVwid3BiY191aV9fY29sbGFwc2libGVfZ3JvdXBcIj5cclxuICpcdFx0XHRcdDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiZ3JvdXBfX2hlYWRlclwiPjxoMz5BZHZhbmNlZDwvaDM+PC9idXR0b24+XHJcbiAqXHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZ3JvdXBfX2ZpZWxkc1wiPuKApjwvZGl2PlxyXG4gKlx0XHRcdCAgPC9zZWN0aW9uPlxyXG4gKlx0XHRcdDwvZGl2PlxyXG4gKlxyXG4gKlx0XHQtLSAyLiBFeGNsdXNpdmUvYWNjb3JkaW9uIG1vZGUgKG9uZSBvcGVuIGF0IGEgdGltZSkgLS1cclxuICpcdFx0XHQ8ZGl2IGNsYXNzPVwid3BiY19jb2xsYXBzaWJsZSB3cGJjX2NvbGxhcHNpYmxlLS1leGNsdXNpdmVcIj7igKY8L2Rpdj5cclxuICpcclxuICpcdFx0LS0gMy4gQXV0by1pbml0IC0tXHJcbiAqXHRcdFx0VGhlIHNjcmlwdCBhdXRvLWluaXRpYWxpemVzIG9uIERPTUNvbnRlbnRMb2FkZWQuIE5vIGV4dHJhIGNvZGUgbmVlZGVkLlxyXG4gKlxyXG4gKlx0XHQtLSA0LiBQcm9ncmFtbWF0aWMgY29udHJvbCAob3B0aW9uYWwpXHJcbiAqXHRcdFx0Y29uc3Qgcm9vdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN3cGJjX2JmYl9faW5zcGVjdG9yJyk7XHJcbiAqXHRcdFx0Y29uc3QgYXBpICA9IHJvb3QuX193cGJjX2NvbGxhcHNpYmxlX2luc3RhbmNlOyAvLyBzZXQgYnkgYXV0by1pbml0XHJcbiAqXHJcbiAqXHRcdFx0YXBpLm9wZW5fYnlfaGVhZGluZygnVmFsaWRhdGlvbicpOyAvLyBvcGVuIGJ5IGhlYWRpbmcgdGV4dFxyXG4gKlx0XHRcdGFwaS5vcGVuX2J5X2luZGV4KDApOyAgICAgICAgICAgICAgLy8gb3BlbiB0aGUgZmlyc3QgZ3JvdXBcclxuICpcclxuICpcdFx0LS0gNS5MaXN0ZW4gdG8gZXZlbnRzIChlLmcuLCB0byBwZXJzaXN0IOKAnG9wZW4gZ3JvdXDigJ0gc3RhdGUpIC0tXHJcbiAqXHRcdFx0cm9vdC5hZGRFdmVudExpc3RlbmVyKCd3cGJjOmNvbGxhcHNpYmxlOm9wZW4nLCAgKGUpID0+IHsgY29uc29sZS5sb2coICBlLmRldGFpbC5ncm91cCApOyB9KTtcclxuICpcdFx0XHRyb290LmFkZEV2ZW50TGlzdGVuZXIoJ3dwYmM6Y29sbGFwc2libGU6Y2xvc2UnLCAoZSkgPT4geyBjb25zb2xlLmxvZyggIGUuZGV0YWlsLmdyb3VwICk7IH0pO1xyXG4gKlxyXG4gKlxyXG4gKlxyXG4gKiBNYXJrdXAgZXhwZWN0YXRpb25zIChtaW5pbWFsKTpcclxuICogIDxkaXYgY2xhc3M9XCJ3cGJjX2NvbGxhcHNpYmxlIFt3cGJjX2NvbGxhcHNpYmxlLS1leGNsdXNpdmVdXCI+XHJcbiAqICAgIDxzZWN0aW9uIGNsYXNzPVwid3BiY191aV9fY29sbGFwc2libGVfZ3JvdXAgW2lzLW9wZW5dXCI+XHJcbiAqICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJncm91cF9faGVhZGVyXCI+IC4uLiA8L2J1dHRvbj5cclxuICogICAgICA8ZGl2IGNsYXNzPVwiZ3JvdXBfX2ZpZWxkc1wiPiAuLi4gPC9kaXY+XHJcbiAqICAgIDwvc2VjdGlvbj5cclxuICogICAgLi4uIG1vcmUgPHNlY3Rpb24+IC4uLlxyXG4gKiAgPC9kaXY+XHJcbiAqXHJcbiAqIE5vdGVzOlxyXG4gKiAgLSBBZGQgYGlzLW9wZW5gIHRvIGFueSBzZWN0aW9uIHlvdSB3YW50IGluaXRpYWxseSBleHBhbmRlZC5cclxuICogIC0gQWRkIGB3cGJjX2NvbGxhcHNpYmxlLS1leGNsdXNpdmVgIHRvIHRoZSBjb250YWluZXIgZm9yIFwib3BlbiBvbmUgYXQgYSB0aW1lXCIgYmVoYXZpb3IuXHJcbiAqICAtIFdvcmtzIHdpdGggeW91ciBleGlzdGluZyBCRkIgbWFya3VwIChjbGFzc2VzIHVzZWQgdGhlcmUgYXJlIHRoZSBkZWZhdWx0cykuXHJcbiAqXHJcbiAqIEFjY2Vzc2liaWxpdHk6XHJcbiAqICAtIFNldHMgYXJpYS1leHBhbmRlZCBvbiAuZ3JvdXBfX2hlYWRlclxyXG4gKiAgLSBTZXRzIGFyaWEtaGlkZGVuICsgW2hpZGRlbl0gb24gLmdyb3VwX19maWVsZHNcclxuICogIC0gQXJyb3dVcC9BcnJvd0Rvd24gbW92ZSBmb2N1cyBiZXR3ZWVuIGhlYWRlcnM7IEVudGVyL1NwYWNlIHRvZ2dsZXNcclxuICpcclxuICogRXZlbnRzIChidWJibGVzIGZyb20gdGhlIDxzZWN0aW9uPik6XHJcbiAqICAtICd3cGJjOmNvbGxhcHNpYmxlOm9wZW4nICAoZGV0YWlsOiB7IGdyb3VwLCByb290LCBpbnN0YW5jZSB9KVxyXG4gKiAgLSAnd3BiYzpjb2xsYXBzaWJsZTpjbG9zZScgKGRldGFpbDogeyBncm91cCwgcm9vdCwgaW5zdGFuY2UgfSlcclxuICpcclxuICogUHVibGljIEFQSSAoaW5zdGFuY2UgbWV0aG9kcyk6XHJcbiAqICAtIGluaXQoKSwgZGVzdHJveSgpLCByZWZyZXNoKClcclxuICogIC0gZXhwYW5kKGdyb3VwLCBbZXhjbHVzaXZlXSksIGNvbGxhcHNlKGdyb3VwKSwgdG9nZ2xlKGdyb3VwKVxyXG4gKiAgLSBvcGVuX2J5X2luZGV4KGluZGV4KSwgb3Blbl9ieV9oZWFkaW5nKHRleHQpXHJcbiAqICAtIGlzX2V4Y2x1c2l2ZSgpLCBpc19vcGVuKGdyb3VwKVxyXG4gKlxyXG4gKiBAdmVyc2lvbiAyMDI1LTA4LTI2XHJcbiAqIEBzaW5jZSAyMDI1LTA4LTI2XHJcbiAqL1xyXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuLy8gPT0gRmlsZSAgL2NvbGxhcHNpYmxlX2dyb3Vwcy5qcyA9PSBUaW1lIHBvaW50OiAyMDI1LTA4LTI2IDE0OjEzXHJcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4oZnVuY3Rpb24gKHcsIGQpIHtcclxuXHQndXNlIHN0cmljdCc7XHJcblxyXG5cdGNsYXNzIFdQQkNfQ29sbGFwc2libGVfR3JvdXBzIHtcclxuXHJcblx0XHQvKipcclxuXHRcdCAqIENyZWF0ZSBhIGNvbGxhcHNpYmxlIGNvbnRyb2xsZXIgZm9yIGEgY29udGFpbmVyLlxyXG5cdFx0ICpcclxuXHRcdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSByb290X2VsXHJcblx0XHQgKiAgICAgICAgVGhlIGNvbnRhaW5lciBlbGVtZW50IChvciBDU1Mgc2VsZWN0b3IpIHRoYXQgd3JhcHMgY29sbGFwc2libGUgZ3JvdXBzLlxyXG5cdFx0ICogICAgICAgIFRoZSBjb250YWluZXIgdXN1YWxseSBoYXMgdGhlIGNsYXNzIGAud3BiY19jb2xsYXBzaWJsZWAuXHJcblx0XHQgKiBAcGFyYW0ge09iamVjdH0gW29wdHM9e31dXHJcblx0XHQgKiBAcGFyYW0ge3N0cmluZ30gIFtvcHRzLmdyb3VwX3NlbGVjdG9yPScud3BiY191aV9fY29sbGFwc2libGVfZ3JvdXAnXVxyXG5cdFx0ICogICAgICAgIFNlbGVjdG9yIGZvciBlYWNoIGNvbGxhcHNpYmxlIGdyb3VwIGluc2lkZSB0aGUgY29udGFpbmVyLlxyXG5cdFx0ICogQHBhcmFtIHtzdHJpbmd9ICBbb3B0cy5oZWFkZXJfc2VsZWN0b3I9Jy5ncm91cF9faGVhZGVyJ11cclxuXHRcdCAqICAgICAgICBTZWxlY3RvciBmb3IgdGhlIGNsaWNrYWJsZSBoZWFkZXIgaW5zaWRlIGEgZ3JvdXAuXHJcblx0XHQgKiBAcGFyYW0ge3N0cmluZ30gIFtvcHRzLmZpZWxkc19zZWxlY3Rvcj0nLmdyb3VwX19maWVsZHMnXVxyXG5cdFx0ICogICAgICAgIFNlbGVjdG9yIGZvciB0aGUgY29udGVudC9wYW5lbCBlbGVtZW50IGluc2lkZSBhIGdyb3VwLlxyXG5cdFx0ICogQHBhcmFtIHtzdHJpbmd9ICBbb3B0cy5vcGVuX2NsYXNzPSdpcy1vcGVuJ11cclxuXHRcdCAqICAgICAgICBDbGFzcyBuYW1lIHRoYXQgaW5kaWNhdGVzIHRoZSBncm91cCBpcyBvcGVuLlxyXG5cdFx0ICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5leGNsdXNpdmU9ZmFsc2VdXHJcblx0XHQgKiAgICAgICAgSWYgdHJ1ZSwgb25seSBvbmUgZ3JvdXAgY2FuIGJlIG9wZW4gYXQgYSB0aW1lIGluIHRoaXMgY29udGFpbmVyLlxyXG5cdFx0ICpcclxuXHRcdCAqIEBjb25zdHJ1Y3RvclxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0Y29uc3RydWN0b3Iocm9vdF9lbCwgb3B0cyA9IHt9KSB7XHJcblx0XHRcdHRoaXMucm9vdCA9ICh0eXBlb2Ygcm9vdF9lbCA9PT0gJ3N0cmluZycpID8gZC5xdWVyeVNlbGVjdG9yKCByb290X2VsICkgOiByb290X2VsO1xyXG5cdFx0XHR0aGlzLm9wdHMgPSBPYmplY3QuYXNzaWduKCB7XHJcblx0XHRcdFx0Z3JvdXBfc2VsZWN0b3IgOiAnLndwYmNfdWlfX2NvbGxhcHNpYmxlX2dyb3VwJyxcclxuXHRcdFx0XHRoZWFkZXJfc2VsZWN0b3I6ICcuZ3JvdXBfX2hlYWRlcicsXHJcblx0XHRcdFx0ZmllbGRzX3NlbGVjdG9yOiAnLmdyb3VwX19maWVsZHMsLmdyb3VwX19jb250ZW50JyxcclxuXHRcdFx0XHRvcGVuX2NsYXNzICAgICA6ICdpcy1vcGVuJyxcclxuXHRcdFx0XHRleGNsdXNpdmUgICAgICA6IGZhbHNlXHJcblx0XHRcdH0sIG9wdHMgKTtcclxuXHJcblx0XHRcdC8vIEJvdW5kIGhhbmRsZXJzIChmb3IgYWRkL3JlbW92ZUV2ZW50TGlzdGVuZXIgc3ltbWV0cnkpLlxyXG5cdFx0XHQvKiogQHByaXZhdGUgKi9cclxuXHRcdFx0dGhpcy5fb25fY2xpY2sgPSB0aGlzLl9vbl9jbGljay5iaW5kKCB0aGlzICk7XHJcblx0XHRcdC8qKiBAcHJpdmF0ZSAqL1xyXG5cdFx0XHR0aGlzLl9vbl9rZXlkb3duID0gdGhpcy5fb25fa2V5ZG93bi5iaW5kKCB0aGlzICk7XHJcblxyXG5cdFx0XHQvKiogQHR5cGUge0hUTUxFbGVtZW50W119IEBwcml2YXRlICovXHJcblx0XHRcdHRoaXMuX2dyb3VwcyA9IFtdO1xyXG5cdFx0XHQvKiogQHR5cGUge011dGF0aW9uT2JzZXJ2ZXJ8bnVsbH0gQHByaXZhdGUgKi9cclxuXHRcdFx0dGhpcy5fb2JzZXJ2ZXIgPSBudWxsO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogSW5pdGlhbGl6ZSB0aGUgY29udHJvbGxlcjogY2FjaGUgZ3JvdXBzLCBhdHRhY2ggbGlzdGVuZXJzLCBzZXQgQVJJQSxcclxuXHRcdCAqIGFuZCBzdGFydCBvYnNlcnZpbmcgRE9NIGNoYW5nZXMgaW5zaWRlIHRoZSBjb250YWluZXIuXHJcblx0XHQgKlxyXG5cdFx0ICogQHJldHVybnMge1dQQkNfQ29sbGFwc2libGVfR3JvdXBzfSBUaGUgaW5zdGFuY2UgKGNoYWluYWJsZSkuXHJcblx0XHQgKiBAbGlzdGVucyBjbGlja1xyXG5cdFx0ICogQGxpc3RlbnMga2V5ZG93blxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0aW5pdCgpIHtcclxuXHRcdFx0aWYgKCAhdGhpcy5yb290ICkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuX2dyb3VwcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKFxyXG5cdFx0XHRcdHRoaXMucm9vdC5xdWVyeVNlbGVjdG9yQWxsKCB0aGlzLm9wdHMuZ3JvdXBfc2VsZWN0b3IgKVxyXG5cdFx0XHQpO1xyXG5cdFx0XHR0aGlzLnJvb3QuYWRkRXZlbnRMaXN0ZW5lciggJ2NsaWNrJywgdGhpcy5fb25fY2xpY2ssIGZhbHNlICk7XHJcblx0XHRcdHRoaXMucm9vdC5hZGRFdmVudExpc3RlbmVyKCAna2V5ZG93bicsIHRoaXMuX29uX2tleWRvd24sIGZhbHNlICk7XHJcblxyXG5cdFx0XHQvLyBPYnNlcnZlIGR5bmFtaWMgaW5zZXJ0cy9yZW1vdmFscyAoSW5zcGVjdG9yIHJlLXJlbmRlcnMpLlxyXG5cdFx0XHR0aGlzLl9vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKCAoKSA9PiB7XHJcblx0XHRcdFx0dGhpcy5yZWZyZXNoKCk7XHJcblx0XHRcdH0gKTtcclxuXHRcdFx0dGhpcy5fb2JzZXJ2ZXIub2JzZXJ2ZSggdGhpcy5yb290LCB7IGNoaWxkTGlzdDogdHJ1ZSwgc3VidHJlZTogdHJ1ZSB9ICk7XHJcblxyXG5cdFx0XHR0aGlzLl9zeW5jX2FsbF9hcmlhKCk7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogVGVhciBkb3duIHRoZSBjb250cm9sbGVyOiBkZXRhY2ggbGlzdGVuZXJzLCBzdG9wIHRoZSBvYnNlcnZlcixcclxuXHRcdCAqIGFuZCBkcm9wIGludGVybmFsIHJlZmVyZW5jZXMuXHJcblx0XHQgKlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAc2luY2UgMjAyNS0wOC0yNlxyXG5cdFx0ICovXHJcblx0XHRkZXN0cm95KCkge1xyXG5cdFx0XHRpZiAoICF0aGlzLnJvb3QgKSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMucm9vdC5yZW1vdmVFdmVudExpc3RlbmVyKCAnY2xpY2snLCB0aGlzLl9vbl9jbGljaywgZmFsc2UgKTtcclxuXHRcdFx0dGhpcy5yb290LnJlbW92ZUV2ZW50TGlzdGVuZXIoICdrZXlkb3duJywgdGhpcy5fb25fa2V5ZG93biwgZmFsc2UgKTtcclxuXHRcdFx0aWYgKCB0aGlzLl9vYnNlcnZlciApIHtcclxuXHRcdFx0XHR0aGlzLl9vYnNlcnZlci5kaXNjb25uZWN0KCk7XHJcblx0XHRcdFx0dGhpcy5fb2JzZXJ2ZXIgPSBudWxsO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuX2dyb3VwcyA9IFtdO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogUmUtc2NhbiB0aGUgRE9NIGZvciBjdXJyZW50IGdyb3VwcyBhbmQgcmUtYXBwbHkgQVJJQSB0byBhbGwgb2YgdGhlbS5cclxuXHRcdCAqIFVzZWZ1bCBhZnRlciBkeW5hbWljIChyZSlyZW5kZXJzLlxyXG5cdFx0ICpcclxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0cmVmcmVzaCgpIHtcclxuXHRcdFx0aWYgKCAhdGhpcy5yb290ICkge1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cdFx0XHR0aGlzLl9ncm91cHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChcclxuXHRcdFx0XHR0aGlzLnJvb3QucXVlcnlTZWxlY3RvckFsbCggdGhpcy5vcHRzLmdyb3VwX3NlbGVjdG9yIClcclxuXHRcdFx0KTtcclxuXHRcdFx0dGhpcy5fc3luY19hbGxfYXJpYSgpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogQ2hlY2sgd2hldGhlciB0aGUgY29udGFpbmVyIGlzIGluIGV4Y2x1c2l2ZSAoYWNjb3JkaW9uKSBtb2RlLlxyXG5cdFx0ICpcclxuXHRcdCAqIE9yZGVyIG9mIHByZWNlZGVuY2U6XHJcblx0XHQgKiAgMSkgRXhwbGljaXQgb3B0aW9uIGBvcHRzLmV4Y2x1c2l2ZWBcclxuXHRcdCAqICAyKSBDb250YWluZXIgaGFzIGNsYXNzIGAud3BiY19jb2xsYXBzaWJsZS0tZXhjbHVzaXZlYFxyXG5cdFx0ICogIDMpIENvbnRhaW5lciBtYXRjaGVzIGBbZGF0YS13cGJjLWFjY29yZGlvbj1cImV4Y2x1c2l2ZVwiXWBcclxuXHRcdCAqXHJcblx0XHQgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBleGNsdXNpdmUgbW9kZSBpcyBhY3RpdmUuXHJcblx0XHQgKiBAc2luY2UgMjAyNS0wOC0yNlxyXG5cdFx0ICovXHJcblx0XHRpc19leGNsdXNpdmUoKSB7XHJcblx0XHRcdHJldHVybiAhIShcclxuXHRcdFx0XHR0aGlzLm9wdHMuZXhjbHVzaXZlIHx8XHJcblx0XHRcdFx0dGhpcy5yb290LmNsYXNzTGlzdC5jb250YWlucyggJ3dwYmNfY29sbGFwc2libGUtLWV4Y2x1c2l2ZScgKSB8fFxyXG5cdFx0XHRcdHRoaXMucm9vdC5tYXRjaGVzKCAnW2RhdGEtd3BiYy1hY2NvcmRpb249XCJleGNsdXNpdmVcIl0nIClcclxuXHRcdFx0KTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIERldGVybWluZSB3aGV0aGVyIGEgc3BlY2lmaWMgZ3JvdXAgaXMgb3Blbi5cclxuXHRcdCAqXHJcblx0XHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBncm91cCBUaGUgZ3JvdXAgZWxlbWVudCB0byB0ZXN0LlxyXG5cdFx0ICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIGdyb3VwIGlzIGN1cnJlbnRseSBvcGVuLlxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0aXNfb3Blbihncm91cCkge1xyXG5cdFx0XHRyZXR1cm4gZ3JvdXAuY2xhc3NMaXN0LmNvbnRhaW5zKCB0aGlzLm9wdHMub3Blbl9jbGFzcyApO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogT3BlbiBhIGdyb3VwLiBIb25vcnMgZXhjbHVzaXZlIG1vZGUgYnkgY29sbGFwc2luZyBhbGwgc2libGluZyBncm91cHNcclxuXHRcdCAqIChxdWVyaWVkIGZyb20gdGhlIGxpdmUgRE9NIGF0IGNhbGwtdGltZSkuXHJcblx0XHQgKlxyXG5cdFx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZ3JvdXAgVGhlIGdyb3VwIGVsZW1lbnQgdG8gb3Blbi5cclxuXHRcdCAqIEBwYXJhbSB7Ym9vbGVhbn0gW2V4Y2x1c2l2ZV1cclxuXHRcdCAqICAgICAgICBJZiBwcm92aWRlZCwgb3ZlcnJpZGVzIGNvbnRhaW5lciBtb2RlIGZvciB0aGlzIGFjdGlvbiBvbmx5LlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAZmlyZXMgQ3VzdG9tRXZlbnQjd3BiYzpjb2xsYXBzaWJsZTpvcGVuXHJcblx0XHQgKiBAc2luY2UgMjAyNS0wOC0yNlxyXG5cdFx0ICovXHJcblx0XHRleHBhbmQoZ3JvdXAsIGV4Y2x1c2l2ZSkge1xyXG5cdFx0XHRpZiAoICFncm91cCApIHtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHRcdFx0Y29uc3QgZG9fZXhjbHVzaXZlID0gKHR5cGVvZiBleGNsdXNpdmUgPT09ICdib29sZWFuJykgPyBleGNsdXNpdmUgOiB0aGlzLmlzX2V4Y2x1c2l2ZSgpO1xyXG5cdFx0XHRpZiAoIGRvX2V4Y2x1c2l2ZSApIHtcclxuXHRcdFx0XHQvLyBBbHdheXMgdXNlIHRoZSBsaXZlIERPTSwgbm90IHRoZSBjYWNoZWQgbGlzdC5cclxuXHRcdFx0XHRBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKFxyXG5cdFx0XHRcdFx0dGhpcy5yb290LnF1ZXJ5U2VsZWN0b3JBbGwoIHRoaXMub3B0cy5ncm91cF9zZWxlY3RvciApLFxyXG5cdFx0XHRcdFx0KGcpID0+IHtcclxuXHRcdFx0XHRcdFx0aWYgKCBnICE9PSBncm91cCApIHtcclxuXHRcdFx0XHRcdFx0XHR0aGlzLl9zZXRfb3BlbiggZywgZmFsc2UgKTtcclxuXHRcdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdCk7XHJcblx0XHRcdH1cclxuXHRcdFx0dGhpcy5fc2V0X29wZW4oIGdyb3VwLCB0cnVlICk7XHJcblx0XHR9XHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBDbG9zZSBhIGdyb3VwLlxyXG5cdFx0ICpcclxuXHRcdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGdyb3VwIFRoZSBncm91cCBlbGVtZW50IHRvIGNsb3NlLlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAZmlyZXMgQ3VzdG9tRXZlbnQjd3BiYzpjb2xsYXBzaWJsZTpjbG9zZVxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0Y29sbGFwc2UoZ3JvdXApIHtcclxuXHRcdFx0aWYgKCAhZ3JvdXAgKSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXMuX3NldF9vcGVuKCBncm91cCwgZmFsc2UgKTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIFRvZ2dsZSBhIGdyb3VwJ3Mgb3Blbi9jbG9zZWQgc3RhdGUuXHJcblx0XHQgKlxyXG5cdFx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZ3JvdXAgVGhlIGdyb3VwIGVsZW1lbnQgdG8gdG9nZ2xlLlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAc2luY2UgMjAyNS0wOC0yNlxyXG5cdFx0ICovXHJcblx0XHR0b2dnbGUoZ3JvdXApIHtcclxuXHRcdFx0aWYgKCAhZ3JvdXAgKSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblx0XHRcdHRoaXNbdGhpcy5pc19vcGVuKCBncm91cCApID8gJ2NvbGxhcHNlJyA6ICdleHBhbmQnXSggZ3JvdXAgKTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIE9wZW4gYSBncm91cCBieSBpdHMgaW5kZXggd2l0aGluIHRoZSBjb250YWluZXIgKDAtYmFzZWQpLlxyXG5cdFx0ICpcclxuXHRcdCAqIEBwYXJhbSB7bnVtYmVyfSBpbmRleCBaZXJvLWJhc2VkIGluZGV4IG9mIHRoZSBncm91cC5cclxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0b3Blbl9ieV9pbmRleChpbmRleCkge1xyXG5cdFx0XHRjb25zdCBncm91cCA9IHRoaXMuX2dyb3Vwc1tpbmRleF07XHJcblx0XHRcdGlmICggZ3JvdXAgKSB7XHJcblx0XHRcdFx0dGhpcy5leHBhbmQoIGdyb3VwICk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIE9wZW4gYSBncm91cCBieSBtYXRjaGluZyB0ZXh0IGNvbnRhaW5lZCB3aXRoaW4gdGhlIDxoMz4gaW5zaWRlIHRoZSBoZWFkZXIuXHJcblx0XHQgKiBUaGUgY29tcGFyaXNvbiBpcyBjYXNlLWluc2Vuc2l0aXZlIGFuZCBzdWJzdHJpbmctYmFzZWQuXHJcblx0XHQgKlxyXG5cdFx0ICogQHBhcmFtIHtzdHJpbmd9IHRleHQgVGV4dCB0byBtYXRjaCBhZ2FpbnN0IHRoZSBoZWFkaW5nIGNvbnRlbnRzLlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAc2luY2UgMjAyNS0wOC0yNlxyXG5cdFx0ICovXHJcblx0XHRvcGVuX2J5X2hlYWRpbmcodGV4dCkge1xyXG5cdFx0XHRpZiAoICF0ZXh0ICkge1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cdFx0XHRjb25zdCB0ICAgICA9IFN0cmluZyggdGV4dCApLnRvTG93ZXJDYXNlKCk7XHJcblx0XHRcdGNvbnN0IG1hdGNoID0gdGhpcy5fZ3JvdXBzLmZpbmQoIChnKSA9PiB7XHJcblx0XHRcdFx0Y29uc3QgaCA9IGcucXVlcnlTZWxlY3RvciggdGhpcy5vcHRzLmhlYWRlcl9zZWxlY3RvciArICcgaDMnICk7XHJcblx0XHRcdFx0cmV0dXJuIGggJiYgaC50ZXh0Q29udGVudC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoIHQgKSAhPT0gLTE7XHJcblx0XHRcdH0gKTtcclxuXHRcdFx0aWYgKCBtYXRjaCApIHtcclxuXHRcdFx0XHR0aGlzLmV4cGFuZCggbWF0Y2ggKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdC8vIEludGVybmFsXHJcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBEZWxlZ2F0ZWQgY2xpY2sgaGFuZGxlciBmb3IgaGVhZGVycy5cclxuXHRcdCAqXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQHBhcmFtIHtNb3VzZUV2ZW50fSBldiBUaGUgY2xpY2sgZXZlbnQuXHJcblx0XHQgKiBAcmV0dXJucyB7dm9pZH1cclxuXHRcdCAqIEBzaW5jZSAyMDI1LTA4LTI2XHJcblx0XHQgKi9cclxuXHRcdF9vbl9jbGljayhldikge1xyXG5cdFx0XHRjb25zdCBidG4gPSBldi50YXJnZXQuY2xvc2VzdCggdGhpcy5vcHRzLmhlYWRlcl9zZWxlY3RvciApO1xyXG5cdFx0XHRpZiAoICFidG4gfHwgIXRoaXMucm9vdC5jb250YWlucyggYnRuICkgKSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblx0XHRcdGV2LnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdGV2LnN0b3BQcm9wYWdhdGlvbigpO1xyXG5cdFx0XHRjb25zdCBncm91cCA9IGJ0bi5jbG9zZXN0KCB0aGlzLm9wdHMuZ3JvdXBfc2VsZWN0b3IgKTtcclxuXHRcdFx0aWYgKCBncm91cCApIHtcclxuXHRcdFx0XHR0aGlzLnRvZ2dsZSggZ3JvdXAgKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogS2V5Ym9hcmQgaGFuZGxlciBmb3IgaGVhZGVyIGludGVyYWN0aW9ucyBhbmQgcm92aW5nIGZvY3VzOlxyXG5cdFx0ICogIC0gRW50ZXIvU3BhY2UgdG9nZ2xlcyB0aGUgYWN0aXZlIGdyb3VwLlxyXG5cdFx0ICogIC0gQXJyb3dVcC9BcnJvd0Rvd24gbW92ZXMgZm9jdXMgYmV0d2VlbiBncm91cCBoZWFkZXJzLlxyXG5cdFx0ICpcclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGV2IFRoZSBrZXlib2FyZCBldmVudC5cclxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0X29uX2tleWRvd24oZXYpIHtcclxuXHRcdFx0Y29uc3QgYnRuID0gZXYudGFyZ2V0LmNsb3Nlc3QoIHRoaXMub3B0cy5oZWFkZXJfc2VsZWN0b3IgKTtcclxuXHRcdFx0aWYgKCAhYnRuICkge1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Y29uc3Qga2V5ID0gZXYua2V5O1xyXG5cclxuXHRcdFx0Ly8gVG9nZ2xlIG9uIEVudGVyIC8gU3BhY2UuXHJcblx0XHRcdGlmICgga2V5ID09PSAnRW50ZXInIHx8IGtleSA9PT0gJyAnICkge1xyXG5cdFx0XHRcdGV2LnByZXZlbnREZWZhdWx0KCk7XHJcblx0XHRcdFx0Y29uc3QgZ3JvdXAgPSBidG4uY2xvc2VzdCggdGhpcy5vcHRzLmdyb3VwX3NlbGVjdG9yICk7XHJcblx0XHRcdFx0aWYgKCBncm91cCApIHtcclxuXHRcdFx0XHRcdHRoaXMudG9nZ2xlKCBncm91cCApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIE1vdmUgZm9jdXMgd2l0aCBBcnJvd1VwL0Fycm93RG93biBiZXR3ZWVuIGhlYWRlcnMgaW4gdGhpcyBjb250YWluZXIuXHJcblx0XHRcdGlmICgga2V5ID09PSAnQXJyb3dVcCcgfHwga2V5ID09PSAnQXJyb3dEb3duJyApIHtcclxuXHRcdFx0XHRldi5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHRcdGNvbnN0IGhlYWRlcnMgPSBBcnJheS5wcm90b3R5cGUubWFwLmNhbGwoXHJcblx0XHRcdFx0XHR0aGlzLnJvb3QucXVlcnlTZWxlY3RvckFsbCggdGhpcy5vcHRzLmdyb3VwX3NlbGVjdG9yICksXHJcblx0XHRcdFx0XHQoZykgPT4gZy5xdWVyeVNlbGVjdG9yKCB0aGlzLm9wdHMuaGVhZGVyX3NlbGVjdG9yIClcclxuXHRcdFx0XHQpLmZpbHRlciggQm9vbGVhbiApO1xyXG5cdFx0XHRcdGNvbnN0IGlkeCAgICAgPSBoZWFkZXJzLmluZGV4T2YoIGJ0biApO1xyXG5cdFx0XHRcdGlmICggaWR4ICE9PSAtMSApIHtcclxuXHRcdFx0XHRcdGNvbnN0IG5leHRfaWR4ID0gKGtleSA9PT0gJ0Fycm93RG93bicpXHJcblx0XHRcdFx0XHRcdD8gTWF0aC5taW4oIGhlYWRlcnMubGVuZ3RoIC0gMSwgaWR4ICsgMSApXHJcblx0XHRcdFx0XHRcdDogTWF0aC5tYXgoIDAsIGlkeCAtIDEgKTtcclxuXHRcdFx0XHRcdGhlYWRlcnNbbmV4dF9pZHhdLmZvY3VzKCk7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBBcHBseSBBUklBIHN5bmNocm9uaXphdGlvbiB0byBhbGwga25vd24gZ3JvdXBzIGJhc2VkIG9uIHRoZWlyIG9wZW4gc3RhdGUuXHJcblx0XHQgKlxyXG5cdFx0ICogQHByaXZhdGVcclxuXHRcdCAqIEByZXR1cm5zIHt2b2lkfVxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0X3N5bmNfYWxsX2FyaWEoKSB7XHJcblx0XHRcdHRoaXMuX2dyb3Vwcy5mb3JFYWNoKCAoZykgPT4gdGhpcy5fc3luY19ncm91cF9hcmlhKCBnICkgKTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIFN5bmMgQVJJQSBhdHRyaWJ1dGVzIGFuZCB2aXNpYmlsaXR5IG9uIGEgc2luZ2xlIGdyb3VwLlxyXG5cdFx0ICpcclxuXHRcdCAqIEBwcml2YXRlXHJcblx0XHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBncm91cCBUaGUgZ3JvdXAgZWxlbWVudCB0byBzeW5jLlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAc2luY2UgMjAyNS0wOC0yNlxyXG5cdFx0ICovXHJcblx0XHRfc3luY19ncm91cF9hcmlhKGdyb3VwKSB7XHJcblx0XHRcdGNvbnN0IGlzX29wZW4gPSB0aGlzLmlzX29wZW4oIGdyb3VwICk7XHJcblx0XHRcdGNvbnN0IGhlYWRlciAgPSBncm91cC5xdWVyeVNlbGVjdG9yKCB0aGlzLm9wdHMuaGVhZGVyX3NlbGVjdG9yICk7XHJcblx0XHRcdC8vIE9ubHkgZGlyZWN0IGNoaWxkcmVuIHRoYXQgbWF0Y2guXHJcblx0XHRcdGNvbnN0IHBhbmVscyA9IEFycmF5LnByb3RvdHlwZS5maWx0ZXIuY2FsbCggZ3JvdXAuY2hpbGRyZW4sIChlbCkgPT4gZWwubWF0Y2hlcyggdGhpcy5vcHRzLmZpZWxkc19zZWxlY3RvciApICk7XHJcblxyXG5cdFx0XHQvLyBIZWFkZXIgQVJJQS5cclxuXHRcdFx0aWYgKCBoZWFkZXIgKSB7XHJcblx0XHRcdFx0aGVhZGVyLnNldEF0dHJpYnV0ZSggJ3JvbGUnLCAnYnV0dG9uJyApO1xyXG5cdFx0XHRcdGhlYWRlci5zZXRBdHRyaWJ1dGUoICdhcmlhLWV4cGFuZGVkJywgaXNfb3BlbiA/ICd0cnVlJyA6ICdmYWxzZScgKTtcclxuXHJcblx0XHRcdFx0aWYgKCBwYW5lbHMubGVuZ3RoICkge1xyXG5cdFx0XHRcdFx0Ly8gRW5zdXJlIGVhY2ggcGFuZWwgaGFzIGFuIGlkOyB0aGVuIHdpcmUgYXJpYS1jb250cm9scyB3aXRoIHNwYWNlLXNlcGFyYXRlZCBpZHMuXHJcblx0XHRcdFx0XHRjb25zdCBpZHMgPSBwYW5lbHMubWFwKCAocCkgPT4ge1xyXG5cdFx0XHRcdFx0XHRpZiAoICFwLmlkICkgcC5pZCA9IHRoaXMuX2dlbmVyYXRlX2lkKCAnd3BiY19jb2xsYXBzaWJsZV9wYW5lbCcgKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIHAuaWQ7XHJcblx0XHRcdFx0XHR9ICk7XHJcblx0XHRcdFx0XHRoZWFkZXIuc2V0QXR0cmlidXRlKCAnYXJpYS1jb250cm9scycsIGlkcy5qb2luKCAnICcgKSApO1xyXG5cdFx0XHRcdH1cclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gKDMpIFBhbmVscyBBUklBICsgdmlzaWJpbGl0eS5cclxuXHRcdFx0cGFuZWxzLmZvckVhY2goIChwKSA9PiB7XHJcblx0XHRcdFx0cC5oaWRkZW4gPSAhaXNfb3BlbjsgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWN0dWFsIHZpc2liaWxpdHkuXHJcblx0XHRcdFx0cC5zZXRBdHRyaWJ1dGUoICdhcmlhLWhpZGRlbicsIGlzX29wZW4gPyAnZmFsc2UnIDogJ3RydWUnICk7IC8vIEFSSUEuXHJcblx0XHRcdH0gKTtcclxuXHRcdH1cclxuXHJcblx0XHQvKipcclxuXHRcdCAqIEludGVybmFsIHN0YXRlIGNoYW5nZTogc2V0IGEgZ3JvdXAncyBvcGVuL2Nsb3NlZCBzdGF0ZSwgc3luYyBBUklBLFxyXG5cdFx0ICogbWFuYWdlIGZvY3VzIG9uIGNvbGxhcHNlLCBhbmQgZW1pdCBhIGN1c3RvbSBldmVudC5cclxuXHRcdCAqXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZ3JvdXAgVGhlIGdyb3VwIGVsZW1lbnQgdG8gbXV0YXRlLlxyXG5cdFx0ICogQHBhcmFtIHtib29sZWFufSBvcGVuIFdoZXRoZXIgdGhlIGdyb3VwIHNob3VsZCBiZSBvcGVuLlxyXG5cdFx0ICogQHJldHVybnMge3ZvaWR9XHJcblx0XHQgKiBAZmlyZXMgQ3VzdG9tRXZlbnQjd3BiYzpjb2xsYXBzaWJsZTpvcGVuXHJcblx0XHQgKiBAZmlyZXMgQ3VzdG9tRXZlbnQjd3BiYzpjb2xsYXBzaWJsZTpjbG9zZVxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0X3NldF9vcGVuKGdyb3VwLCBvcGVuKSB7XHJcblx0XHRcdGlmICggIW9wZW4gJiYgZ3JvdXAuY29udGFpbnMoIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgKSApIHtcclxuXHRcdFx0XHRjb25zdCBoZWFkZXIgPSBncm91cC5xdWVyeVNlbGVjdG9yKCB0aGlzLm9wdHMuaGVhZGVyX3NlbGVjdG9yICk7XHJcblx0XHRcdFx0aGVhZGVyICYmIGhlYWRlci5mb2N1cygpO1xyXG5cdFx0XHR9XHJcblx0XHRcdGdyb3VwLmNsYXNzTGlzdC50b2dnbGUoIHRoaXMub3B0cy5vcGVuX2NsYXNzLCBvcGVuICk7XHJcblx0XHRcdHRoaXMuX3N5bmNfZ3JvdXBfYXJpYSggZ3JvdXAgKTtcclxuXHRcdFx0Y29uc3QgZXZfbmFtZSA9IG9wZW4gPyAnd3BiYzpjb2xsYXBzaWJsZTpvcGVuJyA6ICd3cGJjOmNvbGxhcHNpYmxlOmNsb3NlJztcclxuXHRcdFx0Z3JvdXAuZGlzcGF0Y2hFdmVudCggbmV3IEN1c3RvbUV2ZW50KCBldl9uYW1lLCB7XHJcblx0XHRcdFx0YnViYmxlczogdHJ1ZSxcclxuXHRcdFx0XHRkZXRhaWwgOiB7IGdyb3VwLCByb290OiB0aGlzLnJvb3QsIGluc3RhbmNlOiB0aGlzIH1cclxuXHRcdFx0fSApICk7XHJcblx0XHR9XHJcblxyXG5cdFx0LyoqXHJcblx0XHQgKiBHZW5lcmF0ZSBhIHVuaXF1ZSBET00gaWQgd2l0aCB0aGUgc3BlY2lmaWVkIHByZWZpeC5cclxuXHRcdCAqXHJcblx0XHQgKiBAcHJpdmF0ZVxyXG5cdFx0ICogQHBhcmFtIHtzdHJpbmd9IHByZWZpeCBUaGUgaWQgcHJlZml4IHRvIHVzZS5cclxuXHRcdCAqIEByZXR1cm5zIHtzdHJpbmd9IEEgdW5pcXVlIGVsZW1lbnQgaWQgbm90IHByZXNlbnQgaW4gdGhlIGRvY3VtZW50LlxyXG5cdFx0ICogQHNpbmNlIDIwMjUtMDgtMjZcclxuXHRcdCAqL1xyXG5cdFx0X2dlbmVyYXRlX2lkKHByZWZpeCkge1xyXG5cdFx0XHRsZXQgaSA9IDE7XHJcblx0XHRcdGxldCBpZDtcclxuXHRcdFx0ZG8ge1xyXG5cdFx0XHRcdGlkID0gcHJlZml4ICsgJ18nICsgKGkrKyk7XHJcblx0XHRcdH1cclxuXHRcdFx0d2hpbGUgKCBkLmdldEVsZW1lbnRCeUlkKCBpZCApICk7XHJcblx0XHRcdHJldHVybiBpZDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEF1dG8taW5pdGlhbGl6ZSBjb2xsYXBzaWJsZSBjb250cm9sbGVycyBvbiB0aGUgcGFnZS5cclxuXHQgKiBGaW5kcyB0b3AtbGV2ZWwgYC53cGJjX2NvbGxhcHNpYmxlYCBjb250YWluZXJzIChpZ25vcmluZyBuZXN0ZWQgb25lcyksXHJcblx0ICogYW5kIGluc3RhbnRpYXRlcyB7QGxpbmsgV1BCQ19Db2xsYXBzaWJsZV9Hcm91cHN9IG9uIGVhY2guXHJcblx0ICpcclxuXHQgKiBAZnVuY3Rpb24gV1BCQ19Db2xsYXBzaWJsZV9BdXRvSW5pdFxyXG5cdCAqIEByZXR1cm5zIHt2b2lkfVxyXG5cdCAqIEBzaW5jZSAyMDI1LTA4LTI2XHJcblx0ICogQGV4YW1wbGVcclxuXHQgKiAvLyBSdW5zIGF1dG9tYXRpY2FsbHkgb24gRE9NQ29udGVudExvYWRlZDsgY2FuIGFsc28gYmUgY2FsbGVkIG1hbnVhbGx5OlxyXG5cdCAqIFdQQkNfQ29sbGFwc2libGVfQXV0b0luaXQoKTtcclxuXHQgKi9cclxuXHRmdW5jdGlvbiB3cGJjX2NvbGxhcHNpYmxlX19hdXRvX2luaXQoKSB7XHJcblx0XHR2YXIgUk9PVCAgPSAnLndwYmNfY29sbGFwc2libGUnO1xyXG5cdFx0dmFyIG5vZGVzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoIGQucXVlcnlTZWxlY3RvckFsbCggUk9PVCApIClcclxuXHRcdFx0LmZpbHRlciggZnVuY3Rpb24gKG4pIHtcclxuXHRcdFx0XHRyZXR1cm4gIW4ucGFyZW50RWxlbWVudCB8fCAhbi5wYXJlbnRFbGVtZW50LmNsb3Nlc3QoIFJPT1QgKTtcclxuXHRcdFx0fSApO1xyXG5cclxuXHRcdG5vZGVzLmZvckVhY2goIGZ1bmN0aW9uIChub2RlKSB7XHJcblx0XHRcdGlmICggbm9kZS5fX3dwYmNfY29sbGFwc2libGVfaW5zdGFuY2UgKSB7XHJcblx0XHRcdFx0cmV0dXJuO1xyXG5cdFx0XHR9XHJcblx0XHRcdHZhciBleGNsdXNpdmUgPSBub2RlLmNsYXNzTGlzdC5jb250YWlucyggJ3dwYmNfY29sbGFwc2libGUtLWV4Y2x1c2l2ZScgKSB8fCBub2RlLm1hdGNoZXMoICdbZGF0YS13cGJjLWFjY29yZGlvbj1cImV4Y2x1c2l2ZVwiXScgKTtcclxuXHJcblx0XHRcdG5vZGUuX193cGJjX2NvbGxhcHNpYmxlX2luc3RhbmNlID0gbmV3IFdQQkNfQ29sbGFwc2libGVfR3JvdXBzKCBub2RlLCB7IGV4Y2x1c2l2ZSB9ICkuaW5pdCgpO1xyXG5cdFx0fSApO1xyXG5cdH1cclxuXHJcblx0Ly8gRXhwb3J0IHRvIGdsb2JhbCBmb3IgbWFudWFsIGNvbnRyb2wgaWYgbmVlZGVkLlxyXG5cdHcuV1BCQ19Db2xsYXBzaWJsZV9Hcm91cHMgICA9IFdQQkNfQ29sbGFwc2libGVfR3JvdXBzO1xyXG5cdHcuV1BCQ19Db2xsYXBzaWJsZV9BdXRvSW5pdCA9IHdwYmNfY29sbGFwc2libGVfX2F1dG9faW5pdDtcclxuXHJcblx0Ly8gRE9NLXJlYWR5IGF1dG8gaW5pdC5cclxuXHRpZiAoIGQucmVhZHlTdGF0ZSA9PT0gJ2xvYWRpbmcnICkge1xyXG5cdFx0ZC5hZGRFdmVudExpc3RlbmVyKCAnRE9NQ29udGVudExvYWRlZCcsIHdwYmNfY29sbGFwc2libGVfX2F1dG9faW5pdCwgeyBvbmNlOiB0cnVlIH0gKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0d3BiY19jb2xsYXBzaWJsZV9fYXV0b19pbml0KCk7XHJcblx0fVxyXG59KSggd2luZG93LCBkb2N1bWVudCApO1xyXG4iLCIvKiBnbG9iYWxzIHdpbmRvdywgZG9jdW1lbnQgKi9cclxuLyoqXHJcbiAqIFdQQkMgU2xpZGVyIExlbmd0aCBHcm91cHNcclxuICpcclxuICogVW5pdmVyc2FsLCBkZXBlbmRlbmN5LWZyZWUgY29udHJvbGxlciB0aGF0IGtlZXBzIGEgXCJsZW5ndGhcIiBjb250cm9sIGluIHN5bmM6XHJcbiAqICAtIG51bWJlciBpbnB1dCAgKGRhdGEtd3BiY19zbGlkZXJfbGVuX3ZhbHVlKVxyXG4gKiAgLSB1bml0IHNlbGVjdCAgIChkYXRhLXdwYmNfc2xpZGVyX2xlbl91bml0KVxyXG4gKiAgLSByYW5nZSBzbGlkZXIgIChkYXRhLXdwYmNfc2xpZGVyX2xlbl9yYW5nZSlcclxuICogIC0gd3JpdGVyIGlucHV0ICAoZGF0YS13cGJjX3NsaWRlcl9sZW5fd3JpdGVyKSAgW29wdGlvbmFsIGJ1dCByZWNvbW1lbmRlZF1cclxuICpcclxuICogVGhlIFwid3JpdGVyXCIgc3RvcmVzIHRoZSBjb21iaW5lZCB2YWx1ZSBsaWtlOiBcIjEwMCVcIiwgXCI0MjBweFwiLCBcIjEyLjVyZW1cIi5cclxuICogV2hlbiBudW1iZXIvdW5pdC9zbGlkZXIgY2hhbmdlIC0+IHdyaXRlciB1cGRhdGVzIGFuZCBlbWl0cyAnaW5wdXQnIChidWJibGVzKS5cclxuICogV2hlbiB3cml0ZXIgaXMgY2hhbmdlZCBleHRlcm5hbGx5IChhcHBseS1mcm9tLUpTT04sIGV0YykgLT4gVUkgdXBkYXRlcy5cclxuICpcclxuICogTWFya3VwIGV4cGVjdGF0aW9ucyAobWluaW1hbCk6XHJcbiAqICA8ZGl2IGNsYXNzPVwid3BiY19zbGlkZXJfbGVuX2dyb3VwXCJcclxuICogICAgICAgZGF0YS13cGJjX3NsaWRlcl9sZW5fYm91bmRzX21hcD0ne1wiJVwiOntcIm1pblwiOjMwLFwibWF4XCI6MTAwLFwic3RlcFwiOjF9LFwicHhcIjp7XCJtaW5cIjozMDAsXCJtYXhcIjoyMDAwLFwic3RlcFwiOjEwfX0nXHJcbiAqICAgICAgIGRhdGEtd3BiY19zbGlkZXJfbGVuX2RlZmF1bHRfdW5pdD1cIiVcIj5cclxuICogICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIiBkYXRhLXdwYmNfc2xpZGVyX2xlbl92YWx1ZT5cclxuICogICAgPHNlbGVjdCBkYXRhLXdwYmNfc2xpZGVyX2xlbl91bml0Pi4uLjwvc2VsZWN0PlxyXG4gKiAgICA8aW5wdXQgdHlwZT1cInJhbmdlXCIgZGF0YS13cGJjX3NsaWRlcl9sZW5fcmFuZ2U+XHJcbiAqICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIGRhdGEtd3BiY19zbGlkZXJfbGVuX3dyaXRlciBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj5cclxuICogIDwvZGl2PlxyXG4gKlxyXG4gKiBQZXJmb3JtYW5jZSBub3RlczpcclxuICogLSBNdXRhdGlvbk9ic2VydmVyIGlzIERJU0FCTEVEIGJ5IGRlZmF1bHQgKHByZXZlbnRzIHBlcmZvcm1hbmNlIGlzc3VlcykuXHJcbiAqIC0gSWYgeW91ciBVSSByZS1yZW5kZXJzIGFuZCBpbnNlcnRzIG5ldyBncm91cHMgZHluYW1pY2FsbHksIGNhbGw6XHJcbiAqICAgICBXUEJDX1NsaWRlcl9MZW5fQXV0b0luaXQoKTsgIE9SIGluc3RhbmNlLnJlZnJlc2goKTtcclxuICogICBPciBlbmFibGUgb2JzZXJ2ZXIgdmlhOiBuZXcgV1BCQ19TbGlkZXJfTGVuX0dyb3Vwcyhyb290LCB7IGVuYWJsZV9vYnNlcnZlcjp0cnVlIH0pLmluaXQoKTtcclxuICpcclxuICogUHVibGljIEFQSSAoaW5zdGFuY2UgbWV0aG9kcyk6XHJcbiAqICAtIGluaXQoKSwgZGVzdHJveSgpLCByZWZyZXNoKClcclxuICpcclxuICogQHZlcnNpb24gMjAyNi0wMS0yNVxyXG4gKiBAc2luY2UgICAyMDI2LTAxLTI1XHJcbiAqIEBmaWxlICAgIC4uL2luY2x1ZGVzL19fanMvYWRtaW4vc2xpZGVyX2dyb3Vwcy93cGJjX2xlbl9ncm91cHMuanNcclxuICovXHJcbihmdW5jdGlvbiAodywgZCkge1xyXG5cdCd1c2Ugc3RyaWN0JztcclxuXHJcblx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdC8vIEhlbHBlcnNcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0ZnVuY3Rpb24gY2xhbXBfbnVtKHYsIG1pbiwgbWF4KSB7XHJcblx0XHRpZiAodHlwZW9mIG1pbiA9PT0gJ251bWJlcicgJiYgIWlzTmFOKG1pbikpIHYgPSBNYXRoLm1heChtaW4sIHYpO1xyXG5cdFx0aWYgKHR5cGVvZiBtYXggPT09ICdudW1iZXInICYmICFpc05hTihtYXgpKSB2ID0gTWF0aC5taW4obWF4LCB2KTtcclxuXHRcdHJldHVybiB2O1xyXG5cdH1cclxuXHJcblx0ZnVuY3Rpb24gcGFyc2VfZmxvYXQodikge1xyXG5cdFx0dmFyIG4gPSBwYXJzZUZsb2F0KHYpO1xyXG5cdFx0cmV0dXJuIGlzTmFOKG4pID8gbnVsbCA6IG47XHJcblx0fVxyXG5cclxuXHRmdW5jdGlvbiBzYWZlX2pzb25fcGFyc2Uoc3RyKSB7XHJcblx0XHR0cnkge1xyXG5cdFx0XHRyZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xyXG5cdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdGZ1bmN0aW9uIHBhcnNlX2xlbl9jb21iaW5lZChyYXcsIGRlZmF1bHRfdW5pdCkge1xyXG5cdFx0dmFyIHMgPSAocmF3ID09IG51bGwpID8gJycgOiBTdHJpbmcocmF3KS50cmltKCk7XHJcblx0XHRpZiAoIXMpIHJldHVybiB7IG51bTogJycsIHVuaXQ6IGRlZmF1bHRfdW5pdCB8fCAnJScgfTtcclxuXHJcblx0XHR2YXIgbSA9IHMubWF0Y2goL15cXHMqKFtcXC1dP1xcZCsoPzpcXC5cXGQrKT8pXFxzKihbYS16JV0qKVxccyokL2kpO1xyXG5cdFx0aWYgKCFtKSB7XHJcblx0XHRcdC8vIElmIGl0J3Mgbm90IHBhcnNlYWJsZSwgdHJlYXQgYXMgbnVtYmVyIGFuZCBrZWVwIGRlZmF1bHQgdW5pdC5cclxuXHRcdFx0cmV0dXJuIHsgbnVtOiBzLCB1bml0OiBkZWZhdWx0X3VuaXQgfHwgJyUnIH07XHJcblx0XHR9XHJcblxyXG5cdFx0dmFyIG51bSAgPSBtWzFdID8gU3RyaW5nKG1bMV0pIDogJyc7XHJcblx0XHR2YXIgdW5pdCA9IG1bMl0gPyBTdHJpbmcobVsyXSkgOiAnJztcclxuXHRcdGlmICghdW5pdCkgdW5pdCA9IGRlZmF1bHRfdW5pdCB8fCAnJSc7XHJcblxyXG5cdFx0cmV0dXJuIHsgbnVtOiBudW0sIHVuaXQ6IHVuaXQgfTtcclxuXHR9XHJcblxyXG5cdGZ1bmN0aW9uIGJ1aWxkX2NvbWJpbmVkKG51bSwgdW5pdCkge1xyXG5cdFx0aWYgKG51bSA9PSBudWxsIHx8IFN0cmluZyhudW0pLnRyaW0oKSA9PT0gJycpIHJldHVybiAnJztcclxuXHRcdHJldHVybiBTdHJpbmcobnVtKSArIFN0cmluZyh1bml0IHx8ICcnKTtcclxuXHR9XHJcblxyXG5cdGZ1bmN0aW9uIGVtaXRfaW5wdXQoZWwpIHtcclxuXHRcdGlmICghZWwpIHJldHVybjtcclxuXHRcdGVsLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdpbnB1dCcsIHsgYnViYmxlczogdHJ1ZSB9KSk7XHJcblx0fVxyXG5cclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gQ29udHJvbGxlclxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRjbGFzcyBXUEJDX1NsaWRlcl9MZW5fR3JvdXBzIHtcclxuXHJcblx0XHQvKipcclxuXHRcdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSByb290X2VsIENvbnRhaW5lciAob3Igc2VsZWN0b3IpLiBJZiBvbWl0dGVkLCB1c2VzIGRvY3VtZW50LlxyXG5cdFx0ICogQHBhcmFtIHtPYmplY3R9IFtvcHRzPXt9XVxyXG5cdFx0ICovXHJcblx0XHRjb25zdHJ1Y3Rvcihyb290X2VsLCBvcHRzKSB7XHJcblx0XHRcdHRoaXMucm9vdCA9IHJvb3RfZWxcclxuXHRcdFx0XHQ/ICgodHlwZW9mIHJvb3RfZWwgPT09ICdzdHJpbmcnKSA/IGQucXVlcnlTZWxlY3Rvcihyb290X2VsKSA6IHJvb3RfZWwpXHJcblx0XHRcdFx0OiBkO1xyXG5cclxuXHRcdFx0dGhpcy5vcHRzID0gT2JqZWN0LmFzc2lnbih7XHJcblx0XHRcdFx0Ly8gU3RyaWN0IHNlbGVjdG9ycyAoTk8gYmFja3dhcmQgY29tcGF0aWJpbGl0eSkuXHJcblx0XHRcdFx0Z3JvdXBfc2VsZWN0b3IgIDogJy53cGJjX3NsaWRlcl9sZW5fZ3JvdXAnLFxyXG5cdFx0XHRcdHZhbHVlX3NlbGVjdG9yICA6ICdbZGF0YS13cGJjX3NsaWRlcl9sZW5fdmFsdWVdJyxcclxuXHRcdFx0XHR1bml0X3NlbGVjdG9yICAgOiAnW2RhdGEtd3BiY19zbGlkZXJfbGVuX3VuaXRdJyxcclxuXHRcdFx0XHRyYW5nZV9zZWxlY3RvciAgOiAnW2RhdGEtd3BiY19zbGlkZXJfbGVuX3JhbmdlXScsXHJcblx0XHRcdFx0d3JpdGVyX3NlbGVjdG9yIDogJ1tkYXRhLXdwYmNfc2xpZGVyX2xlbl93cml0ZXJdJyxcclxuXHJcblx0XHRcdFx0ZGVmYXVsdF91bml0ICAgIDogJyUnLFxyXG5cclxuXHRcdFx0XHRmYWxsYmFja19ib3VuZHMgOiB7XHJcblx0XHRcdFx0XHQncHgnIDogeyBtaW46IDAsICAgbWF4OiA1MTIsICBzdGVwOiAxICAgfSxcclxuXHRcdFx0XHRcdCclJyAgOiB7IG1pbjogMCwgICBtYXg6IDEwMCwgIHN0ZXA6IDEgICB9LFxyXG5cdFx0XHRcdFx0J3JlbSc6IHsgbWluOiAwLCAgIG1heDogMTAsICAgc3RlcDogMC4xIH0sXHJcblx0XHRcdFx0XHQnZW0nIDogeyBtaW46IDAsICAgbWF4OiAxMCwgICBzdGVwOiAwLjEgfVxyXG5cdFx0XHRcdH0sXHJcblxyXG5cdFx0XHRcdC8vIERpc2FibGVkIGJ5IGRlZmF1bHQgZm9yIHBlcmZvcm1hbmNlLlxyXG5cdFx0XHRcdGVuYWJsZV9vYnNlcnZlciAgICAgOiBmYWxzZSxcclxuXHRcdFx0XHRvYnNlcnZlcl9kZWJvdW5jZV9tczogMTUwXHJcblx0XHRcdH0sIG9wdHMgfHwge30pO1xyXG5cclxuXHRcdFx0dGhpcy5fb25faW5wdXQgID0gdGhpcy5fb25faW5wdXQuYmluZCh0aGlzKTtcclxuXHRcdFx0dGhpcy5fb25fY2hhbmdlID0gdGhpcy5fb25fY2hhbmdlLmJpbmQodGhpcyk7XHJcblxyXG5cdFx0XHR0aGlzLl9ib3VuZHNfY2FjaGUgPSBuZXcgV2Vha01hcCgpOyAvLyBncm91cCAtPiBib3VuZHNfbWFwX29iamVjdFxyXG5cdFx0XHR0aGlzLl9vYnNlcnZlciAgICAgPSBudWxsO1xyXG5cdFx0XHR0aGlzLl9yZWZyZXNoX3RtciAgPSBudWxsO1xyXG5cdFx0fVxyXG5cclxuXHRcdGluaXQoKSB7XHJcblx0XHRcdGlmICghdGhpcy5yb290KSByZXR1cm4gdGhpcztcclxuXHJcblx0XHRcdHRoaXMucm9vdC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsICB0aGlzLl9vbl9pbnB1dCwgIHRydWUpO1xyXG5cdFx0XHR0aGlzLnJvb3QuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgdGhpcy5fb25fY2hhbmdlLCB0cnVlKTtcclxuXHJcblx0XHRcdGlmICh0aGlzLm9wdHMuZW5hYmxlX29ic2VydmVyICYmIHcuTXV0YXRpb25PYnNlcnZlcikge1xyXG5cdFx0XHRcdHRoaXMuX29ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4geyB0aGlzLl9kZWJvdW5jZWRfcmVmcmVzaCgpOyB9KTtcclxuXHRcdFx0XHR0aGlzLl9vYnNlcnZlci5vYnNlcnZlKHRoaXMucm9vdCA9PT0gZCA/IGQuZG9jdW1lbnRFbGVtZW50IDogdGhpcy5yb290LCB7IGNoaWxkTGlzdDogdHJ1ZSwgc3VidHJlZTogdHJ1ZSB9KTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0dGhpcy5yZWZyZXNoKCk7XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fVxyXG5cclxuXHRcdGRlc3Ryb3koKSB7XHJcblx0XHRcdGlmICghdGhpcy5yb290KSByZXR1cm47XHJcblxyXG5cdFx0XHR0aGlzLnJvb3QucmVtb3ZlRXZlbnRMaXN0ZW5lcignaW5wdXQnLCAgdGhpcy5fb25faW5wdXQsICB0cnVlKTtcclxuXHRcdFx0dGhpcy5yb290LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHRoaXMuX29uX2NoYW5nZSwgdHJ1ZSk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5fb2JzZXJ2ZXIpIHtcclxuXHRcdFx0XHR0aGlzLl9vYnNlcnZlci5kaXNjb25uZWN0KCk7XHJcblx0XHRcdFx0dGhpcy5fb2JzZXJ2ZXIgPSBudWxsO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAodGhpcy5fcmVmcmVzaF90bXIpIHtcclxuXHRcdFx0XHRjbGVhclRpbWVvdXQodGhpcy5fcmVmcmVzaF90bXIpO1xyXG5cdFx0XHRcdHRoaXMuX3JlZnJlc2hfdG1yID0gbnVsbDtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdHJlZnJlc2goKSB7XHJcblx0XHRcdGlmICghdGhpcy5yb290KSByZXR1cm47XHJcblxyXG5cdFx0XHR2YXIgc2NvcGUgID0gKHRoaXMucm9vdCA9PT0gZCA/IGQgOiB0aGlzLnJvb3QpO1xyXG5cdFx0XHR2YXIgZ3JvdXBzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoc2NvcGUucXVlcnlTZWxlY3RvckFsbCh0aGlzLm9wdHMuZ3JvdXBfc2VsZWN0b3IpKTtcclxuXHJcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgZ3JvdXBzLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdFx0dGhpcy5fc3luY19ncm91cF9mcm9tX3dyaXRlcihncm91cHNbaV0pO1xyXG5cdFx0XHRcdHRoaXMuX2FwcGx5X2JvdW5kc19mb3JfY3VycmVudF91bml0KGdyb3Vwc1tpXSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0XHQvLyBJbnRlcm5hbFxyXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0X2RlYm91bmNlZF9yZWZyZXNoKCkge1xyXG5cdFx0XHRpZiAodGhpcy5fcmVmcmVzaF90bXIpIGNsZWFyVGltZW91dCh0aGlzLl9yZWZyZXNoX3Rtcik7XHJcblx0XHRcdHRoaXMuX3JlZnJlc2hfdG1yID0gc2V0VGltZW91dCgoKSA9PiB7XHJcblx0XHRcdFx0dGhpcy5fcmVmcmVzaF90bXIgPSBudWxsO1xyXG5cdFx0XHRcdHRoaXMucmVmcmVzaCgpO1xyXG5cdFx0XHR9LCBOdW1iZXIodGhpcy5vcHRzLm9ic2VydmVyX2RlYm91bmNlX21zKSB8fCAwKTtcclxuXHRcdH1cclxuXHJcblx0XHRfZmluZF9ncm91cChlbCkge1xyXG5cdFx0XHRyZXR1cm4gKGVsICYmIGVsLmNsb3Nlc3QpID8gZWwuY2xvc2VzdCh0aGlzLm9wdHMuZ3JvdXBfc2VsZWN0b3IpIDogbnVsbDtcclxuXHRcdH1cclxuXHJcblx0XHRfZ2V0X3BhcnRzKGdyb3VwKSB7XHJcblx0XHRcdGlmICghZ3JvdXApIHJldHVybiBudWxsO1xyXG5cdFx0XHRyZXR1cm4ge1xyXG5cdFx0XHRcdGdyb3VwIDogZ3JvdXAsXHJcblx0XHRcdFx0bnVtICAgOiBncm91cC5xdWVyeVNlbGVjdG9yKHRoaXMub3B0cy52YWx1ZV9zZWxlY3RvciksXHJcblx0XHRcdFx0dW5pdCAgOiBncm91cC5xdWVyeVNlbGVjdG9yKHRoaXMub3B0cy51bml0X3NlbGVjdG9yKSxcclxuXHRcdFx0XHRyYW5nZSA6IGdyb3VwLnF1ZXJ5U2VsZWN0b3IodGhpcy5vcHRzLnJhbmdlX3NlbGVjdG9yKSxcclxuXHRcdFx0XHR3cml0ZXI6IGdyb3VwLnF1ZXJ5U2VsZWN0b3IodGhpcy5vcHRzLndyaXRlcl9zZWxlY3RvcilcclxuXHRcdFx0fTtcclxuXHRcdH1cclxuXHJcblx0XHRfZ2V0X2RlZmF1bHRfdW5pdChncm91cCkge1xyXG5cdFx0XHR2YXIgZHUgPSAoZ3JvdXAgJiYgZ3JvdXAuZ2V0QXR0cmlidXRlKVxyXG5cdFx0XHRcdD8gZ3JvdXAuZ2V0QXR0cmlidXRlKCdkYXRhLXdwYmNfc2xpZGVyX2xlbl9kZWZhdWx0X3VuaXQnKVxyXG5cdFx0XHRcdDogJyc7XHJcblx0XHRcdHJldHVybiBkdSA/IFN0cmluZyhkdSkgOiB0aGlzLm9wdHMuZGVmYXVsdF91bml0O1xyXG5cdFx0fVxyXG5cclxuXHRcdF9nZXRfYm91bmRzX21hcChncm91cCkge1xyXG5cdFx0XHRpZiAoIWdyb3VwKSByZXR1cm4gbnVsbDtcclxuXHRcdFx0aWYgKHRoaXMuX2JvdW5kc19jYWNoZS5oYXMoZ3JvdXApKSB7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMuX2JvdW5kc19jYWNoZS5nZXQoZ3JvdXApO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHR2YXIgcmF3ID0gZ3JvdXAuZ2V0QXR0cmlidXRlKCdkYXRhLXdwYmNfc2xpZGVyX2xlbl9ib3VuZHNfbWFwJyk7XHJcblx0XHRcdHZhciBtYXAgPSByYXcgPyBzYWZlX2pzb25fcGFyc2UocmF3KSA6IG51bGw7XHJcblx0XHRcdGlmICghbWFwIHx8IHR5cGVvZiBtYXAgIT09ICdvYmplY3QnKSBtYXAgPSBudWxsO1xyXG5cclxuXHRcdFx0dGhpcy5fYm91bmRzX2NhY2hlLnNldChncm91cCwgbWFwKTtcclxuXHRcdFx0cmV0dXJuIG1hcDtcclxuXHRcdH1cclxuXHJcblx0XHRfZ2V0X2JvdW5kc19mb3JfdW5pdChncm91cCwgdW5pdCkge1xyXG5cdFx0XHR2YXIgbWFwID0gdGhpcy5fZ2V0X2JvdW5kc19tYXAoZ3JvdXApO1xyXG5cdFx0XHRpZiAobWFwICYmIHVuaXQgJiYgbWFwW3VuaXRdKSB7XHJcblx0XHRcdFx0cmV0dXJuIG1hcFt1bml0XTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm4gdGhpcy5vcHRzLmZhbGxiYWNrX2JvdW5kc1t1bml0XSB8fCB0aGlzLm9wdHMuZmFsbGJhY2tfYm91bmRzWydweCddO1xyXG5cdFx0fVxyXG5cclxuXHRcdF9hcHBseV9ib3VuZHMocGFydHMsIGJvdW5kcykge1xyXG5cdFx0XHRpZiAoIXBhcnRzIHx8ICFib3VuZHMpIHJldHVybjtcclxuXHJcblx0XHRcdHZhciBtaW4gID0gKGJvdW5kcy5taW4gICE9IG51bGwpID8gTnVtYmVyKGJvdW5kcy5taW4pICA6IG51bGw7XHJcblx0XHRcdHZhciBtYXggID0gKGJvdW5kcy5tYXggICE9IG51bGwpID8gTnVtYmVyKGJvdW5kcy5tYXgpICA6IG51bGw7XHJcblx0XHRcdHZhciBzdGVwID0gKGJvdW5kcy5zdGVwICE9IG51bGwpID8gTnVtYmVyKGJvdW5kcy5zdGVwKSA6IG51bGw7XHJcblxyXG5cdFx0XHRpZiAocGFydHMucmFuZ2UpIHtcclxuXHRcdFx0XHRpZiAoIWlzTmFOKG1pbikpICBwYXJ0cy5yYW5nZS5taW4gID0gU3RyaW5nKG1pbik7XHJcblx0XHRcdFx0aWYgKCFpc05hTihtYXgpKSAgcGFydHMucmFuZ2UubWF4ICA9IFN0cmluZyhtYXgpO1xyXG5cdFx0XHRcdGlmICghaXNOYU4oc3RlcCkpIHBhcnRzLnJhbmdlLnN0ZXAgPSBTdHJpbmcoc3RlcCk7XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHBhcnRzLm51bSkge1xyXG5cdFx0XHRcdGlmICghaXNOYU4obWluKSkgIHBhcnRzLm51bS5taW4gID0gU3RyaW5nKG1pbik7XHJcblx0XHRcdFx0aWYgKCFpc05hTihtYXgpKSAgcGFydHMubnVtLm1heCAgPSBTdHJpbmcobWF4KTtcclxuXHRcdFx0XHRpZiAoIWlzTmFOKHN0ZXApKSBwYXJ0cy5udW0uc3RlcCA9IFN0cmluZyhzdGVwKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdF9hcHBseV9ib3VuZHNfZm9yX2N1cnJlbnRfdW5pdChncm91cCkge1xyXG5cdFx0XHR2YXIgcGFydHMgPSB0aGlzLl9nZXRfcGFydHMoZ3JvdXApO1xyXG5cdFx0XHRpZiAoIXBhcnRzIHx8ICFwYXJ0cy51bml0KSByZXR1cm47XHJcblxyXG5cdFx0XHR2YXIgdW5pdCA9IHBhcnRzLnVuaXQudmFsdWUgfHwgdGhpcy5fZ2V0X2RlZmF1bHRfdW5pdChncm91cCk7XHJcblx0XHRcdHZhciBiICAgID0gdGhpcy5fZ2V0X2JvdW5kc19mb3JfdW5pdChncm91cCwgdW5pdCk7XHJcblxyXG5cdFx0XHR0aGlzLl9hcHBseV9ib3VuZHMocGFydHMsIGIpO1xyXG5cclxuXHRcdFx0Ly8gQ2xhbXAgY3VycmVudCB2YWx1ZSB0byBuZXcgYm91bmRzLlxyXG5cdFx0XHR2YXIgdiA9IHBhcnNlX2Zsb2F0KHBhcnRzLm51bSAmJiBwYXJ0cy5udW0udmFsdWUgPyBwYXJ0cy5udW0udmFsdWUgOiAocGFydHMucmFuZ2UgPyBwYXJ0cy5yYW5nZS52YWx1ZSA6ICcnKSk7XHJcblx0XHRcdGlmICh2ID09IG51bGwpIHJldHVybjtcclxuXHJcblx0XHRcdHZhciBtaW4gPSAoYiAmJiBiLm1pbiAhPSBudWxsKSA/IE51bWJlcihiLm1pbikgOiBudWxsO1xyXG5cdFx0XHR2YXIgbWF4ID0gKGIgJiYgYi5tYXggIT0gbnVsbCkgPyBOdW1iZXIoYi5tYXgpIDogbnVsbDtcclxuXHRcdFx0diA9IGNsYW1wX251bSh2LCBpc05hTihtaW4pID8gbnVsbCA6IG1pbiwgaXNOYU4obWF4KSA/IG51bGwgOiBtYXgpO1xyXG5cclxuXHRcdFx0aWYgKHBhcnRzLm51bSkgICBwYXJ0cy5udW0udmFsdWUgICA9IFN0cmluZyh2KTtcclxuXHRcdFx0aWYgKHBhcnRzLnJhbmdlKSBwYXJ0cy5yYW5nZS52YWx1ZSA9IFN0cmluZyh2KTtcclxuXHJcblx0XHRcdHRoaXMuX3dyaXRlX2NvbWJpbmVkKHBhcnRzLCBTdHJpbmcodiksIHVuaXQsIC8qZW1pdCovIGZhbHNlKTtcclxuXHRcdH1cclxuXHJcblx0XHRfd3JpdGVfY29tYmluZWQocGFydHMsIG51bSwgdW5pdCwgZW1pdCkge1xyXG5cdFx0XHRpZiAoIXBhcnRzKSByZXR1cm47XHJcblxyXG5cdFx0XHR2YXIgY29tYmluZWQgPSBidWlsZF9jb21iaW5lZChudW0sIHVuaXQpO1xyXG5cclxuXHRcdFx0aWYgKHBhcnRzLndyaXRlcikge1xyXG5cdFx0XHRcdC8vIEF2b2lkIHJlY3Vyc2lvbjogbWFyayBhcyBpbnRlcm5hbCB3cml0ZS5cclxuXHRcdFx0XHRwYXJ0cy53cml0ZXIuX193cGJjX3NsaWRlcl9sZW5faW50ZXJuYWwgPSB0cnVlO1xyXG5cdFx0XHRcdHBhcnRzLndyaXRlci52YWx1ZSA9IGNvbWJpbmVkO1xyXG5cdFx0XHRcdGlmIChlbWl0KSBlbWl0X2lucHV0KHBhcnRzLndyaXRlcik7XHJcblx0XHRcdFx0cGFydHMud3JpdGVyLl9fd3BiY19zbGlkZXJfbGVuX2ludGVybmFsID0gZmFsc2U7XHJcblx0XHRcdH0gZWxzZSBpZiAocGFydHMubnVtKSB7XHJcblx0XHRcdFx0Ly8gSWYgd3JpdGVyIGlzIG1pc3NpbmcsIGF0IGxlYXN0IG5vdGlmeSB2aWEgbnVtYmVyIGlucHV0LlxyXG5cdFx0XHRcdGlmIChlbWl0KSBlbWl0X2lucHV0KHBhcnRzLm51bSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRfc3luY19ncm91cF9mcm9tX3dyaXRlcihncm91cCkge1xyXG5cdFx0XHR2YXIgcGFydHMgPSB0aGlzLl9nZXRfcGFydHMoZ3JvdXApO1xyXG5cdFx0XHRpZiAoIXBhcnRzIHx8ICFwYXJ0cy53cml0ZXIpIHJldHVybjtcclxuXHJcblx0XHRcdHZhciByYXcgPSBTdHJpbmcocGFydHMud3JpdGVyLnZhbHVlIHx8ICcnKS50cmltKCk7XHJcblx0XHRcdGlmICghcmF3KSByZXR1cm47XHJcblxyXG5cdFx0XHR2YXIgZHUgPSB0aGlzLl9nZXRfZGVmYXVsdF91bml0KGdyb3VwKTtcclxuXHRcdFx0dmFyIHAgID0gcGFyc2VfbGVuX2NvbWJpbmVkKHJhdywgZHUpO1xyXG5cclxuXHRcdFx0aWYgKHBhcnRzLnVuaXQpICBwYXJ0cy51bml0LnZhbHVlICA9IHAudW5pdDtcclxuXHRcdFx0aWYgKHBhcnRzLm51bSkgICBwYXJ0cy5udW0udmFsdWUgICA9IHAubnVtO1xyXG5cdFx0XHRpZiAocGFydHMucmFuZ2UpIHBhcnRzLnJhbmdlLnZhbHVlID0gcC5udW07XHJcblx0XHR9XHJcblxyXG5cdFx0X29uX2lucHV0KGV2KSB7XHJcblx0XHRcdHZhciB0ID0gZXYudGFyZ2V0O1xyXG5cdFx0XHRpZiAoIXQpIHJldHVybjtcclxuXHJcblx0XHRcdHZhciBncm91cCA9IHRoaXMuX2ZpbmRfZ3JvdXAodCk7XHJcblx0XHRcdGlmICghZ3JvdXApIHJldHVybjtcclxuXHJcblx0XHRcdHZhciBwYXJ0cyA9IHRoaXMuX2dldF9wYXJ0cyhncm91cCk7XHJcblx0XHRcdGlmICghcGFydHMpIHJldHVybjtcclxuXHJcblx0XHRcdC8vIFdyaXRlciBjaGFuZ2VkIGV4dGVybmFsbHkgLT4gdXBkYXRlIFVJLlxyXG5cdFx0XHRpZiAocGFydHMud3JpdGVyICYmIHQgPT09IHBhcnRzLndyaXRlcikge1xyXG5cdFx0XHRcdGlmICh0Ll9fd3BiY19zbGlkZXJfbGVuX2ludGVybmFsKSByZXR1cm47XHJcblx0XHRcdFx0dGhpcy5fc3luY19ncm91cF9mcm9tX3dyaXRlcihncm91cCk7XHJcblx0XHRcdFx0dGhpcy5fYXBwbHlfYm91bmRzX2Zvcl9jdXJyZW50X3VuaXQoZ3JvdXApO1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0Ly8gU2xpZGVyIG1vdmVkIC0+IHVwZGF0ZSBudW1iZXIgKyB3cml0ZXIuXHJcblx0XHRcdGlmICh0Lm1hdGNoZXMgJiYgdC5tYXRjaGVzKHRoaXMub3B0cy5yYW5nZV9zZWxlY3RvcikpIHtcclxuXHRcdFx0XHRpZiAocGFydHMubnVtKSBwYXJ0cy5udW0udmFsdWUgPSB0LnZhbHVlO1xyXG5cclxuXHRcdFx0XHR2YXIgdW5pdCA9IChwYXJ0cy51bml0ICYmIHBhcnRzLnVuaXQudmFsdWUpID8gcGFydHMudW5pdC52YWx1ZSA6IHRoaXMuX2dldF9kZWZhdWx0X3VuaXQoZ3JvdXApO1xyXG5cdFx0XHRcdHRoaXMuX3dyaXRlX2NvbWJpbmVkKHBhcnRzLCB0LnZhbHVlLCB1bml0LCAvKmVtaXQqLyB0cnVlKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIE51bWJlciB0eXBlZCAtPiB1cGRhdGUgc2xpZGVyICsgd3JpdGVyIChjbGFtcCBpZiBzbGlkZXIgaGFzIGJvdW5kcykuXHJcblx0XHRcdGlmICh0Lm1hdGNoZXMgJiYgdC5tYXRjaGVzKHRoaXMub3B0cy52YWx1ZV9zZWxlY3RvcikpIHtcclxuXHRcdFx0XHR2YXIgdiA9IHBhcnNlX2Zsb2F0KHQudmFsdWUpO1xyXG5cclxuXHRcdFx0XHRpZiAodiAhPSBudWxsICYmIHBhcnRzLnJhbmdlKSB7XHJcblx0XHRcdFx0XHR2YXIgcm1pbiA9IE51bWJlcihwYXJ0cy5yYW5nZS5taW4pO1xyXG5cdFx0XHRcdFx0dmFyIHJtYXggPSBOdW1iZXIocGFydHMucmFuZ2UubWF4KTtcclxuXHRcdFx0XHRcdHYgPSBjbGFtcF9udW0odiwgaXNOYU4ocm1pbikgPyBudWxsIDogcm1pbiwgaXNOYU4ocm1heCkgPyBudWxsIDogcm1heCk7XHJcblxyXG5cdFx0XHRcdFx0cGFydHMucmFuZ2UudmFsdWUgPSBTdHJpbmcodik7XHJcblx0XHRcdFx0XHRpZiAoU3RyaW5nKHYpICE9PSB0LnZhbHVlKSB0LnZhbHVlID0gU3RyaW5nKHYpO1xyXG5cdFx0XHRcdH1cclxuXHJcblx0XHRcdFx0dmFyIHVuaXQyID0gKHBhcnRzLnVuaXQgJiYgcGFydHMudW5pdC52YWx1ZSkgPyBwYXJ0cy51bml0LnZhbHVlIDogdGhpcy5fZ2V0X2RlZmF1bHRfdW5pdChncm91cCk7XHJcblx0XHRcdFx0dGhpcy5fd3JpdGVfY29tYmluZWQocGFydHMsIHQudmFsdWUsIHVuaXQyLCAvKmVtaXQqLyB0cnVlKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdF9vbl9jaGFuZ2UoZXYpIHtcclxuXHRcdFx0dmFyIHQgPSBldi50YXJnZXQ7XHJcblx0XHRcdGlmICghdCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIGdyb3VwID0gdGhpcy5fZmluZF9ncm91cCh0KTtcclxuXHRcdFx0aWYgKCFncm91cCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIHBhcnRzID0gdGhpcy5fZ2V0X3BhcnRzKGdyb3VwKTtcclxuXHRcdFx0aWYgKCFwYXJ0cykgcmV0dXJuO1xyXG5cclxuXHRcdFx0Ly8gVW5pdCBjaGFuZ2VkIC0+IHVwZGF0ZSBib3VuZHMgKyB3cml0ZXIuXHJcblx0XHRcdGlmICh0Lm1hdGNoZXMgJiYgdC5tYXRjaGVzKHRoaXMub3B0cy51bml0X3NlbGVjdG9yKSkge1xyXG5cdFx0XHRcdHRoaXMuX2FwcGx5X2JvdW5kc19mb3JfY3VycmVudF91bml0KGdyb3VwKTtcclxuXHJcblx0XHRcdFx0dmFyIG51bSAgPSBwYXJ0cy5udW0gPyBwYXJ0cy5udW0udmFsdWUgOiAocGFydHMucmFuZ2UgPyBwYXJ0cy5yYW5nZS52YWx1ZSA6ICcnKTtcclxuXHRcdFx0XHR2YXIgdW5pdCA9IHQudmFsdWUgfHwgdGhpcy5fZ2V0X2RlZmF1bHRfdW5pdChncm91cCk7XHJcblx0XHRcdFx0dGhpcy5fd3JpdGVfY29tYmluZWQocGFydHMsIG51bSwgdW5pdCwgLyplbWl0Ki8gdHJ1ZSk7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBBdXRvLWluaXRcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0ZnVuY3Rpb24gd3BiY19zbGlkZXJfbGVuX2dyb3Vwc19fYXV0b19pbml0KCkge1xyXG5cdFx0dmFyIFJPT1QgID0gJy53cGJjX3NsaWRlcl9sZW5fZ3JvdXBzJztcclxuXHRcdHZhciBub2RlcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGQucXVlcnlTZWxlY3RvckFsbChST09UKSlcclxuXHRcdFx0LmZpbHRlcihmdW5jdGlvbiAobikgeyByZXR1cm4gIW4ucGFyZW50RWxlbWVudCB8fCAhbi5wYXJlbnRFbGVtZW50LmNsb3Nlc3QoUk9PVCk7IH0pO1xyXG5cclxuXHRcdC8vIElmIG5vIGV4cGxpY2l0IGNvbnRhaW5lcnMsIGluc3RhbGwgYSBzaW5nbGUgZG9jdW1lbnQtcm9vdCBpbnN0YW5jZS5cclxuXHRcdGlmICghbm9kZXMubGVuZ3RoKSB7XHJcblx0XHRcdGlmICghZC5fX3dwYmNfc2xpZGVyX2xlbl9ncm91cHNfZ2xvYmFsX2luc3RhbmNlKSB7XHJcblx0XHRcdFx0ZC5fX3dwYmNfc2xpZGVyX2xlbl9ncm91cHNfZ2xvYmFsX2luc3RhbmNlID0gbmV3IFdQQkNfU2xpZGVyX0xlbl9Hcm91cHMoZCkuaW5pdCgpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHRub2Rlcy5mb3JFYWNoKGZ1bmN0aW9uIChub2RlKSB7XHJcblx0XHRcdGlmIChub2RlLl9fd3BiY19zbGlkZXJfbGVuX2dyb3Vwc19pbnN0YW5jZSkgcmV0dXJuO1xyXG5cdFx0XHRub2RlLl9fd3BiY19zbGlkZXJfbGVuX2dyb3Vwc19pbnN0YW5jZSA9IG5ldyBXUEJDX1NsaWRlcl9MZW5fR3JvdXBzKG5vZGUpLmluaXQoKTtcclxuXHRcdH0pO1xyXG5cdH1cclxuXHJcblx0Ly8gRXhwb3J0IGdsb2JhbHMgKG1hbnVhbCBjb250cm9sIGlmIG5lZWRlZCkuXHJcblx0dy5XUEJDX1NsaWRlcl9MZW5fR3JvdXBzICAgPSBXUEJDX1NsaWRlcl9MZW5fR3JvdXBzO1xyXG5cdHcuV1BCQ19TbGlkZXJfTGVuX0F1dG9Jbml0ID0gd3BiY19zbGlkZXJfbGVuX2dyb3Vwc19fYXV0b19pbml0O1xyXG5cclxuXHQvLyBET00tcmVhZHkgYXV0byBpbml0LlxyXG5cdGlmIChkLnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJykge1xyXG5cdFx0ZC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgd3BiY19zbGlkZXJfbGVuX2dyb3Vwc19fYXV0b19pbml0LCB7IG9uY2U6IHRydWUgfSk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHdwYmNfc2xpZGVyX2xlbl9ncm91cHNfX2F1dG9faW5pdCgpO1xyXG5cdH1cclxuXHJcbn0pKHdpbmRvdywgZG9jdW1lbnQpO1xyXG4iLCIvKiBnbG9iYWxzIHdpbmRvdywgZG9jdW1lbnQgKi9cclxuLyoqXHJcbiAqIFdQQkMgU2xpZGVyIFJhbmdlIEdyb3Vwc1xyXG4gKlxyXG4gKiBVbml2ZXJzYWwsIGRlcGVuZGVuY3ktZnJlZSBjb250cm9sbGVyIHRoYXQga2VlcHMgYSBcInJhbmdlICsgbnVtYmVyXCIgcGFpciBpbiBzeW5jOlxyXG4gKiAgLSBudW1iZXIgaW5wdXQgIChkYXRhLXdwYmNfc2xpZGVyX3JhbmdlX3ZhbHVlKVxyXG4gKiAgLSByYW5nZSBzbGlkZXIgIChkYXRhLXdwYmNfc2xpZGVyX3JhbmdlX3JhbmdlKVxyXG4gKiAgLSB3cml0ZXIgaW5wdXQgIChkYXRhLXdwYmNfc2xpZGVyX3JhbmdlX3dyaXRlcikgW29wdGlvbmFsXVxyXG4gKlxyXG4gKiBJZiB3cml0ZXIgZXhpc3RzOiBudW1iZXIvc2xpZGVyIHVwZGF0ZSB3cml0ZXIgYW5kIGVtaXQgJ2lucHV0JyBvbiB3cml0ZXIgKGJ1YmJsZXMpLlxyXG4gKiBJZiB3cml0ZXIgaXMgbWlzc2luZzogZW1pdHMgJ2lucHV0JyBvbiB0aGUgbnVtYmVyIGlucHV0LlxyXG4gKiBJZiB3cml0ZXIgY2hhbmdlcyBleHRlcm5hbGx5OiB1cGRhdGVzIG51bWJlci9zbGlkZXIuXHJcbiAqXHJcbiAqIE1hcmt1cCBleHBlY3RhdGlvbnMgKG1pbmltYWwpOlxyXG4gKiAgPGRpdiBjbGFzcz1cIndwYmNfc2xpZGVyX3JhbmdlX2dyb3VwXCI+XHJcbiAqICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCIgZGF0YS13cGJjX3NsaWRlcl9yYW5nZV92YWx1ZT5cclxuICogICAgPGlucHV0IHR5cGU9XCJyYW5nZVwiICBkYXRhLXdwYmNfc2xpZGVyX3JhbmdlX3JhbmdlPlxyXG4gKiAgICA8IS0tIG9wdGlvbmFsIC0tPlxyXG4gKiAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBkYXRhLXdwYmNfc2xpZGVyX3JhbmdlX3dyaXRlciBzdHlsZT1cImRpc3BsYXk6bm9uZTtcIj5cclxuICogIDwvZGl2PlxyXG4gKlxyXG4gKiBQZXJmb3JtYW5jZSBub3RlczpcclxuICogLSBNdXRhdGlvbk9ic2VydmVyIGlzIERJU0FCTEVEIGJ5IGRlZmF1bHQuXHJcbiAqIC0gSWYgeW91ciBVSSByZS1yZW5kZXJzIGFuZCBpbnNlcnRzIG5ldyBncm91cHMgZHluYW1pY2FsbHksIGNhbGw6XHJcbiAqICAgICBXUEJDX1NsaWRlcl9SYW5nZV9BdXRvSW5pdCgpOyBPUiBpbnN0YW5jZS5yZWZyZXNoKCk7XHJcbiAqICAgT3IgZW5hYmxlIG9ic2VydmVyIHZpYTogbmV3IFdQQkNfU2xpZGVyX1JhbmdlX0dyb3Vwcyhyb290LCB7IGVuYWJsZV9vYnNlcnZlcjp0cnVlIH0pLmluaXQoKTtcclxuICpcclxuICogUHVibGljIEFQSSAoaW5zdGFuY2UgbWV0aG9kcyk6XHJcbiAqICAtIGluaXQoKSwgZGVzdHJveSgpLCByZWZyZXNoKClcclxuICpcclxuICogQHZlcnNpb24gMjAyNi0wMS0yNVxyXG4gKiBAc2luY2UgICAyMDI2LTAxLTI1XHJcbiAqIEBmaWxlICAgIC4uL2luY2x1ZGVzL19fanMvYWRtaW4vc2xpZGVyX2dyb3Vwcy93cGJjX3JhbmdlX2dyb3Vwcy5qc1xyXG4gKi9cclxuKGZ1bmN0aW9uICh3LCBkKSB7XHJcblx0J3VzZSBzdHJpY3QnO1xyXG5cclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gSGVscGVyc1xyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRmdW5jdGlvbiBjbGFtcF9udW0odiwgbWluLCBtYXgpIHtcclxuXHRcdGlmICh0eXBlb2YgbWluID09PSAnbnVtYmVyJyAmJiAhaXNOYU4obWluKSkgdiA9IE1hdGgubWF4KG1pbiwgdik7XHJcblx0XHRpZiAodHlwZW9mIG1heCA9PT0gJ251bWJlcicgJiYgIWlzTmFOKG1heCkpIHYgPSBNYXRoLm1pbihtYXgsIHYpO1xyXG5cdFx0cmV0dXJuIHY7XHJcblx0fVxyXG5cclxuXHRmdW5jdGlvbiBwYXJzZV9mbG9hdCh2KSB7XHJcblx0XHR2YXIgbiA9IHBhcnNlRmxvYXQodik7XHJcblx0XHRyZXR1cm4gaXNOYU4obikgPyBudWxsIDogbjtcclxuXHR9XHJcblxyXG5cdGZ1bmN0aW9uIGVtaXRfaW5wdXQoZWwpIHtcclxuXHRcdGlmICghZWwpIHJldHVybjtcclxuXHRcdGVsLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdpbnB1dCcsIHsgYnViYmxlczogdHJ1ZSB9KSk7XHJcblx0fVxyXG5cclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0Ly8gQ29udHJvbGxlclxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRjbGFzcyBXUEJDX1NsaWRlcl9SYW5nZV9Hcm91cHMge1xyXG5cclxuXHRcdC8qKlxyXG5cdFx0ICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IHJvb3RfZWwgQ29udGFpbmVyIChvciBzZWxlY3RvcikuIElmIG9taXR0ZWQsIHVzZXMgZG9jdW1lbnQuXHJcblx0XHQgKiBAcGFyYW0ge09iamVjdH0gW29wdHM9e31dXHJcblx0XHQgKi9cclxuXHRcdGNvbnN0cnVjdG9yKHJvb3RfZWwsIG9wdHMpIHtcclxuXHRcdFx0dGhpcy5yb290ID0gcm9vdF9lbFxyXG5cdFx0XHRcdD8gKCh0eXBlb2Ygcm9vdF9lbCA9PT0gJ3N0cmluZycpID8gZC5xdWVyeVNlbGVjdG9yKHJvb3RfZWwpIDogcm9vdF9lbClcclxuXHRcdFx0XHQ6IGQ7XHJcblxyXG5cdFx0XHR0aGlzLm9wdHMgPSBPYmplY3QuYXNzaWduKHtcclxuXHRcdFx0XHQvLyBTdHJpY3Qgc2VsZWN0b3JzIChOTyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5KS5cclxuXHRcdFx0XHRncm91cF9zZWxlY3RvciAgOiAnLndwYmNfc2xpZGVyX3JhbmdlX2dyb3VwJyxcclxuXHRcdFx0XHR2YWx1ZV9zZWxlY3RvciAgOiAnW2RhdGEtd3BiY19zbGlkZXJfcmFuZ2VfdmFsdWVdJyxcclxuXHRcdFx0XHRyYW5nZV9zZWxlY3RvciAgOiAnW2RhdGEtd3BiY19zbGlkZXJfcmFuZ2VfcmFuZ2VdJyxcclxuXHRcdFx0XHR3cml0ZXJfc2VsZWN0b3IgOiAnW2RhdGEtd3BiY19zbGlkZXJfcmFuZ2Vfd3JpdGVyXScsXHJcblxyXG5cdFx0XHRcdC8vIERpc2FibGVkIGJ5IGRlZmF1bHQgZm9yIHBlcmZvcm1hbmNlLlxyXG5cdFx0XHRcdGVuYWJsZV9vYnNlcnZlciAgICAgOiBmYWxzZSxcclxuXHRcdFx0XHRvYnNlcnZlcl9kZWJvdW5jZV9tczogMTUwXHJcblx0XHRcdH0sIG9wdHMgfHwge30pO1xyXG5cclxuXHRcdFx0dGhpcy5fb25faW5wdXQgID0gdGhpcy5fb25faW5wdXQuYmluZCh0aGlzKTtcclxuXHRcdFx0dGhpcy5fb25fY2hhbmdlID0gdGhpcy5fb25fY2hhbmdlLmJpbmQodGhpcyk7XHJcblxyXG5cdFx0XHR0aGlzLl9vYnNlcnZlciAgICA9IG51bGw7XHJcblx0XHRcdHRoaXMuX3JlZnJlc2hfdG1yID0gbnVsbDtcclxuXHRcdH1cclxuXHJcblx0XHRpbml0KCkge1xyXG5cdFx0XHRpZiAoIXRoaXMucm9vdCkgcmV0dXJuIHRoaXM7XHJcblxyXG5cdFx0XHR0aGlzLnJvb3QuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCAgdGhpcy5fb25faW5wdXQsICB0cnVlKTtcclxuXHRcdFx0dGhpcy5yb290LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIHRoaXMuX29uX2NoYW5nZSwgdHJ1ZSk7XHJcblxyXG5cdFx0XHRpZiAodGhpcy5vcHRzLmVuYWJsZV9vYnNlcnZlciAmJiB3Lk11dGF0aW9uT2JzZXJ2ZXIpIHtcclxuXHRcdFx0XHR0aGlzLl9vYnNlcnZlciA9IG5ldyBNdXRhdGlvbk9ic2VydmVyKCgpID0+IHsgdGhpcy5fZGVib3VuY2VkX3JlZnJlc2goKTsgfSk7XHJcblx0XHRcdFx0dGhpcy5fb2JzZXJ2ZXIub2JzZXJ2ZSh0aGlzLnJvb3QgPT09IGQgPyBkLmRvY3VtZW50RWxlbWVudCA6IHRoaXMucm9vdCwgeyBjaGlsZExpc3Q6IHRydWUsIHN1YnRyZWU6IHRydWUgfSk7XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdHRoaXMucmVmcmVzaCgpO1xyXG5cdFx0XHRyZXR1cm4gdGhpcztcclxuXHRcdH1cclxuXHJcblx0XHRkZXN0cm95KCkge1xyXG5cdFx0XHRpZiAoIXRoaXMucm9vdCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dGhpcy5yb290LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2lucHV0JywgIHRoaXMuX29uX2lucHV0LCAgdHJ1ZSk7XHJcblx0XHRcdHRoaXMucm9vdC5yZW1vdmVFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCB0aGlzLl9vbl9jaGFuZ2UsIHRydWUpO1xyXG5cclxuXHRcdFx0aWYgKHRoaXMuX29ic2VydmVyKSB7XHJcblx0XHRcdFx0dGhpcy5fb2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xyXG5cdFx0XHRcdHRoaXMuX29ic2VydmVyID0gbnVsbDtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0aWYgKHRoaXMuX3JlZnJlc2hfdG1yKSB7XHJcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlZnJlc2hfdG1yKTtcclxuXHRcdFx0XHR0aGlzLl9yZWZyZXNoX3RtciA9IG51bGw7XHJcblx0XHRcdH1cclxuXHRcdH1cclxuXHJcblx0XHRyZWZyZXNoKCkge1xyXG5cdFx0XHRpZiAoIXRoaXMucm9vdCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIHNjb3BlICA9ICh0aGlzLnJvb3QgPT09IGQgPyBkIDogdGhpcy5yb290KTtcclxuXHRcdFx0dmFyIGdyb3VwcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHNjb3BlLnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5vcHRzLmdyb3VwX3NlbGVjdG9yKSk7XHJcblxyXG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGdyb3Vwcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHRcdHRoaXMuX3N5bmNfZnJvbV93cml0ZXIoZ3JvdXBzW2ldKTtcclxuXHRcdFx0XHR0aGlzLl9jbGFtcF90b19yYW5nZShncm91cHNbaV0pO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG5cdFx0Ly8gSW50ZXJuYWxcclxuXHRcdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHRcdF9kZWJvdW5jZWRfcmVmcmVzaCgpIHtcclxuXHRcdFx0aWYgKHRoaXMuX3JlZnJlc2hfdG1yKSBjbGVhclRpbWVvdXQodGhpcy5fcmVmcmVzaF90bXIpO1xyXG5cdFx0XHR0aGlzLl9yZWZyZXNoX3RtciA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG5cdFx0XHRcdHRoaXMuX3JlZnJlc2hfdG1yID0gbnVsbDtcclxuXHRcdFx0XHR0aGlzLnJlZnJlc2goKTtcclxuXHRcdFx0fSwgTnVtYmVyKHRoaXMub3B0cy5vYnNlcnZlcl9kZWJvdW5jZV9tcykgfHwgMCk7XHJcblx0XHR9XHJcblxyXG5cdFx0X2ZpbmRfZ3JvdXAoZWwpIHtcclxuXHRcdFx0cmV0dXJuIChlbCAmJiBlbC5jbG9zZXN0KSA/IGVsLmNsb3Nlc3QodGhpcy5vcHRzLmdyb3VwX3NlbGVjdG9yKSA6IG51bGw7XHJcblx0XHR9XHJcblxyXG5cdFx0X2dldF9wYXJ0cyhncm91cCkge1xyXG5cdFx0XHRpZiAoIWdyb3VwKSByZXR1cm4gbnVsbDtcclxuXHRcdFx0cmV0dXJuIHtcclxuXHRcdFx0XHRncm91cCA6IGdyb3VwLFxyXG5cdFx0XHRcdG51bSAgIDogZ3JvdXAucXVlcnlTZWxlY3Rvcih0aGlzLm9wdHMudmFsdWVfc2VsZWN0b3IpLFxyXG5cdFx0XHRcdHJhbmdlIDogZ3JvdXAucXVlcnlTZWxlY3Rvcih0aGlzLm9wdHMucmFuZ2Vfc2VsZWN0b3IpLFxyXG5cdFx0XHRcdHdyaXRlcjogZ3JvdXAucXVlcnlTZWxlY3Rvcih0aGlzLm9wdHMud3JpdGVyX3NlbGVjdG9yKVxyXG5cdFx0XHR9O1xyXG5cdFx0fVxyXG5cclxuXHRcdF93cml0ZShwYXJ0cywgdmFsdWUsIGVtaXQpIHtcclxuXHRcdFx0aWYgKCFwYXJ0cykgcmV0dXJuO1xyXG5cclxuXHRcdFx0aWYgKHBhcnRzLndyaXRlcikge1xyXG5cdFx0XHRcdHBhcnRzLndyaXRlci5fX3dwYmNfc2xpZGVyX3JhbmdlX2ludGVybmFsID0gdHJ1ZTtcclxuXHRcdFx0XHRwYXJ0cy53cml0ZXIudmFsdWUgPSBTdHJpbmcodmFsdWUpO1xyXG5cdFx0XHRcdGlmIChlbWl0KSBlbWl0X2lucHV0KHBhcnRzLndyaXRlcik7XHJcblx0XHRcdFx0cGFydHMud3JpdGVyLl9fd3BiY19zbGlkZXJfcmFuZ2VfaW50ZXJuYWwgPSBmYWxzZTtcclxuXHRcdFx0fSBlbHNlIGlmIChwYXJ0cy5udW0pIHtcclxuXHRcdFx0XHQvLyBJZiB3cml0ZXIgaXMgbWlzc2luZywgYXQgbGVhc3Qgbm90aWZ5IHZpYSBudW1iZXIgaW5wdXQuXHJcblx0XHRcdFx0aWYgKGVtaXQpIGVtaXRfaW5wdXQocGFydHMubnVtKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdF9zeW5jX2Zyb21fd3JpdGVyKGdyb3VwKSB7XHJcblx0XHRcdHZhciBwYXJ0cyA9IHRoaXMuX2dldF9wYXJ0cyhncm91cCk7XHJcblx0XHRcdGlmICghcGFydHMgfHwgIXBhcnRzLndyaXRlcikgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIHJhdyA9IFN0cmluZyhwYXJ0cy53cml0ZXIudmFsdWUgfHwgJycpLnRyaW0oKTtcclxuXHRcdFx0aWYgKCFyYXcpIHJldHVybjtcclxuXHJcblx0XHRcdGlmIChwYXJ0cy5udW0pICAgcGFydHMubnVtLnZhbHVlICAgPSByYXc7XHJcblx0XHRcdGlmIChwYXJ0cy5yYW5nZSkgcGFydHMucmFuZ2UudmFsdWUgPSByYXc7XHJcblx0XHR9XHJcblxyXG5cdFx0X2NsYW1wX3RvX3JhbmdlKGdyb3VwKSB7XHJcblx0XHRcdHZhciBwYXJ0cyA9IHRoaXMuX2dldF9wYXJ0cyhncm91cCk7XHJcblx0XHRcdGlmICghcGFydHMgfHwgIXBhcnRzLnJhbmdlIHx8ICFwYXJ0cy5udW0pIHJldHVybjtcclxuXHJcblx0XHRcdHZhciB2ID0gcGFyc2VfZmxvYXQocGFydHMubnVtLnZhbHVlKTtcclxuXHRcdFx0aWYgKHYgPT0gbnVsbCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIG1pbiA9IE51bWJlcihwYXJ0cy5yYW5nZS5taW4pO1xyXG5cdFx0XHR2YXIgbWF4ID0gTnVtYmVyKHBhcnRzLnJhbmdlLm1heCk7XHJcblx0XHRcdHZhciB2diAgPSBjbGFtcF9udW0odiwgaXNOYU4obWluKSA/IG51bGwgOiBtaW4sIGlzTmFOKG1heCkgPyBudWxsIDogbWF4KTtcclxuXHJcblx0XHRcdGlmIChTdHJpbmcodnYpICE9PSBwYXJ0cy5udW0udmFsdWUpIHBhcnRzLm51bS52YWx1ZSA9IFN0cmluZyh2dik7XHJcblx0XHRcdHBhcnRzLnJhbmdlLnZhbHVlID0gU3RyaW5nKHZ2KTtcclxuXHRcdH1cclxuXHJcblx0XHRfb25faW5wdXQoZXYpIHtcclxuXHRcdFx0dmFyIHQgPSBldi50YXJnZXQ7XHJcblx0XHRcdGlmICghdCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIGdyb3VwID0gdGhpcy5fZmluZF9ncm91cCh0KTtcclxuXHRcdFx0aWYgKCFncm91cCkgcmV0dXJuO1xyXG5cclxuXHRcdFx0dmFyIHBhcnRzID0gdGhpcy5fZ2V0X3BhcnRzKGdyb3VwKTtcclxuXHRcdFx0aWYgKCFwYXJ0cykgcmV0dXJuO1xyXG5cclxuXHRcdFx0Ly8gV3JpdGVyIGNoYW5nZWQgZXh0ZXJuYWxseSAtPiB1cGRhdGUgVUkuXHJcblx0XHRcdGlmIChwYXJ0cy53cml0ZXIgJiYgdCA9PT0gcGFydHMud3JpdGVyKSB7XHJcblx0XHRcdFx0aWYgKHQuX193cGJjX3NsaWRlcl9yYW5nZV9pbnRlcm5hbCkgcmV0dXJuO1xyXG5cdFx0XHRcdHRoaXMuX3N5bmNfZnJvbV93cml0ZXIoZ3JvdXApO1xyXG5cdFx0XHRcdHRoaXMuX2NsYW1wX3RvX3JhbmdlKGdyb3VwKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIFJhbmdlIG1vdmVkIC0+IHVwZGF0ZSBudW1iZXIgKyB3cml0ZXIuXHJcblx0XHRcdGlmICh0Lm1hdGNoZXMgJiYgdC5tYXRjaGVzKHRoaXMub3B0cy5yYW5nZV9zZWxlY3RvcikpIHtcclxuXHRcdFx0XHRpZiAocGFydHMubnVtKSBwYXJ0cy5udW0udmFsdWUgPSB0LnZhbHVlO1xyXG5cdFx0XHRcdHRoaXMuX3dyaXRlKHBhcnRzLCB0LnZhbHVlLCAvKmVtaXQqLyB0cnVlKTtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHJcblx0XHRcdC8vIE51bWJlciB0eXBlZCAtPiB1cGRhdGUgcmFuZ2UgKyB3cml0ZXIgKGNsYW1wIGJ5IHNsaWRlciBib3VuZHMpLlxyXG5cdFx0XHRpZiAodC5tYXRjaGVzICYmIHQubWF0Y2hlcyh0aGlzLm9wdHMudmFsdWVfc2VsZWN0b3IpKSB7XHJcblx0XHRcdFx0aWYgKHBhcnRzLnJhbmdlKSB7XHJcblx0XHRcdFx0XHR2YXIgdiA9IHBhcnNlX2Zsb2F0KHQudmFsdWUpO1xyXG5cdFx0XHRcdFx0aWYgKHYgIT0gbnVsbCkge1xyXG5cdFx0XHRcdFx0XHR2YXIgbWluID0gTnVtYmVyKHBhcnRzLnJhbmdlLm1pbik7XHJcblx0XHRcdFx0XHRcdHZhciBtYXggPSBOdW1iZXIocGFydHMucmFuZ2UubWF4KTtcclxuXHRcdFx0XHRcdFx0diA9IGNsYW1wX251bSh2LCBpc05hTihtaW4pID8gbnVsbCA6IG1pbiwgaXNOYU4obWF4KSA/IG51bGwgOiBtYXgpO1xyXG5cclxuXHRcdFx0XHRcdFx0cGFydHMucmFuZ2UudmFsdWUgPSBTdHJpbmcodik7XHJcblx0XHRcdFx0XHRcdGlmIChTdHJpbmcodikgIT09IHQudmFsdWUpIHQudmFsdWUgPSBTdHJpbmcodik7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHRoaXMuX3dyaXRlKHBhcnRzLCB0LnZhbHVlLCAvKmVtaXQqLyB0cnVlKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdF9vbl9jaGFuZ2UoZXYpIHtcclxuXHRcdFx0Ly8gTm8gc3BlY2lhbCBcImNoYW5nZVwiIGhhbmRsaW5nIG5lZWRlZCBjdXJyZW50bHk7IGtlcHQgZm9yIHN5bW1ldHJ5L2Z1dHVyZS5cclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuXHQvLyBBdXRvLWluaXRcclxuXHQvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0ZnVuY3Rpb24gd3BiY19zbGlkZXJfcmFuZ2VfZ3JvdXBzX19hdXRvX2luaXQoKSB7XHJcblx0XHR2YXIgUk9PVCAgPSAnLndwYmNfc2xpZGVyX3JhbmdlX2dyb3Vwcyc7XHJcblx0XHR2YXIgbm9kZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChkLnF1ZXJ5U2VsZWN0b3JBbGwoUk9PVCkpXHJcblx0XHRcdC5maWx0ZXIoZnVuY3Rpb24gKG4pIHsgcmV0dXJuICFuLnBhcmVudEVsZW1lbnQgfHwgIW4ucGFyZW50RWxlbWVudC5jbG9zZXN0KFJPT1QpOyB9KTtcclxuXHJcblx0XHRpZiAoIW5vZGVzLmxlbmd0aCkge1xyXG5cdFx0XHRpZiAoIWQuX193cGJjX3NsaWRlcl9yYW5nZV9ncm91cHNfZ2xvYmFsX2luc3RhbmNlKSB7XHJcblx0XHRcdFx0ZC5fX3dwYmNfc2xpZGVyX3JhbmdlX2dyb3Vwc19nbG9iYWxfaW5zdGFuY2UgPSBuZXcgV1BCQ19TbGlkZXJfUmFuZ2VfR3JvdXBzKGQpLmluaXQoKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRyZXR1cm47XHJcblx0XHR9XHJcblxyXG5cdFx0bm9kZXMuZm9yRWFjaChmdW5jdGlvbiAobm9kZSkge1xyXG5cdFx0XHRpZiAobm9kZS5fX3dwYmNfc2xpZGVyX3JhbmdlX2dyb3Vwc19pbnN0YW5jZSkgcmV0dXJuO1xyXG5cdFx0XHRub2RlLl9fd3BiY19zbGlkZXJfcmFuZ2VfZ3JvdXBzX2luc3RhbmNlID0gbmV3IFdQQkNfU2xpZGVyX1JhbmdlX0dyb3Vwcyhub2RlKS5pbml0KCk7XHJcblx0XHR9KTtcclxuXHR9XHJcblxyXG5cdC8vIEV4cG9ydCBnbG9iYWxzLlxyXG5cdHcuV1BCQ19TbGlkZXJfUmFuZ2VfR3JvdXBzICAgPSBXUEJDX1NsaWRlcl9SYW5nZV9Hcm91cHM7XHJcblx0dy5XUEJDX1NsaWRlcl9SYW5nZV9BdXRvSW5pdCA9IHdwYmNfc2xpZGVyX3JhbmdlX2dyb3Vwc19fYXV0b19pbml0O1xyXG5cclxuXHRpZiAoZC5yZWFkeVN0YXRlID09PSAnbG9hZGluZycpIHtcclxuXHRcdGQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIHdwYmNfc2xpZGVyX3JhbmdlX2dyb3Vwc19fYXV0b19pbml0LCB7IG9uY2U6IHRydWUgfSk7XHJcblx0fSBlbHNlIHtcclxuXHRcdHdwYmNfc2xpZGVyX3JhbmdlX2dyb3Vwc19fYXV0b19pbml0KCk7XHJcblx0fVxyXG5cclxufSkod2luZG93LCBkb2N1bWVudCk7XHJcbiIsIi8qKlxyXG4gKiBCb29raW5nIENhbGVuZGFyIOKAlCBHZW5lcmljIFVJIFRhYnMgVXRpbGl0eSAoSlMpXHJcbiAqXHJcbiAqIFB1cnBvc2U6IExpZ2h0d2VpZ2h0LCBkZXBlbmRlbmN5LWZyZWUgdGFicyBjb250cm9sbGVyIGZvciBhbnkgc21hbGwgdGFiIGdyb3VwIGluIGFkbWluIFVJcy5cclxuICogLSBBdXRvLWluaXRpYWxpemVzIGdyb3VwcyBtYXJrZWQgd2l0aCBkYXRhLXdwYmMtdGFicy5cclxuICogLSBBc3NpZ25zIEFSSUEgcm9sZXMgYW5kIHRvZ2dsZXMgYXJpYS1zZWxlY3RlZC9hcmlhLWhpZGRlbi90YWJpbmRleC5cclxuICogLSBTdXBwb3J0cyBrZXlib2FyZCBuYXZpZ2F0aW9uIChMZWZ0L1JpZ2h0L0hvbWUvRW5kKS5cclxuICogLSBQdWJsaWMgQVBJOiB3aW5kb3cud3BiY191aV90YWJzLntpbml0X29uLCBpbml0X2dyb3VwLCBzZXRfYWN0aXZlfVxyXG4gKiAtIEVtaXRzICd3cGJjOnRhYnM6Y2hhbmdlJyBvbiB0aGUgZ3JvdXAgcm9vdCB3aGVuIHRoZSBhY3RpdmUgdGFiIGNoYW5nZXMuXHJcbiAqXHJcbiAqIE1hcmt1cCBjb250cmFjdDpcclxuICogLSBSb290OiAgIFtkYXRhLXdwYmMtdGFic11cclxuICogLSBUYWJzOiAgIFtkYXRhLXdwYmMtdGFiLWtleT1cIktcIl1cclxuICogLSBQYW5lbHM6IFtkYXRhLXdwYmMtdGFiLXBhbmVsPVwiS1wiXVxyXG4gKlxyXG4gKiBAcGFja2FnZSAgIEJvb2tpbmcgQ2FsZW5kYXJcclxuICogQHN1YnBhY2thZ2UgQWRtaW5cXFVJXHJcbiAqIEBzaW5jZSAgICAgMTEuMC4wXHJcbiAqIEB2ZXJzaW9uICAgMS4wLjBcclxuICogQHNlZSAgICAgICAvaW5jbHVkZXMvX19qcy9hZG1pbi91aV90YWJzL3VpX3RhYnMuanNcclxuICpcclxuICpcclxuICogSG93IGl0IHdvcmtzOlxyXG4gKiAtIFJvb3Qgbm9kZSBtdXN0IGhhdmUgW2RhdGEtd3BiYy10YWJzXSBhdHRyaWJ1dGUgKGFueSB2YWx1ZSkuXHJcbiAqIC0gVGFiIGJ1dHRvbnMgbXVzdCBjYXJyeSBbZGF0YS13cGJjLXRhYi1rZXk9XCIuLi5cIl0gKHVuaXF1ZSBwZXIgZ3JvdXApLlxyXG4gKiAtIFBhbmVscyBtdXN0IGNhcnJ5IFtkYXRhLXdwYmMtdGFiLXBhbmVsPVwiLi4uXCJdIHdpdGggbWF0Y2hpbmcga2V5cy5cclxuICogLSBBZGRzIFdBSS1BUklBIHJvbGVzIGFuZCBhcmlhLXNlbGVjdGVkL2hpZGRlbiB3aXJpbmcuXHJcbiAqXHJcbiAqIDxkaXYgZGF0YS13cGJjLXRhYnM9XCJjb2x1bW4tc3R5bGVzXCIgZGF0YS13cGJjLXRhYi1hY3RpdmU9XCIxXCIgICAgY2xhc3M9XCJ3cGJjX3VpX3RhYnNfcm9vdFwiID5cclxuICogICAgPCEtLSBUb3AgVGFicyAtLT5cclxuICogICAgPGRpdiBkYXRhLXdwYmMtdGFibGlzdD1cIlwiIHJvbGU9XCJ0YWJsaXN0XCIgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiIHdwYmNfdWlfZWxfX2hvcmlzX3RvcF9iYXJfX3dyYXBwZXJcIiA+XHJcbiAqICAgICAgICA8ZGl2IGNsYXNzPVwid3BiY191aV9lbF9faG9yaXNfdG9wX2Jhcl9fY29udGVudFwiPlxyXG4gKiAgICAgICAgICAgIDxoMiBjbGFzcz1cIndwYmNfdWlfZWxfX2hvcmlzX25hdl9sYWJlbFwiPkNvbHVtbjo8L2gyPlxyXG4gKlxyXG4gKiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cGJjX3VpX2VsX19ob3Jpc19uYXZfaXRlbSB3cGJjX3VpX2VsX19ob3Jpc19uYXZfaXRlbV9fMVwiPlxyXG4gKiAgICAgICAgICAgICAgICA8YVxyXG4gKiAgICAgICAgICAgICAgICAgICAgZGF0YS13cGJjLXRhYi1rZXk9XCIxXCJcclxuICogICAgICAgICAgICAgICAgICAgIGFyaWEtc2VsZWN0ZWQ9XCJ0cnVlXCIgcm9sZT1cInRhYlwiIHRhYmluZGV4PVwiMFwiIGFyaWEtY29udHJvbHM9XCJ3cGJjX3RhYl9wYW5lbF9jb2xfMVwiXHJcbiAqXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgaHJlZj1cImphdmFzY3JpcHQ6dm9pZCgwKTtcIlxyXG4gKiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwid3BiY191aV9lbF9faG9yaXNfbmF2X2l0ZW1fX2Egd3BiY191aV9lbF9faG9yaXNfbmF2X2l0ZW1fX3NpbmdsZVwiXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgaWQ9XCJ3cGJjX3RhYl9jb2xfMVwiXHJcbiAqICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9XCJDb2x1bW4gMVwiXHJcbiAqICAgICAgICAgICAgICAgID48c3BhbiBjbGFzcz1cIndwYmNfdWlfZWxfX2hvcmlzX25hdl90aXRsZVwiPlRpdGxlIDE8L3NwYW4+PC9hPlxyXG4gKiAgICAgICAgICAgIDwvZGl2PlxyXG4gKiAgICAgICAgICAgIC4uLlxyXG4gKiAgICAgICAgPC9kaXY+XHJcbiAqICAgIDwvZGl2PlxyXG4gKiAgICA8IS0tIFRhYnMgQ29udGVudCAtLT5cclxuICogICAgPGRpdiBjbGFzcz1cIndwYmNfdGFiX19wYW5lbCBncm91cF9fZmllbGRzXCIgZGF0YS13cGJjLXRhYi1wYW5lbD1cIjFcIiBpZD1cIndwYmNfdGFiX3BhbmVsX2NvbF8xXCIgcm9sZT1cInRhYnBhbmVsXCIgYXJpYS1sYWJlbGxlZGJ5PVwid3BiY190YWJfY29sXzFcIj5cclxuICogICAgICAgIC4uLlxyXG4gKiAgICA8L2Rpdj5cclxuICogICAgLi4uXHJcbiAqIDwvZGl2PlxyXG4gKlxyXG4gKiBQdWJsaWMgQVBJOlxyXG4gKiAgIC0gd3BiY191aV90YWJzLmluaXRfb24ocm9vdF9vcl9zZWxlY3RvcikgICAvLyBmaW5kIGFuZCBpbml0IGdyb3VwcyB3aXRoaW4gYSBjb250YWluZXJcclxuICogICAtIHdwYmNfdWlfdGFicy5pbml0X2dyb3VwKHJvb3RfZWwpICAgICAgICAgLy8gaW5pdCBhIHNpbmdsZSBncm91cCByb290XHJcbiAqICAgLSB3cGJjX3VpX3RhYnMuc2V0X2FjdGl2ZShyb290X2VsLCBrZXkpICAgIC8vIHByb2dyYW1tYXRpY2FsbHkgY2hhbmdlIGFjdGl2ZSB0YWJcclxuICpcclxuICogRXZlbnRzOlxyXG4gKiAgIC0gRGlzcGF0Y2hlcyBDdXN0b21FdmVudCAnd3BiYzp0YWJzOmNoYW5nZScgb24gcm9vdCB3aGVuIHRhYiBjaGFuZ2VzOlxyXG4gKiAgICAgICBkZXRhaWw6IHsgYWN0aXZlX2tleTogJzInLCBwcmV2X2tleTogJzEnIH1cclxuICpcclxuICogU3dpdGNoIGEgbG9jYWwgKGdlbmVyaWMpIHRhYnMgZ3JvdXAgdG8gdGFiIDM6ICAgICB2YXIgZ3JvdXAgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdbZGF0YS13cGJjLXRhYnM9XCJjb2x1bW4tc3R5bGVzXCJdJyk7IGlmICggZ3JvdXAgKSB7IHdwYmNfdWlfdGFicy5zZXRfYWN0aXZlKGdyb3VwLCAnMycpOyB9XHJcbiAqL1xyXG4oZnVuY3Rpb24gKCB3ICkge1xyXG5cdCd1c2Ugc3RyaWN0JztcclxuXHJcblx0aWYgKCB3LndwYmNfdWlfdGFicyApIHtcclxuXHRcdHJldHVybjtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEludGVybmFsOiB0b2dnbGUgYWN0aXZlIHN0YXRlLlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcm9vdF9lbFxyXG5cdCAqIEBwYXJhbSB7c3RyaW5nfSAgICAgIGtleVxyXG5cdCAqIEBwYXJhbSB7Ym9vbGVhbn0gICAgIHNob3VsZF9lbWl0XHJcblx0ICovXHJcblx0ZnVuY3Rpb24gc2V0X2FjdGl2ZV9pbnRlcm5hbCggcm9vdF9lbCwga2V5LCBzaG91bGRfZW1pdCApIHtcclxuXHRcdHZhciB0YWJfYnRucyA9IHJvb3RfZWwucXVlcnlTZWxlY3RvckFsbCggJ1tkYXRhLXdwYmMtdGFiLWtleV0nICk7XHJcblx0XHR2YXIgcGFuZWxzICAgPSByb290X2VsLnF1ZXJ5U2VsZWN0b3JBbGwoICdbZGF0YS13cGJjLXRhYi1wYW5lbF0nICk7XHJcblxyXG5cdFx0dmFyIHByZXZfa2V5ID0gcm9vdF9lbC5nZXRBdHRyaWJ1dGUoICdkYXRhLXdwYmMtdGFiLWFjdGl2ZScgKSB8fCBudWxsO1xyXG5cdFx0aWYgKCBTdHJpbmcoIHByZXZfa2V5ICkgPT09IFN0cmluZygga2V5ICkgKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHJcblx0XHQvLyBCdXR0b25zOiBhcmlhICsgY2xhc3NcclxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IHRhYl9idG5zLmxlbmd0aDsgaSsrICkge1xyXG5cdFx0XHR2YXIgYnRuICAgPSB0YWJfYnRuc1tpXTtcclxuXHRcdFx0dmFyIGJfa2V5ID0gYnRuLmdldEF0dHJpYnV0ZSggJ2RhdGEtd3BiYy10YWIta2V5JyApO1xyXG5cdFx0XHR2YXIgaXNfb24gPSBTdHJpbmcoIGJfa2V5ICkgPT09IFN0cmluZygga2V5ICk7XHJcblxyXG5cdFx0XHRidG4uc2V0QXR0cmlidXRlKCAncm9sZScsICd0YWInICk7XHJcblx0XHRcdGJ0bi5zZXRBdHRyaWJ1dGUoICdhcmlhLXNlbGVjdGVkJywgaXNfb24gPyAndHJ1ZScgOiAnZmFsc2UnICk7XHJcblx0XHRcdGJ0bi5zZXRBdHRyaWJ1dGUoICd0YWJpbmRleCcsIGlzX29uID8gJzAnIDogJy0xJyApO1xyXG5cclxuXHRcdFx0aWYgKCBpc19vbiApIHtcclxuXHRcdFx0XHRidG4uY2xhc3NMaXN0LmFkZCggJ2FjdGl2ZScgKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRidG4uY2xhc3NMaXN0LnJlbW92ZSggJ2FjdGl2ZScgKTtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFBhbmVsczogYXJpYSArIHZpc2liaWxpdHlcclxuXHRcdGZvciAoIHZhciBqID0gMDsgaiA8IHBhbmVscy5sZW5ndGg7IGorKyApIHtcclxuXHRcdFx0dmFyIHBuICAgPSBwYW5lbHNbal07XHJcblx0XHRcdHZhciBwa2V5ID0gcG4uZ2V0QXR0cmlidXRlKCAnZGF0YS13cGJjLXRhYi1wYW5lbCcgKTtcclxuXHRcdFx0dmFyIHNob3cgPSBTdHJpbmcoIHBrZXkgKSA9PT0gU3RyaW5nKCBrZXkgKTtcclxuXHJcblx0XHRcdHBuLnNldEF0dHJpYnV0ZSggJ3JvbGUnLCAndGFicGFuZWwnICk7XHJcblx0XHRcdHBuLnNldEF0dHJpYnV0ZSggJ2FyaWEtaGlkZGVuJywgc2hvdyA/ICdmYWxzZScgOiAndHJ1ZScgKTtcclxuXHRcdFx0aWYgKCBzaG93ICkge1xyXG5cdFx0XHRcdHBuLnJlbW92ZUF0dHJpYnV0ZSggJ2hpZGRlbicgKTtcclxuXHRcdFx0fSBlbHNlIHtcclxuXHRcdFx0XHRwbi5zZXRBdHRyaWJ1dGUoICdoaWRkZW4nLCAnJyApO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblxyXG5cdFx0cm9vdF9lbC5zZXRBdHRyaWJ1dGUoICdkYXRhLXdwYmMtdGFiLWFjdGl2ZScsIFN0cmluZygga2V5ICkgKTtcclxuXHJcblx0XHRpZiAoIHNob3VsZF9lbWl0ICkge1xyXG5cdFx0XHR0cnkge1xyXG5cdFx0XHRcdHZhciBldiA9IG5ldyB3LkN1c3RvbUV2ZW50KCAnd3BiYzp0YWJzOmNoYW5nZScsIHtcclxuXHRcdFx0XHRcdGJ1YmJsZXMgOiB0cnVlLFxyXG5cdFx0XHRcdFx0ZGV0YWlsICA6IHsgYWN0aXZlX2tleSA6IFN0cmluZygga2V5ICksIHByZXZfa2V5IDogcHJldl9rZXkgfVxyXG5cdFx0XHRcdH0gKTtcclxuXHRcdFx0XHRyb290X2VsLmRpc3BhdGNoRXZlbnQoIGV2ICk7XHJcblx0XHRcdH0gY2F0Y2ggKCBfZSApIHt9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBJbnRlcm5hbDogZ2V0IG9yZGVyZWQga2V5cyBmcm9tIGJ1dHRvbnMuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSByb290X2VsXHJcblx0ICogQHJldHVybnMge3N0cmluZ1tdfVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIGdldF9rZXlzKCByb290X2VsICkge1xyXG5cdFx0dmFyIGxpc3QgPSBbXTtcclxuXHRcdHZhciBidG5zID0gcm9vdF9lbC5xdWVyeVNlbGVjdG9yQWxsKCAnW2RhdGEtd3BiYy10YWIta2V5XScgKTtcclxuXHRcdGZvciAoIHZhciBpID0gMDsgaSA8IGJ0bnMubGVuZ3RoOyBpKysgKSB7XHJcblx0XHRcdHZhciBrID0gYnRuc1tpXS5nZXRBdHRyaWJ1dGUoICdkYXRhLXdwYmMtdGFiLWtleScgKTtcclxuXHRcdFx0aWYgKCBrICE9IG51bGwgJiYgayAhPT0gJycgKSB7XHJcblx0XHRcdFx0bGlzdC5wdXNoKCBTdHJpbmcoIGsgKSApO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbGlzdDtcclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEludGVybmFsOiBtb3ZlIGZvY3VzIGJldHdlZW4gdGFicyB1c2luZyBrZXlib2FyZC5cclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IHJvb3RfZWxcclxuXHQgKiBAcGFyYW0ge251bWJlcn0gICAgICBkaXIgICsxIChuZXh0KSAvIC0xIChwcmV2KVxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIGZvY3VzX3JlbGF0aXZlKCByb290X2VsLCBkaXIgKSB7XHJcblx0XHR2YXIga2V5cyAgICA9IGdldF9rZXlzKCByb290X2VsICk7XHJcblx0XHR2YXIgY3VycmVudCA9IHJvb3RfZWwuZ2V0QXR0cmlidXRlKCAnZGF0YS13cGJjLXRhYi1hY3RpdmUnICkgfHwga2V5c1swXSB8fCBudWxsO1xyXG5cdFx0dmFyIGlkeCAgICAgPSBNYXRoLm1heCggMCwga2V5cy5pbmRleE9mKCBTdHJpbmcoIGN1cnJlbnQgKSApICk7XHJcblx0XHR2YXIgbmV4dCAgICA9IGtleXNbICggaWR4ICsgKCBkaXIgPiAwID8gMSA6IGtleXMubGVuZ3RoIC0gMSApICkgJSBrZXlzLmxlbmd0aCBdO1xyXG5cclxuXHRcdHZhciBuZXh0X2J0biA9IHJvb3RfZWwucXVlcnlTZWxlY3RvciggJ1tkYXRhLXdwYmMtdGFiLWtleT1cIicgKyBuZXh0ICsgJ1wiXScgKTtcclxuXHRcdGlmICggbmV4dF9idG4gKSB7XHJcblx0XHRcdG5leHRfYnRuLmZvY3VzKCk7XHJcblx0XHRcdHNldF9hY3RpdmVfaW50ZXJuYWwoIHJvb3RfZWwsIG5leHQsIHRydWUgKTtcclxuXHRcdH1cclxuXHR9XHJcblxyXG5cdC8qKlxyXG5cdCAqIEluaXRpYWxpemUgYSBzaW5nbGUgdGFicyBncm91cCByb290LlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcm9vdF9lbFxyXG5cdCAqL1xyXG5cdGZ1bmN0aW9uIGluaXRfZ3JvdXAoIHJvb3RfZWwgKSB7XHJcblx0XHRpZiAoICEgcm9vdF9lbCB8fCByb290X2VsLl9fd3BiY190YWJzX2luaXRlZCApIHtcclxuXHRcdFx0cmV0dXJuO1xyXG5cdFx0fVxyXG5cdFx0cm9vdF9lbC5fX3dwYmNfdGFic19pbml0ZWQgPSB0cnVlO1xyXG5cclxuXHRcdC8vIFJvbGVzXHJcblx0XHR2YXIgdGFibGlzdCA9IHJvb3RfZWwucXVlcnlTZWxlY3RvciggJ1tkYXRhLXdwYmMtdGFibGlzdF0nICkgfHwgcm9vdF9lbDtcclxuXHRcdHRhYmxpc3Quc2V0QXR0cmlidXRlKCAncm9sZScsICd0YWJsaXN0JyApO1xyXG5cclxuXHRcdC8vIERlZmF1bHQgYWN0aXZlOiBmcm9tIGF0dHJpYnV0ZSBvciBmaXJzdCBidXR0b25cclxuXHRcdHZhciBrZXlzID0gZ2V0X2tleXMoIHJvb3RfZWwgKTtcclxuXHRcdHZhciBkZWYgID0gcm9vdF9lbC5nZXRBdHRyaWJ1dGUoICdkYXRhLXdwYmMtdGFiLWFjdGl2ZScgKSB8fCAoIGtleXNbMF0gfHwgJzEnICk7XHJcblx0XHRzZXRfYWN0aXZlX2ludGVybmFsKCByb290X2VsLCBkZWYsIGZhbHNlICk7XHJcblxyXG5cdFx0Ly8gQ2xpY2tzXHJcblx0XHRyb290X2VsLmFkZEV2ZW50TGlzdGVuZXIoICdjbGljaycsIGZ1bmN0aW9uICggZSApIHtcclxuXHRcdFx0dmFyIGJ0biA9IGUudGFyZ2V0LmNsb3Nlc3QgPyBlLnRhcmdldC5jbG9zZXN0KCAnW2RhdGEtd3BiYy10YWIta2V5XScgKSA6IG51bGw7XHJcblx0XHRcdGlmICggISBidG4gfHwgISByb290X2VsLmNvbnRhaW5zKCBidG4gKSApIHtcclxuXHRcdFx0XHRyZXR1cm47XHJcblx0XHRcdH1cclxuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cdFx0XHR2YXIga2V5ID0gYnRuLmdldEF0dHJpYnV0ZSggJ2RhdGEtd3BiYy10YWIta2V5JyApO1xyXG5cdFx0XHRpZiAoIGtleSAhPSBudWxsICkge1xyXG5cdFx0XHRcdHNldF9hY3RpdmVfaW50ZXJuYWwoIHJvb3RfZWwsIGtleSwgdHJ1ZSApO1xyXG5cdFx0XHR9XHJcblx0XHR9LCB0cnVlICk7XHJcblxyXG5cdFx0Ly8gS2V5Ym9hcmQgKExlZnQvUmlnaHQvSG9tZS9FbmQpXHJcblx0XHRyb290X2VsLmFkZEV2ZW50TGlzdGVuZXIoICdrZXlkb3duJywgZnVuY3Rpb24gKCBlICkge1xyXG5cdFx0XHR2YXIgdGd0ID0gZS50YXJnZXQ7XHJcblx0XHRcdGlmICggISB0Z3QgfHwgISB0Z3QuaGFzQXR0cmlidXRlIHx8ICEgdGd0Lmhhc0F0dHJpYnV0ZSggJ2RhdGEtd3BiYy10YWIta2V5JyApICkge1xyXG5cdFx0XHRcdHJldHVybjtcclxuXHRcdFx0fVxyXG5cdFx0XHRzd2l0Y2ggKCBlLmtleSApIHtcclxuXHRcdFx0Y2FzZSAnQXJyb3dMZWZ0JzpcclxuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7IGZvY3VzX3JlbGF0aXZlKCByb290X2VsLCAtMSApOyBicmVhaztcclxuXHRcdFx0Y2FzZSAnQXJyb3dSaWdodCc6XHJcblx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpOyBmb2N1c19yZWxhdGl2ZSggcm9vdF9lbCwgKzEgKTsgYnJlYWs7XHJcblx0XHRcdGNhc2UgJ0hvbWUnOlxyXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTsgc2V0X2FjdGl2ZV9pbnRlcm5hbCggcm9vdF9lbCwgKCBnZXRfa2V5cyggcm9vdF9lbCApWzBdIHx8ICcxJyApLCB0cnVlICk7IGJyZWFrO1xyXG5cdFx0XHRjYXNlICdFbmQnOlxyXG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTsgdmFyIGtzID0gZ2V0X2tleXMoIHJvb3RfZWwgKTsgc2V0X2FjdGl2ZV9pbnRlcm5hbCggcm9vdF9lbCwgKCBrc1sga3MubGVuZ3RoIC0gMSBdIHx8ICcxJyApLCB0cnVlICk7IGJyZWFrO1xyXG5cdFx0XHR9XHJcblx0XHR9LCB0cnVlICk7XHJcblx0fVxyXG5cclxuXHQvKipcclxuXHQgKiBJbml0aWFsaXplIGFsbCBncm91cHMgd2l0aGluIGEgY29udGFpbmVyIChvciBkb2N1bWVudCkuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ3xudWxsfSBjb250YWluZXJcclxuXHQgKi9cclxuXHRmdW5jdGlvbiBpbml0X29uKCBjb250YWluZXIgKSB7XHJcblx0XHR2YXIgY3R4ID0gY29udGFpbmVyID8gKCB0eXBlb2YgY29udGFpbmVyID09PSAnc3RyaW5nJyA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIGNvbnRhaW5lciApIDogY29udGFpbmVyICkgOiBkb2N1bWVudDtcclxuXHRcdGlmICggISBjdHggKSB7XHJcblx0XHRcdHJldHVybjtcclxuXHRcdH1cclxuXHRcdHZhciBncm91cHMgPSBjdHgucXVlcnlTZWxlY3RvckFsbCggJ1tkYXRhLXdwYmMtdGFic10nICk7XHJcblx0XHRmb3IgKCB2YXIgaSA9IDA7IGkgPCBncm91cHMubGVuZ3RoOyBpKysgKSB7XHJcblx0XHRcdGluaXRfZ3JvdXAoIGdyb3Vwc1tpXSApO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0LyoqXHJcblx0ICogUHJvZ3JhbW1hdGljYWxseSBzZXQgYWN0aXZlIHRhYiBieSBrZXkuXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSByb290X2VsXHJcblx0ICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSBrZXlcclxuXHQgKi9cclxuXHRmdW5jdGlvbiBzZXRfYWN0aXZlKCByb290X2VsLCBrZXkgKSB7XHJcblx0XHRpZiAoIHJvb3RfZWwgJiYgcm9vdF9lbC5oYXNBdHRyaWJ1dGUgJiYgcm9vdF9lbC5oYXNBdHRyaWJ1dGUoICdkYXRhLXdwYmMtdGFicycgKSApIHtcclxuXHRcdFx0c2V0X2FjdGl2ZV9pbnRlcm5hbCggcm9vdF9lbCwgU3RyaW5nKCBrZXkgKSwgdHJ1ZSApO1xyXG5cdFx0fVxyXG5cdH1cclxuXHJcblx0Ly8gUHVibGljIEFQSSAoc25ha2VfY2FzZSlcclxuXHR3LndwYmNfdWlfdGFicyA9IHtcclxuXHRcdGluaXRfb24gICAgOiBpbml0X29uLFxyXG5cdFx0aW5pdF9ncm91cCA6IGluaXRfZ3JvdXAsXHJcblx0XHRzZXRfYWN0aXZlIDogc2V0X2FjdGl2ZVxyXG5cdH07XHJcblxyXG5cdC8vIEF1dG8taW5pdCBvbiBET00gcmVhZHlcclxuXHRpZiAoIGRvY3VtZW50LnJlYWR5U3RhdGUgPT09ICdsb2FkaW5nJyApIHtcclxuXHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoICdET01Db250ZW50TG9hZGVkJywgZnVuY3Rpb24gKCkgeyBpbml0X29uKCBkb2N1bWVudCApOyB9ICk7XHJcblx0fSBlbHNlIHtcclxuXHRcdGluaXRfb24oIGRvY3VtZW50ICk7XHJcblx0fVxyXG5cclxufSkoIHdpbmRvdyApO1xyXG4iXX0= | |