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>
651 lines
71 KiB
JavaScript
Executable File
651 lines
71 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
function _e8211f5b_defineProperty(e, r, t) { return (r = _e8211f5b_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
function _e8211f5b_toPropertyKey(t) { var i = _e8211f5b_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
function _e8211f5b_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); }
|
|
// @ROUTE-EXISTS-01-EXCEPTION - This file contains documentation examples with fictional route names
|
|
|
|
/**
|
|
* Rsx - Core JavaScript Runtime System
|
|
*
|
|
* The Rsx class is the central hub for the RSX JavaScript runtime, providing essential
|
|
* system-level utilities that all other framework components depend on. It serves as the
|
|
* foundation for the client-side framework, handling core operations that must be globally
|
|
* accessible and consistently available.
|
|
*
|
|
* Core Responsibilities:
|
|
* - Event System: Application-wide event bus for framework lifecycle and custom events
|
|
* - Environment Detection: Runtime environment identification (dev/production)
|
|
* - Route Management: Type-safe route generation and URL building
|
|
* - Unique ID Generation: Client-side unique identifier generation
|
|
* - Framework Bootstrap: Multi-phase initialization orchestration
|
|
* - Logging: Centralized logging interface (delegates to console_debug)
|
|
*
|
|
* The Rsx class deliberately keeps its scope limited to core utilities. Advanced features
|
|
* are delegated to specialized classes:
|
|
* - Manifest operations → Manifest class
|
|
* - Caching → Rsx_Cache class
|
|
* - AJAX/API calls → Ajax_* classes
|
|
* - Route proxies → Rsx_Route_Proxy class
|
|
* - Behaviors → Rsx_Behaviors class
|
|
*
|
|
* All methods are static - Rsx is never instantiated. It's available globally from the
|
|
* moment bundles load and remains constant throughout the application lifecycle.
|
|
*
|
|
* Usage Examples:
|
|
* ```javascript
|
|
* // Event system
|
|
* Rsx.on('app_ready', () => console.log('App initialized'));
|
|
* Rsx.trigger('custom_event', {data: 'value'});
|
|
*
|
|
* // Environment detection
|
|
* if (Rsx.is_dev()) { console.log('Development mode'); }
|
|
*
|
|
* // Route generation
|
|
* const url = Rsx.Route('Controller', 'action').url();
|
|
*
|
|
* // Unique IDs
|
|
* const uniqueId = Rsx.uid(); // e.g., "rsx_1234567890_1"
|
|
* ```
|
|
*
|
|
* @static
|
|
* @global
|
|
*/
|
|
class Rsx {
|
|
// Initialize event handlers storage
|
|
static _init_events() {
|
|
if (typeof Rsx._event_handlers === 'undefined') {
|
|
Rsx._event_handlers = {};
|
|
}
|
|
if (typeof Rsx._triggered_events === 'undefined') {
|
|
Rsx._triggered_events = {};
|
|
}
|
|
}
|
|
|
|
// Register an event handler
|
|
static on(event, callback) {
|
|
Rsx._init_events();
|
|
if (typeof callback !== 'function') {
|
|
throw new Error('Callback must be a function');
|
|
}
|
|
if (!Rsx._event_handlers[event]) {
|
|
Rsx._event_handlers[event] = [];
|
|
}
|
|
Rsx._event_handlers[event].push(callback);
|
|
|
|
// If this event was already triggered, call the callback immediately
|
|
if (Rsx._triggered_events[event]) {
|
|
console_debug('RSX_INIT', 'Triggering ' + event + ' for late registered callback');
|
|
callback(Rsx._triggered_events[event]);
|
|
}
|
|
}
|
|
|
|
// Trigger an event with optional data
|
|
static trigger(event) {
|
|
let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
Rsx._init_events();
|
|
|
|
// Record that this event was triggered
|
|
Rsx._triggered_events[event] = data;
|
|
if (!Rsx._event_handlers[event]) {
|
|
return;
|
|
}
|
|
console_debug('RSX_INIT', 'Triggering ' + event + ' for ' + Rsx._event_handlers[event].length + ' callbacks');
|
|
|
|
// Call all registered handlers for this event in order
|
|
for (const callback of Rsx._event_handlers[event]) {
|
|
callback(data);
|
|
}
|
|
}
|
|
|
|
// Alias for trigger.refresh(''), should be called after major UI updates to apply such effects as
|
|
// underlining links to unimplemented # routes
|
|
static trigger_refresh() {
|
|
// Use Rsx.on('refresh', callback); to register a callback for refresh
|
|
this.trigger('refresh');
|
|
}
|
|
|
|
// Log to server that an event happened
|
|
static log(type) {
|
|
let message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'notice';
|
|
Core_Log.log(type, message);
|
|
}
|
|
|
|
// Returns true if the app is being run in dev mode
|
|
// This should affect caching and some debug checks
|
|
static is_dev() {
|
|
return window.rsxapp.debug;
|
|
}
|
|
static is_prod() {
|
|
return !window.rsxapp.debug;
|
|
}
|
|
|
|
// Generates a unique number for the application instance
|
|
static uid() {
|
|
if (typeof Rsx._uid == undef) {
|
|
Rsx._uid = 0;
|
|
}
|
|
return Rsx._uid++;
|
|
}
|
|
|
|
// Storage for route definitions loaded from bundles
|
|
|
|
/**
|
|
* Define routes from bundled data
|
|
* Called by generated JavaScript in bundles
|
|
*/
|
|
static _define_routes(routes) {
|
|
// Merge routes into the global route storage
|
|
for (const class_name in routes) {
|
|
if (!Rsx._routes[class_name]) {
|
|
Rsx._routes[class_name] = {};
|
|
}
|
|
for (const method_name in routes[class_name]) {
|
|
Rsx._routes[class_name][method_name] = routes[class_name][method_name];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate URL for a controller route
|
|
*
|
|
* This method generates URLs for controller actions by looking up route patterns
|
|
* and replacing parameters. It handles both regular routes and Ajax endpoints.
|
|
*
|
|
* If the route is not found in the route definitions, a default pattern is used:
|
|
* `/_/{controller}/{action}` with all parameters appended as query strings.
|
|
*
|
|
* Usage examples:
|
|
* ```javascript
|
|
* // Simple route without parameters (defaults to 'index' action)
|
|
* const url = Rsx.Route('Frontend_Index_Controller');
|
|
* // Returns: /dashboard
|
|
*
|
|
* // Route with explicit action
|
|
* const url = Rsx.Route('Frontend_Index_Controller', 'index');
|
|
* // Returns: /dashboard
|
|
*
|
|
* // Route with integer parameter (sets 'id')
|
|
* const url = Rsx.Route('Frontend_Client_View_Controller', 'view', 123);
|
|
* // Returns: /clients/view/123
|
|
*
|
|
* // Route with named parameters (object)
|
|
* const url = Rsx.Route('Frontend_Client_View_Controller', 'view', {id: 'C001'});
|
|
* // Returns: /clients/view/C001
|
|
*
|
|
* // Route with required and query parameters
|
|
* const url = Rsx.Route('Frontend_Client_View_Controller', 'view', {
|
|
* id: 'C001',
|
|
* tab: 'history'
|
|
* });
|
|
* // Returns: /clients/view/C001?tab=history
|
|
*
|
|
* // Route not found - uses default pattern
|
|
* const url = Rsx.Route('Unimplemented_Controller', 'some_action', {foo: 'bar'});
|
|
* // Returns: /_/Unimplemented_Controller/some_action?foo=bar
|
|
*
|
|
* // Placeholder route
|
|
* const url = Rsx.Route('Future_Controller', '#index');
|
|
* // Returns: #
|
|
* ```
|
|
*
|
|
* @param {string} class_name The controller class name (e.g., 'User_Controller')
|
|
* @param {string} [action_name='index'] The action/method name (defaults to 'index'). Use '#action' for placeholders.
|
|
* @param {number|Object} [params=null] Route parameters. Integer sets 'id', object provides named params.
|
|
* @returns {string} The generated URL
|
|
*/
|
|
static Route(class_name) {
|
|
let action_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'index';
|
|
let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
// Normalize params to object
|
|
let params_obj = {};
|
|
if (typeof params === 'number') {
|
|
params_obj = {
|
|
id: params
|
|
};
|
|
} else if (params && typeof params === 'object') {
|
|
params_obj = params;
|
|
} else if (params !== null && params !== undefined) {
|
|
throw new Error('Params must be number, object, or null');
|
|
}
|
|
|
|
// Placeholder route: action starts with # means unimplemented/scaffolding
|
|
if (action_name.startsWith('#')) {
|
|
return '#';
|
|
}
|
|
|
|
// Check if route exists in definitions
|
|
let pattern;
|
|
if (Rsx._routes[class_name] && Rsx._routes[class_name][action_name]) {
|
|
pattern = Rsx._routes[class_name][action_name];
|
|
} else {
|
|
// Route not found - use default pattern /_/{controller}/{action}
|
|
pattern = `/_/${class_name}/${action_name}`;
|
|
}
|
|
|
|
// Generate URL from pattern
|
|
return Rsx._generate_url_from_pattern(pattern, params_obj);
|
|
}
|
|
|
|
/**
|
|
* Generate URL from route pattern by replacing parameters
|
|
*
|
|
* @param {string} pattern The route pattern (e.g., '/users/:id/view')
|
|
* @param {Object} params Parameters to fill into the route
|
|
* @returns {string} The generated URL
|
|
*/
|
|
static _generate_url_from_pattern(pattern, params) {
|
|
// Extract required parameters from the pattern
|
|
const required_params = [];
|
|
const matches = pattern.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g);
|
|
if (matches) {
|
|
// Remove the : prefix from each match
|
|
for (const match of matches) {
|
|
required_params.push(match.substring(1));
|
|
}
|
|
}
|
|
|
|
// Check for required parameters
|
|
const missing = [];
|
|
for (const required of required_params) {
|
|
if (!(required in params)) {
|
|
missing.push(required);
|
|
}
|
|
}
|
|
if (missing.length > 0) {
|
|
throw new Error(`Required parameters [${missing.join(', ')}] are missing for route ${pattern}`);
|
|
}
|
|
|
|
// Build the URL by replacing parameters
|
|
let url = pattern;
|
|
const used_params = {};
|
|
for (const param_name of required_params) {
|
|
const value = params[param_name];
|
|
// URL encode the value
|
|
const encoded_value = encodeURIComponent(value);
|
|
url = url.replace(':' + param_name, encoded_value);
|
|
used_params[param_name] = true;
|
|
}
|
|
|
|
// Collect any extra parameters for query string
|
|
const query_params = {};
|
|
for (const key in params) {
|
|
if (!used_params[key]) {
|
|
query_params[key] = params[key];
|
|
}
|
|
}
|
|
|
|
// Append query string if there are extra parameters
|
|
if (Object.keys(query_params).length > 0) {
|
|
const query_string = Object.entries(query_params).map(_ref => {
|
|
let [key, value] = _ref;
|
|
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
|
}).join('&');
|
|
url += '?' + query_string;
|
|
}
|
|
return url;
|
|
}
|
|
|
|
/**
|
|
* Internal: Call a specific method on all classes that have it
|
|
* Collects promises from return values and waits for all to resolve
|
|
* @param {string} method_name The method name to call on all classes
|
|
* @returns {Promise} Promise that resolves when all method calls complete
|
|
*/
|
|
static async _rsx_call_all_classes(method_name) {
|
|
const all_classes = Manifest.get_all_classes();
|
|
const classes_with_method = [];
|
|
const promise_pile = [];
|
|
for (const class_info of all_classes) {
|
|
const class_object = class_info.class_object;
|
|
const class_name = class_info.class_name;
|
|
|
|
// Check if this class has the method (static methods are on the class itself)
|
|
if (typeof class_object[method_name] === 'function') {
|
|
classes_with_method.push(class_name);
|
|
const return_value = await class_object[method_name]();
|
|
|
|
// Collect promises from return value
|
|
if (return_value instanceof Promise) {
|
|
promise_pile.push(return_value);
|
|
} else if (Array.isArray(return_value)) {
|
|
for (const item of return_value) {
|
|
if (item instanceof Promise) {
|
|
promise_pile.push(item);
|
|
}
|
|
}
|
|
}
|
|
if (Rsx.__stopped) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if (classes_with_method.length > 0) {
|
|
console_debug('RSX_INIT', `${method_name}: ${classes_with_method.length} classes`);
|
|
}
|
|
|
|
// Await all promises before returning
|
|
if (promise_pile.length > 0) {
|
|
console_debug('RSX_INIT', `${method_name}: Awaiting ${promise_pile.length} promises`);
|
|
await Promise.all(promise_pile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Internal: Execute multi-phase initialization for all registered classes
|
|
* This runs various initialization phases in order to properly set up the application
|
|
* @returns {Promise} Promise that resolves when all initialization phases complete
|
|
*/
|
|
static async _rsx_core_boot() {
|
|
if (Rsx.__booted) {
|
|
console.error('Rsx._rsx_core_boot called more than once');
|
|
return;
|
|
}
|
|
Rsx.__booted = true;
|
|
|
|
// Get all registered classes from the manifest
|
|
const all_classes = Manifest.get_all_classes();
|
|
console_debug('RSX_INIT', `Starting _rsx_core_boot with ${all_classes.length} classes`);
|
|
if (!all_classes || all_classes.length === 0) {
|
|
// No classes to initialize
|
|
shouldnt_happen('No classes registered in js - there should be at least the core framework classes');
|
|
return;
|
|
}
|
|
|
|
// Define initialization phases in order
|
|
const phases = [{
|
|
event: 'framework_core_define',
|
|
method: '_on_framework_core_define'
|
|
}, {
|
|
event: 'framework_modules_define',
|
|
method: '_on_framework_modules_define'
|
|
}, {
|
|
event: 'framework_core_init',
|
|
method: '_on_framework_core_init'
|
|
}, {
|
|
event: 'app_modules_define',
|
|
method: 'on_app_modules_define'
|
|
}, {
|
|
event: 'app_define',
|
|
method: 'on_app_define'
|
|
}, {
|
|
event: 'framework_modules_init',
|
|
method: '_on_framework_modules_init'
|
|
}, {
|
|
event: 'app_modules_init',
|
|
method: 'on_app_modules_init'
|
|
}, {
|
|
event: 'app_init',
|
|
method: 'on_app_init'
|
|
}, {
|
|
event: 'app_ready',
|
|
method: 'on_app_ready'
|
|
}];
|
|
|
|
// Execute each phase in order
|
|
for (const phase of phases) {
|
|
await Rsx._rsx_call_all_classes(phase.method);
|
|
if (Rsx.__stopped) {
|
|
return;
|
|
}
|
|
Rsx.trigger(phase.event);
|
|
}
|
|
|
|
// Ui refresh callbacks
|
|
Rsx.trigger_refresh();
|
|
|
|
// All phases complete
|
|
console_debug('RSX_INIT', 'Initialization complete');
|
|
|
|
// TODO: Find a good wait to wait for all jqhtml components to load, then trigger on_ready and on('ready') emulating the top level last syntax that jqhtml components operateas, but as a standard js class (such as a page class). The biggest question is, how do we efficiently choose only the top level jqhtml components. do we only consider components cretaed directly on blade templates? that seams reasonable...
|
|
|
|
// Trigger _debug_ready event - this is ONLY for tooling like rsx:debug
|
|
// DO NOT use this in application code - use on_app_ready() phase instead
|
|
// This event exists solely for debugging tools that need to run after full initialization
|
|
Rsx.trigger('_debug_ready');
|
|
}
|
|
|
|
/* Calling this stops the boot process. */
|
|
static async _rsx_core_boot_stop(reason) {
|
|
console.error(reason);
|
|
Rsx.__stopped = true;
|
|
}
|
|
|
|
/**
|
|
* Parse URL hash into key-value object
|
|
* Handles format: #key=value&key2=value2
|
|
*
|
|
* @returns {Object} Parsed hash parameters
|
|
*/
|
|
static _parse_hash() {
|
|
const hash = window.location.hash;
|
|
if (!hash || hash === '#') {
|
|
return {};
|
|
}
|
|
|
|
// Remove leading # and parse as query string
|
|
const hash_string = hash.substring(1);
|
|
const params = {};
|
|
const pairs = hash_string.split('&');
|
|
for (const pair of pairs) {
|
|
const [key, value] = pair.split('=');
|
|
if (key) {
|
|
params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
|
|
}
|
|
}
|
|
return params;
|
|
}
|
|
|
|
/**
|
|
* Serialize object into URL hash format
|
|
* Produces format: #key=value&key2=value2
|
|
*
|
|
* @param {Object} params Key-value pairs to encode
|
|
* @returns {string} Encoded hash string (with leading #, or empty string)
|
|
*/
|
|
static _serialize_hash(params) {
|
|
const pairs = [];
|
|
for (const key in params) {
|
|
const value = params[key];
|
|
if (value !== null && value !== undefined && value !== '') {
|
|
pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);
|
|
}
|
|
}
|
|
return pairs.length > 0 ? '#' + pairs.join('&') : '';
|
|
}
|
|
|
|
/**
|
|
* Get all page state from URL hash
|
|
*
|
|
* Usage:
|
|
* ```javascript
|
|
* const state = Rsx.get_all_page_state();
|
|
* // Returns: {dg_page: '2', dg_sort: 'name'}
|
|
* ```
|
|
*
|
|
* @returns {Object} All hash parameters as key-value pairs
|
|
*/
|
|
static get_all_page_state() {
|
|
return Rsx._parse_hash();
|
|
}
|
|
|
|
/**
|
|
* Get single value from URL hash state
|
|
*
|
|
* Usage:
|
|
* ```javascript
|
|
* const page = Rsx.get_page_state('dg_page');
|
|
* // Returns: '2' or null if not set
|
|
* ```
|
|
*
|
|
* @param {string} key The key to retrieve
|
|
* @returns {string|null} The value or null if not found
|
|
*/
|
|
static get_page_state(key) {
|
|
var _state$key;
|
|
const state = Rsx._parse_hash();
|
|
return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null;
|
|
}
|
|
|
|
/**
|
|
* Set single value in URL hash state (replaces history, doesn't add)
|
|
*
|
|
* Usage:
|
|
* ```javascript
|
|
* Rsx.set_page_state('dg_page', 2);
|
|
* // URL becomes: http://example.com/page#dg_page=2
|
|
*
|
|
* Rsx.set_page_state('dg_page', null); // Remove key
|
|
* ```
|
|
*
|
|
* @param {string} key The key to set
|
|
* @param {string|number|null} value The value (null/empty removes the key)
|
|
*/
|
|
static set_page_state(key, value) {
|
|
const state = Rsx._parse_hash();
|
|
|
|
// Update or remove the key
|
|
if (value === null || value === undefined || value === '') {
|
|
delete state[key];
|
|
} else {
|
|
state[key] = String(value);
|
|
}
|
|
|
|
// Update URL without adding history
|
|
const new_hash = Rsx._serialize_hash(state);
|
|
const url = window.location.pathname + window.location.search + new_hash;
|
|
history.replaceState(null, '', url);
|
|
}
|
|
|
|
/**
|
|
* Set multiple values in URL hash state at once
|
|
*
|
|
* Usage:
|
|
* ```javascript
|
|
* Rsx.set_all_page_state({dg_page: 2, dg_sort: 'name'});
|
|
* // URL becomes: http://example.com/page#dg_page=2&dg_sort=name
|
|
* ```
|
|
*
|
|
* @param {Object} new_state Object with key-value pairs to set
|
|
*/
|
|
static set_all_page_state(new_state) {
|
|
const state = Rsx._parse_hash();
|
|
|
|
// Merge new state
|
|
for (const key in new_state) {
|
|
const value = new_state[key];
|
|
if (value === null || value === undefined || value === '') {
|
|
delete state[key];
|
|
} else {
|
|
state[key] = String(value);
|
|
}
|
|
}
|
|
|
|
// Update URL without adding history
|
|
const new_hash = Rsx._serialize_hash(state);
|
|
const url = window.location.pathname + window.location.search + new_hash;
|
|
history.replaceState(null, '', url);
|
|
}
|
|
|
|
/**
|
|
* Render an error in a DOM element
|
|
*
|
|
* Displays errors from Ajax calls in a standardized format. Handles different
|
|
* error types (fatal, validation, auth, generic) with appropriate formatting.
|
|
*
|
|
* Usage:
|
|
* ```javascript
|
|
* try {
|
|
* const result = await Controller.method();
|
|
* } catch (error) {
|
|
* Rsx.render_error(error, '#error_container');
|
|
* }
|
|
* ```
|
|
*
|
|
* @param {Error|Object} error - Error object from Ajax call
|
|
* @param {jQuery|string} container - jQuery element or selector for error display
|
|
*/
|
|
static render_error(error, container) {
|
|
const $container = $(container);
|
|
if (!$container.exists()) {
|
|
console.error('Rsx.render_error: Container not found', container);
|
|
return;
|
|
}
|
|
|
|
// Clear existing content
|
|
$container.empty();
|
|
let html = '';
|
|
|
|
// Handle different error types
|
|
if (error.type === 'fatal' && error.details) {
|
|
// Fatal PHP error with file/line/error
|
|
const details = error.details;
|
|
const file = details.file || 'Unknown file';
|
|
const line = details.line || '?';
|
|
const message = details.error || error.message || 'Fatal error occurred';
|
|
html = `
|
|
<div class="alert alert-danger" role="alert">
|
|
<h5>Uncaught Fatal Error in ${file}:${line}:</h5>
|
|
<p class="mb-0">${Rsx._escape_html(message)}</p>
|
|
</div>
|
|
`;
|
|
} else if (error.type === 'form_error' && error.details) {
|
|
// Validation errors - show unmatched errors only
|
|
// (matched errors should be handled by Form_Utils.apply_form_errors)
|
|
const errors = error.details;
|
|
const error_list = [];
|
|
for (const field in errors) {
|
|
error_list.push(errors[field]);
|
|
}
|
|
if (error_list.length > 0) {
|
|
html = `
|
|
<div class="alert alert-warning" role="alert">
|
|
<h5>Validation Errors:</h5>
|
|
<ul class="mb-0">
|
|
${error_list.map(err => `<li>${Rsx._escape_html(err)}</li>`).join('')}
|
|
</ul>
|
|
</div>
|
|
`;
|
|
}
|
|
} else if (error.type === 'auth_required' || error.type === 'unauthorized') {
|
|
// Authentication/authorization errors
|
|
const message = error.message || 'Authentication required';
|
|
html = `
|
|
<div class="alert alert-warning" role="alert">
|
|
<p class="mb-0">${Rsx._escape_html(message)}</p>
|
|
</div>
|
|
`;
|
|
} else if (error.type === 'network') {
|
|
// Network errors
|
|
const message = error.message || 'Unable to reach server. Please check your connection.';
|
|
html = `
|
|
<div class="alert alert-danger" role="alert">
|
|
<p class="mb-0">${Rsx._escape_html(message)}</p>
|
|
</div>
|
|
`;
|
|
} else {
|
|
// Generic/unknown error
|
|
const message = error.message || error.toString() || 'An unknown error occurred';
|
|
html = `
|
|
<div class="alert alert-danger" role="alert">
|
|
<p class="mb-0">${Rsx._escape_html(message)}</p>
|
|
</div>
|
|
`;
|
|
}
|
|
$container.html(html);
|
|
}
|
|
|
|
/**
|
|
* Escape HTML to prevent XSS in error messages
|
|
* @private
|
|
*/
|
|
static _escape_html(text) {
|
|
const div = document.createElement('div');
|
|
div.textContent = text;
|
|
return div.innerHTML;
|
|
}
|
|
}
|
|
// Gets set to true to interupt startup sequence
|
|
_e8211f5b_defineProperty(Rsx, "__stopped", false);
|
|
_e8211f5b_defineProperty(Rsx, "_routes", {});
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSc3giLCJfaW5pdF9ldmVudHMiLCJfZXZlbnRfaGFuZGxlcnMiLCJfdHJpZ2dlcmVkX2V2ZW50cyIsIm9uIiwiZXZlbnQiLCJjYWxsYmFjayIsIkVycm9yIiwicHVzaCIsImNvbnNvbGVfZGVidWciLCJ0cmlnZ2VyIiwiZGF0YSIsImFyZ3VtZW50cyIsImxlbmd0aCIsInVuZGVmaW5lZCIsInRyaWdnZXJfcmVmcmVzaCIsImxvZyIsInR5cGUiLCJtZXNzYWdlIiwiQ29yZV9Mb2ciLCJpc19kZXYiLCJ3aW5kb3ciLCJyc3hhcHAiLCJkZWJ1ZyIsImlzX3Byb2QiLCJ1aWQiLCJfdWlkIiwidW5kZWYiLCJfZGVmaW5lX3JvdXRlcyIsInJvdXRlcyIsImNsYXNzX25hbWUiLCJfcm91dGVzIiwibWV0aG9kX25hbWUiLCJSb3V0ZSIsImFjdGlvbl9uYW1lIiwicGFyYW1zIiwicGFyYW1zX29iaiIsImlkIiwic3RhcnRzV2l0aCIsInBhdHRlcm4iLCJfZ2VuZXJhdGVfdXJsX2Zyb21fcGF0dGVybiIsInJlcXVpcmVkX3BhcmFtcyIsIm1hdGNoZXMiLCJtYXRjaCIsInN1YnN0cmluZyIsIm1pc3NpbmciLCJyZXF1aXJlZCIsImpvaW4iLCJ1cmwiLCJ1c2VkX3BhcmFtcyIsInBhcmFtX25hbWUiLCJ2YWx1ZSIsImVuY29kZWRfdmFsdWUiLCJlbmNvZGVVUklDb21wb25lbnQiLCJyZXBsYWNlIiwicXVlcnlfcGFyYW1zIiwia2V5IiwiT2JqZWN0Iiwia2V5cyIsInF1ZXJ5X3N0cmluZyIsImVudHJpZXMiLCJtYXAiLCJfcmVmIiwiX3JzeF9jYWxsX2FsbF9jbGFzc2VzIiwiYWxsX2NsYXNzZXMiLCJNYW5pZmVzdCIsImdldF9hbGxfY2xhc3NlcyIsImNsYXNzZXNfd2l0aF9tZXRob2QiLCJwcm9taXNlX3BpbGUiLCJjbGFzc19pbmZvIiwiY2xhc3Nfb2JqZWN0IiwicmV0dXJuX3ZhbHVlIiwiUHJvbWlzZSIsIkFycmF5IiwiaXNBcnJheSIsIml0ZW0iLCJfX3N0b3BwZWQiLCJhbGwiLCJfcnN4X2NvcmVfYm9vdCIsIl9fYm9vdGVkIiwiY29uc29sZSIsImVycm9yIiwic2hvdWxkbnRfaGFwcGVuIiwicGhhc2VzIiwibWV0aG9kIiwicGhhc2UiLCJfcnN4X2NvcmVfYm9vdF9zdG9wIiwicmVhc29uIiwiX3BhcnNlX2hhc2giLCJoYXNoIiwibG9jYXRpb24iLCJoYXNoX3N0cmluZyIsInBhaXJzIiwic3BsaXQiLCJwYWlyIiwiZGVjb2RlVVJJQ29tcG9uZW50IiwiX3NlcmlhbGl6ZV9oYXNoIiwiZ2V0X2FsbF9wYWdlX3N0YXRlIiwiZ2V0X3BhZ2Vfc3RhdGUiLCJfc3RhdGUka2V5Iiwic3RhdGUiLCJzZXRfcGFnZV9zdGF0ZSIsIlN0cmluZyIsIm5ld19oYXNoIiwicGF0aG5hbWUiLCJzZWFyY2giLCJoaXN0b3J5IiwicmVwbGFjZVN0YXRlIiwic2V0X2FsbF9wYWdlX3N0YXRlIiwibmV3X3N0YXRlIiwicmVuZGVyX2Vycm9yIiwiY29udGFpbmVyIiwiJGNvbnRhaW5lciIsIiQiLCJleGlzdHMiLCJlbXB0eSIsImh0bWwiLCJkZXRhaWxzIiwiZmlsZSIsImxpbmUiLCJfZXNjYXBlX2h0bWwiLCJlcnJvcnMiLCJlcnJvcl9saXN0IiwiZmllbGQiLCJlcnIiLCJ0b1N0cmluZyIsInRleHQiLCJkaXYiLCJkb2N1bWVudCIsImNyZWF0ZUVsZW1lbnQiLCJ0ZXh0Q29udGVudCIsImlubmVySFRNTCIsIl9lODIxMWY1Yl9kZWZpbmVQcm9wZXJ0eSJdLCJzb3VyY2VzIjpbImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3guanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQFJPVVRFLUVYSVNUUy0wMS1FWENFUFRJT04gLSBUaGlzIGZpbGUgY29udGFpbnMgZG9jdW1lbnRhdGlvbiBleGFtcGxlcyB3aXRoIGZpY3Rpb25hbCByb3V0ZSBuYW1lc1xuXG4vKipcbiAqIFJzeCAtIENvcmUgSmF2YVNjcmlwdCBSdW50aW1lIFN5c3RlbVxuICpcbiAqIFRoZSBSc3ggY2xhc3MgaXMgdGhlIGNlbnRyYWwgaHViIGZvciB0aGUgUlNYIEphdmFTY3JpcHQgcnVudGltZSwgcHJvdmlkaW5nIGVzc2VudGlhbFxuICogc3lzdGVtLWxldmVsIHV0aWxpdGllcyB0aGF0IGFsbCBvdGhlciBmcmFtZXdvcmsgY29tcG9uZW50cyBkZXBlbmQgb24uIEl0IHNlcnZlcyBhcyB0aGVcbiAqIGZvdW5kYXRpb24gZm9yIHRoZSBjbGllbnQtc2lkZSBmcmFtZXdvcmssIGhhbmRsaW5nIGNvcmUgb3BlcmF0aW9ucyB0aGF0IG11c3QgYmUgZ2xvYmFsbHlcbiAqIGFjY2Vzc2libGUgYW5kIGNvbnNpc3RlbnRseSBhdmFpbGFibGUuXG4gKlxuICogQ29yZSBSZXNwb25zaWJpbGl0aWVzOlxuICogLSBFdmVudCBTeXN0ZW06IEFwcGxpY2F0aW9uLXdpZGUgZXZlbnQgYnVzIGZvciBmcmFtZXdvcmsgbGlmZWN5Y2xlIGFuZCBjdXN0b20gZXZlbnRzXG4gKiAtIEVudmlyb25tZW50IERldGVjdGlvbjogUnVudGltZSBlbnZpcm9ubWVudCBpZGVudGlmaWNhdGlvbiAoZGV2L3Byb2R1Y3Rpb24pXG4gKiAtIFJvdXRlIE1hbmFnZW1lbnQ6IFR5cGUtc2FmZSByb3V0ZSBnZW5lcmF0aW9uIGFuZCBVUkwgYnVpbGRpbmdcbiAqIC0gVW5pcXVlIElEIEdlbmVyYXRpb246IENsaWVudC1zaWRlIHVuaXF1ZSBpZGVudGlmaWVyIGdlbmVyYXRpb25cbiAqIC0gRnJhbWV3b3JrIEJvb3RzdHJhcDogTXVsdGktcGhhc2UgaW5pdGlhbGl6YXRpb24gb3JjaGVzdHJhdGlvblxuICogLSBMb2dnaW5nOiBDZW50cmFsaXplZCBsb2dnaW5nIGludGVyZmFjZSAoZGVsZWdhdGVzIHRvIGNvbnNvbGVfZGVidWcpXG4gKlxuICogVGhlIFJzeCBjbGFzcyBkZWxpYmVyYXRlbHkga2VlcHMgaXRzIHNjb3BlIGxpbWl0ZWQgdG8gY29yZSB1dGlsaXRpZXMuIEFkdmFuY2VkIGZlYXR1cmVzXG4gKiBhcmUgZGVsZWdhdGVkIHRvIHNwZWNpYWxpemVkIGNsYXNzZXM6XG4gKiAtIE1hbmlmZXN0IG9wZXJhdGlvbnMg4oaSIE1hbmlmZXN0IGNsYXNzXG4gKiAtIENhY2hpbmcg4oaSIFJzeF9DYWNoZSBjbGFzc1xuICogLSBBSkFYL0FQSSBjYWxscyDihpIgQWpheF8qIGNsYXNzZXNcbiAqIC0gUm91dGUgcHJveGllcyDihpIgUnN4X1JvdXRlX1Byb3h5IGNsYXNzXG4gKiAtIEJlaGF2aW9ycyDihpIgUnN4X0JlaGF2aW9ycyBjbGFzc1xuICpcbiAqIEFsbCBtZXRob2RzIGFyZSBzdGF0aWMgLSBSc3ggaXMgbmV2ZXIgaW5zdGFudGlhdGVkLiBJdCdzIGF2YWlsYWJsZSBnbG9iYWxseSBmcm9tIHRoZVxuICogbW9tZW50IGJ1bmRsZXMgbG9hZCBhbmQgcmVtYWlucyBjb25zdGFudCB0aHJvdWdob3V0IHRoZSBhcHBsaWNhdGlvbiBsaWZlY3ljbGUuXG4gKlxuICogVXNhZ2UgRXhhbXBsZXM6XG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBFdmVudCBzeXN0ZW1cbiAqIFJzeC5vbignYXBwX3JlYWR5JywgKCkgPT4gY29uc29sZS5sb2coJ0FwcCBpbml0aWFsaXplZCcpKTtcbiAqIFJzeC50cmlnZ2VyKCdjdXN0b21fZXZlbnQnLCB7ZGF0YTogJ3ZhbHVlJ30pO1xuICpcbiAqIC8vIEVudmlyb25tZW50IGRldGVjdGlvblxuICogaWYgKFJzeC5pc19kZXYoKSkgeyBjb25zb2xlLmxvZygnRGV2ZWxvcG1lbnQgbW9kZScpOyB9XG4gKlxuICogLy8gUm91dGUgZ2VuZXJhdGlvblxuICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdDb250cm9sbGVyJywgJ2FjdGlvbicpLnVybCgpO1xuICpcbiAqIC8vIFVuaXF1ZSBJRHNcbiAqIGNvbnN0IHVuaXF1ZUlkID0gUnN4LnVpZCgpOyAvLyBlLmcuLCBcInJzeF8xMjM0NTY3ODkwXzFcIlxuICogYGBgXG4gKlxuICogQHN0YXRpY1xuICogQGdsb2JhbFxuICovXG5jbGFzcyBSc3gge1xuICAgIC8vIEdldHMgc2V0IHRvIHRydWUgdG8gaW50ZXJ1cHQgc3RhcnR1cCBzZXF1ZW5jZVxuICAgIHN0YXRpYyBfX3N0b3BwZWQgPSBmYWxzZTtcblxuICAgIC8vIEluaXRpYWxpemUgZXZlbnQgaGFuZGxlcnMgc3RvcmFnZVxuICAgIHN0YXRpYyBfaW5pdF9ldmVudHMoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgUnN4Ll9ldmVudF9oYW5kbGVycyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIFJzeC5fZXZlbnRfaGFuZGxlcnMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIFJzeC5fdHJpZ2dlcmVkX2V2ZW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIFJzeC5fdHJpZ2dlcmVkX2V2ZW50cyA9IHt9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmVnaXN0ZXIgYW4gZXZlbnQgaGFuZGxlclxuICAgIHN0YXRpYyBvbihldmVudCwgY2FsbGJhY2spIHtcbiAgICAgICAgUnN4Ll9pbml0X2V2ZW50cygpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XSA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0ucHVzaChjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gSWYgdGhpcyBldmVudCB3YXMgYWxyZWFkeSB0cmlnZ2VyZWQsIGNhbGwgdGhlIGNhbGxiYWNrIGltbWVkaWF0ZWx5XG4gICAgICAgIGlmIChSc3guX3RyaWdnZXJlZF9ldmVudHNbZXZlbnRdKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdUcmlnZ2VyaW5nICcgKyBldmVudCArICcgZm9yIGxhdGUgcmVnaXN0ZXJlZCBjYWxsYmFjaycpO1xuICAgICAgICAgICAgY2FsbGJhY2soUnN4Ll90cmlnZ2VyZWRfZXZlbnRzW2V2ZW50XSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUcmlnZ2VyIGFuIGV2ZW50IHdpdGggb3B0aW9uYWwgZGF0YVxuICAgIHN0YXRpYyB0cmlnZ2VyKGV2ZW50LCBkYXRhID0ge30pIHtcbiAgICAgICAgUnN4Ll9pbml0X2V2ZW50cygpO1xuXG4gICAgICAgIC8vIFJlY29yZCB0aGF0IHRoaXMgZXZlbnQgd2FzIHRyaWdnZXJlZFxuICAgICAgICBSc3guX3RyaWdnZXJlZF9ldmVudHNbZXZlbnRdID0gZGF0YTtcblxuICAgICAgICBpZiAoIVJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdUcmlnZ2VyaW5nICcgKyBldmVudCArICcgZm9yICcgKyBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XS5sZW5ndGggKyAnIGNhbGxiYWNrcycpO1xuXG4gICAgICAgIC8vIENhbGwgYWxsIHJlZ2lzdGVyZWQgaGFuZGxlcnMgZm9yIHRoaXMgZXZlbnQgaW4gb3JkZXJcbiAgICAgICAgZm9yIChjb25zdCBjYWxsYmFjayBvZiBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XSkge1xuICAgICAgICAgICAgY2FsbGJhY2soZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbGlhcyBmb3IgdHJpZ2dlci5yZWZyZXNoKCcnKSwgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciBtYWpvciBVSSB1cGRhdGVzIHRvIGFwcGx5IHN1Y2ggZWZmZWN0cyBhc1xuICAgIC8vIHVuZGVybGluaW5nIGxpbmtzIHRvIHVuaW1wbGVtZW50ZWQgIyByb3V0ZXNcbiAgICBzdGF0aWMgdHJpZ2dlcl9yZWZyZXNoKCkge1xuICAgICAgICAvLyBVc2UgUnN4Lm9uKCdyZWZyZXNoJywgY2FsbGJhY2spOyB0byByZWdpc3RlciBhIGNhbGxiYWNrIGZvciByZWZyZXNoXG4gICAgICAgIHRoaXMudHJpZ2dlcigncmVmcmVzaCcpO1xuICAgIH1cblxuICAgIC8vIExvZyB0byBzZXJ2ZXIgdGhhdCBhbiBldmVudCBoYXBwZW5lZFxuICAgIHN0YXRpYyBsb2codHlwZSwgbWVzc2FnZSA9ICdub3RpY2UnKSB7XG4gICAgICAgIENvcmVfTG9nLmxvZyh0eXBlLCBtZXNzYWdlKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhlIGFwcCBpcyBiZWluZyBydW4gaW4gZGV2IG1vZGVcbiAgICAvLyBUaGlzIHNob3VsZCBhZmZlY3QgY2FjaGluZyBhbmQgc29tZSBkZWJ1ZyBjaGVja3NcbiAgICBzdGF0aWMgaXNfZGV2KCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnJzeGFwcC5kZWJ1ZztcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNfcHJvZCgpIHtcbiAgICAgICAgcmV0dXJuICF3aW5kb3cucnN4YXBwLmRlYnVnO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlcyBhIHVuaXF1ZSBudW1iZXIgZm9yIHRoZSBhcHBsaWNhdGlvbiBpbnN0YW5jZVxuICAgIHN0YXRpYyB1aWQoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgUnN4Ll91aWQgPT0gdW5kZWYpIHtcbiAgICAgICAgICAgIFJzeC5fdWlkID0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUnN4Ll91aWQrKztcbiAgICB9XG5cbiAgICAvLyBTdG9yYWdlIGZvciByb3V0ZSBkZWZpbml0aW9ucyBsb2FkZWQgZnJvbSBidW5kbGVzXG4gICAgc3RhdGljIF9yb3V0ZXMgPSB7fTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZSByb3V0ZXMgZnJvbSBidW5kbGVkIGRhdGFcbiAgICAgKiBDYWxsZWQgYnkgZ2VuZXJhdGVkIEphdmFTY3JpcHQgaW4gYnVuZGxlc1xuICAgICAqL1xuICAgIHN0YXRpYyBfZGVmaW5lX3JvdXRlcyhyb3V0ZXMpIHtcbiAgICAgICAgLy8gTWVyZ2Ugcm91dGVzIGludG8gdGhlIGdsb2JhbCByb3V0ZSBzdG9yYWdlXG4gICAgICAgIGZvciAoY29uc3QgY2xhc3NfbmFtZSBpbiByb3V0ZXMpIHtcbiAgICAgICAgICAgIGlmICghUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV0pIHtcbiAgICAgICAgICAgICAgICBSc3guX3JvdXRlc1tjbGFzc19uYW1lXSA9IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCBtZXRob2RfbmFtZSBpbiByb3V0ZXNbY2xhc3NfbmFtZV0pIHtcbiAgICAgICAgICAgICAgICBSc3guX3JvdXRlc1tjbGFzc19uYW1lXVttZXRob2RfbmFtZV0gPSByb3V0ZXNbY2xhc3NfbmFtZV1bbWV0aG9kX25hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgVVJMIGZvciBhIGNvbnRyb2xsZXIgcm91dGVcbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGdlbmVyYXRlcyBVUkxzIGZvciBjb250cm9sbGVyIGFjdGlvbnMgYnkgbG9va2luZyB1cCByb3V0ZSBwYXR0ZXJuc1xuICAgICAqIGFuZCByZXBsYWNpbmcgcGFyYW1ldGVycy4gSXQgaGFuZGxlcyBib3RoIHJlZ3VsYXIgcm91dGVzIGFuZCBBamF4IGVuZHBvaW50cy5cbiAgICAgKlxuICAgICAqIElmIHRoZSByb3V0ZSBpcyBub3QgZm91bmQgaW4gdGhlIHJvdXRlIGRlZmluaXRpb25zLCBhIGRlZmF1bHQgcGF0dGVybiBpcyB1c2VkOlxuICAgICAqIGAvXy97Y29udHJvbGxlcn0ve2FjdGlvbn1gIHdpdGggYWxsIHBhcmFtZXRlcnMgYXBwZW5kZWQgYXMgcXVlcnkgc3RyaW5ncy5cbiAgICAgKlxuICAgICAqIFVzYWdlIGV4YW1wbGVzOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiAvLyBTaW1wbGUgcm91dGUgd2l0aG91dCBwYXJhbWV0ZXJzIChkZWZhdWx0cyB0byAnaW5kZXgnIGFjdGlvbilcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0luZGV4X0NvbnRyb2xsZXInKTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvZGFzaGJvYXJkXG4gICAgICpcbiAgICAgKiAvLyBSb3V0ZSB3aXRoIGV4cGxpY2l0IGFjdGlvblxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfSW5kZXhfQ29udHJvbGxlcicsICdpbmRleCcpO1xuICAgICAqIC8vIFJldHVybnM6IC9kYXNoYm9hcmRcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggaW50ZWdlciBwYXJhbWV0ZXIgKHNldHMgJ2lkJylcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0NsaWVudF9WaWV3X0NvbnRyb2xsZXInLCAndmlldycsIDEyMyk7XG4gICAgICogLy8gUmV0dXJuczogL2NsaWVudHMvdmlldy8xMjNcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggbmFtZWQgcGFyYW1ldGVycyAob2JqZWN0KVxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfQ2xpZW50X1ZpZXdfQ29udHJvbGxlcicsICd2aWV3Jywge2lkOiAnQzAwMSd9KTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvY2xpZW50cy92aWV3L0MwMDFcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggcmVxdWlyZWQgYW5kIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0NsaWVudF9WaWV3X0NvbnRyb2xsZXInLCAndmlldycsIHtcbiAgICAgKiAgICAgaWQ6ICdDMDAxJyxcbiAgICAgKiAgICAgdGFiOiAnaGlzdG9yeSdcbiAgICAgKiB9KTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvY2xpZW50cy92aWV3L0MwMDE/dGFiPWhpc3RvcnlcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIG5vdCBmb3VuZCAtIHVzZXMgZGVmYXVsdCBwYXR0ZXJuXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdVbmltcGxlbWVudGVkX0NvbnRyb2xsZXInLCAnc29tZV9hY3Rpb24nLCB7Zm9vOiAnYmFyJ30pO1xuICAgICAqIC8vIFJldHVybnM6IC9fL1VuaW1wbGVtZW50ZWRfQ29udHJvbGxlci9zb21lX2FjdGlvbj9mb289YmFyXG4gICAgICpcbiAgICAgKiAvLyBQbGFjZWhvbGRlciByb3V0ZVxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnV0dXJlX0NvbnRyb2xsZXInLCAnI2luZGV4Jyk7XG4gICAgICogLy8gUmV0dXJuczogI1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzX25hbWUgVGhlIGNvbnRyb2xsZXIgY2xhc3MgbmFtZSAoZS5nLiwgJ1VzZXJfQ29udHJvbGxlcicpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFthY3Rpb25fbmFtZT0naW5kZXgnXSBUaGUgYWN0aW9uL21ldGhvZCBuYW1lIChkZWZhdWx0cyB0byAnaW5kZXgnKS4gVXNlICcjYWN0aW9uJyBmb3IgcGxhY2Vob2xkZXJzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfE9iamVjdH0gW3BhcmFtcz1udWxsXSBSb3V0ZSBwYXJhbWV0ZXJzLiBJbnRlZ2VyIHNldHMgJ2lkJywgb2JqZWN0IHByb3ZpZGVzIG5hbWVkIHBhcmFtcy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIFVSTFxuICAgICAqL1xuICAgIHN0YXRpYyBSb3V0ZShjbGFzc19uYW1lLCBhY3Rpb25fbmFtZSA9ICdpbmRleCcsIHBhcmFtcyA9IG51bGwpIHtcbiAgICAgICAgLy8gTm9ybWFsaXplIHBhcmFtcyB0byBvYmplY3RcbiAgICAgICAgbGV0IHBhcmFtc19vYmogPSB7fTtcbiAgICAgICAgaWYgKHR5cGVvZiBwYXJhbXMgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBwYXJhbXNfb2JqID0geyBpZDogcGFyYW1zIH07XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBwYXJhbXNfb2JqID0gcGFyYW1zO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtcyAhPT0gbnVsbCAmJiBwYXJhbXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQYXJhbXMgbXVzdCBiZSBudW1iZXIsIG9iamVjdCwgb3IgbnVsbCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGxhY2Vob2xkZXIgcm91dGU6IGFjdGlvbiBzdGFydHMgd2l0aCAjIG1lYW5zIHVuaW1wbGVtZW50ZWQvc2NhZmZvbGRpbmdcbiAgICAgICAgaWYgKGFjdGlvbl9uYW1lLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICAgICAgcmV0dXJuICcjJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIHJvdXRlIGV4aXN0cyBpbiBkZWZpbml0aW9uc1xuICAgICAgICBsZXQgcGF0dGVybjtcbiAgICAgICAgaWYgKFJzeC5fcm91dGVzW2NsYXNzX25hbWVdICYmIFJzeC5fcm91dGVzW2NsYXNzX25hbWVdW2FjdGlvbl9uYW1lXSkge1xuICAgICAgICAgICAgcGF0dGVybiA9IFJzeC5fcm91dGVzW2NsYXNzX25hbWVdW2FjdGlvbl9uYW1lXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJvdXRlIG5vdCBmb3VuZCAtIHVzZSBkZWZhdWx0IHBhdHRlcm4gL18ve2NvbnRyb2xsZXJ9L3thY3Rpb259XG4gICAgICAgICAgICBwYXR0ZXJuID0gYC9fLyR7Y2xhc3NfbmFtZX0vJHthY3Rpb25fbmFtZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgVVJMIGZyb20gcGF0dGVyblxuICAgICAgICByZXR1cm4gUnN4Ll9nZW5lcmF0ZV91cmxfZnJvbV9wYXR0ZXJuKHBhdHRlcm4sIHBhcmFtc19vYmopO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIFVSTCBmcm9tIHJvdXRlIHBhdHRlcm4gYnkgcmVwbGFjaW5nIHBhcmFtZXRlcnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXR0ZXJuIFRoZSByb3V0ZSBwYXR0ZXJuIChlLmcuLCAnL3VzZXJzLzppZC92aWV3JylcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIFBhcmFtZXRlcnMgdG8gZmlsbCBpbnRvIHRoZSByb3V0ZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgVVJMXG4gICAgICovXG4gICAgc3RhdGljIF9nZW5lcmF0ZV91cmxfZnJvbV9wYXR0ZXJuKHBhdHRlcm4sIHBhcmFtcykge1xuICAgICAgICAvLyBFeHRyYWN0IHJlcXVpcmVkIHBhcmFtZXRlcnMgZnJvbSB0aGUgcGF0dGVyblxuICAgICAgICBjb25zdCByZXF1aXJlZF9wYXJhbXMgPSBbXTtcbiAgICAgICAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWF0Y2goLzooW2EtekEtWl9dW2EtekEtWjAtOV9dKikvZyk7XG4gICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIDogcHJlZml4IGZyb20gZWFjaCBtYXRjaFxuICAgICAgICAgICAgZm9yIChjb25zdCBtYXRjaCBvZiBtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgcmVxdWlyZWRfcGFyYW1zLnB1c2gobWF0Y2guc3Vic3RyaW5nKDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGZvciByZXF1aXJlZCBwYXJhbWV0ZXJzXG4gICAgICAgIGNvbnN0IG1pc3NpbmcgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCByZXF1aXJlZCBvZiByZXF1aXJlZF9wYXJhbXMpIHtcbiAgICAgICAgICAgIGlmICghKHJlcXVpcmVkIGluIHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICBtaXNzaW5nLnB1c2gocmVxdWlyZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1pc3NpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXF1aXJlZCBwYXJhbWV0ZXJzIFske21pc3Npbmcuam9pbignLCAnKX1dIGFyZSBtaXNzaW5nIGZvciByb3V0ZSAke3BhdHRlcm59YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBCdWlsZCB0aGUgVVJMIGJ5IHJlcGxhY2luZyBwYXJhbWV0ZXJzXG4gICAgICAgIGxldCB1cmwgPSBwYXR0ZXJuO1xuICAgICAgICBjb25zdCB1c2VkX3BhcmFtcyA9IHt9O1xuXG4gICAgICAgIGZvciAoY29uc3QgcGFyYW1fbmFtZSBvZiByZXF1aXJlZF9wYXJhbXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcGFyYW1zW3BhcmFtX25hbWVdO1xuICAgICAgICAgICAgLy8gVVJMIGVuY29kZSB0aGUgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IGVuY29kZWRfdmFsdWUgPSBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICAgICAgICAgICAgdXJsID0gdXJsLnJlcGxhY2UoJzonICsgcGFyYW1fbmFtZSwgZW5jb2RlZF92YWx1ZSk7XG4gICAgICAgICAgICB1c2VkX3BhcmFtc1twYXJhbV9uYW1lXSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb2xsZWN0IGFueSBleHRyYSBwYXJhbWV0ZXJzIGZvciBxdWVyeSBzdHJpbmdcbiAgICAgICAgY29uc3QgcXVlcnlfcGFyYW1zID0ge307XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHBhcmFtcykge1xuICAgICAgICAgICAgaWYgKCF1c2VkX3BhcmFtc1trZXldKSB7XG4gICAgICAgICAgICAgICAgcXVlcnlfcGFyYW1zW2tleV0gPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFwcGVuZCBxdWVyeSBzdHJpbmcgaWYgdGhlcmUgYXJlIGV4dHJhIHBhcmFtZXRlcnNcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHF1ZXJ5X3BhcmFtcykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcXVlcnlfc3RyaW5nID0gT2JqZWN0LmVudHJpZXMocXVlcnlfcGFyYW1zKVxuICAgICAgICAgICAgICAgIC5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGtleSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKX1gKVxuICAgICAgICAgICAgICAgIC5qb2luKCcmJyk7XG4gICAgICAgICAgICB1cmwgKz0gJz8nICsgcXVlcnlfc3RyaW5nO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogQ2FsbCBhIHNwZWNpZmljIG1ldGhvZCBvbiBhbGwgY2xhc3NlcyB0aGF0IGhhdmUgaXRcbiAgICAgKiBDb2xsZWN0cyBwcm9taXNlcyBmcm9tIHJldHVybiB2YWx1ZXMgYW5kIHdhaXRzIGZvciBhbGwgdG8gcmVzb2x2ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RfbmFtZSBUaGUgbWV0aG9kIG5hbWUgdG8gY2FsbCBvbiBhbGwgY2xhc3Nlc1xuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgbWV0aG9kIGNhbGxzIGNvbXBsZXRlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9yc3hfY2FsbF9hbGxfY2xhc3NlcyhtZXRob2RfbmFtZSkge1xuICAgICAgICBjb25zdCBhbGxfY2xhc3NlcyA9IE1hbmlmZXN0LmdldF9hbGxfY2xhc3NlcygpO1xuICAgICAgICBjb25zdCBjbGFzc2VzX3dpdGhfbWV0aG9kID0gW107XG4gICAgICAgIGNvbnN0IHByb21pc2VfcGlsZSA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3QgY2xhc3NfaW5mbyBvZiBhbGxfY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3Nfb2JqZWN0ID0gY2xhc3NfaW5mby5jbGFzc19vYmplY3Q7XG4gICAgICAgICAgICBjb25zdCBjbGFzc19uYW1lID0gY2xhc3NfaW5mby5jbGFzc19uYW1lO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGlzIGNsYXNzIGhhcyB0aGUgbWV0aG9kIChzdGF0aWMgbWV0aG9kcyBhcmUgb24gdGhlIGNsYXNzIGl0c2VsZilcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2xhc3Nfb2JqZWN0W21ldGhvZF9uYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGNsYXNzZXNfd2l0aF9tZXRob2QucHVzaChjbGFzc19uYW1lKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXR1cm5fdmFsdWUgPSBhd2FpdCBjbGFzc19vYmplY3RbbWV0aG9kX25hbWVdKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBDb2xsZWN0IHByb21pc2VzIGZyb20gcmV0dXJuIHZhbHVlXG4gICAgICAgICAgICAgICAgaWYgKHJldHVybl92YWx1ZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZV9waWxlLnB1c2gocmV0dXJuX3ZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocmV0dXJuX3ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgcmV0dXJuX3ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlX3BpbGUucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChSc3guX19zdG9wcGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2xhc3Nlc193aXRoX21ldGhvZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsIGAke21ldGhvZF9uYW1lfTogJHtjbGFzc2VzX3dpdGhfbWV0aG9kLmxlbmd0aH0gY2xhc3Nlc2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXdhaXQgYWxsIHByb21pc2VzIGJlZm9yZSByZXR1cm5pbmdcbiAgICAgICAgaWYgKHByb21pc2VfcGlsZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsIGAke21ldGhvZF9uYW1lfTogQXdhaXRpbmcgJHtwcm9taXNlX3BpbGUubGVuZ3RofSBwcm9taXNlc2ApO1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZV9waWxlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBFeGVjdXRlIG11bHRpLXBoYXNlIGluaXRpYWxpemF0aW9uIGZvciBhbGwgcmVnaXN0ZXJlZCBjbGFzc2VzXG4gICAgICogVGhpcyBydW5zIHZhcmlvdXMgaW5pdGlhbGl6YXRpb24gcGhhc2VzIGluIG9yZGVyIHRvIHByb3Blcmx5IHNldCB1cCB0aGUgYXBwbGljYXRpb25cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIGluaXRpYWxpemF0aW9uIHBoYXNlcyBjb21wbGV0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfcnN4X2NvcmVfYm9vdCgpIHtcbiAgICAgICAgaWYgKFJzeC5fX2Jvb3RlZCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignUnN4Ll9yc3hfY29yZV9ib290IGNhbGxlZCBtb3JlIHRoYW4gb25jZScpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgUnN4Ll9fYm9vdGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBHZXQgYWxsIHJlZ2lzdGVyZWQgY2xhc3NlcyBmcm9tIHRoZSBtYW5pZmVzdFxuICAgICAgICBjb25zdCBhbGxfY2xhc3NlcyA9IE1hbmlmZXN0LmdldF9hbGxfY2xhc3NlcygpO1xuXG4gICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgYFN0YXJ0aW5nIF9yc3hfY29yZV9ib290IHdpdGggJHthbGxfY2xhc3Nlcy5sZW5ndGh9IGNsYXNzZXNgKTtcblxuICAgICAgICBpZiAoIWFsbF9jbGFzc2VzIHx8IGFsbF9jbGFzc2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgLy8gTm8gY2xhc3NlcyB0byBpbml0aWFsaXplXG4gICAgICAgICAgICBzaG91bGRudF9oYXBwZW4oJ05vIGNsYXNzZXMgcmVnaXN0ZXJlZCBpbiBqcyAtIHRoZXJlIHNob3VsZCBiZSBhdCBsZWFzdCB0aGUgY29yZSBmcmFtZXdvcmsgY2xhc3NlcycpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmaW5lIGluaXRpYWxpemF0aW9uIHBoYXNlcyBpbiBvcmRlclxuICAgICAgICBjb25zdCBwaGFzZXMgPSBbXG4gICAgICAgICAgICB7IGV2ZW50OiAnZnJhbWV3b3JrX2NvcmVfZGVmaW5lJywgbWV0aG9kOiAnX29uX2ZyYW1ld29ya19jb3JlX2RlZmluZScgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdmcmFtZXdvcmtfbW9kdWxlc19kZWZpbmUnLCBtZXRob2Q6ICdfb25fZnJhbWV3b3JrX21vZHVsZXNfZGVmaW5lJyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2ZyYW1ld29ya19jb3JlX2luaXQnLCBtZXRob2Q6ICdfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCcgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdhcHBfbW9kdWxlc19kZWZpbmUnLCBtZXRob2Q6ICdvbl9hcHBfbW9kdWxlc19kZWZpbmUnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX2RlZmluZScsIG1ldGhvZDogJ29uX2FwcF9kZWZpbmUnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnZnJhbWV3b3JrX21vZHVsZXNfaW5pdCcsIG1ldGhvZDogJ19vbl9mcmFtZXdvcmtfbW9kdWxlc19pbml0JyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9tb2R1bGVzX2luaXQnLCBtZXRob2Q6ICdvbl9hcHBfbW9kdWxlc19pbml0JyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9pbml0JywgbWV0aG9kOiAnb25fYXBwX2luaXQnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX3JlYWR5JywgbWV0aG9kOiAnb25fYXBwX3JlYWR5JyB9LFxuICAgICAgICBdO1xuXG4gICAgICAgIC8vIEV4ZWN1dGUgZWFjaCBwaGFzZSBpbiBvcmRlclxuICAgICAgICBmb3IgKGNvbnN0IHBoYXNlIG9mIHBoYXNlcykge1xuICAgICAgICAgICAgYXdhaXQgUnN4Ll9yc3hfY2FsbF9hbGxfY2xhc3NlcyhwaGFzZS5tZXRob2QpO1xuXG4gICAgICAgICAgICBpZiAoUnN4Ll9fc3RvcHBlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgUnN4LnRyaWdnZXIocGhhc2UuZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVWkgcmVmcmVzaCBjYWxsYmFja3NcbiAgICAgICAgUnN4LnRyaWdnZXJfcmVmcmVzaCgpO1xuXG4gICAgICAgIC8vIEFsbCBwaGFzZXMgY29tcGxldGVcbiAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCAnSW5pdGlhbGl6YXRpb24gY29tcGxldGUnKTtcblxuICAgICAgICAvLyBUT0RPOiBGaW5kIGEgZ29vZCB3YWl0IHRvIHdhaXQgZm9yIGFsbCBqcWh0bWwgY29tcG9uZW50cyB0byBsb2FkLCB0aGVuIHRyaWdnZXIgb25fcmVhZHkgYW5kIG9uKCdyZWFkeScpIGVtdWxhdGluZyB0aGUgdG9wIGxldmVsIGxhc3Qgc3ludGF4IHRoYXQganFodG1sIGNvbXBvbmVudHMgb3BlcmF0ZWFzLCBidXQgYXMgYSBzdGFuZGFyZCBqcyBjbGFzcyAoc3VjaCBhcyBhIHBhZ2UgY2xhc3MpLiAgVGhlIGJpZ2dlc3QgcXVlc3Rpb24gaXMsIGhvdyBkbyB3ZSBlZmZpY2llbnRseSBjaG9vc2Ugb25seSB0aGUgdG9wIGxldmVsIGpxaHRtbCBjb21wb25lbnRzLiAgZG8gd2Ugb25seSBjb25zaWRlciBjb21wb25lbnRzIGNyZXRhZWQgZGlyZWN0bHkgb24gYmxhZGUgdGVtcGxhdGVzPyB0aGF0IHNlYW1zIHJlYXNvbmFibGUuLi5cblxuICAgICAgICAvLyBUcmlnZ2VyIF9kZWJ1Z19yZWFkeSBldmVudCAtIHRoaXMgaXMgT05MWSBmb3IgdG9vbGluZyBsaWtlIHJzeDpkZWJ1Z1xuICAgICAgICAvLyBETyBOT1QgdXNlIHRoaXMgaW4gYXBwbGljYXRpb24gY29kZSAtIHVzZSBvbl9hcHBfcmVhZHkoKSBwaGFzZSBpbnN0ZWFkXG4gICAgICAgIC8vIFRoaXMgZXZlbnQgZXhpc3RzIHNvbGVseSBmb3IgZGVidWdnaW5nIHRvb2xzIHRoYXQgbmVlZCB0byBydW4gYWZ0ZXIgZnVsbCBpbml0aWFsaXphdGlvblxuICAgICAgICBSc3gudHJpZ2dlcignX2RlYnVnX3JlYWR5Jyk7XG4gICAgfVxuXG4gICAgLyogQ2FsbGluZyB0aGlzIHN0b3BzIHRoZSBib290IHByb2Nlc3MuICovXG4gICAgc3RhdGljIGFzeW5jIF9yc3hfY29yZV9ib290X3N0b3AocmVhc29uKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IocmVhc29uKTtcbiAgICAgICAgUnN4Ll9fc3RvcHBlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2UgVVJMIGhhc2ggaW50byBrZXktdmFsdWUgb2JqZWN0XG4gICAgICogSGFuZGxlcyBmb3JtYXQ6ICNrZXk9dmFsdWUma2V5Mj12YWx1ZTJcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFBhcnNlZCBoYXNoIHBhcmFtZXRlcnNcbiAgICAgKi9cbiAgICBzdGF0aWMgX3BhcnNlX2hhc2goKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSB3aW5kb3cubG9jYXRpb24uaGFzaDtcbiAgICAgICAgaWYgKCFoYXNoIHx8IGhhc2ggPT09ICcjJykge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIGxlYWRpbmcgIyBhbmQgcGFyc2UgYXMgcXVlcnkgc3RyaW5nXG4gICAgICAgIGNvbnN0IGhhc2hfc3RyaW5nID0gaGFzaC5zdWJzdHJpbmcoMSk7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHt9O1xuXG4gICAgICAgIGNvbnN0IHBhaXJzID0gaGFzaF9zdHJpbmcuc3BsaXQoJyYnKTtcbiAgICAgICAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzKSB7XG4gICAgICAgICAgICBjb25zdCBba2V5LCB2YWx1ZV0gPSBwYWlyLnNwbGl0KCc9Jyk7XG4gICAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zW2RlY29kZVVSSUNvbXBvbmVudChrZXkpXSA9IHZhbHVlID8gZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlKSA6ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgb2JqZWN0IGludG8gVVJMIGhhc2ggZm9ybWF0XG4gICAgICogUHJvZHVjZXMgZm9ybWF0OiAja2V5PXZhbHVlJmtleTI9dmFsdWUyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIEtleS12YWx1ZSBwYWlycyB0byBlbmNvZGVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBFbmNvZGVkIGhhc2ggc3RyaW5nICh3aXRoIGxlYWRpbmcgIywgb3IgZW1wdHkgc3RyaW5nKVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplX2hhc2gocGFyYW1zKSB7XG4gICAgICAgIGNvbnN0IHBhaXJzID0gW107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHBhcmFtcykge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSAnJykge1xuICAgICAgICAgICAgICAgIHBhaXJzLnB1c2goYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGtleSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYWlycy5sZW5ndGggPiAwID8gJyMnICsgcGFpcnMuam9pbignJicpIDogJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBwYWdlIHN0YXRlIGZyb20gVVJMIGhhc2hcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBjb25zdCBzdGF0ZSA9IFJzeC5nZXRfYWxsX3BhZ2Vfc3RhdGUoKTtcbiAgICAgKiAvLyBSZXR1cm5zOiB7ZGdfcGFnZTogJzInLCBkZ19zb3J0OiAnbmFtZSd9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBbGwgaGFzaCBwYXJhbWV0ZXJzIGFzIGtleS12YWx1ZSBwYWlyc1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfYWxsX3BhZ2Vfc3RhdGUoKSB7XG4gICAgICAgIHJldHVybiBSc3guX3BhcnNlX2hhc2goKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgc2luZ2xlIHZhbHVlIGZyb20gVVJMIGhhc2ggc3RhdGVcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBjb25zdCBwYWdlID0gUnN4LmdldF9wYWdlX3N0YXRlKCdkZ19wYWdlJyk7XG4gICAgICogLy8gUmV0dXJuczogJzInIG9yIG51bGwgaWYgbm90IHNldFxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IHRvIHJldHJpZXZlXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBUaGUgdmFsdWUgb3IgbnVsbCBpZiBub3QgZm91bmRcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X3BhZ2Vfc3RhdGUoa2V5KSB7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gUnN4Ll9wYXJzZV9oYXNoKCk7XG4gICAgICAgIHJldHVybiBzdGF0ZVtrZXldID8/IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHNpbmdsZSB2YWx1ZSBpbiBVUkwgaGFzaCBzdGF0ZSAocmVwbGFjZXMgaGlzdG9yeSwgZG9lc24ndCBhZGQpXG4gICAgICpcbiAgICAgKiBVc2FnZTpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogUnN4LnNldF9wYWdlX3N0YXRlKCdkZ19wYWdlJywgMik7XG4gICAgICogLy8gVVJMIGJlY29tZXM6IGh0dHA6Ly9leGFtcGxlLmNvbS9wYWdlI2RnX3BhZ2U9MlxuICAgICAqXG4gICAgICogUnN4LnNldF9wYWdlX3N0YXRlKCdkZ19wYWdlJywgbnVsbCk7IC8vIFJlbW92ZSBrZXlcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSB0byBzZXRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8bnVsbH0gdmFsdWUgVGhlIHZhbHVlIChudWxsL2VtcHR5IHJlbW92ZXMgdGhlIGtleSlcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0X3BhZ2Vfc3RhdGUoa2V5LCB2YWx1ZSkge1xuICAgICAgICBjb25zdCBzdGF0ZSA9IFJzeC5fcGFyc2VfaGFzaCgpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBvciByZW1vdmUgdGhlIGtleVxuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBzdGF0ZVtrZXldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RhdGVba2V5XSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgVVJMIHdpdGhvdXQgYWRkaW5nIGhpc3RvcnlcbiAgICAgICAgY29uc3QgbmV3X2hhc2ggPSBSc3guX3NlcmlhbGl6ZV9oYXNoKHN0YXRlKTtcbiAgICAgICAgY29uc3QgdXJsID0gd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lICsgd2luZG93LmxvY2F0aW9uLnNlYXJjaCArIG5ld19oYXNoO1xuICAgICAgICBoaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCAnJywgdXJsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgbXVsdGlwbGUgdmFsdWVzIGluIFVSTCBoYXNoIHN0YXRlIGF0IG9uY2VcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBSc3guc2V0X2FsbF9wYWdlX3N0YXRlKHtkZ19wYWdlOiAyLCBkZ19zb3J0OiAnbmFtZSd9KTtcbiAgICAgKiAvLyBVUkwgYmVjb21lczogaHR0cDovL2V4YW1wbGUuY29tL3BhZ2UjZGdfcGFnZT0yJmRnX3NvcnQ9bmFtZVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG5ld19zdGF0ZSBPYmplY3Qgd2l0aCBrZXktdmFsdWUgcGFpcnMgdG8gc2V0XG4gICAgICovXG4gICAgc3RhdGljIHNldF9hbGxfcGFnZV9zdGF0ZShuZXdfc3RhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBSc3guX3BhcnNlX2hhc2goKTtcblxuICAgICAgICAvLyBNZXJnZSBuZXcgc3RhdGVcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gbmV3X3N0YXRlKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IG5ld19zdGF0ZVtrZXldO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHN0YXRlW2tleV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0YXRlW2tleV0gPSBTdHJpbmcodmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIFVSTCB3aXRob3V0IGFkZGluZyBoaXN0b3J5XG4gICAgICAgIGNvbnN0IG5ld19oYXNoID0gUnN4Ll9zZXJpYWxpemVfaGFzaChzdGF0ZSk7XG4gICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2ggKyBuZXdfaGFzaDtcbiAgICAgICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUobnVsbCwgJycsIHVybCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVyIGFuIGVycm9yIGluIGEgRE9NIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIERpc3BsYXlzIGVycm9ycyBmcm9tIEFqYXggY2FsbHMgaW4gYSBzdGFuZGFyZGl6ZWQgZm9ybWF0LiBIYW5kbGVzIGRpZmZlcmVudFxuICAgICAqIGVycm9yIHR5cGVzIChmYXRhbCwgdmFsaWRhdGlvbiwgYXV0aCwgZ2VuZXJpYykgd2l0aCBhcHByb3ByaWF0ZSBmb3JtYXR0aW5nLlxuICAgICAqXG4gICAgICogVXNhZ2U6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIHRyeSB7XG4gICAgICogICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IENvbnRyb2xsZXIubWV0aG9kKCk7XG4gICAgICogfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgKiAgICAgUnN4LnJlbmRlcl9lcnJvcihlcnJvciwgJyNlcnJvcl9jb250YWluZXInKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfE9iamVjdH0gZXJyb3IgLSBFcnJvciBvYmplY3QgZnJvbSBBamF4IGNhbGxcbiAgICAgKiBAcGFyYW0ge2pRdWVyeXxzdHJpbmd9IGNvbnRhaW5lciAtIGpRdWVyeSBlbGVtZW50IG9yIHNlbGVjdG9yIGZvciBlcnJvciBkaXNwbGF5XG4gICAgICovXG4gICAgc3RhdGljIHJlbmRlcl9lcnJvcihlcnJvciwgY29udGFpbmVyKSB7XG4gICAgICAgIGNvbnN0ICRjb250YWluZXIgPSAkKGNvbnRhaW5lcik7XG5cbiAgICAgICAgaWYgKCEkY29udGFpbmVyLmV4aXN0cygpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdSc3gucmVuZGVyX2Vycm9yOiBDb250YWluZXIgbm90IGZvdW5kJywgY29udGFpbmVyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENsZWFyIGV4aXN0aW5nIGNvbnRlbnRcbiAgICAgICAgJGNvbnRhaW5lci5lbXB0eSgpO1xuXG4gICAgICAgIGxldCBodG1sID0gJyc7XG5cbiAgICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBlcnJvciB0eXBlc1xuICAgICAgICBpZiAoZXJyb3IudHlwZSA9PT0gJ2ZhdGFsJyAmJiBlcnJvci5kZXRhaWxzKSB7XG4gICAgICAgICAgICAvLyBGYXRhbCBQSFAgZXJyb3Igd2l0aCBmaWxlL2xpbmUvZXJyb3JcbiAgICAgICAgICAgIGNvbnN0IGRldGFpbHMgPSBlcnJvci5kZXRhaWxzO1xuICAgICAgICAgICAgY29uc3QgZmlsZSA9IGRldGFpbHMuZmlsZSB8fCAnVW5rbm93biBmaWxlJztcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBkZXRhaWxzLmxpbmUgfHwgJz8nO1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGRldGFpbHMuZXJyb3IgfHwgZXJyb3IubWVzc2FnZSB8fCAnRmF0YWwgZXJyb3Igb2NjdXJyZWQnO1xuXG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPGg1PlVuY2F1Z2h0IEZhdGFsIEVycm9yIGluICR7ZmlsZX06JHtsaW5lfTo8L2g1PlxuICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj4ke1JzeC5fZXNjYXBlX2h0bWwobWVzc2FnZSl9PC9wPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgYDtcbiAgICAgICAgfSBlbHNlIGlmIChlcnJvci50eXBlID09PSAnZm9ybV9lcnJvcicgJiYgZXJyb3IuZGV0YWlscykge1xuICAgICAgICAgICAgLy8gVmFsaWRhdGlvbiBlcnJvcnMgLSBzaG93IHVubWF0Y2hlZCBlcnJvcnMgb25seVxuICAgICAgICAgICAgLy8gKG1hdGNoZWQgZXJyb3JzIHNob3VsZCBiZSBoYW5kbGVkIGJ5IEZvcm1fVXRpbHMuYXBwbHlfZm9ybV9lcnJvcnMpXG4gICAgICAgICAgICBjb25zdCBlcnJvcnMgPSBlcnJvci5kZXRhaWxzO1xuICAgICAgICAgICAgY29uc3QgZXJyb3JfbGlzdCA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIGVycm9ycykge1xuICAgICAgICAgICAgICAgIGVycm9yX2xpc3QucHVzaChlcnJvcnNbZmllbGRdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGVycm9yX2xpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGh0bWwgPSBgXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aDU+VmFsaWRhdGlvbiBFcnJvcnM6PC9oNT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx1bCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke2Vycm9yX2xpc3QubWFwKGVyciA9PiBgPGxpPiR7UnN4Ll9lc2NhcGVfaHRtbChlcnIpfTwvbGk+YCkuam9pbignJyl9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3VsPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICBgO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGVycm9yLnR5cGUgPT09ICdhdXRoX3JlcXVpcmVkJyB8fCBlcnJvci50eXBlID09PSAndW5hdXRob3JpemVkJykge1xuICAgICAgICAgICAgLy8gQXV0aGVudGljYXRpb24vYXV0aG9yaXphdGlvbiBlcnJvcnNcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8ICdBdXRoZW50aWNhdGlvbiByZXF1aXJlZCc7XG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPiR7UnN4Ll9lc2NhcGVfaHRtbChtZXNzYWdlKX08L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yLnR5cGUgPT09ICduZXR3b3JrJykge1xuICAgICAgICAgICAgLy8gTmV0d29yayBlcnJvcnNcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8ICdVbmFibGUgdG8gcmVhY2ggc2VydmVyLiBQbGVhc2UgY2hlY2sgeW91ciBjb25uZWN0aW9uLic7XG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+JHtSc3guX2VzY2FwZV9odG1sKG1lc3NhZ2UpfTwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBHZW5lcmljL3Vua25vd24gZXJyb3JcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8IGVycm9yLnRvU3RyaW5nKCkgfHwgJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQnO1xuICAgICAgICAgICAgaHRtbCA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPiR7UnN4Ll9lc2NhcGVfaHRtbChtZXNzYWdlKX08L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgICAgICB9XG5cbiAgICAgICAgJGNvbnRhaW5lci5odG1sKGh0bWwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVzY2FwZSBIVE1MIHRvIHByZXZlbnQgWFNTIGluIGVycm9yIG1lc3NhZ2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2VzY2FwZV9odG1sKHRleHQpIHtcbiAgICAgICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGRpdi50ZXh0Q29u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
|