Files
rspade_system/storage-broken/rsx-tmp/babel_d1f5a3cbd71c76e0f2d68aa98923bcd9.js
root 77b4d10af8 Refactor filename naming system and apply convention-based renames
Standardize settings file naming and relocate documentation files
Fix code quality violations from rsx:check
Reorganize user_management directory into logical subdirectories
Move Quill Bundle to core and align with Tom Select pattern
Simplify Site Settings page to focus on core site information
Complete Phase 5: Multi-tenant authentication with login flow and site selection
Add route query parameter rule and synchronize filename validation logic
Fix critical bug in UpdateNpmCommand causing missing JavaScript stubs
Implement filename convention rule and resolve VS Code auto-rename conflict
Implement js-sanitizer RPC server to eliminate 900+ Node.js process spawns
Implement RPC server architecture for JavaScript parsing
WIP: Add RPC server infrastructure for JS parsing (partial implementation)
Update jqhtml terminology from destroy to stop, fix datagrid DOM preservation
Add JQHTML-CLASS-01 rule and fix redundant class names
Improve code quality rules and resolve violations
Remove legacy fatal error format in favor of unified 'fatal' error type
Filter internal keys from window.rsxapp output
Update button styling and comprehensive form/modal documentation
Add conditional fly-in animation for modals
Fix non-deterministic bundle compilation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 19:10:02 +00:00

704 lines
76 KiB
JavaScript
Executable File

