"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 = `
Uncaught Fatal Error in ${file}:${line}:
${Rsx._escape_html(message)}
`;
} 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 = `
Validation Errors:
${error_list.map(err => `- ${Rsx._escape_html(err)}
`).join('')}
`;
}
} else if (error.type === 'auth_required' || error.type === 'unauthorized') {
// Authentication/authorization errors
const message = error.message || 'Authentication required';
html = `
${Rsx._escape_html(message)}
`;
} else if (error.type === 'network') {
// Network errors
const message = error.message || 'Unable to reach server. Please check your connection.';
html = `
${Rsx._escape_html(message)}
`;
} else {
// Generic/unknown error
const message = error.message || error.toString() || 'An unknown error occurred';
html = `
${Rsx._escape_html(message)}
`;
}
$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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