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>
350 lines
40 KiB
JavaScript
Executable File
350 lines
40 KiB
JavaScript
Executable File
"use strict";
|
|
|
|
/**
|
|
* Manifest - JavaScript class registry and metadata system
|
|
*
|
|
* This class maintains a registry of all JavaScript classes in the bundle,
|
|
* tracking their names and inheritance relationships. It provides utilities
|
|
* for working with class hierarchies and calling initialization methods.
|
|
*/
|
|
class Manifest {
|
|
/**
|
|
* Define classes in the manifest (framework internal)
|
|
* @param {Array} items - Array of class definitions [[Class, "ClassName", ParentClass, decorators], ...]
|
|
*/
|
|
static _define(items) {
|
|
// Initialize the classes object if not already defined
|
|
if (typeof Manifest._classes === 'undefined') {
|
|
Manifest._classes = {};
|
|
}
|
|
|
|
// Process each class definition
|
|
items.forEach(item => {
|
|
let class_object = item[0];
|
|
let class_name = item[1];
|
|
let class_extends = item[2] || null;
|
|
let decorators = item[3] || null;
|
|
|
|
// Store the class information (using object to avoid duplicates)
|
|
Manifest._classes[class_name] = {
|
|
class: class_object,
|
|
name: class_name,
|
|
extends: class_extends,
|
|
decorators: decorators // Store compact decorator data
|
|
};
|
|
|
|
// Add metadata to the class object itself
|
|
class_object._name = class_name;
|
|
class_object._extends = class_extends;
|
|
class_object._decorators = decorators;
|
|
});
|
|
|
|
// Build the subclass index after all classes are defined
|
|
Manifest._build_subclass_index();
|
|
}
|
|
|
|
/**
|
|
* Build an index of subclasses for efficient lookups
|
|
* This creates a mapping where each class name points to an array of all its subclasses
|
|
* @private
|
|
*/
|
|
static _build_subclass_index() {
|
|
// Initialize the subclass index
|
|
Manifest._subclass_index = {};
|
|
|
|
// Step through each class and walk up its parent chain
|
|
for (let class_name in Manifest._classes) {
|
|
const classdata = Manifest._classes[class_name];
|
|
let current_class_name = class_name;
|
|
let current_classdata = classdata;
|
|
|
|
// Walk up the parent chain until we reach the root
|
|
while (current_classdata) {
|
|
const extends_name = current_classdata.extends;
|
|
if (extends_name) {
|
|
// Initialize the parent's subclass array if needed
|
|
if (!Manifest._subclass_index[extends_name]) {
|
|
Manifest._subclass_index[extends_name] = [];
|
|
}
|
|
|
|
// Add this class to its parent's subclass list
|
|
if (!Manifest._subclass_index[extends_name].includes(class_name)) {
|
|
Manifest._subclass_index[extends_name].push(class_name);
|
|
}
|
|
|
|
// Move up to the parent's metadata (if it exists in manifest)
|
|
if (Manifest._classes[extends_name]) {
|
|
current_classdata = Manifest._classes[extends_name];
|
|
} else {
|
|
// Parent not in manifest (e.g., native JavaScript class), stop here
|
|
current_classdata = null;
|
|
}
|
|
} else {
|
|
// No parent, we've reached the root
|
|
current_classdata = null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all classes that extend a given base class
|
|
* @param {Class|string} base_class - The base class (object or name string) to check for
|
|
* @returns {Array} Array of objects with {class_name, class_object} for classes that extend the base class
|
|
*/
|
|
static get_extending(base_class) {
|
|
if (!Manifest._classes) {
|
|
return [];
|
|
}
|
|
|
|
// Convert string to class object if needed
|
|
let base_class_object = base_class;
|
|
if (typeof base_class === 'string') {
|
|
base_class_object = Manifest.get_class_by_name(base_class);
|
|
if (!base_class_object) {
|
|
throw new Error(`Base class not found: ${base_class}`);
|
|
}
|
|
}
|
|
const classes = [];
|
|
for (let class_name in Manifest._classes) {
|
|
const classdata = Manifest._classes[class_name];
|
|
if (Manifest.js_is_subclass_of(classdata.class, base_class_object)) {
|
|
classes.push({
|
|
class_name: class_name,
|
|
class_object: classdata.class
|
|
});
|
|
}
|
|
}
|
|
|
|
// Sort alphabetically by class name to ensure deterministic behavior and prevent race condition bugs
|
|
classes.sort((a, b) => a.class_name.localeCompare(b.class_name));
|
|
return classes;
|
|
}
|
|
|
|
/**
|
|
* Check if a class is a subclass of another class
|
|
* Matches PHP Manifest::js_is_subclass_of() signature and behavior
|
|
* @param {Class|string} subclass - The child class (object or name) to check
|
|
* @param {Class|string} superclass - The parent class (object or name) to check against
|
|
* @returns {boolean} True if subclass extends superclass (directly or indirectly)
|
|
*/
|
|
static js_is_subclass_of(subclass, superclass) {
|
|
// Convert string names to class objects
|
|
let subclass_object = subclass;
|
|
if (typeof subclass === 'string') {
|
|
subclass_object = Manifest.get_class_by_name(subclass);
|
|
if (!subclass_object) {
|
|
// Can't resolve subclass - return false per spec
|
|
return false;
|
|
}
|
|
}
|
|
let superclass_object = superclass;
|
|
if (typeof superclass === 'string') {
|
|
superclass_object = Manifest.get_class_by_name(superclass);
|
|
if (!superclass_object) {
|
|
// Can't resolve superclass - fail loud per spec
|
|
throw new Error(`Superclass not found in manifest: ${superclass}`);
|
|
}
|
|
}
|
|
|
|
// Classes are not subclasses of themselves
|
|
if (subclass_object === superclass_object) {
|
|
return false;
|
|
}
|
|
|
|
// Walk up the inheritance chain
|
|
let current_class = subclass_object;
|
|
while (current_class) {
|
|
if (current_class === superclass_object) {
|
|
return true;
|
|
}
|
|
// Move up to parent class
|
|
if (current_class._extends) {
|
|
// _extends may be a string or class reference
|
|
if (typeof current_class._extends === 'string') {
|
|
current_class = Manifest.get_class_by_name(current_class._extends);
|
|
} else {
|
|
current_class = current_class._extends;
|
|
}
|
|
} else {
|
|
current_class = null;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get a class by its name
|
|
* @param {string} class_name - The name of the class
|
|
* @returns {Class|null} The class object or null if not found
|
|
*/
|
|
static get_class_by_name(class_name) {
|
|
if (!Manifest._classes || !Manifest._classes[class_name]) {
|
|
return null;
|
|
}
|
|
return Manifest._classes[class_name].class;
|
|
}
|
|
|
|
/**
|
|
* Get all registered classes
|
|
* @returns {Array} Array of objects with {class_name, class_object, extends}
|
|
*/
|
|
static get_all_classes() {
|
|
if (!Manifest._classes) {
|
|
return [];
|
|
}
|
|
const results = [];
|
|
for (let class_name in Manifest._classes) {
|
|
const classdata = Manifest._classes[class_name];
|
|
results.push({
|
|
class_name: classdata.name,
|
|
class_object: classdata.class,
|
|
extends: classdata.extends
|
|
});
|
|
}
|
|
|
|
// Sort alphabetically by class name to ensure deterministic behavior and prevent race condition bugs
|
|
results.sort((a, b) => a.class_name.localeCompare(b.class_name));
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Get the build key from the application configuration
|
|
* @returns {string} The build key or "NOBUILD" if not available
|
|
*/
|
|
static build_key() {
|
|
if (window.rsxapp && window.rsxapp.build_key) {
|
|
return window.rsxapp.build_key;
|
|
}
|
|
return 'NOBUILD';
|
|
}
|
|
|
|
/**
|
|
* Get decorators for a specific class and method
|
|
* @param {string|Class} class_name - The class name or class object
|
|
* @param {string} method_name - The method name
|
|
* @returns {Array|null} Array of decorator objects or null if none found
|
|
*/
|
|
static get_decorators(class_name, method_name) {
|
|
// Convert class object to name if needed
|
|
if (typeof class_name !== 'string') {
|
|
class_name = class_name._name || class_name.name;
|
|
}
|
|
const class_info = Manifest._classes[class_name];
|
|
if (!class_info || !class_info.decorators || !class_info.decorators[method_name]) {
|
|
return null;
|
|
}
|
|
|
|
// Transform compact format to object format
|
|
return Manifest._transform_decorators(class_info.decorators[method_name]);
|
|
}
|
|
|
|
/**
|
|
* Get all methods with decorators for a class
|
|
* @param {string|Class} class_name - The class name or class object
|
|
* @returns {Object} Object with method names as keys and decorator arrays as values
|
|
*/
|
|
static get_all_decorators(class_name) {
|
|
// Convert class object to name if needed
|
|
if (typeof class_name !== 'string') {
|
|
class_name = class_name._name || class_name.name;
|
|
}
|
|
const class_info = Manifest._classes[class_name];
|
|
if (!class_info || !class_info.decorators) {
|
|
return {};
|
|
}
|
|
|
|
// Transform all decorators from compact to object format
|
|
const result = {};
|
|
for (let method_name in class_info.decorators) {
|
|
result[method_name] = Manifest._transform_decorators(class_info.decorators[method_name]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Transform compact decorator format to object format
|
|
* @param {Array} compact_decorators - Array of [name, [args]] tuples
|
|
* @returns {Array} Array of decorator objects with name and arguments properties
|
|
* @private
|
|
*/
|
|
static _transform_decorators(compact_decorators) {
|
|
if (!Array.isArray(compact_decorators)) {
|
|
return [];
|
|
}
|
|
return compact_decorators.map(decorator => {
|
|
if (Array.isArray(decorator) && decorator.length >= 2) {
|
|
return {
|
|
name: decorator[0],
|
|
arguments: decorator[1] || []
|
|
};
|
|
}
|
|
// Handle malformed decorator data
|
|
return {
|
|
name: 'unknown',
|
|
arguments: []
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Check if a method has a specific decorator
|
|
* @param {string|Class} class_name - The class name or class object
|
|
* @param {string} method_name - The method name
|
|
* @param {string} decorator_name - The decorator name to check for
|
|
* @returns {boolean} True if the method has the decorator
|
|
*/
|
|
static has_decorator(class_name, method_name, decorator_name) {
|
|
const decorators = Manifest.get_decorators(class_name, method_name);
|
|
if (!decorators) {
|
|
return false;
|
|
}
|
|
return decorators.some(d => d.name === decorator_name);
|
|
}
|
|
|
|
/**
|
|
* Get all subclasses of a given class using the pre-built index
|
|
* This is the JavaScript equivalent of PHP's Manifest::js_get_subclasses_of()
|
|
* @param {Class|string} base_class - The base class (object or name string) to get subclasses of
|
|
* @returns {Array<Class>} Array of actual class objects that are subclasses of the base class
|
|
*/
|
|
static js_get_subclasses_of(base_class) {
|
|
// Initialize index if needed
|
|
if (!Manifest._subclass_index) {
|
|
Manifest._build_subclass_index();
|
|
}
|
|
|
|
// Convert class object to name if needed
|
|
let base_class_name = base_class;
|
|
if (typeof base_class !== 'string') {
|
|
base_class_name = base_class._name || base_class.name;
|
|
}
|
|
|
|
// Check if the base class exists
|
|
if (!Manifest._classes[base_class_name]) {
|
|
// Base class not in manifest - return empty array
|
|
return [];
|
|
}
|
|
|
|
// Get subclass names from the index
|
|
const subclass_names = Manifest._subclass_index[base_class_name] || [];
|
|
|
|
// Convert names to actual class objects
|
|
const subclass_objects = [];
|
|
for (let subclass_name of subclass_names) {
|
|
const classdata = Manifest._classes[subclass_name];
|
|
subclass_objects.push(classdata.class);
|
|
}
|
|
|
|
// Sort by class name for deterministic behavior
|
|
subclass_objects.sort((a, b) => {
|
|
const name_a = a._name || a.name;
|
|
const name_b = b._name || b.name;
|
|
return name_a.localeCompare(name_b);
|
|
});
|
|
return subclass_objects;
|
|
}
|
|
}
|
|
|
|
// RSX manifest automatically makes classes global - no manual assignment needed
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJNYW5pZmVzdCIsIl9kZWZpbmUiLCJpdGVtcyIsIl9jbGFzc2VzIiwiZm9yRWFjaCIsIml0ZW0iLCJjbGFzc19vYmplY3QiLCJjbGFzc19uYW1lIiwiY2xhc3NfZXh0ZW5kcyIsImRlY29yYXRvcnMiLCJjbGFzcyIsIm5hbWUiLCJleHRlbmRzIiwiX25hbWUiLCJfZXh0ZW5kcyIsIl9kZWNvcmF0b3JzIiwiX2J1aWxkX3N1YmNsYXNzX2luZGV4IiwiX3N1YmNsYXNzX2luZGV4IiwiY2xhc3NkYXRhIiwiY3VycmVudF9jbGFzc19uYW1lIiwiY3VycmVudF9jbGFzc2RhdGEiLCJleHRlbmRzX25hbWUiLCJpbmNsdWRlcyIsInB1c2giLCJnZXRfZXh0ZW5kaW5nIiwiYmFzZV9jbGFzcyIsImJhc2VfY2xhc3Nfb2JqZWN0IiwiZ2V0X2NsYXNzX2J5X25hbWUiLCJFcnJvciIsImNsYXNzZXMiLCJqc19pc19zdWJjbGFzc19vZiIsInNvcnQiLCJhIiwiYiIsImxvY2FsZUNvbXBhcmUiLCJzdWJjbGFzcyIsInN1cGVyY2xhc3MiLCJzdWJjbGFzc19vYmplY3QiLCJzdXBlcmNsYXNzX29iamVjdCIsImN1cnJlbnRfY2xhc3MiLCJnZXRfYWxsX2NsYXNzZXMiLCJyZXN1bHRzIiwiYnVpbGRfa2V5Iiwid2luZG93IiwicnN4YXBwIiwiZ2V0X2RlY29yYXRvcnMiLCJtZXRob2RfbmFtZSIsImNsYXNzX2luZm8iLCJfdHJhbnNmb3JtX2RlY29yYXRvcnMiLCJnZXRfYWxsX2RlY29yYXRvcnMiLCJyZXN1bHQiLCJjb21wYWN0X2RlY29yYXRvcnMiLCJBcnJheSIsImlzQXJyYXkiLCJtYXAiLCJkZWNvcmF0b3IiLCJsZW5ndGgiLCJhcmd1bWVudHMiLCJoYXNfZGVjb3JhdG9yIiwiZGVjb3JhdG9yX25hbWUiLCJzb21lIiwiZCIsImpzX2dldF9zdWJjbGFzc2VzX29mIiwiYmFzZV9jbGFzc19uYW1lIiwic3ViY2xhc3NfbmFtZXMiLCJzdWJjbGFzc19vYmplY3RzIiwic3ViY2xhc3NfbmFtZSIsIm5hbWVfYSIsIm5hbWVfYiJdLCJzb3VyY2VzIjpbImFwcC9SU3BhZGUvQ29yZS9Kcy9NYW5pZmVzdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1hbmlmZXN0IC0gSmF2YVNjcmlwdCBjbGFzcyByZWdpc3RyeSBhbmQgbWV0YWRhdGEgc3lzdGVtXG4gKlxuICogVGhpcyBjbGFzcyBtYWludGFpbnMgYSByZWdpc3RyeSBvZiBhbGwgSmF2YVNjcmlwdCBjbGFzc2VzIGluIHRoZSBidW5kbGUsXG4gKiB0cmFja2luZyB0aGVpciBuYW1lcyBhbmQgaW5oZXJpdGFuY2UgcmVsYXRpb25zaGlwcy4gSXQgcHJvdmlkZXMgdXRpbGl0aWVzXG4gKiBmb3Igd29ya2luZyB3aXRoIGNsYXNzIGhpZXJhcmNoaWVzIGFuZCBjYWxsaW5nIGluaXRpYWxpemF0aW9uIG1ldGhvZHMuXG4gKi9cbmNsYXNzIE1hbmlmZXN0IHtcbiAgICAvKipcbiAgICAgKiBEZWZpbmUgY2xhc3NlcyBpbiB0aGUgbWFuaWZlc3QgKGZyYW1ld29yayBpbnRlcm5hbClcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBpdGVtcyAtIEFycmF5IG9mIGNsYXNzIGRlZmluaXRpb25zIFtbQ2xhc3MsIFwiQ2xhc3NOYW1lXCIsIFBhcmVudENsYXNzLCBkZWNvcmF0b3JzXSwgLi4uXVxuICAgICAqL1xuICAgIHN0YXRpYyBfZGVmaW5lKGl0ZW1zKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGNsYXNzZXMgb2JqZWN0IGlmIG5vdCBhbHJlYWR5IGRlZmluZWRcbiAgICAgICAgaWYgKHR5cGVvZiBNYW5pZmVzdC5fY2xhc3NlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9jbGFzc2VzID0ge307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm9jZXNzIGVhY2ggY2xhc3MgZGVmaW5pdGlvblxuICAgICAgICBpdGVtcy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgICAgICBsZXQgY2xhc3Nfb2JqZWN0ID0gaXRlbVswXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19uYW1lID0gaXRlbVsxXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19leHRlbmRzID0gaXRlbVsyXSB8fCBudWxsO1xuICAgICAgICAgICAgbGV0IGRlY29yYXRvcnMgPSBpdGVtWzNdIHx8IG51bGw7XG5cbiAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBjbGFzcyBpbmZvcm1hdGlvbiAodXNpbmcgb2JqZWN0IHRvIGF2b2lkIGR1cGxpY2F0ZXMpXG4gICAgICAgICAgICBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXSA9IHtcbiAgICAgICAgICAgICAgICBjbGFzczogY2xhc3Nfb2JqZWN0LFxuICAgICAgICAgICAgICAgIG5hbWU6IGNsYXNzX25hbWUsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NfZXh0ZW5kcyxcbiAgICAgICAgICAgICAgICBkZWNvcmF0b3JzOiBkZWNvcmF0b3JzLCAgLy8gU3RvcmUgY29tcGFjdCBkZWNvcmF0b3IgZGF0YVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIG1ldGFkYXRhIHRvIHRoZSBjbGFzcyBvYmplY3QgaXRzZWxmXG4gICAgICAgICAgICBjbGFzc19vYmplY3QuX25hbWUgPSBjbGFzc19uYW1lO1xuICAgICAgICAgICAgY2xhc3Nfb2JqZWN0Ll9leHRlbmRzID0gY2xhc3NfZXh0ZW5kcztcbiAgICAgICAgICAgIGNsYXNzX29iamVjdC5fZGVjb3JhdG9ycyA9IGRlY29yYXRvcnM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBzdWJjbGFzcyBpbmRleCBhZnRlciBhbGwgY2xhc3NlcyBhcmUgZGVmaW5lZFxuICAgICAgICBNYW5pZmVzdC5fYnVpbGRfc3ViY2xhc3NfaW5kZXgoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiBpbmRleCBvZiBzdWJjbGFzc2VzIGZvciBlZmZpY2llbnQgbG9va3Vwc1xuICAgICAqIFRoaXMgY3JlYXRlcyBhIG1hcHBpbmcgd2hlcmUgZWFjaCBjbGFzcyBuYW1lIHBvaW50cyB0byBhbiBhcnJheSBvZiBhbGwgaXRzIHN1YmNsYXNzZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYnVpbGRfc3ViY2xhc3NfaW5kZXgoKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHN1YmNsYXNzIGluZGV4XG4gICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleCA9IHt9O1xuXG4gICAgICAgIC8vIFN0ZXAgdGhyb3VnaCBlYWNoIGNsYXNzIGFuZCB3YWxrIHVwIGl0cyBwYXJlbnQgY2hhaW5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBsZXQgY3VycmVudF9jbGFzc19uYW1lID0gY2xhc3NfbmFtZTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50X2NsYXNzZGF0YSA9IGNsYXNzZGF0YTtcblxuICAgICAgICAgICAgLy8gV2FsayB1cCB0aGUgcGFyZW50IGNoYWluIHVudGlsIHdlIHJlYWNoIHRoZSByb290XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudF9jbGFzc2RhdGEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHRlbmRzX25hbWUgPSBjdXJyZW50X2NsYXNzZGF0YS5leHRlbmRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuZHNfbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBwYXJlbnQncyBzdWJjbGFzcyBhcnJheSBpZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGNsYXNzIHRvIGl0cyBwYXJlbnQncyBzdWJjbGFzcyBsaXN0XG4gICAgICAgICAgICAgICAgICAgIGlmICghTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0uaW5jbHVkZXMoY2xhc3NfbmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdLnB1c2goY2xhc3NfbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBNb3ZlIHVwIHRvIHRoZSBwYXJlbnQncyBtZXRhZGF0YSAoaWYgaXQgZXhpc3RzIGluIG1hbmlmZXN0KVxuICAgICAgICAgICAgICAgICAgICBpZiAoTWFuaWZlc3QuX2NsYXNzZXNbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tleHRlbmRzX25hbWVdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFyZW50IG5vdCBpbiBtYW5pZmVzdCAoZS5nLiwgbmF0aXZlIEphdmFTY3JpcHQgY2xhc3MpLCBzdG9wIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3NkYXRhID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vIHBhcmVudCwgd2UndmUgcmVhY2hlZCB0aGUgcm9vdFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGEgZ2l2ZW4gYmFzZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gY2hlY2sgZm9yXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBvYmplY3RzIHdpdGgge2NsYXNzX25hbWUsIGNsYXNzX29iamVjdH0gZm9yIGNsYXNzZXMgdGhhdCBleHRlbmQgdGhlIGJhc2UgY2xhc3NcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2V4dGVuZGluZyhiYXNlX2NsYXNzKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIGNsYXNzIG9iamVjdCBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3Nfb2JqZWN0ID0gYmFzZV9jbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBiYXNlX2NsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgYmFzZV9jbGFzc19vYmplY3QgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShiYXNlX2NsYXNzKTtcbiAgICAgICAgICAgIGlmICghYmFzZV9jbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhc2UgY2xhc3Mgbm90IGZvdW5kOiAke2Jhc2VfY2xhc3N9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc2VzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBpZiAoTWFuaWZlc3QuanNfaXNfc3ViY2xhc3Nfb2YoY2xhc3NkYXRhLmNsYXNzLCBiYXNlX2NsYXNzX29iamVjdCkpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbGFzc19uYW1lOiBjbGFzc19uYW1lLFxuICAgICAgICAgICAgICAgICAgICBjbGFzc19vYmplY3Q6IGNsYXNzZGF0YS5jbGFzcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIGNsYXNzZXMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIGNsYXNzZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBjbGFzcyBpcyBhIHN1YmNsYXNzIG9mIGFub3RoZXIgY2xhc3NcbiAgICAgKiBNYXRjaGVzIFBIUCBNYW5pZmVzdDo6anNfaXNfc3ViY2xhc3Nfb2YoKSBzaWduYXR1cmUgYW5kIGJlaGF2aW9yXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IHN1YmNsYXNzIC0gVGhlIGNoaWxkIGNsYXNzIChvYmplY3Qgb3IgbmFtZSkgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gc3VwZXJjbGFzcyAtIFRoZSBwYXJlbnQgY2xhc3MgKG9iamVjdCBvciBuYW1lKSB0byBjaGVjayBhZ2FpbnN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgc3ViY2xhc3MgZXh0ZW5kcyBzdXBlcmNsYXNzIChkaXJlY3RseSBvciBpbmRpcmVjdGx5KVxuICAgICAqL1xuICAgIHN0YXRpYyBqc19pc19zdWJjbGFzc19vZihzdWJjbGFzcywgc3VwZXJjbGFzcykge1xuICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyBuYW1lcyB0byBjbGFzcyBvYmplY3RzXG4gICAgICAgIGxldCBzdWJjbGFzc19vYmplY3QgPSBzdWJjbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBzdWJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdCA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKHN1YmNsYXNzKTtcbiAgICAgICAgICAgIGlmICghc3ViY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdWJjbGFzcyAtIHJldHVybiBmYWxzZSBwZXIgc3BlY1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzdXBlcmNsYXNzX29iamVjdCA9IHN1cGVyY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2Ygc3VwZXJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1cGVyY2xhc3Nfb2JqZWN0ID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoc3VwZXJjbGFzcyk7XG4gICAgICAgICAgICBpZiAoIXN1cGVyY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdXBlcmNsYXNzIC0gZmFpbCBsb3VkIHBlciBzcGVjXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdXBlcmNsYXNzIG5vdCBmb3VuZCBpbiBtYW5pZmVzdDogJHtzdXBlcmNsYXNzfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2xhc3NlcyBhcmUgbm90IHN1YmNsYXNzZXMgb2YgdGhlbXNlbHZlc1xuICAgICAgICBpZiAoc3ViY2xhc3Nfb2JqZWN0ID09PSBzdXBlcmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2FsayB1cCB0aGUgaW5oZXJpdGFuY2UgY2hhaW5cbiAgICAgICAgbGV0IGN1cnJlbnRfY2xhc3MgPSBzdWJjbGFzc19vYmplY3Q7XG4gICAgICAgIHdoaWxlIChjdXJyZW50X2NsYXNzKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcyA9PT0gc3VwZXJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1vdmUgdXAgdG8gcGFyZW50IGNsYXNzXG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcy5fZXh0ZW5kcykge1xuICAgICAgICAgICAgICAgIC8vIF9leHRlbmRzIG1heSBiZSBhIHN0cmluZyBvciBjbGFzcyByZWZlcmVuY2VcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRfY2xhc3MuX2V4dGVuZHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShjdXJyZW50X2NsYXNzLl9leHRlbmRzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzID0gY3VycmVudF9jbGFzcy5fZXh0ZW5kcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhIGNsYXNzIGJ5IGl0cyBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzX25hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY2xhc3NcbiAgICAgKiBAcmV0dXJucyB7Q2xhc3N8bnVsbH0gVGhlIGNsYXNzIG9iamVjdCBvciBudWxsIGlmIG5vdCBmb3VuZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfY2xhc3NfYnlfbmFtZShjbGFzc19uYW1lKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMgfHwgIU1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXS5jbGFzcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHJlZ2lzdGVyZWQgY2xhc3Nlc1xuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIHtjbGFzc19uYW1lLCBjbGFzc19vYmplY3QsIGV4dGVuZHN9XG4gICAgICovXG4gICAgc3RhdGljIGdldF9hbGxfY2xhc3NlcygpIHtcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjbGFzc19uYW1lIGluIE1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgY2xhc3NfbmFtZTogY2xhc3NkYXRhLm5hbWUsXG4gICAgICAgICAgICAgICAgY2xhc3Nfb2JqZWN0OiBjbGFzc2RhdGEuY2xhc3MsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NkYXRhLmV4dGVuZHMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIHJlc3VsdHMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBidWlsZCBrZXkgZnJvbSB0aGUgYXBwbGljYXRpb24gY29uZmlndXJhdGlvblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBidWlsZCBrZXkgb3IgXCJOT0JVSUxEXCIgaWYgbm90IGF2YWlsYWJsZVxuICAgICAqL1xuICAgIHN0YXRpYyBidWlsZF9rZXkoKSB7XG4gICAgICAgIGlmICh3aW5kb3cucnN4YXBwICYmIHdpbmRvdy5yc3hhcHAuYnVpbGRfa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LnJzeGFwcC5idWlsZF9rZXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdOT0JVSUxEJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGVjb3JhdG9ycyBmb3IgYSBzcGVjaWZpYyBjbGFzcyBhbmQgbWV0aG9kXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kX25hbWUgLSBUaGUgbWV0aG9kIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8bnVsbH0gQXJyYXkgb2YgZGVjb3JhdG9yIG9iamVjdHMgb3IgbnVsbCBpZiBub25lIGZvdW5kXG4gICAgICovXG4gICAgc3RhdGljIGdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIC8vIENvbnZlcnQgY2xhc3Mgb2JqZWN0IHRvIG5hbWUgaWYgbmVlZGVkXG4gICAgICAgIGlmICh0eXBlb2YgY2xhc3NfbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNsYXNzX25hbWUgPSBjbGFzc19uYW1lLl9uYW1lIHx8IGNsYXNzX25hbWUubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsYXNzX2luZm8gPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgaWYgKCFjbGFzc19pbmZvIHx8ICFjbGFzc19pbmZvLmRlY29yYXRvcnMgfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9yc1ttZXRob2RfbmFtZV0pIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGNvbXBhY3QgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgICAgcmV0dXJuIE1hbmlmZXN0Ll90cmFuc2Zvcm1fZGVjb3JhdG9ycyhjbGFzc19pbmZvLmRlY29yYXRvcnNbbWV0aG9kX25hbWVdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIG1ldGhvZHMgd2l0aCBkZWNvcmF0b3JzIGZvciBhIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3Qgd2l0aCBtZXRob2QgbmFtZXMgYXMga2V5cyBhbmQgZGVjb3JhdG9yIGFycmF5cyBhcyB2YWx1ZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2FsbF9kZWNvcmF0b3JzKGNsYXNzX25hbWUpIHtcbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgaWYgKHR5cGVvZiBjbGFzc19uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY2xhc3NfbmFtZSA9IGNsYXNzX25hbWUuX25hbWUgfHwgY2xhc3NfbmFtZS5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xhc3NfaW5mbyA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICBpZiAoIWNsYXNzX2luZm8gfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9ycykge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGFsbCBkZWNvcmF0b3JzIGZyb20gY29tcGFjdCB0byBvYmplY3QgZm9ybWF0XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgICBmb3IgKGxldCBtZXRob2RfbmFtZSBpbiBjbGFzc19pbmZvLmRlY29yYXRvcnMpIHtcbiAgICAgICAgICAgIHJlc3VsdFttZXRob2RfbmFtZV0gPSBNYW5pZmVzdC5fdHJhbnNmb3JtX2RlY29yYXRvcnMoY2xhc3NfaW5mby5kZWNvcmF0b3JzW21ldGhvZF9uYW1lXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmFuc2Zvcm0gY29tcGFjdCBkZWNvcmF0b3IgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjb21wYWN0X2RlY29yYXRvcnMgLSBBcnJheSBvZiBbbmFtZSwgW2FyZ3NdXSB0dXBsZXNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIGRlY29yYXRvciBvYmplY3RzIHdpdGggbmFtZSBhbmQgYXJndW1lbnRzIHByb3BlcnRpZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJhbnNmb3JtX2RlY29yYXRvcnMoY29tcGFjdF9kZWNvcmF0b3JzKSB7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb21wYWN0X2RlY29yYXRvcnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcGFjdF9kZWNvcmF0b3JzLm1hcChkZWNvcmF0b3IgPT4ge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGVjb3JhdG9yKSAmJiBkZWNvcmF0b3IubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBkZWNvcmF0b3JbMF0sXG4gICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50czogZGVjb3JhdG9yWzFdIHx8IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEhhbmRsZSBtYWxmb3JtZWQgZGVjb3JhdG9yIGRhdGFcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ3Vua25vd24nLFxuICAgICAgICAgICAgICAgIGFyZ3VtZW50czogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgbWV0aG9kIGhhcyBhIHNwZWNpZmljIGRlY29yYXRvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfENsYXNzfSBjbGFzc19uYW1lIC0gVGhlIGNsYXNzIG5hbWUgb3IgY2xhc3Mgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZF9uYW1lIC0gVGhlIG1ldGhvZCBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRlY29yYXRvcl9uYW1lIC0gVGhlIGRlY29yYXRvciBuYW1lIHRvIGNoZWNrIGZvclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBtZXRob2QgaGFzIHRoZSBkZWNvcmF0b3JcbiAgICAgKi9cbiAgICBzdGF0aWMgaGFzX2RlY29yYXRvcihjbGFzc19uYW1lLCBtZXRob2RfbmFtZSwgZGVjb3JhdG9yX25hbWUpIHtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9ycyA9IE1hbmlmZXN0LmdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKTtcbiAgICAgICAgaWYgKCFkZWNvcmF0b3JzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGVjb3JhdG9ycy5zb21lKGQgPT4gZC5uYW1lID09PSBkZWNvcmF0b3JfbmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBzdWJjbGFzc2VzIG9mIGEgZ2l2ZW4gY2xhc3MgdXNpbmcgdGhlIHByZS1idWlsdCBpbmRleFxuICAgICAqIFRoaXMgaXMgdGhlIEphdmFTY3JpcHQgZXF1aXZhbGVudCBvZiBQSFAncyBNYW5pZmVzdDo6anNfZ2V0X3N1YmNsYXNzZXNfb2YoKVxuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gZ2V0IHN1YmNsYXNzZXMgb2ZcbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8Q2xhc3M+fSBBcnJheSBvZiBhY3R1YWwgY2xhc3Mgb2JqZWN0cyB0aGF0IGFyZSBzdWJjbGFzc2VzIG9mIHRoZSBiYXNlIGNsYXNzXG4gICAgICovXG4gICAgc3RhdGljIGpzX2dldF9zdWJjbGFzc2VzX29mKGJhc2VfY2xhc3MpIHtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBpbmRleCBpZiBuZWVkZWRcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXgpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9idWlsZF9zdWJjbGFzc19pbmRleCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3NfbmFtZSA9IGJhc2VfY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2YgYmFzZV9jbGFzcyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGJhc2VfY2xhc3NfbmFtZSA9IGJhc2VfY2xhc3MuX25hbWUgfHwgYmFzZV9jbGFzcy5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGJhc2UgY2xhc3MgZXhpc3RzXG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXNbYmFzZV9jbGFzc19uYW1lXSkge1xuICAgICAgICAgICAgLy8gQmFzZSBjbGFzcyBub3QgaW4gbWFuaWZlc3QgLSByZXR1cm4gZW1wdHkgYXJyYXlcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCBzdWJjbGFzcyBuYW1lcyBmcm9tIHRoZSBpbmRleFxuICAgICAgICBjb25zdCBzdWJjbGFzc19uYW1lcyA9IE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtiYXNlX2NsYXNzX25hbWVdIHx8IFtdO1xuXG4gICAgICAgIC8vIENvbnZlcnQgbmFtZXMgdG8gYWN0dWFsIGNsYXNzIG9iamVjdHNcbiAgICAgICAgY29uc3Qgc3ViY2xhc3Nfb2JqZWN0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBzdWJjbGFzc19uYW1lIG9mIHN1YmNsYXNzX25hbWVzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tzdWJjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdHMucHVzaChjbGFzc2RhdGEuY2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU29ydCBieSBjbGFzcyBuYW1lIGZvciBkZXRlcm1pbmlzdGljIGJlaGF2aW9yXG4gICAgICAgIHN1YmNsYXNzX29iamVjdHMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgY29uc3QgbmFtZV9hID0gYS5fbmFtZSB8fCBhLm5hbWU7XG4gICAgICAgICAgICBjb25zdCBuYW1lX2IgPSBiLl9uYW1lIHx8IGIubmFtZTtcbiAgICAgICAgICAgIHJldHVybiBuYW1lX2EubG9jYWxlQ29tcGFyZShuYW1lX2IpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3ViY2xhc3Nfb2JqZWN0cztcbiAgICB9XG59XG5cbi8vIFJTWCBtYW5pZmVzdCBhdXRvbWF0aWNhbGx5IG1ha2VzIGNsYXNzZXMgZ2xvYmFsIC0gbm8gbWFudWFsIGFzc2lnbm1lbnQgbmVlZGVkXG4iXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNQSxRQUFRLENBQUM7RUFDWDtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLE9BQU9BLENBQUNDLEtBQUssRUFBRTtJQUNsQjtJQUNBLElBQUksT0FBT0YsUUFBUSxDQUFDRyxRQUFRLEtBQUssV0FBVyxFQUFFO01BQzFDSCxRQUFRLENBQUNHLFFBQVEsR0FBRyxDQUFDLENBQUM7SUFDMUI7O0lBRUE7SUFDQUQsS0FBSyxDQUFDRSxPQUFPLENBQUVDLElBQUksSUFBSztNQUNwQixJQUFJQyxZQUFZLEdBQUdELElBQUksQ0FBQyxDQUFDLENBQUM7TUFDMUIsSUFBSUUsVUFBVSxHQUFHRixJQUFJLENBQUMsQ0FBQyxDQUFDO01BQ3hCLElBQUlHLGFBQWEsR0FBR0gsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUk7TUFDbkMsSUFBSUksVUFBVSxHQUFHSixJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSTs7TUFFaEM7TUFDQUwsUUFBUSxDQUFDRyxRQUFRLENBQUNJLFVBQVUsQ0FBQyxHQUFHO1FBQzVCRyxLQUFLLEVBQUVKLFlBQVk7UUFDbkJLLElBQUksRUFBRUosVUFBVTtRQUNoQkssT0FBTyxFQUFFSixhQUFhO1FBQ3RCQyxVQUFVLEVBQUVBLFVBQVUsQ0FBRztNQUM3QixDQUFDOztNQUVEO01BQ0FILFlBQVksQ0FBQ08sS0FBSyxHQUFHTixVQUFVO01BQy9CRCxZQUFZLENBQUNRLFFBQVEsR0FBR04sYUFBYTtNQUNyQ0YsWUFBWSxDQUFDUyxXQUFXLEdBQUdOLFVBQVU7SUFDekMsQ0FBQyxDQUFDOztJQUVGO0lBQ0FU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
|