"use strict";
function _d1f5a3cb_defineProperty(e, r, t) { return (r = _d1f5a3cb_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _d1f5a3cb_toPropertyKey(t) { var i = _d1f5a3cb_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _d1f5a3cb_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
/**
* Modal Static API
*
* Primary interface for displaying modals throughout the application.
* Provides simple methods for common dialogs and flexible options for custom modals.
*
* Usage:
* await Modal.alert("File saved")
* if (await Modal.confirm("Delete?")) { ... }
* let name = await Modal.prompt("Enter name:")
* let result = await Modal.show({ title, body, buttons })
*/
class Modal {
/**
* Initialize global handlers (called automatically on first modal)
* @private
*/
static _init() {
if (this._initialized) return;
this._initialized = true;
// Create shared backdrop element
this._backdrop = $('<div class="modal-backdrop fade"></div>');
$('body').append(this._backdrop);
}
/**
* Calculate scrollbar width
* @private
* @returns {number}
*/
static _get_scrollbar_width() {
// Create temporary element to measure scrollbar width
const $outer = $('<div>').css({
visibility: 'hidden',
overflow: 'scroll',
width: '100px',
position: 'absolute',
top: '-9999px'
});
$('body').append($outer);
const width_with_scrollbar = $outer[0].offsetWidth;
const $inner = $('<div>').css('width', '100%');
$outer.append($inner);
const width_without_scrollbar = $inner[0].offsetWidth;
$outer.remove();
return width_with_scrollbar - width_without_scrollbar;
}
/**
* Lock body scroll and compensate for scrollbar width
* Only locks if we haven't already saved the original state (first modal in chain)
* @private
*/
static _lock_body_scroll() {
// Cancel any pending unlock timeout
if (this._unlock_timeout) {
clearTimeout(this._unlock_timeout);
this._unlock_timeout = null;
}
// Only lock scroll if we haven't already saved state (first modal)
// This is the true indicator - not backdrop visibility which can be transitional
if (this._original_body_overflow === null) {
const $body = $('body');
// Store original values
this._original_body_overflow = $body.css('overflow');
this._original_body_padding = $body.css('padding-right');
// Check if body currently has vertical scroll
const has_scrollbar = document.body.scrollHeight > window.innerHeight;
// If there's a scrollbar, add padding to compensate for its removal
if (has_scrollbar) {
const scrollbar_width = this._get_scrollbar_width();
const current_padding = int(this._original_body_padding) || 0;
$body.css('padding-right', current_padding + scrollbar_width + 'px');
}
// Lock scroll
$body.css('overflow', 'hidden');
}
}
/**
* Unlock body scroll and restore original state
* Uses delayed check to ensure no other modals are opening
* @private
*/
static _unlock_body_scroll() {
// Clear any existing timeout
if (this._unlock_timeout) {
clearTimeout(this._unlock_timeout);
}
// Minimal delay before unlocking
this._unlock_timeout = setTimeout(() => {
// Double-check no modal is currently open and queue is empty
if (!this._current && this._queue.length === 0) {
const $body = $('body');
// Restore original values
if (this._original_body_overflow !== null) {
$body.css('overflow', this._original_body_overflow);
this._original_body_overflow = null;
}
if (this._original_body_padding !== null) {
$body.css('padding-right', this._original_body_padding);
this._original_body_padding = null;
}
}
this._unlock_timeout = null;
}, 50); // Minimal safety buffer
}
/**
* Show the shared backdrop (instant - no animation)
* @private
*/
static async _show_backdrop() {
if (!this._backdrop.hasClass('show')) {
// Lock body scroll before showing backdrop
this._lock_body_scroll();
this._backdrop.css('display', 'block').addClass('show');
// No delay - return immediately
}
}
/**
* Hide the shared backdrop (instant - no animation)
* @private
*/
static async _hide_backdrop() {
this._backdrop.removeClass('show').css('display', 'none');
// Unlock body scroll after backdrop is hidden
this._unlock_body_scroll();
}
/**
* Create a new Rsx_Modal instance
* @private
*/
static async _create_modal() {
// Create modal component using jQuery plugin
const $modal_element = $('<div>');
// Create component instance directly (returns the component)
const modal_instance = $modal_element.component('Rsx_Modal', {});
// Wait for component to be fully ready (DOM elements queryable)
await new Promise(resolve => {
modal_instance.on('ready', () => {
console.log('[Modal] Component ready, elements:', {
title: modal_instance.$id('title').length,
body: modal_instance.$id('body').length,
footer: modal_instance.$id('footer').length
});
resolve();
});
});
return modal_instance;
}
/**
* Show a modal and manage queue
* @private
*/
static async _show_modal(options) {
return new Promise(resolve => {
this._queue.push({
options,
resolve
});
// Process queue if no modal currently showing
if (!this._current) {
this._process_queue();
}
});
}
/**
* Process the modal queue
* @private
*/
static async _process_queue() {
if (this._queue.length === 0) {
this._current = null;
// Hide backdrop when queue is empty
await this._hide_backdrop();
return;
}
const {
options,
resolve
} = this._queue.shift();
// Ensure initialized
this._init();
// Show backdrop if not already visible (instant - no delay between modals)
const backdrop_visible = this._backdrop.hasClass('show');
if (!backdrop_visible) {
await this._show_backdrop();
}
// No delay between sequential modals - immediate transition
// Create modal instance
const modal_instance = await this._create_modal();
this._current = modal_instance;
// Determine if we should animate based on:
// 1. Desktop viewport (>= 1000px)
// 2. More than 1 second since last modal closed
const viewport_width = $(window).width();
const is_desktop = viewport_width >= 1000;
const time_since_last_close = Date.now() - this._last_close_timestamp;
const should_animate = is_desktop && time_since_last_close > 1000;
// Show modal and wait for result (modal won't create its own backdrop)
const result = await modal_instance.show(options, {
skip_backdrop: true,
animate: should_animate
});
// Record close timestamp BEFORE resolving (ensures it's set before next modal can start)
this._last_close_timestamp = Date.now();
// Resolve the promise with the result
resolve(result);
// Clear current and process next
this._current = null;
this._process_queue();
}
// ================================================================================
// State Management Methods
// ================================================================================
/**
* Check if a modal is currently open
* @returns {boolean}
*/
static is_open() {
return this._current !== null;
}
/**
* Get the currently open modal instance
* @returns {Rsx_Modal|null}
*/
static get_current() {
return this._current;
}
/**
* Force close the current modal
* @returns {Promise<void>}
*/
static async close() {
if (this._current) {
await this._current.close(false);
}
}
/**
* Apply validation errors to the current modal
* @param {Object} errors - Error object {field: message}
*/
static apply_errors(errors) {
if (this._current) {
this._current.apply_errors(errors);
}
}
// ================================================================================
// Simple Dialog Methods
// ================================================================================
/**
* Show an alert dialog
* @param {string|jQuery} title_or_body - Message (if only 1 arg) or Title (if 2 args). Can be string or jQuery element.
* @param {string|jQuery} body - Message body (if 2 args). Can be string or jQuery element.
* @param {string} button_label - Button text (default: "OK")
* @returns {Promise<void>}
*/
static async alert(title_or_body) {
let body = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
let button_label = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'OK';
let title = 'Notice';
let message = title_or_body;
if (body !== null) {
title = title_or_body;
message = body;
}
await this._show_modal({
title: title,
body: message,
buttons: [{
label: button_label,
value: true,
class: 'btn-primary',
default: true
}],
closable: true,
close_on_submit: true
});
}
/**
* Show a confirmation dialog
* @param {string|jQuery} title_or_body - Message (if 1-2 args) or Title (if 3-4 args). Can be string or jQuery element.
* @param {string|jQuery} body - Message body (optional). Can be string or jQuery element.
* @param {string} confirm_label - Confirm button text (default: "Confirm")
* @param {string} cancel_label - Cancel button text (default: "Cancel")
* @returns {Promise<boolean>}
*/
static async confirm(title_or_body) {
let body = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
let confirm_label = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'Confirm';
let cancel_label = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'Cancel';
let title = 'Confirm';
let message = title_or_body;
if (body !== null) {
title = title_or_body;
message = body;
}
const result = await this._show_modal({
title: title,
body: message,
buttons: [{
label: cancel_label,
value: false,
class: 'btn-secondary'
}, {
label: confirm_label,
value: true,
class: 'btn-primary',
default: true
}],
closable: true,
close_on_submit: true
});
return result === true;
}
/**
* Show a prompt dialog for text input
* @param {string|jQuery} title_or_body - Message (if 1-3 args) or Title (if 4 args). Can be string or jQuery element.
* @param {string|jQuery} body - Message body (optional). Can be string or jQuery element.
* @param {string} default_value - Default input value
* @param {boolean} multiline - Show textarea instead of input
* @param {string} error - Optional error message to display as validation feedback
* @returns {Promise<string|false>}
*/
static async prompt(title_or_body) {
let body = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
let default_value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
let multiline = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
let error = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
let title = 'Input';
let message = title_or_body;
// Handle overloaded arguments
if (typeof body === 'string' && body !== '') {
title = title_or_body;
message = body;
}
// Create input element with minimum width constraints
const $input = multiline ? $('<textarea class="form-control" rows="4" style="min-width: 315px;"></textarea>') : $('<input type="text" class="form-control" style="min-width: 245px;">');
$input.val(default_value);
// Mark as invalid if there's an error
if (error) {
$input.addClass('is-invalid');
}
// Create body with message and input
let $body;
if (message instanceof jQuery) {
// If message is a jQuery element, use it as the container and append input
$body = message.append($input);
} else {
// If message is a string, create wrapper with text and input (36px spacing)
$body = $('<div class="form-group">').append($('<div style="margin-bottom: 36px;">').text(message)).append($input);
}
// Add error message if provided
if (error) {
const $error = $('<div class="invalid-feedback d-block"></div>').text(error);
$body.append($error);
}
const result = await this._show_modal({
title: title,
body: $body,
buttons: [{
label: 'Cancel',
value: false,
class: 'btn-secondary'
}, {
label: 'Submit',
value: null,
// Will be replaced by callback
class: 'btn-primary',
default: true,
callback: function () {
return $input.val();
}
}],
closable: true,
close_on_submit: true,
max_width: 500
});
// Focus and select input after modal shows
requestAnimationFrame(() => {
$input.focus();
if (!multiline) {
$input.select();
}
});
return result;
}
/**
* Show an error dialog with red alert styling
*
* Can appear over other modals to show critical uncaught exceptions.
* Used primarily for Ajax errors that weren't caught by application code.
*
* @param {string|Error|Object} error - Error message string, Error object, or structured error
* @param {string} title - Modal title (default: "Error")
* @returns {Promise<void>}
*/
static async error(error) {
let title = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Error';
let message = '';
// Handle different error types
if (typeof error === 'string') {
message = error;
} else if (error instanceof Error) {
message = error.message || error.toString();
} else if (error && error.message) {
message = error.message;
} else if (error && error.error) {
// Fatal error with details
const details = error.error;
if (details.file && details.line) {
message = `Uncaught Fatal Error in ${details.file}:${details.line}:\n\n${details.error}`;
} else {
message = details.error || 'An unknown error occurred';
}
} else {
message = 'An unknown error occurred';
}
// Create error body with red alert styling
const $body = $('<div class="alert alert-danger mb-0" role="alert">').append($('<pre class="mb-0" style="white-space: pre-wrap; word-wrap: break-word; font-family: monospace; font-size: 0.9em;">').text(message));
await this._show_modal({
title: title,
body: $body,
buttons: [{
label: 'Close',
value: true,
class: 'btn-danger',
default: true
}],
closable: true,
close_on_submit: true,
max_width: 600
});
}
// ================================================================================
// Custom Modal Methods
// ================================================================================
/**
* Show a custom modal with specified content and buttons
* @param {Object} options
* @returns {Promise<*>}
*/
static async show(options) {
const defaults = {
title: 'Modal',
body: '',
buttons: [],
max_width: 800,
closable: true,
close_on_submit: true
};
const final_options = Object.assign({}, defaults, options);
return await this._show_modal(final_options);
}
/**
* Show a modal with a jqhtml form component
* @param {Object} options
* @param {string} options.component - Component class name
* @param {Object} options.component_args - Arguments to pass to component
* @param {Function} options.on_submit - Callback function called on submit. Receives form component instance.
* Return false to keep modal open, or return data to close and resolve.
* @returns {Promise<Object|false>}
*/
static async form(options) {
const defaults = {
title: 'Form',
component: null,
component_args: {},
max_width: 800,
closable: true,
submit_label: 'Submit',
cancel_label: 'Cancel',
on_submit: null
};
const final_options = Object.assign({}, defaults, options);
if (!final_options.component) {
console.error('Modal.form() requires a component');
return false;
}
// Create component instance
let $component_container = $('<div>');
let component_instance = $component_container.component(final_options.component, final_options.component_args);
// Wait for component to be ready
await new Promise(resolve => {
component_instance.on('ready', () => resolve());
});
// Find a form instance if component instance doesnt have .vals()
if (!component_instance.vals) {
let $form = component_instance.$.find('.Rsx_Form');
if ($form.exists()) {
component_instance = $form.component();
}
}
// Create buttons
const buttons = [{
label: final_options.cancel_label,
value: false,
class: 'btn-secondary'
}, {
label: final_options.submit_label,
value: null,
class: 'btn-primary',
default: true,
callback: async function () {
// If on_submit callback provided, use it
if (final_options.on_submit && typeof final_options.on_submit === 'function') {
const result = await final_options.on_submit(component_instance);
// If callback returns null/undefined, keep modal open
if (result === null || result === undefined) {
return false;
}
// Otherwise (including false), return the result to close modal
return result;
}
// No on_submit callback - get form data and close modal
if (component_instance.submit && typeof component_instance.submit === 'function') {
return await component_instance.submit();
} else if (component_instance.vals && typeof component_instance.vals === 'function') {
return component_instance.vals();
} else {
console.warn('Form component has no submit() or vals() method');
return true;
}
}
}];
return await this._show_modal({
title: final_options.title,
body: component_instance.$,
buttons: buttons,
max_width: final_options.max_width,
closable: final_options.closable
});
}
/**
* Show an unclosable modal
* @param {string} title_or_body
* @param {string} body
* @returns {Promise<void>}
*/
static async unclosable(title_or_body) {
let body = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
let title = 'Please Wait';
let message = title_or_body;
if (body !== null) {
title = title_or_body;
message = body;
}
// Don't wait for this promise - it never resolves until closed manually
this._show_modal({
title: title,
body: message,
buttons: [],
// No buttons
closable: false,
// Can't close
close_on_submit: false
});
// Wait for next animation frame for modal to render
await new Promise(resolve => requestAnimationFrame(resolve));
}
/**
* Show a modal with custom jQuery content
* @param {Object} options
* @returns {Promise<*>}
*/
static async custom(options) {
// Alias for show() - same functionality
return await this.show(options);
}
// ================================================================================
// Helper Methods
// ================================================================================
/**
* Show an error alert
* @param {*} errors
* @param {string} title
* @returns {Promise<void>}
*/
static async error(errors) {
let title = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Error';
let message = 'An error occurred';
// Handle various error formats
if (typeof errors === 'string') {
message = errors;
} else if (errors && 'responseJSON' in errors && 'message' in errors.responseJSON) {
message = errors.responseJSON.message;
} else if (errors && 'message' in errors) {
message = errors.message;
} else if (errors && typeof errors === 'object') {
// Try to format error object
const error_messages = [];
for (const key in errors) {
if (is_array(errors[key])) {
error_messages.push(errors[key][0]);
} else {
error_messages.push(errors[key]);
}
}
if (error_messages.length > 0) {
message = error_messages.join('\n');
}
}
await this._show_modal({
title: title,
body: message,
icon: 'exclamation-circle',
buttons: [{
label: 'OK',
value: true,
class: 'btn-danger',
default: true
}],
closable: true,
close_on_submit: true
});
}
/**
* Reopen current modal with validation errors
* @param {Object} errors
* @returns {Promise<void>}
*/
static async reopen_with_errors(errors) {
if (this._current) {
// Modal is still open, just apply errors
this.apply_errors(errors);
} else {
console.warn('No modal open to apply errors to');
}
}
}
// Internal state
_d1f5a3cb_defineProperty(Modal, "_queue", []);
_d1f5a3cb_defineProperty(Modal, "_current", null);
_d1f5a3cb_defineProperty(Modal, "_initialized", false);
_d1f5a3cb_defineProperty(Modal, "_backdrop", null);
_d1f5a3cb_defineProperty(Modal, "_original_body_overflow", null);
_d1f5a3cb_defineProperty(Modal, "_original_body_padding", null);
_d1f5a3cb_defineProperty(Modal, "_unlock_timeout", null);
_d1f5a3cb_defineProperty(Modal, "_last_close_timestamp", 0);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJNb2RhbCIsIl9pbml0IiwiX2luaXRpYWxpemVkIiwiX2JhY2tkcm9wIiwiJCIsImFwcGVuZCIsIl9nZXRfc2Nyb2xsYmFyX3dpZHRoIiwiJG91dGVyIiwiY3NzIiwidmlzaWJpbGl0eSIsIm92ZXJmbG93Iiwid2lkdGgiLCJwb3NpdGlvbiIsInRvcCIsIndpZHRoX3dpdGhfc2Nyb2xsYmFyIiwib2Zmc2V0V2lkdGgiLCIkaW5uZXIiLCJ3aWR0aF93aXRob3V0X3Njcm9sbGJhciIsInJlbW92ZSIsIl9sb2NrX2JvZHlfc2Nyb2xsIiwiX3VubG9ja190aW1lb3V0IiwiY2xlYXJUaW1lb3V0IiwiX29yaWdpbmFsX2JvZHlfb3ZlcmZsb3ciLCIkYm9keSIsIl9vcmlnaW5hbF9ib2R5X3BhZGRpbmciLCJoYXNfc2Nyb2xsYmFyIiwiZG9jdW1lbnQiLCJib2R5Iiwic2Nyb2xsSGVpZ2h0Iiwid2luZG93IiwiaW5uZXJIZWlnaHQiLCJzY3JvbGxiYXJfd2lkdGgiLCJjdXJyZW50X3BhZGRpbmciLCJpbnQiLCJfdW5sb2NrX2JvZHlfc2Nyb2xsIiwic2V0VGltZW91dCIsIl9jdXJyZW50IiwiX3F1ZXVlIiwibGVuZ3RoIiwiX3Nob3dfYmFja2Ryb3AiLCJoYXNDbGFzcyIsImFkZENsYXNzIiwiX2hpZGVfYmFja2Ryb3AiLCJyZW1vdmVDbGFzcyIsIl9jcmVhdGVfbW9kYWwiLCIkbW9kYWxfZWxlbWVudCIsIm1vZGFsX2luc3RhbmNlIiwiY29tcG9uZW50IiwiUHJvbWlzZSIsInJlc29sdmUiLCJvbiIsImNvbnNvbGUiLCJsb2ciLCJ0aXRsZSIsIiRpZCIsImZvb3RlciIsIl9zaG93X21vZGFsIiwib3B0aW9ucyIsInB1c2giLCJfcHJvY2Vzc19xdWV1ZSIsInNoaWZ0IiwiYmFja2Ryb3BfdmlzaWJsZSIsInZpZXdwb3J0X3dpZHRoIiwiaXNfZGVza3RvcCIsInRpbWVfc2luY2VfbGFzdF9jbG9zZSIsIkRhdGUiLCJub3ciLCJfbGFzdF9jbG9zZV90aW1lc3RhbXAiLCJzaG91bGRfYW5pbWF0ZSIsInJlc3VsdCIsInNob3ciLCJza2lwX2JhY2tkcm9wIiwiYW5pbWF0ZSIsImlzX29wZW4iLCJnZXRfY3VycmVudCIsImNsb3NlIiwiYXBwbHlfZXJyb3JzIiwiZXJyb3JzIiwiYWxlcnQiLCJ0aXRsZV9vcl9ib2R5IiwiYXJndW1lbnRzIiwidW5kZWZpbmVkIiwiYnV0dG9uX2xhYmVsIiwibWVzc2FnZSIsImJ1dHRvbnMiLCJsYWJlbCIsInZhbHVlIiwiY2xhc3MiLCJkZWZhdWx0IiwiY2xvc2FibGUiLCJjbG9zZV9vbl9zdWJtaXQiLCJjb25maXJtIiwiY29uZmlybV9sYWJlbCIsImNhbmNlbF9sYWJlbCIsInByb21wdCIsImRlZmF1bHRfdmFsdWUiLCJtdWx0aWxpbmUiLCJlcnJvciIsIiRpbnB1dCIsInZhbCIsImpRdWVyeSIsInRleHQiLCIkZXJyb3IiLCJjYWxsYmFjayIsIm1heF93aWR0aCIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsImZvY3VzIiwic2VsZWN0IiwiRXJyb3IiLCJ0b1N0cmluZyIsImRldGFpbHMiLCJmaWxlIiwibGluZSIsImRlZmF1bHRzIiwiZmluYWxfb3B0aW9ucyIsIk9iamVjdCIsImFzc2lnbiIsImZvcm0iLCJjb21wb25lbnRfYXJncyIsInN1Ym1pdF9sYWJlbCIsIm9uX3N1Ym1pdCIsIiRjb21wb25lbnRfY29udGFpbmVyIiwiY29tcG9uZW50X2luc3RhbmNlIiwidmFscyIsIiRmb3JtIiwiZmluZCIsImV4aXN0cyIsInN1Ym1pdCIsIndhcm4iLCJ1bmNsb3NhYmxlIiwiY3VzdG9tIiwicmVzcG9uc2VKU09OIiwiZXJyb3JfbWVzc2FnZXMiLCJrZXkiLCJpc19hcnJheSIsImpvaW4iLCJpY29uIiwicmVvcGVuX3dpdGhfZXJyb3JzIiwiX2QxZjVhM2NiX2RlZmluZVByb3BlcnR5Il0sInNvdXJjZXMiOlsicnN4L3RoZW1lL2NvbXBvbmVudHMvbW9kYWwvTW9kYWwuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNb2RhbCBTdGF0aWMgQVBJXG4gKlxuICogUHJpbWFyeSBpbnRlcmZhY2UgZm9yIGRpc3BsYXlpbmcgbW9kYWxzIHRocm91Z2hvdXQgdGhlIGFwcGxpY2F0aW9uLlxuICogUHJvdmlkZXMgc2ltcGxlIG1ldGhvZHMgZm9yIGNvbW1vbiBkaWFsb2dzIGFuZCBmbGV4aWJsZSBvcHRpb25zIGZvciBjdXN0b20gbW9kYWxzLlxuICpcbiAqIFVzYWdlOlxuICogICBhd2FpdCBNb2RhbC5hbGVydChcIkZpbGUgc2F2ZWRcIilcbiAqICAgaWYgKGF3YWl0IE1vZGFsLmNvbmZpcm0oXCJEZWxldGU/XCIpKSB7IC4uLiB9XG4gKiAgIGxldCBuYW1lID0gYXdhaXQgTW9kYWwucHJvbXB0KFwiRW50ZXIgbmFtZTpcIilcbiAqICAgbGV0IHJlc3VsdCA9IGF3YWl0IE1vZGFsLnNob3coeyB0aXRsZSwgYm9keSwgYnV0dG9ucyB9KVxuICovXG5jbGFzcyBNb2RhbCB7XG4gICAgLy8gSW50ZXJuYWwgc3RhdGVcbiAgICBzdGF0aWMgX3F1ZXVlID0gW107XG4gICAgc3RhdGljIF9jdXJyZW50ID0gbnVsbDtcbiAgICBzdGF0aWMgX2luaXRpYWxpemVkID0gZmFsc2U7XG4gICAgc3RhdGljIF9iYWNrZHJvcCA9IG51bGw7XG4gICAgc3RhdGljIF9vcmlnaW5hbF9ib2R5X292ZXJmbG93ID0gbnVsbDtcbiAgICBzdGF0aWMgX29yaWdpbmFsX2JvZHlfcGFkZGluZyA9IG51bGw7XG4gICAgc3RhdGljIF91bmxvY2tfdGltZW91dCA9IG51bGw7XG4gICAgc3RhdGljIF9sYXN0X2Nsb3NlX3RpbWVzdGFtcCA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGdsb2JhbCBoYW5kbGVycyAoY2FsbGVkIGF1dG9tYXRpY2FsbHkgb24gZmlyc3QgbW9kYWwpXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2luaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLl9pbml0aWFsaXplZCkgcmV0dXJuO1xuICAgICAgICB0aGlzLl9pbml0aWFsaXplZCA9IHRydWU7XG5cbiAgICAgICAgLy8gQ3JlYXRlIHNoYXJlZCBiYWNrZHJvcCBlbGVtZW50XG4gICAgICAgIHRoaXMuX2JhY2tkcm9wID0gJCgnPGRpdiBjbGFzcz1cIm1vZGFsLWJhY2tkcm9wIGZhZGVcIj48L2Rpdj4nKTtcbiAgICAgICAgJCgnYm9keScpLmFwcGVuZCh0aGlzLl9iYWNrZHJvcCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlIHNjcm9sbGJhciB3aWR0aFxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2dldF9zY3JvbGxiYXJfd2lkdGgoKSB7XG4gICAgICAgIC8vIENyZWF0ZSB0ZW1wb3JhcnkgZWxlbWVudCB0byBtZWFzdXJlIHNjcm9sbGJhciB3aWR0aFxuICAgICAgICBjb25zdCAkb3V0ZXIgPSAkKCc8ZGl2PicpLmNzcyh7XG4gICAgICAgICAgICB2aXNpYmlsaXR5OiAnaGlkZGVuJyxcbiAgICAgICAgICAgIG92ZXJmbG93OiAnc2Nyb2xsJyxcbiAgICAgICAgICAgIHdpZHRoOiAnMTAwcHgnLFxuICAgICAgICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICAgICAgICB0b3A6ICctOTk5OXB4JyxcbiAgICAgICAgfSk7XG4gICAgICAgICQoJ2JvZHknKS5hcHBlbmQoJG91dGVyKTtcblxuICAgICAgICBjb25zdCB3aWR0aF93aXRoX3Njcm9sbGJhciA9ICRvdXRlclswXS5vZmZzZXRXaWR0aDtcblxuICAgICAgICBjb25zdCAkaW5uZXIgPSAkKCc8ZGl2PicpLmNzcygnd2lkdGgnLCAnMTAwJScpO1xuICAgICAgICAkb3V0ZXIuYXBwZW5kKCRpbm5lcik7XG5cbiAgICAgICAgY29uc3Qgd2lkdGhfd2l0aG91dF9zY3JvbGxiYXIgPSAkaW5uZXJbMF0ub2Zmc2V0V2lkdGg7XG5cbiAgICAgICAgJG91dGVyLnJlbW92ZSgpO1xuXG4gICAgICAgIHJldHVybiB3aWR0aF93aXRoX3Njcm9sbGJhciAtIHdpZHRoX3dpdGhvdXRfc2Nyb2xsYmFyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIExvY2sgYm9keSBzY3JvbGwgYW5kIGNvbXBlbnNhdGUgZm9yIHNjcm9sbGJhciB3aWR0aFxuICAgICAqIE9ubHkgbG9ja3MgaWYgd2UgaGF2ZW4ndCBhbHJlYWR5IHNhdmVkIHRoZSBvcmlnaW5hbCBzdGF0ZSAoZmlyc3QgbW9kYWwgaW4gY2hhaW4pXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2xvY2tfYm9keV9zY3JvbGwoKSB7XG4gICAgICAgIC8vIENhbmNlbCBhbnkgcGVuZGluZyB1bmxvY2sgdGltZW91dFxuICAgICAgICBpZiAodGhpcy5fdW5sb2NrX3RpbWVvdXQpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aGlzLl91bmxvY2tfdGltZW91dCk7XG4gICAgICAgICAgICB0aGlzLl91bmxvY2tfdGltZW91dCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPbmx5IGxvY2sgc2Nyb2xsIGlmIHdlIGhhdmVuJ3QgYWxyZWFkeSBzYXZlZCBzdGF0ZSAoZmlyc3QgbW9kYWwpXG4gICAgICAgIC8vIFRoaXMgaXMgdGhlIHRydWUgaW5kaWNhdG9yIC0gbm90IGJhY2tkcm9wIHZpc2liaWxpdHkgd2hpY2ggY2FuIGJlIHRyYW5zaXRpb25hbFxuICAgICAgICBpZiAodGhpcy5fb3JpZ2luYWxfYm9keV9vdmVyZmxvdyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc3QgJGJvZHkgPSAkKCdib2R5Jyk7XG5cbiAgICAgICAgICAgIC8vIFN0b3JlIG9yaWdpbmFsIHZhbHVlc1xuICAgICAgICAgICAgdGhpcy5fb3JpZ2luYWxfYm9keV9vdmVyZmxvdyA9ICRib2R5LmNzcygnb3ZlcmZsb3cnKTtcbiAgICAgICAgICAgIHRoaXMuX29yaWdpbmFsX2JvZHlfcGFkZGluZyA9ICRib2R5LmNzcygncGFkZGluZy1yaWdodCcpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBib2R5IGN1cnJlbnRseSBoYXMgdmVydGljYWwgc2Nyb2xsXG4gICAgICAgICAgICBjb25zdCBoYXNfc2Nyb2xsYmFyID0gZG9jdW1lbnQuYm9keS5zY3JvbGxIZWlnaHQgPiB3aW5kb3cuaW5uZXJIZWlnaHQ7XG5cbiAgICAgICAgICAgIC8vIElmIHRoZXJlJ3MgYSBzY3JvbGxiYXIsIGFkZCBwYWRkaW5nIHRvIGNvbXBlbnNhdGUgZm9yIGl0cyByZW1vdmFsXG4gICAgICAgICAgICBpZiAoaGFzX3Njcm9sbGJhcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNjcm9sbGJhcl93aWR0aCA9IHRoaXMuX2dldF9zY3JvbGxiYXJfd2lkdGgoKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50X3BhZGRpbmcgPSBpbnQodGhpcy5fb3JpZ2luYWxfYm9keV9wYWRkaW5nKSB8fCAwO1xuICAgICAgICAgICAgICAgICRib2R5LmNzcygncGFkZGluZy1yaWdodCcsIGN1cnJlbnRfcGFkZGluZyArIHNjcm9sbGJhcl93aWR0aCArICdweCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMb2NrIHNjcm9sbFxuICAgICAgICAgICAgJGJvZHkuY3NzKCdvdmVyZmxvdycsICdoaWRkZW4nKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVubG9jayBib2R5IHNjcm9sbCBhbmQgcmVzdG9yZSBvcmlnaW5hbCBzdGF0ZVxuICAgICAqIFVzZXMgZGVsYXllZCBjaGVjayB0byBlbnN1cmUgbm8gb3RoZXIgbW9kYWxzIGFyZSBvcGVuaW5nXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3VubG9ja19ib2R5X3Njcm9sbCgpIHtcbiAgICAgICAgLy8gQ2xlYXIgYW55IGV4aXN0aW5nIHRpbWVvdXRcbiAgICAgICAgaWYgKHRoaXMuX3VubG9ja190aW1lb3V0KSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy5fdW5sb2NrX3RpbWVvdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWluaW1hbCBkZWxheSBiZWZvcmUgdW5sb2NraW5nXG4gICAgICAgIHRoaXMuX3VubG9ja190aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAvLyBEb3VibGUtY2hlY2sgbm8gbW9kYWwgaXMgY3VycmVudGx5IG9wZW4gYW5kIHF1ZXVlIGlzIGVtcHR5XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2N1cnJlbnQgJiYgdGhpcy5fcXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgJGJvZHkgPSAkKCdib2R5Jyk7XG5cbiAgICAgICAgICAgICAgICAvLyBSZXN0b3JlIG9yaWdpbmFsIHZhbHVlc1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9vcmlnaW5hbF9ib2R5X292ZXJmbG93ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICRib2R5LmNzcygnb3ZlcmZsb3cnLCB0aGlzLl9vcmlnaW5hbF9ib2R5X292ZXJmbG93KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fb3JpZ2luYWxfYm9keV9vdmVyZmxvdyA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX29yaWdpbmFsX2JvZHlfcGFkZGluZyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAkYm9keS5jc3MoJ3BhZGRpbmctcmlnaHQnLCB0aGlzLl9vcmlnaW5hbF9ib2R5X3BhZGRpbmcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9vcmlnaW5hbF9ib2R5X3BhZGRpbmcgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fdW5sb2NrX3RpbWVvdXQgPSBudWxsO1xuICAgICAgICB9LCA1MCk7IC8vIE1pbmltYWwgc2FmZXR5IGJ1ZmZlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3cgdGhlIHNoYXJlZCBiYWNrZHJvcCAoaW5zdGFudCAtIG5vIGFuaW1hdGlvbilcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfc2hvd19iYWNrZHJvcCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9iYWNrZHJvcC5oYXNDbGFzcygnc2hvdycpKSB7XG4gICAgICAgICAgICAvLyBMb2NrIGJvZHkgc2Nyb2xsIGJlZm9yZSBzaG93aW5nIGJhY2tkcm9wXG4gICAgICAgICAgICB0aGlzLl9sb2NrX2JvZHlfc2Nyb2xsKCk7XG5cbiAgICAgICAgICAgIHRoaXMuX2JhY2tkcm9wLmNzcygnZGlzcGxheScsICdibG9jaycpLmFkZENsYXNzKCdzaG93Jyk7XG4gICAgICAgICAgICAvLyBObyBkZWxheSAtIHJldHVybiBpbW1lZGlhdGVseVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGlkZSB0aGUgc2hhcmVkIGJhY2tkcm9wIChpbnN0YW50IC0gbm8gYW5pbWF0aW9uKVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9oaWRlX2JhY2tkcm9wKCkge1xuICAgICAgICB0aGlzLl9iYWNrZHJvcC5yZW1vdmVDbGFzcygnc2hvdycpLmNzcygnZGlzcGxheScsICdub25lJyk7XG5cbiAgICAgICAgLy8gVW5sb2NrIGJvZHkgc2Nyb2xsIGFmdGVyIGJhY2tkcm9wIGlzIGhpZGRlblxuICAgICAgICB0aGlzLl91bmxvY2tfYm9keV9zY3JvbGwoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBuZXcgUnN4X01vZGFsIGluc3RhbmNlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX2NyZWF0ZV9tb2RhbCgpIHtcbiAgICAgICAgLy8gQ3JlYXRlIG1vZGFsIGNvbXBvbmVudCB1c2luZyBqUXVlcnkgcGx1Z2luXG4gICAgICAgIGNvbnN0ICRtb2RhbF9lbGVtZW50ID0gJCgnPGRpdj4nKTtcblxuICAgICAgICAvLyBDcmVhdGUgY29tcG9uZW50IGluc3RhbmNlIGRpcmVjdGx5IChyZXR1cm5zIHRoZSBjb21wb25lbnQpXG4gICAgICAgIGNvbnN0IG1vZGFsX2luc3RhbmNlID0gJG1vZGFsX2VsZW1lbnQuY29tcG9uZW50KCdSc3hfTW9kYWwnLCB7fSk7XG5cbiAgICAgICAgLy8gV2FpdCBmb3IgY29tcG9uZW50IHRvIGJlIGZ1bGx5IHJlYWR5IChET00gZWxlbWVudHMgcXVlcnlhYmxlKVxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgbW9kYWxfaW5zdGFuY2Uub24oJ3JlYWR5JywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdbTW9kYWxdIENvbXBvbmVudCByZWFkeSwgZWxlbWVudHM6Jywge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZTogbW9kYWxfaW5zdGFuY2UuJGlkKCd0aXRsZScpLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgYm9keTogbW9kYWxfaW5zdGFuY2UuJGlkKCdib2R5JykubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICBmb290ZXI6IG1vZGFsX2luc3RhbmNlLiRpZCgnZm9vdGVyJykubGVuZ3RoLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gbW9kYWxfaW5zdGFuY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvdyBhIG1vZGFsIGFuZCBtYW5hZ2UgcXVldWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfc2hvd19tb2RhbChvcHRpb25zKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcXVldWUucHVzaCh7IG9wdGlvbnMsIHJlc29sdmUgfSk7XG5cbiAgICAgICAgICAgIC8vIFByb2Nlc3MgcXVldWUgaWYgbm8gbW9kYWwgY3VycmVudGx5IHNob3dpbmdcbiAgICAgICAgICAgIGlmICghdGhpcy5fY3VycmVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NfcXVldWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgbW9kYWwgcXVldWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfcHJvY2Vzc19xdWV1ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuX3F1ZXVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5fY3VycmVudCA9IG51bGw7XG4gICAgICAgICAgICAvLyBIaWRlIGJhY2tkcm9wIHdoZW4gcXVldWUgaXMgZW1wdHlcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX2hpZGVfYmFja2Ryb3AoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgb3B0aW9ucywgcmVzb2x2ZSB9ID0gdGhpcy5fcXVldWUuc2hpZnQoKTtcblxuICAgICAgICAvLyBFbnN1cmUgaW5pdGlhbGl6ZWRcbiAgICAgICAgdGhpcy5faW5pdCgpO1xuXG4gICAgICAgIC8vIFNob3cgYmFja2Ryb3AgaWYgbm90IGFscmVhZHkgdmlzaWJsZSAoaW5zdGFudCAtIG5vIGRlbGF5IGJldHdlZW4gbW9kYWxzKVxuICAgICAgICBjb25zdCBiYWNrZHJvcF92aXNpYmxlID0gdGhpcy5fYmFja2Ryb3AuaGFzQ2xhc3MoJ3Nob3cnKTtcbiAgICAgICAgaWYgKCFiYWNrZHJvcF92aXNpYmxlKSB7XG4gICAgICAgICAgICBhd2FpdCB0aGlzLl9zaG93X2JhY2tkcm9wKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm8gZGVsYXkgYmV0d2VlbiBzZXF1ZW50aWFsIG1vZGFscyAtIGltbWVkaWF0ZSB0cmFuc2l0aW9uXG5cbiAgICAgICAgLy8gQ3JlYXRlIG1vZGFsIGluc3RhbmNlXG4gICAgICAgIGNvbnN0IG1vZGFsX2luc3RhbmNlID0gYXdhaXQgdGhpcy5fY3JlYXRlX21vZGFsKCk7XG4gICAgICAgIHRoaXMuX2N1cnJlbnQgPSBtb2RhbF9pbnN0YW5jZTtcblxuICAgICAgICAvLyBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIGFuaW1hdGUgYmFzZWQgb246XG4gICAgICAgIC8vIDEuIERlc2t0b3Agdmlld3BvcnQgKD49IDEwMDBweClcbiAgICAgICAgLy8gMi4gTW9yZSB0aGFuIDEgc2Vjb25kIHNpbmNlIGxhc3QgbW9kYWwgY2xvc2VkXG4gICAgICAgIGNvbnN0IHZpZXdwb3J0X3dpZHRoID0gJCh3aW5kb3cpLndpZHRoKCk7XG4gICAgICAgIGNvbnN0IGlzX2Rlc2t0b3AgPSB2aWV3cG9ydF93aWR0aCA+PSAxMDAwO1xuICAgICAgICBjb25zdCB0aW1lX3NpbmNlX2xhc3RfY2xvc2UgPSBEYXRlLm5vdygpIC0gdGhpcy5fbGFzdF9jbG9zZV90aW1lc3RhbXA7XG4gICAgICAgIGNvbnN0IHNob3VsZF9hbmltYXRlID0gaXNfZGVza3RvcCAmJiB0aW1lX3NpbmNlX2xhc3RfY2xvc2UgPiAxMDAwO1xuXG4gICAgICAgIC8vIFNob3cgbW9kYWwgYW5kIHdhaXQgZm9yIHJlc3VsdCAobW9kYWwgd29uJ3QgY3JlYXRlIGl0cyBvd24gYmFja2Ryb3ApXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG1vZGFsX2luc3RhbmNlLnNob3cob3B0aW9ucywgeyBza2lwX2JhY2tkcm9wOiB0cnVlLCBhbmltYXRlOiBzaG91bGRfYW5pbWF0ZSB9KTtcblxuICAgICAgICAvLyBSZWNvcmQgY2xvc2UgdGltZXN0YW1wIEJFRk9SRSByZXNvbHZpbmcgKGVuc3VyZXMgaXQncyBzZXQgYmVmb3JlIG5leHQgbW9kYWwgY2FuIHN0YXJ0KVxuICAgICAgICB0aGlzLl9sYXN0X2Nsb3NlX3RpbWVzdGFtcCA9IERhdGUubm93KCk7XG5cbiAgICAgICAgLy8gUmVzb2x2ZSB0aGUgcHJvbWlzZSB3aXRoIHRoZSByZXN1bHRcbiAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuXG4gICAgICAgIC8vIENsZWFyIGN1cnJlbnQgYW5kIHByb2Nlc3MgbmV4dFxuICAgICAgICB0aGlzLl9jdXJyZW50ID0gbnVsbDtcbiAgICAgICAgdGhpcy5fcHJvY2Vzc19xdWV1ZSgpO1xuICAgIH1cblxuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gICAgLy8gU3RhdGUgTWFuYWdlbWVudCBNZXRob2RzXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgbW9kYWwgaXMgY3VycmVudGx5IG9wZW5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNfb3BlbigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2N1cnJlbnQgIT09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50bHkgb3BlbiBtb2RhbCBpbnN0YW5jZVxuICAgICAqIEByZXR1cm5zIHtSc3hfTW9kYWx8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2N1cnJlbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jdXJyZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcmNlIGNsb3NlIHRoZSBjdXJyZW50IG1vZGFsXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGNsb3NlKCkge1xuICAgICAgICBpZiAodGhpcy5fY3VycmVudCkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fY3VycmVudC5jbG9zZShmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBseSB2YWxpZGF0aW9uIGVycm9ycyB0byB0aGUgY3VycmVudCBtb2RhbFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBlcnJvcnMgLSBFcnJvciBvYmplY3Qge2ZpZWxkOiBtZXNzYWdlfVxuICAgICAqL1xuICAgIHN0YXRpYyBhcHBseV9lcnJvcnMoZXJyb3JzKSB7XG4gICAgICAgIGlmICh0aGlzLl9jdXJyZW50KSB7XG4gICAgICAgICAgICB0aGlzLl9jdXJyZW50LmFwcGx5X2Vycm9ycyhlcnJvcnMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBTaW1wbGUgRGlhbG9nIE1ldGhvZHNcbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gICAgLyoqXG4gICAgICogU2hvdyBhbiBhbGVydCBkaWFsb2dcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xqUXVlcnl9IHRpdGxlX29yX2JvZHkgLSBNZXNzYWdlIChpZiBvbmx5IDEgYXJnKSBvciBUaXRsZSAoaWYgMiBhcmdzKS4gQ2FuIGJlIHN0cmluZyBvciBqUXVlcnkgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xqUXVlcnl9IGJvZHkgLSBNZXNzYWdlIGJvZHkgKGlmIDIgYXJncykuIENhbiBiZSBzdHJpbmcgb3IgalF1ZXJ5IGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGJ1dHRvbl9sYWJlbCAtIEJ1dHRvbiB0ZXh0IChkZWZhdWx0OiBcIk9LXCIpXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGFsZXJ0KHRpdGxlX29yX2JvZHksIGJvZHkgPSBudWxsLCBidXR0b25fbGFiZWwgPSAnT0snKSB7XG4gICAgICAgIGxldCB0aXRsZSA9ICdOb3RpY2UnO1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHRpdGxlX29yX2JvZHk7XG5cbiAgICAgICAgaWYgKGJvZHkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRpdGxlID0gdGl0bGVfb3JfYm9keTtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBib2R5O1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fc2hvd19tb2RhbCh7XG4gICAgICAgICAgICB0aXRsZTogdGl0bGUsXG4gICAgICAgICAgICBib2R5OiBtZXNzYWdlLFxuICAgICAgICAgICAgYnV0dG9uczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IGJ1dHRvbl9sYWJlbCxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzOiAnYnRuLXByaW1hcnknLFxuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiB0cnVlLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY2xvc2FibGU6IHRydWUsXG4gICAgICAgICAgICBjbG9zZV9vbl9zdWJtaXQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3cgYSBjb25maXJtYXRpb24gZGlhbG9nXG4gICAgICogQHBhcmFtIHtzdHJpbmd8alF1ZXJ5fSB0aXRsZV9vcl9ib2R5IC0gTWVzc2FnZSAoaWYgMS0yIGFyZ3MpIG9yIFRpdGxlIChpZiAzLTQgYXJncykuIENhbiBiZSBzdHJpbmcgb3IgalF1ZXJ5IGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd8alF1ZXJ5fSBib2R5IC0gTWVzc2FnZSBib2R5IChvcHRpb25hbCkuIENhbiBiZSBzdHJpbmcgb3IgalF1ZXJ5IGVsZW1lbnQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNvbmZpcm1fbGFiZWwgLSBDb25maXJtIGJ1dHRvbiB0ZXh0IChkZWZhdWx0OiBcIkNvbmZpcm1cIilcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2FuY2VsX2xhYmVsIC0gQ2FuY2VsIGJ1dHRvbiB0ZXh0IChkZWZhdWx0OiBcIkNhbmNlbFwiKVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGJvb2xlYW4+fVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBjb25maXJtKHRpdGxlX29yX2JvZHksIGJvZHkgPSBudWxsLCBjb25maXJtX2xhYmVsID0gJ0NvbmZpcm0nLCBjYW5jZWxfbGFiZWwgPSAnQ2FuY2VsJykge1xuICAgICAgICBsZXQgdGl0bGUgPSAnQ29uZmlybSc7XG4gICAgICAgIGxldCBtZXNzYWdlID0gdGl0bGVfb3JfYm9keTtcblxuICAgICAgICBpZiAoYm9keSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdGl0bGUgPSB0aXRsZV9vcl9ib2R5O1xuICAgICAgICAgICAgbWVzc2FnZSA9IGJvZHk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLl9zaG93X21vZGFsKHtcbiAgICAgICAgICAgIHRpdGxlOiB0aXRsZSxcbiAgICAgICAgICAgIGJvZHk6IG1lc3NhZ2UsXG4gICAgICAgICAgICBidXR0b25zOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBsYWJlbDogY2FuY2VsX2xhYmVsLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzOiAnYnRuLXNlY29uZGFyeScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsOiBjb25maXJtX2xhYmVsLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M6ICdidG4tcHJpbWFyeScsXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRydWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBjbG9zYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNsb3NlX29uX3N1Ym1pdDogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGEgcHJvbXB0IGRpYWxvZyBmb3IgdGV4dCBpbnB1dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfGpRdWVyeX0gdGl0bGVfb3JfYm9keSAtIE1lc3NhZ2UgKGlmIDEtMyBhcmdzKSBvciBUaXRsZSAoaWYgNCBhcmdzKS4gQ2FuIGJlIHN0cmluZyBvciBqUXVlcnkgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xqUXVlcnl9IGJvZHkgLSBNZXNzYWdlIGJvZHkgKG9wdGlvbmFsKS4gQ2FuIGJlIHN0cmluZyBvciBqUXVlcnkgZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGVmYXVsdF92YWx1ZSAtIERlZmF1bHQgaW5wdXQgdmFsdWVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IG11bHRpbGluZSAtIFNob3cgdGV4dGFyZWEgaW5zdGVhZCBvZiBpbnB1dFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBlcnJvciAtIE9wdGlvbmFsIGVycm9yIG1lc3NhZ2UgdG8gZGlzcGxheSBhcyB2YWxpZGF0aW9uIGZlZWRiYWNrXG4gICAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nfGZhbHNlPn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgcHJvbXB0KHRpdGxlX29yX2JvZHksIGJvZHkgPSBudWxsLCBkZWZhdWx0X3ZhbHVlID0gJycsIG11bHRpbGluZSA9IGZhbHNlLCBlcnJvciA9IG51bGwpIHtcbiAgICAgICAgbGV0IHRpdGxlID0gJ0lucHV0JztcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSB0aXRsZV9vcl9ib2R5O1xuXG4gICAgICAgIC8vIEhhbmRsZSBvdmVybG9hZGVkIGFyZ3VtZW50c1xuICAgICAgICBpZiAodHlwZW9mIGJvZHkgPT09ICdzdHJpbmcnICYmIGJvZHkgIT09ICcnKSB7XG4gICAgICAgICAgICB0aXRsZSA9IHRpdGxlX29yX2JvZHk7XG4gICAgICAgICAgICBtZXNzYWdlID0gYm9keTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENyZWF0ZSBpbnB1dCBlbGVtZW50IHdpdGggbWluaW11bSB3aWR0aCBjb25zdHJhaW50c1xuICAgICAgICBjb25zdCAkaW5wdXQgPSBtdWx0aWxpbmVcbiAgICAgICAgICAgID8gJCgnPHRleHRhcmVhIGNsYXNzPVwiZm9ybS1jb250cm9sXCIgcm93cz1cIjRcIiBzdHlsZT1cIm1pbi13aWR0aDogMzE1cHg7XCI+PC90ZXh0YXJlYT4nKVxuICAgICAgICAgICAgOiAkKCc8aW5wdXQgdHlwZT1cInRleHRcIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIHN0eWxlPVwibWluLXdpZHRoOiAyNDVweDtcIj4nKTtcblxuICAgICAgICAkaW5wdXQudmFsKGRlZmF1bHRfdmFsdWUpO1xuXG4gICAgICAgIC8vIE1hcmsgYXMgaW52YWxpZCBpZiB0aGVyZSdzIGFuIGVycm9yXG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgJGlucHV0LmFkZENsYXNzKCdpcy1pbnZhbGlkJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgYm9keSB3aXRoIG1lc3NhZ2UgYW5kIGlucHV0XG4gICAgICAgIGxldCAkYm9keTtcbiAgICAgICAgaWYgKG1lc3NhZ2UgaW5zdGFuY2VvZiBqUXVlcnkpIHtcbiAgICAgICAgICAgIC8vIElmIG1lc3NhZ2UgaXMgYSBqUXVlcnkgZWxlbWVudCwgdXNlIGl0IGFzIHRoZSBjb250YWluZXIgYW5kIGFwcGVuZCBpbnB1dFxuICAgICAgICAgICAgJGJvZHkgPSBtZXNzYWdlLmFwcGVuZCgkaW5wdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSWYgbWVzc2FnZSBpcyBhIHN0cmluZywgY3JlYXRlIHdyYXBwZXIgd2l0aCB0ZXh0IGFuZCBpbnB1dCAoMzZweCBzcGFjaW5nKVxuICAgICAgICAgICAgJGJvZHkgPSAkKCc8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPicpLmFwcGVuZCgkKCc8ZGl2IHN0eWxlPVwibWFyZ2luLWJvdHRvbTogMzZweDtcIj4nKS50ZXh0KG1lc3NhZ2UpKS5hcHBlbmQoJGlucHV0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCBlcnJvciBtZXNzYWdlIGlmIHByb3ZpZGVkXG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgY29uc3QgJGVycm9yID0gJCgnPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgZC1ibG9ja1wiPjwvZGl2PicpLnRleHQoZXJyb3IpO1xuICAgICAgICAgICAgJGJvZHkuYXBwZW5kKCRlcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLl9zaG93X21vZGFsKHtcbiAgICAgICAgICAgIHRpdGxlOiB0aXRsZSxcbiAgICAgICAgICAgIGJvZHk6ICRib2R5LFxuICAgICAgICAgICAgYnV0dG9uczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbGFiZWw6ICdDYW5jZWwnLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzOiAnYnRuLXNlY29uZGFyeScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIGxhYmVsOiAnU3VibWl0JyxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG51bGwsIC8vIFdpbGwgYmUgcmVwbGFjZWQgYnkgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M6ICdidG4tcHJpbWFyeScsXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGlucHV0LnZhbCgpO1xuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY2xvc2FibGU6IHRydWUsXG4gICAgICAgICAgICBjbG9zZV9vbl9zdWJtaXQ6IHRydWUsXG4gICAgICAgICAgICBtYXhfd2lkdGg6IDUwMCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRm9jdXMgYW5kIHNlbGVjdCBpbnB1dCBhZnRlciBtb2RhbCBzaG93c1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4ge1xuICAgICAgICAgICAgJGlucHV0LmZvY3VzKCk7XG4gICAgICAgICAgICBpZiAoIW11bHRpbGluZSkge1xuICAgICAgICAgICAgICAgICRpbnB1dC5zZWxlY3QoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGFuIGVycm9yIGRpYWxvZyB3aXRoIHJlZCBhbGVydCBzdHlsaW5nXG4gICAgICpcbiAgICAgKiBDYW4gYXBwZWFyIG92ZXIgb3RoZXIgbW9kYWxzIHRvIHNob3cgY3JpdGljYWwgdW5jYXVnaHQgZXhjZXB0aW9ucy5cbiAgICAgKiBVc2VkIHByaW1hcmlseSBmb3IgQWpheCBlcnJvcnMgdGhhdCB3ZXJlbid0IGNhdWdodCBieSBhcHBsaWNhdGlvbiBjb2RlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8RXJyb3J8T2JqZWN0fSBlcnJvciAtIEVycm9yIG1lc3NhZ2Ugc3RyaW5nLCBFcnJvciBvYmplY3QsIG9yIHN0cnVjdHVyZWQgZXJyb3JcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGl0bGUgLSBNb2RhbCB0aXRsZSAoZGVmYXVsdDogXCJFcnJvclwiKVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBlcnJvcihlcnJvciwgdGl0bGUgPSAnRXJyb3InKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gJyc7XG5cbiAgICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBlcnJvciB0eXBlc1xuICAgICAgICBpZiAodHlwZW9mIGVycm9yID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgbWVzc2FnZSA9IGVycm9yO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8IGVycm9yLnRvU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgJiYgZXJyb3IubWVzc2FnZSkge1xuICAgICAgICAgICAgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2U7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgJiYgZXJyb3IuZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIEZhdGFsIGVycm9yIHdpdGggZGV0YWlsc1xuICAgICAgICAgICAgY29uc3QgZGV0YWlscyA9IGVycm9yLmVycm9yO1xuICAgICAgICAgICAgaWYgKGRldGFpbHMuZmlsZSAmJiBkZXRhaWxzLmxpbmUpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gYFVuY2F1Z2h0IEZhdGFsIEVycm9yIGluICR7ZGV0YWlscy5maWxlfToke2RldGFpbHMubGluZX06XFxuXFxuJHtkZXRhaWxzLmVycm9yfWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBkZXRhaWxzLmVycm9yIHx8ICdBbiB1bmtub3duIGVycm9yIG9jY3VycmVkJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSAnQW4gdW5rbm93biBlcnJvciBvY2N1cnJlZCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDcmVhdGUgZXJyb3IgYm9keSB3aXRoIHJlZCBhbGVydCBzdHlsaW5nXG4gICAgICAgIGNvbnN0ICRib2R5ID0gJCgnPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlciBtYi0wXCIgcm9sZT1cImFsZXJ0XCI+JykuYXBwZW5kKFxuICAgICAgICAgICAgJCgnPHByZSBjbGFzcz1cIm1iLTBcIiBzdHlsZT1cIndoaXRlLXNwYWNlOiBwcmUtd3JhcDsgd29yZC13cmFwOiBicmVhay13b3JkOyBmb250LWZhbWlseTogbW9ub3NwYWNlOyBmb250LXNpemU6IDAuOWVtO1wiPicpLnRleHQoXG4gICAgICAgICAgICAgICAgbWVzc2FnZVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuX3Nob3dfbW9kYWwoe1xuICAgICAgICAgICAgdGl0bGU6IHRpdGxlLFxuICAgICAgICAgICAgYm9keTogJGJvZHksXG4gICAgICAgICAgICBidXR0b25zOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBsYWJlbDogJ0Nsb3NlJyxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzOiAnYnRuLWRhbmdlcicsXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHRydWUsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBjbG9zYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGNsb3NlX29uX3N1Ym1pdDogdHJ1ZSxcbiAgICAgICAgICAgIG1heF93aWR0aDogNjAwLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAgIC8vIEN1c3RvbSBNb2RhbCBNZXRob2RzXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAgIC8qKlxuICAgICAqIFNob3cgYSBjdXN0b20gbW9kYWwgd2l0aCBzcGVjaWZpZWQgY29udGVudCBhbmQgYnV0dG9uc1xuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAgICogQHJldHVybnMge1Byb21pc2U8Kj59XG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIHNob3cob3B0aW9ucykge1xuICAgICAgICBjb25zdCBkZWZhdWx0cyA9IHtcbiAgICAgICAgICAgIHRpdGxlOiAnTW9kYWwnLFxuICAgICAgICAgICAgYm9keTogJycsXG4gICAgICAgICAgICBidXR0b25zOiBbXSxcbiAgICAgICAgICAgIG1heF93aWR0aDogODAwLFxuICAgICAgICAgICAgY2xvc2FibGU6IHRydWUsXG4gICAgICAgICAgICBjbG9zZV9vbl9zdWJtaXQ6IHRydWUsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgZmluYWxfb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIGRlZmF1bHRzLCBvcHRpb25zKTtcblxuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fc2hvd19tb2RhbChmaW5hbF9vcHRpb25zKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGEgbW9kYWwgd2l0aCBhIGpxaHRtbCBmb3JtIGNvbXBvbmVudFxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMuY29tcG9uZW50IC0gQ29tcG9uZW50IGNsYXNzIG5hbWVcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucy5jb21wb25lbnRfYXJncyAtIEFyZ3VtZW50cyB0byBwYXNzIHRvIGNvbXBvbmVudFxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IG9wdGlvbnMub25fc3VibWl0IC0gQ2FsbGJhY2sgZnVuY3Rpb24gY2FsbGVkIG9uIHN1Ym1pdC4gUmVjZWl2ZXMgZm9ybSBjb21wb25lbnQgaW5zdGFuY2UuXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmV0dXJuIGZhbHNlIHRvIGtlZXAgbW9kYWwgb3Blbiwgb3IgcmV0dXJuIGRhdGEgdG8gY2xvc2UgYW5kIHJlc29sdmUuXG4gICAgICogQHJldHVybnMge1Byb21pc2U8T2JqZWN0fGZhbHNlPn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgZm9ybShvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGRlZmF1bHRzID0ge1xuICAgICAgICAgICAgdGl0bGU6ICdGb3JtJyxcbiAgICAgICAgICAgIGNvbXBvbmVudDogbnVsbCxcbiAgICAgICAgICAgIGNvbXBvbmVudF9hcmdzOiB7fSxcbiAgICAgICAgICAgIG1heF93aWR0aDogODAwLFxuICAgICAgICAgICAgY2xvc2FibGU6IHRydWUsXG4gICAgICAgICAgICBzdWJtaXRfbGFiZWw6ICdTdWJtaXQnLFxuICAgICAgICAgICAgY2FuY2VsX2xhYmVsOiAnQ2FuY2VsJyxcbiAgICAgICAgICAgIG9uX3N1Ym1pdDogbnVsbCxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBmaW5hbF9vcHRpb25zID0gT2JqZWN0LmFzc2lnbih7fSwgZGVmYXVsdHMsIG9wdGlvbnMpO1xuXG4gICAgICAgIGlmICghZmluYWxfb3B0aW9ucy5jb21wb25lbnQpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ01vZGFsLmZvcm0oKSByZXF1aXJlcyBhIGNvbXBvbmVudCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIGNvbXBvbmVudCBpbnN0YW5jZVxuICAgICAgICBsZXQgJGNvbXBvbmVudF9jb250YWluZXIgPSAkKCc8ZGl2PicpO1xuICAgICAgICBsZXQgY29tcG9uZW50X2luc3RhbmNlID0gJGNvbXBvbmVudF9jb250YWluZXIuY29tcG9uZW50KGZpbmFsX29wdGlvbnMuY29tcG9uZW50LCBmaW5hbF9vcHRpb25zLmNvbXBvbmVudF9hcmdzKTtcblxuICAgICAgICAvLyBXYWl0IGZvciBjb21wb25lbnQgdG8gYmUgcmVhZHlcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIGNvbXBvbmVudF9pbnN0YW5jZS5vbigncmVhZHknLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBGaW5kIGEgZm9ybSBpbnN0YW5jZSBpZiBjb21wb25lbnQgaW5zdGFuY2UgZG9lc250IGhhdmUgLnZhbHMoKVxuICAgICAgICBpZiAoIWNvbXBvbmVudF9pbnN0YW5jZS52YWxzKSB7XG4gICAgICAgICAgICBsZXQgJGZvcm0gPSBjb21wb25lbnRfaW5zdGFuY2UuJC5maW5kKCcuUnN4X0Zvcm0nKTtcbiAgICAgICAgICAgIGlmICgkZm9ybS5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudF9pbnN0YW5jZSA9ICRmb3JtLmNvbXBvbmVudCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIGJ1dHRvbnNcbiAgICAgICAgY29uc3QgYnV0dG9ucyA9IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBsYWJlbDogZmluYWxfb3B0aW9ucy5jYW5jZWxfbGFiZWwsXG4gICAgICAgICAgICAgICAgdmFsdWU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNsYXNzOiAnYnRuLXNlY29uZGFyeScsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGxhYmVsOiBmaW5hbF9vcHRpb25zLnN1Ym1pdF9sYWJlbCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogbnVsbCxcbiAgICAgICAgICAgICAgICBjbGFzczogJ2J0bi1wcmltYXJ5JyxcbiAgICAgICAgICAgICAgICBkZWZhdWx0OiB0cnVlLFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrOiBhc3luYyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIG9uX3N1Ym1pdCBjYWxsYmFjayBwcm92aWRlZCwgdXNlIGl0XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaW5hbF9vcHRpb25zLm9uX3N1Ym1pdCAmJiB0eXBlb2YgZmluYWxfb3B0aW9ucy5vbl9zdWJtaXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpbmFsX29wdGlvbnMub25fc3VibWl0KGNvbXBvbmVudF9pbnN0YW5jZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBjYWxsYmFjayByZXR1cm5zIG51bGwvdW5kZWZpbmVkLCBrZWVwIG1vZGFsIG9wZW5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPT09IG51bGwgfHwgcmVzdWx0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgKGluY2x1ZGluZyBmYWxzZSksIHJldHVybiB0aGUgcmVzdWx0IHRvIGNsb3NlIG1vZGFsXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTm8gb25fc3VibWl0IGNhbGxiYWNrIC0gZ2V0IGZvcm0gZGF0YSBhbmQgY2xvc2UgbW9kYWxcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbXBvbmVudF9pbnN0YW5jZS5zdWJtaXQgJiYgdHlwZW9mIGNvbXBvbmVudF9pbnN0YW5jZS5zdWJtaXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhd2FpdCBjb21wb25lbnRfaW5zdGFuY2Uuc3VibWl0KCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY29tcG9uZW50X2luc3RhbmNlLnZhbHMgJiYgdHlwZW9mIGNvbXBvbmVudF9pbnN0YW5jZS52YWxzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29tcG9uZW50X2luc3RhbmNlLnZhbHMoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignRm9ybSBjb21wb25lbnQgaGFzIG5vIHN1Ym1pdCgpIG9yIHZhbHMoKSBtZXRob2QnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF07XG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX3Nob3dfbW9kYWwoe1xuICAgICAgICAgICAgdGl0bGU6IGZpbmFsX29wdGlvbnMudGl0bGUsXG4gICAgICAgICAgICBib2R5OiBjb21wb25lbnRfaW5zdGFuY2UuJCxcbiAgICAgICAgICAgIGJ1dHRvbnM6IGJ1dHRvbnMsXG4gICAgICAgICAgICBtYXhfd2lkdGg6IGZpbmFsX29wdGlvbnMubWF4X3dpZHRoLFxuICAgICAgICAgICAgY2xvc2FibGU6IGZpbmFsX29wdGlvbnMuY2xvc2FibGUsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3cgYW4gdW5jbG9zYWJsZSBtb2RhbFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZV9vcl9ib2R5XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGJvZHlcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgdW5jbG9zYWJsZSh0aXRsZV9vcl9ib2R5LCBib2R5ID0gbnVsbCkge1xuICAgICAgICBsZXQgdGl0bGUgPSAnUGxlYXNlIFdhaXQnO1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHRpdGxlX29yX2JvZHk7XG5cbiAgICAgICAgaWYgKGJvZHkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRpdGxlID0gdGl0bGVfb3JfYm9keTtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBib2R5O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRG9uJ3Qgd2FpdCBmb3IgdGhpcyBwcm9taXNlIC0gaXQgbmV2ZXIgcmVzb2x2ZXMgdW50aWwgY2xvc2VkIG1hbnVhbGx5XG4gICAgICAgIHRoaXMuX3Nob3dfbW9kYWwoe1xuICAgICAgICAgICAgdGl0bGU6IHRpdGxlLFxuICAgICAgICAgICAgYm9keTogbWVzc2FnZSxcbiAgICAgICAgICAgIGJ1dHRvbnM6IFtdLCAvLyBObyBidXR0b25zXG4gICAgICAgICAgICBjbG9zYWJsZTogZmFsc2UsIC8vIENhbid0IGNsb3NlXG4gICAgICAgICAgICBjbG9zZV9vbl9zdWJtaXQ6IGZhbHNlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBXYWl0IGZvciBuZXh0IGFuaW1hdGlvbiBmcmFtZSBmb3IgbW9kYWwgdG8gcmVuZGVyXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHJlc29sdmUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGEgbW9kYWwgd2l0aCBjdXN0b20galF1ZXJ5IGNvbnRlbnRcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9uc1xuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPCo+fVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBjdXN0b20ob3B0aW9ucykge1xuICAgICAgICAvLyBBbGlhcyBmb3Igc2hvdygpIC0gc2FtZSBmdW5jdGlvbmFsaXR5XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLnNob3cob3B0aW9ucyk7XG4gICAgfVxuXG4gICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgICAvLyBIZWxwZXIgTWV0aG9kc1xuICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAvKipcbiAgICAgKiBTaG93IGFuIGVycm9yIGFsZXJ0XG4gICAgICogQHBhcmFtIHsqfSBlcnJvcnNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgZXJyb3IoZXJyb3JzLCB0aXRsZSA9ICdFcnJvcicpIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSAnQW4gZXJyb3Igb2NjdXJyZWQnO1xuXG4gICAgICAgIC8vIEhhbmRsZSB2YXJpb3VzIGVycm9yIGZvcm1hdHNcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvcnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gZXJyb3JzO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9ycyAmJiAncmVzcG9uc2VKU09OJyBpbiBlcnJvcnMgJiYgJ21lc3NhZ2UnIGluIGVycm9ycy5yZXNwb25zZUpTT04pIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBlcnJvcnMucmVzcG9uc2VKU09OLm1lc3NhZ2U7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3JzICYmICdtZXNzYWdlJyBpbiBlcnJvcnMpIHtcbiAgICAgICAgICAgIG1lc3NhZ2UgPSBlcnJvcnMubWVzc2FnZTtcbiAgICAgICAgfSBlbHNlIGlmIChlcnJvcnMgJiYgdHlwZW9mIGVycm9ycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBmb3JtYXQgZXJyb3Igb2JqZWN0XG4gICAgICAgICAgICBjb25zdCBlcnJvcl9tZXNzYWdlcyA9IFtdO1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzX2FycmF5KGVycm9yc1trZXldKSkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlcy5wdXNoKGVycm9yc1trZXldWzBdKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlcy5wdXNoKGVycm9yc1trZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXJyb3JfbWVzc2FnZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBlcnJvcl9tZXNzYWdlcy5qb2luKCdcXG4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IHRoaXMuX3Nob3dfbW9kYWwoe1xuICAgICAgICAgICAgdGl0bGU6IHRpdGxlLFxuICAgICAgICAgICAgYm9keTogbWVzc2FnZSxcbiAgICAgICAgICAgIGljb246ICdleGNsYW1hdGlvbi1jaXJjbGUnLFxuICAgICAgICAgICAgYnV0dG9uczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbGFiZWw6ICdPSycsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBjbGFzczogJ2J0bi1kYW5nZXInLFxuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiB0cnVlLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgY2xvc2FibGU6IHRydWUsXG4gICAgICAgICAgICBjbG9zZV9vbl9zdWJtaXQ6IHRydWUsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlb3BlbiBjdXJyZW50IG1vZGFsIHdpdGggdmFsaWRhdGlvbiBlcnJvcnNcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZXJyb3JzXG4gICAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIHJlb3Blbl93aXRoX2Vycm9ycyhlcnJvcnMpIHtcbiAgICAgICAgaWYgKHRoaXMuX2N1cnJlbnQpIHtcbiAgICAgICAgICAgIC8vIE1vZGFsIGlzIHN0aWxsIG9wZW4sIGp1c3QgYXBwbHkgZXJyb3JzXG4gICAgICAgICAgICB0aGlzLmFwcGx5X2Vycm9ycyhlcnJvcnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdObyBtb2RhbCBvcGVuIHRvIGFwcGx5IGVycm9ycyB0bycpO1xuICAgICAgICB9XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7OztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU1BLEtBQUssQ0FBQztFQVdSO0FBQ0o7QUFDQTtBQUNBO0VBQ0ksT0FBT0MsS0FBS0EsQ0FBQSxFQUFHO0lBQ1gsSUFBSSxJQUFJLENBQUNDLFlBQVksRUFBRTtJQUN2QixJQUFJLENBQUNBLFlBQVksR0FBRyxJQUFJOztJQUV4QjtJQUNBLElBQUksQ0FBQ0MsU0FBUyxHQUFHQyxDQUFDLENBQUMseUNBQXlDLENBQUM7SUFDN0RBLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQ0MsTUFBTSxDQUFDLElBQUksQ0FBQ0YsU0FBUyxDQUFDO0VBQ3BDOztFQUVBO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7RUFDSSxPQUFP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