/* === storage/rsx-tmp/bundle_config_Bootstrap5_Src_Bundle.js === */ window.rsxapp = window.rsxapp || {}; window.rsxapp.module_paths = {"bootstrap5_src":"rsx\/theme\/vendor\/bootstrap5\/scss"}; /* === storage/rsx-tmp/npm_import_declarations_95a6f602c98037611b640b0b5342830b.js === */ // NPM Import Declarations for App Bundle // Auto-generated to provide NPM modules to app bundle scope // Cache key: 95a6f602c98037611b640b0b5342830b const jqhtml = window._rsx_npm.jqhtml; if (!jqhtml) { throw new Error( 'RSX Framework Error: NPM module "jqhtml" not found.\n' + 'Expected window._rsx_npm.jqhtml to be defined by the vendor bundle.' ); } const _Base_Jqhtml_Component = window._rsx_npm._Base_Jqhtml_Component; if (!_Base_Jqhtml_Component) { throw new Error( 'RSX Framework Error: NPM module "_Base_Jqhtml_Component" not found.\n' + 'Expected window._rsx_npm._Base_Jqhtml_Component to be defined by the vendor bundle.' ); } // Clean up NPM container to prevent console access delete window._rsx_npm; /* === app/RSpade/Core/Js/decorator.js (babel) === */ "use strict"; /** * Decorator function that marks a function as a decorator implementation. * * When a function has @decorator in its JSDoc comment, it whitelists that function * to be used as a decorator on other methods throughout the codebase. * * The function itself performs no operation - it simply returns its input unchanged. * Its purpose is purely as a marker for the manifest validation system. * * Usage: * // /** * // * My custom decorator implementation * // * @decorator * // *\/ * function my_custom_decorator(target, key, descriptor) { * // Decorator implementation * } * * This allows my_custom_decorator to be used as @my_custom_decorator on static methods. * * TODO: This is probably no longer necessary? maybe? */ function decorator(value) { return value; } /* === app/RSpade/Core/Js/browser.js (babel) === */ "use strict"; /* * Browser and DOM utility functions for the RSpade framework. * These functions handle browser detection, viewport utilities, and DOM manipulation. */ // ============================================================================ // BROWSER DETECTION // ============================================================================ /** * Detects if user is on a mobile device or using mobile viewport * @returns {boolean} True if mobile device or viewport < 992px * @todo Improve user agent detection for all mobile devices */ function is_mobile() { if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) { return true; } else if ($(window).width() < 992) { // 992px = bootstrap 4 col-md- return true; } else { return false; } } /** * Detects if user is on desktop (not mobile) * @returns {boolean} True if not mobile device/viewport */ function is_desktop() { return !is_mobile(); } /** * Detects the user's operating system * @returns {string} OS name: 'Mac OS', 'iPhone', 'iPad', 'Windows', 'Android-Phone', 'Android-Tablet', 'Linux', or 'Unknown' */ function get_os() { let user_agent = window.navigator.userAgent, platform = window.navigator.platform, macos_platforms = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'], windows_platforms = ['Win32', 'Win64', 'Windows', 'WinCE'], ios_platforms = ['iPhone', 'iPad', 'iPod'], os = null; let is_mobile_device = is_mobile(); if (macos_platforms.indexOf(platform) !== -1) { os = 'Mac OS'; } else if (ios_platforms.indexOf(platform) !== -1 && is_mobile_device) { os = 'iPhone'; } else if (ios_platforms.indexOf(platform) !== -1 && !is_mobile_device) { os = 'iPad'; } else if (windows_platforms.indexOf(platform) !== -1) { os = 'Windows'; } else if (/Android/.test(user_agent) && is_mobile_device) { os = 'Android-Phone'; } else if (/Android/.test(user_agent) && !is_mobile_device) { os = 'Android-Tablet'; } else if (!os && /Linux/.test(platform)) { os = 'Linux'; } else { os = 'Unknown'; } return os; } /** * Detects if the user agent is a web crawler/bot * @returns {boolean} True if user agent appears to be a bot/crawler */ function is_crawler() { let user_agent = navigator.userAgent; let bot_pattern = /bot|spider|crawl|slurp|archiver|ping|search|dig|tracker|monitor|snoopy|yahoo|baidu|msn|ask|teoma|axios/i; return bot_pattern.test(user_agent); } // ============================================================================ // DOM SCROLLING UTILITIES // ============================================================================ /** * Scrolls parent container to make target element visible if needed * @param {string|HTMLElement|jQuery} target - Target element to scroll into view */ function scroll_into_view_if_needed(target) { const $target = $(target); // Find the closest parent with overflow-y: auto const $parent = $target.parent(); // Calculate the absolute top position of the target const target_top = $target.position().top + $parent.scrollTop(); const target_height = $target.outerHeight(); const parent_height = $parent.height(); const scroll_position = $parent.scrollTop(); // Check if the target is out of view if (target_top < scroll_position || target_top + target_height > scroll_position + parent_height) { Debugger.console_debug('UI', 'Scrolling!', target_top); // Calculate the new scroll position to center the target let new_scroll_position = target_top + target_height / 2 - parent_height / 2; // Limit the scroll position between 0 and the maximum scrollable height new_scroll_position = Math.max(0, Math.min(new_scroll_position, $parent[0].scrollHeight - parent_height)); // Scroll the parent to the new scroll position $parent.scrollTop(new_scroll_position); } } /** * Scrolls page to make target element visible if needed (with animation) * @param {string|HTMLElement|jQuery} target - Target element to scroll into view */ function scroll_page_into_view_if_needed(target) { const $target = $(target); // Calculate the absolute top position of the target relative to the document const target_top = $target.offset().top; const target_height = $target.outerHeight(); const window_height = $(window).height(); const window_scroll_position = $(window).scrollTop(); // Check if the target is out of view if (target_top < window_scroll_position || target_top + target_height > window_scroll_position + window_height) { Debugger.console_debug('UI', 'Scrolling!', target_top); // Calculate the new scroll position to center the target const new_scroll_position = target_top + target_height / 2 - window_height / 2; // Animate the scroll to the new position $('html, body').animate({ scrollTop: new_scroll_position }, 1000); // duration of the scroll animation in milliseconds } } // ============================================================================ // DOM UTILITIES // ============================================================================ /** * Waits for all images on the page to load * @param {Function} callback - Function to call when all images are loaded */ function wait_for_images(callback) { const $images = $('img'); // Get all img tags const total_images = $images.length; let images_loaded = 0; if (total_images === 0) { callback(); // if there are no images, immediately call the callback } $images.each(function () { const img = new Image(); img.onload = function () { images_loaded++; if (images_loaded === total_images) { callback(); // call the callback when all images are loaded } }; img.onerror = function () { images_loaded++; if (images_loaded === total_images) { callback(); // also call the callback if an image fails to load } }; img.src = this.src; // this triggers the loading }); } /** * Creates a jQuery element containing a non-breaking space * @returns {jQuery} jQuery span element with   */ function $nbsp() { return $(' '); } /** * Escapes special characters in a jQuery selector * @param {string} id - Element ID to escape * @returns {string} jQuery selector string with escaped special characters * @warning Not safe for security-critical operations */ function escape_jq_selector(id) { return '#' + id.replace(/(:|\.|\[|\]|,|=|@)/g, '\\$1'); } /* === app/RSpade/Core/Js/datetime.js (babel) === */ "use strict"; /* * Date and time utility functions for the RSpade framework. * These functions handle date/time conversions and Unix timestamps. */ // ============================================================================ // DATE/TIME UTILITIES // ============================================================================ /** * Gets the current Unix timestamp (seconds since epoch) * @returns {number} Current Unix timestamp in seconds * @todo Calculate based on server time at page render * @todo Move to a date library */ function unix_time() { return Math.round(new Date().getTime() / 1000); } /** * Converts a date string to Unix timestamp * @param {string} str_date - Date string (Y-m-d H:i:s format) * @returns {number} Unix timestamp in seconds */ function ymdhis_to_unix(str_date) { const date = new Date(str_date); return date.getTime() / 1000; } /* === app/RSpade/Core/Js/error.js (babel) === */ "use strict"; /* * Error handling utility functions for the RSpade framework. * These functions handle error creation and debugging utilities. */ // ============================================================================ // ERROR HANDLING // ============================================================================ /** * Creates an error object from a string * @param {string|Object} str - Error message or existing error object * @param {number} [error_code] - Optional error status code * @returns {Object} Error object with error and status properties */ function error(str, error_code) { if (typeof str.error != undef) { return str; } else { if (typeof error_code == undef) { return { error: str, status: null }; } else { return { error: str, status: error_code }; } } } /** * Sanity check failure handler for JavaScript * * This function should be called when a sanity check fails - i.e., when the code * encounters a condition that "shouldn't happen" if everything is working correctly. * * Unlike PHP, we can't stop JavaScript execution, but we can: * 1. Throw an error that will be caught by error handlers * 2. Log a clear error to the console * 3. Provide stack trace for debugging * * Use this instead of silently returning or continuing when encountering unexpected conditions. * * @param {string} message Optional specific message about what shouldn't have happened * @throws {Error} Always throws with location and context information */ function shouldnt_happen() { let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; const error = new Error(); const stack = error.stack || ''; const stackLines = stack.split('\n'); // Get the caller location (skip the Error line and this function) let callerInfo = 'unknown location'; if (stackLines.length > 2) { const callerLine = stackLines[2] || stackLines[1] || ''; // Extract file and line number from stack trace const match = callerLine.match(/at\s+.*?\s+\((.*?):(\d+):(\d+)\)/) || callerLine.match(/at\s+(.*?):(\d+):(\d+)/); if (match) { callerInfo = `${match[1]}:${match[2]}`; } } let errorMessage = `Fatal: shouldnt_happen() was called at ${callerInfo}\n`; errorMessage += 'This indicates a sanity check failed - the code is not behaving as expected.\n'; if (message) { errorMessage += `Details: ${message}\n`; } errorMessage += 'Please thoroughly review the related code to determine why this error occurred.'; // Log to console with full visibility console.error('='.repeat(80)); console.error('SANITY CHECK FAILURE'); console.error('='.repeat(80)); console.error(errorMessage); console.error('Stack trace:', stack); console.error('='.repeat(80)); // Throw error to stop execution flow const fatalError = new Error(errorMessage); fatalError.name = 'SanityCheckFailure'; throw fatalError; } /* === app/RSpade/Core/Js/hash.js (babel) === */ "use strict"; /* * Hashing and comparison utility functions for the RSpade framework. * These functions handle object hashing and deep comparison. */ // ============================================================================ // HASHING AND COMPARISON // ============================================================================ /** * Generates a unique hash for any value (handles objects, arrays, circular references) * @param {*} the_var - Value to hash * @param {boolean} [calc_sha1=true] - If true, returns SHA1 hash; if false, returns JSON * @param {Array} [ignored_keys=null] - Keys to ignore when hashing objects * @returns {string} SHA1 hash or JSON string of the value */ function hash(the_var) { let calc_sha1 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; let ignored_keys = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; if (typeof the_var == undef) { the_var = '__undefined__'; } if (ignored_keys === null) { ignored_keys = ['$']; } // Converts value to json, discarding circular references let json_stringify_nocirc = function (value) { const cache = []; return JSON.stringify(value, function (key, v) { if (typeof v === 'object' && typeof the_var._cache_key == 'function') { return the_var._hash_key(); } else if (typeof v === 'object' && v !== null) { if (cache.indexOf(v) !== -1) { // Duplicate reference found, discard key return; } cache.push(v); } return v; }); }; // Turn every property and all its children into a single depth array of values that we can then // sort and hash as a whole let flat_var = {}; let _flatten = function (the_var, prefix) { let depth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; // If a class object is provided, circular references can make the call stack recursive. // For the purposes of how the hash function is called, this should be sufficient. if (depth > 10) { return; } // Does not account for dates i think... if (is_object(the_var) && typeof the_var._cache_key == 'function') { // Use _cache_key to hash components flat_var[prefix] = the_var._hash_key(); } else if (is_object(the_var) && typeof Abstract !== 'undefined' && the_var instanceof Abstract) { // Stringify all class objects flat_var[prefix] = json_stringify_nocirc(the_var); } else if (is_object(the_var)) { // Iterate other objects flat_var[prefix] = {}; for (let k in the_var) { if (the_var.hasOwnProperty(k) && ignored_keys.indexOf(k) == -1) { _flatten(the_var[k], prefix + '..' + k, depth + 1); } } } else if (is_array(the_var)) { // Iterate arrays flat_var[prefix] = []; let i = 0; foreach(the_var, v => { _flatten(v, prefix + '..' + i, depth + 1); i++; }); } else if (is_function(the_var)) { // nothing } else if (!is_numeric(the_var)) { flat_var[prefix] = String(the_var); } else { flat_var[prefix] = the_var; } }; _flatten(the_var, '_'); let sorter = []; foreach(flat_var, function (v, k) { sorter.push([k, v]); }); sorter.sort(function (a, b) { return a[0] > b[0]; }); let json = JSON.stringify(sorter); if (calc_sha1) { let hashed = sha1.sha1(json); return hashed; } else { return json; } } /** * Deep comparison of two values (ignores property order and functions) * @param {*} a - First value to compare * @param {*} b - Second value to compare * @returns {boolean} True if values are deeply equal */ function deep_equal(a, b) { return hash(a, false) == hash(b, false); } /* === app/RSpade/Core/Js/Mutex.js (babel) === */ "use strict"; /** * Mutex decorator for exclusive method execution * * Without arguments: Per-instance locking (each object has its own lock per method) * @mutex * async my_method() { ... } * * With ID argument: Global locking by ID (all instances share the lock) * @mutex('operation_name') * async my_method() { ... } * * @decorator * @param {string} [global_id] - Optional global mutex ID for cross-instance locking */ function mutex(global_id) { // Storage (using IIFEs to keep WeakMap/Map in closure scope) const instance_mutexes = function () { if (!mutex._instance_storage) { mutex._instance_storage = new WeakMap(); } return mutex._instance_storage; }(); const global_mutexes = function () { if (!mutex._global_storage) { mutex._global_storage = new Map(); } return mutex._global_storage; }(); /** * Get or create a mutex for a specific instance and method */ function get_instance_mutex(instance, method_name) { let instance_locks = instance_mutexes.get(instance); if (!instance_locks) { instance_locks = new Map(); instance_mutexes.set(instance, instance_locks); } let lock_state = instance_locks.get(method_name); if (!lock_state) { lock_state = { active: false, queue: [] }; instance_locks.set(method_name, lock_state); } return lock_state; } /** * Get or create a global mutex by ID */ function get_global_mutex(id) { let lock_state = global_mutexes.get(id); if (!lock_state) { lock_state = { active: false, queue: [] }; global_mutexes.set(id, lock_state); } return lock_state; } /** * Execute the next queued operation for a mutex */ function schedule_next(lock_state) { if (lock_state.active || lock_state.queue.length === 0) { return; } const { fn, resolve, reject } = lock_state.queue.shift(); lock_state.active = true; Promise.resolve().then(fn).then(resolve, reject).finally(() => { lock_state.active = false; schedule_next(lock_state); }); } /** * Acquire a mutex lock and execute callback */ function acquire_lock(lock_state, fn) { return new Promise((resolve, reject) => { lock_state.queue.push({ fn, resolve, reject }); schedule_next(lock_state); }); } // If called with an ID argument: @mutex('id') if (typeof global_id === 'string') { return function (target, key, descriptor) { const original_method = descriptor.value; if (typeof original_method !== 'function') { throw new Error(`@mutex can only be applied to methods (tried to apply to ${key})`); } descriptor.value = function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } const lock_state = get_global_mutex(global_id); return acquire_lock(lock_state, () => original_method.apply(this, args)); }; return descriptor; }; } // If called without arguments: @mutex (target is the first argument) const target = global_id; // In this case, first arg is target const key = arguments[1]; const descriptor = arguments[2]; const original_method = descriptor.value; if (typeof original_method !== 'function') { throw new Error(`@mutex can only be applied to methods (tried to apply to ${key})`); } descriptor.value = function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } const lock_state = get_instance_mutex(this, key); return acquire_lock(lock_state, () => original_method.apply(this, args)); }; return descriptor; } /* === app/RSpade/Core/Js/async.js (babel) === */ "use strict"; /* * Async utility functions for the RSpade framework. * These functions handle asynchronous operations, delays, debouncing, and mutexes. */ // ============================================================================ // ASYNC UTILITIES // ============================================================================ /** * Pauses execution for specified milliseconds * @param {number} [milliseconds=0] - Delay in milliseconds (0 uses requestAnimationFrame) * @returns {Promise} Promise that resolves after delay * @example await sleep(1000); // Wait 1 second */ function sleep() { let milliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; return new Promise(resolve => { if (milliseconds == 0 && requestAnimationFrame) { requestAnimationFrame(resolve); } else { setTimeout(resolve, milliseconds); } }); } /** * Creates a debounced function with exclusivity and promise fan-in * * This function, when invoked, immediately runs the callback exclusively. * For subsequent invocations, it applies a delay before running the callback exclusively again. * The delay starts after the current asynchronous operation resolves. * * If 'delay' is set to 0, the function will only prevent enqueueing multiple executions of the * same method more than once, but will still run them immediately in an exclusive sequential manner. * * The most recent invocation of the function will be the parameters that get passed to the function * when it invokes. * * The function returns a promise that resolves when the next exclusive execution completes. * * Usage as function: * const debouncedFn = debounce(myFunction, 250); * * Usage as decorator: * @debounce(250) * myMethod() { ... } * * @param {function|number} callback_or_delay The callback function OR delay when used as decorator * @param {number} delay The delay in milliseconds before subsequent invocations * @param {boolean} immediate if true, the first time the action is called, the callback executes immediately * @returns {function} A function that when invoked, runs the callback immediately and exclusively, * * @decorator */ function debounce(callback_or_delay, delay) { let immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; // Decorator usage: @debounce(250) or @debounce(250, true) // First argument is a number (the delay), returns decorator function if (typeof callback_or_delay === 'number') { const decorator_delay = callback_or_delay; const decorator_immediate = delay || false; // TC39 decorator form: receives (value, context) return function (value, context) { if (context.kind === 'method') { return debounce_impl(value, decorator_delay, decorator_immediate); } }; } // Function usage: debounce(fn, 250) // First argument is a function (the callback) const callback = callback_or_delay; return debounce_impl(callback, delay, immediate); } /** * Internal implementation of debounce logic * @private */ function debounce_impl(callback, delay) { let immediate = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; let running = false; let queued = false; let last_end_time = 0; // timestamp of last completed run let timer = null; let next_args = []; let next_context = null; let resolve_queue = []; let reject_queue = []; const run_function = async () => { const these_resolves = resolve_queue; const these_rejects = reject_queue; const args = next_args; const context = next_context; resolve_queue = []; reject_queue = []; next_args = []; next_context = null; queued = false; running = true; try { const result = await callback.apply(context, args); for (const resolve of these_resolves) resolve(result); } catch (err) { for (const reject of these_rejects) reject(err); } finally { running = false; last_end_time = Date.now(); if (queued) { clearTimeout(timer); timer = setTimeout(run_function, Math.max(delay, 0)); } else { timer = null; } } }; return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } next_args = args; next_context = this; return new Promise((resolve, reject) => { resolve_queue.push(resolve); reject_queue.push(reject); // Nothing running and nothing scheduled if (!running && !timer) { const first_call = last_end_time === 0; if (immediate && first_call) { run_function(); return; } const since = first_call ? Infinity : Date.now() - last_end_time; if (since >= delay) { run_function(); } else { const wait = Math.max(delay - since, 0); clearTimeout(timer); timer = setTimeout(run_function, wait); } return; } // If we're already running or a timer exists, just mark queued. // The finally{} of run_function handles scheduling after full delay. queued = true; }); }; } // ============================================================================ // READ-WRITE LOCK FUNCTIONS - Delegated to ReadWriteLock class // ============================================================================ /** * Acquire an exclusive write lock by name. * Only one writer runs at a time; blocks readers until finished. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ function rwlock(name, cb) { return ReadWriteLock.acquire(name, cb); } /** * Acquire a shared read lock by name. * Multiple readers run in parallel, but readers are blocked by queued/active writers. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ function rwlock_read(name, cb) { return ReadWriteLock.acquire_read(name, cb); } /** * Forcefully clear all locks and queues for a given name. * @param {string} name */ function rwlock_force_unlock(name) { ReadWriteLock.force_unlock(name); } /** * Inspect lock state for debugging. * @param {string} name * @returns {{readers:number, writer_active:boolean, reader_q:number, writer_q:number}} */ function rwlock_pending(name) { return ReadWriteLock.pending(name); } /* === app/RSpade/Core/Js/functions.js (babel) === */ "use strict"; /* * Core utility functions for the RSpade framework. * These functions handle type checking, type conversion, string manipulation, * and object/array utilities. They mirror functionality from PHP functions. * * Other utility functions are organized in: * - async.js: Async utilities (sleep, debounce, mutex) * - browser.js: Browser/DOM utilities (is_mobile, scroll functions) * - datetime.js: Date/time utilities * - hash.js: Hashing and comparison * - error.js: Error handling */ // Todo: test that prod build identifies and removes uncalled functions from the final bundle. // ============================================================================ // CONSTANTS AND HELPERS // ============================================================================ // Define commonly used constants const undef = 'undefined'; /** * Iterates over arrays or objects with promise support * * Works with both synchronous and asynchronous callbacks. If the callback * returns promises, they are executed in parallel and this function returns * a promise that resolves when all parallel tasks complete. * * @param {Array|Object} obj - Collection to iterate * @param {Function} callback - Function to call for each item (value, key) - can be async * @returns {Promise|undefined} Promise if any callbacks return promises, undefined otherwise * * @example * // Synchronous usage * foreach([1,2,3], (val) => console.log(val)); * * @example * // Asynchronous usage - waits for all to complete * await foreach([1,2,3], async (val) => { * await fetch('/api/process/' + val); * }); */ function foreach(obj, callback) { const results = []; if (Array.isArray(obj)) { obj.forEach((value, index) => { results.push(callback(value, index)); }); } else if (obj && typeof obj === 'object') { for (let key in obj) { if (obj.hasOwnProperty(key)) { results.push(callback(obj[key], key)); } } } // Filter for promises const promises = results.filter(result => result && typeof result.then === 'function'); // If there are any promises, return Promise.all to wait for all to complete if (promises.length > 0) { return Promise.all(promises); } // No promises returned, so we're done return undefined; } // ============================================================================ // TYPE CHECKING FUNCTIONS // ============================================================================ /** * Checks if a value is numeric * @param {*} n - Value to check * @returns {boolean} True if the value is a finite number */ function is_numeric(n) { return !isNaN(parseFloat(n)) && isFinite(n); } /** * Checks if a value is a string * @param {*} s - Value to check * @returns {boolean} True if the value is a string */ function is_string(s) { return typeof s == 'string'; } /** * Checks if a value is an integer * @param {*} n - Value to check * @returns {boolean} True if the value is an integer */ function is_integer(n) { return Number.isInteger(n); } /** * Checks if a value is a promise-like object * @param {*} obj - Value to check * @returns {boolean} True if the value has a then method */ function is_promise(obj) { return typeof obj == 'object' && typeof obj.then == 'function'; } /** * Checks if a value is an array * @param {*} obj - Value to check * @returns {boolean} True if the value is an array */ function is_array(obj) { return Array.isArray(obj); } /** * Checks if a value is an object (excludes null) * @param {*} obj - Value to check * @returns {boolean} True if the value is an object and not null */ function is_object(obj) { return typeof obj === 'object' && obj !== null; } /** * Checks if a value is a function * @param {*} function_to_check - Value to check * @returns {boolean} True if the value is a function */ function is_function(function_to_check) { return function_to_check && {}.toString.call(function_to_check) === '[object Function]'; } /** * Checks if a string is a valid email address * Uses a practical RFC 5322 compliant regex that matches 99.99% of real-world email addresses * @param {string} email - Email address to validate * @returns {boolean} True if the string is a valid email address */ function is_email(email) { if (!is_string(email)) { return false; } const regex = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i; return regex.test(email); } /** * Checks if a value is defined (not undefined) * @param {*} value - Value to check * @returns {boolean} True if value is not undefined */ function isset(value) { return typeof value != undef; } /** * Checks if a value is empty (null, undefined, 0, "", empty array/object) * @param {*} object - Value to check * @returns {boolean} True if the value is considered empty */ function empty(object) { if (typeof object == undef) { return true; } if (object === null) { return true; } if (typeof object == 'string' && object == '') { return true; } if (typeof object == 'number') { return object == 0; } if (Array.isArray(object)) { return !object.length; } if (typeof object == 'function') { return false; } for (let key in object) { if (object.hasOwnProperty(key)) { return false; } } return true; } // ============================================================================ // TYPE CONVERSION FUNCTIONS // ============================================================================ /** * Converts a value to a floating point number * Returns 0 for null, undefined, NaN, or non-numeric values * @param {*} val - Value to convert * @returns {number} Floating point number */ function float(val) { // Handle null, undefined, empty string if (val === null || val === undefined || val === '') { return 0.0; } // Try to parse the value const parsed = parseFloat(val); // Check for NaN and return 0 if parsing failed return isNaN(parsed) ? 0.0 : parsed; } /** * Converts a value to an integer * Returns 0 for null, undefined, NaN, or non-numeric values * @param {*} val - Value to convert * @returns {number} Integer value */ function int(val) { // Handle null, undefined, empty string if (val === null || val === undefined || val === '') { return 0; } // Try to parse the value const parsed = parseInt(val, 10); // Check for NaN and return 0 if parsing failed return isNaN(parsed) ? 0 : parsed; } /** * Converts a value to a string * Returns empty string for null or undefined * @param {*} val - Value to convert * @returns {string} String representation */ function str(val) { // Handle null and undefined specially if (val === null || val === undefined) { return ''; } // Convert to string return String(val); } /** * Converts numeric strings to numbers, returns all other values unchanged * Used when you need to ensure numeric types but don't want to force * conversion of non-numeric values (which would become 0) * @param {*} val - Value to convert * @returns {*} Number if input was numeric string, otherwise unchanged */ function value_unless_numeric_string_then_numeric_value(val) { // If it's already a number, return it if (typeof val === 'number') { return val; } // If it's a string and numeric, convert it if (is_string(val) && is_numeric(val)) { // Use parseFloat to handle both integers and floats return parseFloat(val); } // Return everything else unchanged (null, objects, non-numeric strings, etc.) return val; } // ============================================================================ // STRING MANIPULATION FUNCTIONS // ============================================================================ /** * Escapes HTML special characters (uses Lodash escape) * @param {string} str - String to escape * @returns {string} HTML-escaped string */ function html(str) { return _.escape(str); } /** * Converts newlines to HTML line breaks * @param {string} str - String to convert * @returns {string} String with newlines replaced by
*/ function nl2br(str) { if (typeof str === undef || str === null) { return ''; } return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1
$2'); } /** * Escapes HTML and converts newlines to
* @param {string} str - String to process * @returns {string} HTML-escaped string with line breaks */ function htmlbr(str) { return nl2br(html(str)); } /** * URL-encodes a string * @param {string} str - String to encode * @returns {string} URL-encoded string */ function urlencode(str) { return encodeURIComponent(str); } /** * URL-decodes a string * @param {string} str - String to decode * @returns {string} URL-decoded string */ function urldecode(str) { return decodeURIComponent(str); } /** * JSON-encodes a value * @param {*} value - Value to encode * @returns {string} JSON string */ function json_encode(value) { return JSON.stringify(value); } /** * JSON-decodes a string * @param {string} str - JSON string to decode * @returns {*} Decoded value */ function json_decode(str) { return JSON.parse(str); } /** * Console debug output with channel filtering * Alias for Debugger.console_debug * @param {string} channel - Debug channel name * @param {...*} values - Values to log */ function console_debug(channel) { for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { values[_key - 1] = arguments[_key]; } Debugger.console_debug(channel, ...values); } /** * Replaces all occurrences of a substring in a string * @param {string} string - String to search in * @param {string} search - Substring to find * @param {string} replace - Replacement substring * @returns {string} String with all occurrences replaced */ function replace_all(string, search, replace) { if (!is_string(string)) { string = string + ''; } return string.split(search).join(replace); } /** * Capitalizes the first letter of each word * @param {string} input - String to capitalize * @returns {string} String with first letter of each word capitalized */ function ucwords(input) { return input.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); } // ============================================================================ // OBJECT AND ARRAY UTILITIES // ============================================================================ /** * Counts the number of properties in an object or elements in an array * @param {Object|Array} o - Object or array to count * @returns {number} Number of own properties/elements */ function count(o) { let c = 0; for (const k in o) { if (o.hasOwnProperty(k)) { ++c; } } return c; } /** * Creates a shallow clone of an object, array, or function * @param {*} obj - Value to clone * @returns {*} Cloned value */ function clone(obj) { if (typeof Function.prototype.__clone == undef) { Function.prototype.__clone = function () { //https://stackoverflow.com/questions/1833588/javascript-clone-a-function const that = this; let temp = function cloned() { return that.apply(this, arguments); }; for (let key in this) { if (this.hasOwnProperty(key)) { temp[key] = this[key]; } } return temp; }; } if (typeof obj == 'function') { return obj.__clone(); } else if (obj.constructor && obj.constructor == Array) { return obj.slice(0); } else { // https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object/30042948#30042948 return Object.assign({}, obj); } } /** * Returns the first non-null/undefined value from arguments * @param {...*} arguments - Values to check * @returns {*} First non-null/undefined value, or null if none found */ function coalesce() { let args = Array.from(arguments); let return_val = null; args.forEach(function (arg) { if (return_val === null && typeof arg != undef && arg !== null) { return_val = arg; } }); return return_val; } /** * Converts CSV string to array, trimming each element * @param {string} str_csv - CSV string to convert * @returns {Array} Array of trimmed values * @todo Handle quoted/escaped characters */ function csv_to_array_trim(str_csv) { const parts = str_csv.split(','); const ret = []; foreach(parts, part => { ret.push(part.trim()); }); return ret; } /* === app/RSpade/Core/Js/Manifest.js (babel) === */ "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} 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 /* === app/RSpade/Core/Js/Rsx_Behaviors.js (babel) === */ "use strict"; /** * Rsx_Behaviors - Core Framework User Experience Enhancements * * This class provides automatic quality-of-life behaviors that improve the default * browser experience for RSX applications. These behaviors are transparent to * application developers and run automatically on framework initialization. * * These behaviors use jQuery event delegation to handle both existing and dynamically * added content. They are implemented with low priority to allow application code to * override default behaviors when needed. * * @internal Framework use only - not part of public API */ class Rsx_Behaviors { static _on_framework_core_init() { Rsx_Behaviors._init_ignore_invalid_anchor_links(); Rsx_Behaviors._trim_copied_text(); } /** * - Anchor link handling: Prevents broken "#" links from causing page jumps or URL changes * - Ignores "#" (empty hash) to prevent scroll-to-top behavior * - Ignores "#placeholder*" links used as route placeholders during development * - Validates anchor targets exist before allowing navigation * - Preserves normal anchor behavior when targets exist */ static _init_ignore_invalid_anchor_links() { return; // disabled for now - make this into a configurable option // Use event delegation on document to handle all current and future anchor clicks // Use mousedown instead of click to run before most application handlers $(document).on('mousedown', 'a[href^="#"]', function (e) { const $link = $(this); const href = $link.attr('href'); // Check if another handler has already prevented default if (e.isDefaultPrevented()) { return; } // Allow data-rsx-allow-hash attribute to bypass this behavior if ($link.data('rsx-allow-hash')) { return; } // Handle empty hash - prevent scroll to top if (href === '#') { e.preventDefault(); e.stopImmediatePropagation(); return false; } // Handle placeholder links used during development if (href.startsWith('#placeholder')) { e.preventDefault(); e.stopImmediatePropagation(); return false; } // For other hash links, check if target exists const targetId = href.substring(1); if (targetId) { // Check for element with matching ID or name attribute const targetExists = document.getElementById(targetId) !== null || document.querySelector(`[name="${targetId}"]`) !== null; if (!targetExists) { // Target doesn't exist - prevent navigation e.preventDefault(); e.stopImmediatePropagation(); return false; } // Target exists - allow normal anchor behavior } }); } /** * - Copy text trimming: Automatically removes leading/trailing whitespace from copied text * - Hold Shift to preserve whitespace * - Skips trimming in code blocks, textareas, and contenteditable elements */ static _trim_copied_text() { document.addEventListener('copy', function (event) { // Don't trim if user is holding Shift (allows copying with whitespace if needed) if (event.shiftKey) return; let selection = window.getSelection(); let selected_text = selection.toString(); // Don't trim if selection is empty if (!selected_text) return; // Don't trim if copying from code blocks, textareas, or content-editable (preserve formatting) let container = selection.getRangeAt(0).commonAncestorContainer; if (container.nodeType === 3) container = container.parentNode; // Text node to element if (container.closest('pre, code, .code-block, textarea, [contenteditable="true"]')) return; let trimmed_text = selected_text.trim(); // Only modify if there's actually whitespace to trim if (trimmed_text !== selected_text && trimmed_text.length > 0) { event.preventDefault(); event.clipboardData.setData('text/plain', trimmed_text); console.log('Copy: trimmed whitespace from selection'); } }); } } /* === app/RSpade/Core/Js/Rsx_Cache.js (babel) === */ "use strict"; // Simple key value cache. Can only store 5000 entries, will reset after 5000 entries. // Todo: keep local cache concept the same, replace global cache concept with the nov 2019 version of // session cache. Use a session key & build key to track cache keys so cached values only last until user logs out. // review session code to ensure that session key *always* rotates on logout. Make session id a protected value. class Rsx_Cache { static on_core_define() { Core_Cache._caches = { global: {}, instance: {} }; Core_Cache._caches_set = 0; } // Alias for get_instance static get(key) { return Rsx_Cache.get_instance(key); } // Returns from the pool of cached data for this 'instance'. An instance // in this case is a virtual page load / navigation in the SPA. Call Main.lib.reset() to reset. // Returns null on failure static get_instance(key) { if (Main.debug('no_api_cache')) { return null; } let key_encoded = Rsx_Cache._encodekey(key); if (typeof Core_Cache._caches.instance[key_encoded] != undef) { return JSON.parse(Core_Cache._caches.instance[key_encoded]); } return null; } // Returns null on failure // Returns a cached value from global cache (unique to page load, survives reset()) static get_global(key) { if (Main.debug('no_api_cache')) { return null; } let key_encoded = Rsx_Cache._encodekey(key); if (typeof Core_Cache._caches.global[key_encoded] != undef) { return JSON.parse(Core_Cache._caches.global[key_encoded]); } return null; } // Sets a value in instance and global cache (not shared between browser tabs) static set(key, value) { if (Main.debug('no_api_cache')) { return; } if (value === null) { return; } if (value.length > 64 * 1024) { Debugger.console_debug('CACHE', 'Warning - not caching large cache entry', key); return; } let key_encoded = Rsx_Cache._encodekey(key); Core_Cache._caches.global[key_encoded] = JSON.stringify(value); Core_Cache._caches.instance[key_encoded] = JSON.stringify(value); // Debugger.console_debug("CACHE", "Set", key, value); Core_Cache._caches_set++; // Reset cache after 5000 items set if (Core_Cache._caches_set > 5000) { // Get an accurate count Core_Cache._caches_set = count(Core_Cache._caches.global); if (Core_Cache._caches_set > 5000) { Core_Cache._caches = { global: {}, instance: {} }; Core_Cache._caches_set = 0; } } } // Returns null on failure // Returns a cached value from session cache (shared between browser tabs) static get_session(key) { if (Main.debug('no_api_cache')) { return null; } if (!Rsx_Cache._supportsStorage()) { return null; } let key_encoded = Rsx_Cache._encodekey(key); let rs = sessionStorage.getItem(key_encoded); if (!empty(rs)) { return JSON.parse(rs); } else { return null; } } // Sets a value in session cache (shared between browser tabs) static set_session(key, value) { let _tryagain = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; if (Main.debug('no_api_cache')) { return; } if (value.length > 64 * 1024) { Debugger.console_debug('CACHE', 'Warning - not caching large cache entry', key); return; } if (!Rsx_Cache._supportsStorage()) { return null; } let key_encoded = Rsx_Cache._encodekey(key); try { sessionStorage.removeItem(key_encoded); sessionStorage.setItem(key_encoded, JSON.stringify(value)); } catch (e) { if (Rsx_Cache._isOutOfSpace(e) && sessionStorage.length) { sessionStorage.clear(); if (_tryagain) { Core_Cache.set_session(key, value, false); } } } } static _reset() { Core_Cache._caches.instance = {}; } /** * For given key of any type including an object, return a string representing * the key that the cached value should be stored as in sessionstorage */ static _encodekey(key) { const prefix = 'cache_'; // Session reimplement // var prefix = "cache_" + Spa.session().user_id() + "_"; if (is_string(key) && key.length < 150 && key.indexOf(' ') == -1) { return prefix + Manifest.build_key() + '_' + key; } else { return prefix + hash([Manifest.build_key(), key]); } } // Determines if sessionStorage is supported in the browser; // result is cached for better performance instead of being run each time. // Feature detection is based on how Modernizr does it; // it's not straightforward due to FF4 issues. // It's not run at parse-time as it takes 200ms in Android. // Code from https://github.com/pamelafox/lscache/blob/master/lscache.js, Apache License Pamelafox static _supportsStorage() { let key = '__cachetest__'; let value = key; if (Rsx_Cache.__supportsStorage !== undefined) { return Rsx_Cache.__supportsStorage; } // some browsers will throw an error if you try to access local storage (e.g. brave browser) // hence check is inside a try/catch try { if (!sessionStorage) { return false; } } catch (ex) { return false; } try { sessionStorage.setItem(key, value); sessionStorage.removeItem(key); Rsx_Cache.__supportsStorage = true; } catch (e) { // If we hit the limit, and we don't have an empty sessionStorage then it means we have support if (Rsx_Cache._isOutOfSpace(e) && sessionStorage.length) { Rsx_Cache.__supportsStorage = true; // just maxed it out and even the set test failed. } else { Rsx_Cache.__supportsStorage = false; } } return Rsx_Cache.__supportsStorage; } // Check to set if the error is us dealing with being out of space static _isOutOfSpace(e) { return e && (e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED' || e.name === 'QuotaExceededError'); } } /* === app/RSpade/Core/Js/Rsx_Init.js (babel) === */ "use strict"; /** * Rsx_Init - Core framework initialization and environment validation */ class Rsx_Init { /** * Called via Rsx._rsx_core_boot * Initializes the core environment and runs basic sanity checks */ static _on_framework_core_init() { if (!Rsx.is_prod()) { Rsx_Init.__environment_checks(); } } /** * Development environment checks to ensure proper configuration */ static __environment_checks() { // Find all script tags in the DOM const scripts = document.getElementsByTagName('script'); for (let i = 0; i < scripts.length; i++) { const script = scripts[i]; // Skip inline scripts (no src attribute) if (!script.src) { continue; } // Check if script has defer attribute if (!script.defer) { const src = script.src || '(inline script)'; const reason = `All script tags used in an RSpade project must have defer attribute. Found script without defer: ${src}`; // Stop framework boot with reason Rsx._rsx_core_boot_stop(reason); // Also log to console for visibility console.error(`[RSX BOOT STOPPED] ${reason}`); // Stop checking after first violation return; } } } } /* === app/RSpade/Core/Js/Rsx_Js_Model.js (babel) === */ "use strict"; // @FILE-SUBCLASS-01-EXCEPTION /** * Base class for JavaScript ORM models * * Provides core functionality for fetching records from backend PHP models. * All model stubs generated by the manifest extend this base class. * * Example usage: * // Fetch single record * const user = await User_Model.fetch(123); * * // Fetch multiple records * const users = await User_Model.fetch([1, 2, 3]); * * // Create instance with data * const user = new User_Model({id: 1, name: 'John'}); * * @Instantiatable */ class Rsx_Js_Model { /** * Constructor - Initialize model instance with data * * @param {Object} data - Key-value pairs to populate the model */ constructor() { let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; // __MODEL SYSTEM: Enables automatic ORM instantiation when fetching from PHP models. // PHP models add "__MODEL": "ClassName" to JSON, JavaScript uses it to create proper instances. // This provides typed model objects instead of plain JSON, with methods and type checking. // This constructor filters out the __MODEL marker that was used to identify which class // to instantiate, keeping only the actual data properties on the instance. const { __MODEL, ...modelData } = data; Object.assign(this, modelData); } /** * Fetch record(s) from the backend model * * This method mirrors the PHP Model::fetch() functionality. * The backend model must have a fetch() method with the * #[Ajax_Endpoint_Model_Fetch] annotation to be callable. * * @param {number|Array} id - Single ID or array of IDs to fetch * @returns {Promise} - Single model instance, array of instances, or false */ static async fetch(id) { const CurrentClass = this; // Get the model class name from the current class const modelName = CurrentClass.name; const response = await $.ajax({ url: `/_fetch/${modelName}`, method: 'POST', data: { id: id }, dataType: 'json' }); // Handle response based on type if (response === false) { return false; } // Use _instantiate_models_recursive to handle ORM instantiation // This will automatically detect __MODEL properties and create appropriate instances return Rsx_Js_Model._instantiate_models_recursive(response); } /** * Get the model class name * Used internally for API calls * * @returns {string} The class name */ static getModelName() { const CurrentClass = this; return CurrentClass.name; } /** * Refresh this instance with latest data from server * * @returns {Promise} Updated instance or false if not found */ async refresh() { const that = this; if (!that.id) { shouldnt_happen('Cannot refresh model without id property'); } const fresh = await that.constructor.fetch(that.id); if (fresh === false) { return false; } // Update this instance with fresh data Object.assign(that, fresh); return that; } /** * Convert model instance to plain object * Useful for serialization or sending to APIs * * @returns {Object} Plain object representation */ toObject() { const that = this; const obj = {}; for (const key in that) { if (that.hasOwnProperty(key) && typeof that[key] !== 'function') { obj[key] = that[key]; } } return obj; } /** * Convert model instance to JSON string * * @returns {string} JSON representation */ toJSON() { const that = this; return JSON.stringify(that.toObject()); } /** * Recursively instantiate ORM models in response data * * Looks for objects with __MODEL property and instantiates the appropriate * JavaScript model class if it exists in the global scope. * * @param {*} data - The data to process (can be any type) * @returns {*} The data with ORM objects instantiated */ static _instantiate_models_recursive(data) { // __MODEL SYSTEM: Enables automatic ORM instantiation when fetching from PHP models. // PHP models add "__MODEL": "ClassName" to JSON, JavaScript uses it to create proper instances. // This provides typed model objects instead of plain JSON, with methods and type checking. // This recursive processor scans all API response data looking for __MODEL markers. // When found, it attempts to instantiate the appropriate JavaScript model class, // converting {__MODEL: "User_Model", id: 1, name: "John"} into new User_Model({...}). // Works recursively through arrays and nested objects to handle complex data structures. // Handle null/undefined if (data === null || data === undefined) { return data; } // Handle arrays - recursively process each element if (Array.isArray(data)) { return data.map(item => Rsx_Js_Model._instantiate_models_recursive(item)); } // Handle objects if (typeof data === 'object') { // Check if this object has a __MODEL property if (data.__MODEL && typeof data.__MODEL === 'string') { // Try to find the model class in the global scope const ModelClass = window[data.__MODEL]; // If the model class exists and extends Rsx_Js_Model, instantiate it // Dynamic model resolution requires checking class existence - @JS-DEFENSIVE-01-EXCEPTION if (ModelClass && ModelClass.prototype instanceof Rsx_Js_Model) { return new ModelClass(data); } } // Recursively process all object properties const result = {}; for (const key in data) { if (data.hasOwnProperty(key)) { result[key] = Rsx_Js_Model._instantiate_models_recursive(data[key]); } } return result; } // Return primitive values as-is return data; } } /* === app/RSpade/Core/Js/Rsx_View_Transitions.js (babel) === */ "use strict"; /** * View_Transitions - Smooth page-to-page transitions using View Transitions API * * Enables cross-document view transitions so the browser doesn't paint the new page * until it's ready, creating smooth animations between pages. * * Falls back gracefully if View Transitions API is not available. */ class Rsx_View_Transitions { /** * Called during framework core init phase * Checks for View Transitions API support and enables if available */ static _on_framework_core_init() { // Check if View Transitions API is supported if (!document.startViewTransition) { console_debug('VIEW_TRANSITIONS', 'View Transitions API not supported, skipping'); return; } // Enable cross-document view transitions via CSS Rsx_View_Transitions._inject_transition_css(); } /** * Inject CSS to enable cross-document view transitions * * The @view-transition { navigation: auto; } rule tells the browser to: * 1. Capture a snapshot of the current page before navigation * 2. Fetch the new page * 3. Wait until the new page is fully loaded and painted (document.ready) * 4. Animate smoothly between the two states * * This prevents the white flash during navigation and creates app-like transitions. */ static _inject_transition_css() { const style = document.createElement('style'); style.textContent = ` @view-transition { navigation: auto; } /* Disable animation - instant transition */ ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation-duration: 0s; } `; document.head.appendChild(style); } } /* === app/RSpade/Core/Js/ReadWriteLock.js (babel) === */ "use strict"; var _50ae609e_ReadWriteLock; function _50ae609e_assertClassBrand(e, t, n) { if ("function" == typeof e ? e === t : e.has(t)) return arguments.length < 3 ? t : n; throw new TypeError("Private element is not present on this object"); } /** * ReadWriteLock implementation for RSpade framework * Provides exclusive (write) and shared (read) locking mechanisms for asynchronous operations */ class ReadWriteLock { /** * Acquire an exclusive mutex lock by name. * Only one writer runs at a time; blocks readers until finished. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ static acquire(name, cb) { return new Promise((resolve, reject) => { const s = _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_get_lock).call(this, name); s.writer_q.push({ cb, resolve, reject }); _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); } /** * Acquire a shared read lock by name. * Multiple readers can run in parallel; blocks when writer is active. * @param {string} name * @param {() => any|Promise} cb * @returns {Promise} */ static acquire_read(name, cb) { return new Promise((resolve, reject) => { const s = _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_get_lock).call(this, name); if (s.writer_active || s.writer_q.length > 0) { s.reader_q.push({ cb, resolve, reject }); return _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_schedule).call(this, name); } s.readers += 1; Promise.resolve().then(cb).then(resolve, reject).finally(() => { s.readers -= 1; if (s.readers === 0) _50ae609e_assertClassBrand(ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); }); } /** * Force-unlock a mutex (use with caution). * Completely removes the lock state, potentially breaking waiting operations. * @param {string} name */ static force_unlock(name) { _50ae609e_assertClassBrand(ReadWriteLock, this, _locks)._.delete(name); } /** * Get information about pending operations on a mutex. * @param {string} name * @returns {{readers: number, writer_active: boolean, reader_q: number, writer_q: number}} */ static pending(name) { const s = _50ae609e_assertClassBrand(ReadWriteLock, this, _locks)._.get(name); if (!s) return { readers: 0, writer_active: false, reader_q: 0, writer_q: 0 }; return { readers: s.readers, writer_active: s.writer_active, reader_q: s.reader_q.length, writer_q: s.writer_q.length }; } } _50ae609e_ReadWriteLock = ReadWriteLock; /** * Get or create a lock object for a given name * @private */ function _50ae609e_get_lock(name) { let s = _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _locks)._.get(name); if (!s) { s = { readers: 0, writer_active: false, reader_q: [], writer_q: [] }; _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _locks)._.set(name, s); } return s; } /** * Schedule the next operation for a lock * @private */ function _50ae609e_schedule(name) { const s = _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _50ae609e_get_lock).call(this, name); if (s.writer_active || s.readers > 0) return; // run one writer if queued if (s.writer_q.length > 0) { const { cb, resolve, reject } = s.writer_q.shift(); s.writer_active = true; Promise.resolve().then(cb).then(resolve, reject).finally(() => { s.writer_active = false; _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); return; } // otherwise run all queued readers in parallel if (s.reader_q.length > 0) { const batch = s.reader_q.splice(0); s.readers += batch.length; for (const { cb, resolve, reject } of batch) { Promise.resolve().then(cb).then(resolve, reject).finally(() => { s.readers -= 1; if (s.readers === 0) _50ae609e_assertClassBrand(_50ae609e_ReadWriteLock, this, _50ae609e_schedule).call(this, name); }); } } } var _locks = { _: new Map() }; /* === app/RSpade/Core/Js/Form_Utils.js (babel) === */ "use strict"; /** * Form utilities for validation and error handling */ class Form_Utils { /** * Framework initialization hook to register jQuery plugin * Creates $.fn.ajax_submit() for form elements * @private */ static _on_framework_core_define() { let params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; $.fn.ajax_submit = function () { let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; const $element = $(this); if (!$element.is('form')) { throw new Error('ajax_submit() can only be called on form elements'); } const url = $element.attr('action'); if (!url) { throw new Error('Form must have an action attribute'); } const { controller, action } = Ajax.ajax_url_to_controller_action(url); return Form_Utils.ajax_submit($element, controller, action, options); }; } /** * Shows form validation errors * * REQUIRED HTML STRUCTURE: * For inline field errors to display properly, form fields must follow this structure: * *
* * *
* * Key requirements: * - Wrap each field in a container with class "form-group" (or "form-check" / "input-group") * - Input must have a "name" attribute matching the error key * - Use "form-control" class on inputs for Bootstrap 5 styling * * Accepts three formats: * - String: Single error shown as alert * - Array of strings: Multiple errors shown as bulleted alert * - Object: Field names mapped to errors, shown inline (unmatched shown as alert) * * @param {string} parent_selector - jQuery selector for parent element * @param {string|Object|Array} errors - Error messages to display * @returns {Promise} Promise that resolves when all animations complete */ static apply_form_errors(parent_selector, errors) { console.error(errors); const $parent = $(parent_selector); // Reset the form errors before applying new ones Form_Utils.reset_form_errors(parent_selector); // Normalize input to standard format const normalized = Form_Utils._normalize_errors(errors); return new Promise(resolve => { let animations = []; if (normalized.type === 'string') { // Single error message animations = Form_Utils._apply_general_errors($parent, normalized.data); } else if (normalized.type === 'array') { // Array of error messages const deduplicated = Form_Utils._deduplicate_errors(normalized.data); animations = Form_Utils._apply_general_errors($parent, deduplicated); } else if (normalized.type === 'fields') { // Field-specific errors const result = Form_Utils._apply_field_errors($parent, normalized.data); animations = result.animations; // Count matched fields const matched_count = Object.keys(normalized.data).length - Object.keys(result.unmatched).length; const unmatched_deduplicated = Form_Utils._deduplicate_errors(result.unmatched); const unmatched_count = Object.keys(unmatched_deduplicated).length; // Show summary alert if there are any field errors (matched or unmatched) if (matched_count > 0 || unmatched_count > 0) { // Build summary message let summary_msg = ''; if (matched_count > 0) { summary_msg = matched_count === 1 ? 'Please correct the error highlighted below.' : 'Please correct the errors highlighted below.'; } // If there are unmatched errors, add them as a bulleted list if (unmatched_count > 0) { const summary_animations = Form_Utils._apply_combined_error($parent, summary_msg, unmatched_deduplicated); animations.push(...summary_animations); } else { // Just the summary message, no unmatched errors const summary_animations = Form_Utils._apply_general_errors($parent, summary_msg); animations.push(...summary_animations); } } } // Resolve the promise once all animations are complete Promise.all(animations).then(() => { // Scroll to error container if it exists const $error_container = $parent.find('[data-id="error_container"]').first(); if ($error_container.length > 0) { const container_top = $error_container.offset().top; // Calculate fixed header offset const fixed_header_height = Form_Utils._get_fixed_header_height(); // Scroll to position error container 20px below any fixed headers const target_scroll = container_top - fixed_header_height - 20; $('html, body').animate({ scrollTop: target_scroll }, 500); } resolve(); }); }); } /** * Clears form validation errors and resets all form values to defaults * @param {string|jQuery} form_selector - jQuery selector or jQuery object for form element */ static reset(form_selector) { const $form = typeof form_selector === 'string' ? $(form_selector) : form_selector; Form_Utils.reset_form_errors(form_selector); $form.trigger('reset'); } /** * Serializes form data into key-value object * Returns all input elements with name attributes as object properties * @param {string|jQuery} form_selector - jQuery selector or jQuery object for form element * @returns {Object} Form data as key-value pairs */ static serialize(form_selector) { const $form = typeof form_selector === 'string' ? $(form_selector) : form_selector; const data = {}; $form.serializeArray().forEach(item => { data[item.name] = item.value; }); return data; } /** * Submits form to RSX controller action via AJAX * @param {string|jQuery} form_selector - jQuery selector or jQuery object for form element * @param {string} controller - Controller class name (e.g., 'User_Controller') * @param {string} action - Action method name (e.g., 'save_profile') * @param {Object} options - Optional configuration {on_success: fn, on_error: fn} * @returns {Promise} Promise that resolves with response data */ static async ajax_submit(form_selector, controller, action) { let options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; const $form = typeof form_selector === 'string' ? $(form_selector) : form_selector; const form_data = Form_Utils.serialize($form); Form_Utils.reset_form_errors(form_selector); try { const response = await Ajax.call(controller, action, form_data); if (options.on_success) { options.on_success(response); } return response; } catch (error) { if (error.type === 'form_error' && error.details) { await Form_Utils.apply_form_errors(form_selector, error.details); } else { await Form_Utils.apply_form_errors(form_selector, error.message || 'An error occurred'); } if (options.on_error) { options.on_error(error); } throw error; } } /** * Removes form validation errors * @param {string} parent_selector - jQuery selector for parent element */ static reset_form_errors(parent_selector) { const $parent = $(parent_selector); // Remove flash messages $('.flash-messages').remove(); // Remove alert-danger messages $parent.find('.alert-danger').remove(); // Remove validation error classes and text from form elements $parent.find('.is-invalid').removeClass('is-invalid'); $parent.find('.invalid-feedback').remove(); } // ------------------------ /** * Normalizes error input into standard formats * @param {string|Object|Array} errors - Raw error input * @returns {Object} Normalized errors as {type: 'string'|'array'|'fields', data: ...} * @private */ static _normalize_errors(errors) { // Handle null/undefined if (!errors) { return { type: 'string', data: 'An error has occurred' }; } // Handle string if (typeof errors === 'string') { return { type: 'string', data: errors }; } // Handle array if (Array.isArray(errors)) { // Array of strings - general errors if (errors.every(e => typeof e === 'string')) { return { type: 'array', data: errors }; } // Array with object as first element - extract it if (errors.length > 0 && typeof errors[0] === 'object') { return Form_Utils._normalize_errors(errors[0]); } // Empty or mixed array return { type: 'array', data: [] }; } // Handle object - check for Laravel response wrapper if (typeof errors === 'object') { // Unwrap {errors: {...}} or {error: {...}} const unwrapped = errors.errors || errors.error; if (unwrapped) { return Form_Utils._normalize_errors(unwrapped); } // Convert Laravel validator format {field: [msg1, msg2]} to {field: msg1} const normalized = {}; for (const field in errors) { if (errors.hasOwnProperty(field)) { const value = errors[field]; if (Array.isArray(value) && value.length > 0) { normalized[field] = value[0]; } else if (typeof value === 'string') { normalized[field] = value; } else { normalized[field] = String(value); } } } return { type: 'fields', data: normalized }; } // Final catch-all* return { type: 'string', data: String(errors) }; } /** * Removes duplicate error messages from array or object values * @param {Array|Object} errors - Errors to deduplicate * @returns {Array|Object} Deduplicated errors * @private */ static _deduplicate_errors(errors) { if (Array.isArray(errors)) { return [...new Set(errors)]; } if (typeof errors === 'object') { const seen = new Set(); const result = {}; for (const key in errors) { const value = errors[key]; if (!seen.has(value)) { seen.add(value); result[key] = value; } } return result; } return errors; } /** * Applies field-specific validation errors to form inputs * @param {jQuery} $parent - Parent element containing form * @param {Object} field_errors - Object mapping field names to error messages * @returns {Object} Object containing {animations: Array, unmatched: Object} * @private */ static _apply_field_errors($parent, field_errors) { const animations = []; const unmatched = {}; for (const field_name in field_errors) { const error_message = field_errors[field_name]; const $input = $parent.find(`[name="${field_name}"]`); if (!$input.length) { unmatched[field_name] = error_message; continue; } const $error = $('
').html(error_message); const $target = $input.closest('.form-group, .form-check, .input-group'); if (!$target.length) { unmatched[field_name] = error_message; continue; } $input.addClass('is-invalid'); $error.appendTo($target); animations.push($error.hide().fadeIn(300).promise()); } return { animations, unmatched }; } /** * Applies combined error message with summary and unmatched field errors * @param {jQuery} $parent - Parent element containing form * @param {string} summary_msg - Summary message (e.g., "Please correct the errors below") * @param {Object} unmatched_errors - Object of field errors that couldn't be matched to fields * @returns {Array} Array of animation promises * @private */ static _apply_combined_error($parent, summary_msg, unmatched_errors) { const animations = []; const $error_container = $parent.find('[data-id="error_container"]').first(); const $target = $error_container.length > 0 ? $error_container : $parent; // Create alert with summary message and bulleted list of unmatched errors const $alert = $(''); // Add summary message if provided if (summary_msg) { $('

').text(summary_msg).appendTo($alert); } // Add unmatched errors as bulleted list if (Object.keys(unmatched_errors).length > 0) { const $list = $('
    '); for (const field_name in unmatched_errors) { const error_msg = unmatched_errors[field_name]; $('
  • ').html(error_msg).appendTo($list); } $list.appendTo($alert); } if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } return animations; } /** * Applies general error messages as alert box * @param {jQuery} $parent - Parent element to prepend alert to * @param {string|Array} messages - Error message(s) to display * @returns {Array} Array of animation promises * @private */ static _apply_general_errors($parent, messages) { const animations = []; // Look for a specific error container div (e.g., in Rsx_Form component) const $error_container = $parent.find('[data-id="error_container"]').first(); const $target = $error_container.length > 0 ? $error_container : $parent; if (typeof messages === 'string') { // Single error - simple alert without list const $alert = $('').text(messages); if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } } else if (Array.isArray(messages) && messages.length > 0) { // Multiple errors - bulleted list const $alert = $(''); const $list = $alert.find('ul'); messages.forEach(msg => { const text = (msg + '').trim() || 'An error has occurred'; $('
  • ').html(text).appendTo($list); }); if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } } else if (typeof messages === 'object' && !Array.isArray(messages)) { // Object of unmatched field errors - convert to array const error_list = Object.values(messages).map(v => String(v).trim()).filter(v => v); if (error_list.length > 0) { return Form_Utils._apply_general_errors($parent, error_list); } } return animations; } /** * Calculates the total height of fixed/sticky headers at the top of the page * @returns {number} Total height in pixels of fixed top elements * @private */ static _get_fixed_header_height() { let total_height = 0; // Find all fixed or sticky positioned elements $('*').each(function () { const $el = $(this); const position = $el.css('position'); // Only check fixed or sticky elements if (position !== 'fixed' && position !== 'sticky') { return; } // Check if element is positioned at or near the top const top = parseInt($el.css('top')) || 0; if (top > 50) { return; // Not a top header } // Check if element is visible if (!$el.is(':visible')) { return; } // Check if element spans significant width (likely a header/navbar) const width = $el.outerWidth(); const viewport_width = $(window).width(); if (width < viewport_width * 0.5) { return; // Too narrow to be a header } // Add this element's height total_height += $el.outerHeight(); }); return total_height; } } /* === app/RSpade/Core/Js/Debugger.js (babel) === */ "use strict"; function _27e0e986_defineProperty(e, r, t) { return (r = _27e0e986_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _27e0e986_toPropertyKey(t) { var i = _27e0e986_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _27e0e986_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); } /** * Debugger class for console_debug and browser error logging * Handles batched submission to server when configured */ class Debugger { /** * Initialize framework error handling * Called during framework initialization */ static _on_framework_core_init() { // Check if browser error logging is enabled if (window.rsxapp && window.rsxapp.log_browser_errors) { // Register global error handler window.addEventListener('error', function (event) { Debugger._handle_browser_error({ message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, stack: event.error ? event.error.stack : null, type: 'error' }); }); // Register unhandled promise rejection handler window.addEventListener('unhandledrejection', function (event) { Debugger._handle_browser_error({ message: event.reason ? event.reason.message || String(event.reason) : 'Unhandled promise rejection', stack: event.reason && event.reason.stack ? event.reason.stack : null, type: 'unhandledrejection' }); }); } // Register ui refresh handler Rsx.on('refresh', Debugger.on_refresh); } // In dev mode, some ui elements can be automatically applied to assist with development static on_refresh() { if (!Rsx.is_prod()) { // Add an underline 2 px blue to all a tags with href === "#" using jquery // Todo: maybe this should be a configurable debug option? // $('a[href="#"]').css({ // 'border-bottom': '2px solid blue', // 'text-decoration': 'none' // }); } } /** * JavaScript implementation of console_debug * Mirrors PHP functionality with batching for Laravel log */ static console_debug(channel) { // Check if console_debug is enabled if (!window.rsxapp || !window.rsxapp.console_debug || !window.rsxapp.console_debug.enabled) { return; } const config = window.rsxapp.console_debug; // Normalize channel name channel = String(channel).toUpperCase().replace(/[\[\]]/g, ''); // Apply filtering if (config.filter_mode === 'specific') { const specific = config.specific_channel; if (specific) { // Split comma-separated values and normalize const channels = specific.split(',').map(c => c.trim().toUpperCase()); if (!channels.includes(channel)) { return; } } } else if (config.filter_mode === 'whitelist') { const whitelist = (config.filter_channels || []).map(c => c.toUpperCase()); if (!whitelist.includes(channel)) { return; } } else if (config.filter_mode === 'blacklist') { const blacklist = (config.filter_channels || []).map(c => c.toUpperCase()); if (blacklist.includes(channel)) { return; } } // Prepare the message for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { values[_key - 1] = arguments[_key]; } let message = { channel: channel, values: values, timestamp: new Date().toISOString() }; // Add location if configured if (config.include_location || config.include_backtrace) { const error = new Error(); const stack = error.stack || ''; const stackLines = stack.split('\n'); if (config.include_location && stackLines.length > 2) { // Skip Error line and this function const callerLine = stackLines[2] || ''; const match = callerLine.match(/at\s+.*?\s+\((.*?):(\d+):(\d+)\)/) || callerLine.match(/at\s+(.*?):(\d+):(\d+)/); if (match) { message.location = `${match[1]}:${match[2]}`; } } if (config.include_backtrace) { // Include first 5 stack frames, skipping this function message.backtrace = stackLines.slice(2, 7).map(line => line.trim()).filter(line => line); } } // Output to browser console if enabled if (config.outputs && config.outputs.browser) { const prefix = config.include_benchmark ? `[${Debugger._get_time_prefix()}] ` : ''; const channelPrefix = `[${channel}]`; // Use appropriate console method based on channel let consoleMethod = 'log'; if (channel.includes('ERROR')) consoleMethod = 'error';else if (channel.includes('WARN')) consoleMethod = 'warn';else if (channel.includes('INFO')) consoleMethod = 'info'; console[consoleMethod](prefix + channelPrefix, ...values); } // Batch for Laravel log if enabled if (config.outputs && config.outputs.laravel_log) { Debugger._batch_console_message(message); } } /** * Log an error to the server * Used manually or by Ajax error handling */ static log_error(error) { // Check if browser error logging is enabled if (!window.rsxapp || !window.rsxapp.log_browser_errors) { return; } // Normalize error format let errorData = {}; if (typeof error === 'string') { errorData.message = error; errorData.type = 'manual'; } else if (error instanceof Error) { errorData.message = error.message; errorData.stack = error.stack; errorData.type = 'exception'; } else if (error && typeof error === 'object') { errorData = error; if (!errorData.type) { errorData.type = 'manual'; } } Debugger._handle_browser_error(errorData); } /** * Internal: Handle browser errors with batching */ static _handle_browser_error(errorData) { // Check limits if (Debugger._error_count >= Debugger.MAX_ERRORS_PER_PAGE) { return; } if (Debugger._error_batch_count >= Debugger.MAX_ERROR_BATCHES) { return; } Debugger._error_count++; // Add metadata errorData.url = window.location.href; errorData.userAgent = navigator.userAgent; errorData.timestamp = new Date().toISOString(); // Add to batch Debugger._error_batch.push(errorData); // Clear existing timer if (Debugger._error_timer) { clearTimeout(Debugger._error_timer); } // Set debounce timer Debugger._error_timer = setTimeout(() => { Debugger._flush_error_batch(); }, Debugger.DEBOUNCE_MS); } /** * Internal: Batch console_debug messages for Laravel log */ static _batch_console_message(message) { Debugger._console_batch.push(message); // Clear existing timer if (Debugger._console_timer) { clearTimeout(Debugger._console_timer); } // Set debounce timer Debugger._console_timer = setTimeout(() => { Debugger._flush_console_batch(); }, Debugger.DEBOUNCE_MS); } /** * Internal: Flush console_debug batch to server */ static async _flush_console_batch() { if (Debugger._console_batch.length === 0) { return; } const messages = Debugger._console_batch; Debugger._console_batch = []; Debugger._console_timer = null; try { return Ajax.call(Rsx.Route('Debugger_Controller', 'log_console_messages'), { messages: messages }); } catch (error) { // Silently fail - don't create error loop console.error('Failed to send console_debug messages to server:', error); } } /** * Internal: Flush error batch to server */ static async _flush_error_batch() { if (Debugger._error_batch.length === 0) { return; } const errors = Debugger._error_batch; Debugger._error_batch = []; Debugger._error_timer = null; Debugger._error_batch_count++; try { return Ajax.call(Rsx.Route('Debugger_Controller', 'log_browser_errors'), { errors: errors }); } catch (error) { // Silently fail - don't create error loop console.error('Failed to send browser errors to server:', error); } } /** * Internal: Get time prefix for benchmarking */ static _get_time_prefix() { const now = Date.now(); if (!Debugger._start_time) { Debugger._start_time = now; } const elapsed = now - Debugger._start_time; return (elapsed / 1000).toFixed(3) + 's'; } } // Batching state for console_debug messages _27e0e986_defineProperty(Debugger, "_console_batch", []); _27e0e986_defineProperty(Debugger, "_console_timer", null); _27e0e986_defineProperty(Debugger, "_console_batch_count", 0); // Batching state for error messages _27e0e986_defineProperty(Debugger, "_error_batch", []); _27e0e986_defineProperty(Debugger, "_error_timer", null); _27e0e986_defineProperty(Debugger, "_error_count", 0); _27e0e986_defineProperty(Debugger, "_error_batch_count", 0); // Constants _27e0e986_defineProperty(Debugger, "DEBOUNCE_MS", 2000); _27e0e986_defineProperty(Debugger, "MAX_ERRORS_PER_PAGE", 20); _27e0e986_defineProperty(Debugger, "MAX_ERROR_BATCHES", 5); // Store start time for benchmarking _27e0e986_defineProperty(Debugger, "_start_time", null); /* === app/RSpade/Core/Js/Rsx_Jq_Helpers.js (babel) === */ "use strict"; // @JS-THIS-01-EXCEPTION /** * jQuery helper extensions for the RSX framework * These extensions add utility methods to jQuery's prototype * Note: 'this' references in jQuery extensions refer to jQuery objects by design */ class Rsx_Jq_Helpers { /** * Initialize jQuery extensions when the framework core is defined * This method is called during framework initialization */ static _on_framework_core_define() { // Returns true if jquery selector matched an element $.fn.exists = function () { return this.length > 0; }; // Returns true if jquery element is visible $.fn.is_visible = function () { return this.is(':visible'); }; // Scrolls to the target element, only scrolls up. Todo: Create a version // of this that also scrolls only down, or both $.fn.scroll_up_to = function () { let speed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; if (!this.exists()) { // console.warn("Could not find target element to scroll to"); return; } if (!this.is_in_dom()) { // console.warn("Target element for scroll is not on dom"); return; } let e_top = Math.round(this.offset().top); let s_top = $('body').scrollTop(); if (e_top < 0) { let target = s_top + e_top; $('html, body').animate({ scrollTop: target }, speed); } }; // $().is(":focus") - check if element has focus $.expr[':'].focus = function (elem) { return elem === document.activeElement && (elem.type || elem.href); }; // Save native click behavior before override $.fn._click_native = $.fn.click; // Override .click() to call preventDefault by default // This prevents accidental page navigation/form submission - the correct behavior 95% of the time $.fn.click = function (handler) { // If no handler provided, trigger click event (jQuery .click() with no args) if (typeof handler === 'undefined') { return this._click_native(); } // Attach click handler with automatic preventDefault return this.on('click', function (e) { // Save original preventDefault const original_preventDefault = e.preventDefault.bind(e); // Override preventDefault to show warning when called explicitly e.preventDefault = function () { console.warn('event.preventDefault() is called automatically by RSpade .click() handlers and can be removed.'); return original_preventDefault(); }; // Call preventDefault before handler original_preventDefault(); return handler.call(this, e); }); }; // Escape hatch: click handler without preventDefault for the 5% case $.fn.click_allow_default = function (handler) { if (typeof handler === 'undefined') { return this._click_native(); } return this._click_native(handler); }; // Returns true if the jquery element exists in and is attached to the DOM $.fn.is_in_dom = function () { let $element = this; let _ancestor = function (HTMLobj) { while (HTMLobj.parentElement) { HTMLobj = HTMLobj.parentElement; } return HTMLobj; }; return _ancestor($element[0]) === document.documentElement; }; // Returns true if the element is visible in the viewport $.fn.is_in_viewport = function () { let scrolltop = $(window).scrollTop() > 0 ? $(window).scrollTop() : $('body').scrollTop(); let $element = this; const top_of_element = $element.offset().top; const bottom_of_element = $element.offset().top + $element.outerHeight(); const bottom_of_screen = scrolltop + $(window).innerHeight(); const top_of_screen = scrolltop; if (bottom_of_screen > top_of_element && top_of_screen < bottom_of_element) { return true; } else { return false; } }; // Gets the tagname of a jquery element $.fn.tagname = function () { return this.prop('tagName').toLowerCase(); }; // Returns true if a href is not same domain $.fn.is_external = function () { const host = window.location.host; const link = $('', { href: this.attr('href') })[0].hostname; return link !== host; }; // HTML5 form validation wrappers $.fn.checkValidity = function () { if (this.length === 0) return false; return this[0].checkValidity(); }; $.fn.reportValidity = function () { if (this.length === 0) return false; return this[0].reportValidity(); }; $.fn.requestSubmit = function () { if (this.length === 0) return this; this[0].requestSubmit(); return this; }; // Find related components by searching up the ancestor tree // Like .closest() but searches within ancestors instead of matching them $.fn.closest_sibling = function (selector) { let $current = this; let $parent = $current.parent(); // Keep going up the tree until we hit body while ($parent.length > 0 && !$parent.is('body')) { // Search within this parent for the selector let $found = $parent.find(selector); if ($found.length > 0) { return $found; } // Move up one level $parent = $parent.parent(); } // If we reached body, search within body as well if ($parent.is('body')) { let $found = $parent.find(selector); if ($found.length > 0) { return $found; } } // Return empty jQuery object if nothing found return $(); }; // Override $.ajax to prevent direct AJAX calls to local server // Developers must use the Ajax endpoint pattern: await Controller.method(params) const native_ajax = $.ajax; $.ajax = function (url, options) { // Handle both $.ajax(url, options) and $.ajax(options) signatures let settings; if (typeof url === 'string') { settings = options || {}; settings.url = url; } else { settings = url || {}; } // Check if this is a local request (relative URL or same domain) const request_url = settings.url || ''; const is_relative = !request_url.match(/^https?:\/\//); const is_same_domain = request_url.startsWith(window.location.origin); const is_local_request = is_relative || is_same_domain; // Allow framework Ajax.call() to function if (settings.__local_integration === true) { return native_ajax.call(this, settings); } // Allow file upload endpoint - requires native $.ajax for FormData support const is_file_upload = request_url === '/_upload' || request_url.endsWith('/_upload'); if (is_file_upload) { return native_ajax.call(this, settings); } // Block local AJAX requests that don't use the Ajax endpoint pattern if (is_local_request) { // Try to parse controller and action from URL let controller_name = null; let action_name = null; const url_match = request_url.match(/\/_rsx_api\/([^\/]+)\/([^\/\?]+)/); if (url_match) { controller_name = url_match[1]; action_name = url_match[2]; } let error_message = 'AJAX requests to localhost via $.ajax() are prohibited.\n\n'; if (controller_name && action_name) { error_message += `Instead of:\n`; error_message += ` $.ajax({url: '${request_url}', ...})\n\n`; error_message += `Use:\n`; error_message += ` await ${controller_name}.${action_name}(parameters)\n\n`; } else { error_message += `Use the Ajax endpoint pattern:\n`; error_message += ` await Controller_Name.action_name(parameters)\n\n`; } error_message += `The controller method must have the #[Ajax_Endpoint] attribute.`; shouldnt_happen(error_message); } // Allow external requests (different domain) return native_ajax.call(this, settings); }; } } /* === app/RSpade/Core/Js/Rsx.js (babel) === */ "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 = ` `; } 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 = ` `; } } else if (error.type === 'auth_required' || error.type === 'unauthorized') { // Authentication/authorization errors const message = error.message || 'Authentication required'; html = ` `; } else if (error.type === 'network') { // Network errors const message = error.message || 'Unable to reach server. Please check your connection.'; html = ` `; } else { // Generic/unknown error const message = error.message || error.toString() || 'An unknown error occurred'; html = ` `; } $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", {}); /* === app/RSpade/Core/Js/Ajax.js (babel) === */ "use strict"; // @FILE-SUBCLASS-01-EXCEPTION /** * Client-side Ajax class for making API calls to RSX controllers * * Automatically batches multiple calls into single HTTP requests to reduce network overhead. * Batches up to 20 calls or flushes after setTimeout(0) debounce. */ class Ajax { /** * Initialize Ajax system * Called automatically when class is loaded */ static _on_framework_core_init() { // Queue of pending calls waiting to be batched Ajax._pending_calls = {}; // Timer for batching flush Ajax._flush_timeout = null; // Call counter for generating unique call IDs Ajax._call_counter = 0; // Maximum batch size before forcing immediate flush Ajax.MAX_BATCH_SIZE = 20; // Debounce time in milliseconds Ajax.DEBOUNCE_MS = 0; // Track promises from Ajax calls to detect uncaught rejections Ajax._tracked_promises = new WeakSet(); // Set up global unhandled rejection handler for Ajax errors window.addEventListener('unhandledrejection', async event => { // Only handle rejections from Ajax promises if (Ajax._tracked_promises.has(event.promise)) { event.preventDefault(); // Prevent browser's default "Uncaught (in promise)" error const error = event.reason; console.error('Uncaught Ajax error:', error); // Show Modal.error() for uncaught Ajax errors if (typeof Modal !== 'undefined' && Modal.error) { await Modal.error(error, 'Uncaught Ajax Error'); } } }); } /** * Make an AJAX call to an RSX controller action * * All calls are automatically batched unless window.rsxapp.ajax_disable_batching is true. * * @param {string|object|function} url - The Ajax URL (e.g., '/_ajax/Controller_Name/action_name') or an object/function with a .path property * @param {object} params - Parameters to send to the action * @returns {Promise} - Resolves with the return value, rejects with error */ static async call(url) { let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // If url is an object or function with a .path property, use that as the URL if (url && typeof url === 'object' && url.path) { url = url.path; } else if (url && typeof url === 'function' && url.path) { url = url.path; } // Validate url is a non-empty string if (typeof url !== 'string' || url.length === 0) { throw new Error('Ajax.call() requires a non-empty string URL or an object/function with a .path property'); } // Extract controller and action from URL const { controller, action } = Ajax.ajax_url_to_controller_action(url); console.log('Ajax:', controller, action, params); // Check if batching is disabled for debugging let promise; if (window.rsxapp && window.rsxapp.ajax_disable_batching) { promise = Ajax._call_direct(controller, action, params); } else { promise = Ajax._call_batch(controller, action, params); } // Track this promise for unhandled rejection detection Ajax._tracked_promises.add(promise); return promise; } /** * Make a batched Ajax call * @private */ static _call_batch(controller, action) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; console.log('Ajax Batch:', controller, action, params); return new Promise((resolve, reject) => { // Generate call key for deduplication const call_key = Ajax._generate_call_key(controller, action, params); // Check if this exact call is already pending if (Ajax._pending_calls[call_key]) { const existing_call = Ajax._pending_calls[call_key]; // If call already completed (cached), return immediately if (existing_call.is_complete) { if (existing_call.is_error) { reject(existing_call.error); } else { resolve(existing_call.result); } return; } // Call is pending, add this promise to callbacks existing_call.callbacks.push({ resolve, reject }); return; } // Create new pending call const call_id = Ajax._call_counter++; const pending_call = { call_id: call_id, call_key: call_key, controller: controller, action: action, params: params, callbacks: [{ resolve, reject }], is_complete: false, is_error: false, result: null, error: null }; // Add to pending queue Ajax._pending_calls[call_key] = pending_call; // Count pending calls const pending_count = Object.keys(Ajax._pending_calls).filter(key => !Ajax._pending_calls[key].is_complete).length; // If we've hit the batch size limit, flush immediately if (pending_count >= Ajax.MAX_BATCH_SIZE) { clearTimeout(Ajax._flush_timeout); Ajax._flush_timeout = null; Ajax._flush_pending_calls(); } else { // Schedule batch flush with debounce clearTimeout(Ajax._flush_timeout); Ajax._flush_timeout = setTimeout(() => { Ajax._flush_pending_calls(); }, Ajax.DEBOUNCE_MS); } }); } /** * Make a direct (non-batched) Ajax call * @private */ static async _call_direct(controller, action) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; // Construct URL from controller and action const url = `/_ajax/${controller}/${action}`; // Log the AJAX call using console_debug if (typeof Debugger !== 'undefined' && Debugger.console_debug) { Debugger.console_debug('AJAX', `Calling ${controller}.${action} (unbatched)`, params); } return new Promise((resolve, reject) => { $.ajax({ url: url, method: 'POST', data: params, dataType: 'json', __local_integration: true, // Bypass $.ajax override success: response => { // Handle console_debug messages if (response.console_debug && Array.isArray(response.console_debug)) { response.console_debug.forEach(msg => { if (!Array.isArray(msg) || msg.length !== 2) { throw new Error('Invalid console_debug message format - expected [channel, [arguments]]'); } const [channel, args] = msg; console.log(channel, ...args); }); } // Check if the response was successful if (response._success === true) { // @JS-AJAX-02-EXCEPTION - Unwrap server responses with _ajax_return_value const processed_value = Rsx_Js_Model._instantiate_models_recursive(response._ajax_return_value); resolve(processed_value); } else { // Handle error responses const error_type = response.error_type || 'unknown_error'; const reason = response.reason || 'Unknown error occurred'; const details = response.details || {}; // Handle specific error types switch (error_type) { case 'fatal': // Fatal PHP error with full error details const fatal_error_data = response.error || {}; const error_message = fatal_error_data.error || 'Fatal error occurred'; console.error('Ajax error response from server:', response.error); const fatal_error = new Error(error_message); fatal_error.type = 'fatal'; fatal_error.details = response.error; // Log to server if browser error logging is enabled Debugger.log_error({ message: `Ajax Fatal Error: ${error_message}`, type: 'ajax_fatal', endpoint: url, details: response.error }); reject(fatal_error); break; case 'response_auth_required': console.error('The user is no longer authenticated, this is a placeholder for future code which handles this scenario.'); const auth_error = new Error(reason); auth_error.type = 'auth_required'; auth_error.details = details; reject(auth_error); break; case 'response_unauthorized': console.error('The user is unauthorized to perform this action, this is a placeholder for future code which handles this scenario.'); const unauth_error = new Error(reason); unauth_error.type = 'unauthorized'; unauth_error.details = details; reject(unauth_error); break; case 'response_form_error': const form_error = new Error(reason); form_error.type = 'form_error'; form_error.details = details; reject(form_error); break; default: const generic_error = new Error(reason); generic_error.type = error_type; generic_error.details = details; reject(generic_error); break; } } }, error: (xhr, status, error) => { const error_message = Ajax._extract_error_message(xhr); const network_error = new Error(error_message); network_error.type = 'network_error'; network_error.status = xhr.status; network_error.statusText = status; // Log server errors (500+) to the server if browser error logging is enabled if (xhr.status >= 500) { Debugger.log_error({ message: `Ajax Server Error ${xhr.status}: ${error_message}`, type: 'ajax_server_error', endpoint: url, status: xhr.status, statusText: status }); } reject(network_error); } }); }); } /** * Flush all pending calls by sending batch request * @private */ static async _flush_pending_calls() { // Collect all pending calls const calls_to_send = []; const call_map = {}; // Map call_id to pending_call object for (const call_key in Ajax._pending_calls) { const pending_call = Ajax._pending_calls[call_key]; if (!pending_call.is_complete) { calls_to_send.push({ call_id: pending_call.call_id, controller: pending_call.controller, action: pending_call.action, params: pending_call.params }); call_map[pending_call.call_id] = pending_call; } } // Nothing to send if (calls_to_send.length === 0) { return; } // Log batch for debugging if (typeof Debugger !== 'undefined' && Debugger.console_debug) { Debugger.console_debug('AJAX_BATCH', `Sending batch of ${calls_to_send.length} calls`, calls_to_send.map(c => `${c.controller}.${c.action}`)); } try { // Send batch request const response = await $.ajax({ url: '/_ajax/_batch', method: 'POST', data: { batch_calls: JSON.stringify(calls_to_send) }, dataType: 'json', __local_integration: true // Bypass $.ajax override }); // Process batch response // Response format: { C_0: {success, _ajax_return_value}, C_1: {...}, ... } for (const response_key in response) { if (!response_key.startsWith('C_')) { continue; } const call_id = parseInt(response_key.substring(2), 10); const call_response = response[response_key]; const pending_call = call_map[call_id]; if (!pending_call) { console.error('Received response for unknown call_id:', call_id); continue; } // Handle console_debug messages if present if (call_response.console_debug && Array.isArray(call_response.console_debug)) { call_response.console_debug.forEach(msg => { if (!Array.isArray(msg) || msg.length !== 2) { throw new Error('Invalid console_debug message format - expected [channel, [arguments]]'); } const [channel, args] = msg; console.log(channel, ...args); }); } // Mark call as complete pending_call.is_complete = true; // Check if successful if (call_response._success === true) { // @JS-AJAX-02-EXCEPTION - Batch system unwraps server responses with _ajax_return_value const processed_value = Rsx_Js_Model._instantiate_models_recursive(call_response._ajax_return_value); pending_call.result = processed_value; // Resolve all callbacks pending_call.callbacks.forEach(_ref => { let { resolve } = _ref; resolve(processed_value); }); } else { // Handle error const error_type = call_response.error_type || 'unknown_error'; let error_message; let error_details; if (error_type === 'fatal' && call_response.error) { // Fatal PHP error with full error details const fatal_error_data = call_response.error; error_message = fatal_error_data.error || 'Fatal error occurred'; error_details = call_response.error; console.error('Ajax error response from server:', call_response.error); } else { // Other error types error_message = call_response.reason || 'Unknown error occurred'; error_details = call_response.details || {}; } const error = new Error(error_message); error.type = error_type; error.details = error_details; pending_call.is_error = true; pending_call.error = error; // Reject all callbacks pending_call.callbacks.forEach(_ref2 => { let { reject } = _ref2; reject(error); }); } } } catch (xhr_error) { // Network or server error - reject all pending calls const error_message = Ajax._extract_error_message(xhr_error); const error = new Error(error_message); error.type = 'network_error'; for (const call_id in call_map) { const pending_call = call_map[call_id]; pending_call.is_complete = true; pending_call.is_error = true; pending_call.error = error; pending_call.callbacks.forEach(_ref3 => { let { reject } = _ref3; reject(error); }); } console.error('Batch Ajax request failed:', error_message); } } /** * Generate a unique key for deduplicating calls * @private */ static _generate_call_key(controller, action, params) { // Create a stable string representation of the call // Sort params keys for consistent hashing const sorted_params = {}; Object.keys(params).sort().forEach(key => { sorted_params[key] = params[key]; }); return `${controller}::${action}::${JSON.stringify(sorted_params)}`; } /** * Extract error message from jQuery XHR object * @private */ static _extract_error_message(xhr) { if (xhr.responseJSON && xhr.responseJSON.message) { return xhr.responseJSON.message; } else if (xhr.responseText) { try { const response = JSON.parse(xhr.responseText); if (response.message) { return response.message; } } catch (e) { // Not JSON } } return `${xhr.status}: ${xhr.statusText || 'Unknown error'}`; } /** * Parses an AJAX URL into controller and action * Supports both /_ajax/ and /_/ URL prefixes * @param {string|object|function} url - URL in format '/_ajax/Controller_Name/action_name' or '/_/Controller_Name/action_name', or an object/function with a .path property * @returns {Object} Object with {controller: string, action: string} * @throws {Error} If URL doesn't start with /_ajax or /_ or has invalid structure */ static ajax_url_to_controller_action(url) { // If url is an object or function with a .path property, use that as the URL if (url && typeof url === 'object' && url.path) { url = url.path; } else if (url && typeof url === 'function' && url.path) { url = url.path; } // Validate url is a string if (typeof url !== 'string') { throw new Error(`URL must be a string or have a .path property, got: ${typeof url}`); } if (!url.startsWith('/_ajax') && !url.startsWith('/_/')) { throw new Error(`URL must start with /_ajax or /_, got: ${url}`); } const parts = url.split('/').filter(part => part !== ''); if (parts.length < 2) { throw new Error(`Invalid AJAX URL structure: ${url}`); } if (parts.length > 3) { throw new Error(`AJAX URL has too many segments: ${url}`); } const controller = parts[1]; const action = parts[2] || 'index'; return { controller, action }; } /** * Auto-initialize static properties when class is first loaded */ static on_core_define() { Ajax._on_framework_core_init(); } } /* === app/RSpade/Integrations/Jqhtml/Component.js (babel) === */ "use strict"; /** * Component - Base class for JQHTML components in RSX framework * * This class wraps the jqhtml.Component from the npm package and provides * the standard interface for RSX components following the Upper_Case naming convention. * * _Base_Jqhtml_Component is imported from npm via Jqhtml_Bundle. * * @Instantiatable */ class Component extends _Base_Jqhtml_Component {} // RSX manifest automatically makes classes global - no manual assignment needed /* === app/RSpade/Integrations/Jqhtml/Jqhtml_Integration.js (babel) === */ "use strict"; /** * JQHTML Integration - Automatic component registration and binding * * This module automatically: * 1. Registers component classes that extend Component * 2. Binds templates to component classes when names match * 3. Enables $(selector).component("Component_Name") syntax */ class Jqhtml_Integration { /** * Compiled Jqhtml templates self-register. The developer (the framework in this case) is still * responsible for registering es6 component classes with jqhtml. This does so at an early stage * of framework init. */ static _on_framework_modules_define() { let jqhtml_components = Manifest.get_extending('Component'); console_debug('JQHTML_INIT', 'Registering ' + jqhtml_components.length + ' Jqhtml Components'); for (let component of jqhtml_components) { jqhtml.register_component(component.class_name, component.class_object); } } /** * Framework modules init phase - Bind components and initialize DOM * This runs after templates are registered to bind component classes * @param {jQuery} [$scope] Optional scope to search within (defaults to body) * @returns {Array|undefined} Array of promises for recursive calls, undefined for top-level */ static _on_framework_modules_init($scope) { const is_top_level = !$scope; const promises = []; const components_needing_init = ($scope || $('body')).find('.Component_Init'); if (components_needing_init.length > 0) { console_debug('JQHTML_INIT', `Initializing ${components_needing_init.length} DOM components`); } components_needing_init.each(function () { const $element = $(this); // Skip if element is no longer attached to the document // (may have been removed by a parent component's .empty() call) if (!document.contains($element[0])) { return; } // Check if any parent has Component_Init class - skip nested components let parent = $element[0].parentElement; while (parent) { if (parent.classList.contains('Component_Init')) { return; // Skip this element, it's nested } parent = parent.parentElement; } const component_name = $element.attr('data-component-init-name'); // jQuery's .data() doesn't auto-parse JSON - we need to parse it manually let component_args = {}; const args_string = $element.attr('data-component-args'); // Unset component- php side initialization args, it is no longer needed as a compionent attribute // Unsetting also prevents undesired access to this code in other parts of the program, prevening an // unwanted future dependency on this paradigm $element.removeAttr('data-component-init-name'); $element.removeAttr('data-component-args'); $element.removeData('component-init-name'); $element.removeData('component-args'); if (args_string) { try { component_args = JSON.parse(args_string); } catch (e) { console.error(`[JQHTML Integration] Failed to parse component args for ${component_name}:`, e); component_args = {}; } } if (component_name) { // Transform $ prefixed keys to data- attributes let component_args_filtered = {}; for (const [key, value] of Object.entries(component_args)) { // if (key.startsWith('$')) { // component_args_filtered[key.substring(1)] = value; // } else if (key.startsWith('data-')) { component_args_filtered[key.substring(5)] = value; } else { component_args_filtered[key] = value; } } try { // Store inner HTML as string for nested component processing component_args_filtered._inner_html = $element.html(); $element.empty(); // Remove the init class before instantiation to prevent re-initialization $element.removeClass('Component_Init'); // Create promise for this component's initialization const component_promise = new Promise(resolve => { // Use jQuery component plugin to create the component // Plugin handles element internally, just pass args // Get the updated $element from let component = $element.component(component_name, component_args_filtered); component.on('render', function () { // Recursively collect promises from nested components // Getting the updated component here - if the tag name was not div, the element would have been recreated, so we need to get the element set on the component, not from our earlier selector const nested_promises = Jqhtml_Integration._on_framework_modules_init(component.$); promises.push(...nested_promises); // Resolve this component's promise resolve(); }).$; }); promises.push(component_promise); } catch (error) { console.error(`[JQHTML Integration] Failed to initialize component ${component_name}:`, error); console.error('Error details:', error.stack || error); } } }); // Top-level call: spawn async handler to wait for all promises, then trigger event if (is_top_level) { (async () => { await Promise.all(promises); await Rsx._rsx_call_all_classes('on_jqhtml_ready'); Rsx.trigger('jqhtml_ready'); })(); return; } // Recursive call: return promises for parent to collect return promises; } /** * Get all registered component names * @returns {Array} Array of component names */ static get_component_names() { return jqhtml.get_component_names(); } /** * Check if a component is registered * @param {string} name Component name * @returns {boolean} True if component is registered */ static has_component(name) { return jqhtml.has_component(name); } } // RSX manifest automatically makes classes global - no manual assignment needed /* === storage/rsx-tmp/bundle_Bootstrap5_Src_Bundle_57b2a356.js === */ // JavaScript Manifest - Generated by BundleCompiler // Registers all classes in this bundle for runtime introspection Manifest._define([ [Manifest, "Manifest", null], [Rsx_Behaviors, "Rsx_Behaviors", null], [Rsx_Cache, "Rsx_Cache", null], [Rsx_Init, "Rsx_Init", null], [Rsx_Js_Model, "Rsx_Js_Model", null], [Rsx_View_Transitions, "Rsx_View_Transitions", null], [ReadWriteLock, "ReadWriteLock", null], [Form_Utils, "Form_Utils", null], [Debugger, "Debugger", null], [Rsx_Jq_Helpers, "Rsx_Jq_Helpers", null], [Rsx, "Rsx", null], [Ajax, "Ajax", null], [Component, "Component", _Base_Jqhtml_Component], [Jqhtml_Integration, "Jqhtml_Integration", null] ]); /* === storage/rsx-tmp/bundle_Bootstrap5_Src_Bundle_e83e43d3.js === */ $(document).ready(async function() { try { console_debug('RSX_INIT', 'Document ready, starting Rsx._rsx_core_boot'); await Rsx._rsx_core_boot(); console_debug('RSX_INIT', 'Initialization complete'); } catch (error) { console.error('[RSX_INIT] Initialization failed:', error); console.error('[RSX_INIT] Stack:', error.stack); throw error; } }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0b3JhZ2UvcnN4LXRtcC9idW5kbGVfY29uZmlnX0Jvb3RzdHJhcDVfU3JjX0J1bmRsZS5qcyIsInN0b3JhZ2UvcnN4LXRtcC9ucG1faW1wb3J0X2RlY2xhcmF0aW9uc185NWE2ZjYwMmM5ODAzNzYxMWI2NDBiMGI1MzQyODMwYi5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kZWNvcmF0b3IuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvYnJvd3Nlci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kYXRldGltZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9lcnJvci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9oYXNoLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL011dGV4LmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2FzeW5jLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2Z1bmN0aW9ucy5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9NYW5pZmVzdC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfQmVoYXZpb3JzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9DYWNoZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSW5pdC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSnNfTW9kZWwuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X1ZpZXdfVHJhbnNpdGlvbnMuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUmVhZFdyaXRlTG9jay5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Gb3JtX1V0aWxzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL0RlYnVnZ2VyLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9KcV9IZWxwZXJzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9BamF4LmpzIiwiYXBwL1JTcGFkZS9JbnRlZ3JhdGlvbnMvSnFodG1sL0pxaHRtbF9Db21wb25lbnQuanMiLCJhcHAvUlNwYWRlL0ludGVncmF0aW9ucy9KcWh0bWwvSnFodG1sX0ludGVncmF0aW9uLmpzIiwic3RvcmFnZS9yc3gtdG1wL2J1bmRsZV9Cb290c3RyYXA1X1NyY19CdW5kbGVfNTdiMmEzNTYuanMiLCJzdG9yYWdlL3JzeC10bXAvYnVuZGxlX0Jvb3RzdHJhcDVfU3JjX0J1bmRsZV9lODNlNDNkMy5qcyJdLCJuYW1lcyI6WyJkZWNvcmF0b3IiLCJ2YWx1ZSIsImlzX21vYmlsZSIsInRlc3QiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCIkIiwid2luZG93Iiwid2lkdGgiLCJpc19kZXNrdG9wIiwiZ2V0X29zIiwidXNlcl9hZ2VudCIsInBsYXRmb3JtIiwibWFjb3NfcGxhdGZvcm1zIiwid2luZG93c19wbGF0Zm9ybXMiLCJpb3NfcGxhdGZvcm1zIiwib3MiLCJpc19tb2JpbGVfZGV2aWNlIiwiaW5kZXhPZiIsImlzX2NyYXdsZXIiLCJib3RfcGF0dGVybiIsInNjcm9sbF9pbnRvX3ZpZXdfaWZfbmVlZGVkIiwidGFyZ2V0IiwiJHRhcmdldCIsIiRwYXJlbnQiLCJwYXJlbnQiLCJ0YXJnZXRfdG9wIiwicG9zaXRpb24iLCJ0b3AiLCJzY3JvbGxUb3AiLCJ0YXJnZXRfaGVpZ2h0Iiwib3V0ZXJIZWlnaHQiLCJwYXJlbnRfaGVpZ2h0IiwiaGVpZ2h0Iiwic2Nyb2xsX3Bvc2l0aW9uIiwiRGVidWdnZXIiLCJjb25zb2xlX2RlYnVnIiwibmV3X3Njcm9sbF9wb3NpdGlvbiIsIk1hdGgiLCJtYXgiLCJtaW4iLCJzY3JvbGxIZWlnaHQiLCJzY3JvbGxfcGFnZV9pbnRvX3ZpZXdfaWZfbmVlZGVkIiwib2Zmc2V0Iiwid2luZG93X2hlaWdodCIsIndpbmRvd19zY3JvbGxfcG9zaXRpb24iLCJhbmltYXRlIiwid2FpdF9mb3JfaW1hZ2VzIiwiY2FsbGJhY2siLCIkaW1hZ2VzIiwidG90YWxfaW1hZ2VzIiwibGVuZ3RoIiwiaW1hZ2VzX2xvYWRlZCIsImVhY2giLCJpbWciLCJJbWFnZSIsIm9ubG9hZCIsIm9uZXJyb3IiLCJzcmMiLCIkbmJzcCIsImVzY2FwZV9qcV9zZWxlY3RvciIsImlkIiwicmVwbGFjZSIsInVuaXhfdGltZSIsInJvdW5kIiwiRGF0ZSIsImdldFRpbWUiLCJ5bWRoaXNfdG9fdW5peCIsInN0cl9kYXRlIiwiZGF0ZSIsImVycm9yIiwic3RyIiwiZXJyb3JfY29kZSIsInVuZGVmIiwic3RhdHVzIiwic2hvdWxkbnRfaGFwcGVuIiwibWVzc2FnZSIsImFyZ3VtZW50cyIsInVuZGVmaW5lZCIsIkVycm9yIiwic3RhY2siLCJzdGFja0xpbmVzIiwic3BsaXQiLCJjYWxsZXJJbmZvIiwiY2FsbGVyTGluZSIsIm1hdGNoIiwiZXJyb3JNZXNzYWdlIiwiY29uc29sZSIsInJlcGVhdCIsImZhdGFsRXJyb3IiLCJuYW1lIiwiaGFzaCIsInRoZV92YXIiLCJjYWxjX3NoYTEiLCJpZ25vcmVkX2tleXMiLCJqc29uX3N0cmluZ2lmeV9ub2NpcmMiLCJjYWNoZSIsIkpTT04iLCJzdHJpbmdpZnkiLCJrZXkiLCJ2IiwiX2NhY2hlX2tleSIsIl9oYXNoX2tleSIsInB1c2giLCJmbGF0X3ZhciIsIl9mbGF0dGVuIiwicHJlZml4IiwiZGVwdGgiLCJpc19vYmplY3QiLCJBYnN0cmFjdCIsImsiLCJoYXNPd25Qcm9wZXJ0eSIsImlzX2FycmF5IiwiaSIsImZvcmVhY2giLCJpc19mdW5jdGlvbiIsImlzX251bWVyaWMiLCJTdHJpbmciLCJzb3J0ZXIiLCJzb3J0IiwiYSIsImIiLCJqc29uIiwiaGFzaGVkIiwic2hhMSIsImRlZXBfZXF1YWwiLCJtdXRleCIsImdsb2JhbF9pZCIsImluc3RhbmNlX211dGV4ZXMiLCJfaW5zdGFuY2Vfc3RvcmFnZSIsIldlYWtNYXAiLCJnbG9iYWxfbXV0ZXhlcyIsIl9nbG9iYWxfc3RvcmFnZSIsIk1hcCIsImdldF9pbnN0YW5jZV9tdXRleCIsImluc3RhbmNlIiwibWV0aG9kX25hbWUiLCJpbnN0YW5jZV9sb2NrcyIsImdldCIsInNldCIsImxvY2tfc3RhdGUiLCJhY3RpdmUiLCJxdWV1ZSIsImdldF9nbG9iYWxfbXV0ZXgiLCJzY2hlZHVsZV9uZXh0IiwiZm4iLCJyZXNvbHZlIiwicmVqZWN0Iiwic2hpZnQiLCJQcm9taXNlIiwidGhlbiIsImZpbmFsbHkiLCJhY3F1aXJlX2xvY2siLCJkZXNjcmlwdG9yIiwib3JpZ2luYWxfbWV0aG9kIiwiX2xlbiIsImFyZ3MiLCJBcnJheSIsIl9rZXkiLCJhcHBseSIsIl9sZW4yIiwiX2tleTIiLCJzbGVlcCIsIm1pbGxpc2Vjb25kcyIsInJlcXVlc3RBbmltYXRpb25GcmFtZSIsInNldFRpbWVvdXQiLCJkZWJvdW5jZSIsImNhbGxiYWNrX29yX2RlbGF5IiwiZGVsYXkiLCJpbW1lZGlhdGUiLCJkZWNvcmF0b3JfZGVsYXkiLCJkZWNvcmF0b3JfaW1tZWRpYXRlIiwiY29udGV4dCIsImtpbmQiLCJkZWJvdW5jZV9pbXBsIiwicnVubmluZyIsInF1ZXVlZCIsImxhc3RfZW5kX3RpbWUiLCJ0aW1lciIsIm5leHRfYXJncyIsIm5leHRfY29udGV4dCIsInJlc29sdmVfcXVldWUiLCJyZWplY3RfcXVldWUiLCJydW5fZnVuY3Rpb24iLCJ0aGVzZV9yZXNvbHZlcyIsInRoZXNlX3JlamVjdHMiLCJyZXN1bHQiLCJlcnIiLCJub3ciLCJjbGVhclRpbWVvdXQiLCJmaXJzdF9jYWxsIiwic2luY2UiLCJJbmZpbml0eSIsIndhaXQiLCJyd2xvY2siLCJjYiIsIlJlYWRXcml0ZUxvY2siLCJhY3F1aXJlIiwicndsb2NrX3JlYWQiLCJhY3F1aXJlX3JlYWQiLCJyd2xvY2tfZm9yY2VfdW5sb2NrIiwiZm9yY2VfdW5sb2NrIiwicndsb2NrX3BlbmRpbmciLCJwZW5kaW5nIiwib2JqIiwicmVzdWx0cyIsImlzQXJyYXkiLCJmb3JFYWNoIiwiaW5kZXgiLCJwcm9taXNlcyIsImZpbHRlciIsImFsbCIsIm4iLCJpc05hTiIsInBhcnNlRmxvYXQiLCJpc0Zpbml0ZSIsImlzX3N0cmluZyIsInMiLCJpc19pbnRlZ2VyIiwiTnVtYmVyIiwiaXNJbnRlZ2VyIiwiaXNfcHJvbWlzZSIsImZ1bmN0aW9uX3RvX2NoZWNrIiwidG9TdHJpbmciLCJjYWxsIiwiaXNfZW1haWwiLCJlbWFpbCIsInJlZ2V4IiwiaXNzZXQiLCJlbXB0eSIsIm9iamVjdCIsImZsb2F0IiwidmFsIiwicGFyc2VkIiwiaW50IiwicGFyc2VJbnQiLCJ2YWx1ZV91bmxlc3NfbnVtZXJpY19zdHJpbmdfdGhlbl9udW1lcmljX3ZhbHVlIiwiaHRtbCIsIl8iLCJlc2NhcGUiLCJubDJiciIsImh0bWxiciIsInVybGVuY29kZSIsImVuY29kZVVSSUNvbXBvbmVudCIsInVybGRlY29kZSIsImRlY29kZVVSSUNvbXBvbmVudCIsImpzb25fZW5jb2RlIiwianNvbl9kZWNvZGUiLCJwYXJzZSIsImNoYW5uZWwiLCJ2YWx1ZXMiLCJyZXBsYWNlX2FsbCIsInN0cmluZyIsInNlYXJjaCIsImpvaW4iLCJ1Y3dvcmRzIiwiaW5wdXQiLCJtYXAiLCJ3b3JkIiwiY2hhckF0IiwidG9VcHBlckNhc2UiLCJzbGljZSIsImNvdW50IiwibyIsImMiLCJjbG9uZSIsIkZ1bmN0aW9uIiwicHJvdG90eXBlIiwiX19jbG9uZSIsInRoYXQiLCJ0ZW1wIiwiY2xvbmVkIiwiY29uc3RydWN0b3IiLCJPYmplY3QiLCJhc3NpZ24iLCJjb2FsZXNjZSIsImZyb20iLCJyZXR1cm5fdmFsIiwiYXJnIiwiY3N2X3RvX2FycmF5X3RyaW0iLCJzdHJfY3N2IiwicGFydHMiLCJyZXQiLCJwYXJ0IiwidHJpbSIsIk1hbmlmZXN0IiwiX2RlZmluZSIsIml0ZW1zIiwiX2NsYXNzZXMiLCJpdGVtIiwiY2xhc3Nfb2JqZWN0IiwiY2xhc3NfbmFtZSIsImNsYXNzX2V4dGVuZHMiLCJkZWNvcmF0b3JzIiwiY2xhc3MiLCJleHRlbmRzIiwiX25hbWUiLCJfZXh0ZW5kcyIsIl9kZWNvcmF0b3JzIiwiX2J1aWxkX3N1YmNsYXNzX2luZGV4IiwiX3N1YmNsYXNzX2luZGV4IiwiY2xhc3NkYXRhIiwiY3VycmVudF9jbGFzc19uYW1lIiwiY3VycmVudF9jbGFzc2RhdGEiLCJleHRlbmRzX25hbWUiLCJpbmNsdWRlcyIsImdldF9leHRlbmRpbmciLCJiYXNlX2NsYXNzIiwiYmFzZV9jbGFzc19vYmplY3QiLCJnZXRfY2xhc3NfYnlfbmFtZSIsImNsYXNzZXMiLCJqc19pc19zdWJjbGFzc19vZiIsImxvY2FsZUNvbXBhcmUiLCJzdWJjbGFzcyIsInN1cGVyY2xhc3MiLCJzdWJjbGFzc19vYmplY3QiLCJzdXBlcmNsYXNzX29iamVjdCIsImN1cnJlbnRfY2xhc3MiLCJnZXRfYWxsX2NsYXNzZXMiLCJidWlsZF9rZXkiLCJyc3hhcHAiLCJnZXRfZGVjb3JhdG9ycyIsImNsYXNzX2luZm8iLCJfdHJhbnNmb3JtX2RlY29yYXRvcnMiLCJnZXRfYWxsX2RlY29yYXRvcnMiLCJjb21wYWN0X2RlY29yYXRvcnMiLCJoYXNfZGVjb3JhdG9yIiwiZGVjb3JhdG9yX25hbWUiLCJzb21lIiwiZCIsImpzX2dldF9zdWJjbGFzc2VzX29mIiwiYmFzZV9jbGFzc19uYW1lIiwic3ViY2xhc3NfbmFtZXMiLCJzdWJjbGFzc19vYmplY3RzIiwic3ViY2xhc3NfbmFtZSIsIm5hbWVfYSIsIm5hbWVfYiIsIlJzeF9CZWhhdmlvcnMiLCJfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCIsIl9pbml0X2lnbm9yZV9pbnZhbGlkX2FuY2hvcl9saW5rcyIsIl90cmltX2NvcGllZF90ZXh0IiwiZG9jdW1lbnQiLCJvbiIsImUiLCIkbGluayIsImhyZWYiLCJhdHRyIiwiaXNEZWZhdWx0UHJldmVudGVkIiwiZGF0YSIsInByZXZlbnREZWZhdWx0Iiwic3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uIiwic3RhcnRzV2l0aCIsInRhcmdldElkIiwic3Vic3RyaW5nIiwidGFyZ2V0RXhpc3RzIiwiZ2V0RWxlbWVudEJ5SWQiLCJxdWVyeVNlbGVjdG9yIiwiYWRkRXZlbnRMaXN0ZW5lciIsImV2ZW50Iiwic2hpZnRLZXkiLCJzZWxlY3Rpb24iLCJnZXRTZWxlY3Rpb24iLCJzZWxlY3RlZF90ZXh0IiwiY29udGFpbmVyIiwiZ2V0UmFuZ2VBdCIsImNvbW1vbkFuY2VzdG9yQ29udGFpbmVyIiwibm9kZVR5cGUiLCJwYXJlbnROb2RlIiwiY2xvc2VzdCIsInRyaW1tZWRfdGV4dCIsImNsaXBib2FyZERhdGEiLCJzZXREYXRhIiwibG9nIiwiUnN4X0NhY2hlIiwib25fY29yZV9kZWZpbmUiLCJDb3JlX0NhY2hlIiwiX2NhY2hlcyIsImdsb2JhbCIsIl9jYWNoZXNfc2V0IiwiZ2V0X2luc3RhbmNlIiwiTWFpbiIsImRlYnVnIiwia2V5X2VuY29kZWQiLCJfZW5jb2Rla2V5IiwiZ2V0X2dsb2JhbCIsImdldF9zZXNzaW9uIiwiX3N1cHBvcnRzU3RvcmFnZSIsInJzIiwic2Vzc2lvblN0b3JhZ2UiLCJnZXRJdGVtIiwic2V0X3Nlc3Npb24iLCJfdHJ5YWdhaW4iLCJyZW1vdmVJdGVtIiwic2V0SXRlbSIsIl9pc091dE9mU3BhY2UiLCJjbGVhciIsIl9yZXNldCIsIl9fc3VwcG9ydHNTdG9yYWdlIiwiZXgiLCJSc3hfSW5pdCIsIlJzeCIsImlzX3Byb2QiLCJfX2Vudmlyb25tZW50X2NoZWNrcyIsInNjcmlwdHMiLCJnZXRFbGVtZW50c0J5VGFnTmFtZSIsInNjcmlwdCIsImRlZmVyIiwicmVhc29uIiwiX3JzeF9jb3JlX2Jvb3Rfc3RvcCIsIlJzeF9Kc19Nb2RlbCIsIl9fTU9ERUwiLCJtb2RlbERhdGEiLCJmZXRjaCIsIkN1cnJlbnRDbGFzcyIsIm1vZGVsTmFtZSIsInJlc3BvbnNlIiwiYWpheCIsInVybCIsIm1ldGhvZCIsImRhdGFUeXBlIiwiX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUiLCJnZXRNb2RlbE5hbWUiLCJyZWZyZXNoIiwiZnJlc2giLCJ0b09iamVjdCIsInRvSlNPTiIsIk1vZGVsQ2xhc3MiLCJSc3hfVmlld19UcmFuc2l0aW9ucyIsInN0YXJ0Vmlld1RyYW5zaXRpb24iLCJfaW5qZWN0X3RyYW5zaXRpb25fY3NzIiwic3R5bGUiLCJjcmVhdGVFbGVtZW50IiwidGV4dENvbnRlbnQiLCJoZWFkIiwiYXBwZW5kQ2hpbGQiLCJfNTBhZTYwOWVfYXNzZXJ0Q2xhc3NCcmFuZCIsIl81MGFlNjA5ZV9nZXRfbG9jayIsIndyaXRlcl9xIiwiXzUwYWU2MDllX3NjaGVkdWxlIiwid3JpdGVyX2FjdGl2ZSIsInJlYWRlcl9xIiwicmVhZGVycyIsIl9sb2NrcyIsImRlbGV0ZSIsIl81MGFlNjA5ZV9SZWFkV3JpdGVMb2NrIiwiYmF0Y2giLCJzcGxpY2UiLCJGb3JtX1V0aWxzIiwiX29uX2ZyYW1ld29ya19jb3JlX2RlZmluZSIsInBhcmFtcyIsImFqYXhfc3VibWl0Iiwib3B0aW9ucyIsIiRlbGVtZW50IiwiaXMiLCJjb250cm9sbGVyIiwiYWN0aW9uIiwiQWpheCIsImFqYXhfdXJsX3RvX2NvbnRyb2xsZXJfYWN0aW9uIiwiYXBwbHlfZm9ybV9lcnJvcnMiLCJwYXJlbnRfc2VsZWN0b3IiLCJlcnJvcnMiLCJyZXNldF9mb3JtX2Vycm9ycyIsIm5vcm1hbGl6ZWQiLCJfbm9ybWFsaXplX2Vycm9ycyIsImFuaW1hdGlvbnMiLCJ0eXBlIiwiX2FwcGx5X2dlbmVyYWxfZXJyb3JzIiwiZGVkdXBsaWNhdGVkIiwiX2RlZHVwbGljYXRlX2Vycm9ycyIsIl9hcHBseV9maWVsZF9lcnJvcnMiLCJtYXRjaGVkX2NvdW50Iiwia2V5cyIsInVubWF0Y2hlZCIsInVubWF0Y2hlZF9kZWR1cGxpY2F0ZWQiLCJ1bm1hdGNoZWRfY291bnQiLCJzdW1tYXJ5X21zZyIsInN1bW1hcnlfYW5pbWF0aW9ucyIsIl9hcHBseV9jb21iaW5lZF9lcnJvciIsIiRlcnJvcl9jb250YWluZXIiLCJmaW5kIiwiZmlyc3QiLCJjb250YWluZXJfdG9wIiwiZml4ZWRfaGVhZGVyX2hlaWdodCIsIl9nZXRfZml4ZWRfaGVhZGVyX2hlaWdodCIsInRhcmdldF9zY3JvbGwiLCJyZXNldCIsImZvcm1fc2VsZWN0b3IiLCIkZm9ybSIsInRyaWdnZXIiLCJzZXJpYWxpemUiLCJzZXJpYWxpemVBcnJheSIsImZvcm1fZGF0YSIsIm9uX3N1Y2Nlc3MiLCJkZXRhaWxzIiwib25fZXJyb3IiLCJyZW1vdmUiLCJyZW1vdmVDbGFzcyIsImV2ZXJ5IiwidW53cmFwcGVkIiwiZmllbGQiLCJTZXQiLCJzZWVuIiwiaGFzIiwiYWRkIiwiZmllbGRfZXJyb3JzIiwiZmllbGRfbmFtZSIsImVycm9yX21lc3NhZ2UiLCIkaW5wdXQiLCIkZXJyb3IiLCJhZGRDbGFzcyIsImFwcGVuZFRvIiwiaGlkZSIsImZhZGVJbiIsInByb21pc2UiLCJ1bm1hdGNoZWRfZXJyb3JzIiwiJGFsZXJ0IiwidGV4dCIsIiRsaXN0IiwiZXJyb3JfbXNnIiwicHJlcGVuZFRvIiwibWVzc2FnZXMiLCJtc2ciLCJlcnJvcl9saXN0IiwidG90YWxfaGVpZ2h0IiwiJGVsIiwiY3NzIiwib3V0ZXJXaWR0aCIsInZpZXdwb3J0X3dpZHRoIiwibG9nX2Jyb3dzZXJfZXJyb3JzIiwiX2hhbmRsZV9icm93c2VyX2Vycm9yIiwiZmlsZW5hbWUiLCJsaW5lbm8iLCJjb2xubyIsIm9uX3JlZnJlc2giLCJlbmFibGVkIiwiY29uZmlnIiwiZmlsdGVyX21vZGUiLCJzcGVjaWZpYyIsInNwZWNpZmljX2NoYW5uZWwiLCJjaGFubmVscyIsIndoaXRlbGlzdCIsImZpbHRlcl9jaGFubmVscyIsImJsYWNrbGlzdCIsInRpbWVzdGFtcCIsInRvSVNPU3RyaW5nIiwiaW5jbHVkZV9sb2NhdGlvbiIsImluY2x1ZGVfYmFja3RyYWNlIiwibG9jYXRpb24iLCJiYWNrdHJhY2UiLCJsaW5lIiwib3V0cHV0cyIsImJyb3dzZXIiLCJpbmNsdWRlX2JlbmNobWFyayIsIl9nZXRfdGltZV9wcmVmaXgiLCJjaGFubmVsUHJlZml4IiwiY29uc29sZU1ldGhvZCIsImxhcmF2ZWxfbG9nIiwiX2JhdGNoX2NvbnNvbGVfbWVzc2FnZSIsImxvZ19lcnJvciIsImVycm9yRGF0YSIsIl9lcnJvcl9jb3VudCIsIk1BWF9FUlJPUlNfUEVSX1BBR0UiLCJfZXJyb3JfYmF0Y2hfY291bnQiLCJNQVhfRVJST1JfQkFUQ0hFUyIsIl9lcnJvcl9iYXRjaCIsIl9lcnJvcl90aW1lciIsIl9mbHVzaF9lcnJvcl9iYXRjaCIsIkRFQk9VTkNFX01TIiwiX2NvbnNvbGVfYmF0Y2giLCJfY29uc29sZV90aW1lciIsIl9mbHVzaF9jb25zb2xlX2JhdGNoIiwiUm91dGUiLCJfc3RhcnRfdGltZSIsImVsYXBzZWQiLCJ0b0ZpeGVkIiwiXzI3ZTBlOTg2X2RlZmluZVByb3BlcnR5IiwiUnN4X0pxX0hlbHBlcnMiLCJleGlzdHMiLCJpc192aXNpYmxlIiwic2Nyb2xsX3VwX3RvIiwic3BlZWQiLCJpc19pbl9kb20iLCJlX3RvcCIsInNfdG9wIiwiZXhwciIsImZvY3VzIiwiZWxlbSIsImFjdGl2ZUVsZW1lbnQiLCJfY2xpY2tfbmF0aXZlIiwiY2xpY2siLCJoYW5kbGVyIiwib3JpZ2luYWxfcHJldmVudERlZmF1bHQiLCJiaW5kIiwid2FybiIsImNsaWNrX2FsbG93X2RlZmF1bHQiLCJfYW5jZXN0b3IiLCJIVE1Mb2JqIiwicGFyZW50RWxlbWVudCIsImRvY3VtZW50RWxlbWVudCIsImlzX2luX3ZpZXdwb3J0Iiwic2Nyb2xsdG9wIiwidG9wX29mX2VsZW1lbnQiLCJib3R0b21fb2ZfZWxlbWVudCIsImJvdHRvbV9vZl9zY3JlZW4iLCJpbm5lckhlaWdodCIsInRvcF9vZl9zY3JlZW4iLCJ0YWduYW1lIiwicHJvcCIsInRvTG93ZXJDYXNlIiwiaXNfZXh0ZXJuYWwiLCJob3N0IiwibGluayIsImhvc3RuYW1lIiwiY2hlY2tWYWxpZGl0eSIsInJlcG9ydFZhbGlkaXR5IiwicmVxdWVzdFN1Ym1pdCIsImNsb3Nlc3Rfc2libGluZyIsInNlbGVjdG9yIiwiJGN1cnJlbnQiLCIkZm91bmQiLCJuYXRpdmVfYWpheCIsInNldHRpbmdzIiwicmVxdWVzdF91cmwiLCJpc19yZWxhdGl2ZSIsImlzX3NhbWVfZG9tYWluIiwib3JpZ2luIiwiaXNfbG9jYWxfcmVxdWVzdCIsIl9fbG9jYWxfaW50ZWdyYXRpb24iLCJpc19maWxlX3VwbG9hZCIsImVuZHNXaXRoIiwiY29udHJvbGxlcl9uYW1lIiwiYWN0aW9uX25hbWUiLCJ1cmxfbWF0Y2giLCJfaW5pdF9ldmVudHMiLCJfZXZlbnRfaGFuZGxlcnMiLCJfdHJpZ2dlcmVkX2V2ZW50cyIsInRyaWdnZXJfcmVmcmVzaCIsIkNvcmVfTG9nIiwiaXNfZGV2IiwidWlkIiwiX3VpZCIsIl9kZWZpbmVfcm91dGVzIiwicm91dGVzIiwiX3JvdXRlcyIsInBhcmFtc19vYmoiLCJwYXR0ZXJuIiwiX2dlbmVyYXRlX3VybF9mcm9tX3BhdHRlcm4iLCJyZXF1aXJlZF9wYXJhbXMiLCJtYXRjaGVzIiwibWlzc2luZyIsInJlcXVpcmVkIiwidXNlZF9wYXJhbXMiLCJwYXJhbV9uYW1lIiwiZW5jb2RlZF92YWx1ZSIsInF1ZXJ5X3BhcmFtcyIsInF1ZXJ5X3N0cmluZyIsImVudHJpZXMiLCJfcmVmIiwiX3JzeF9jYWxsX2FsbF9jbGFzc2VzIiwiYWxsX2NsYXNzZXMiLCJjbGFzc2VzX3dpdGhfbWV0aG9kIiwicHJvbWlzZV9waWxlIiwicmV0dXJuX3ZhbHVlIiwiX19zdG9wcGVkIiwiX3JzeF9jb3JlX2Jvb3QiLCJfX2Jvb3RlZCIsInBoYXNlcyIsInBoYXNlIiwiX3BhcnNlX2hhc2giLCJoYXNoX3N0cmluZyIsInBhaXJzIiwicGFpciIsIl9zZXJpYWxpemVfaGFzaCIsImdldF9hbGxfcGFnZV9zdGF0ZSIsImdldF9wYWdlX3N0YXRlIiwiX3N0YXRlJGtleSIsInN0YXRlIiwic2V0X3BhZ2Vfc3RhdGUiLCJuZXdfaGFzaCIsInBhdGhuYW1lIiwiaGlzdG9yeSIsInJlcGxhY2VTdGF0ZSIsInNldF9hbGxfcGFnZV9zdGF0ZSIsIm5ld19zdGF0ZSIsInJlbmRlcl9lcnJvciIsIiRjb250YWluZXIiLCJmaWxlIiwiX2VzY2FwZV9odG1sIiwiZGl2IiwiaW5uZXJIVE1MIiwiX2U4MjExZjViX2RlZmluZVByb3BlcnR5IiwiX3BlbmRpbmdfY2FsbHMiLCJfZmx1c2hfdGltZW91dCIsIl9jYWxsX2NvdW50ZXIiLCJNQVhfQkFUQ0hfU0laRSIsIl90cmFja2VkX3Byb21pc2VzIiwiV2Vha1NldCIsIk1vZGFsIiwicGF0aCIsImFqYXhfZGlzYWJsZV9iYXRjaGluZyIsIl9jYWxsX2RpcmVjdCIsIl9jYWxsX2JhdGNoIiwiY2FsbF9rZXkiLCJfZ2VuZXJhdGVfY2FsbF9rZXkiLCJleGlzdGluZ19jYWxsIiwiaXNfY29tcGxldGUiLCJpc19lcnJvciIsImNhbGxiYWNrcyIsImNhbGxfaWQiLCJwZW5kaW5nX2NhbGwiLCJwZW5kaW5nX2NvdW50IiwiX2ZsdXNoX3BlbmRpbmdfY2FsbHMiLCJzdWNjZXNzIiwiX3N1Y2Nlc3MiLCJwcm9jZXNzZWRfdmFsdWUiLCJfYWpheF9yZXR1cm5fdmFsdWUiLCJlcnJvcl90eXBlIiwiZmF0YWxfZXJyb3JfZGF0YSIsImZhdGFsX2Vycm9yIiwiZW5kcG9pbnQiLCJhdXRoX2Vycm9yIiwidW5hdXRoX2Vycm9yIiwiZm9ybV9lcnJvciIsImdlbmVyaWNfZXJyb3IiLCJ4aHIiLCJfZXh0cmFjdF9lcnJvcl9tZXNzYWdlIiwibmV0d29ya19lcnJvciIsInN0YXR1c1RleHQiLCJjYWxsc190b19zZW5kIiwiY2FsbF9tYXAiLCJiYXRjaF9jYWxscyIsInJlc3BvbnNlX2tleSIsImNhbGxfcmVzcG9uc2UiLCJlcnJvcl9kZXRhaWxzIiwiX3JlZjIiLCJ4aHJfZXJyb3IiLCJfcmVmMyIsInNvcnRlZF9wYXJhbXMiLCJyZXNwb25zZUpTT04iLCJyZXNwb25zZVRleHQiLCJKcWh0bWxfQ29tcG9uZW50IiwiX0Jhc2VfSnFodG1sX0NvbXBvbmVudCIsIkpxaHRtbF9JbnRlZ3JhdGlvbiIsIl9vbl9mcmFtZXdvcmtfbW9kdWxlc19kZWZpbmUiLCJqcWh0bWxfY29tcG9uZW50cyIsImNvbXBvbmVudCIsImpxaHRtbCIsInJlZ2lzdGVyX2NvbXBvbmVudCIsIl9vbl9mcmFtZXdvcmtfbW9kdWxlc19pbml0IiwiJHNjb3BlIiwiaXNfdG9wX2xldmVsIiwiY29tcG9uZW50c19uZWVkaW5nX2luaXQiLCJjb250YWlucyIsImNsYXNzTGlzdCIsImNvbXBvbmVudF9uYW1lIiwiY29tcG9uZW50X2FyZ3MiLCJhcmdzX3N0cmluZyIsInJlbW92ZUF0dHIiLCJyZW1vdmVEYXRhIiwiY29tcG9uZW50X2FyZ3NfZmlsdGVyZWQiLCJfaW5uZXJfaHRtbCIsImNvbXBvbmVudF9wcm9taXNlIiwibmVzdGVkX3Byb21pc2VzIiwiZ2V0X2NvbXBvbmVudF9uYW1lcyIsImhhc19jb21wb25lbnQiXSwibWFwcGluZ3MiOiI7QUFBQTtBQUNBOzs7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNBLFNBQVNBLENBQUNDLEtBQUssRUFBRTtFQUN0QixPQUFPQSxLQUFLO0FBQ2hCOzs7Ozs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxTQUFTQSxDQUFBLEVBQUc7RUFDakIsSUFBSSxnRUFBZ0UsQ0FBQ0MsSUFBSSxDQUFDQyxTQUFTLENBQUNDLFNBQVMsQ0FBQyxFQUFFO0lBQzVGLE9BQU8sSUFBSTtFQUNmLENBQUMsTUFBTSxJQUFJQyxDQUFDLENBQUNDLE1BQU0sQ0FBQyxDQUFDQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsRUFBRTtJQUNoQztJQUNBLE9BQU8sSUFBSTtFQUNmLENBQUMsTUFBTTtJQUNILE9BQU8sS0FBSztFQUNoQjtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsVUFBVUEsQ0FBQSxFQUFHO0VBQ2xCLE9BQU8sQ0FBQ1AsU0FBUyxDQUFDLENBQUM7QUFDdkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxT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QUU7VUFDWmlCLE9BQU8sQ0FBQ2pCLEtBQUssQ0FBQyx1REFBdUQ0cUIsY0FBYyxHQUFHLEVBQUU1cUIsS0FBSyxDQUFDO1VBQzlGaUIsT0FBTyxDQUFDakIsS0FBSyxDQUFDLGdCQUFnQixFQUFFQSxLQUFLLENBQUNVLEtBQUssSUFBSVYsS0FBSyxDQUFDO1FBQ3pEO01BQ0o7SUFDSixDQUFDLENBQUM7O0lBRUY7SUFDQSxJQUFJd3FCLFlBQVksRUFBRTtNQUNkLENBQUMsWUFBWTtRQUNULE1BQU16bEIsT0FBTyxDQUFDOEQsR0FBRyxDQUFDRixRQUFRLENBQUM7UUFDM0IsTUFBTStMLEdBQUcsQ0FBQ2tRLHFCQUFxQixDQUFDLGlCQUFpQixDQUFDO1FBQ2xEbFEsR0FBRyxDQUFDd0YsT0FBTyxDQUFDLGNBQWMsQ0FBQztNQUMvQixDQUFDLEVBQUUsQ0FBQztNQUNKO0lBQ0o7O0lBRUE7SUFDQSxPQUFPdlIsUUFBUTtFQUNuQjs7RUFFQTtBQUNKO0FBQ0E7QUFDQTtFQUNJLE9BQU8waUIsbUJBQW1CQSxDQUFBLEVBQUc7SUFDekIsT0FBT2pCLE1BQU0sQ0FBQ2lCLG1CQUFtQixDQUFDLENBQUM7RUFDdkM7O0VBRUE7QUFDSjtBQUNBO0FBQ0E7QUFDQTtFQUNJLE9BQU9DLGFBQWFBLENBQUNscUIsSUFBSSxFQUFFO0lBQ3ZCLE9BQU9ncEIsTUFBTSxDQUFDa0IsYUFBYSxDQUFDbHFCLElBQUksQ0FBQztFQUNyQztBQUNKOztBQUVBOzs7O0FDaktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRyIsImZpbGUiOiJidW5kbGVfb3V0cHV0X0Jvb3RzdHJhcDVfU3JjX0J1bmRsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIndpbmRvdy5yc3hhcHAgPSB3aW5kb3cucnN4YXBwIHx8IHt9O1xud2luZG93LnJzeGFwcC5tb2R1bGVfcGF0aHMgPSB7XCJib290c3RyYXA1X3NyY1wiOlwicnN4XFwvdGhlbWVcXC92ZW5kb3JcXC9ib290c3RyYXA1XFwvc2Nzc1wifTtcbiIsIi8vIE5QTSBJbXBvcnQgRGVjbGFyYXRpb25zIGZvciBBcHAgQnVuZGxlXG4vLyBBdXRvLWdlbmVyYXRlZCB0byBwcm92aWRlIE5QTSBtb2R1bGVzIHRvIGFwcCBidW5kbGUgc2NvcGVcbi8vIENhY2hlIGtleTogOTVhNmY2MDJjOTgwMzc2MTFiNjQwYjBiNTM0MjgzMGJcblxuY29uc3QganFodG1sID0gd2luZG93Ll9yc3hfbnBtLmpxaHRtbDtcbmlmICghanFodG1sKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnUlNYIEZyYW1ld29yayBFcnJvcjogTlBNIG1vZHVsZSBcImpxaHRtbFwiIG5vdCBmb3VuZC5cXG4nICtcbiAgICAgICAgJ0V4cGVjdGVkIHdpbmRvdy5fcnN4X25wbS5qcWh0bWwgdG8gYmUgZGVmaW5lZCBieSB0aGUgdmVuZG9yIGJ1bmRsZS4nXG4gICAgKTtcbn1cblxuY29uc3QgX0Jhc2VfSnFodG1sX0NvbXBvbmVudCA9IHdpbmRvdy5fcnN4X25wbS5fQmFzZV9KcWh0bWxfQ29tcG9uZW50O1xuaWYgKCFfQmFzZV9KcWh0bWxfQ29tcG9uZW50KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnUlNYIEZyYW1ld29yayBFcnJvcjogTlBNIG1vZHVsZSBcIl9CYXNlX0pxaHRtbF9Db21wb25lbnRcIiBub3QgZm91bmQuXFxuJyArXG4gICAgICAgICdFeHBlY3RlZCB3aW5kb3cuX3JzeF9ucG0uX0Jhc2VfSnFodG1sX0NvbXBvbmVudCB0byBiZSBkZWZpbmVkIGJ5IHRoZSB2ZW5kb3IgYnVuZGxlLidcbiAgICApO1xufVxuXG4vLyBDbGVhbiB1cCBOUE0gY29udGFpbmVyIHRvIHByZXZlbnQgY29uc29sZSBhY2Nlc3NcbmRlbGV0ZSB3aW5kb3cuX3JzeF9ucG07XG4iLCIvKipcbiAqIERlY29yYXRvciBmdW5jdGlvbiB0aGF0IG1hcmtzIGEgZnVuY3Rpb24gYXMgYSBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb24uXG4gKlxuICogV2hlbiBhIGZ1bmN0aW9uIGhhcyBAZGVjb3JhdG9yIGluIGl0cyBKU0RvYyBjb21tZW50LCBpdCB3aGl0ZWxpc3RzIHRoYXQgZnVuY3Rpb25cbiAqIHRvIGJlIHVzZWQgYXMgYSBkZWNvcmF0b3Igb24gb3RoZXIgbWV0aG9kcyB0aHJvdWdob3V0IHRoZSBjb2RlYmFzZS5cbiAqXG4gKiBUaGUgZnVuY3Rpb24gaXRzZWxmIHBlcmZvcm1zIG5vIG9wZXJhdGlvbiAtIGl0IHNpbXBseSByZXR1cm5zIGl0cyBpbnB1dCB1bmNoYW5nZWQuXG4gKiBJdHMgcHVycG9zZSBpcyBwdXJlbHkgYXMgYSBtYXJrZXIgZm9yIHRoZSBtYW5pZmVzdCB2YWxpZGF0aW9uIHN5c3RlbS5cbiAqXG4gKiBVc2FnZTpcbiAqICAgLy8gLyoqXG4gKiAgIC8vICAqIE15IGN1c3RvbSBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb25cbiAqICAgLy8gICogQGRlY29yYXRvclxuICogICAvLyAgKlxcL1xuICogICBmdW5jdGlvbiBteV9jdXN0b21fZGVjb3JhdG9yKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKSB7XG4gKiAgICAgICAvLyBEZWNvcmF0b3IgaW1wbGVtZW50YXRpb25cbiAqICAgfVxuICpcbiAqIFRoaXMgYWxsb3dzIG15X2N1c3RvbV9kZWNvcmF0b3IgdG8gYmUgdXNlZCBhcyBAbXlfY3VzdG9tX2RlY29yYXRvciBvbiBzdGF0aWMgbWV0aG9kcy5cbiAqXG4gKiBUT0RPOiBUaGlzIGlzIHByb2JhYmx5IG5vIGxvbmdlciBuZWNlc3Nhcnk/IG1heWJlP1xuICovXG5mdW5jdGlvbiBkZWNvcmF0b3IodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG59XG4iLCIvKlxuICogQnJvd3NlciBhbmQgRE9NIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgYnJvd3NlciBkZXRlY3Rpb24sIHZpZXdwb3J0IHV0aWxpdGllcywgYW5kIERPTSBtYW5pcHVsYXRpb24uXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQlJPV1NFUiBERVRFQ1RJT05cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHVzZXIgaXMgb24gYSBtb2JpbGUgZGV2aWNlIG9yIHVzaW5nIG1vYmlsZSB2aWV3cG9ydFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgbW9iaWxlIGRldmljZSBvciB2aWV3cG9ydCA8IDk5MnB4XG4gKiBAdG9kbyBJbXByb3ZlIHVzZXIgYWdlbnQgZGV0ZWN0aW9uIGZvciBhbGwgbW9iaWxlIGRldmljZXNcbiAqL1xuZnVuY3Rpb24gaXNfbW9iaWxlKCkge1xuICAgIGlmICgvQW5kcm9pZHx3ZWJPU3xpUGhvbmV8aVBhZHxpUG9kfEJsYWNrQmVycnl8SUVNb2JpbGV8T3BlcmEgTWluaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmICgkKHdpbmRvdykud2lkdGgoKSA8IDk5Mikge1xuICAgICAgICAvLyA5OTJweCA9IGJvb3RzdHJhcCA0IGNvbC1tZC1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHVzZXIgaXMgb24gZGVza3RvcCAobm90IG1vYmlsZSlcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG5vdCBtb2JpbGUgZGV2aWNlL3ZpZXdwb3J0XG4gKi9cbmZ1bmN0aW9uIGlzX2Rlc2t0b3AoKSB7XG4gICAgcmV0dXJuICFpc19tb2JpbGUoKTtcbn1cblxuLyoqXG4gKiBEZXRlY3RzIHRoZSB1c2VyJ3Mgb3BlcmF0aW5nIHN5c3RlbVxuICogQHJldHVybnMge3N0cmluZ30gT1MgbmFtZTogJ01hYyBPUycsICdpUGhvbmUnLCAnaVBhZCcsICdXaW5kb3dzJywgJ0FuZHJvaWQtUGhvbmUnLCAnQW5kcm9pZC1UYWJsZXQnLCAnTGludXgnLCBvciAnVW5rbm93bidcbiAqL1xuZnVuY3Rpb24gZ2V0X29zKCkge1xuICAgIGxldCB1c2VyX2FnZW50ID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQsXG4gICAgICAgIHBsYXRmb3JtID0gd2luZG93Lm5hdmlnYXRvci5wbGF0Zm9ybSxcbiAgICAgICAgbWFjb3NfcGxhdGZvcm1zID0gWydNYWNpbnRvc2gnLCAnTWFjSW50ZWwnLCAnTWFjUFBDJywgJ01hYzY4SyddLFxuICAgICAgICB3aW5kb3dzX3BsYXRmb3JtcyA9IFsnV2luMzInLCAnV2luNjQnLCAnV2luZG93cycsICdXaW5DRSddLFxuICAgICAgICBpb3NfcGxhdGZvcm1zID0gWydpUGhvbmUnLCAnaVBhZCcsICdpUG9kJ10sXG4gICAgICAgIG9zID0gbnVsbDtcblxuICAgIGxldCBpc19tb2JpbGVfZGV2aWNlID0gaXNfbW9iaWxlKCk7XG5cbiAgICBpZiAobWFjb3NfcGxhdGZvcm1zLmluZGV4T2YocGxhdGZvcm0pICE9PSAtMSkge1xuICAgICAgICBvcyA9ICdNYWMgT1MnO1xuICAgIH0gZWxzZSBpZiAoaW9zX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEgJiYgaXNfbW9iaWxlX2RldmljZSkge1xuICAgICAgICBvcyA9ICdpUGhvbmUnO1xuICAgIH0gZWxzZSBpZiAoaW9zX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEgJiYgIWlzX21vYmlsZV9kZXZpY2UpIHtcbiAgICAgICAgb3MgPSAnaVBhZCc7XG4gICAgfSBlbHNlIGlmICh3aW5kb3dzX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEpIHtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgfSBlbHNlIGlmICgvQW5kcm9pZC8udGVzdCh1c2VyX2FnZW50KSAmJiBpc19tb2JpbGVfZGV2aWNlKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQtUGhvbmUnO1xuICAgIH0gZWxzZSBpZiAoL0FuZHJvaWQvLnRlc3QodXNlcl9hZ2VudCkgJiYgIWlzX21vYmlsZV9kZXZpY2UpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZC1UYWJsZXQnO1xuICAgIH0gZWxzZSBpZiAoIW9zICYmIC9MaW51eC8udGVzdChwbGF0Zm9ybSkpIHtcbiAgICAgICAgb3MgPSAnTGludXgnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gJ1Vua25vd24nO1xuICAgIH1cblxuICAgIHJldHVybiBvcztcbn1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHRoZSB1c2VyIGFnZW50IGlzIGEgd2ViIGNyYXdsZXIvYm90XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB1c2VyIGFnZW50IGFwcGVhcnMgdG8gYmUgYSBib3QvY3Jhd2xlclxuICovXG5mdW5jdGlvbiBpc19jcmF3bGVyKCkge1xuICAgIGxldCB1c2VyX2FnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICBsZXQgYm90X3BhdHRlcm4gPSAvYm90fHNwaWRlcnxjcmF3bHxzbHVycHxhcmNoaXZlcnxwaW5nfHNlYXJjaHxkaWd8dHJhY2tlcnxtb25pdG9yfHNub29weXx5YWhvb3xiYWlkdXxtc258YXNrfHRlb21hfGF4aW9zL2k7XG5cbiAgICByZXR1cm4gYm90X3BhdHRlcm4udGVzdCh1c2VyX2FnZW50KTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRE9NIFNDUk9MTElORyBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBTY3JvbGxzIHBhcmVudCBjb250YWluZXIgdG8gbWFrZSB0YXJnZXQgZWxlbWVudCB2aXNpYmxlIGlmIG5lZWRlZFxuICogQHBhcmFtIHtzdHJpbmd8SFRNTEVsZW1lbnR8alF1ZXJ5fSB0YXJnZXQgLSBUYXJnZXQgZWxlbWVudCB0byBzY3JvbGwgaW50byB2aWV3XG4gKi9cbmZ1bmN0aW9uIHNjcm9sbF9pbnRvX3ZpZXdfaWZfbmVlZGVkKHRhcmdldCkge1xuICAgIGNvbnN0ICR0YXJnZXQgPSAkKHRhcmdldCk7XG5cbiAgICAvLyBGaW5kIHRoZSBjbG9zZXN0IHBhcmVudCB3aXRoIG92ZXJmbG93LXk6IGF1dG9cbiAgICBjb25zdCAkcGFyZW50ID0gJHRhcmdldC5wYXJlbnQoKTtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgYWJzb2x1dGUgdG9wIHBvc2l0aW9uIG9mIHRoZSB0YXJnZXRcbiAgICBjb25zdCB0YXJnZXRfdG9wID0gJHRhcmdldC5wb3NpdGlvbigpLnRvcCArICRwYXJlbnQuc2Nyb2xsVG9wKCk7XG5cbiAgICBjb25zdCB0YXJnZXRfaGVpZ2h0ID0gJHRhcmdldC5vdXRlckhlaWdodCgpO1xuICAgIGNvbnN0IHBhcmVudF9oZWlnaHQgPSAkcGFyZW50LmhlaWdodCgpO1xuICAgIGNvbnN0IHNjcm9sbF9wb3NpdGlvbiA9ICRwYXJlbnQuc2Nyb2xsVG9wKCk7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgdGFyZ2V0IGlzIG91dCBvZiB2aWV3XG4gICAgaWYgKHRhcmdldF90b3AgPCBzY3JvbGxfcG9zaXRpb24gfHwgdGFyZ2V0X3RvcCArIHRhcmdldF9oZWlnaHQgPiBzY3JvbGxfcG9zaXRpb24gKyBwYXJlbnRfaGVpZ2h0KSB7XG4gICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ1VJJywgJ1Njcm9sbGluZyEnLCB0YXJnZXRfdG9wKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG5ldyBzY3JvbGwgcG9zaXRpb24gdG8gY2VudGVyIHRoZSB0YXJnZXRcbiAgICAgICAgbGV0IG5ld19zY3JvbGxfcG9zaXRpb24gPSB0YXJnZXRfdG9wICsgdGFyZ2V0X2hlaWdodCAvIDIgLSBwYXJlbnRfaGVpZ2h0IC8gMjtcblxuICAgICAgICAvLyBMaW1pdCB0aGUgc2Nyb2xsIHBvc2l0aW9uIGJldHdlZW4gMCBhbmQgdGhlIG1heGltdW0gc2Nyb2xsYWJsZSBoZWlnaHRcbiAgICAgICAgbmV3X3Njcm9sbF9wb3NpdGlvbiA9IE1hdGgubWF4KDAsIE1hdGgubWluKG5ld19zY3JvbGxfcG9zaXRpb24sICRwYXJlbnRbMF0uc2Nyb2xsSGVpZ2h0IC0gcGFyZW50X2hlaWdodCkpO1xuXG4gICAgICAgIC8vIFNjcm9sbCB0aGUgcGFyZW50IHRvIHRoZSBuZXcgc2Nyb2xsIHBvc2l0aW9uXG4gICAgICAgICRwYXJlbnQuc2Nyb2xsVG9wKG5ld19zY3JvbGxfcG9zaXRpb24pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBTY3JvbGxzIHBhZ2UgdG8gbWFrZSB0YXJnZXQgZWxlbWVudCB2aXNpYmxlIGlmIG5lZWRlZCAod2l0aCBhbmltYXRpb24pXG4gKiBAcGFyYW0ge3N0cmluZ3xIVE1MRWxlbWVudHxqUXVlcnl9IHRhcmdldCAtIFRhcmdldCBlbGVtZW50IHRvIHNjcm9sbCBpbnRvIHZpZXdcbiAqL1xuZnVuY3Rpb24gc2Nyb2xsX3BhZ2VfaW50b192aWV3X2lmX25lZWRlZCh0YXJnZXQpIHtcbiAgICBjb25zdCAkdGFyZ2V0ID0gJCh0YXJnZXQpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBhYnNvbHV0ZSB0b3AgcG9zaXRpb24gb2YgdGhlIHRhcmdldCByZWxhdGl2ZSB0byB0aGUgZG9jdW1lbnRcbiAgICBjb25zdCB0YXJnZXRfdG9wID0gJHRhcmdldC5vZmZzZXQoKS50b3A7XG5cbiAgICBjb25zdCB0YXJnZXRfaGVpZ2h0ID0gJHRhcmdldC5vdXRlckhlaWdodCgpO1xuICAgIGNvbnN0IHdpbmRvd19oZWlnaHQgPSAkKHdpbmRvdykuaGVpZ2h0KCk7XG4gICAgY29uc3Qgd2luZG93X3Njcm9sbF9wb3NpdGlvbiA9ICQod2luZG93KS5zY3JvbGxUb3AoKTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB0YXJnZXQgaXMgb3V0IG9mIHZpZXdcbiAgICBpZiAodGFyZ2V0X3RvcCA8IHdpbmRvd19zY3JvbGxfcG9zaXRpb24gfHwgdGFyZ2V0X3RvcCArIHRhcmdldF9oZWlnaHQgPiB3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uICsgd2luZG93X2hlaWdodCkge1xuICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKCdVSScsICdTY3JvbGxpbmchJywgdGFyZ2V0X3RvcCk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuZXcgc2Nyb2xsIHBvc2l0aW9uIHRvIGNlbnRlciB0aGUgdGFyZ2V0XG4gICAgICAgIGNvbnN0IG5ld19zY3JvbGxfcG9zaXRpb24gPSB0YXJnZXRfdG9wICsgdGFyZ2V0X2hlaWdodCAvIDIgLSB3aW5kb3dfaGVpZ2h0IC8gMjtcblxuICAgICAgICAvLyBBbmltYXRlIHRoZSBzY3JvbGwgdG8gdGhlIG5ldyBwb3NpdGlvblxuICAgICAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZShcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzY3JvbGxUb3A6IG5ld19zY3JvbGxfcG9zaXRpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgMTAwMFxuICAgICAgICApOyAvLyBkdXJhdGlvbiBvZiB0aGUgc2Nyb2xsIGFuaW1hdGlvbiBpbiBtaWxsaXNlY29uZHNcbiAgICB9XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERPTSBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBXYWl0cyBmb3IgYWxsIGltYWdlcyBvbiB0aGUgcGFnZSB0byBsb2FkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGNhbGwgd2hlbiBhbGwgaW1hZ2VzIGFyZSBsb2FkZWRcbiAqL1xuZnVuY3Rpb24gd2FpdF9mb3JfaW1hZ2VzKGNhbGxiYWNrKSB7XG4gICAgY29uc3QgJGltYWdlcyA9ICQoJ2ltZycpOyAvLyBHZXQgYWxsIGltZyB0YWdzXG4gICAgY29uc3QgdG90YWxfaW1hZ2VzID0gJGltYWdlcy5sZW5ndGg7XG4gICAgbGV0IGltYWdlc19sb2FkZWQgPSAwO1xuXG4gICAgaWYgKHRvdGFsX2ltYWdlcyA9PT0gMCkge1xuICAgICAgICBjYWxsYmFjaygpOyAvLyBpZiB0aGVyZSBhcmUgbm8gaW1hZ2VzLCBpbW1lZGlhdGVseSBjYWxsIHRoZSBjYWxsYmFja1xuICAgIH1cblxuICAgICRpbWFnZXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBpbWcub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaW1hZ2VzX2xvYWRlZCsrO1xuICAgICAgICAgICAgaWYgKGltYWdlc19sb2FkZWQgPT09IHRvdGFsX2ltYWdlcykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7IC8vIGNhbGwgdGhlIGNhbGxiYWNrIHdoZW4gYWxsIGltYWdlcyBhcmUgbG9hZGVkXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGltZy5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaW1hZ2VzX2xvYWRlZCsrO1xuICAgICAgICAgICAgaWYgKGltYWdlc19sb2FkZWQgPT09IHRvdGFsX2ltYWdlcykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7IC8vIGFsc28gY2FsbCB0aGUgY2FsbGJhY2sgaWYgYW4gaW1hZ2UgZmFpbHMgdG8gbG9hZFxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpbWcuc3JjID0gdGhpcy5zcmM7IC8vIHRoaXMgdHJpZ2dlcnMgdGhlIGxvYWRpbmdcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgalF1ZXJ5IGVsZW1lbnQgY29udGFpbmluZyBhIG5vbi1icmVha2luZyBzcGFjZVxuICogQHJldHVybnMge2pRdWVyeX0galF1ZXJ5IHNwYW4gZWxlbWVudCB3aXRoICZuYnNwO1xuICovXG5mdW5jdGlvbiAkbmJzcCgpIHtcbiAgICByZXR1cm4gJCgnPHNwYW4+Jm5ic3A7PC9zcGFuPicpO1xufVxuXG4vKipcbiAqIEVzY2FwZXMgc3BlY2lhbCBjaGFyYWN0ZXJzIGluIGEgalF1ZXJ5IHNlbGVjdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBFbGVtZW50IElEIHRvIGVzY2FwZVxuICogQHJldHVybnMge3N0cmluZ30galF1ZXJ5IHNlbGVjdG9yIHN0cmluZyB3aXRoIGVzY2FwZWQgc3BlY2lhbCBjaGFyYWN0ZXJzXG4gKiBAd2FybmluZyBOb3Qgc2FmZSBmb3Igc2VjdXJpdHktY3JpdGljYWwgb3BlcmF0aW9uc1xuICovXG5mdW5jdGlvbiBlc2NhcGVfanFfc2VsZWN0b3IoaWQpIHtcbiAgICByZXR1cm4gJyMnICsgaWQucmVwbGFjZSgvKDp8XFwufFxcW3xcXF18LHw9fEApL2csICdcXFxcJDEnKTtcbn0iLCIvKlxuICogRGF0ZSBhbmQgdGltZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIGRhdGUvdGltZSBjb252ZXJzaW9ucyBhbmQgVW5peCB0aW1lc3RhbXBzLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERBVEUvVElNRSBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBHZXRzIHRoZSBjdXJyZW50IFVuaXggdGltZXN0YW1wIChzZWNvbmRzIHNpbmNlIGVwb2NoKVxuICogQHJldHVybnMge251bWJlcn0gQ3VycmVudCBVbml4IHRpbWVzdGFtcCBpbiBzZWNvbmRzXG4gKiBAdG9kbyBDYWxjdWxhdGUgYmFzZWQgb24gc2VydmVyIHRpbWUgYXQgcGFnZSByZW5kZXJcbiAqIEB0b2RvIE1vdmUgdG8gYSBkYXRlIGxpYnJhcnlcbiAqL1xuZnVuY3Rpb24gdW5peF90aW1lKCkge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBkYXRlIHN0cmluZyB0byBVbml4IHRpbWVzdGFtcFxuICogQHBhcmFtIHtzdHJpbmd9IHN0cl9kYXRlIC0gRGF0ZSBzdHJpbmcgKFktbS1kIEg6aTpzIGZvcm1hdClcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFVuaXggdGltZXN0YW1wIGluIHNlY29uZHNcbiAqL1xuZnVuY3Rpb24geW1kaGlzX3RvX3VuaXgoc3RyX2RhdGUpIHtcbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoc3RyX2RhdGUpO1xuICAgIHJldHVybiBkYXRlLmdldFRpbWUoKSAvIDEwMDA7XG59IiwiLypcbiAqIEVycm9yIGhhbmRsaW5nIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgZXJyb3IgY3JlYXRpb24gYW5kIGRlYnVnZ2luZyB1dGlsaXRpZXMuXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRVJST1IgSEFORExJTkdcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGVycm9yIG9iamVjdCBmcm9tIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R9IHN0ciAtIEVycm9yIG1lc3NhZ2Ugb3IgZXhpc3RpbmcgZXJyb3Igb2JqZWN0XG4gKiBAcGFyYW0ge251bWJlcn0gW2Vycm9yX2NvZGVdIC0gT3B0aW9uYWwgZXJyb3Igc3RhdHVzIGNvZGVcbiAqIEByZXR1cm5zIHtPYmplY3R9IEVycm9yIG9iamVjdCB3aXRoIGVycm9yIGFuZCBzdGF0dXMgcHJvcGVydGllc1xuICovXG5mdW5jdGlvbiBlcnJvcihzdHIsIGVycm9yX2NvZGUpIHtcbiAgICBpZiAodHlwZW9mIHN0ci5lcnJvciAhPSB1bmRlZikge1xuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3JfY29kZSA9PSB1bmRlZikge1xuICAgICAgICAgICAgcmV0dXJuIHsgZXJyb3I6IHN0ciwgc3RhdHVzOiBudWxsIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4geyBlcnJvcjogc3RyLCBzdGF0dXM6IGVycm9yX2NvZGUgfTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBTYW5pdHkgY2hlY2sgZmFpbHVyZSBoYW5kbGVyIGZvciBKYXZhU2NyaXB0XG4gKlxuICogVGhpcyBmdW5jdGlvbiBzaG91bGQgYmUgY2FsbGVkIHdoZW4gYSBzYW5pdHkgY2hlY2sgZmFpbHMgLSBpLmUuLCB3aGVuIHRoZSBjb2RlXG4gKiBlbmNvdW50ZXJzIGEgY29uZGl0aW9uIHRoYXQgXCJzaG91bGRuJ3QgaGFwcGVuXCIgaWYgZXZlcnl0aGluZyBpcyB3b3JraW5nIGNvcnJlY3RseS5cbiAqXG4gKiBVbmxpa2UgUEhQLCB3ZSBjYW4ndCBzdG9wIEphdmFTY3JpcHQgZXhlY3V0aW9uLCBidXQgd2UgY2FuOlxuICogMS4gVGhyb3cgYW4gZXJyb3IgdGhhdCB3aWxsIGJlIGNhdWdodCBieSBlcnJvciBoYW5kbGVyc1xuICogMi4gTG9nIGEgY2xlYXIgZXJyb3IgdG8gdGhlIGNvbnNvbGVcbiAqIDMuIFByb3ZpZGUgc3RhY2sgdHJhY2UgZm9yIGRlYnVnZ2luZ1xuICpcbiAqIFVzZSB0aGlzIGluc3RlYWQgb2Ygc2lsZW50bHkgcmV0dXJuaW5nIG9yIGNvbnRpbnVpbmcgd2hlbiBlbmNvdW50ZXJpbmcgdW5leHBlY3RlZCBjb25kaXRpb25zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIE9wdGlvbmFsIHNwZWNpZmljIG1lc3NhZ2UgYWJvdXQgd2hhdCBzaG91bGRuJ3QgaGF2ZSBoYXBwZW5lZFxuICogQHRocm93cyB7RXJyb3J9IEFsd2F5cyB0aHJvd3Mgd2l0aCBsb2NhdGlvbiBhbmQgY29udGV4dCBpbmZvcm1hdGlvblxuICovXG5mdW5jdGlvbiBzaG91bGRudF9oYXBwZW4obWVzc2FnZSA9IG51bGwpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIGNvbnN0IHN0YWNrID0gZXJyb3Iuc3RhY2sgfHwgJyc7XG4gICAgY29uc3Qgc3RhY2tMaW5lcyA9IHN0YWNrLnNwbGl0KCdcXG4nKTtcblxuICAgIC8vIEdldCB0aGUgY2FsbGVyIGxvY2F0aW9uIChza2lwIHRoZSBFcnJvciBsaW5lIGFuZCB0aGlzIGZ1bmN0aW9uKVxuICAgIGxldCBjYWxsZXJJbmZvID0gJ3Vua25vd24gbG9jYXRpb24nO1xuICAgIGlmIChzdGFja0xpbmVzLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgY29uc3QgY2FsbGVyTGluZSA9IHN0YWNrTGluZXNbMl0gfHwgc3RhY2tMaW5lc1sxXSB8fCAnJztcbiAgICAgICAgLy8gRXh0cmFjdCBmaWxlIGFuZCBsaW5lIG51bWJlciBmcm9tIHN0YWNrIHRyYWNlXG4gICAgICAgIGNvbnN0IG1hdGNoID0gY2FsbGVyTGluZS5tYXRjaCgvYXRcXHMrLio/XFxzK1xcKCguKj8pOihcXGQrKTooXFxkKylcXCkvKSB8fCBjYWxsZXJMaW5lLm1hdGNoKC9hdFxccysoLio/KTooXFxkKyk6KFxcZCspLyk7XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgY2FsbGVySW5mbyA9IGAke21hdGNoWzFdfToke21hdGNoWzJdfWA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgZXJyb3JNZXNzYWdlID0gYEZhdGFsOiBzaG91bGRudF9oYXBwZW4oKSB3YXMgY2FsbGVkIGF0ICR7Y2FsbGVySW5mb31cXG5gO1xuICAgIGVycm9yTWVzc2FnZSArPSAnVGhpcyBpbmRpY2F0ZXMgYSBzYW5pdHkgY2hlY2sgZmFpbGVkIC0gdGhlIGNvZGUgaXMgbm90IGJlaGF2aW5nIGFzIGV4cGVjdGVkLlxcbic7XG5cbiAgICBpZiAobWVzc2FnZSkge1xuICAgICAgICBlcnJvck1lc3NhZ2UgKz0gYERldGFpbHM6ICR7bWVzc2FnZX1cXG5gO1xuICAgIH1cblxuICAgIGVycm9yTWVzc2FnZSArPSAnUGxlYXNlIHRob3JvdWdobHkgcmV2aWV3IHRoZSByZWxhdGVkIGNvZGUgdG8gZGV0ZXJtaW5lIHdoeSB0aGlzIGVycm9yIG9jY3VycmVkLic7XG5cbiAgICAvLyBMb2cgdG8gY29uc29sZSB3aXRoIGZ1bGwgdmlzaWJpbGl0eVxuICAgIGNvbnNvbGUuZXJyb3IoJz0nLnJlcGVhdCg4MCkpO1xuICAgIGNvbnNvbGUuZXJyb3IoJ1NBTklUWSBDSEVDSyBGQUlMVVJFJyk7XG4gICAgY29uc29sZS5lcnJvcignPScucmVwZWF0KDgwKSk7XG4gICAgY29uc29sZS5lcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgIGNvbnNvbGUuZXJyb3IoJ1N0YWNrIHRyYWNlOicsIHN0YWNrKTtcbiAgICBjb25zb2xlLmVycm9yKCc9Jy5yZXBlYXQoODApKTtcblxuICAgIC8vIFRocm93IGVycm9yIHRvIHN0b3AgZXhlY3V0aW9uIGZsb3dcbiAgICBjb25zdCBmYXRhbEVycm9yID0gbmV3IEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgZmF0YWxFcnJvci5uYW1lID0gJ1Nhbml0eUNoZWNrRmFpbHVyZSc7XG4gICAgdGhyb3cgZmF0YWxFcnJvcjtcbn0iLCIvKlxuICogSGFzaGluZyBhbmQgY29tcGFyaXNvbiB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIG9iamVjdCBoYXNoaW5nIGFuZCBkZWVwIGNvbXBhcmlzb24uXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEFTSElORyBBTkQgQ09NUEFSSVNPTlxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBoYXNoIGZvciBhbnkgdmFsdWUgKGhhbmRsZXMgb2JqZWN0cywgYXJyYXlzLCBjaXJjdWxhciByZWZlcmVuY2VzKVxuICogQHBhcmFtIHsqfSB0aGVfdmFyIC0gVmFsdWUgdG8gaGFzaFxuICogQHBhcmFtIHtib29sZWFufSBbY2FsY19zaGExPXRydWVdIC0gSWYgdHJ1ZSwgcmV0dXJucyBTSEExIGhhc2g7IGlmIGZhbHNlLCByZXR1cm5zIEpTT05cbiAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nPn0gW2lnbm9yZWRfa2V5cz1udWxsXSAtIEtleXMgdG8gaWdub3JlIHdoZW4gaGFzaGluZyBvYmplY3RzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTSEExIGhhc2ggb3IgSlNPTiBzdHJpbmcgb2YgdGhlIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIGhhc2godGhlX3ZhciwgY2FsY19zaGExID0gdHJ1ZSwgaWdub3JlZF9rZXlzID0gbnVsbCkge1xuICAgIGlmICh0eXBlb2YgdGhlX3ZhciA9PSB1bmRlZikge1xuICAgICAgICB0aGVfdmFyID0gJ19fdW5kZWZpbmVkX18nO1xuICAgIH1cblxuICAgIGlmIChpZ25vcmVkX2tleXMgPT09IG51bGwpIHtcbiAgICAgICAgaWdub3JlZF9rZXlzID0gWyckJ107XG4gICAgfVxuXG4gICAgLy8gQ29udmVydHMgdmFsdWUgdG8ganNvbiwgZGlzY2FyZGluZyBjaXJjdWxhciByZWZlcmVuY2VzXG4gICAgbGV0IGpzb25fc3RyaW5naWZ5X25vY2lyYyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBjb25zdCBjYWNoZSA9IFtdO1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUsIGZ1bmN0aW9uIChrZXksIHYpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHRoZV92YXIuX2NhY2hlX2tleSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoZV92YXIuX2hhc2hfa2V5KCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2ID09PSAnb2JqZWN0JyAmJiB2ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNhY2hlLmluZGV4T2YodikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIER1cGxpY2F0ZSByZWZlcmVuY2UgZm91bmQsIGRpc2NhcmQga2V5XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FjaGUucHVzaCh2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLy8gVHVybiBldmVyeSBwcm9wZXJ0eSBhbmQgYWxsIGl0cyBjaGlsZHJlbiBpbnRvIGEgc2luZ2xlIGRlcHRoIGFycmF5IG9mIHZhbHVlcyB0aGF0IHdlIGNhbiB0aGVuXG4gICAgLy8gc29ydCBhbmQgaGFzaCBhcyBhIHdob2xlXG4gICAgbGV0IGZsYXRfdmFyID0ge307XG4gICAgbGV0IF9mbGF0dGVuID0gZnVuY3Rpb24gKHRoZV92YXIsIHByZWZpeCwgZGVwdGggPSAwKSB7XG4gICAgICAgIC8vIElmIGEgY2xhc3Mgb2JqZWN0IGlzIHByb3ZpZGVkLCBjaXJjdWxhciByZWZlcmVuY2VzIGNhbiBtYWtlIHRoZSBjYWxsIHN0YWNrIHJlY3Vyc2l2ZS5cbiAgICAgICAgLy8gRm9yIHRoZSBwdXJwb3NlcyBvZiBob3cgdGhlIGhhc2ggZnVuY3Rpb24gaXMgY2FsbGVkLCB0aGlzIHNob3VsZCBiZSBzdWZmaWNpZW50LlxuICAgICAgICBpZiAoZGVwdGggPiAxMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRG9lcyBub3QgYWNjb3VudCBmb3IgZGF0ZXMgaSB0aGluay4uLlxuXG4gICAgICAgIGlmIChpc19vYmplY3QodGhlX3ZhcikgJiYgdHlwZW9mIHRoZV92YXIuX2NhY2hlX2tleSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBVc2UgX2NhY2hlX2tleSB0byBoYXNoIGNvbXBvbmVudHNcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSB0aGVfdmFyLl9oYXNoX2tleSgpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzX29iamVjdCh0aGVfdmFyKSAmJiB0eXBlb2YgQWJzdHJhY3QgIT09ICd1bmRlZmluZWQnICYmIHRoZV92YXIgaW5zdGFuY2VvZiBBYnN0cmFjdCkge1xuICAgICAgICAgICAgLy8gU3RyaW5naWZ5IGFsbCBjbGFzcyBvYmplY3RzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0ganNvbl9zdHJpbmdpZnlfbm9jaXJjKHRoZV92YXIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzX29iamVjdCh0aGVfdmFyKSkge1xuICAgICAgICAgICAgLy8gSXRlcmF0ZSBvdGhlciBvYmplY3RzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0ge307XG4gICAgICAgICAgICBmb3IgKGxldCBrIGluIHRoZV92YXIpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhlX3Zhci5oYXNPd25Qcm9wZXJ0eShrKSAmJiBpZ25vcmVkX2tleXMuaW5kZXhPZihrKSA9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBfZmxhdHRlbih0aGVfdmFyW2tdLCBwcmVmaXggKyAnLi4nICsgaywgZGVwdGggKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaXNfYXJyYXkodGhlX3ZhcikpIHtcbiAgICAgICAgICAgIC8vIEl0ZXJhdGUgYXJyYXlzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0gW107XG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICBmb3JlYWNoKHRoZV92YXIsICh2KSA9PiB7XG4gICAgICAgICAgICAgICAgX2ZsYXR0ZW4odiwgcHJlZml4ICsgJy4uJyArIGksIGRlcHRoICsgMSk7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNfZnVuY3Rpb24odGhlX3ZhcikpIHtcbiAgICAgICAgICAgIC8vIG5vdGhpbmdcbiAgICAgICAgfSBlbHNlIGlmICghaXNfbnVtZXJpYyh0aGVfdmFyKSkge1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IFN0cmluZyh0aGVfdmFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSB0aGVfdmFyO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIF9mbGF0dGVuKHRoZV92YXIsICdfJyk7XG5cbiAgICBsZXQgc29ydGVyID0gW107XG5cbiAgICBmb3JlYWNoKGZsYXRfdmFyLCBmdW5jdGlvbiAodiwgaykge1xuICAgICAgICBzb3J0ZXIucHVzaChbaywgdl0pO1xuICAgIH0pO1xuXG4gICAgc29ydGVyLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGFbMF0gPiBiWzBdO1xuICAgIH0pO1xuXG4gICAgbGV0IGpzb24gPSBKU09OLnN0cmluZ2lmeShzb3J0ZXIpO1xuXG4gICAgaWYgKGNhbGNfc2hhMSkge1xuICAgICAgICBsZXQgaGFzaGVkID0gc2hhMS5zaGExKGpzb24pO1xuICAgICAgICByZXR1cm4gaGFzaGVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBqc29uO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZWVwIGNvbXBhcmlzb24gb2YgdHdvIHZhbHVlcyAoaWdub3JlcyBwcm9wZXJ0eSBvcmRlciBhbmQgZnVuY3Rpb25zKVxuICogQHBhcmFtIHsqfSBhIC0gRmlyc3QgdmFsdWUgdG8gY29tcGFyZVxuICogQHBhcmFtIHsqfSBiIC0gU2Vjb25kIHZhbHVlIHRvIGNvbXBhcmVcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlcyBhcmUgZGVlcGx5IGVxdWFsXG4gKi9cbmZ1bmN0aW9uIGRlZXBfZXF1YWwoYSwgYikge1xuICAgIHJldHVybiBoYXNoKGEsIGZhbHNlKSA9PSBoYXNoKGIsIGZhbHNlKTtcbn0iLCIvKipcbiAqIE11dGV4IGRlY29yYXRvciBmb3IgZXhjbHVzaXZlIG1ldGhvZCBleGVjdXRpb25cbiAqXG4gKiBXaXRob3V0IGFyZ3VtZW50czogUGVyLWluc3RhbmNlIGxvY2tpbmcgKGVhY2ggb2JqZWN0IGhhcyBpdHMgb3duIGxvY2sgcGVyIG1ldGhvZClcbiAqICAgQG11dGV4XG4gKiAgIGFzeW5jIG15X21ldGhvZCgpIHsgLi4uIH1cbiAqXG4gKiBXaXRoIElEIGFyZ3VtZW50OiBHbG9iYWwgbG9ja2luZyBieSBJRCAoYWxsIGluc3RhbmNlcyBzaGFyZSB0aGUgbG9jaylcbiAqICAgQG11dGV4KCdvcGVyYXRpb25fbmFtZScpXG4gKiAgIGFzeW5jIG15X21ldGhvZCgpIHsgLi4uIH1cbiAqXG4gKiBAZGVjb3JhdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gW2dsb2JhbF9pZF0gLSBPcHRpb25hbCBnbG9iYWwgbXV0ZXggSUQgZm9yIGNyb3NzLWluc3RhbmNlIGxvY2tpbmdcbiAqL1xuZnVuY3Rpb24gbXV0ZXgoZ2xvYmFsX2lkKSB7XG4gICAgLy8gU3RvcmFnZSAodXNpbmcgSUlGRXMgdG8ga2VlcCBXZWFrTWFwL01hcCBpbiBjbG9zdXJlIHNjb3BlKVxuICAgIGNvbnN0IGluc3RhbmNlX211dGV4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghbXV0ZXguX2luc3RhbmNlX3N0b3JhZ2UpIHtcbiAgICAgICAgICAgIG11dGV4Ll9pbnN0YW5jZV9zdG9yYWdlID0gbmV3IFdlYWtNYXAoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbXV0ZXguX2luc3RhbmNlX3N0b3JhZ2U7XG4gICAgfSkoKTtcblxuICAgIGNvbnN0IGdsb2JhbF9tdXRleGVzID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIW11dGV4Ll9nbG9iYWxfc3RvcmFnZSkge1xuICAgICAgICAgICAgbXV0ZXguX2dsb2JhbF9zdG9yYWdlID0gbmV3IE1hcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtdXRleC5fZ2xvYmFsX3N0b3JhZ2U7XG4gICAgfSkoKTtcblxuICAgIC8qKlxuICAgICAqIEdldCBvciBjcmVhdGUgYSBtdXRleCBmb3IgYSBzcGVjaWZpYyBpbnN0YW5jZSBhbmQgbWV0aG9kXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0X2luc3RhbmNlX211dGV4KGluc3RhbmNlLCBtZXRob2RfbmFtZSkge1xuICAgICAgICBsZXQgaW5zdGFuY2VfbG9ja3MgPSBpbnN0YW5jZV9tdXRleGVzLmdldChpbnN0YW5jZSk7XG4gICAgICAgIGlmICghaW5zdGFuY2VfbG9ja3MpIHtcbiAgICAgICAgICAgIGluc3RhbmNlX2xvY2tzID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgaW5zdGFuY2VfbXV0ZXhlcy5zZXQoaW5zdGFuY2UsIGluc3RhbmNlX2xvY2tzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsb2NrX3N0YXRlID0gaW5zdGFuY2VfbG9ja3MuZ2V0KG1ldGhvZF9uYW1lKTtcbiAgICAgICAgaWYgKCFsb2NrX3N0YXRlKSB7XG4gICAgICAgICAgICBsb2NrX3N0YXRlID0geyBhY3RpdmU6IGZhbHNlLCBxdWV1ZTogW10gfTtcbiAgICAgICAgICAgIGluc3RhbmNlX2xvY2tzLnNldChtZXRob2RfbmFtZSwgbG9ja19zdGF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbG9ja19zdGF0ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgb3IgY3JlYXRlIGEgZ2xvYmFsIG11dGV4IGJ5IElEXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0X2dsb2JhbF9tdXRleChpZCkge1xuICAgICAgICBsZXQgbG9ja19zdGF0ZSA9IGdsb2JhbF9tdXRleGVzLmdldChpZCk7XG4gICAgICAgIGlmICghbG9ja19zdGF0ZSkge1xuICAgICAgICAgICAgbG9ja19zdGF0ZSA9IHsgYWN0aXZlOiBmYWxzZSwgcXVldWU6IFtdIH07XG4gICAgICAgICAgICBnbG9iYWxfbXV0ZXhlcy5zZXQoaWQsIGxvY2tfc3RhdGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2NrX3N0YXRlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGUgdGhlIG5leHQgcXVldWVkIG9wZXJhdGlvbiBmb3IgYSBtdXRleFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNjaGVkdWxlX25leHQobG9ja19zdGF0ZSkge1xuICAgICAgICBpZiAobG9ja19zdGF0ZS5hY3RpdmUgfHwgbG9ja19zdGF0ZS5xdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgZm4sIHJlc29sdmUsIHJlamVjdCB9ID0gbG9ja19zdGF0ZS5xdWV1ZS5zaGlmdCgpO1xuICAgICAgICBsb2NrX3N0YXRlLmFjdGl2ZSA9IHRydWU7XG5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgIC50aGVuKGZuKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KVxuICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvY2tfc3RhdGUuYWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2NoZWR1bGVfbmV4dChsb2NrX3N0YXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFjcXVpcmUgYSBtdXRleCBsb2NrIGFuZCBleGVjdXRlIGNhbGxiYWNrXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWNxdWlyZV9sb2NrKGxvY2tfc3RhdGUsIGZuKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsb2NrX3N0YXRlLnF1ZXVlLnB1c2goeyBmbiwgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgc2NoZWR1bGVfbmV4dChsb2NrX3N0YXRlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gSWYgY2FsbGVkIHdpdGggYW4gSUQgYXJndW1lbnQ6IEBtdXRleCgnaWQnKVxuICAgIGlmICh0eXBlb2YgZ2xvYmFsX2lkID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odGFyZ2V0LCBrZXksIGRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsX21ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3JpZ2luYWxfbWV0aG9kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBAbXV0ZXggY2FuIG9ubHkgYmUgYXBwbGllZCB0byBtZXRob2RzICh0cmllZCB0byBhcHBseSB0byAke2tleX0pYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9ja19zdGF0ZSA9IGdldF9nbG9iYWxfbXV0ZXgoZ2xvYmFsX2lkKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNxdWlyZV9sb2NrKGxvY2tfc3RhdGUsICgpID0+IG9yaWdpbmFsX21ldGhvZC5hcHBseSh0aGlzLCBhcmdzKSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBJZiBjYWxsZWQgd2l0aG91dCBhcmd1bWVudHM6IEBtdXRleCAodGFyZ2V0IGlzIHRoZSBmaXJzdCBhcmd1bWVudClcbiAgICBjb25zdCB0YXJnZXQgPSBnbG9iYWxfaWQ7ICAvLyBJbiB0aGlzIGNhc2UsIGZpcnN0IGFyZyBpcyB0YXJnZXRcbiAgICBjb25zdCBrZXkgPSBhcmd1bWVudHNbMV07XG4gICAgY29uc3QgZGVzY3JpcHRvciA9IGFyZ3VtZW50c1syXTtcblxuICAgIGNvbnN0IG9yaWdpbmFsX21ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG5cbiAgICBpZiAodHlwZW9mIG9yaWdpbmFsX21ldGhvZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEBtdXRleCBjYW4gb25seSBiZSBhcHBsaWVkIHRvIG1ldGhvZHMgKHRyaWVkIHRvIGFwcGx5IHRvICR7a2V5fSlgKTtcbiAgICB9XG5cbiAgICBkZXNjcmlwdG9yLnZhbHVlID0gZnVuY3Rpb24oLi4uYXJncykge1xuICAgICAgICBjb25zdCBsb2NrX3N0YXRlID0gZ2V0X2luc3RhbmNlX211dGV4KHRoaXMsIGtleSk7XG4gICAgICAgIHJldHVybiBhY3F1aXJlX2xvY2sobG9ja19zdGF0ZSwgKCkgPT4gb3JpZ2luYWxfbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRlc2NyaXB0b3I7XG59XG4iLCIvKlxuICogQXN5bmMgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSBhc3luY2hyb25vdXMgb3BlcmF0aW9ucywgZGVsYXlzLCBkZWJvdW5jaW5nLCBhbmQgbXV0ZXhlcy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBBU1lOQyBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBQYXVzZXMgZXhlY3V0aW9uIGZvciBzcGVjaWZpZWQgbWlsbGlzZWNvbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gW21pbGxpc2Vjb25kcz0wXSAtIERlbGF5IGluIG1pbGxpc2Vjb25kcyAoMCB1c2VzIHJlcXVlc3RBbmltYXRpb25GcmFtZSlcbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgZGVsYXlcbiAqIEBleGFtcGxlIGF3YWl0IHNsZWVwKDEwMDApOyAvLyBXYWl0IDEgc2Vjb25kXG4gKi9cbmZ1bmN0aW9uIHNsZWVwKG1pbGxpc2Vjb25kcyA9IDApIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgaWYgKG1pbGxpc2Vjb25kcyA9PSAwICYmIHJlcXVlc3RBbmltYXRpb25GcmFtZSkge1xuICAgICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHJlc29sdmUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0VGltZW91dChyZXNvbHZlLCBtaWxsaXNlY29uZHMpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB3aXRoIGV4Y2x1c2l2aXR5IGFuZCBwcm9taXNlIGZhbi1pblxuICpcbiAqIFRoaXMgZnVuY3Rpb24sIHdoZW4gaW52b2tlZCwgaW1tZWRpYXRlbHkgcnVucyB0aGUgY2FsbGJhY2sgZXhjbHVzaXZlbHkuXG4gKiBGb3Igc3Vic2VxdWVudCBpbnZvY2F0aW9ucywgaXQgYXBwbGllcyBhIGRlbGF5IGJlZm9yZSBydW5uaW5nIHRoZSBjYWxsYmFjayBleGNsdXNpdmVseSBhZ2Fpbi5cbiAqIFRoZSBkZWxheSBzdGFydHMgYWZ0ZXIgdGhlIGN1cnJlbnQgYXN5bmNocm9ub3VzIG9wZXJhdGlvbiByZXNvbHZlcy5cbiAqXG4gKiBJZiAnZGVsYXknIGlzIHNldCB0byAwLCB0aGUgZnVuY3Rpb24gd2lsbCBvbmx5IHByZXZlbnQgZW5xdWV1ZWluZyBtdWx0aXBsZSBleGVjdXRpb25zIG9mIHRoZVxuICogc2FtZSBtZXRob2QgbW9yZSB0aGFuIG9uY2UsIGJ1dCB3aWxsIHN0aWxsIHJ1biB0aGVtIGltbWVkaWF0ZWx5IGluIGFuIGV4Y2x1c2l2ZSBzZXF1ZW50aWFsIG1hbm5lci5cbiAqXG4gKiBUaGUgbW9zdCByZWNlbnQgaW52b2NhdGlvbiBvZiB0aGUgZnVuY3Rpb24gd2lsbCBiZSB0aGUgcGFyYW1ldGVycyB0aGF0IGdldCBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uXG4gKiB3aGVuIGl0IGludm9rZXMuXG4gKlxuICogVGhlIGZ1bmN0aW9uIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbmV4dCBleGNsdXNpdmUgZXhlY3V0aW9uIGNvbXBsZXRlcy5cbiAqXG4gKiBVc2FnZSBhcyBmdW5jdGlvbjpcbiAqICAgY29uc3QgZGVib3VuY2VkRm4gPSBkZWJvdW5jZShteUZ1bmN0aW9uLCAyNTApO1xuICpcbiAqIFVzYWdlIGFzIGRlY29yYXRvcjpcbiAqICAgQGRlYm91bmNlKDI1MClcbiAqICAgbXlNZXRob2QoKSB7IC4uLiB9XG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbnxudW1iZXJ9IGNhbGxiYWNrX29yX2RlbGF5IFRoZSBjYWxsYmFjayBmdW5jdGlvbiBPUiBkZWxheSB3aGVuIHVzZWQgYXMgZGVjb3JhdG9yXG4gKiBAcGFyYW0ge251bWJlcn0gZGVsYXkgVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgc3Vic2VxdWVudCBpbnZvY2F0aW9uc1xuICogQHBhcmFtIHtib29sZWFufSBpbW1lZGlhdGUgaWYgdHJ1ZSwgdGhlIGZpcnN0IHRpbWUgdGhlIGFjdGlvbiBpcyBjYWxsZWQsIHRoZSBjYWxsYmFjayBleGVjdXRlcyBpbW1lZGlhdGVseVxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRoYXQgd2hlbiBpbnZva2VkLCBydW5zIHRoZSBjYWxsYmFjayBpbW1lZGlhdGVseSBhbmQgZXhjbHVzaXZlbHksXG4gKlxuICogQGRlY29yYXRvclxuICovXG5mdW5jdGlvbiBkZWJvdW5jZShjYWxsYmFja19vcl9kZWxheSwgZGVsYXksIGltbWVkaWF0ZSA9IGZhbHNlKSB7XG4gICAgLy8gRGVjb3JhdG9yIHVzYWdlOiBAZGVib3VuY2UoMjUwKSBvciBAZGVib3VuY2UoMjUwLCB0cnVlKVxuICAgIC8vIEZpcnN0IGFyZ3VtZW50IGlzIGEgbnVtYmVyICh0aGUgZGVsYXkpLCByZXR1cm5zIGRlY29yYXRvciBmdW5jdGlvblxuICAgIGlmICh0eXBlb2YgY2FsbGJhY2tfb3JfZGVsYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbnN0IGRlY29yYXRvcl9kZWxheSA9IGNhbGxiYWNrX29yX2RlbGF5O1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JfaW1tZWRpYXRlID0gZGVsYXkgfHwgZmFsc2U7XG5cbiAgICAgICAgLy8gVEMzOSBkZWNvcmF0b3IgZm9ybTogcmVjZWl2ZXMgKHZhbHVlLCBjb250ZXh0KVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBjb250ZXh0KSB7XG4gICAgICAgICAgICBpZiAoY29udGV4dC5raW5kID09PSAnbWV0aG9kJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBkZWJvdW5jZV9pbXBsKHZhbHVlLCBkZWNvcmF0b3JfZGVsYXksIGRlY29yYXRvcl9pbW1lZGlhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZ1bmN0aW9uIHVzYWdlOiBkZWJvdW5jZShmbiwgMjUwKVxuICAgIC8vIEZpcnN0IGFyZ3VtZW50IGlzIGEgZnVuY3Rpb24gKHRoZSBjYWxsYmFjaylcbiAgICBjb25zdCBjYWxsYmFjayA9IGNhbGxiYWNrX29yX2RlbGF5O1xuICAgIHJldHVybiBkZWJvdW5jZV9pbXBsKGNhbGxiYWNrLCBkZWxheSwgaW1tZWRpYXRlKTtcbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiBkZWJvdW5jZSBsb2dpY1xuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2VfaW1wbChjYWxsYmFjaywgZGVsYXksIGltbWVkaWF0ZSA9IGZhbHNlKSB7XG4gICAgbGV0IHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBsZXQgcXVldWVkID0gZmFsc2U7XG4gICAgbGV0IGxhc3RfZW5kX3RpbWUgPSAwOyAvLyB0aW1lc3RhbXAgb2YgbGFzdCBjb21wbGV0ZWQgcnVuXG4gICAgbGV0IHRpbWVyID0gbnVsbDtcblxuICAgIGxldCBuZXh0X2FyZ3MgPSBbXTtcbiAgICBsZXQgbmV4dF9jb250ZXh0ID0gbnVsbDtcbiAgICBsZXQgcmVzb2x2ZV9xdWV1ZSA9IFtdO1xuICAgIGxldCByZWplY3RfcXVldWUgPSBbXTtcblxuICAgIGNvbnN0IHJ1bl9mdW5jdGlvbiA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgdGhlc2VfcmVzb2x2ZXMgPSByZXNvbHZlX3F1ZXVlO1xuICAgICAgICBjb25zdCB0aGVzZV9yZWplY3RzID0gcmVqZWN0X3F1ZXVlO1xuICAgICAgICBjb25zdCBhcmdzID0gbmV4dF9hcmdzO1xuICAgICAgICBjb25zdCBjb250ZXh0ID0gbmV4dF9jb250ZXh0O1xuXG4gICAgICAgIHJlc29sdmVfcXVldWUgPSBbXTtcbiAgICAgICAgcmVqZWN0X3F1ZXVlID0gW107XG4gICAgICAgIG5leHRfYXJncyA9IFtdO1xuICAgICAgICBuZXh0X2NvbnRleHQgPSBudWxsO1xuICAgICAgICBxdWV1ZWQgPSBmYWxzZTtcbiAgICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNhbGxiYWNrLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgZm9yIChjb25zdCByZXNvbHZlIG9mIHRoZXNlX3Jlc29sdmVzKSByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZm9yIChjb25zdCByZWplY3Qgb2YgdGhlc2VfcmVqZWN0cykgcmVqZWN0KGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICBsYXN0X2VuZF90aW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIGlmIChxdWV1ZWQpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICAgICAgICAgIHRpbWVyID0gc2V0VGltZW91dChydW5fZnVuY3Rpb24sIE1hdGgubWF4KGRlbGF5LCAwKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRpbWVyID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbmV4dF9hcmdzID0gYXJncztcbiAgICAgICAgbmV4dF9jb250ZXh0ID0gdGhpcztcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZV9xdWV1ZS5wdXNoKHJlc29sdmUpO1xuICAgICAgICAgICAgcmVqZWN0X3F1ZXVlLnB1c2gocmVqZWN0KTtcblxuICAgICAgICAgICAgLy8gTm90aGluZyBydW5uaW5nIGFuZCBub3RoaW5nIHNjaGVkdWxlZFxuICAgICAgICAgICAgaWYgKCFydW5uaW5nICYmICF0aW1lcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0X2NhbGwgPSBsYXN0X2VuZF90aW1lID09PSAwO1xuXG4gICAgICAgICAgICAgICAgaWYgKGltbWVkaWF0ZSAmJiBmaXJzdF9jYWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bl9mdW5jdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2luY2UgPSBmaXJzdF9jYWxsID8gSW5maW5pdHkgOiBEYXRlLm5vdygpIC0gbGFzdF9lbmRfdGltZTtcbiAgICAgICAgICAgICAgICBpZiAoc2luY2UgPj0gZGVsYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcnVuX2Z1bmN0aW9uKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2FpdCA9IE1hdGgubWF4KGRlbGF5IC0gc2luY2UsIDApO1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICAgICAgICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQocnVuX2Z1bmN0aW9uLCB3YWl0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB3ZSdyZSBhbHJlYWR5IHJ1bm5pbmcgb3IgYSB0aW1lciBleGlzdHMsIGp1c3QgbWFyayBxdWV1ZWQuXG4gICAgICAgICAgICAvLyBUaGUgZmluYWxseXt9IG9mIHJ1bl9mdW5jdGlvbiBoYW5kbGVzIHNjaGVkdWxpbmcgYWZ0ZXIgZnVsbCBkZWxheS5cbiAgICAgICAgICAgIHF1ZXVlZCA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJFQUQtV1JJVEUgTE9DSyBGVU5DVElPTlMgLSBEZWxlZ2F0ZWQgdG8gUmVhZFdyaXRlTG9jayBjbGFzc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEFjcXVpcmUgYW4gZXhjbHVzaXZlIHdyaXRlIGxvY2sgYnkgbmFtZS5cbiAqIE9ubHkgb25lIHdyaXRlciBydW5zIGF0IGEgdGltZTsgYmxvY2tzIHJlYWRlcnMgdW50aWwgZmluaXNoZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHsoKSA9PiBhbnl8UHJvbWlzZTxhbnk+fSBjYlxuICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAqL1xuZnVuY3Rpb24gcndsb2NrKG5hbWUsIGNiKSB7XG4gICAgcmV0dXJuIFJlYWRXcml0ZUxvY2suYWNxdWlyZShuYW1lLCBjYik7XG59XG5cbi8qKlxuICogQWNxdWlyZSBhIHNoYXJlZCByZWFkIGxvY2sgYnkgbmFtZS5cbiAqIE11bHRpcGxlIHJlYWRlcnMgcnVuIGluIHBhcmFsbGVsLCBidXQgcmVhZGVycyBhcmUgYmxvY2tlZCBieSBxdWV1ZWQvYWN0aXZlIHdyaXRlcnMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHsoKSA9PiBhbnl8UHJvbWlzZTxhbnk+fSBjYlxuICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAqL1xuZnVuY3Rpb24gcndsb2NrX3JlYWQobmFtZSwgY2IpIHtcbiAgICByZXR1cm4gUmVhZFdyaXRlTG9jay5hY3F1aXJlX3JlYWQobmFtZSwgY2IpO1xufVxuXG4vKipcbiAqIEZvcmNlZnVsbHkgY2xlYXIgYWxsIGxvY2tzIGFuZCBxdWV1ZXMgZm9yIGEgZ2l2ZW4gbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbmZ1bmN0aW9uIHJ3bG9ja19mb3JjZV91bmxvY2sobmFtZSkge1xuICAgIFJlYWRXcml0ZUxvY2suZm9yY2VfdW5sb2NrKG5hbWUpO1xufVxuXG4vKipcbiAqIEluc3BlY3QgbG9jayBzdGF0ZSBmb3IgZGVidWdnaW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHt7cmVhZGVyczpudW1iZXIsIHdyaXRlcl9hY3RpdmU6Ym9vbGVhbiwgcmVhZGVyX3E6bnVtYmVyLCB3cml0ZXJfcTpudW1iZXJ9fVxuICovXG5mdW5jdGlvbiByd2xvY2tfcGVuZGluZyhuYW1lKSB7XG4gICAgcmV0dXJuIFJlYWRXcml0ZUxvY2sucGVuZGluZyhuYW1lKTtcbn1cbiIsIi8qXG4gKiBDb3JlIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgdHlwZSBjaGVja2luZywgdHlwZSBjb252ZXJzaW9uLCBzdHJpbmcgbWFuaXB1bGF0aW9uLFxuICogYW5kIG9iamVjdC9hcnJheSB1dGlsaXRpZXMuIFRoZXkgbWlycm9yIGZ1bmN0aW9uYWxpdHkgZnJvbSBQSFAgZnVuY3Rpb25zLlxuICpcbiAqIE90aGVyIHV0aWxpdHkgZnVuY3Rpb25zIGFyZSBvcmdhbml6ZWQgaW46XG4gKiAtIGFzeW5jLmpzOiBBc3luYyB1dGlsaXRpZXMgKHNsZWVwLCBkZWJvdW5jZSwgbXV0ZXgpXG4gKiAtIGJyb3dzZXIuanM6IEJyb3dzZXIvRE9NIHV0aWxpdGllcyAoaXNfbW9iaWxlLCBzY3JvbGwgZnVuY3Rpb25zKVxuICogLSBkYXRldGltZS5qczogRGF0ZS90aW1lIHV0aWxpdGllc1xuICogLSBoYXNoLmpzOiBIYXNoaW5nIGFuZCBjb21wYXJpc29uXG4gKiAtIGVycm9yLmpzOiBFcnJvciBoYW5kbGluZ1xuICovXG5cbi8vIFRvZG86IHRlc3QgdGhhdCBwcm9kIGJ1aWxkIGlkZW50aWZpZXMgYW5kIHJlbW92ZXMgdW5jYWxsZWQgZnVuY3Rpb25zIGZyb20gdGhlIGZpbmFsIGJ1bmRsZS5cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ09OU1RBTlRTIEFORCBIRUxQRVJTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8vIERlZmluZSBjb21tb25seSB1c2VkIGNvbnN0YW50c1xuY29uc3QgdW5kZWYgPSAndW5kZWZpbmVkJztcblxuLyoqXG4gKiBJdGVyYXRlcyBvdmVyIGFycmF5cyBvciBvYmplY3RzIHdpdGggcHJvbWlzZSBzdXBwb3J0XG4gKlxuICogV29ya3Mgd2l0aCBib3RoIHN5bmNocm9ub3VzIGFuZCBhc3luY2hyb25vdXMgY2FsbGJhY2tzLiBJZiB0aGUgY2FsbGJhY2tcbiAqIHJldHVybnMgcHJvbWlzZXMsIHRoZXkgYXJlIGV4ZWN1dGVkIGluIHBhcmFsbGVsIGFuZCB0aGlzIGZ1bmN0aW9uIHJldHVybnNcbiAqIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIHBhcmFsbGVsIHRhc2tzIGNvbXBsZXRlLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmogLSBDb2xsZWN0aW9uIHRvIGl0ZXJhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIC0gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCBpdGVtICh2YWx1ZSwga2V5KSAtIGNhbiBiZSBhc3luY1xuICogQHJldHVybnMge1Byb21pc2V8dW5kZWZpbmVkfSBQcm9taXNlIGlmIGFueSBjYWxsYmFja3MgcmV0dXJuIHByb21pc2VzLCB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFN5bmNocm9ub3VzIHVzYWdlXG4gKiBmb3JlYWNoKFsxLDIsM10sICh2YWwpID0+IGNvbnNvbGUubG9nKHZhbCkpO1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBBc3luY2hyb25vdXMgdXNhZ2UgLSB3YWl0cyBmb3IgYWxsIHRvIGNvbXBsZXRlXG4gKiBhd2FpdCBmb3JlYWNoKFsxLDIsM10sIGFzeW5jICh2YWwpID0+IHtcbiAqICAgICBhd2FpdCBmZXRjaCgnL2FwaS9wcm9jZXNzLycgKyB2YWwpO1xuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGZvcmVhY2gob2JqLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBbXTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICAgICAgb2JqLmZvckVhY2goKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGNhbGxiYWNrKHZhbHVlLCBpbmRleCkpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKG9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgICAgICBmb3IgKGxldCBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goY2FsbGJhY2sob2JqW2tleV0sIGtleSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmlsdGVyIGZvciBwcm9taXNlc1xuICAgIGNvbnN0IHByb21pc2VzID0gcmVzdWx0cy5maWx0ZXIoKHJlc3VsdCkgPT4gcmVzdWx0ICYmIHR5cGVvZiByZXN1bHQudGhlbiA9PT0gJ2Z1bmN0aW9uJyk7XG5cbiAgICAvLyBJZiB0aGVyZSBhcmUgYW55IHByb21pc2VzLCByZXR1cm4gUHJvbWlzZS5hbGwgdG8gd2FpdCBmb3IgYWxsIHRvIGNvbXBsZXRlXG4gICAgaWYgKHByb21pc2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICB9XG5cbiAgICAvLyBObyBwcm9taXNlcyByZXR1cm5lZCwgc28gd2UncmUgZG9uZVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG59XG5cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRSBDSEVDS0lORyBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBudW1lcmljXG4gKiBAcGFyYW0geyp9IG4gLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGEgZmluaXRlIG51bWJlclxuICovXG5mdW5jdGlvbiBpc19udW1lcmljKG4pIHtcbiAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGEgc3RyaW5nXG4gKiBAcGFyYW0geyp9IHMgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGEgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIGlzX3N0cmluZyhzKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzID09ICdzdHJpbmcnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGFuIGludGVnZXJcbiAqIEBwYXJhbSB7Kn0gbiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYW4gaW50ZWdlclxuICovXG5mdW5jdGlvbiBpc19pbnRlZ2VyKG4pIHtcbiAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihuKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIHByb21pc2UtbGlrZSBvYmplY3RcbiAqIEBwYXJhbSB7Kn0gb2JqIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBoYXMgYSB0aGVuIG1ldGhvZFxuICovXG5mdW5jdGlvbiBpc19wcm9taXNlKG9iaikge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqID09ICdvYmplY3QnICYmIHR5cGVvZiBvYmoudGhlbiA9PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGFuIGFycmF5XG4gKiBAcGFyYW0geyp9IG9iaiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYW4gYXJyYXlcbiAqL1xuZnVuY3Rpb24gaXNfYXJyYXkob2JqKSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkob2JqKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhbiBvYmplY3QgKGV4Y2x1ZGVzIG51bGwpXG4gKiBAcGFyYW0geyp9IG9iaiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYW4gb2JqZWN0IGFuZCBub3QgbnVsbFxuICovXG5mdW5jdGlvbiBpc19vYmplY3Qob2JqKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIG9iaiAhPT0gbnVsbDtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIGZ1bmN0aW9uXG4gKiBAcGFyYW0geyp9IGZ1bmN0aW9uX3RvX2NoZWNrIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIGZ1bmN0aW9uXG4gKi9cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uKGZ1bmN0aW9uX3RvX2NoZWNrKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uX3RvX2NoZWNrICYmIHt9LnRvU3RyaW5nLmNhbGwoZnVuY3Rpb25fdG9fY2hlY2spID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHN0cmluZyBpcyBhIHZhbGlkIGVtYWlsIGFkZHJlc3NcbiAqIFVzZXMgYSBwcmFjdGljYWwgUkZDIDUzMjIgY29tcGxpYW50IHJlZ2V4IHRoYXQgbWF0Y2hlcyA5OS45OSUgb2YgcmVhbC13b3JsZCBlbWFpbCBhZGRyZXNzZXNcbiAqIEBwYXJhbSB7c3RyaW5nfSBlbWFpbCAtIEVtYWlsIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBlbWFpbCBhZGRyZXNzXG4gKi9cbmZ1bmN0aW9uIGlzX2VtYWlsKGVtYWlsKSB7XG4gICAgaWYgKCFpc19zdHJpbmcoZW1haWwpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgcmVnZXggPSAvXlthLXowLTkhIyQlJicqKy89P15fYHt8fX4tXSsoPzpcXC5bYS16MC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKSpAKD86W2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pP1xcLikrW2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pPyQvaTtcbiAgICByZXR1cm4gcmVnZXgudGVzdChlbWFpbCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgZGVmaW5lZCAobm90IHVuZGVmaW5lZClcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgbm90IHVuZGVmaW5lZFxuICovXG5mdW5jdGlvbiBpc3NldCh2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgIT0gdW5kZWY7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgZW1wdHkgKG51bGwsIHVuZGVmaW5lZCwgMCwgXCJcIiwgZW1wdHkgYXJyYXkvb2JqZWN0KVxuICogQHBhcmFtIHsqfSBvYmplY3QgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGNvbnNpZGVyZWQgZW1wdHlcbiAqL1xuZnVuY3Rpb24gZW1wdHkob2JqZWN0KSB7XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gdW5kZWYpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChvYmplY3QgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09ICdzdHJpbmcnICYmIG9iamVjdCA9PSAnJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PSAwO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiAhb2JqZWN0Lmxlbmd0aDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgaWYgKG9iamVjdC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRZUEUgQ09OVkVSU0lPTiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHZhbHVlIHRvIGEgZmxvYXRpbmcgcG9pbnQgbnVtYmVyXG4gKiBSZXR1cm5zIDAgZm9yIG51bGwsIHVuZGVmaW5lZCwgTmFOLCBvciBub24tbnVtZXJpYyB2YWx1ZXNcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMge251bWJlcn0gRmxvYXRpbmcgcG9pbnQgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGZsb2F0KHZhbCkge1xuICAgIC8vIEhhbmRsZSBudWxsLCB1bmRlZmluZWQsIGVtcHR5IHN0cmluZ1xuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQgfHwgdmFsID09PSAnJykge1xuICAgICAgICByZXR1cm4gMC4wO1xuICAgIH1cblxuICAgIC8vIFRyeSB0byBwYXJzZSB0aGUgdmFsdWVcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUZsb2F0KHZhbCk7XG5cbiAgICAvLyBDaGVjayBmb3IgTmFOIGFuZCByZXR1cm4gMCBpZiBwYXJzaW5nIGZhaWxlZFxuICAgIHJldHVybiBpc05hTihwYXJzZWQpID8gMC4wIDogcGFyc2VkO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgdmFsdWUgdG8gYW4gaW50ZWdlclxuICogUmV0dXJucyAwIGZvciBudWxsLCB1bmRlZmluZWQsIE5hTiwgb3Igbm9uLW51bWVyaWMgdmFsdWVzXG4gKiBAcGFyYW0geyp9IHZhbCAtIFZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IEludGVnZXIgdmFsdWVcbiAqL1xuZnVuY3Rpb24gaW50KHZhbCkge1xuICAgIC8vIEhhbmRsZSBudWxsLCB1bmRlZmluZWQsIGVtcHR5IHN0cmluZ1xuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQgfHwgdmFsID09PSAnJykge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gcGFyc2UgdGhlIHZhbHVlXG4gICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnQodmFsLCAxMCk7XG5cbiAgICAvLyBDaGVjayBmb3IgTmFOIGFuZCByZXR1cm4gMCBpZiBwYXJzaW5nIGZhaWxlZFxuICAgIHJldHVybiBpc05hTihwYXJzZWQpID8gMCA6IHBhcnNlZDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHZhbHVlIHRvIGEgc3RyaW5nXG4gKiBSZXR1cm5zIGVtcHR5IHN0cmluZyBmb3IgbnVsbCBvciB1bmRlZmluZWRcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gKi9cbmZ1bmN0aW9uIHN0cih2YWwpIHtcbiAgICAvLyBIYW5kbGUgbnVsbCBhbmQgdW5kZWZpbmVkIHNwZWNpYWxseVxuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIC8vIENvbnZlcnQgdG8gc3RyaW5nXG4gICAgcmV0dXJuIFN0cmluZyh2YWwpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIG51bWVyaWMgc3RyaW5ncyB0byBudW1iZXJzLCByZXR1cm5zIGFsbCBvdGhlciB2YWx1ZXMgdW5jaGFuZ2VkXG4gKiBVc2VkIHdoZW4geW91IG5lZWQgdG8gZW5zdXJlIG51bWVyaWMgdHlwZXMgYnV0IGRvbid0IHdhbnQgdG8gZm9yY2VcbiAqIGNvbnZlcnNpb24gb2Ygbm9uLW51bWVyaWMgdmFsdWVzICh3aGljaCB3b3VsZCBiZWNvbWUgMClcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMgeyp9IE51bWJlciBpZiBpbnB1dCB3YXMgbnVtZXJpYyBzdHJpbmcsIG90aGVyd2lzZSB1bmNoYW5nZWRcbiAqL1xuZnVuY3Rpb24gdmFsdWVfdW5sZXNzX251bWVyaWNfc3RyaW5nX3RoZW5fbnVtZXJpY192YWx1ZSh2YWwpIHtcbiAgICAvLyBJZiBpdCdzIGFscmVhZHkgYSBudW1iZXIsIHJldHVybiBpdFxuICAgIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH1cblxuICAgIC8vIElmIGl0J3MgYSBzdHJpbmcgYW5kIG51bWVyaWMsIGNvbnZlcnQgaXRcbiAgICBpZiAoaXNfc3RyaW5nKHZhbCkgJiYgaXNfbnVtZXJpYyh2YWwpKSB7XG4gICAgICAgIC8vIFVzZSBwYXJzZUZsb2F0IHRvIGhhbmRsZSBib3RoIGludGVnZXJzIGFuZCBmbG9hdHNcbiAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXQodmFsKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm4gZXZlcnl0aGluZyBlbHNlIHVuY2hhbmdlZCAobnVsbCwgb2JqZWN0cywgbm9uLW51bWVyaWMgc3RyaW5ncywgZXRjLilcbiAgICByZXR1cm4gdmFsO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBTVFJJTkcgTUFOSVBVTEFUSU9OIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEVzY2FwZXMgSFRNTCBzcGVjaWFsIGNoYXJhY3RlcnMgKHVzZXMgTG9kYXNoIGVzY2FwZSlcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gZXNjYXBlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBIVE1MLWVzY2FwZWQgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIGh0bWwoc3RyKSB7XG4gICAgcmV0dXJuIF8uZXNjYXBlKHN0cik7XG59XG5cbi8qKlxuICogQ29udmVydHMgbmV3bGluZXMgdG8gSFRNTCBsaW5lIGJyZWFrc1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgd2l0aCBuZXdsaW5lcyByZXBsYWNlZCBieSA8YnIgLz5cbiAqL1xuZnVuY3Rpb24gbmwyYnIoc3RyKSB7XG4gICAgaWYgKHR5cGVvZiBzdHIgPT09IHVuZGVmIHx8IHN0ciA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiAoc3RyICsgJycpLnJlcGxhY2UoLyhbXj5cXHJcXG5dPykoXFxyXFxufFxcblxccnxcXHJ8XFxuKS9nLCAnJDE8YnIgLz4kMicpO1xufVxuXG4vKipcbiAqIEVzY2FwZXMgSFRNTCBhbmQgY29udmVydHMgbmV3bGluZXMgdG8gPGJyIC8+XG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gU3RyaW5nIHRvIHByb2Nlc3NcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEhUTUwtZXNjYXBlZCBzdHJpbmcgd2l0aCBsaW5lIGJyZWFrc1xuICovXG5mdW5jdGlvbiBodG1sYnIoc3RyKSB7XG4gICAgcmV0dXJuIG5sMmJyKGh0bWwoc3RyKSk7XG59XG5cbi8qKlxuICogVVJMLWVuY29kZXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gZW5jb2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBVUkwtZW5jb2RlZCBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gdXJsZW5jb2RlKHN0cikge1xuICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoc3RyKTtcbn1cblxuLyoqXG4gKiBVUkwtZGVjb2RlcyBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBkZWNvZGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFVSTC1kZWNvZGVkIHN0cmluZ1xuICovXG5mdW5jdGlvbiB1cmxkZWNvZGUoc3RyKSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzdHIpO1xufVxuXG4vKipcbiAqIEpTT04tZW5jb2RlcyBhIHZhbHVlXG4gKiBAcGFyYW0geyp9IHZhbHVlIC0gVmFsdWUgdG8gZW5jb2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBKU09OIHN0cmluZ1xuICovXG5mdW5jdGlvbiBqc29uX2VuY29kZSh2YWx1ZSkge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG59XG5cbi8qKlxuICogSlNPTi1kZWNvZGVzIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gSlNPTiBzdHJpbmcgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyB7Kn0gRGVjb2RlZCB2YWx1ZVxuICovXG5mdW5jdGlvbiBqc29uX2RlY29kZShzdHIpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xufVxuXG4vKipcbiAqIENvbnNvbGUgZGVidWcgb3V0cHV0IHdpdGggY2hhbm5lbCBmaWx0ZXJpbmdcbiAqIEFsaWFzIGZvciBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbCAtIERlYnVnIGNoYW5uZWwgbmFtZVxuICogQHBhcmFtIHsuLi4qfSB2YWx1ZXMgLSBWYWx1ZXMgdG8gbG9nXG4gKi9cbmZ1bmN0aW9uIGNvbnNvbGVfZGVidWcoY2hhbm5lbCwgLi4udmFsdWVzKSB7XG4gICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZyhjaGFubmVsLCAuLi52YWx1ZXMpO1xufVxuXG4vKipcbiAqIFJlcGxhY2VzIGFsbCBvY2N1cnJlbmNlcyBvZiBhIHN1YnN0cmluZyBpbiBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyAtIFN0cmluZyB0byBzZWFyY2ggaW5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWFyY2ggLSBTdWJzdHJpbmcgdG8gZmluZFxuICogQHBhcmFtIHtzdHJpbmd9IHJlcGxhY2UgLSBSZXBsYWNlbWVudCBzdWJzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFN0cmluZyB3aXRoIGFsbCBvY2N1cnJlbmNlcyByZXBsYWNlZFxuICovXG5mdW5jdGlvbiByZXBsYWNlX2FsbChzdHJpbmcsIHNlYXJjaCwgcmVwbGFjZSkge1xuICAgIGlmICghaXNfc3RyaW5nKHN0cmluZykpIHtcbiAgICAgICAgc3RyaW5nID0gc3RyaW5nICsgJyc7XG4gICAgfVxuICAgIHJldHVybiBzdHJpbmcuc3BsaXQoc2VhcmNoKS5qb2luKHJlcGxhY2UpO1xufVxuXG4vKipcbiAqIENhcGl0YWxpemVzIHRoZSBmaXJzdCBsZXR0ZXIgb2YgZWFjaCB3b3JkXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQgLSBTdHJpbmcgdG8gY2FwaXRhbGl6ZVxuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHdpdGggZmlyc3QgbGV0dGVyIG9mIGVhY2ggd29yZCBjYXBpdGFsaXplZFxuICovXG5mdW5jdGlvbiB1Y3dvcmRzKGlucHV0KSB7XG4gICAgcmV0dXJuIGlucHV0XG4gICAgICAgIC5zcGxpdCgnICcpXG4gICAgICAgIC5tYXAoKHdvcmQpID0+IHdvcmQuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyB3b3JkLnNsaWNlKDEpKVxuICAgICAgICAuam9pbignICcpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBPQkpFQ1QgQU5EIEFSUkFZIFVUSUxJVElFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENvdW50cyB0aGUgbnVtYmVyIG9mIHByb3BlcnRpZXMgaW4gYW4gb2JqZWN0IG9yIGVsZW1lbnRzIGluIGFuIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdHxBcnJheX0gbyAtIE9iamVjdCBvciBhcnJheSB0byBjb3VudFxuICogQHJldHVybnMge251bWJlcn0gTnVtYmVyIG9mIG93biBwcm9wZXJ0aWVzL2VsZW1lbnRzXG4gKi9cbmZ1bmN0aW9uIGNvdW50KG8pIHtcbiAgICBsZXQgYyA9IDA7XG4gICAgZm9yIChjb25zdCBrIGluIG8pIHtcbiAgICAgICAgaWYgKG8uaGFzT3duUHJvcGVydHkoaykpIHtcbiAgICAgICAgICAgICsrYztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc2hhbGxvdyBjbG9uZSBvZiBhbiBvYmplY3QsIGFycmF5LCBvciBmdW5jdGlvblxuICogQHBhcmFtIHsqfSBvYmogLSBWYWx1ZSB0byBjbG9uZVxuICogQHJldHVybnMgeyp9IENsb25lZCB2YWx1ZVxuICovXG5mdW5jdGlvbiBjbG9uZShvYmopIHtcbiAgICBpZiAodHlwZW9mIEZ1bmN0aW9uLnByb3RvdHlwZS5fX2Nsb25lID09IHVuZGVmKSB7XG4gICAgICAgIEZ1bmN0aW9uLnByb3RvdHlwZS5fX2Nsb25lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy9odHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xODMzNTg4L2phdmFzY3JpcHQtY2xvbmUtYS1mdW5jdGlvblxuICAgICAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICBsZXQgdGVtcCA9IGZ1bmN0aW9uIGNsb25lZCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiB0aGlzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB0ZW1wW2tleV0gPSB0aGlzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRlbXA7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvYmogPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gb2JqLl9fY2xvbmUoKTtcbiAgICB9IGVsc2UgaWYgKG9iai5jb25zdHJ1Y3RvciAmJiBvYmouY29uc3RydWN0b3IgPT0gQXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIG9iai5zbGljZSgwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83MjgzNjAvaG93LWRvLWktY29ycmVjdGx5LWNsb25lLWEtamF2YXNjcmlwdC1vYmplY3QvMzAwNDI5NDgjMzAwNDI5NDhcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIG9iaik7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IG5vbi1udWxsL3VuZGVmaW5lZCB2YWx1ZSBmcm9tIGFyZ3VtZW50c1xuICogQHBhcmFtIHsuLi4qfSBhcmd1bWVudHMgLSBWYWx1ZXMgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHsqfSBGaXJzdCBub24tbnVsbC91bmRlZmluZWQgdmFsdWUsIG9yIG51bGwgaWYgbm9uZSBmb3VuZFxuICovXG5mdW5jdGlvbiBjb2FsZXNjZSgpIHtcbiAgICBsZXQgYXJncyA9IEFycmF5LmZyb20oYXJndW1lbnRzKTtcbiAgICBsZXQgcmV0dXJuX3ZhbCA9IG51bGw7XG4gICAgYXJncy5mb3JFYWNoKGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgaWYgKHJldHVybl92YWwgPT09IG51bGwgJiYgdHlwZW9mIGFyZyAhPSB1bmRlZiAmJiBhcmcgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybl92YWwgPSBhcmc7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmV0dXJuX3ZhbDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBDU1Ygc3RyaW5nIHRvIGFycmF5LCB0cmltbWluZyBlYWNoIGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJfY3N2IC0gQ1NWIHN0cmluZyB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gQXJyYXkgb2YgdHJpbW1lZCB2YWx1ZXNcbiAqIEB0b2RvIEhhbmRsZSBxdW90ZWQvZXNjYXBlZCBjaGFyYWN0ZXJzXG4gKi9cbmZ1bmN0aW9uIGNzdl90b19hcnJheV90cmltKHN0cl9jc3YpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHN0cl9jc3Yuc3BsaXQoJywnKTtcbiAgICBjb25zdCByZXQgPSBbXTtcbiAgICBmb3JlYWNoKHBhcnRzLCAocGFydCkgPT4ge1xuICAgICAgICByZXQucHVzaChwYXJ0LnRyaW0oKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJldDtcbn1cbiIsIi8qKlxuICogTWFuaWZlc3QgLSBKYXZhU2NyaXB0IGNsYXNzIHJlZ2lzdHJ5IGFuZCBtZXRhZGF0YSBzeXN0ZW1cbiAqXG4gKiBUaGlzIGNsYXNzIG1haW50YWlucyBhIHJlZ2lzdHJ5IG9mIGFsbCBKYXZhU2NyaXB0IGNsYXNzZXMgaW4gdGhlIGJ1bmRsZSxcbiAqIHRyYWNraW5nIHRoZWlyIG5hbWVzIGFuZCBpbmhlcml0YW5jZSByZWxhdGlvbnNoaXBzLiBJdCBwcm92aWRlcyB1dGlsaXRpZXNcbiAqIGZvciB3b3JraW5nIHdpdGggY2xhc3MgaGllcmFyY2hpZXMgYW5kIGNhbGxpbmcgaW5pdGlhbGl6YXRpb24gbWV0aG9kcy5cbiAqL1xuY2xhc3MgTWFuaWZlc3Qge1xuICAgIC8qKlxuICAgICAqIERlZmluZSBjbGFzc2VzIGluIHRoZSBtYW5pZmVzdCAoZnJhbWV3b3JrIGludGVybmFsKVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGl0ZW1zIC0gQXJyYXkgb2YgY2xhc3MgZGVmaW5pdGlvbnMgW1tDbGFzcywgXCJDbGFzc05hbWVcIiwgUGFyZW50Q2xhc3MsIGRlY29yYXRvcnNdLCAuLi5dXG4gICAgICovXG4gICAgc3RhdGljIF9kZWZpbmUoaXRlbXMpIHtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgY2xhc3NlcyBvYmplY3QgaWYgbm90IGFscmVhZHkgZGVmaW5lZFxuICAgICAgICBpZiAodHlwZW9mIE1hbmlmZXN0Ll9jbGFzc2VzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgTWFuaWZlc3QuX2NsYXNzZXMgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByb2Nlc3MgZWFjaCBjbGFzcyBkZWZpbml0aW9uXG4gICAgICAgIGl0ZW1zLmZvckVhY2goKGl0ZW0pID0+IHtcbiAgICAgICAgICAgIGxldCBjbGFzc19vYmplY3QgPSBpdGVtWzBdO1xuICAgICAgICAgICAgbGV0IGNsYXNzX25hbWUgPSBpdGVtWzFdO1xuICAgICAgICAgICAgbGV0IGNsYXNzX2V4dGVuZHMgPSBpdGVtWzJdIHx8IG51bGw7XG4gICAgICAgICAgICBsZXQgZGVjb3JhdG9ycyA9IGl0ZW1bM10gfHwgbnVsbDtcblxuICAgICAgICAgICAgLy8gU3RvcmUgdGhlIGNsYXNzIGluZm9ybWF0aW9uICh1c2luZyBvYmplY3QgdG8gYXZvaWQgZHVwbGljYXRlcylcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdID0ge1xuICAgICAgICAgICAgICAgIGNsYXNzOiBjbGFzc19vYmplY3QsXG4gICAgICAgICAgICAgICAgbmFtZTogY2xhc3NfbmFtZSxcbiAgICAgICAgICAgICAgICBleHRlbmRzOiBjbGFzc19leHRlbmRzLFxuICAgICAgICAgICAgICAgIGRlY29yYXRvcnM6IGRlY29yYXRvcnMsICAvLyBTdG9yZSBjb21wYWN0IGRlY29yYXRvciBkYXRhXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBBZGQgbWV0YWRhdGEgdG8gdGhlIGNsYXNzIG9iamVjdCBpdHNlbGZcbiAgICAgICAgICAgIGNsYXNzX29iamVjdC5fbmFtZSA9IGNsYXNzX25hbWU7XG4gICAgICAgICAgICBjbGFzc19vYmplY3QuX2V4dGVuZHMgPSBjbGFzc19leHRlbmRzO1xuICAgICAgICAgICAgY2xhc3Nfb2JqZWN0Ll9kZWNvcmF0b3JzID0gZGVjb3JhdG9ycztcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQnVpbGQgdGhlIHN1YmNsYXNzIGluZGV4IGFmdGVyIGFsbCBjbGFzc2VzIGFyZSBkZWZpbmVkXG4gICAgICAgIE1hbmlmZXN0Ll9idWlsZF9zdWJjbGFzc19pbmRleCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJ1aWxkIGFuIGluZGV4IG9mIHN1YmNsYXNzZXMgZm9yIGVmZmljaWVudCBsb29rdXBzXG4gICAgICogVGhpcyBjcmVhdGVzIGEgbWFwcGluZyB3aGVyZSBlYWNoIGNsYXNzIG5hbWUgcG9pbnRzIHRvIGFuIGFycmF5IG9mIGFsbCBpdHMgc3ViY2xhc3Nlc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9idWlsZF9zdWJjbGFzc19pbmRleCgpIHtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgc3ViY2xhc3MgaW5kZXhcbiAgICAgICAgTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4ID0ge307XG5cbiAgICAgICAgLy8gU3RlcCB0aHJvdWdoIGVhY2ggY2xhc3MgYW5kIHdhbGsgdXAgaXRzIHBhcmVudCBjaGFpblxuICAgICAgICBmb3IgKGxldCBjbGFzc19uYW1lIGluIE1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50X2NsYXNzX25hbWUgPSBjbGFzc19uYW1lO1xuICAgICAgICAgICAgbGV0IGN1cnJlbnRfY2xhc3NkYXRhID0gY2xhc3NkYXRhO1xuXG4gICAgICAgICAgICAvLyBXYWxrIHVwIHRoZSBwYXJlbnQgY2hhaW4gdW50aWwgd2UgcmVhY2ggdGhlIHJvb3RcbiAgICAgICAgICAgIHdoaWxlIChjdXJyZW50X2NsYXNzZGF0YSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV4dGVuZHNfbmFtZSA9IGN1cnJlbnRfY2xhc3NkYXRhLmV4dGVuZHM7XG5cbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5kc19uYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHBhcmVudCdzIHN1YmNsYXNzIGFycmF5IGlmIG5lZWRlZFxuICAgICAgICAgICAgICAgICAgICBpZiAoIU1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQWRkIHRoaXMgY2xhc3MgdG8gaXRzIHBhcmVudCdzIHN1YmNsYXNzIGxpc3RcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXS5pbmNsdWRlcyhjbGFzc19uYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0ucHVzaChjbGFzc19uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1vdmUgdXAgdG8gdGhlIHBhcmVudCdzIG1ldGFkYXRhIChpZiBpdCBleGlzdHMgaW4gbWFuaWZlc3QpXG4gICAgICAgICAgICAgICAgICAgIGlmIChNYW5pZmVzdC5fY2xhc3Nlc1tleHRlbmRzX25hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzZGF0YSA9IE1hbmlmZXN0Ll9jbGFzc2VzW2V4dGVuZHNfbmFtZV07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQYXJlbnQgbm90IGluIG1hbmlmZXN0IChlLmcuLCBuYXRpdmUgSmF2YVNjcmlwdCBjbGFzcyksIHN0b3AgaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzc2RhdGEgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTm8gcGFyZW50LCB3ZSd2ZSByZWFjaGVkIHRoZSByb290XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3NkYXRhID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIGNsYXNzZXMgdGhhdCBleHRlbmQgYSBnaXZlbiBiYXNlIGNsYXNzXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IGJhc2VfY2xhc3MgLSBUaGUgYmFzZSBjbGFzcyAob2JqZWN0IG9yIG5hbWUgc3RyaW5nKSB0byBjaGVjayBmb3JcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIG9iamVjdHMgd2l0aCB7Y2xhc3NfbmFtZSwgY2xhc3Nfb2JqZWN0fSBmb3IgY2xhc3NlcyB0aGF0IGV4dGVuZCB0aGUgYmFzZSBjbGFzc1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfZXh0ZW5kaW5nKGJhc2VfY2xhc3MpIHtcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udmVydCBzdHJpbmcgdG8gY2xhc3Mgb2JqZWN0IGlmIG5lZWRlZFxuICAgICAgICBsZXQgYmFzZV9jbGFzc19vYmplY3QgPSBiYXNlX2NsYXNzO1xuICAgICAgICBpZiAodHlwZW9mIGJhc2VfY2xhc3MgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBiYXNlX2NsYXNzX29iamVjdCA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKGJhc2VfY2xhc3MpO1xuICAgICAgICAgICAgaWYgKCFiYXNlX2NsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQmFzZSBjbGFzcyBub3QgZm91bmQ6ICR7YmFzZV9jbGFzc31gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsYXNzZXMgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBjbGFzc19uYW1lIGluIE1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIGlmIChNYW5pZmVzdC5qc19pc19zdWJjbGFzc19vZihjbGFzc2RhdGEuY2xhc3MsIGJhc2VfY2xhc3Nfb2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGNsYXNzX25hbWU6IGNsYXNzX25hbWUsXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzX29iamVjdDogY2xhc3NkYXRhLmNsYXNzLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gU29ydCBhbHBoYWJldGljYWxseSBieSBjbGFzcyBuYW1lIHRvIGVuc3VyZSBkZXRlcm1pbmlzdGljIGJlaGF2aW9yIGFuZCBwcmV2ZW50IHJhY2UgY29uZGl0aW9uIGJ1Z3NcbiAgICAgICAgY2xhc3Nlcy5zb3J0KChhLCBiKSA9PiBhLmNsYXNzX25hbWUubG9jYWxlQ29tcGFyZShiLmNsYXNzX25hbWUpKTtcblxuICAgICAgICByZXR1cm4gY2xhc3NlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBhIGNsYXNzIGlzIGEgc3ViY2xhc3Mgb2YgYW5vdGhlciBjbGFzc1xuICAgICAqIE1hdGNoZXMgUEhQIE1hbmlmZXN0Ojpqc19pc19zdWJjbGFzc19vZigpIHNpZ25hdHVyZSBhbmQgYmVoYXZpb3JcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gc3ViY2xhc3MgLSBUaGUgY2hpbGQgY2xhc3MgKG9iamVjdCBvciBuYW1lKSB0byBjaGVja1xuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBzdXBlcmNsYXNzIC0gVGhlIHBhcmVudCBjbGFzcyAob2JqZWN0IG9yIG5hbWUpIHRvIGNoZWNrIGFnYWluc3RcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBzdWJjbGFzcyBleHRlbmRzIHN1cGVyY2xhc3MgKGRpcmVjdGx5IG9yIGluZGlyZWN0bHkpXG4gICAgICovXG4gICAgc3RhdGljIGpzX2lzX3N1YmNsYXNzX29mKHN1YmNsYXNzLCBzdXBlcmNsYXNzKSB7XG4gICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIG5hbWVzIHRvIGNsYXNzIG9iamVjdHNcbiAgICAgICAgbGV0IHN1YmNsYXNzX29iamVjdCA9IHN1YmNsYXNzO1xuICAgICAgICBpZiAodHlwZW9mIHN1YmNsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgc3ViY2xhc3Nfb2JqZWN0ID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoc3ViY2xhc3MpO1xuICAgICAgICAgICAgaWYgKCFzdWJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICAvLyBDYW4ndCByZXNvbHZlIHN1YmNsYXNzIC0gcmV0dXJuIGZhbHNlIHBlciBzcGVjXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHN1cGVyY2xhc3Nfb2JqZWN0ID0gc3VwZXJjbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBzdXBlcmNsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgc3VwZXJjbGFzc19vYmplY3QgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShzdXBlcmNsYXNzKTtcbiAgICAgICAgICAgIGlmICghc3VwZXJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICAvLyBDYW4ndCByZXNvbHZlIHN1cGVyY2xhc3MgLSBmYWlsIGxvdWQgcGVyIHNwZWNcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFN1cGVyY2xhc3Mgbm90IGZvdW5kIGluIG1hbmlmZXN0OiAke3N1cGVyY2xhc3N9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDbGFzc2VzIGFyZSBub3Qgc3ViY2xhc3NlcyBvZiB0aGVtc2VsdmVzXG4gICAgICAgIGlmIChzdWJjbGFzc19vYmplY3QgPT09IHN1cGVyY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBXYWxrIHVwIHRoZSBpbmhlcml0YW5jZSBjaGFpblxuICAgICAgICBsZXQgY3VycmVudF9jbGFzcyA9IHN1YmNsYXNzX29iamVjdDtcbiAgICAgICAgd2hpbGUgKGN1cnJlbnRfY2xhc3MpIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50X2NsYXNzID09PSBzdXBlcmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTW92ZSB1cCB0byBwYXJlbnQgY2xhc3NcbiAgICAgICAgICAgIGlmIChjdXJyZW50X2NsYXNzLl9leHRlbmRzKSB7XG4gICAgICAgICAgICAgICAgLy8gX2V4dGVuZHMgbWF5IGJlIGEgc3RyaW5nIG9yIGNsYXNzIHJlZmVyZW5jZVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY3VycmVudF9jbGFzcy5fZXh0ZW5kcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzcyA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKGN1cnJlbnRfY2xhc3MuX2V4dGVuZHMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBjdXJyZW50X2NsYXNzLl9leHRlbmRzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY3VycmVudF9jbGFzcyA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGEgY2xhc3MgYnkgaXRzIG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NfbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBjbGFzc1xuICAgICAqIEByZXR1cm5zIHtDbGFzc3xudWxsfSBUaGUgY2xhc3Mgb2JqZWN0IG9yIG51bGwgaWYgbm90IGZvdW5kXG4gICAgICovXG4gICAgc3RhdGljIGdldF9jbGFzc19ieV9uYW1lKGNsYXNzX25hbWUpIHtcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3NlcyB8fCAhTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV0pIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdLmNsYXNzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgcmVnaXN0ZXJlZCBjbGFzc2VzXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBvYmplY3RzIHdpdGgge2NsYXNzX25hbWUsIGNsYXNzX29iamVjdCwgZXh0ZW5kc31cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2FsbF9jbGFzc2VzKCkge1xuICAgICAgICBpZiAoIU1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHRzID0gW107XG4gICAgICAgIGZvciAobGV0IGNsYXNzX25hbWUgaW4gTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzZGF0YSA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBjbGFzc19uYW1lOiBjbGFzc2RhdGEubmFtZSxcbiAgICAgICAgICAgICAgICBjbGFzc19vYmplY3Q6IGNsYXNzZGF0YS5jbGFzcyxcbiAgICAgICAgICAgICAgICBleHRlbmRzOiBjbGFzc2RhdGEuZXh0ZW5kcyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU29ydCBhbHBoYWJldGljYWxseSBieSBjbGFzcyBuYW1lIHRvIGVuc3VyZSBkZXRlcm1pbmlzdGljIGJlaGF2aW9yIGFuZCBwcmV2ZW50IHJhY2UgY29uZGl0aW9uIGJ1Z3NcbiAgICAgICAgcmVzdWx0cy5zb3J0KChhLCBiKSA9PiBhLmNsYXNzX25hbWUubG9jYWxlQ29tcGFyZShiLmNsYXNzX25hbWUpKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIGJ1aWxkIGtleSBmcm9tIHRoZSBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGJ1aWxkIGtleSBvciBcIk5PQlVJTERcIiBpZiBub3QgYXZhaWxhYmxlXG4gICAgICovXG4gICAgc3RhdGljIGJ1aWxkX2tleSgpIHtcbiAgICAgICAgaWYgKHdpbmRvdy5yc3hhcHAgJiYgd2luZG93LnJzeGFwcC5idWlsZF9rZXkpIHtcbiAgICAgICAgICAgIHJldHVybiB3aW5kb3cucnN4YXBwLmJ1aWxkX2tleTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ05PQlVJTEQnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBkZWNvcmF0b3JzIGZvciBhIHNwZWNpZmljIGNsYXNzIGFuZCBtZXRob2RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xDbGFzc30gY2xhc3NfbmFtZSAtIFRoZSBjbGFzcyBuYW1lIG9yIGNsYXNzIG9iamVjdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RfbmFtZSAtIFRoZSBtZXRob2QgbmFtZVxuICAgICAqIEByZXR1cm5zIHtBcnJheXxudWxsfSBBcnJheSBvZiBkZWNvcmF0b3Igb2JqZWN0cyBvciBudWxsIGlmIG5vbmUgZm91bmRcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2RlY29yYXRvcnMoY2xhc3NfbmFtZSwgbWV0aG9kX25hbWUpIHtcbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgaWYgKHR5cGVvZiBjbGFzc19uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY2xhc3NfbmFtZSA9IGNsYXNzX25hbWUuX25hbWUgfHwgY2xhc3NfbmFtZS5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xhc3NfaW5mbyA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICBpZiAoIWNsYXNzX2luZm8gfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9ycyB8fCAhY2xhc3NfaW5mby5kZWNvcmF0b3JzW21ldGhvZF9uYW1lXSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmFuc2Zvcm0gY29tcGFjdCBmb3JtYXQgdG8gb2JqZWN0IGZvcm1hdFxuICAgICAgICByZXR1cm4gTWFuaWZlc3QuX3RyYW5zZm9ybV9kZWNvcmF0b3JzKGNsYXNzX2luZm8uZGVjb3JhdG9yc1ttZXRob2RfbmFtZV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgbWV0aG9kcyB3aXRoIGRlY29yYXRvcnMgZm9yIGEgY2xhc3NcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xDbGFzc30gY2xhc3NfbmFtZSAtIFRoZSBjbGFzcyBuYW1lIG9yIGNsYXNzIG9iamVjdFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IE9iamVjdCB3aXRoIG1ldGhvZCBuYW1lcyBhcyBrZXlzIGFuZCBkZWNvcmF0b3IgYXJyYXlzIGFzIHZhbHVlc1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfYWxsX2RlY29yYXRvcnMoY2xhc3NfbmFtZSkge1xuICAgICAgICAvLyBDb252ZXJ0IGNsYXNzIG9iamVjdCB0byBuYW1lIGlmIG5lZWRlZFxuICAgICAgICBpZiAodHlwZW9mIGNsYXNzX25hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjbGFzc19uYW1lID0gY2xhc3NfbmFtZS5fbmFtZSB8fCBjbGFzc19uYW1lLm5hbWU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc19pbmZvID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgIGlmICghY2xhc3NfaW5mbyB8fCAhY2xhc3NfaW5mby5kZWNvcmF0b3JzKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmFuc2Zvcm0gYWxsIGRlY29yYXRvcnMgZnJvbSBjb21wYWN0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgIGZvciAobGV0IG1ldGhvZF9uYW1lIGluIGNsYXNzX2luZm8uZGVjb3JhdG9ycykge1xuICAgICAgICAgICAgcmVzdWx0W21ldGhvZF9uYW1lXSA9IE1hbmlmZXN0Ll90cmFuc2Zvcm1fZGVjb3JhdG9ycyhjbGFzc19pbmZvLmRlY29yYXRvcnNbbWV0aG9kX25hbWVdKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRyYW5zZm9ybSBjb21wYWN0IGRlY29yYXRvciBmb3JtYXQgdG8gb2JqZWN0IGZvcm1hdFxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGNvbXBhY3RfZGVjb3JhdG9ycyAtIEFycmF5IG9mIFtuYW1lLCBbYXJnc11dIHR1cGxlc1xuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2YgZGVjb3JhdG9yIG9iamVjdHMgd2l0aCBuYW1lIGFuZCBhcmd1bWVudHMgcHJvcGVydGllc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF90cmFuc2Zvcm1fZGVjb3JhdG9ycyhjb21wYWN0X2RlY29yYXRvcnMpIHtcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGNvbXBhY3RfZGVjb3JhdG9ycykpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjb21wYWN0X2RlY29yYXRvcnMubWFwKGRlY29yYXRvciA9PiB7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShkZWNvcmF0b3IpICYmIGRlY29yYXRvci5sZW5ndGggPj0gMikge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IGRlY29yYXRvclswXSxcbiAgICAgICAgICAgICAgICAgICAgYXJndW1lbnRzOiBkZWNvcmF0b3JbMV0gfHwgW11cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSGFuZGxlIG1hbGZvcm1lZCBkZWNvcmF0b3IgZGF0YVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAndW5rbm93bicsXG4gICAgICAgICAgICAgICAgYXJndW1lbnRzOiBbXVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBtZXRob2QgaGFzIGEgc3BlY2lmaWMgZGVjb3JhdG9yXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kX25hbWUgLSBUaGUgbWV0aG9kIG5hbWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZGVjb3JhdG9yX25hbWUgLSBUaGUgZGVjb3JhdG9yIG5hbWUgdG8gY2hlY2sgZm9yXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIG1ldGhvZCBoYXMgdGhlIGRlY29yYXRvclxuICAgICAqL1xuICAgIHN0YXRpYyBoYXNfZGVjb3JhdG9yKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lLCBkZWNvcmF0b3JfbmFtZSkge1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JzID0gTWFuaWZlc3QuZ2V0X2RlY29yYXRvcnMoY2xhc3NfbmFtZSwgbWV0aG9kX25hbWUpO1xuICAgICAgICBpZiAoIWRlY29yYXRvcnMpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkZWNvcmF0b3JzLnNvbWUoZCA9PiBkLm5hbWUgPT09IGRlY29yYXRvcl9uYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHN1YmNsYXNzZXMgb2YgYSBnaXZlbiBjbGFzcyB1c2luZyB0aGUgcHJlLWJ1aWx0IGluZGV4XG4gICAgICogVGhpcyBpcyB0aGUgSmF2YVNjcmlwdCBlcXVpdmFsZW50IG9mIFBIUCdzIE1hbmlmZXN0Ojpqc19nZXRfc3ViY2xhc3Nlc19vZigpXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IGJhc2VfY2xhc3MgLSBUaGUgYmFzZSBjbGFzcyAob2JqZWN0IG9yIG5hbWUgc3RyaW5nKSB0byBnZXQgc3ViY2xhc3NlcyBvZlxuICAgICAqIEByZXR1cm5zIHtBcnJheTxDbGFzcz59IEFycmF5IG9mIGFjdHVhbCBjbGFzcyBvYmplY3RzIHRoYXQgYXJlIHN1YmNsYXNzZXMgb2YgdGhlIGJhc2UgY2xhc3NcbiAgICAgKi9cbiAgICBzdGF0aWMganNfZ2V0X3N1YmNsYXNzZXNfb2YoYmFzZV9jbGFzcykge1xuICAgICAgICAvLyBJbml0aWFsaXplIGluZGV4IGlmIG5lZWRlZFxuICAgICAgICBpZiAoIU1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleCkge1xuICAgICAgICAgICAgTWFuaWZlc3QuX2J1aWxkX3N1YmNsYXNzX2luZGV4KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb252ZXJ0IGNsYXNzIG9iamVjdCB0byBuYW1lIGlmIG5lZWRlZFxuICAgICAgICBsZXQgYmFzZV9jbGFzc19uYW1lID0gYmFzZV9jbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBiYXNlX2NsYXNzICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgYmFzZV9jbGFzc19uYW1lID0gYmFzZV9jbGFzcy5fbmFtZSB8fCBiYXNlX2NsYXNzLm5hbWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgYmFzZSBjbGFzcyBleGlzdHNcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3Nlc1tiYXNlX2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICAvLyBCYXNlIGNsYXNzIG5vdCBpbiBtYW5pZmVzdCAtIHJldHVybiBlbXB0eSBhcnJheVxuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2V0IHN1YmNsYXNzIG5hbWVzIGZyb20gdGhlIGluZGV4XG4gICAgICAgIGNvbnN0IHN1YmNsYXNzX25hbWVzID0gTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2Jhc2VfY2xhc3NfbmFtZV0gfHwgW107XG5cbiAgICAgICAgLy8gQ29udmVydCBuYW1lcyB0byBhY3R1YWwgY2xhc3Mgb2JqZWN0c1xuICAgICAgICBjb25zdCBzdWJjbGFzc19vYmplY3RzID0gW107XG4gICAgICAgIGZvciAobGV0IHN1YmNsYXNzX25hbWUgb2Ygc3ViY2xhc3NfbmFtZXMpIHtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzZGF0YSA9IE1hbmlmZXN0Ll9jbGFzc2VzW3N1YmNsYXNzX25hbWVdO1xuICAgICAgICAgICAgc3ViY2xhc3Nfb2JqZWN0cy5wdXNoKGNsYXNzZGF0YS5jbGFzcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTb3J0IGJ5IGNsYXNzIG5hbWUgZm9yIGRldGVybWluaXN0aWMgYmVoYXZpb3JcbiAgICAgICAgc3ViY2xhc3Nfb2JqZWN0cy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBuYW1lX2EgPSBhLl9uYW1lIHx8IGEubmFtZTtcbiAgICAgICAgICAgIGNvbnN0IG5hbWVfYiA9IGIuX25hbWUgfHwgYi5uYW1lO1xuICAgICAgICAgICAgcmV0dXJuIG5hbWVfYS5sb2NhbGVDb21wYXJlKG5hbWVfYik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdWJjbGFzc19vYmplY3RzO1xuICAgIH1cbn1cblxuLy8gUlNYIG1hbmlmZXN0IGF1dG9tYXRpY2FsbHkgbWFrZXMgY2xhc3NlcyBnbG9iYWwgLSBubyBtYW51YWwgYXNzaWdubWVudCBuZWVkZWRcbiIsIi8qKlxuICogUnN4X0JlaGF2aW9ycyAtIENvcmUgRnJhbWV3b3JrIFVzZXIgRXhwZXJpZW5jZSBFbmhhbmNlbWVudHNcbiAqXG4gKiBUaGlzIGNsYXNzIHByb3ZpZGVzIGF1dG9tYXRpYyBxdWFsaXR5LW9mLWxpZmUgYmVoYXZpb3JzIHRoYXQgaW1wcm92ZSB0aGUgZGVmYXVsdFxuICogYnJvd3NlciBleHBlcmllbmNlIGZvciBSU1ggYXBwbGljYXRpb25zLiBUaGVzZSBiZWhhdmlvcnMgYXJlIHRyYW5zcGFyZW50IHRvXG4gKiBhcHBsaWNhdGlvbiBkZXZlbG9wZXJzIGFuZCBydW4gYXV0b21hdGljYWxseSBvbiBmcmFtZXdvcmsgaW5pdGlhbGl6YXRpb24uXG4gKlxuICogVGhlc2UgYmVoYXZpb3JzIHVzZSBqUXVlcnkgZXZlbnQgZGVsZWdhdGlvbiB0byBoYW5kbGUgYm90aCBleGlzdGluZyBhbmQgZHluYW1pY2FsbHlcbiAqIGFkZGVkIGNvbnRlbnQuIFRoZXkgYXJlIGltcGxlbWVudGVkIHdpdGggbG93IHByaW9yaXR5IHRvIGFsbG93IGFwcGxpY2F0aW9uIGNvZGUgdG9cbiAqIG92ZXJyaWRlIGRlZmF1bHQgYmVoYXZpb3JzIHdoZW4gbmVlZGVkLlxuICpcbiAqIEBpbnRlcm5hbCBGcmFtZXdvcmsgdXNlIG9ubHkgLSBub3QgcGFydCBvZiBwdWJsaWMgQVBJXG4gKi9cbmNsYXNzIFJzeF9CZWhhdmlvcnMge1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCgpIHtcbiAgICAgICAgUnN4X0JlaGF2aW9ycy5faW5pdF9pZ25vcmVfaW52YWxpZF9hbmNob3JfbGlua3MoKTtcbiAgICAgICAgUnN4X0JlaGF2aW9ycy5fdHJpbV9jb3BpZWRfdGV4dCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIC0gQW5jaG9yIGxpbmsgaGFuZGxpbmc6IFByZXZlbnRzIGJyb2tlbiBcIiNcIiBsaW5rcyBmcm9tIGNhdXNpbmcgcGFnZSBqdW1wcyBvciBVUkwgY2hhbmdlc1xuICAgICAqIC0gSWdub3JlcyBcIiNcIiAoZW1wdHkgaGFzaCkgdG8gcHJldmVudCBzY3JvbGwtdG8tdG9wIGJlaGF2aW9yXG4gICAgICogLSBJZ25vcmVzIFwiI3BsYWNlaG9sZGVyKlwiIGxpbmtzIHVzZWQgYXMgcm91dGUgcGxhY2Vob2xkZXJzIGR1cmluZyBkZXZlbG9wbWVudFxuICAgICAqIC0gVmFsaWRhdGVzIGFuY2hvciB0YXJnZXRzIGV4aXN0IGJlZm9yZSBhbGxvd2luZyBuYXZpZ2F0aW9uXG4gICAgICogLSBQcmVzZXJ2ZXMgbm9ybWFsIGFuY2hvciBiZWhhdmlvciB3aGVuIHRhcmdldHMgZXhpc3RcbiAgICAgKi9cbiAgICBzdGF0aWMgX2luaXRfaWdub3JlX2ludmFsaWRfYW5jaG9yX2xpbmtzKCkge1xuICAgICAgICByZXR1cm47IC8vIGRpc2FibGVkIGZvciBub3cgLSBtYWtlIHRoaXMgaW50byBhIGNvbmZpZ3VyYWJsZSBvcHRpb25cblxuICAgICAgICAvLyBVc2UgZXZlbnQgZGVsZWdhdGlvbiBvbiBkb2N1bWVudCB0byBoYW5kbGUgYWxsIGN1cnJlbnQgYW5kIGZ1dHVyZSBhbmNob3IgY2xpY2tzXG4gICAgICAgIC8vIFVzZSBtb3VzZWRvd24gaW5zdGVhZCBvZiBjbGljayB0byBydW4gYmVmb3JlIG1vc3QgYXBwbGljYXRpb24gaGFuZGxlcnNcbiAgICAgICAgJChkb2N1bWVudCkub24oJ21vdXNlZG93bicsICdhW2hyZWZePVwiI1wiXScsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICBjb25zdCAkbGluayA9ICQodGhpcyk7XG4gICAgICAgICAgICBjb25zdCBocmVmID0gJGxpbmsuYXR0cignaHJlZicpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBhbm90aGVyIGhhbmRsZXIgaGFzIGFscmVhZHkgcHJldmVudGVkIGRlZmF1bHRcbiAgICAgICAgICAgIGlmIChlLmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBbGxvdyBkYXRhLXJzeC1hbGxvdy1oYXNoIGF0dHJpYnV0ZSB0byBieXBhc3MgdGhpcyBiZWhhdmlvclxuICAgICAgICAgICAgaWYgKCRsaW5rLmRhdGEoJ3JzeC1hbGxvdy1oYXNoJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEhhbmRsZSBlbXB0eSBoYXNoIC0gcHJldmVudCBzY3JvbGwgdG8gdG9wXG4gICAgICAgICAgICBpZiAoaHJlZiA9PT0gJyMnKSB7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBIYW5kbGUgcGxhY2Vob2xkZXIgbGlua3MgdXNlZCBkdXJpbmcgZGV2ZWxvcG1lbnRcbiAgICAgICAgICAgIGlmIChocmVmLnN0YXJ0c1dpdGgoJyNwbGFjZWhvbGRlcicpKSB7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIGUuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBGb3Igb3RoZXIgaGFzaCBsaW5rcywgY2hlY2sgaWYgdGFyZ2V0IGV4aXN0c1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0SWQgPSBocmVmLnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgIGlmICh0YXJnZXRJZCkge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGZvciBlbGVtZW50IHdpdGggbWF0Y2hpbmcgSUQgb3IgbmFtZSBhdHRyaWJ1dGVcbiAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXRFeGlzdHMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0YXJnZXRJZCkgIT09IG51bGwgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgW25hbWU9XCIke3RhcmdldElkfVwiXWApICE9PSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKCF0YXJnZXRFeGlzdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGFyZ2V0IGRvZXNuJ3QgZXhpc3QgLSBwcmV2ZW50IG5hdmlnYXRpb25cbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFRhcmdldCBleGlzdHMgLSBhbGxvdyBub3JtYWwgYW5jaG9yIGJlaGF2aW9yXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIC0gQ29weSB0ZXh0IHRyaW1taW5nOiBBdXRvbWF0aWNhbGx5IHJlbW92ZXMgbGVhZGluZy90cmFpbGluZyB3aGl0ZXNwYWNlIGZyb20gY29waWVkIHRleHRcbiAgICAgKiAtIEhvbGQgU2hpZnQgdG8gcHJlc2VydmUgd2hpdGVzcGFjZVxuICAgICAqIC0gU2tpcHMgdHJpbW1pbmcgaW4gY29kZSBibG9ja3MsIHRleHRhcmVhcywgYW5kIGNvbnRlbnRlZGl0YWJsZSBlbGVtZW50c1xuICAgICAqL1xuICAgIHN0YXRpYyBfdHJpbV9jb3BpZWRfdGV4dCgpIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY29weScsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgLy8gRG9uJ3QgdHJpbSBpZiB1c2VyIGlzIGhvbGRpbmcgU2hpZnQgKGFsbG93cyBjb3B5aW5nIHdpdGggd2hpdGVzcGFjZSBpZiBuZWVkZWQpXG4gICAgICAgICAgICBpZiAoZXZlbnQuc2hpZnRLZXkpIHJldHVybjtcblxuICAgICAgICAgICAgbGV0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgIGxldCBzZWxlY3RlZF90ZXh0ID0gc2VsZWN0aW9uLnRvU3RyaW5nKCk7XG5cbiAgICAgICAgICAgIC8vIERvbid0IHRyaW0gaWYgc2VsZWN0aW9uIGlzIGVtcHR5XG4gICAgICAgICAgICBpZiAoIXNlbGVjdGVkX3RleHQpIHJldHVybjtcblxuICAgICAgICAgICAgLy8gRG9uJ3QgdHJpbSBpZiBjb3B5aW5nIGZyb20gY29kZSBibG9ja3MsIHRleHRhcmVhcywgb3IgY29udGVudC1lZGl0YWJsZSAocHJlc2VydmUgZm9ybWF0dGluZylcbiAgICAgICAgICAgIGxldCBjb250YWluZXIgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdCgwKS5jb21tb25BbmNlc3RvckNvbnRhaW5lcjtcbiAgICAgICAgICAgIGlmIChjb250YWluZXIubm9kZVR5cGUgPT09IDMpIGNvbnRhaW5lciA9IGNvbnRhaW5lci5wYXJlbnROb2RlOyAvLyBUZXh0IG5vZGUgdG8gZWxlbWVudFxuICAgICAgICAgICAgaWYgKGNvbnRhaW5lci5jbG9zZXN0KCdwcmUsIGNvZGUsIC5jb2RlLWJsb2NrLCB0ZXh0YXJlYSwgW2NvbnRlbnRlZGl0YWJsZT1cInRydWVcIl0nKSkgcmV0dXJuO1xuXG4gICAgICAgICAgICBsZXQgdHJpbW1lZF90ZXh0ID0gc2VsZWN0ZWRfdGV4dC50cmltKCk7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgbW9kaWZ5IGlmIHRoZXJlJ3MgYWN0dWFsbHkgd2hpdGVzcGFjZSB0byB0cmltXG4gICAgICAgICAgICBpZiAodHJpbW1lZF90ZXh0ICE9PSBzZWxlY3RlZF90ZXh0ICYmIHRyaW1tZWRfdGV4dC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBldmVudC5jbGlwYm9hcmREYXRhLnNldERhdGEoJ3RleHQvcGxhaW4nLCB0cmltbWVkX3RleHQpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdDb3B5OiB0cmltbWVkIHdoaXRlc3BhY2UgZnJvbSBzZWxlY3Rpb24nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufVxuIiwiLy8gU2ltcGxlIGtleSB2YWx1ZSBjYWNoZS4gIENhbiBvbmx5IHN0b3JlIDUwMDAgZW50cmllcywgd2lsbCByZXNldCBhZnRlciA1MDAwIGVudHJpZXMuXG5cbi8vIFRvZG86IGtlZXAgbG9jYWwgY2FjaGUgY29uY2VwdCB0aGUgc2FtZSwgcmVwbGFjZSBnbG9iYWwgY2FjaGUgY29uY2VwdCB3aXRoIHRoZSBub3YgMjAxOSB2ZXJzaW9uIG9mXG4vLyBzZXNzaW9uIGNhY2hlLiAgVXNlIGEgc2Vzc2lvbiBrZXkgJiBidWlsZCBrZXkgdG8gdHJhY2sgY2FjaGUga2V5cyBzbyBjYWNoZWQgdmFsdWVzIG9ubHkgbGFzdCB1bnRpbCB1c2VyIGxvZ3Mgb3V0LlxuLy8gcmV2aWV3IHNlc3Npb24gY29kZSB0byBlbnN1cmUgdGhhdCBzZXNzaW9uIGtleSAqYWx3YXlzKiByb3RhdGVzIG9uIGxvZ291dC4gIE1ha2Ugc2Vzc2lvbiBpZCBhIHByb3RlY3RlZCB2YWx1ZS5cbmNsYXNzIFJzeF9DYWNoZSB7XG4gICAgc3RhdGljIG9uX2NvcmVfZGVmaW5lKCkge1xuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXMgPSB7XG4gICAgICAgICAgICBnbG9iYWw6IHt9LFxuICAgICAgICAgICAgaW5zdGFuY2U6IHt9LFxuICAgICAgICB9O1xuXG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPSAwO1xuICAgIH1cblxuICAgIC8vIEFsaWFzIGZvciBnZXRfaW5zdGFuY2VcbiAgICBzdGF0aWMgZ2V0KGtleSkge1xuICAgICAgICByZXR1cm4gUnN4X0NhY2hlLmdldF9pbnN0YW5jZShrZXkpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgZnJvbSB0aGUgcG9vbCBvZiBjYWNoZWQgZGF0YSBmb3IgdGhpcyAnaW5zdGFuY2UnLiAgQW4gaW5zdGFuY2VcbiAgICAvLyBpbiB0aGlzIGNhc2UgaXMgYSB2aXJ0dWFsIHBhZ2UgbG9hZCAvIG5hdmlnYXRpb24gaW4gdGhlIFNQQS4gIENhbGwgTWFpbi5saWIucmVzZXQoKSB0byByZXNldC5cbiAgICAvLyBSZXR1cm5zIG51bGwgb24gZmFpbHVyZVxuICAgIHN0YXRpYyBnZXRfaW5zdGFuY2Uoa2V5KSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgQ29yZV9DYWNoZS5fY2FjaGVzLmluc3RhbmNlW2tleV9lbmNvZGVkXSAhPSB1bmRlZikge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UoQ29yZV9DYWNoZS5fY2FjaGVzLmluc3RhbmNlW2tleV9lbmNvZGVkXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIG51bGwgb24gZmFpbHVyZVxuICAgIC8vIFJldHVybnMgYSBjYWNoZWQgdmFsdWUgZnJvbSBnbG9iYWwgY2FjaGUgKHVuaXF1ZSB0byBwYWdlIGxvYWQsIHN1cnZpdmVzIHJlc2V0KCkpXG4gICAgc3RhdGljIGdldF9nbG9iYWwoa2V5KSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgQ29yZV9DYWNoZS5fY2FjaGVzLmdsb2JhbFtrZXlfZW5jb2RlZF0gIT0gdW5kZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKENvcmVfQ2FjaGUuX2NhY2hlcy5nbG9iYWxba2V5X2VuY29kZWRdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIFNldHMgYSB2YWx1ZSBpbiBpbnN0YW5jZSBhbmQgZ2xvYmFsIGNhY2hlIChub3Qgc2hhcmVkIGJldHdlZW4gYnJvd3NlciB0YWJzKVxuICAgIHN0YXRpYyBzZXQoa2V5LCB2YWx1ZSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+IDY0ICogMTAyNCkge1xuICAgICAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZygnQ0FDSEUnLCAnV2FybmluZyAtIG5vdCBjYWNoaW5nIGxhcmdlIGNhY2hlIGVudHJ5Jywga2V5KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBrZXlfZW5jb2RlZCA9IFJzeF9DYWNoZS5fZW5jb2Rla2V5KGtleSk7XG5cbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzLmdsb2JhbFtrZXlfZW5jb2RlZF0gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlcy5pbnN0YW5jZVtrZXlfZW5jb2RlZF0gPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG5cbiAgICAgICAgLy8gRGVidWdnZXIuY29uc29sZV9kZWJ1ZyhcIkNBQ0hFXCIsIFwiU2V0XCIsIGtleSwgdmFsdWUpO1xuXG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlc19zZXQrKztcblxuICAgICAgICAvLyBSZXNldCBjYWNoZSBhZnRlciA1MDAwIGl0ZW1zIHNldFxuICAgICAgICBpZiAoQ29yZV9DYWNoZS5fY2FjaGVzX3NldCA+IDUwMDApIHtcbiAgICAgICAgICAgIC8vIEdldCBhbiBhY2N1cmF0ZSBjb3VudFxuICAgICAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzX3NldCA9IGNvdW50KENvcmVfQ2FjaGUuX2NhY2hlcy5nbG9iYWwpO1xuXG4gICAgICAgICAgICBpZiAoQ29yZV9DYWNoZS5fY2FjaGVzX3NldCA+IDUwMDApIHtcbiAgICAgICAgICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGdsb2JhbDoge30sXG4gICAgICAgICAgICAgICAgICAgIGluc3RhbmNlOiB7fSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBudWxsIG9uIGZhaWx1cmVcbiAgICAvLyBSZXR1cm5zIGEgY2FjaGVkIHZhbHVlIGZyb20gc2Vzc2lvbiBjYWNoZSAoc2hhcmVkIGJldHdlZW4gYnJvd3NlciB0YWJzKVxuICAgIHN0YXRpYyBnZXRfc2Vzc2lvbihrZXkpIHtcbiAgICAgICAgaWYgKE1haW4uZGVidWcoJ25vX2FwaV9jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghUnN4X0NhY2hlLl9zdXBwb3J0c1N0b3JhZ2UoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIGxldCBycyA9IHNlc3Npb25TdG9yYWdlLmdldEl0ZW0oa2V5X2VuY29kZWQpO1xuXG4gICAgICAgIGlmICghZW1wdHkocnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShycyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFNldHMgYSB2YWx1ZSBpbiBzZXNzaW9uIGNhY2hlIChzaGFyZWQgYmV0d2VlbiBicm93c2VyIHRhYnMpXG4gICAgc3RhdGljIHNldF9zZXNzaW9uKGtleSwgdmFsdWUsIF90cnlhZ2FpbiA9IHRydWUpIHtcbiAgICAgICAgaWYgKE1haW4uZGVidWcoJ25vX2FwaV9jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUubGVuZ3RoID4gNjQgKiAxMDI0KSB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKCdDQUNIRScsICdXYXJuaW5nIC0gbm90IGNhY2hpbmcgbGFyZ2UgY2FjaGUgZW50cnknLCBrZXkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFSc3hfQ2FjaGUuX3N1cHBvcnRzU3RvcmFnZSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBrZXlfZW5jb2RlZCA9IFJzeF9DYWNoZS5fZW5jb2Rla2V5KGtleSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0oa2V5X2VuY29kZWQpO1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShrZXlfZW5jb2RlZCwgSlNPTi5zdHJpbmdpZnkodmFsdWUpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgaWYgKFJzeF9DYWNoZS5faXNPdXRPZlNwYWNlKGUpICYmIHNlc3Npb25TdG9yYWdlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgaWYgKF90cnlhZ2Fpbikge1xuICAgICAgICAgICAgICAgICAgICBDb3JlX0NhY2hlLnNldF9zZXNzaW9uKGtleSwgdmFsdWUsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzdGF0aWMgX3Jlc2V0KCkge1xuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXMuaW5zdGFuY2UgPSB7fTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3IgZ2l2ZW4ga2V5IG9mIGFueSB0eXBlIGluY2x1ZGluZyBhbiBvYmplY3QsIHJldHVybiBhIHN0cmluZyByZXByZXNlbnRpbmdcbiAgICAgKiB0aGUga2V5IHRoYXQgdGhlIGNhY2hlZCB2YWx1ZSBzaG91bGQgYmUgc3RvcmVkIGFzIGluIHNlc3Npb25zdG9yYWdlXG4gICAgICovXG4gICAgc3RhdGljIF9lbmNvZGVrZXkoa2V5KSB7XG4gICAgICAgIGNvbnN0IHByZWZpeCA9ICdjYWNoZV8nO1xuXG4gICAgICAgIC8vIFNlc3Npb24gcmVpbXBsZW1lbnRcbiAgICAgICAgLy8gdmFyIHByZWZpeCA9IFwiY2FjaGVfXCIgKyBTcGEuc2Vzc2lvbigpLnVzZXJfaWQoKSArIFwiX1wiO1xuXG4gICAgICAgIGlmIChpc19zdHJpbmcoa2V5KSAmJiBrZXkubGVuZ3RoIDwgMTUwICYmIGtleS5pbmRleE9mKCcgJykgPT0gLTEpIHtcbiAgICAgICAgICAgIHJldHVybiBwcmVmaXggKyBNYW5pZmVzdC5idWlsZF9rZXkoKSArICdfJyArIGtleTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBwcmVmaXggKyBoYXNoKFtNYW5pZmVzdC5idWlsZF9rZXkoKSwga2V5XSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEZXRlcm1pbmVzIGlmIHNlc3Npb25TdG9yYWdlIGlzIHN1cHBvcnRlZCBpbiB0aGUgYnJvd3NlcjtcbiAgICAvLyByZXN1bHQgaXMgY2FjaGVkIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UgaW5zdGVhZCBvZiBiZWluZyBydW4gZWFjaCB0aW1lLlxuICAgIC8vIEZlYXR1cmUgZGV0ZWN0aW9uIGlzIGJhc2VkIG9uIGhvdyBNb2Rlcm5penIgZG9lcyBpdDtcbiAgICAvLyBpdCdzIG5vdCBzdHJhaWdodGZvcndhcmQgZHVlIHRvIEZGNCBpc3N1ZXMuXG4gICAgLy8gSXQncyBub3QgcnVuIGF0IHBhcnNlLXRpbWUgYXMgaXQgdGFrZXMgMjAwbXMgaW4gQW5kcm9pZC5cbiAgICAvLyBDb2RlIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL3BhbWVsYWZveC9sc2NhY2hlL2Jsb2IvbWFzdGVyL2xzY2FjaGUuanMsIEFwYWNoZSBMaWNlbnNlIFBhbWVsYWZveFxuICAgIHN0YXRpYyBfc3VwcG9ydHNTdG9yYWdlKCkge1xuICAgICAgICBsZXQga2V5ID0gJ19fY2FjaGV0ZXN0X18nO1xuICAgICAgICBsZXQgdmFsdWUgPSBrZXk7XG5cbiAgICAgICAgaWYgKFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gc29tZSBicm93c2VycyB3aWxsIHRocm93IGFuIGVycm9yIGlmIHlvdSB0cnkgdG8gYWNjZXNzIGxvY2FsIHN0b3JhZ2UgKGUuZy4gYnJhdmUgYnJvd3NlcilcbiAgICAgICAgLy8gaGVuY2UgY2hlY2sgaXMgaW5zaWRlIGEgdHJ5L2NhdGNoXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoIXNlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0oa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5yZW1vdmVJdGVtKGtleSk7XG4gICAgICAgICAgICBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgPSB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBJZiB3ZSBoaXQgdGhlIGxpbWl0LCBhbmQgd2UgZG9uJ3QgaGF2ZSBhbiBlbXB0eSBzZXNzaW9uU3RvcmFnZSB0aGVuIGl0IG1lYW5zIHdlIGhhdmUgc3VwcG9ydFxuICAgICAgICAgICAgaWYgKFJzeF9DYWNoZS5faXNPdXRPZlNwYWNlKGUpICYmIHNlc3Npb25TdG9yYWdlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZSA9IHRydWU7IC8vIGp1c3QgbWF4ZWQgaXQgb3V0IGFuZCBldmVuIHRoZSBzZXQgdGVzdCBmYWlsZWQuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZSA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayB0byBzZXQgaWYgdGhlIGVycm9yIGlzIHVzIGRlYWxpbmcgd2l0aCBiZWluZyBvdXQgb2Ygc3BhY2VcbiAgICBzdGF0aWMgX2lzT3V0T2ZTcGFjZShlKSB7XG4gICAgICAgIHJldHVybiBlICYmIChlLm5hbWUgPT09ICdRVU9UQV9FWENFRURFRF9FUlInIHx8IGUubmFtZSA9PT0gJ05TX0VSUk9SX0RPTV9RVU9UQV9SRUFDSEVEJyB8fCBlLm5hbWUgPT09ICdRdW90YUV4Y2VlZGVkRXJyb3InKTtcbiAgICB9XG59XG4iLCIvKipcbiAqIFJzeF9Jbml0IC0gQ29yZSBmcmFtZXdvcmsgaW5pdGlhbGl6YXRpb24gYW5kIGVudmlyb25tZW50IHZhbGlkYXRpb25cbiAqL1xuY2xhc3MgUnN4X0luaXQge1xuICAgIC8qKlxuICAgICAqIENhbGxlZCB2aWEgUnN4Ll9yc3hfY29yZV9ib290XG4gICAgICogSW5pdGlhbGl6ZXMgdGhlIGNvcmUgZW52aXJvbm1lbnQgYW5kIHJ1bnMgYmFzaWMgc2FuaXR5IGNoZWNrc1xuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCgpIHtcbiAgICAgICAgaWYgKCFSc3guaXNfcHJvZCgpKSB7XG4gICAgICAgICAgICBSc3hfSW5pdC5fX2Vudmlyb25tZW50X2NoZWNrcygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgY2hlY2tzIHRvIGVuc3VyZSBwcm9wZXIgY29uZmlndXJhdGlvblxuICAgICAqL1xuICAgIHN0YXRpYyBfX2Vudmlyb25tZW50X2NoZWNrcygpIHtcbiAgICAgICAgLy8gRmluZCBhbGwgc2NyaXB0IHRhZ3MgaW4gdGhlIERPTVxuICAgICAgICBjb25zdCBzY3JpcHRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3NjcmlwdCcpO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2NyaXB0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgY29uc3Qgc2NyaXB0ID0gc2NyaXB0c1tpXTtcblxuICAgICAgICAgICAgLy8gU2tpcCBpbmxpbmUgc2NyaXB0cyAobm8gc3JjIGF0dHJpYnV0ZSlcbiAgICAgICAgICAgIGlmICghc2NyaXB0LnNyYykge1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBzY3JpcHQgaGFzIGRlZmVyIGF0dHJpYnV0ZVxuICAgICAgICAgICAgaWYgKCFzY3JpcHQuZGVmZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzcmMgPSBzY3JpcHQuc3JjIHx8ICcoaW5saW5lIHNjcmlwdCknO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlYXNvbiA9IGBBbGwgc2NyaXB0IHRhZ3MgdXNlZCBpbiBhbiBSU3BhZGUgcHJvamVjdCBtdXN0IGhhdmUgZGVmZXIgYXR0cmlidXRlLiBGb3VuZCBzY3JpcHQgd2l0aG91dCBkZWZlcjogJHtzcmN9YDtcblxuICAgICAgICAgICAgICAgIC8vIFN0b3AgZnJhbWV3b3JrIGJvb3Qgd2l0aCByZWFzb25cbiAgICAgICAgICAgICAgICBSc3guX3JzeF9jb3JlX2Jvb3Rfc3RvcChyZWFzb24pO1xuXG4gICAgICAgICAgICAgICAgLy8gQWxzbyBsb2cgdG8gY29uc29sZSBmb3IgdmlzaWJpbGl0eVxuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFtSU1ggQk9PVCBTVE9QUEVEXSAke3JlYXNvbn1gKTtcblxuICAgICAgICAgICAgICAgIC8vIFN0b3AgY2hlY2tpbmcgYWZ0ZXIgZmlyc3QgdmlvbGF0aW9uXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufSIsIi8vIEBGSUxFLVNVQkNMQVNTLTAxLUVYQ0VQVElPTlxuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIEphdmFTY3JpcHQgT1JNIG1vZGVsc1xuICpcbiAqIFByb3ZpZGVzIGNvcmUgZnVuY3Rpb25hbGl0eSBmb3IgZmV0Y2hpbmcgcmVjb3JkcyBmcm9tIGJhY2tlbmQgUEhQIG1vZGVscy5cbiAqIEFsbCBtb2RlbCBzdHVicyBnZW5lcmF0ZWQgYnkgdGhlIG1hbmlmZXN0IGV4dGVuZCB0aGlzIGJhc2UgY2xhc3MuXG4gKlxuICogRXhhbXBsZSB1c2FnZTpcbiAqICAgLy8gRmV0Y2ggc2luZ2xlIHJlY29yZFxuICogICBjb25zdCB1c2VyID0gYXdhaXQgVXNlcl9Nb2RlbC5mZXRjaCgxMjMpO1xuICpcbiAqICAgLy8gRmV0Y2ggbXVsdGlwbGUgcmVjb3Jkc1xuICogICBjb25zdCB1c2VycyA9IGF3YWl0IFVzZXJfTW9kZWwuZmV0Y2goWzEsIDIsIDNdKTtcbiAqXG4gKiAgIC8vIENyZWF0ZSBpbnN0YW5jZSB3aXRoIGRhdGFcbiAqICAgY29uc3QgdXNlciA9IG5ldyBVc2VyX01vZGVsKHtpZDogMSwgbmFtZTogJ0pvaG4nfSk7XG4gKlxuICogIEBJbnN0YW50aWF0YWJsZVxuICovXG5jbGFzcyBSc3hfSnNfTW9kZWwge1xuICAgIC8qKlxuICAgICAqIENvbnN0cnVjdG9yIC0gSW5pdGlhbGl6ZSBtb2RlbCBpbnN0YW5jZSB3aXRoIGRhdGFcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIC0gS2V5LXZhbHVlIHBhaXJzIHRvIHBvcHVsYXRlIHRoZSBtb2RlbFxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGRhdGEgPSB7fSkge1xuICAgICAgICAvLyBfX01PREVMIFNZU1RFTTogRW5hYmxlcyBhdXRvbWF0aWMgT1JNIGluc3RhbnRpYXRpb24gd2hlbiBmZXRjaGluZyBmcm9tIFBIUCBtb2RlbHMuXG4gICAgICAgIC8vIFBIUCBtb2RlbHMgYWRkIFwiX19NT0RFTFwiOiBcIkNsYXNzTmFtZVwiIHRvIEpTT04sIEphdmFTY3JpcHQgdXNlcyBpdCB0byBjcmVhdGUgcHJvcGVyIGluc3RhbmNlcy5cbiAgICAgICAgLy8gVGhpcyBwcm92aWRlcyB0eXBlZCBtb2RlbCBvYmplY3RzIGluc3RlYWQgb2YgcGxhaW4gSlNPTiwgd2l0aCBtZXRob2RzIGFuZCB0eXBlIGNoZWNraW5nLlxuXG4gICAgICAgIC8vIFRoaXMgY29uc3RydWN0b3IgZmlsdGVycyBvdXQgdGhlIF9fTU9ERUwgbWFya2VyIHRoYXQgd2FzIHVzZWQgdG8gaWRlbnRpZnkgd2hpY2ggY2xhc3NcbiAgICAgICAgLy8gdG8gaW5zdGFudGlhdGUsIGtlZXBpbmcgb25seSB0aGUgYWN0dWFsIGRhdGEgcHJvcGVydGllcyBvbiB0aGUgaW5zdGFuY2UuXG4gICAgICAgIGNvbnN0IHsgX19NT0RFTCwgLi4ubW9kZWxEYXRhIH0gPSBkYXRhO1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIG1vZGVsRGF0YSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmV0Y2ggcmVjb3JkKHMpIGZyb20gdGhlIGJhY2tlbmQgbW9kZWxcbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIG1pcnJvcnMgdGhlIFBIUCBNb2RlbDo6ZmV0Y2goKSBmdW5jdGlvbmFsaXR5LlxuICAgICAqIFRoZSBiYWNrZW5kIG1vZGVsIG11c3QgaGF2ZSBhIGZldGNoKCkgbWV0aG9kIHdpdGggdGhlXG4gICAgICogI1tBamF4X0VuZHBvaW50X01vZGVsX0ZldGNoXSBhbm5vdGF0aW9uIHRvIGJlIGNhbGxhYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8QXJyYXl9IGlkIC0gU2luZ2xlIElEIG9yIGFycmF5IG9mIElEcyB0byBmZXRjaFxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSAtIFNpbmdsZSBtb2RlbCBpbnN0YW5jZSwgYXJyYXkgb2YgaW5zdGFuY2VzLCBvciBmYWxzZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBmZXRjaChpZCkge1xuICAgICAgICBjb25zdCBDdXJyZW50Q2xhc3MgPSB0aGlzO1xuICAgICAgICAvLyBHZXQgdGhlIG1vZGVsIGNsYXNzIG5hbWUgZnJvbSB0aGUgY3VycmVudCBjbGFzc1xuICAgICAgICBjb25zdCBtb2RlbE5hbWUgPSBDdXJyZW50Q2xhc3MubmFtZTtcblxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0ICQuYWpheCh7XG4gICAgICAgICAgICB1cmw6IGAvX2ZldGNoLyR7bW9kZWxOYW1lfWAsXG4gICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIGRhdGE6IHsgaWQ6IGlkIH0sXG4gICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBIYW5kbGUgcmVzcG9uc2UgYmFzZWQgb24gdHlwZVxuICAgICAgICBpZiAocmVzcG9uc2UgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVc2UgX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUgdG8gaGFuZGxlIE9STSBpbnN0YW50aWF0aW9uXG4gICAgICAgIC8vIFRoaXMgd2lsbCBhdXRvbWF0aWNhbGx5IGRldGVjdCBfX01PREVMIHByb3BlcnRpZXMgYW5kIGNyZWF0ZSBhcHByb3ByaWF0ZSBpbnN0YW5jZXNcbiAgICAgICAgcmV0dXJuIFJzeF9Kc19Nb2RlbC5faW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZShyZXNwb25zZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBtb2RlbCBjbGFzcyBuYW1lXG4gICAgICogVXNlZCBpbnRlcm5hbGx5IGZvciBBUEkgY2FsbHNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBjbGFzcyBuYW1lXG4gICAgICovXG4gICAgc3RhdGljIGdldE1vZGVsTmFtZSgpIHtcbiAgICAgICAgY29uc3QgQ3VycmVudENsYXNzID0gdGhpcztcbiAgICAgICAgcmV0dXJuIEN1cnJlbnRDbGFzcy5uYW1lO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZnJlc2ggdGhpcyBpbnN0YW5jZSB3aXRoIGxhdGVzdCBkYXRhIGZyb20gc2VydmVyXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gVXBkYXRlZCBpbnN0YW5jZSBvciBmYWxzZSBpZiBub3QgZm91bmRcbiAgICAgKi9cbiAgICBhc3luYyByZWZyZXNoKCkge1xuICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGF0LmlkKSB7XG4gICAgICAgICAgICBzaG91bGRudF9oYXBwZW4oJ0Nhbm5vdCByZWZyZXNoIG1vZGVsIHdpdGhvdXQgaWQgcHJvcGVydHknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGZyZXNoID0gYXdhaXQgdGhhdC5jb25zdHJ1Y3Rvci5mZXRjaCh0aGF0LmlkKTtcblxuICAgICAgICBpZiAoZnJlc2ggPT09IGZhbHNlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgdGhpcyBpbnN0YW5jZSB3aXRoIGZyZXNoIGRhdGFcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGF0LCBmcmVzaCk7XG4gICAgICAgIHJldHVybiB0aGF0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgbW9kZWwgaW5zdGFuY2UgdG8gcGxhaW4gb2JqZWN0XG4gICAgICogVXNlZnVsIGZvciBzZXJpYWxpemF0aW9uIG9yIHNlbmRpbmcgdG8gQVBJc1xuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH0gUGxhaW4gb2JqZWN0IHJlcHJlc2VudGF0aW9uXG4gICAgICovXG4gICAgdG9PYmplY3QoKSB7XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICBjb25zdCBvYmogPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gdGhhdCkge1xuICAgICAgICAgICAgaWYgKHRoYXQuaGFzT3duUHJvcGVydHkoa2V5KSAmJiB0eXBlb2YgdGhhdFtrZXldICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgb2JqW2tleV0gPSB0aGF0W2tleV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9iajtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IG1vZGVsIGluc3RhbmNlIHRvIEpTT04gc3RyaW5nXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBKU09OIHJlcHJlc2VudGF0aW9uXG4gICAgICovXG4gICAgdG9KU09OKCkge1xuICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoYXQudG9PYmplY3QoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjdXJzaXZlbHkgaW5zdGFudGlhdGUgT1JNIG1vZGVscyBpbiByZXNwb25zZSBkYXRhXG4gICAgICpcbiAgICAgKiBMb29rcyBmb3Igb2JqZWN0cyB3aXRoIF9fTU9ERUwgcHJvcGVydHkgYW5kIGluc3RhbnRpYXRlcyB0aGUgYXBwcm9wcmlhdGVcbiAgICAgKiBKYXZhU2NyaXB0IG1vZGVsIGNsYXNzIGlmIGl0IGV4aXN0cyBpbiB0aGUgZ2xvYmFsIHNjb3BlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBkYXRhIC0gVGhlIGRhdGEgdG8gcHJvY2VzcyAoY2FuIGJlIGFueSB0eXBlKVxuICAgICAqIEByZXR1cm5zIHsqfSBUaGUgZGF0YSB3aXRoIE9STSBvYmplY3RzIGluc3RhbnRpYXRlZFxuICAgICAqL1xuICAgIHN0YXRpYyBfaW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZShkYXRhKSB7XG4gICAgICAgIC8vIF9fTU9ERUwgU1lTVEVNOiBFbmFibGVzIGF1dG9tYXRpYyBPUk0gaW5zdGFudGlhdGlvbiB3aGVuIGZldGNoaW5nIGZyb20gUEhQIG1vZGVscy5cbiAgICAgICAgLy8gUEhQIG1vZGVscyBhZGQgXCJfX01PREVMXCI6IFwiQ2xhc3NOYW1lXCIgdG8gSlNPTiwgSmF2YVNjcmlwdCB1c2VzIGl0IHRvIGNyZWF0ZSBwcm9wZXIgaW5zdGFuY2VzLlxuICAgICAgICAvLyBUaGlzIHByb3ZpZGVzIHR5cGVkIG1vZGVsIG9iamVjdHMgaW5zdGVhZCBvZiBwbGFpbiBKU09OLCB3aXRoIG1ldGhvZHMgYW5kIHR5cGUgY2hlY2tpbmcuXG5cbiAgICAgICAgLy8gVGhpcyByZWN1cnNpdmUgcHJvY2Vzc29yIHNjYW5zIGFsbCBBUEkgcmVzcG9uc2UgZGF0YSBsb29raW5nIGZvciBfX01PREVMIG1hcmtlcnMuXG4gICAgICAgIC8vIFdoZW4gZm91bmQsIGl0IGF0dGVtcHRzIHRvIGluc3RhbnRpYXRlIHRoZSBhcHByb3ByaWF0ZSBKYXZhU2NyaXB0IG1vZGVsIGNsYXNzLFxuICAgICAgICAvLyBjb252ZXJ0aW5nIHtfX01PREVMOiBcIlVzZXJfTW9kZWxcIiwgaWQ6IDEsIG5hbWU6IFwiSm9oblwifSBpbnRvIG5ldyBVc2VyX01vZGVsKHsuLi59KS5cbiAgICAgICAgLy8gV29ya3MgcmVjdXJzaXZlbHkgdGhyb3VnaCBhcnJheXMgYW5kIG5lc3RlZCBvYmplY3RzIHRvIGhhbmRsZSBjb21wbGV4IGRhdGEgc3RydWN0dXJlcy5cbiAgICAgICAgLy8gSGFuZGxlIG51bGwvdW5kZWZpbmVkXG4gICAgICAgIGlmIChkYXRhID09PSBudWxsIHx8IGRhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW5kbGUgYXJyYXlzIC0gcmVjdXJzaXZlbHkgcHJvY2VzcyBlYWNoIGVsZW1lbnRcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhLm1hcCgoaXRlbSkgPT4gUnN4X0pzX01vZGVsLl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlKGl0ZW0pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBvYmplY3RzXG4gICAgICAgIGlmICh0eXBlb2YgZGF0YSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoaXMgb2JqZWN0IGhhcyBhIF9fTU9ERUwgcHJvcGVydHlcbiAgICAgICAgICAgIGlmIChkYXRhLl9fTU9ERUwgJiYgdHlwZW9mIGRhdGEuX19NT0RFTCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAvLyBUcnkgdG8gZmluZCB0aGUgbW9kZWwgY2xhc3MgaW4gdGhlIGdsb2JhbCBzY29wZVxuICAgICAgICAgICAgICAgIGNvbnN0IE1vZGVsQ2xhc3MgPSB3aW5kb3dbZGF0YS5fX01PREVMXTtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBtb2RlbCBjbGFzcyBleGlzdHMgYW5kIGV4dGVuZHMgUnN4X0pzX01vZGVsLCBpbnN0YW50aWF0ZSBpdFxuICAgICAgICAgICAgICAgIC8vIER5bmFtaWMgbW9kZWwgcmVzb2x1dGlvbiByZXF1aXJlcyBjaGVja2luZyBjbGFzcyBleGlzdGVuY2UgLSBASlMtREVGRU5TSVZFLTAxLUVYQ0VQVElPTlxuICAgICAgICAgICAgICAgIGlmIChNb2RlbENsYXNzICYmIE1vZGVsQ2xhc3MucHJvdG90eXBlIGluc3RhbmNlb2YgUnN4X0pzX01vZGVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTW9kZWxDbGFzcyhkYXRhKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJlY3Vyc2l2ZWx5IHByb2Nlc3MgYWxsIG9iamVjdCBwcm9wZXJ0aWVzXG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gUnN4X0pzX01vZGVsLl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlKGRhdGFba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldHVybiBwcmltaXRpdmUgdmFsdWVzIGFzLWlzXG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbn1cbiIsIi8qKlxuICogVmlld19UcmFuc2l0aW9ucyAtIFNtb290aCBwYWdlLXRvLXBhZ2UgdHJhbnNpdGlvbnMgdXNpbmcgVmlldyBUcmFuc2l0aW9ucyBBUElcbiAqXG4gKiBFbmFibGVzIGNyb3NzLWRvY3VtZW50IHZpZXcgdHJhbnNpdGlvbnMgc28gdGhlIGJyb3dzZXIgZG9lc24ndCBwYWludCB0aGUgbmV3IHBhZ2VcbiAqIHVudGlsIGl0J3MgcmVhZHksIGNyZWF0aW5nIHNtb290aCBhbmltYXRpb25zIGJldHdlZW4gcGFnZXMuXG4gKlxuICogRmFsbHMgYmFjayBncmFjZWZ1bGx5IGlmIFZpZXcgVHJhbnNpdGlvbnMgQVBJIGlzIG5vdCBhdmFpbGFibGUuXG4gKi9cbmNsYXNzIFJzeF9WaWV3X1RyYW5zaXRpb25zIHtcbiAgICAvKipcbiAgICAgKiBDYWxsZWQgZHVyaW5nIGZyYW1ld29yayBjb3JlIGluaXQgcGhhc2VcbiAgICAgKiBDaGVja3MgZm9yIFZpZXcgVHJhbnNpdGlvbnMgQVBJIHN1cHBvcnQgYW5kIGVuYWJsZXMgaWYgYXZhaWxhYmxlXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9pbml0KCkge1xuICAgICAgICAvLyBDaGVjayBpZiBWaWV3IFRyYW5zaXRpb25zIEFQSSBpcyBzdXBwb3J0ZWRcbiAgICAgICAgaWYgKCFkb2N1bWVudC5zdGFydFZpZXdUcmFuc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdWSUVXX1RSQU5TSVRJT05TJywgJ1ZpZXcgVHJhbnNpdGlvbnMgQVBJIG5vdCBzdXBwb3J0ZWQsIHNraXBwaW5nJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbmFibGUgY3Jvc3MtZG9jdW1lbnQgdmlldyB0cmFuc2l0aW9ucyB2aWEgQ1NTXG4gICAgICAgIFJzeF9WaWV3X1RyYW5zaXRpb25zLl9pbmplY3RfdHJhbnNpdGlvbl9jc3MoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmplY3QgQ1NTIHRvIGVuYWJsZSBjcm9zcy1kb2N1bWVudCB2aWV3IHRyYW5zaXRpb25zXG4gICAgICpcbiAgICAgKiBUaGUgQHZpZXctdHJhbnNpdGlvbiB7IG5hdmlnYXRpb246IGF1dG87IH0gcnVsZSB0ZWxscyB0aGUgYnJvd3NlciB0bzpcbiAgICAgKiAxLiBDYXB0dXJlIGEgc25hcHNob3Qgb2YgdGhlIGN1cnJlbnQgcGFnZSBiZWZvcmUgbmF2aWdhdGlvblxuICAgICAqIDIuIEZldGNoIHRoZSBuZXcgcGFnZVxuICAgICAqIDMuIFdhaXQgdW50aWwgdGhlIG5ldyBwYWdlIGlzIGZ1bGx5IGxvYWRlZCBhbmQgcGFpbnRlZCAoZG9jdW1lbnQucmVhZHkpXG4gICAgICogNC4gQW5pbWF0ZSBzbW9vdGhseSBiZXR3ZWVuIHRoZSB0d28gc3RhdGVzXG4gICAgICpcbiAgICAgKiBUaGlzIHByZXZlbnRzIHRoZSB3aGl0ZSBmbGFzaCBkdXJpbmcgbmF2aWdhdGlvbiBhbmQgY3JlYXRlcyBhcHAtbGlrZSB0cmFuc2l0aW9ucy5cbiAgICAgKi9cbiAgICBzdGF0aWMgX2luamVjdF90cmFuc2l0aW9uX2NzcygpIHtcbiAgICAgICAgY29uc3Qgc3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzdHlsZScpO1xuXG4gICAgICAgIHN0eWxlLnRleHRDb250ZW50ID0gYFxuICAgICAgICAgICAgQHZpZXctdHJhbnNpdGlvbiB7XG4gICAgICAgICAgICAgICAgbmF2aWdhdGlvbjogYXV0bztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyogRGlzYWJsZSBhbmltYXRpb24gLSBpbnN0YW50IHRyYW5zaXRpb24gKi9cbiAgICAgICAgICAgIDo6dmlldy10cmFuc2l0aW9uLWdyb3VwKCopLFxuICAgICAgICAgICAgOjp2aWV3LXRyYW5zaXRpb24tb2xkKCopLFxuICAgICAgICAgICAgOjp2aWV3LXRyYW5zaXRpb24tbmV3KCopIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb24tZHVyYXRpb246IDBzO1xuICAgICAgICAgICAgfVxuICAgICAgICBgO1xuXG4gICAgICAgIGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoc3R5bGUpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogUmVhZFdyaXRlTG9jayBpbXBsZW1lbnRhdGlvbiBmb3IgUlNwYWRlIGZyYW1ld29ya1xuICogUHJvdmlkZXMgZXhjbHVzaXZlICh3cml0ZSkgYW5kIHNoYXJlZCAocmVhZCkgbG9ja2luZyBtZWNoYW5pc21zIGZvciBhc3luY2hyb25vdXMgb3BlcmF0aW9uc1xuICovXG5jbGFzcyBSZWFkV3JpdGVMb2NrIHtcbiAgICBzdGF0aWMgI2xvY2tzID0gbmV3IE1hcCgpO1xuXG4gICAgLyoqXG4gICAgICogR2V0IG9yIGNyZWF0ZSBhIGxvY2sgb2JqZWN0IGZvciBhIGdpdmVuIG5hbWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyAjZ2V0X2xvY2sobmFtZSkge1xuICAgICAgICBsZXQgcyA9IHRoaXMuI2xvY2tzLmdldChuYW1lKTtcbiAgICAgICAgaWYgKCFzKSB7XG4gICAgICAgICAgICBzID0geyByZWFkZXJzOiAwLCB3cml0ZXJfYWN0aXZlOiBmYWxzZSwgcmVhZGVyX3E6IFtdLCB3cml0ZXJfcTogW10gfTtcbiAgICAgICAgICAgIHRoaXMuI2xvY2tzLnNldChuYW1lLCBzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTY2hlZHVsZSB0aGUgbmV4dCBvcGVyYXRpb24gZm9yIGEgbG9ja1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljICNzY2hlZHVsZShuYW1lKSB7XG4gICAgICAgIGNvbnN0IHMgPSB0aGlzLiNnZXRfbG9jayhuYW1lKTtcbiAgICAgICAgaWYgKHMud3JpdGVyX2FjdGl2ZSB8fCBzLnJlYWRlcnMgPiAwKSByZXR1cm47XG5cbiAgICAgICAgLy8gcnVuIG9uZSB3cml0ZXIgaWYgcXVldWVkXG4gICAgICAgIGlmIChzLndyaXRlcl9xLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHsgY2IsIHJlc29sdmUsIHJlamVjdCB9ID0gcy53cml0ZXJfcS5zaGlmdCgpO1xuICAgICAgICAgICAgcy53cml0ZXJfYWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oY2IpXG4gICAgICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KVxuICAgICAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcy53cml0ZXJfYWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuI3NjaGVkdWxlKG5hbWUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gb3RoZXJ3aXNlIHJ1biBhbGwgcXVldWVkIHJlYWRlcnMgaW4gcGFyYWxsZWxcbiAgICAgICAgaWYgKHMucmVhZGVyX3EubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgYmF0Y2ggPSBzLnJlYWRlcl9xLnNwbGljZSgwKTtcbiAgICAgICAgICAgIHMucmVhZGVycyArPSBiYXRjaC5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHsgY2IsIHJlc29sdmUsIHJlamVjdCB9IG9mIGJhdGNoKSB7XG4gICAgICAgICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oY2IpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKHJlc29sdmUsIHJlamVjdClcbiAgICAgICAgICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcy5yZWFkZXJzIC09IDE7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocy5yZWFkZXJzID09PSAwKSB0aGlzLiNzY2hlZHVsZShuYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBY3F1aXJlIGFuIGV4Y2x1c2l2ZSBtdXRleCBsb2NrIGJ5IG5hbWUuXG4gICAgICogT25seSBvbmUgd3JpdGVyIHJ1bnMgYXQgYSB0aW1lOyBibG9ja3MgcmVhZGVycyB1bnRpbCBmaW5pc2hlZC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqIEBwYXJhbSB7KCkgPT4gYW55fFByb21pc2U8YW55Pn0gY2JcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICAgICAqL1xuICAgIHN0YXRpYyBhY3F1aXJlKG5hbWUsIGNiKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzID0gdGhpcy4jZ2V0X2xvY2sobmFtZSk7XG4gICAgICAgICAgICBzLndyaXRlcl9xLnB1c2goeyBjYiwgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgdGhpcy4jc2NoZWR1bGUobmFtZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFjcXVpcmUgYSBzaGFyZWQgcmVhZCBsb2NrIGJ5IG5hbWUuXG4gICAgICogTXVsdGlwbGUgcmVhZGVycyBjYW4gcnVuIGluIHBhcmFsbGVsOyBibG9ja3Mgd2hlbiB3cml0ZXIgaXMgYWN0aXZlLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICogQHBhcmFtIHsoKSA9PiBhbnl8UHJvbWlzZTxhbnk+fSBjYlxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gICAgICovXG4gICAgc3RhdGljIGFjcXVpcmVfcmVhZChuYW1lLCBjYikge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcyA9IHRoaXMuI2dldF9sb2NrKG5hbWUpO1xuICAgICAgICAgICAgaWYgKHMud3JpdGVyX2FjdGl2ZSB8fCBzLndyaXRlcl9xLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBzLnJlYWRlcl9xLnB1c2goeyBjYiwgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiNzY2hlZHVsZShuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHMucmVhZGVycyArPSAxO1xuICAgICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgICAgICAudGhlbihjYilcbiAgICAgICAgICAgICAgICAudGhlbihyZXNvbHZlLCByZWplY3QpXG4gICAgICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzLnJlYWRlcnMgLT0gMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMucmVhZGVycyA9PT0gMCkgdGhpcy4jc2NoZWR1bGUobmFtZSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcmNlLXVubG9jayBhIG11dGV4ICh1c2Ugd2l0aCBjYXV0aW9uKS5cbiAgICAgKiBDb21wbGV0ZWx5IHJlbW92ZXMgdGhlIGxvY2sgc3RhdGUsIHBvdGVudGlhbGx5IGJyZWFraW5nIHdhaXRpbmcgb3BlcmF0aW9ucy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqL1xuICAgIHN0YXRpYyBmb3JjZV91bmxvY2sobmFtZSkge1xuICAgICAgICB0aGlzLiNsb2Nrcy5kZWxldGUobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGluZm9ybWF0aW9uIGFib3V0IHBlbmRpbmcgb3BlcmF0aW9ucyBvbiBhIG11dGV4LlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gICAgICogQHJldHVybnMge3tyZWFkZXJzOiBudW1iZXIsIHdyaXRlcl9hY3RpdmU6IGJvb2xlYW4sIHJlYWRlcl9xOiBudW1iZXIsIHdyaXRlcl9xOiBudW1iZXJ9fVxuICAgICAqL1xuICAgIHN0YXRpYyBwZW5kaW5nKG5hbWUpIHtcbiAgICAgICAgY29uc3QgcyA9IHRoaXMuI2xvY2tzLmdldChuYW1lKTtcbiAgICAgICAgaWYgKCFzKSByZXR1cm4geyByZWFkZXJzOiAwLCB3cml0ZXJfYWN0aXZlOiBmYWxzZSwgcmVhZGVyX3E6IDAsIHdyaXRlcl9xOiAwIH07XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByZWFkZXJzOiBzLnJlYWRlcnMsXG4gICAgICAgICAgICB3cml0ZXJfYWN0aXZlOiBzLndyaXRlcl9hY3RpdmUsXG4gICAgICAgICAgICByZWFkZXJfcTogcy5yZWFkZXJfcS5sZW5ndGgsXG4gICAgICAgICAgICB3cml0ZXJfcTogcy53cml0ZXJfcS5sZW5ndGhcbiAgICAgICAgfTtcbiAgICB9XG59IiwiLyoqXG4gKiBGb3JtIHV0aWxpdGllcyBmb3IgdmFsaWRhdGlvbiBhbmQgZXJyb3IgaGFuZGxpbmdcbiAqL1xuY2xhc3MgRm9ybV9VdGlscyB7XG4gICAgLyoqXG4gICAgICogRnJhbWV3b3JrIGluaXRpYWxpemF0aW9uIGhvb2sgdG8gcmVnaXN0ZXIgalF1ZXJ5IHBsdWdpblxuICAgICAqIENyZWF0ZXMgJC5mbi5hamF4X3N1Ym1pdCgpIGZvciBmb3JtIGVsZW1lbnRzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2RlZmluZShwYXJhbXMgPSB7fSkge1xuICAgICAgICAkLmZuLmFqYXhfc3VibWl0ID0gZnVuY3Rpb24ob3B0aW9ucyA9IHt9KSB7XG4gICAgICAgICAgICBjb25zdCAkZWxlbWVudCA9ICQodGhpcyk7XG5cbiAgICAgICAgICAgIGlmICghJGVsZW1lbnQuaXMoJ2Zvcm0nKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYWpheF9zdWJtaXQoKSBjYW4gb25seSBiZSBjYWxsZWQgb24gZm9ybSBlbGVtZW50cycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCB1cmwgPSAkZWxlbWVudC5hdHRyKCdhY3Rpb24nKTtcbiAgICAgICAgICAgIGlmICghdXJsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGb3JtIG11c3QgaGF2ZSBhbiBhY3Rpb24gYXR0cmlidXRlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHsgY29udHJvbGxlciwgYWN0aW9uIH0gPSBBamF4LmFqYXhfdXJsX3RvX2NvbnRyb2xsZXJfYWN0aW9uKHVybCk7XG5cbiAgICAgICAgICAgIHJldHVybiBGb3JtX1V0aWxzLmFqYXhfc3VibWl0KCRlbGVtZW50LCBjb250cm9sbGVyLCBhY3Rpb24sIG9wdGlvbnMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3dzIGZvcm0gdmFsaWRhdGlvbiBlcnJvcnNcbiAgICAgKlxuICAgICAqIFJFUVVJUkVEIEhUTUwgU1RSVUNUVVJFOlxuICAgICAqIEZvciBpbmxpbmUgZmllbGQgZXJyb3JzIHRvIGRpc3BsYXkgcHJvcGVybHksIGZvcm0gZmllbGRzIG11c3QgZm9sbG93IHRoaXMgc3RydWN0dXJlOlxuICAgICAqXG4gICAgICogPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgKiAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIiBmb3I9XCJmaWVsZC1uYW1lXCI+RmllbGQgTGFiZWw8L2xhYmVsPlxuICAgICAqICAgPGlucHV0IGNsYXNzPVwiZm9ybS1jb250cm9sXCIgaWQ9XCJmaWVsZC1uYW1lXCIgbmFtZT1cImZpZWxkLW5hbWVcIiB0eXBlPVwidGV4dFwiPlxuICAgICAqIDwvZGl2PlxuICAgICAqXG4gICAgICogS2V5IHJlcXVpcmVtZW50czpcbiAgICAgKiAtIFdyYXAgZWFjaCBmaWVsZCBpbiBhIGNvbnRhaW5lciB3aXRoIGNsYXNzIFwiZm9ybS1ncm91cFwiIChvciBcImZvcm0tY2hlY2tcIiAvIFwiaW5wdXQtZ3JvdXBcIilcbiAgICAgKiAtIElucHV0IG11c3QgaGF2ZSBhIFwibmFtZVwiIGF0dHJpYnV0ZSBtYXRjaGluZyB0aGUgZXJyb3Iga2V5XG4gICAgICogLSBVc2UgXCJmb3JtLWNvbnRyb2xcIiBjbGFzcyBvbiBpbnB1dHMgZm9yIEJvb3RzdHJhcCA1IHN0eWxpbmdcbiAgICAgKlxuICAgICAqIEFjY2VwdHMgdGhyZWUgZm9ybWF0czpcbiAgICAgKiAtIFN0cmluZzogU2luZ2xlIGVycm9yIHNob3duIGFzIGFsZXJ0XG4gICAgICogLSBBcnJheSBvZiBzdHJpbmdzOiBNdWx0aXBsZSBlcnJvcnMgc2hvd24gYXMgYnVsbGV0ZWQgYWxlcnRcbiAgICAgKiAtIE9iamVjdDogRmllbGQgbmFtZXMgbWFwcGVkIHRvIGVycm9ycywgc2hvd24gaW5saW5lICh1bm1hdGNoZWQgc2hvd24gYXMgYWxlcnQpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyZW50X3NlbGVjdG9yIC0galF1ZXJ5IHNlbGVjdG9yIGZvciBwYXJlbnQgZWxlbWVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfE9iamVjdHxBcnJheX0gZXJyb3JzIC0gRXJyb3IgbWVzc2FnZXMgdG8gZGlzcGxheVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgYW5pbWF0aW9ucyBjb21wbGV0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhcHBseV9mb3JtX2Vycm9ycyhwYXJlbnRfc2VsZWN0b3IsIGVycm9ycykge1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycm9ycyk7XG5cbiAgICAgICAgY29uc3QgJHBhcmVudCA9ICQocGFyZW50X3NlbGVjdG9yKTtcblxuICAgICAgICAvLyBSZXNldCB0aGUgZm9ybSBlcnJvcnMgYmVmb3JlIGFwcGx5aW5nIG5ldyBvbmVzXG4gICAgICAgIEZvcm1fVXRpbHMucmVzZXRfZm9ybV9lcnJvcnMocGFyZW50X3NlbGVjdG9yKTtcblxuICAgICAgICAvLyBOb3JtYWxpemUgaW5wdXQgdG8gc3RhbmRhcmQgZm9ybWF0XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBGb3JtX1V0aWxzLl9ub3JtYWxpemVfZXJyb3JzKGVycm9ycyk7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICBsZXQgYW5pbWF0aW9ucyA9IFtdO1xuXG4gICAgICAgICAgICBpZiAobm9ybWFsaXplZC50eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIC8vIFNpbmdsZSBlcnJvciBtZXNzYWdlXG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucyA9IEZvcm1fVXRpbHMuX2FwcGx5X2dlbmVyYWxfZXJyb3JzKCRwYXJlbnQsIG5vcm1hbGl6ZWQuZGF0YSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWQudHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgICAgICAgIC8vIEFycmF5IG9mIGVycm9yIG1lc3NhZ2VzXG4gICAgICAgICAgICAgICAgY29uc3QgZGVkdXBsaWNhdGVkID0gRm9ybV9VdGlscy5fZGVkdXBsaWNhdGVfZXJyb3JzKG5vcm1hbGl6ZWQuZGF0YSk7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucyA9IEZvcm1fVXRpbHMuX2FwcGx5X2dlbmVyYWxfZXJyb3JzKCRwYXJlbnQsIGRlZHVwbGljYXRlZCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG5vcm1hbGl6ZWQudHlwZSA9PT0gJ2ZpZWxkcycpIHtcbiAgICAgICAgICAgICAgICAvLyBGaWVsZC1zcGVjaWZpYyBlcnJvcnNcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBGb3JtX1V0aWxzLl9hcHBseV9maWVsZF9lcnJvcnMoJHBhcmVudCwgbm9ybWFsaXplZC5kYXRhKTtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zID0gcmVzdWx0LmFuaW1hdGlvbnM7XG5cbiAgICAgICAgICAgICAgICAvLyBDb3VudCBtYXRjaGVkIGZpZWxkc1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoZWRfY291bnQgPSBPYmplY3Qua2V5cyhub3JtYWxpemVkLmRhdGEpLmxlbmd0aCAtIE9iamVjdC5rZXlzKHJlc3VsdC51bm1hdGNoZWQpLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBjb25zdCB1bm1hdGNoZWRfZGVkdXBsaWNhdGVkID0gRm9ybV9VdGlscy5fZGVkdXBsaWNhdGVfZXJyb3JzKHJlc3VsdC51bm1hdGNoZWQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHVubWF0Y2hlZF9jb3VudCA9IE9iamVjdC5rZXlzKHVubWF0Y2hlZF9kZWR1cGxpY2F0ZWQpLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIC8vIFNob3cgc3VtbWFyeSBhbGVydCBpZiB0aGVyZSBhcmUgYW55IGZpZWxkIGVycm9ycyAobWF0Y2hlZCBvciB1bm1hdGNoZWQpXG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoZWRfY291bnQgPiAwIHx8IHVubWF0Y2hlZF9jb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQnVpbGQgc3VtbWFyeSBtZXNzYWdlXG4gICAgICAgICAgICAgICAgICAgIGxldCBzdW1tYXJ5X21zZyA9ICcnO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hlZF9jb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcnlfbXNnID0gbWF0Y2hlZF9jb3VudCA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gJ1BsZWFzZSBjb3JyZWN0IHRoZSBlcnJvciBoaWdobGlnaHRlZCBiZWxvdy4nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnUGxlYXNlIGNvcnJlY3QgdGhlIGVycm9ycyBoaWdobGlnaHRlZCBiZWxvdy4nO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlcmUgYXJlIHVubWF0Y2hlZCBlcnJvcnMsIGFkZCB0aGVtIGFzIGEgYnVsbGV0ZWQgbGlzdFxuICAgICAgICAgICAgICAgICAgICBpZiAodW5tYXRjaGVkX2NvdW50ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3VtbWFyeV9hbmltYXRpb25zID0gRm9ybV9VdGlscy5fYXBwbHlfY29tYmluZWRfZXJyb3IoJHBhcmVudCwgc3VtbWFyeV9tc2csIHVubWF0Y2hlZF9kZWR1cGxpY2F0ZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKC4uLnN1bW1hcnlfYW5pbWF0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBKdXN0IHRoZSBzdW1tYXJ5IG1lc3NhZ2UsIG5vIHVubWF0Y2hlZCBlcnJvcnNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1bW1hcnlfYW5pbWF0aW9ucyA9IEZvcm1fVXRpbHMuX2FwcGx5X2dlbmVyYWxfZXJyb3JzKCRwYXJlbnQsIHN1bW1hcnlfbXNnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCguLi5zdW1tYXJ5X2FuaW1hdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZXNvbHZlIHRoZSBwcm9taXNlIG9uY2UgYWxsIGFuaW1hdGlvbnMgYXJlIGNvbXBsZXRlXG4gICAgICAgICAgICBQcm9taXNlLmFsbChhbmltYXRpb25zKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBTY3JvbGwgdG8gZXJyb3IgY29udGFpbmVyIGlmIGl0IGV4aXN0c1xuICAgICAgICAgICAgICAgIGNvbnN0ICRlcnJvcl9jb250YWluZXIgPSAkcGFyZW50LmZpbmQoJ1tkYXRhLWlkPVwiZXJyb3JfY29udGFpbmVyXCJdJykuZmlyc3QoKTtcbiAgICAgICAgICAgICAgICBpZiAoJGVycm9yX2NvbnRhaW5lci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRhaW5lcl90b3AgPSAkZXJyb3JfY29udGFpbmVyLm9mZnNldCgpLnRvcDtcblxuICAgICAgICAgICAgICAgICAgICAvLyBDYWxjdWxhdGUgZml4ZWQgaGVhZGVyIG9mZnNldFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaXhlZF9oZWFkZXJfaGVpZ2h0ID0gRm9ybV9VdGlscy5fZ2V0X2ZpeGVkX2hlYWRlcl9oZWlnaHQoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBTY3JvbGwgdG8gcG9zaXRpb24gZXJyb3IgY29udGFpbmVyIDIwcHggYmVsb3cgYW55IGZpeGVkIGhlYWRlcnNcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0X3Njcm9sbCA9IGNvbnRhaW5lcl90b3AgLSBmaXhlZF9oZWFkZXJfaGVpZ2h0IC0gMjA7XG4gICAgICAgICAgICAgICAgICAgICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFRvcDogdGFyZ2V0X3Njcm9sbFxuICAgICAgICAgICAgICAgICAgICB9LCA1MDApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbGVhcnMgZm9ybSB2YWxpZGF0aW9uIGVycm9ycyBhbmQgcmVzZXRzIGFsbCBmb3JtIHZhbHVlcyB0byBkZWZhdWx0c1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfGpRdWVyeX0gZm9ybV9zZWxlY3RvciAtIGpRdWVyeSBzZWxlY3RvciBvciBqUXVlcnkgb2JqZWN0IGZvciBmb3JtIGVsZW1lbnRcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzZXQoZm9ybV9zZWxlY3Rvcikge1xuICAgICAgICBjb25zdCAkZm9ybSA9IHR5cGVvZiBmb3JtX3NlbGVjdG9yID09PSAnc3RyaW5nJyA/ICQoZm9ybV9zZWxlY3RvcikgOiBmb3JtX3NlbGVjdG9yO1xuXG4gICAgICAgIEZvcm1fVXRpbHMucmVzZXRfZm9ybV9lcnJvcnMoZm9ybV9zZWxlY3Rvcik7XG4gICAgICAgICRmb3JtLnRyaWdnZXIoJ3Jlc2V0Jyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VyaWFsaXplcyBmb3JtIGRhdGEgaW50byBrZXktdmFsdWUgb2JqZWN0XG4gICAgICogUmV0dXJucyBhbGwgaW5wdXQgZWxlbWVudHMgd2l0aCBuYW1lIGF0dHJpYnV0ZXMgYXMgb2JqZWN0IHByb3BlcnRpZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xqUXVlcnl9IGZvcm1fc2VsZWN0b3IgLSBqUXVlcnkgc2VsZWN0b3Igb3IgalF1ZXJ5IG9iamVjdCBmb3IgZm9ybSBlbGVtZW50XG4gICAgICogQHJldHVybnMge09iamVjdH0gRm9ybSBkYXRhIGFzIGtleS12YWx1ZSBwYWlyc1xuICAgICAqL1xuICAgIHN0YXRpYyBzZXJpYWxpemUoZm9ybV9zZWxlY3Rvcikge1xuICAgICAgICBjb25zdCAkZm9ybSA9IHR5cGVvZiBmb3JtX3NlbGVjdG9yID09PSAnc3RyaW5nJyA/ICQoZm9ybV9zZWxlY3RvcikgOiBmb3JtX3NlbGVjdG9yO1xuICAgICAgICBjb25zdCBkYXRhID0ge307XG5cbiAgICAgICAgJGZvcm0uc2VyaWFsaXplQXJyYXkoKS5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgICAgICBkYXRhW2l0ZW0ubmFtZV0gPSBpdGVtLnZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdWJtaXRzIGZvcm0gdG8gUlNYIGNvbnRyb2xsZXIgYWN0aW9uIHZpYSBBSkFYXG4gICAgICogQHBhcmFtIHtzdHJpbmd8alF1ZXJ5fSBmb3JtX3NlbGVjdG9yIC0galF1ZXJ5IHNlbGVjdG9yIG9yIGpRdWVyeSBvYmplY3QgZm9yIGZvcm0gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjb250cm9sbGVyIC0gQ29udHJvbGxlciBjbGFzcyBuYW1lIChlLmcuLCAnVXNlcl9Db250cm9sbGVyJylcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYWN0aW9uIC0gQWN0aW9uIG1ldGhvZCBuYW1lIChlLmcuLCAnc2F2ZV9wcm9maWxlJylcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIE9wdGlvbmFsIGNvbmZpZ3VyYXRpb24ge29uX3N1Y2Nlc3M6IGZuLCBvbl9lcnJvcjogZm59XG4gICAgICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHJlc3BvbnNlIGRhdGFcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgYWpheF9zdWJtaXQoZm9ybV9zZWxlY3RvciwgY29udHJvbGxlciwgYWN0aW9uLCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgY29uc3QgJGZvcm0gPSB0eXBlb2YgZm9ybV9zZWxlY3RvciA9PT0gJ3N0cmluZycgPyAkKGZvcm1fc2VsZWN0b3IpIDogZm9ybV9zZWxlY3RvcjtcbiAgICAgICAgY29uc3QgZm9ybV9kYXRhID0gRm9ybV9VdGlscy5zZXJpYWxpemUoJGZvcm0pO1xuXG4gICAgICAgIEZvcm1fVXRpbHMucmVzZXRfZm9ybV9lcnJvcnMoZm9ybV9zZWxlY3Rvcik7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgQWpheC5jYWxsKGNvbnRyb2xsZXIsIGFjdGlvbiwgZm9ybV9kYXRhKTtcblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMub25fc3VjY2Vzcykge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMub25fc3VjY2VzcyhyZXNwb25zZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXNwb25zZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGlmIChlcnJvci50eXBlID09PSAnZm9ybV9lcnJvcicgJiYgZXJyb3IuZGV0YWlscykge1xuICAgICAgICAgICAgICAgIGF3YWl0IEZvcm1fVXRpbHMuYXBwbHlfZm9ybV9lcnJvcnMoZm9ybV9zZWxlY3RvciwgZXJyb3IuZGV0YWlscyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGF3YWl0IEZvcm1fVXRpbHMuYXBwbHlfZm9ybV9lcnJvcnMoZm9ybV9zZWxlY3RvciwgZXJyb3IubWVzc2FnZSB8fCAnQW4gZXJyb3Igb2NjdXJyZWQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMub25fZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zLm9uX2Vycm9yKGVycm9yKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGZvcm0gdmFsaWRhdGlvbiBlcnJvcnNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFyZW50X3NlbGVjdG9yIC0galF1ZXJ5IHNlbGVjdG9yIGZvciBwYXJlbnQgZWxlbWVudFxuICAgICAqL1xuICAgIHN0YXRpYyByZXNldF9mb3JtX2Vycm9ycyhwYXJlbnRfc2VsZWN0b3IpIHtcbiAgICAgICAgY29uc3QgJHBhcmVudCA9ICQocGFyZW50X3NlbGVjdG9yKTtcblxuICAgICAgICAvLyBSZW1vdmUgZmxhc2ggbWVzc2FnZXNcbiAgICAgICAgJCgnLmZsYXNoLW1lc3NhZ2VzJykucmVtb3ZlKCk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGFsZXJ0LWRhbmdlciBtZXNzYWdlc1xuICAgICAgICAkcGFyZW50LmZpbmQoJy5hbGVydC1kYW5nZXInKS5yZW1vdmUoKTtcblxuICAgICAgICAvLyBSZW1vdmUgdmFsaWRhdGlvbiBlcnJvciBjbGFzc2VzIGFuZCB0ZXh0IGZyb20gZm9ybSBlbGVtZW50c1xuICAgICAgICAkcGFyZW50LmZpbmQoJy5pcy1pbnZhbGlkJykucmVtb3ZlQ2xhc3MoJ2lzLWludmFsaWQnKTtcbiAgICAgICAgJHBhcmVudC5maW5kKCcuaW52YWxpZC1mZWVkYmFjaycpLnJlbW92ZSgpO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gICAgLyoqXG4gICAgICogTm9ybWFsaXplcyBlcnJvciBpbnB1dCBpbnRvIHN0YW5kYXJkIGZvcm1hdHNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R8QXJyYXl9IGVycm9ycyAtIFJhdyBlcnJvciBpbnB1dFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IE5vcm1hbGl6ZWQgZXJyb3JzIGFzIHt0eXBlOiAnc3RyaW5nJ3wnYXJyYXknfCdmaWVsZHMnLCBkYXRhOiAuLi59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX25vcm1hbGl6ZV9lcnJvcnMoZXJyb3JzKSB7XG4gICAgICAgIC8vIEhhbmRsZSBudWxsL3VuZGVmaW5lZFxuICAgICAgICBpZiAoIWVycm9ycykge1xuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3N0cmluZycsIGRhdGE6ICdBbiBlcnJvciBoYXMgb2NjdXJyZWQnIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW5kbGUgc3RyaW5nXG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3JzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3N0cmluZycsIGRhdGE6IGVycm9ycyB9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIGFycmF5XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGVycm9ycykpIHtcbiAgICAgICAgICAgIC8vIEFycmF5IG9mIHN0cmluZ3MgLSBnZW5lcmFsIGVycm9yc1xuICAgICAgICAgICAgaWYgKGVycm9ycy5ldmVyeSgoZSkgPT4gdHlwZW9mIGUgPT09ICdzdHJpbmcnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdhcnJheScsIGRhdGE6IGVycm9ycyB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gQXJyYXkgd2l0aCBvYmplY3QgYXMgZmlyc3QgZWxlbWVudCAtIGV4dHJhY3QgaXRcbiAgICAgICAgICAgIGlmIChlcnJvcnMubGVuZ3RoID4gMCAmJiB0eXBlb2YgZXJyb3JzWzBdID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIHJldHVybiBGb3JtX1V0aWxzLl9ub3JtYWxpemVfZXJyb3JzKGVycm9yc1swXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBFbXB0eSBvciBtaXhlZCBhcnJheVxuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2FycmF5JywgZGF0YTogW10gfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBvYmplY3QgLSBjaGVjayBmb3IgTGFyYXZlbCByZXNwb25zZSB3cmFwcGVyXG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3JzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgLy8gVW53cmFwIHtlcnJvcnM6IHsuLi59fSBvciB7ZXJyb3I6IHsuLi59fVxuICAgICAgICAgICAgY29uc3QgdW53cmFwcGVkID0gZXJyb3JzLmVycm9ycyB8fCBlcnJvcnMuZXJyb3I7XG4gICAgICAgICAgICBpZiAodW53cmFwcGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZvcm1fVXRpbHMuX25vcm1hbGl6ZV9lcnJvcnModW53cmFwcGVkKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ29udmVydCBMYXJhdmVsIHZhbGlkYXRvciBmb3JtYXQge2ZpZWxkOiBbbXNnMSwgbXNnMl19IHRvIHtmaWVsZDogbXNnMX1cbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gZXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9ycy5oYXNPd25Qcm9wZXJ0eShmaWVsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBlcnJvcnNbZmllbGRdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZFtmaWVsZF0gPSB2YWx1ZVswXTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkW2ZpZWxkXSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZFtmaWVsZF0gPSBTdHJpbmcodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnZmllbGRzJywgZGF0YTogbm9ybWFsaXplZCB9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRmluYWwgY2F0Y2gtYWxsKlxuICAgICAgICByZXR1cm4geyB0eXBlOiAnc3RyaW5nJywgZGF0YTogU3RyaW5nKGVycm9ycykgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGR1cGxpY2F0ZSBlcnJvciBtZXNzYWdlcyBmcm9tIGFycmF5IG9yIG9iamVjdCB2YWx1ZXNcbiAgICAgKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gZXJyb3JzIC0gRXJyb3JzIHRvIGRlZHVwbGljYXRlXG4gICAgICogQHJldHVybnMge0FycmF5fE9iamVjdH0gRGVkdXBsaWNhdGVkIGVycm9yc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9kZWR1cGxpY2F0ZV9lcnJvcnMoZXJyb3JzKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGVycm9ycykpIHtcbiAgICAgICAgICAgIHJldHVybiBbLi4ubmV3IFNldChlcnJvcnMpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3JzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgY29uc3Qgc2VlbiA9IG5ldyBTZXQoKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBlcnJvcnNba2V5XTtcbiAgICAgICAgICAgICAgICBpZiAoIXNlZW4uaGFzKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBzZWVuLmFkZCh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlcnJvcnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyBmaWVsZC1zcGVjaWZpYyB2YWxpZGF0aW9uIGVycm9ycyB0byBmb3JtIGlucHV0c1xuICAgICAqIEBwYXJhbSB7alF1ZXJ5fSAkcGFyZW50IC0gUGFyZW50IGVsZW1lbnQgY29udGFpbmluZyBmb3JtXG4gICAgICogQHBhcmFtIHtPYmplY3R9IGZpZWxkX2Vycm9ycyAtIE9iamVjdCBtYXBwaW5nIGZpZWxkIG5hbWVzIHRvIGVycm9yIG1lc3NhZ2VzXG4gICAgICogQHJldHVybnMge09iamVjdH0gT2JqZWN0IGNvbnRhaW5pbmcge2FuaW1hdGlvbnM6IEFycmF5LCB1bm1hdGNoZWQ6IE9iamVjdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYXBwbHlfZmllbGRfZXJyb3JzKCRwYXJlbnQsIGZpZWxkX2Vycm9ycykge1xuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gW107XG4gICAgICAgIGNvbnN0IHVubWF0Y2hlZCA9IHt9O1xuXG4gICAgICAgIGZvciAoY29uc3QgZmllbGRfbmFtZSBpbiBmaWVsZF9lcnJvcnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yX21lc3NhZ2UgPSBmaWVsZF9lcnJvcnNbZmllbGRfbmFtZV07XG4gICAgICAgICAgICBjb25zdCAkaW5wdXQgPSAkcGFyZW50LmZpbmQoYFtuYW1lPVwiJHtmaWVsZF9uYW1lfVwiXWApO1xuXG4gICAgICAgICAgICBpZiAoISRpbnB1dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB1bm1hdGNoZWRbZmllbGRfbmFtZV0gPSBlcnJvcl9tZXNzYWdlO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCAkZXJyb3IgPSAkKCc8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiPjwvZGl2PicpLmh0bWwoZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgICAgICBjb25zdCAkdGFyZ2V0ID0gJGlucHV0LmNsb3Nlc3QoJy5mb3JtLWdyb3VwLCAuZm9ybS1jaGVjaywgLmlucHV0LWdyb3VwJyk7XG5cbiAgICAgICAgICAgIGlmICghJHRhcmdldC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB1bm1hdGNoZWRbZmllbGRfbmFtZV0gPSBlcnJvcl9tZXNzYWdlO1xuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAkaW5wdXQuYWRkQ2xhc3MoJ2lzLWludmFsaWQnKTtcbiAgICAgICAgICAgICRlcnJvci5hcHBlbmRUbygkdGFyZ2V0KTtcbiAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkZXJyb3IuaGlkZSgpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyBhbmltYXRpb25zLCB1bm1hdGNoZWQgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIGNvbWJpbmVkIGVycm9yIG1lc3NhZ2Ugd2l0aCBzdW1tYXJ5IGFuZCB1bm1hdGNoZWQgZmllbGQgZXJyb3JzXG4gICAgICogQHBhcmFtIHtqUXVlcnl9ICRwYXJlbnQgLSBQYXJlbnQgZWxlbWVudCBjb250YWluaW5nIGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3VtbWFyeV9tc2cgLSBTdW1tYXJ5IG1lc3NhZ2UgKGUuZy4sIFwiUGxlYXNlIGNvcnJlY3QgdGhlIGVycm9ycyBiZWxvd1wiKVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSB1bm1hdGNoZWRfZXJyb3JzIC0gT2JqZWN0IG9mIGZpZWxkIGVycm9ycyB0aGF0IGNvdWxkbid0IGJlIG1hdGNoZWQgdG8gZmllbGRzXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBhbmltYXRpb24gcHJvbWlzZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYXBwbHlfY29tYmluZWRfZXJyb3IoJHBhcmVudCwgc3VtbWFyeV9tc2csIHVubWF0Y2hlZF9lcnJvcnMpIHtcbiAgICAgICAgY29uc3QgYW5pbWF0aW9ucyA9IFtdO1xuICAgICAgICBjb25zdCAkZXJyb3JfY29udGFpbmVyID0gJHBhcmVudC5maW5kKCdbZGF0YS1pZD1cImVycm9yX2NvbnRhaW5lclwiXScpLmZpcnN0KCk7XG4gICAgICAgIGNvbnN0ICR0YXJnZXQgPSAkZXJyb3JfY29udGFpbmVyLmxlbmd0aCA+IDAgPyAkZXJyb3JfY29udGFpbmVyIDogJHBhcmVudDtcblxuICAgICAgICAvLyBDcmVhdGUgYWxlcnQgd2l0aCBzdW1tYXJ5IG1lc3NhZ2UgYW5kIGJ1bGxldGVkIGxpc3Qgb2YgdW5tYXRjaGVkIGVycm9yc1xuICAgICAgICBjb25zdCAkYWxlcnQgPSAkKCc8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+PC9kaXY+Jyk7XG5cbiAgICAgICAgLy8gQWRkIHN1bW1hcnkgbWVzc2FnZSBpZiBwcm92aWRlZFxuICAgICAgICBpZiAoc3VtbWFyeV9tc2cpIHtcbiAgICAgICAgICAgICQoJzxwIGNsYXNzPVwibWItMlwiPjwvcD4nKS50ZXh0KHN1bW1hcnlfbXNnKS5hcHBlbmRUbygkYWxlcnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHVubWF0Y2hlZCBlcnJvcnMgYXMgYnVsbGV0ZWQgbGlzdFxuICAgICAgICBpZiAoT2JqZWN0LmtleXModW5tYXRjaGVkX2Vycm9ycykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgJGxpc3QgPSAkKCc8dWwgY2xhc3M9XCJtYi0wXCI+PC91bD4nKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZmllbGRfbmFtZSBpbiB1bm1hdGNoZWRfZXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3JfbXNnID0gdW5tYXRjaGVkX2Vycm9yc1tmaWVsZF9uYW1lXTtcbiAgICAgICAgICAgICAgICAkKCc8bGk+PC9saT4nKS5odG1sKGVycm9yX21zZykuYXBwZW5kVG8oJGxpc3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJGxpc3QuYXBwZW5kVG8oJGFsZXJ0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgkZXJyb3JfY29udGFpbmVyLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkYWxlcnQuaGlkZSgpLmFwcGVuZFRvKCR0YXJnZXQpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGFsZXJ0LmhpZGUoKS5wcmVwZW5kVG8oJHRhcmdldCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhbmltYXRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgZ2VuZXJhbCBlcnJvciBtZXNzYWdlcyBhcyBhbGVydCBib3hcbiAgICAgKiBAcGFyYW0ge2pRdWVyeX0gJHBhcmVudCAtIFBhcmVudCBlbGVtZW50IHRvIHByZXBlbmQgYWxlcnQgdG9cbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xBcnJheX0gbWVzc2FnZXMgLSBFcnJvciBtZXNzYWdlKHMpIHRvIGRpc3BsYXlcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIGFuaW1hdGlvbiBwcm9taXNlc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9hcHBseV9nZW5lcmFsX2Vycm9ycygkcGFyZW50LCBtZXNzYWdlcykge1xuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gW107XG5cbiAgICAgICAgLy8gTG9vayBmb3IgYSBzcGVjaWZpYyBlcnJvciBjb250YWluZXIgZGl2IChlLmcuLCBpbiBSc3hfRm9ybSBjb21wb25lbnQpXG4gICAgICAgIGNvbnN0ICRlcnJvcl9jb250YWluZXIgPSAkcGFyZW50LmZpbmQoJ1tkYXRhLWlkPVwiZXJyb3JfY29udGFpbmVyXCJdJykuZmlyc3QoKTtcbiAgICAgICAgY29uc3QgJHRhcmdldCA9ICRlcnJvcl9jb250YWluZXIubGVuZ3RoID4gMCA/ICRlcnJvcl9jb250YWluZXIgOiAkcGFyZW50O1xuXG4gICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAvLyBTaW5nbGUgZXJyb3IgLSBzaW1wbGUgYWxlcnQgd2l0aG91dCBsaXN0XG4gICAgICAgICAgICBjb25zdCAkYWxlcnQgPSAkKCc8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+PC9kaXY+JykudGV4dChtZXNzYWdlcyk7XG4gICAgICAgICAgICBpZiAoJGVycm9yX2NvbnRhaW5lci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRhbGVydC5oaWRlKCkuYXBwZW5kVG8oJHRhcmdldCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRhbGVydC5oaWRlKCkucHJlcGVuZFRvKCR0YXJnZXQpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShtZXNzYWdlcykgJiYgbWVzc2FnZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLy8gTXVsdGlwbGUgZXJyb3JzIC0gYnVsbGV0ZWQgbGlzdFxuICAgICAgICAgICAgY29uc3QgJGFsZXJ0ID0gJCgnPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiIHJvbGU9XCJhbGVydFwiPjx1bCBjbGFzcz1cIm1iLTBcIj48L3VsPjwvZGl2PicpO1xuICAgICAgICAgICAgY29uc3QgJGxpc3QgPSAkYWxlcnQuZmluZCgndWwnKTtcblxuICAgICAgICAgICAgbWVzc2FnZXMuZm9yRWFjaCgobXNnKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgdGV4dCA9IChtc2cgKyAnJykudHJpbSgpIHx8ICdBbiBlcnJvciBoYXMgb2NjdXJyZWQnO1xuICAgICAgICAgICAgICAgICQoJzxsaT48L2xpPicpLmh0bWwodGV4dCkuYXBwZW5kVG8oJGxpc3QpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmICgkZXJyb3JfY29udGFpbmVyLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGFsZXJ0LmhpZGUoKS5hcHBlbmRUbygkdGFyZ2V0KS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGFsZXJ0LmhpZGUoKS5wcmVwZW5kVG8oJHRhcmdldCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbWVzc2FnZXMgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KG1lc3NhZ2VzKSkge1xuICAgICAgICAgICAgLy8gT2JqZWN0IG9mIHVubWF0Y2hlZCBmaWVsZCBlcnJvcnMgLSBjb252ZXJ0IHRvIGFycmF5XG4gICAgICAgICAgICBjb25zdCBlcnJvcl9saXN0ID0gT2JqZWN0LnZhbHVlcyhtZXNzYWdlcylcbiAgICAgICAgICAgICAgICAubWFwKCh2KSA9PiBTdHJpbmcodikudHJpbSgpKVxuICAgICAgICAgICAgICAgIC5maWx0ZXIoKHYpID0+IHYpO1xuICAgICAgICAgICAgaWYgKGVycm9yX2xpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBGb3JtX1V0aWxzLl9hcHBseV9nZW5lcmFsX2Vycm9ycygkcGFyZW50LCBlcnJvcl9saXN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhbmltYXRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZXMgdGhlIHRvdGFsIGhlaWdodCBvZiBmaXhlZC9zdGlja3kgaGVhZGVycyBhdCB0aGUgdG9wIG9mIHRoZSBwYWdlXG4gICAgICogQHJldHVybnMge251bWJlcn0gVG90YWwgaGVpZ2h0IGluIHBpeGVscyBvZiBmaXhlZCB0b3AgZWxlbWVudHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZ2V0X2ZpeGVkX2hlYWRlcl9oZWlnaHQoKSB7XG4gICAgICAgIGxldCB0b3RhbF9oZWlnaHQgPSAwO1xuXG4gICAgICAgIC8vIEZpbmQgYWxsIGZpeGVkIG9yIHN0aWNreSBwb3NpdGlvbmVkIGVsZW1lbnRzXG4gICAgICAgICQoJyonKS5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgY29uc3QgJGVsID0gJCh0aGlzKTtcbiAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gJGVsLmNzcygncG9zaXRpb24nKTtcblxuICAgICAgICAgICAgLy8gT25seSBjaGVjayBmaXhlZCBvciBzdGlja3kgZWxlbWVudHNcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiAhPT0gJ2ZpeGVkJyAmJiBwb3NpdGlvbiAhPT0gJ3N0aWNreScpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGVsZW1lbnQgaXMgcG9zaXRpb25lZCBhdCBvciBuZWFyIHRoZSB0b3BcbiAgICAgICAgICAgIGNvbnN0IHRvcCA9IHBhcnNlSW50KCRlbC5jc3MoJ3RvcCcpKSB8fCAwO1xuICAgICAgICAgICAgaWYgKHRvcCA+IDUwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBOb3QgYSB0b3AgaGVhZGVyXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGVsZW1lbnQgaXMgdmlzaWJsZVxuICAgICAgICAgICAgaWYgKCEkZWwuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGVsZW1lbnQgc3BhbnMgc2lnbmlmaWNhbnQgd2lkdGggKGxpa2VseSBhIGhlYWRlci9uYXZiYXIpXG4gICAgICAgICAgICBjb25zdCB3aWR0aCA9ICRlbC5vdXRlcldpZHRoKCk7XG4gICAgICAgICAgICBjb25zdCB2aWV3cG9ydF93aWR0aCA9ICQod2luZG93KS53aWR0aCgpO1xuICAgICAgICAgICAgaWYgKHdpZHRoIDwgdmlld3BvcnRfd2lkdGggKiAwLjUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47IC8vIFRvbyBuYXJyb3cgdG8gYmUgYSBoZWFkZXJcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWRkIHRoaXMgZWxlbWVudCdzIGhlaWdodFxuICAgICAgICAgICAgdG90YWxfaGVpZ2h0ICs9ICRlbC5vdXRlckhlaWdodCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdG90YWxfaGVpZ2h0O1xuICAgIH1cbn1cbiIsIi8qKlxuICogRGVidWdnZXIgY2xhc3MgZm9yIGNvbnNvbGVfZGVidWcgYW5kIGJyb3dzZXIgZXJyb3IgbG9nZ2luZ1xuICogSGFuZGxlcyBiYXRjaGVkIHN1Ym1pc3Npb24gdG8gc2VydmVyIHdoZW4gY29uZmlndXJlZFxuICovXG5jbGFzcyBEZWJ1Z2dlciB7XG4gICAgLy8gQmF0Y2hpbmcgc3RhdGUgZm9yIGNvbnNvbGVfZGVidWcgbWVzc2FnZXNcbiAgICBzdGF0aWMgX2NvbnNvbGVfYmF0Y2ggPSBbXTtcbiAgICBzdGF0aWMgX2NvbnNvbGVfdGltZXIgPSBudWxsO1xuICAgIHN0YXRpYyBfY29uc29sZV9iYXRjaF9jb3VudCA9IDA7XG5cbiAgICAvLyBCYXRjaGluZyBzdGF0ZSBmb3IgZXJyb3IgbWVzc2FnZXNcbiAgICBzdGF0aWMgX2Vycm9yX2JhdGNoID0gW107XG4gICAgc3RhdGljIF9lcnJvcl90aW1lciA9IG51bGw7XG4gICAgc3RhdGljIF9lcnJvcl9jb3VudCA9IDA7XG4gICAgc3RhdGljIF9lcnJvcl9iYXRjaF9jb3VudCA9IDA7XG5cbiAgICAvLyBDb25zdGFudHNcbiAgICBzdGF0aWMgREVCT1VOQ0VfTVMgPSAyMDAwO1xuICAgIHN0YXRpYyBNQVhfRVJST1JTX1BFUl9QQUdFID0gMjA7XG4gICAgc3RhdGljIE1BWF9FUlJPUl9CQVRDSEVTID0gNTtcblxuICAgIC8vIFN0b3JlIHN0YXJ0IHRpbWUgZm9yIGJlbmNobWFya2luZ1xuICAgIHN0YXRpYyBfc3RhcnRfdGltZSA9IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGZyYW1ld29yayBlcnJvciBoYW5kbGluZ1xuICAgICAqIENhbGxlZCBkdXJpbmcgZnJhbWV3b3JrIGluaXRpYWxpemF0aW9uXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9pbml0KCkge1xuICAgICAgICAvLyBDaGVjayBpZiBicm93c2VyIGVycm9yIGxvZ2dpbmcgaXMgZW5hYmxlZFxuICAgICAgICBpZiAod2luZG93LnJzeGFwcCAmJiB3aW5kb3cucnN4YXBwLmxvZ19icm93c2VyX2Vycm9ycykge1xuICAgICAgICAgICAgLy8gUmVnaXN0ZXIgZ2xvYmFsIGVycm9yIGhhbmRsZXJcbiAgICAgICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdlcnJvcicsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIERlYnVnZ2VyLl9oYW5kbGVfYnJvd3Nlcl9lcnJvcih7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGV2ZW50Lm1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgIGZpbGVuYW1lOiBldmVudC5maWxlbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgbGluZW5vOiBldmVudC5saW5lbm8sXG4gICAgICAgICAgICAgICAgICAgIGNvbG5vOiBldmVudC5jb2xubyxcbiAgICAgICAgICAgICAgICAgICAgc3RhY2s6IGV2ZW50LmVycm9yID8gZXZlbnQuZXJyb3Iuc3RhY2sgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIHVuaGFuZGxlZCBwcm9taXNlIHJlamVjdGlvbiBoYW5kbGVyXG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigndW5oYW5kbGVkcmVqZWN0aW9uJywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgRGVidWdnZXIuX2hhbmRsZV9icm93c2VyX2Vycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogZXZlbnQucmVhc29uID8gZXZlbnQucmVhc29uLm1lc3NhZ2UgfHwgU3RyaW5nKGV2ZW50LnJlYXNvbikgOiAnVW5oYW5kbGVkIHByb21pc2UgcmVqZWN0aW9uJyxcbiAgICAgICAgICAgICAgICAgICAgc3RhY2s6IGV2ZW50LnJlYXNvbiAmJiBldmVudC5yZWFzb24uc3RhY2sgPyBldmVudC5yZWFzb24uc3RhY2sgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAndW5oYW5kbGVkcmVqZWN0aW9uJyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVnaXN0ZXIgdWkgcmVmcmVzaCBoYW5kbGVyXG4gICAgICAgIFJzeC5vbigncmVmcmVzaCcsIERlYnVnZ2VyLm9uX3JlZnJlc2gpO1xuICAgIH1cblxuICAgIC8vIEluIGRldiBtb2RlLCBzb21lIHVpIGVsZW1lbnRzIGNhbiBiZSBhdXRvbWF0aWNhbGx5IGFwcGxpZWQgdG8gYXNzaXN0IHdpdGggZGV2ZWxvcG1lbnRcbiAgICBzdGF0aWMgb25fcmVmcmVzaCgpIHtcbiAgICAgICAgaWYgKCFSc3guaXNfcHJvZCgpKSB7XG4gICAgICAgICAgICAvLyBBZGQgYW4gdW5kZXJsaW5lIDIgcHggYmx1ZSB0byBhbGwgYSB0YWdzIHdpdGggaHJlZiA9PT0gXCIjXCIgdXNpbmcganF1ZXJ5XG4gICAgICAgICAgICAvLyBUb2RvOiBtYXliZSB0aGlzIHNob3VsZCBiZSBhIGNvbmZpZ3VyYWJsZSBkZWJ1ZyBvcHRpb24/XG4gICAgICAgICAgICAvLyAkKCdhW2hyZWY9XCIjXCJdJykuY3NzKHtcbiAgICAgICAgICAgIC8vICAgICAnYm9yZGVyLWJvdHRvbSc6ICcycHggc29saWQgYmx1ZScsXG4gICAgICAgICAgICAvLyAgICAgJ3RleHQtZGVjb3JhdGlvbic6ICdub25lJ1xuICAgICAgICAgICAgLy8gfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIGNvbnNvbGVfZGVidWdcbiAgICAgKiBNaXJyb3JzIFBIUCBmdW5jdGlvbmFsaXR5IHdpdGggYmF0Y2hpbmcgZm9yIExhcmF2ZWwgbG9nXG4gICAgICovXG4gICAgc3RhdGljIGNvbnNvbGVfZGVidWcoY2hhbm5lbCwgLi4udmFsdWVzKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIGNvbnNvbGVfZGVidWcgaXMgZW5hYmxlZFxuICAgICAgICBpZiAoIXdpbmRvdy5yc3hhcHAgfHwgIXdpbmRvdy5yc3hhcHAuY29uc29sZV9kZWJ1ZyB8fCAhd2luZG93LnJzeGFwcC5jb25zb2xlX2RlYnVnLmVuYWJsZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHdpbmRvdy5yc3hhcHAuY29uc29sZV9kZWJ1ZztcblxuICAgICAgICAvLyBOb3JtYWxpemUgY2hhbm5lbCBuYW1lXG4gICAgICAgIGNoYW5uZWwgPSBTdHJpbmcoY2hhbm5lbClcbiAgICAgICAgICAgIC50b1VwcGVyQ2FzZSgpXG4gICAgICAgICAgICAucmVwbGFjZSgvW1xcW1xcXV0vZywgJycpO1xuXG4gICAgICAgIC8vIEFwcGx5IGZpbHRlcmluZ1xuICAgICAgICBpZiAoY29uZmlnLmZpbHRlcl9tb2RlID09PSAnc3BlY2lmaWMnKSB7XG4gICAgICAgICAgICBjb25zdCBzcGVjaWZpYyA9IGNvbmZpZy5zcGVjaWZpY19jaGFubmVsO1xuICAgICAgICAgICAgaWYgKHNwZWNpZmljKSB7XG4gICAgICAgICAgICAgICAgLy8gU3BsaXQgY29tbWEtc2VwYXJhdGVkIHZhbHVlcyBhbmQgbm9ybWFsaXplXG4gICAgICAgICAgICAgICAgY29uc3QgY2hhbm5lbHMgPSBzcGVjaWZpYy5zcGxpdCgnLCcpLm1hcCgoYykgPT4gYy50cmltKCkudG9VcHBlckNhc2UoKSk7XG4gICAgICAgICAgICAgICAgaWYgKCFjaGFubmVscy5pbmNsdWRlcyhjaGFubmVsKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGNvbmZpZy5maWx0ZXJfbW9kZSA9PT0gJ3doaXRlbGlzdCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHdoaXRlbGlzdCA9IChjb25maWcuZmlsdGVyX2NoYW5uZWxzIHx8IFtdKS5tYXAoKGMpID0+IGMudG9VcHBlckNhc2UoKSk7XG4gICAgICAgICAgICBpZiAoIXdoaXRlbGlzdC5pbmNsdWRlcyhjaGFubmVsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjb25maWcuZmlsdGVyX21vZGUgPT09ICdibGFja2xpc3QnKSB7XG4gICAgICAgICAgICBjb25zdCBibGFja2xpc3QgPSAoY29uZmlnLmZpbHRlcl9jaGFubmVscyB8fCBbXSkubWFwKChjKSA9PiBjLnRvVXBwZXJDYXNlKCkpO1xuICAgICAgICAgICAgaWYgKGJsYWNrbGlzdC5pbmNsdWRlcyhjaGFubmVsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXBhcmUgdGhlIG1lc3NhZ2VcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSB7XG4gICAgICAgICAgICBjaGFubmVsOiBjaGFubmVsLFxuICAgICAgICAgICAgdmFsdWVzOiB2YWx1ZXMsXG4gICAgICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBBZGQgbG9jYXRpb24gaWYgY29uZmlndXJlZFxuICAgICAgICBpZiAoY29uZmlnLmluY2x1ZGVfbG9jYXRpb24gfHwgY29uZmlnLmluY2x1ZGVfYmFja3RyYWNlKSB7XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgICAgICAgICAgY29uc3Qgc3RhY2sgPSBlcnJvci5zdGFjayB8fCAnJztcbiAgICAgICAgICAgIGNvbnN0IHN0YWNrTGluZXMgPSBzdGFjay5zcGxpdCgnXFxuJyk7XG5cbiAgICAgICAgICAgIGlmIChjb25maWcuaW5jbHVkZV9sb2NhdGlvbiAmJiBzdGFja0xpbmVzLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgICAgICAgICAvLyBTa2lwIEVycm9yIGxpbmUgYW5kIHRoaXMgZnVuY3Rpb25cbiAgICAgICAgICAgICAgICBjb25zdCBjYWxsZXJMaW5lID0gc3RhY2tMaW5lc1syXSB8fCAnJztcbiAgICAgICAgICAgICAgICBjb25zdCBtYXRjaCA9IGNhbGxlckxpbmUubWF0Y2goL2F0XFxzKy4qP1xccytcXCgoLio/KTooXFxkKyk6KFxcZCspXFwpLykgfHwgY2FsbGVyTGluZS5tYXRjaCgvYXRcXHMrKC4qPyk6KFxcZCspOihcXGQrKS8pO1xuICAgICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmxvY2F0aW9uID0gYCR7bWF0Y2hbMV19OiR7bWF0Y2hbMl19YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcuaW5jbHVkZV9iYWNrdHJhY2UpIHtcbiAgICAgICAgICAgICAgICAvLyBJbmNsdWRlIGZpcnN0IDUgc3RhY2sgZnJhbWVzLCBza2lwcGluZyB0aGlzIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5iYWNrdHJhY2UgPSBzdGFja0xpbmVzXG4gICAgICAgICAgICAgICAgICAgIC5zbGljZSgyLCA3KVxuICAgICAgICAgICAgICAgICAgICAubWFwKChsaW5lKSA9PiBsaW5lLnRyaW0oKSlcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcigobGluZSkgPT4gbGluZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPdXRwdXQgdG8gYnJvd3NlciBjb25zb2xlIGlmIGVuYWJsZWRcbiAgICAgICAgaWYgKGNvbmZpZy5vdXRwdXRzICYmIGNvbmZpZy5vdXRwdXRzLmJyb3dzZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IHByZWZpeCA9IGNvbmZpZy5pbmNsdWRlX2JlbmNobWFyayA/IGBbJHtEZWJ1Z2dlci5fZ2V0X3RpbWVfcHJlZml4KCl9XSBgIDogJyc7XG4gICAgICAgICAgICBjb25zdCBjaGFubmVsUHJlZml4ID0gYFske2NoYW5uZWx9XWA7XG5cbiAgICAgICAgICAgIC8vIFVzZSBhcHByb3ByaWF0ZSBjb25zb2xlIG1ldGhvZCBiYXNlZCBvbiBjaGFubmVsXG4gICAgICAgICAgICBsZXQgY29uc29sZU1ldGhvZCA9ICdsb2cnO1xuICAgICAgICAgICAgaWYgKGNoYW5uZWwuaW5jbHVkZXMoJ0VSUk9SJykpIGNvbnNvbGVNZXRob2QgPSAnZXJyb3InO1xuICAgICAgICAgICAgZWxzZSBpZiAoY2hhbm5lbC5pbmNsdWRlcygnV0FSTicpKSBjb25zb2xlTWV0aG9kID0gJ3dhcm4nO1xuICAgICAgICAgICAgZWxzZSBpZiAoY2hhbm5lbC5pbmNsdWRlcygnSU5GTycpKSBjb25zb2xlTWV0aG9kID0gJ2luZm8nO1xuXG4gICAgICAgICAgICBjb25zb2xlW2NvbnNvbGVNZXRob2RdKHByZWZpeCArIGNoYW5uZWxQcmVmaXgsIC4uLnZhbHVlcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBCYXRjaCBmb3IgTGFyYXZlbCBsb2cgaWYgZW5hYmxlZFxuICAgICAgICBpZiAoY29uZmlnLm91dHB1dHMgJiYgY29uZmlnLm91dHB1dHMubGFyYXZlbF9sb2cpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLl9iYXRjaF9jb25zb2xlX21lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2cgYW4gZXJyb3IgdG8gdGhlIHNlcnZlclxuICAgICAqIFVzZWQgbWFudWFsbHkgb3IgYnkgQWpheCBlcnJvciBoYW5kbGluZ1xuICAgICAqL1xuICAgIHN0YXRpYyBsb2dfZXJyb3IoZXJyb3IpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgYnJvd3NlciBlcnJvciBsb2dnaW5nIGlzIGVuYWJsZWRcbiAgICAgICAgaWYgKCF3aW5kb3cucnN4YXBwIHx8ICF3aW5kb3cucnN4YXBwLmxvZ19icm93c2VyX2Vycm9ycykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTm9ybWFsaXplIGVycm9yIGZvcm1hdFxuICAgICAgICBsZXQgZXJyb3JEYXRhID0ge307XG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBlcnJvckRhdGEubWVzc2FnZSA9IGVycm9yO1xuICAgICAgICAgICAgZXJyb3JEYXRhLnR5cGUgPSAnbWFudWFsJztcbiAgICAgICAgfSBlbHNlIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgICAgICBlcnJvckRhdGEubWVzc2FnZSA9IGVycm9yLm1lc3NhZ2U7XG4gICAgICAgICAgICBlcnJvckRhdGEuc3RhY2sgPSBlcnJvci5zdGFjaztcbiAgICAgICAgICAgIGVycm9yRGF0YS50eXBlID0gJ2V4Y2VwdGlvbic7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgJiYgdHlwZW9mIGVycm9yID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgZXJyb3JEYXRhID0gZXJyb3I7XG4gICAgICAgICAgICBpZiAoIWVycm9yRGF0YS50eXBlKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JEYXRhLnR5cGUgPSAnbWFudWFsJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIERlYnVnZ2VyLl9oYW5kbGVfYnJvd3Nlcl9lcnJvcihlcnJvckRhdGEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBIYW5kbGUgYnJvd3NlciBlcnJvcnMgd2l0aCBiYXRjaGluZ1xuICAgICAqL1xuICAgIHN0YXRpYyBfaGFuZGxlX2Jyb3dzZXJfZXJyb3IoZXJyb3JEYXRhKSB7XG4gICAgICAgIC8vIENoZWNrIGxpbWl0c1xuICAgICAgICBpZiAoRGVidWdnZXIuX2Vycm9yX2NvdW50ID49IERlYnVnZ2VyLk1BWF9FUlJPUlNfUEVSX1BBR0UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoRGVidWdnZXIuX2Vycm9yX2JhdGNoX2NvdW50ID49IERlYnVnZ2VyLk1BWF9FUlJPUl9CQVRDSEVTKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBEZWJ1Z2dlci5fZXJyb3JfY291bnQrKztcblxuICAgICAgICAvLyBBZGQgbWV0YWRhdGFcbiAgICAgICAgZXJyb3JEYXRhLnVybCA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuICAgICAgICBlcnJvckRhdGEudXNlckFnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICAgICAgZXJyb3JEYXRhLnRpbWVzdGFtcCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcblxuICAgICAgICAvLyBBZGQgdG8gYmF0Y2hcbiAgICAgICAgRGVidWdnZXIuX2Vycm9yX2JhdGNoLnB1c2goZXJyb3JEYXRhKTtcblxuICAgICAgICAvLyBDbGVhciBleGlzdGluZyB0aW1lclxuICAgICAgICBpZiAoRGVidWdnZXIuX2Vycm9yX3RpbWVyKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoRGVidWdnZXIuX2Vycm9yX3RpbWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBkZWJvdW5jZSB0aW1lclxuICAgICAgICBEZWJ1Z2dlci5fZXJyb3JfdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIERlYnVnZ2VyLl9mbHVzaF9lcnJvcl9iYXRjaCgpO1xuICAgICAgICB9LCBEZWJ1Z2dlci5ERUJPVU5DRV9NUyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEJhdGNoIGNvbnNvbGVfZGVidWcgbWVzc2FnZXMgZm9yIExhcmF2ZWwgbG9nXG4gICAgICovXG4gICAgc3RhdGljIF9iYXRjaF9jb25zb2xlX21lc3NhZ2UobWVzc2FnZSkge1xuICAgICAgICBEZWJ1Z2dlci5fY29uc29sZV9iYXRjaC5wdXNoKG1lc3NhZ2UpO1xuXG4gICAgICAgIC8vIENsZWFyIGV4aXN0aW5nIHRpbWVyXG4gICAgICAgIGlmIChEZWJ1Z2dlci5fY29uc29sZV90aW1lcikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KERlYnVnZ2VyLl9jb25zb2xlX3RpbWVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNldCBkZWJvdW5jZSB0aW1lclxuICAgICAgICBEZWJ1Z2dlci5fY29uc29sZV90aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgRGVidWdnZXIuX2ZsdXNoX2NvbnNvbGVfYmF0Y2goKTtcbiAgICAgICAgfSwgRGVidWdnZXIuREVCT1VOQ0VfTVMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBGbHVzaCBjb25zb2xlX2RlYnVnIGJhdGNoIHRvIHNlcnZlclxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfZmx1c2hfY29uc29sZV9iYXRjaCgpIHtcbiAgICAgICAgaWYgKERlYnVnZ2VyLl9jb25zb2xlX2JhdGNoLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbWVzc2FnZXMgPSBEZWJ1Z2dlci5fY29uc29sZV9iYXRjaDtcbiAgICAgICAgRGVidWdnZXIuX2NvbnNvbGVfYmF0Y2ggPSBbXTtcbiAgICAgICAgRGVidWdnZXIuX2NvbnNvbGVfdGltZXIgPSBudWxsO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gQWpheC5jYWxsKFJzeC5Sb3V0ZSgnRGVidWdnZXJfQ29udHJvbGxlcicsICdsb2dfY29uc29sZV9tZXNzYWdlcycpLCB7IG1lc3NhZ2VzOiBtZXNzYWdlcyB9KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIFNpbGVudGx5IGZhaWwgLSBkb24ndCBjcmVhdGUgZXJyb3IgbG9vcFxuICAgICAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIHNlbmQgY29uc29sZV9kZWJ1ZyBtZXNzYWdlcyB0byBzZXJ2ZXI6JywgZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEZsdXNoIGVycm9yIGJhdGNoIHRvIHNlcnZlclxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfZmx1c2hfZXJyb3JfYmF0Y2goKSB7XG4gICAgICAgIGlmIChEZWJ1Z2dlci5fZXJyb3JfYmF0Y2gubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlcnJvcnMgPSBEZWJ1Z2dlci5fZXJyb3JfYmF0Y2g7XG4gICAgICAgIERlYnVnZ2VyLl9lcnJvcl9iYXRjaCA9IFtdO1xuICAgICAgICBEZWJ1Z2dlci5fZXJyb3JfdGltZXIgPSBudWxsO1xuICAgICAgICBEZWJ1Z2dlci5fZXJyb3JfYmF0Y2hfY291bnQrKztcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIEFqYXguY2FsbChSc3guUm91dGUoJ0RlYnVnZ2VyX0NvbnRyb2xsZXInLCAnbG9nX2Jyb3dzZXJfZXJyb3JzJyksIHsgZXJyb3JzOiBlcnJvcnMgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvLyBTaWxlbnRseSBmYWlsIC0gZG9uJ3QgY3JlYXRlIGVycm9yIGxvb3BcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBzZW5kIGJyb3dzZXIgZXJyb3JzIHRvIHNlcnZlcjonLCBlcnJvcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogR2V0IHRpbWUgcHJlZml4IGZvciBiZW5jaG1hcmtpbmdcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dldF90aW1lX3ByZWZpeCgpIHtcbiAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgaWYgKCFEZWJ1Z2dlci5fc3RhcnRfdGltZSkge1xuICAgICAgICAgICAgRGVidWdnZXIuX3N0YXJ0X3RpbWUgPSBub3c7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZWxhcHNlZCA9IG5vdyAtIERlYnVnZ2VyLl9zdGFydF90aW1lO1xuICAgICAgICByZXR1cm4gKGVsYXBzZWQgLyAxMDAwKS50b0ZpeGVkKDMpICsgJ3MnO1xuICAgIH1cbn1cbiIsIi8vIEBKUy1USElTLTAxLUVYQ0VQVElPTlxuLyoqXG4gKiBqUXVlcnkgaGVscGVyIGV4dGVuc2lvbnMgZm9yIHRoZSBSU1ggZnJhbWV3b3JrXG4gKiBUaGVzZSBleHRlbnNpb25zIGFkZCB1dGlsaXR5IG1ldGhvZHMgdG8galF1ZXJ5J3MgcHJvdG90eXBlXG4gKiBOb3RlOiAndGhpcycgcmVmZXJlbmNlcyBpbiBqUXVlcnkgZXh0ZW5zaW9ucyByZWZlciB0byBqUXVlcnkgb2JqZWN0cyBieSBkZXNpZ25cbiAqL1xuY2xhc3MgUnN4X0pxX0hlbHBlcnMge1xuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgalF1ZXJ5IGV4dGVuc2lvbnMgd2hlbiB0aGUgZnJhbWV3b3JrIGNvcmUgaXMgZGVmaW5lZFxuICAgICAqIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBkdXJpbmcgZnJhbWV3b3JrIGluaXRpYWxpemF0aW9uXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9kZWZpbmUoKSB7XG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiBqcXVlcnkgc2VsZWN0b3IgbWF0Y2hlZCBhbiBlbGVtZW50XG4gICAgICAgICQuZm4uZXhpc3RzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGVuZ3RoID4gMDtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYganF1ZXJ5IGVsZW1lbnQgaXMgdmlzaWJsZVxuICAgICAgICAkLmZuLmlzX3Zpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pcygnOnZpc2libGUnKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBTY3JvbGxzIHRvIHRoZSB0YXJnZXQgZWxlbWVudCwgb25seSBzY3JvbGxzIHVwLiAgVG9kbzogQ3JlYXRlIGEgdmVyc2lvblxuICAgICAgICAvLyBvZiB0aGlzIHRoYXQgYWxzbyBzY3JvbGxzIG9ubHkgZG93biwgb3IgYm90aFxuICAgICAgICAkLmZuLnNjcm9sbF91cF90byA9IGZ1bmN0aW9uIChzcGVlZCA9IDApIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5leGlzdHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUud2FybihcIkNvdWxkIG5vdCBmaW5kIHRhcmdldCBlbGVtZW50IHRvIHNjcm9sbCB0b1wiKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5pc19pbl9kb20oKSkge1xuICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUud2FybihcIlRhcmdldCBlbGVtZW50IGZvciBzY3JvbGwgaXMgbm90IG9uIGRvbVwiKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBlX3RvcCA9IE1hdGgucm91bmQodGhpcy5vZmZzZXQoKS50b3ApO1xuICAgICAgICAgICAgbGV0IHNfdG9wID0gJCgnYm9keScpLnNjcm9sbFRvcCgpO1xuICAgICAgICAgICAgaWYgKGVfdG9wIDwgMCkge1xuICAgICAgICAgICAgICAgIGxldCB0YXJnZXQgPSBzX3RvcCArIGVfdG9wO1xuICAgICAgICAgICAgICAgICQoJ2h0bWwsIGJvZHknKS5hbmltYXRlKFxuICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxUb3A6IHRhcmdldCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgc3BlZWRcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vICQoKS5pcyhcIjpmb2N1c1wiKSAtIGNoZWNrIGlmIGVsZW1lbnQgaGFzIGZvY3VzXG4gICAgICAgICQuZXhwclsnOiddLmZvY3VzID0gZnVuY3Rpb24gKGVsZW0pIHtcbiAgICAgICAgICAgIHJldHVybiBlbGVtID09PSBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICYmIChlbGVtLnR5cGUgfHwgZWxlbS5ocmVmKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBTYXZlIG5hdGl2ZSBjbGljayBiZWhhdmlvciBiZWZvcmUgb3ZlcnJpZGVcbiAgICAgICAgJC5mbi5fY2xpY2tfbmF0aXZlID0gJC5mbi5jbGljaztcblxuICAgICAgICAvLyBPdmVycmlkZSAuY2xpY2soKSB0byBjYWxsIHByZXZlbnREZWZhdWx0IGJ5IGRlZmF1bHRcbiAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhY2NpZGVudGFsIHBhZ2UgbmF2aWdhdGlvbi9mb3JtIHN1Ym1pc3Npb24gLSB0aGUgY29ycmVjdCBiZWhhdmlvciA5NSUgb2YgdGhlIHRpbWVcbiAgICAgICAgJC5mbi5jbGljayA9IGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAvLyBJZiBubyBoYW5kbGVyIHByb3ZpZGVkLCB0cmlnZ2VyIGNsaWNrIGV2ZW50IChqUXVlcnkgLmNsaWNrKCkgd2l0aCBubyBhcmdzKVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jbGlja19uYXRpdmUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQXR0YWNoIGNsaWNrIGhhbmRsZXIgd2l0aCBhdXRvbWF0aWMgcHJldmVudERlZmF1bHRcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm9uKCdjbGljaycsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gU2F2ZSBvcmlnaW5hbCBwcmV2ZW50RGVmYXVsdFxuICAgICAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsX3ByZXZlbnREZWZhdWx0ID0gZS5wcmV2ZW50RGVmYXVsdC5iaW5kKGUpO1xuXG4gICAgICAgICAgICAgICAgLy8gT3ZlcnJpZGUgcHJldmVudERlZmF1bHQgdG8gc2hvdyB3YXJuaW5nIHdoZW4gY2FsbGVkIGV4cGxpY2l0bHlcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignZXZlbnQucHJldmVudERlZmF1bHQoKSBpcyBjYWxsZWQgYXV0b21hdGljYWxseSBieSBSU3BhZGUgLmNsaWNrKCkgaGFuZGxlcnMgYW5kIGNhbiBiZSByZW1vdmVkLicpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxfcHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgLy8gQ2FsbCBwcmV2ZW50RGVmYXVsdCBiZWZvcmUgaGFuZGxlclxuICAgICAgICAgICAgICAgIG9yaWdpbmFsX3ByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlci5jYWxsKHRoaXMsIGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRXNjYXBlIGhhdGNoOiBjbGljayBoYW5kbGVyIHdpdGhvdXQgcHJldmVudERlZmF1bHQgZm9yIHRoZSA1JSBjYXNlXG4gICAgICAgICQuZm4uY2xpY2tfYWxsb3dfZGVmYXVsdCA9IGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGhhbmRsZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NsaWNrX25hdGl2ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2NsaWNrX25hdGl2ZShoYW5kbGVyKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhlIGpxdWVyeSBlbGVtZW50IGV4aXN0cyBpbiBhbmQgaXMgYXR0YWNoZWQgdG8gdGhlIERPTVxuICAgICAgICAkLmZuLmlzX2luX2RvbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGxldCAkZWxlbWVudCA9IHRoaXM7XG4gICAgICAgICAgICBsZXQgX2FuY2VzdG9yID0gZnVuY3Rpb24gKEhUTUxvYmopIHtcbiAgICAgICAgICAgICAgICB3aGlsZSAoSFRNTG9iai5wYXJlbnRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIEhUTUxvYmogPSBIVE1Mb2JqLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBIVE1Mb2JqO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiBfYW5jZXN0b3IoJGVsZW1lbnRbMF0pID09PSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoZSBlbGVtZW50IGlzIHZpc2libGUgaW4gdGhlIHZpZXdwb3J0XG4gICAgICAgICQuZm4uaXNfaW5fdmlld3BvcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBsZXQgc2Nyb2xsdG9wID0gJCh3aW5kb3cpLnNjcm9sbFRvcCgpID4gMCA/ICQod2luZG93KS5zY3JvbGxUb3AoKSA6ICQoJ2JvZHknKS5zY3JvbGxUb3AoKTtcblxuICAgICAgICAgICAgbGV0ICRlbGVtZW50ID0gdGhpcztcblxuICAgICAgICAgICAgY29uc3QgdG9wX29mX2VsZW1lbnQgPSAkZWxlbWVudC5vZmZzZXQoKS50b3A7XG4gICAgICAgICAgICBjb25zdCBib3R0b21fb2ZfZWxlbWVudCA9ICRlbGVtZW50Lm9mZnNldCgpLnRvcCArICRlbGVtZW50Lm91dGVySGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCBib3R0b21fb2Zfc2NyZWVuID0gc2Nyb2xsdG9wICsgJCh3aW5kb3cpLmlubmVySGVpZ2h0KCk7XG4gICAgICAgICAgICBjb25zdCB0b3Bfb2Zfc2NyZWVuID0gc2Nyb2xsdG9wO1xuXG4gICAgICAgICAgICBpZiAoYm90dG9tX29mX3NjcmVlbiA+IHRvcF9vZl9lbGVtZW50ICYmIHRvcF9vZl9zY3JlZW4gPCBib3R0b21fb2ZfZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gR2V0cyB0aGUgdGFnbmFtZSBvZiBhIGpxdWVyeSBlbGVtZW50XG4gICAgICAgICQuZm4udGFnbmFtZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnByb3AoJ3RhZ05hbWUnKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiBhIGhyZWYgaXMgbm90IHNhbWUgZG9tYWluXG4gICAgICAgICQuZm4uaXNfZXh0ZXJuYWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCBob3N0ID0gd2luZG93LmxvY2F0aW9uLmhvc3Q7XG4gICAgICAgICAgICBjb25zdCBsaW5rID0gJCgnPGE+Jywge1xuICAgICAgICAgICAgICAgIGhyZWY6IHRoaXMuYXR0cignaHJlZicpLFxuICAgICAgICAgICAgfSlbMF0uaG9zdG5hbWU7XG4gICAgICAgICAgICByZXR1cm4gbGluayAhPT0gaG9zdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBIVE1MNSBmb3JtIHZhbGlkYXRpb24gd3JhcHBlcnNcbiAgICAgICAgJC5mbi5jaGVja1ZhbGlkaXR5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1swXS5jaGVja1ZhbGlkaXR5KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgJC5mbi5yZXBvcnRWYWxpZGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbMF0ucmVwb3J0VmFsaWRpdHkoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAkLmZuLnJlcXVlc3RTdWJtaXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgdGhpc1swXS5yZXF1ZXN0U3VibWl0KCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBGaW5kIHJlbGF0ZWQgY29tcG9uZW50cyBieSBzZWFyY2hpbmcgdXAgdGhlIGFuY2VzdG9yIHRyZWVcbiAgICAgICAgLy8gTGlrZSAuY2xvc2VzdCgpIGJ1dCBzZWFyY2hlcyB3aXRoaW4gYW5jZXN0b3JzIGluc3RlYWQgb2YgbWF0Y2hpbmcgdGhlbVxuICAgICAgICAkLmZuLmNsb3Nlc3Rfc2libGluZyA9IGZ1bmN0aW9uIChzZWxlY3Rvcikge1xuICAgICAgICAgICAgbGV0ICRjdXJyZW50ID0gdGhpcztcbiAgICAgICAgICAgIGxldCAkcGFyZW50ID0gJGN1cnJlbnQucGFyZW50KCk7XG5cbiAgICAgICAgICAgIC8vIEtlZXAgZ29pbmcgdXAgdGhlIHRyZWUgdW50aWwgd2UgaGl0IGJvZHlcbiAgICAgICAgICAgIHdoaWxlICgkcGFyZW50Lmxlbmd0aCA+IDAgJiYgISRwYXJlbnQuaXMoJ2JvZHknKSkge1xuICAgICAgICAgICAgICAgIC8vIFNlYXJjaCB3aXRoaW4gdGhpcyBwYXJlbnQgZm9yIHRoZSBzZWxlY3RvclxuICAgICAgICAgICAgICAgIGxldCAkZm91bmQgPSAkcGFyZW50LmZpbmQoc2VsZWN0b3IpO1xuICAgICAgICAgICAgICAgIGlmICgkZm91bmQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJGZvdW5kO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE1vdmUgdXAgb25lIGxldmVsXG4gICAgICAgICAgICAgICAgJHBhcmVudCA9ICRwYXJlbnQucGFyZW50KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIHdlIHJlYWNoZWQgYm9keSwgc2VhcmNoIHdpdGhpbiBib2R5IGFzIHdlbGxcbiAgICAgICAgICAgIGlmICgkcGFyZW50LmlzKCdib2R5JykpIHtcbiAgICAgICAgICAgICAgICBsZXQgJGZvdW5kID0gJHBhcmVudC5maW5kKHNlbGVjdG9yKTtcbiAgICAgICAgICAgICAgICBpZiAoJGZvdW5kLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRmb3VuZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFJldHVybiBlbXB0eSBqUXVlcnkgb2JqZWN0IGlmIG5vdGhpbmcgZm91bmRcbiAgICAgICAgICAgIHJldHVybiAkKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gT3ZlcnJpZGUgJC5hamF4IHRvIHByZXZlbnQgZGlyZWN0IEFKQVggY2FsbHMgdG8gbG9jYWwgc2VydmVyXG4gICAgICAgIC8vIERldmVsb3BlcnMgbXVzdCB1c2UgdGhlIEFqYXggZW5kcG9pbnQgcGF0dGVybjogYXdhaXQgQ29udHJvbGxlci5tZXRob2QocGFyYW1zKVxuICAgICAgICBjb25zdCBuYXRpdmVfYWpheCA9ICQuYWpheDtcbiAgICAgICAgJC5hamF4ID0gZnVuY3Rpb24gKHVybCwgb3B0aW9ucykge1xuICAgICAgICAgICAgLy8gSGFuZGxlIGJvdGggJC5hamF4KHVybCwgb3B0aW9ucykgYW5kICQuYWpheChvcHRpb25zKSBzaWduYXR1cmVzXG4gICAgICAgICAgICBsZXQgc2V0dGluZ3M7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHVybCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MudXJsID0gdXJsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncyA9IHVybCB8fCB7fTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhIGxvY2FsIHJlcXVlc3QgKHJlbGF0aXZlIFVSTCBvciBzYW1lIGRvbWFpbilcbiAgICAgICAgICAgIGNvbnN0IHJlcXVlc3RfdXJsID0gc2V0dGluZ3MudXJsIHx8ICcnO1xuICAgICAgICAgICAgY29uc3QgaXNfcmVsYXRpdmUgPSAhcmVxdWVzdF91cmwubWF0Y2goL15odHRwcz86XFwvXFwvLyk7XG4gICAgICAgICAgICBjb25zdCBpc19zYW1lX2RvbWFpbiA9IHJlcXVlc3RfdXJsLnN0YXJ0c1dpdGgod2luZG93LmxvY2F0aW9uLm9yaWdpbik7XG4gICAgICAgICAgICBjb25zdCBpc19sb2NhbF9yZXF1ZXN0ID0gaXNfcmVsYXRpdmUgfHwgaXNfc2FtZV9kb21haW47XG5cbiAgICAgICAgICAgIC8vIEFsbG93IGZyYW1ld29yayBBamF4LmNhbGwoKSB0byBmdW5jdGlvblxuICAgICAgICAgICAgaWYgKHNldHRpbmdzLl9fbG9jYWxfaW50ZWdyYXRpb24gPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlX2FqYXguY2FsbCh0aGlzLCBzZXR0aW5ncyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFsbG93IGZpbGUgdXBsb2FkIGVuZHBvaW50IC0gcmVxdWlyZXMgbmF0aXZlICQuYWpheCBmb3IgRm9ybURhdGEgc3VwcG9ydFxuICAgICAgICAgICAgY29uc3QgaXNfZmlsZV91cGxvYWQgPSByZXF1ZXN0X3VybCA9PT0gJy9fdXBsb2FkJyB8fCByZXF1ZXN0X3VybC5lbmRzV2l0aCgnL191cGxvYWQnKTtcbiAgICAgICAgICAgIGlmIChpc19maWxlX3VwbG9hZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVfYWpheC5jYWxsKHRoaXMsIHNldHRpbmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmxvY2sgbG9jYWwgQUpBWCByZXF1ZXN0cyB0aGF0IGRvbid0IHVzZSB0aGUgQWpheCBlbmRwb2ludCBwYXR0ZXJuXG4gICAgICAgICAgICBpZiAoaXNfbG9jYWxfcmVxdWVzdCkge1xuICAgICAgICAgICAgICAgIC8vIFRyeSB0byBwYXJzZSBjb250cm9sbGVyIGFuZCBhY3Rpb24gZnJvbSBVUkxcbiAgICAgICAgICAgICAgICBsZXQgY29udHJvbGxlcl9uYW1lID0gbnVsbDtcbiAgICAgICAgICAgICAgICBsZXQgYWN0aW9uX25hbWUgPSBudWxsO1xuICAgICAgICAgICAgICAgIGNvbnN0IHVybF9tYXRjaCA9IHJlcXVlc3RfdXJsLm1hdGNoKC9cXC9fcnN4X2FwaVxcLyhbXlxcL10rKVxcLyhbXlxcL1xcP10rKS8pO1xuICAgICAgICAgICAgICAgIGlmICh1cmxfbWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlcl9uYW1lID0gdXJsX21hdGNoWzFdO1xuICAgICAgICAgICAgICAgICAgICBhY3Rpb25fbmFtZSA9IHVybF9tYXRjaFsyXTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgZXJyb3JfbWVzc2FnZSA9ICdBSkFYIHJlcXVlc3RzIHRvIGxvY2FsaG9zdCB2aWEgJC5hamF4KCkgYXJlIHByb2hpYml0ZWQuXFxuXFxuJztcblxuICAgICAgICAgICAgICAgIGlmIChjb250cm9sbGVyX25hbWUgJiYgYWN0aW9uX25hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgSW5zdGVhZCBvZjpcXG5gO1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGAgICQuYWpheCh7dXJsOiAnJHtyZXF1ZXN0X3VybH0nLCAuLi59KVxcblxcbmA7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYFVzZTpcXG5gO1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGAgIGF3YWl0ICR7Y29udHJvbGxlcl9uYW1lfS4ke2FjdGlvbl9uYW1lfShwYXJhbWV0ZXJzKVxcblxcbmA7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgVXNlIHRoZSBBamF4IGVuZHBvaW50IHBhdHRlcm46XFxuYDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgICBhd2FpdCBDb250cm9sbGVyX05hbWUuYWN0aW9uX25hbWUocGFyYW1ldGVycylcXG5cXG5gO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYFRoZSBjb250cm9sbGVyIG1ldGhvZCBtdXN0IGhhdmUgdGhlICNbQWpheF9FbmRwb2ludF0gYXR0cmlidXRlLmA7XG5cbiAgICAgICAgICAgICAgICBzaG91bGRudF9oYXBwZW4oZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFsbG93IGV4dGVybmFsIHJlcXVlc3RzIChkaWZmZXJlbnQgZG9tYWluKVxuICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZV9hamF4LmNhbGwodGhpcywgc2V0dGluZ3MpO1xuICAgICAgICB9O1xuICAgIH1cbn0iLCIvLyBAUk9VVEUtRVhJU1RTLTAxLUVYQ0VQVElPTiAtIFRoaXMgZmlsZSBjb250YWlucyBkb2N1bWVudGF0aW9uIGV4YW1wbGVzIHdpdGggZmljdGlvbmFsIHJvdXRlIG5hbWVzXG5cbi8qKlxuICogUnN4IC0gQ29yZSBKYXZhU2NyaXB0IFJ1bnRpbWUgU3lzdGVtXG4gKlxuICogVGhlIFJzeCBjbGFzcyBpcyB0aGUgY2VudHJhbCBodWIgZm9yIHRoZSBSU1ggSmF2YVNjcmlwdCBydW50aW1lLCBwcm92aWRpbmcgZXNzZW50aWFsXG4gKiBzeXN0ZW0tbGV2ZWwgdXRpbGl0aWVzIHRoYXQgYWxsIG90aGVyIGZyYW1ld29yayBjb21wb25lbnRzIGRlcGVuZCBvbi4gSXQgc2VydmVzIGFzIHRoZVxuICogZm91bmRhdGlvbiBmb3IgdGhlIGNsaWVudC1zaWRlIGZyYW1ld29yaywgaGFuZGxpbmcgY29yZSBvcGVyYXRpb25zIHRoYXQgbXVzdCBiZSBnbG9iYWxseVxuICogYWNjZXNzaWJsZSBhbmQgY29uc2lzdGVudGx5IGF2YWlsYWJsZS5cbiAqXG4gKiBDb3JlIFJlc3BvbnNpYmlsaXRpZXM6XG4gKiAtIEV2ZW50IFN5c3RlbTogQXBwbGljYXRpb24td2lkZSBldmVudCBidXMgZm9yIGZyYW1ld29yayBsaWZlY3ljbGUgYW5kIGN1c3RvbSBldmVudHNcbiAqIC0gRW52aXJvbm1lbnQgRGV0ZWN0aW9uOiBSdW50aW1lIGVudmlyb25tZW50IGlkZW50aWZpY2F0aW9uIChkZXYvcHJvZHVjdGlvbilcbiAqIC0gUm91dGUgTWFuYWdlbWVudDogVHlwZS1zYWZlIHJvdXRlIGdlbmVyYXRpb24gYW5kIFVSTCBidWlsZGluZ1xuICogLSBVbmlxdWUgSUQgR2VuZXJhdGlvbjogQ2xpZW50LXNpZGUgdW5pcXVlIGlkZW50aWZpZXIgZ2VuZXJhdGlvblxuICogLSBGcmFtZXdvcmsgQm9vdHN0cmFwOiBNdWx0aS1waGFzZSBpbml0aWFsaXphdGlvbiBvcmNoZXN0cmF0aW9uXG4gKiAtIExvZ2dpbmc6IENlbnRyYWxpemVkIGxvZ2dpbmcgaW50ZXJmYWNlIChkZWxlZ2F0ZXMgdG8gY29uc29sZV9kZWJ1ZylcbiAqXG4gKiBUaGUgUnN4IGNsYXNzIGRlbGliZXJhdGVseSBrZWVwcyBpdHMgc2NvcGUgbGltaXRlZCB0byBjb3JlIHV0aWxpdGllcy4gQWR2YW5jZWQgZmVhdHVyZXNcbiAqIGFyZSBkZWxlZ2F0ZWQgdG8gc3BlY2lhbGl6ZWQgY2xhc3NlczpcbiAqIC0gTWFuaWZlc3Qgb3BlcmF0aW9ucyDihpIgTWFuaWZlc3QgY2xhc3NcbiAqIC0gQ2FjaGluZyDihpIgUnN4X0NhY2hlIGNsYXNzXG4gKiAtIEFKQVgvQVBJIGNhbGxzIOKGkiBBamF4XyogY2xhc3Nlc1xuICogLSBSb3V0ZSBwcm94aWVzIOKGkiBSc3hfUm91dGVfUHJveHkgY2xhc3NcbiAqIC0gQmVoYXZpb3JzIOKGkiBSc3hfQmVoYXZpb3JzIGNsYXNzXG4gKlxuICogQWxsIG1ldGhvZHMgYXJlIHN0YXRpYyAtIFJzeCBpcyBuZXZlciBpbnN0YW50aWF0ZWQuIEl0J3MgYXZhaWxhYmxlIGdsb2JhbGx5IGZyb20gdGhlXG4gKiBtb21lbnQgYnVuZGxlcyBsb2FkIGFuZCByZW1haW5zIGNvbnN0YW50IHRocm91Z2hvdXQgdGhlIGFwcGxpY2F0aW9uIGxpZmVjeWNsZS5cbiAqXG4gKiBVc2FnZSBFeGFtcGxlczpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIC8vIEV2ZW50IHN5c3RlbVxuICogUnN4Lm9uKCdhcHBfcmVhZHknLCAoKSA9PiBjb25zb2xlLmxvZygnQXBwIGluaXRpYWxpemVkJykpO1xuICogUnN4LnRyaWdnZXIoJ2N1c3RvbV9ldmVudCcsIHtkYXRhOiAndmFsdWUnfSk7XG4gKlxuICogLy8gRW52aXJvbm1lbnQgZGV0ZWN0aW9uXG4gKiBpZiAoUnN4LmlzX2RldigpKSB7IGNvbnNvbGUubG9nKCdEZXZlbG9wbWVudCBtb2RlJyk7IH1cbiAqXG4gKiAvLyBSb3V0ZSBnZW5lcmF0aW9uXG4gKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0NvbnRyb2xsZXInLCAnYWN0aW9uJykudXJsKCk7XG4gKlxuICogLy8gVW5pcXVlIElEc1xuICogY29uc3QgdW5pcXVlSWQgPSBSc3gudWlkKCk7IC8vIGUuZy4sIFwicnN4XzEyMzQ1Njc4OTBfMVwiXG4gKiBgYGBcbiAqXG4gKiBAc3RhdGljXG4gKiBAZ2xvYmFsXG4gKi9cbmNsYXNzIFJzeCB7XG4gICAgLy8gR2V0cyBzZXQgdG8gdHJ1ZSB0byBpbnRlcnVwdCBzdGFydHVwIHNlcXVlbmNlXG4gICAgc3RhdGljIF9fc3RvcHBlZCA9IGZhbHNlO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBldmVudCBoYW5kbGVycyBzdG9yYWdlXG4gICAgc3RhdGljIF9pbml0X2V2ZW50cygpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBSc3guX2V2ZW50X2hhbmRsZXJzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgUnN4Ll9ldmVudF9oYW5kbGVycyA9IHt9O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgUnN4Ll90cmlnZ2VyZWRfZXZlbnRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgUnN4Ll90cmlnZ2VyZWRfZXZlbnRzID0ge307XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBSZWdpc3RlciBhbiBldmVudCBoYW5kbGVyXG4gICAgc3RhdGljIG9uKGV2ZW50LCBjYWxsYmFjaykge1xuICAgICAgICBSc3guX2luaXRfZXZlbnRzKCk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0pIHtcbiAgICAgICAgICAgIFJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XS5wdXNoKGNhbGxiYWNrKTtcblxuICAgICAgICAvLyBJZiB0aGlzIGV2ZW50IHdhcyBhbHJlYWR5IHRyaWdnZXJlZCwgY2FsbCB0aGUgY2FsbGJhY2sgaW1tZWRpYXRlbHlcbiAgICAgICAgaWYgKFJzeC5fdHJpZ2dlcmVkX2V2ZW50c1tldmVudF0pIHtcbiAgICAgICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgJ1RyaWdnZXJpbmcgJyArIGV2ZW50ICsgJyBmb3IgbGF0ZSByZWdpc3RlcmVkIGNhbGxiYWNrJyk7XG4gICAgICAgICAgICBjYWxsYmFjayhSc3guX3RyaWdnZXJlZF9ldmVudHNbZXZlbnRdKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRyaWdnZXIgYW4gZXZlbnQgd2l0aCBvcHRpb25hbCBkYXRhXG4gICAgc3RhdGljIHRyaWdnZXIoZXZlbnQsIGRhdGEgPSB7fSkge1xuICAgICAgICBSc3guX2luaXRfZXZlbnRzKCk7XG5cbiAgICAgICAgLy8gUmVjb3JkIHRoYXQgdGhpcyBldmVudCB3YXMgdHJpZ2dlcmVkXG4gICAgICAgIFJzeC5fdHJpZ2dlcmVkX2V2ZW50c1tldmVudF0gPSBkYXRhO1xuXG4gICAgICAgIGlmICghUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgJ1RyaWdnZXJpbmcgJyArIGV2ZW50ICsgJyBmb3IgJyArIFJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdLmxlbmd0aCArICcgY2FsbGJhY2tzJyk7XG5cbiAgICAgICAgLy8gQ2FsbCBhbGwgcmVnaXN0ZXJlZCBoYW5kbGVycyBmb3IgdGhpcyBldmVudCBpbiBvcmRlclxuICAgICAgICBmb3IgKGNvbnN0IGNhbGxiYWNrIG9mIFJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhkYXRhKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFsaWFzIGZvciB0cmlnZ2VyLnJlZnJlc2goJycpLCBzaG91bGQgYmUgY2FsbGVkIGFmdGVyIG1ham9yIFVJIHVwZGF0ZXMgdG8gYXBwbHkgc3VjaCBlZmZlY3RzIGFzXG4gICAgLy8gdW5kZXJsaW5pbmcgbGlua3MgdG8gdW5pbXBsZW1lbnRlZCAjIHJvdXRlc1xuICAgIHN0YXRpYyB0cmlnZ2VyX3JlZnJlc2goKSB7XG4gICAgICAgIC8vIFVzZSBSc3gub24oJ3JlZnJlc2gnLCBjYWxsYmFjayk7IHRvIHJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIHJlZnJlc2hcbiAgICAgICAgdGhpcy50cmlnZ2VyKCdyZWZyZXNoJyk7XG4gICAgfVxuXG4gICAgLy8gTG9nIHRvIHNlcnZlciB0aGF0IGFuIGV2ZW50IGhhcHBlbmVkXG4gICAgc3RhdGljIGxvZyh0eXBlLCBtZXNzYWdlID0gJ25vdGljZScpIHtcbiAgICAgICAgQ29yZV9Mb2cubG9nKHR5cGUsIG1lc3NhZ2UpO1xuICAgIH1cblxuICAgIC8vIFJldHVybnMgdHJ1ZSBpZiB0aGUgYXBwIGlzIGJlaW5nIHJ1biBpbiBkZXYgbW9kZVxuICAgIC8vIFRoaXMgc2hvdWxkIGFmZmVjdCBjYWNoaW5nIGFuZCBzb21lIGRlYnVnIGNoZWNrc1xuICAgIHN0YXRpYyBpc19kZXYoKSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cucnN4YXBwLmRlYnVnO1xuICAgIH1cblxuICAgIHN0YXRpYyBpc19wcm9kKCkge1xuICAgICAgICByZXR1cm4gIXdpbmRvdy5yc3hhcHAuZGVidWc7XG4gICAgfVxuXG4gICAgLy8gR2VuZXJhdGVzIGEgdW5pcXVlIG51bWJlciBmb3IgdGhlIGFwcGxpY2F0aW9uIGluc3RhbmNlXG4gICAgc3RhdGljIHVpZCgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBSc3guX3VpZCA9PSB1bmRlZikge1xuICAgICAgICAgICAgUnN4Ll91aWQgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBSc3guX3VpZCsrO1xuICAgIH1cblxuICAgIC8vIFN0b3JhZ2UgZm9yIHJvdXRlIGRlZmluaXRpb25zIGxvYWRlZCBmcm9tIGJ1bmRsZXNcbiAgICBzdGF0aWMgX3JvdXRlcyA9IHt9O1xuXG4gICAgLyoqXG4gICAgICogRGVmaW5lIHJvdXRlcyBmcm9tIGJ1bmRsZWQgZGF0YVxuICAgICAqIENhbGxlZCBieSBnZW5lcmF0ZWQgSmF2YVNjcmlwdCBpbiBidW5kbGVzXG4gICAgICovXG4gICAgc3RhdGljIF9kZWZpbmVfcm91dGVzKHJvdXRlcykge1xuICAgICAgICAvLyBNZXJnZSByb3V0ZXMgaW50byB0aGUgZ2xvYmFsIHJvdXRlIHN0b3JhZ2VcbiAgICAgICAgZm9yIChjb25zdCBjbGFzc19uYW1lIGluIHJvdXRlcykge1xuICAgICAgICAgICAgaWYgKCFSc3guX3JvdXRlc1tjbGFzc19uYW1lXSkge1xuICAgICAgICAgICAgICAgIFJzeC5fcm91dGVzW2NsYXNzX25hbWVdID0ge307XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1ldGhvZF9uYW1lIGluIHJvdXRlc1tjbGFzc19uYW1lXSkge1xuICAgICAgICAgICAgICAgIFJzeC5fcm91dGVzW2NsYXNzX25hbWVdW21ldGhvZF9uYW1lXSA9IHJvdXRlc1tjbGFzc19uYW1lXVttZXRob2RfbmFtZV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBVUkwgZm9yIGEgY29udHJvbGxlciByb3V0ZVxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgZ2VuZXJhdGVzIFVSTHMgZm9yIGNvbnRyb2xsZXIgYWN0aW9ucyBieSBsb29raW5nIHVwIHJvdXRlIHBhdHRlcm5zXG4gICAgICogYW5kIHJlcGxhY2luZyBwYXJhbWV0ZXJzLiBJdCBoYW5kbGVzIGJvdGggcmVndWxhciByb3V0ZXMgYW5kIEFqYXggZW5kcG9pbnRzLlxuICAgICAqXG4gICAgICogSWYgdGhlIHJvdXRlIGlzIG5vdCBmb3VuZCBpbiB0aGUgcm91dGUgZGVmaW5pdGlvbnMsIGEgZGVmYXVsdCBwYXR0ZXJuIGlzIHVzZWQ6XG4gICAgICogYC9fL3tjb250cm9sbGVyfS97YWN0aW9ufWAgd2l0aCBhbGwgcGFyYW1ldGVycyBhcHBlbmRlZCBhcyBxdWVyeSBzdHJpbmdzLlxuICAgICAqXG4gICAgICogVXNhZ2UgZXhhbXBsZXM6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIC8vIFNpbXBsZSByb3V0ZSB3aXRob3V0IHBhcmFtZXRlcnMgKGRlZmF1bHRzIHRvICdpbmRleCcgYWN0aW9uKVxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfSW5kZXhfQ29udHJvbGxlcicpO1xuICAgICAqIC8vIFJldHVybnM6IC9kYXNoYm9hcmRcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggZXhwbGljaXQgYWN0aW9uXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdGcm9udGVuZF9JbmRleF9Db250cm9sbGVyJywgJ2luZGV4Jyk7XG4gICAgICogLy8gUmV0dXJuczogL2Rhc2hib2FyZFxuICAgICAqXG4gICAgICogLy8gUm91dGUgd2l0aCBpbnRlZ2VyIHBhcmFtZXRlciAoc2V0cyAnaWQnKVxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfQ2xpZW50X1ZpZXdfQ29udHJvbGxlcicsICd2aWV3JywgMTIzKTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvY2xpZW50cy92aWV3LzEyM1xuICAgICAqXG4gICAgICogLy8gUm91dGUgd2l0aCBuYW1lZCBwYXJhbWV0ZXJzIChvYmplY3QpXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdGcm9udGVuZF9DbGllbnRfVmlld19Db250cm9sbGVyJywgJ3ZpZXcnLCB7aWQ6ICdDMDAxJ30pO1xuICAgICAqIC8vIFJldHVybnM6IC9jbGllbnRzL3ZpZXcvQzAwMVxuICAgICAqXG4gICAgICogLy8gUm91dGUgd2l0aCByZXF1aXJlZCBhbmQgcXVlcnkgcGFyYW1ldGVyc1xuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfQ2xpZW50X1ZpZXdfQ29udHJvbGxlcicsICd2aWV3Jywge1xuICAgICAqICAgICBpZDogJ0MwMDEnLFxuICAgICAqICAgICB0YWI6ICdoaXN0b3J5J1xuICAgICAqIH0pO1xuICAgICAqIC8vIFJldHVybnM6IC9jbGllbnRzL3ZpZXcvQzAwMT90YWI9aGlzdG9yeVxuICAgICAqXG4gICAgICogLy8gUm91dGUgbm90IGZvdW5kIC0gdXNlcyBkZWZhdWx0IHBhdHRlcm5cbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ1VuaW1wbGVtZW50ZWRfQ29udHJvbGxlcicsICdzb21lX2FjdGlvbicsIHtmb286ICdiYXInfSk7XG4gICAgICogLy8gUmV0dXJuczogL18vVW5pbXBsZW1lbnRlZF9Db250cm9sbGVyL3NvbWVfYWN0aW9uP2Zvbz1iYXJcbiAgICAgKlxuICAgICAqIC8vIFBsYWNlaG9sZGVyIHJvdXRlXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdGdXR1cmVfQ29udHJvbGxlcicsICcjaW5kZXgnKTtcbiAgICAgKiAvLyBSZXR1cm5zOiAjXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NfbmFtZSBUaGUgY29udHJvbGxlciBjbGFzcyBuYW1lIChlLmcuLCAnVXNlcl9Db250cm9sbGVyJylcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gW2FjdGlvbl9uYW1lPSdpbmRleCddIFRoZSBhY3Rpb24vbWV0aG9kIG5hbWUgKGRlZmF1bHRzIHRvICdpbmRleCcpLiBVc2UgJyNhY3Rpb24nIGZvciBwbGFjZWhvbGRlcnMuXG4gICAgICogQHBhcmFtIHtudW1iZXJ8T2JqZWN0fSBbcGFyYW1zPW51bGxdIFJvdXRlIHBhcmFtZXRlcnMuIEludGVnZXIgc2V0cyAnaWQnLCBvYmplY3QgcHJvdmlkZXMgbmFtZWQgcGFyYW1zLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgVVJMXG4gICAgICovXG4gICAgc3RhdGljIFJvdXRlKGNsYXNzX25hbWUsIGFjdGlvbl9uYW1lID0gJ2luZGV4JywgcGFyYW1zID0gbnVsbCkge1xuICAgICAgICAvLyBOb3JtYWxpemUgcGFyYW1zIHRvIG9iamVjdFxuICAgICAgICBsZXQgcGFyYW1zX29iaiA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIHBhcmFtcyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHBhcmFtc19vYmogPSB7IGlkOiBwYXJhbXMgfTtcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbXMgJiYgdHlwZW9mIHBhcmFtcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHBhcmFtc19vYmogPSBwYXJhbXM7XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1zICE9PSBudWxsICYmIHBhcmFtcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhcmFtcyBtdXN0IGJlIG51bWJlciwgb2JqZWN0LCBvciBudWxsJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQbGFjZWhvbGRlciByb3V0ZTogYWN0aW9uIHN0YXJ0cyB3aXRoICMgbWVhbnMgdW5pbXBsZW1lbnRlZC9zY2FmZm9sZGluZ1xuICAgICAgICBpZiAoYWN0aW9uX25hbWUuc3RhcnRzV2l0aCgnIycpKSB7XG4gICAgICAgICAgICByZXR1cm4gJyMnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgcm91dGUgZXhpc3RzIGluIGRlZmluaXRpb25zXG4gICAgICAgIGxldCBwYXR0ZXJuO1xuICAgICAgICBpZiAoUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV0gJiYgUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV1bYWN0aW9uX25hbWVdKSB7XG4gICAgICAgICAgICBwYXR0ZXJuID0gUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV1bYWN0aW9uX25hbWVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gUm91dGUgbm90IGZvdW5kIC0gdXNlIGRlZmF1bHQgcGF0dGVybiAvXy97Y29udHJvbGxlcn0ve2FjdGlvbn1cbiAgICAgICAgICAgIHBhdHRlcm4gPSBgL18vJHtjbGFzc19uYW1lfS8ke2FjdGlvbl9uYW1lfWA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZW5lcmF0ZSBVUkwgZnJvbSBwYXR0ZXJuXG4gICAgICAgIHJldHVybiBSc3guX2dlbmVyYXRlX3VybF9mcm9tX3BhdHRlcm4ocGF0dGVybiwgcGFyYW1zX29iaik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgVVJMIGZyb20gcm91dGUgcGF0dGVybiBieSByZXBsYWNpbmcgcGFyYW1ldGVyc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhdHRlcm4gVGhlIHJvdXRlIHBhdHRlcm4gKGUuZy4sICcvdXNlcnMvOmlkL3ZpZXcnKVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMgUGFyYW1ldGVycyB0byBmaWxsIGludG8gdGhlIHJvdXRlXG4gICAgICogQHJldHVybnMge3N0cmluZ30gVGhlIGdlbmVyYXRlZCBVUkxcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dlbmVyYXRlX3VybF9mcm9tX3BhdHRlcm4ocGF0dGVybiwgcGFyYW1zKSB7XG4gICAgICAgIC8vIEV4dHJhY3QgcmVxdWlyZWQgcGFyYW1ldGVycyBmcm9tIHRoZSBwYXR0ZXJuXG4gICAgICAgIGNvbnN0IHJlcXVpcmVkX3BhcmFtcyA9IFtdO1xuICAgICAgICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXRjaCgvOihbYS16QS1aX11bYS16QS1aMC05X10qKS9nKTtcbiAgICAgICAgaWYgKG1hdGNoZXMpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgOiBwcmVmaXggZnJvbSBlYWNoIG1hdGNoXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG1hdGNoIG9mIG1hdGNoZXMpIHtcbiAgICAgICAgICAgICAgICByZXF1aXJlZF9wYXJhbXMucHVzaChtYXRjaC5zdWJzdHJpbmcoMSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgZm9yIHJlcXVpcmVkIHBhcmFtZXRlcnNcbiAgICAgICAgY29uc3QgbWlzc2luZyA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHJlcXVpcmVkIG9mIHJlcXVpcmVkX3BhcmFtcykge1xuICAgICAgICAgICAgaWYgKCEocmVxdWlyZWQgaW4gcGFyYW1zKSkge1xuICAgICAgICAgICAgICAgIG1pc3NpbmcucHVzaChyZXF1aXJlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWlzc2luZy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFJlcXVpcmVkIHBhcmFtZXRlcnMgWyR7bWlzc2luZy5qb2luKCcsICcpfV0gYXJlIG1pc3NpbmcgZm9yIHJvdXRlICR7cGF0dGVybn1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBVUkwgYnkgcmVwbGFjaW5nIHBhcmFtZXRlcnNcbiAgICAgICAgbGV0IHVybCA9IHBhdHRlcm47XG4gICAgICAgIGNvbnN0IHVzZWRfcGFyYW1zID0ge307XG5cbiAgICAgICAgZm9yIChjb25zdCBwYXJhbV9uYW1lIG9mIHJlcXVpcmVkX3BhcmFtcykge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwYXJhbXNbcGFyYW1fbmFtZV07XG4gICAgICAgICAgICAvLyBVUkwgZW5jb2RlIHRoZSB2YWx1ZVxuICAgICAgICAgICAgY29uc3QgZW5jb2RlZF92YWx1ZSA9IGVuY29kZVVSSUNvbXBvbmVudCh2YWx1ZSk7XG4gICAgICAgICAgICB1cmwgPSB1cmwucmVwbGFjZSgnOicgKyBwYXJhbV9uYW1lLCBlbmNvZGVkX3ZhbHVlKTtcbiAgICAgICAgICAgIHVzZWRfcGFyYW1zW3BhcmFtX25hbWVdID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbGxlY3QgYW55IGV4dHJhIHBhcmFtZXRlcnMgZm9yIHF1ZXJ5IHN0cmluZ1xuICAgICAgICBjb25zdCBxdWVyeV9wYXJhbXMgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBpZiAoIXVzZWRfcGFyYW1zW2tleV0pIHtcbiAgICAgICAgICAgICAgICBxdWVyeV9wYXJhbXNba2V5XSA9IHBhcmFtc1trZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXBwZW5kIHF1ZXJ5IHN0cmluZyBpZiB0aGVyZSBhcmUgZXh0cmEgcGFyYW1ldGVyc1xuICAgICAgICBpZiAoT2JqZWN0LmtleXMocXVlcnlfcGFyYW1zKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCBxdWVyeV9zdHJpbmcgPSBPYmplY3QuZW50cmllcyhxdWVyeV9wYXJhbXMpXG4gICAgICAgICAgICAgICAgLm1hcCgoW2tleSwgdmFsdWVdKSA9PiBgJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQodmFsdWUpfWApXG4gICAgICAgICAgICAgICAgLmpvaW4oJyYnKTtcbiAgICAgICAgICAgIHVybCArPSAnPycgKyBxdWVyeV9zdHJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdXJsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBDYWxsIGEgc3BlY2lmaWMgbWV0aG9kIG9uIGFsbCBjbGFzc2VzIHRoYXQgaGF2ZSBpdFxuICAgICAqIENvbGxlY3RzIHByb21pc2VzIGZyb20gcmV0dXJuIHZhbHVlcyBhbmQgd2FpdHMgZm9yIGFsbCB0byByZXNvbHZlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZF9uYW1lIFRoZSBtZXRob2QgbmFtZSB0byBjYWxsIG9uIGFsbCBjbGFzc2VzXG4gICAgICogQHJldHVybnMge1Byb21pc2V9IFByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBtZXRob2QgY2FsbHMgY29tcGxldGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX3JzeF9jYWxsX2FsbF9jbGFzc2VzKG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIGNvbnN0IGFsbF9jbGFzc2VzID0gTWFuaWZlc3QuZ2V0X2FsbF9jbGFzc2VzKCk7XG4gICAgICAgIGNvbnN0IGNsYXNzZXNfd2l0aF9tZXRob2QgPSBbXTtcbiAgICAgICAgY29uc3QgcHJvbWlzZV9waWxlID0gW107XG5cbiAgICAgICAgZm9yIChjb25zdCBjbGFzc19pbmZvIG9mIGFsbF9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc19vYmplY3QgPSBjbGFzc19pbmZvLmNsYXNzX29iamVjdDtcbiAgICAgICAgICAgIGNvbnN0IGNsYXNzX25hbWUgPSBjbGFzc19pbmZvLmNsYXNzX25hbWU7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoaXMgY2xhc3MgaGFzIHRoZSBtZXRob2QgKHN0YXRpYyBtZXRob2RzIGFyZSBvbiB0aGUgY2xhc3MgaXRzZWxmKVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBjbGFzc19vYmplY3RbbWV0aG9kX25hbWVdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgY2xhc3Nlc193aXRoX21ldGhvZC5wdXNoKGNsYXNzX25hbWUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJldHVybl92YWx1ZSA9IGF3YWl0IGNsYXNzX29iamVjdFttZXRob2RfbmFtZV0oKTtcblxuICAgICAgICAgICAgICAgIC8vIENvbGxlY3QgcHJvbWlzZXMgZnJvbSByZXR1cm4gdmFsdWVcbiAgICAgICAgICAgICAgICBpZiAocmV0dXJuX3ZhbHVlIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9taXNlX3BpbGUucHVzaChyZXR1cm5fdmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyZXR1cm5fdmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiByZXR1cm5fdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpdGVtIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VfcGlsZS5wdXNoKGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKFJzeC5fX3N0b3BwZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjbGFzc2VzX3dpdGhfbWV0aG9kLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgYCR7bWV0aG9kX25hbWV9OiAke2NsYXNzZXNfd2l0aF9tZXRob2QubGVuZ3RofSBjbGFzc2VzYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBd2FpdCBhbGwgcHJvbWlzZXMgYmVmb3JlIHJldHVybmluZ1xuICAgICAgICBpZiAocHJvbWlzZV9waWxlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgYCR7bWV0aG9kX25hbWV9OiBBd2FpdGluZyAke3Byb21pc2VfcGlsZS5sZW5ndGh9IHByb21pc2VzYCk7XG4gICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlX3BpbGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEV4ZWN1dGUgbXVsdGktcGhhc2UgaW5pdGlhbGl6YXRpb24gZm9yIGFsbCByZWdpc3RlcmVkIGNsYXNzZXNcbiAgICAgKiBUaGlzIHJ1bnMgdmFyaW91cyBpbml0aWFsaXphdGlvbiBwaGFzZXMgaW4gb3JkZXIgdG8gcHJvcGVybHkgc2V0IHVwIHRoZSBhcHBsaWNhdGlvblxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgaW5pdGlhbGl6YXRpb24gcGhhc2VzIGNvbXBsZXRlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9yc3hfY29yZV9ib290KCkge1xuICAgICAgICBpZiAoUnN4Ll9fYm9vdGVkKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdSc3guX3JzeF9jb3JlX2Jvb3QgY2FsbGVkIG1vcmUgdGhhbiBvbmNlJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBSc3guX19ib290ZWQgPSB0cnVlO1xuXG4gICAgICAgIC8vIEdldCBhbGwgcmVnaXN0ZXJlZCBjbGFzc2VzIGZyb20gdGhlIG1hbmlmZXN0XG4gICAgICAgIGNvbnN0IGFsbF9jbGFzc2VzID0gTWFuaWZlc3QuZ2V0X2FsbF9jbGFzc2VzKCk7XG5cbiAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCBgU3RhcnRpbmcgX3JzeF9jb3JlX2Jvb3Qgd2l0aCAke2FsbF9jbGFzc2VzLmxlbmd0aH0gY2xhc3Nlc2ApO1xuXG4gICAgICAgIGlmICghYWxsX2NsYXNzZXMgfHwgYWxsX2NsYXNzZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAvLyBObyBjbGFzc2VzIHRvIGluaXRpYWxpemVcbiAgICAgICAgICAgIHNob3VsZG50X2hhcHBlbignTm8gY2xhc3NlcyByZWdpc3RlcmVkIGluIGpzIC0gdGhlcmUgc2hvdWxkIGJlIGF0IGxlYXN0IHRoZSBjb3JlIGZyYW1ld29yayBjbGFzc2VzJyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZpbmUgaW5pdGlhbGl6YXRpb24gcGhhc2VzIGluIG9yZGVyXG4gICAgICAgIGNvbnN0IHBoYXNlcyA9IFtcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdmcmFtZXdvcmtfY29yZV9kZWZpbmUnLCBtZXRob2Q6ICdfb25fZnJhbWV3b3JrX2NvcmVfZGVmaW5lJyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2ZyYW1ld29ya19tb2R1bGVzX2RlZmluZScsIG1ldGhvZDogJ19vbl9mcmFtZXdvcmtfbW9kdWxlc19kZWZpbmUnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnZnJhbWV3b3JrX2NvcmVfaW5pdCcsIG1ldGhvZDogJ19vbl9mcmFtZXdvcmtfY29yZV9pbml0JyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9tb2R1bGVzX2RlZmluZScsIG1ldGhvZDogJ29uX2FwcF9tb2R1bGVzX2RlZmluZScgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdhcHBfZGVmaW5lJywgbWV0aG9kOiAnb25fYXBwX2RlZmluZScgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdmcmFtZXdvcmtfbW9kdWxlc19pbml0JywgbWV0aG9kOiAnX29uX2ZyYW1ld29ya19tb2R1bGVzX2luaXQnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX21vZHVsZXNfaW5pdCcsIG1ldGhvZDogJ29uX2FwcF9tb2R1bGVzX2luaXQnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX2luaXQnLCBtZXRob2Q6ICdvbl9hcHBfaW5pdCcgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdhcHBfcmVhZHknLCBtZXRob2Q6ICdvbl9hcHBfcmVhZHknIH0sXG4gICAgICAgIF07XG5cbiAgICAgICAgLy8gRXhlY3V0ZSBlYWNoIHBoYXNlIGluIG9yZGVyXG4gICAgICAgIGZvciAoY29uc3QgcGhhc2Ugb2YgcGhhc2VzKSB7XG4gICAgICAgICAgICBhd2FpdCBSc3guX3JzeF9jYWxsX2FsbF9jbGFzc2VzKHBoYXNlLm1ldGhvZCk7XG5cbiAgICAgICAgICAgIGlmIChSc3guX19zdG9wcGVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBSc3gudHJpZ2dlcihwaGFzZS5ldmVudCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVaSByZWZyZXNoIGNhbGxiYWNrc1xuICAgICAgICBSc3gudHJpZ2dlcl9yZWZyZXNoKCk7XG5cbiAgICAgICAgLy8gQWxsIHBoYXNlcyBjb21wbGV0ZVxuICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdJbml0aWFsaXphdGlvbiBjb21wbGV0ZScpO1xuXG4gICAgICAgIC8vIFRPRE86IEZpbmQgYSBnb29kIHdhaXQgdG8gd2FpdCBmb3IgYWxsIGpxaHRtbCBjb21wb25lbnRzIHRvIGxvYWQsIHRoZW4gdHJpZ2dlciBvbl9yZWFkeSBhbmQgb24oJ3JlYWR5JykgZW11bGF0aW5nIHRoZSB0b3AgbGV2ZWwgbGFzdCBzeW50YXggdGhhdCBqcWh0bWwgY29tcG9uZW50cyBvcGVyYXRlYXMsIGJ1dCBhcyBhIHN0YW5kYXJkIGpzIGNsYXNzIChzdWNoIGFzIGEgcGFnZSBjbGFzcykuICBUaGUgYmlnZ2VzdCBxdWVzdGlvbiBpcywgaG93IGRvIHdlIGVmZmljaWVudGx5IGNob29zZSBvbmx5IHRoZSB0b3AgbGV2ZWwganFodG1sIGNvbXBvbmVudHMuICBkbyB3ZSBvbmx5IGNvbnNpZGVyIGNvbXBvbmVudHMgY3JldGFlZCBkaXJlY3RseSBvbiBibGFkZSB0ZW1wbGF0ZXM/IHRoYXQgc2VhbXMgcmVhc29uYWJsZS4uLlxuXG4gICAgICAgIC8vIFRyaWdnZXIgX2RlYnVnX3JlYWR5IGV2ZW50IC0gdGhpcyBpcyBPTkxZIGZvciB0b29saW5nIGxpa2UgcnN4OmRlYnVnXG4gICAgICAgIC8vIERPIE5PVCB1c2UgdGhpcyBpbiBhcHBsaWNhdGlvbiBjb2RlIC0gdXNlIG9uX2FwcF9yZWFkeSgpIHBoYXNlIGluc3RlYWRcbiAgICAgICAgLy8gVGhpcyBldmVudCBleGlzdHMgc29sZWx5IGZvciBkZWJ1Z2dpbmcgdG9vbHMgdGhhdCBuZWVkIHRvIHJ1biBhZnRlciBmdWxsIGluaXRpYWxpemF0aW9uXG4gICAgICAgIFJzeC50cmlnZ2VyKCdfZGVidWdfcmVhZHknKTtcbiAgICB9XG5cbiAgICAvKiBDYWxsaW5nIHRoaXMgc3RvcHMgdGhlIGJvb3QgcHJvY2Vzcy4gKi9cbiAgICBzdGF0aWMgYXN5bmMgX3JzeF9jb3JlX2Jvb3Rfc3RvcChyZWFzb24pIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihyZWFzb24pO1xuICAgICAgICBSc3guX19zdG9wcGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZSBVUkwgaGFzaCBpbnRvIGtleS12YWx1ZSBvYmplY3RcbiAgICAgKiBIYW5kbGVzIGZvcm1hdDogI2tleT12YWx1ZSZrZXkyPXZhbHVlMlxuICAgICAqXG4gICAgICogQHJldHVybnMge09iamVjdH0gUGFyc2VkIGhhc2ggcGFyYW1ldGVyc1xuICAgICAqL1xuICAgIHN0YXRpYyBfcGFyc2VfaGFzaCgpIHtcbiAgICAgICAgY29uc3QgaGFzaCA9IHdpbmRvdy5sb2NhdGlvbi5oYXNoO1xuICAgICAgICBpZiAoIWhhc2ggfHwgaGFzaCA9PT0gJyMnKSB7XG4gICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgbGVhZGluZyAjIGFuZCBwYXJzZSBhcyBxdWVyeSBzdHJpbmdcbiAgICAgICAgY29uc3QgaGFzaF9zdHJpbmcgPSBoYXNoLnN1YnN0cmluZygxKTtcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge307XG5cbiAgICAgICAgY29uc3QgcGFpcnMgPSBoYXNoX3N0cmluZy5zcGxpdCgnJicpO1xuICAgICAgICBmb3IgKGNvbnN0IHBhaXIgb2YgcGFpcnMpIHtcbiAgICAgICAgICAgIGNvbnN0IFtrZXksIHZhbHVlXSA9IHBhaXIuc3BsaXQoJz0nKTtcbiAgICAgICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgICAgICBwYXJhbXNbZGVjb2RlVVJJQ29tcG9uZW50KGtleSldID0gdmFsdWUgPyBkZWNvZGVVUklDb21wb25lbnQodmFsdWUpIDogJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSBvYmplY3QgaW50byBVUkwgaGFzaCBmb3JtYXRcbiAgICAgKiBQcm9kdWNlcyBmb3JtYXQ6ICNrZXk9dmFsdWUma2V5Mj12YWx1ZTJcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBwYXJhbXMgS2V5LXZhbHVlIHBhaXJzIHRvIGVuY29kZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEVuY29kZWQgaGFzaCBzdHJpbmcgKHdpdGggbGVhZGluZyAjLCBvciBlbXB0eSBzdHJpbmcpXG4gICAgICovXG4gICAgc3RhdGljIF9zZXJpYWxpemVfaGFzaChwYXJhbXMpIHtcbiAgICAgICAgY29uc3QgcGFpcnMgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcGFyYW1zKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHBhcmFtc1trZXldO1xuICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBudWxsICYmIHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgcGFpcnMucHVzaChgJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQodmFsdWUpfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhaXJzLmxlbmd0aCA+IDAgPyAnIycgKyBwYWlycy5qb2luKCcmJykgOiAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHBhZ2Ugc3RhdGUgZnJvbSBVUkwgaGFzaFxuICAgICAqXG4gICAgICogVXNhZ2U6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIGNvbnN0IHN0YXRlID0gUnN4LmdldF9hbGxfcGFnZV9zdGF0ZSgpO1xuICAgICAqIC8vIFJldHVybnM6IHtkZ19wYWdlOiAnMicsIGRnX3NvcnQ6ICduYW1lJ31cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IEFsbCBoYXNoIHBhcmFtZXRlcnMgYXMga2V5LXZhbHVlIHBhaXJzXG4gICAgICovXG4gICAgc3RhdGljIGdldF9hbGxfcGFnZV9zdGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIFJzeC5fcGFyc2VfaGFzaCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBzaW5nbGUgdmFsdWUgZnJvbSBVUkwgaGFzaCBzdGF0ZVxuICAgICAqXG4gICAgICogVXNhZ2U6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIGNvbnN0IHBhZ2UgPSBSc3guZ2V0X3BhZ2Vfc3RhdGUoJ2RnX3BhZ2UnKTtcbiAgICAgKiAvLyBSZXR1cm5zOiAnMicgb3IgbnVsbCBpZiBub3Qgc2V0XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgdG8gcmV0cmlldmVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IFRoZSB2YWx1ZSBvciBudWxsIGlmIG5vdCBmb3VuZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfcGFnZV9zdGF0ZShrZXkpIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBSc3guX3BhcnNlX2hhc2goKTtcbiAgICAgICAgcmV0dXJuIHN0YXRlW2tleV0gPz8gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgc2luZ2xlIHZhbHVlIGluIFVSTCBoYXNoIHN0YXRlIChyZXBsYWNlcyBoaXN0b3J5LCBkb2Vzbid0IGFkZClcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBSc3guc2V0X3BhZ2Vfc3RhdGUoJ2RnX3BhZ2UnLCAyKTtcbiAgICAgKiAvLyBVUkwgYmVjb21lczogaHR0cDovL2V4YW1wbGUuY29tL3BhZ2UjZGdfcGFnZT0yXG4gICAgICpcbiAgICAgKiBSc3guc2V0X3BhZ2Vfc3RhdGUoJ2RnX3BhZ2UnLCBudWxsKTsgLy8gUmVtb3ZlIGtleVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IHRvIHNldFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxudWxsfSB2YWx1ZSBUaGUgdmFsdWUgKG51bGwvZW1wdHkgcmVtb3ZlcyB0aGUga2V5KVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRfcGFnZV9zdGF0ZShrZXksIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gUnN4Ll9wYXJzZV9oYXNoKCk7XG5cbiAgICAgICAgLy8gVXBkYXRlIG9yIHJlbW92ZSB0aGUga2V5XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgZGVsZXRlIHN0YXRlW2tleV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGF0ZVtrZXldID0gU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSBVUkwgd2l0aG91dCBhZGRpbmcgaGlzdG9yeVxuICAgICAgICBjb25zdCBuZXdfaGFzaCA9IFJzeC5fc2VyaWFsaXplX2hhc2goc3RhdGUpO1xuICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUgKyB3aW5kb3cubG9jYXRpb24uc2VhcmNoICsgbmV3X2hhc2g7XG4gICAgICAgIGhpc3RvcnkucmVwbGFjZVN0YXRlKG51bGwsICcnLCB1cmwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCBtdWx0aXBsZSB2YWx1ZXMgaW4gVVJMIGhhc2ggc3RhdGUgYXQgb25jZVxuICAgICAqXG4gICAgICogVXNhZ2U6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIFJzeC5zZXRfYWxsX3BhZ2Vfc3RhdGUoe2RnX3BhZ2U6IDIsIGRnX3NvcnQ6ICduYW1lJ30pO1xuICAgICAqIC8vIFVSTCBiZWNvbWVzOiBodHRwOi8vZXhhbXBsZS5jb20vcGFnZSNkZ19wYWdlPTImZGdfc29ydD1uYW1lXG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gbmV3X3N0YXRlIE9iamVjdCB3aXRoIGtleS12YWx1ZSBwYWlycyB0byBzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0X2FsbF9wYWdlX3N0YXRlKG5ld19zdGF0ZSkge1xuICAgICAgICBjb25zdCBzdGF0ZSA9IFJzeC5fcGFyc2VfaGFzaCgpO1xuXG4gICAgICAgIC8vIE1lcmdlIG5ldyBzdGF0ZVxuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBuZXdfc3RhdGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gbmV3X3N0YXRlW2tleV07XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgc3RhdGVba2V5XTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RhdGVba2V5XSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgVVJMIHdpdGhvdXQgYWRkaW5nIGhpc3RvcnlcbiAgICAgICAgY29uc3QgbmV3X2hhc2ggPSBSc3guX3NlcmlhbGl6ZV9oYXNoKHN0YXRlKTtcbiAgICAgICAgY29uc3QgdXJsID0gd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lICsgd2luZG93LmxvY2F0aW9uLnNlYXJjaCArIG5ld19oYXNoO1xuICAgICAgICBoaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCAnJywgdXJsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW5kZXIgYW4gZXJyb3IgaW4gYSBET00gZWxlbWVudFxuICAgICAqXG4gICAgICogRGlzcGxheXMgZXJyb3JzIGZyb20gQWpheCBjYWxscyBpbiBhIHN0YW5kYXJkaXplZCBmb3JtYXQuIEhhbmRsZXMgZGlmZmVyZW50XG4gICAgICogZXJyb3IgdHlwZXMgKGZhdGFsLCB2YWxpZGF0aW9uLCBhdXRoLCBnZW5lcmljKSB3aXRoIGFwcHJvcHJpYXRlIGZvcm1hdHRpbmcuXG4gICAgICpcbiAgICAgKiBVc2FnZTpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogdHJ5IHtcbiAgICAgKiAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgQ29udHJvbGxlci5tZXRob2QoKTtcbiAgICAgKiB9IGNhdGNoIChlcnJvcikge1xuICAgICAqICAgICBSc3gucmVuZGVyX2Vycm9yKGVycm9yLCAnI2Vycm9yX2NvbnRhaW5lcicpO1xuICAgICAqIH1cbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RXJyb3J8T2JqZWN0fSBlcnJvciAtIEVycm9yIG9iamVjdCBmcm9tIEFqYXggY2FsbFxuICAgICAqIEBwYXJhbSB7alF1ZXJ5fHN0cmluZ30gY29udGFpbmVyIC0galF1ZXJ5IGVsZW1lbnQgb3Igc2VsZWN0b3IgZm9yIGVycm9yIGRpc3BsYXlcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVuZGVyX2Vycm9yKGVycm9yLCBjb250YWluZXIpIHtcbiAgICAgICAgY29uc3QgJGNvbnRhaW5lciA9ICQoY29udGFpbmVyKTtcblxuICAgICAgICBpZiAoISRjb250YWluZXIuZXhpc3RzKCkpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1JzeC5yZW5kZXJfZXJyb3I6IENvbnRhaW5lciBub3QgZm91bmQnLCBjb250YWluZXIpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgY29udGVudFxuICAgICAgICAkY29udGFpbmVyLmVtcHR5KCk7XG5cbiAgICAgICAgbGV0IGh0bWwgPSAnJztcblxuICAgICAgICAvLyBIYW5kbGUgZGlmZmVyZW50IGVycm9yIHR5cGVzXG4gICAgICAgIGlmIChlcnJvci50eXBlID09PSAnZmF0YWwnICYmIGVycm9yLmRldGFpbHMpIHtcbiAgICAgICAgICAgIC8vIEZhdGFsIFBIUCBlcnJvciB3aXRoIGZpbGUvbGluZS9lcnJvclxuICAgICAgICAgICAgY29uc3QgZGV0YWlscyA9IGVycm9yLmRldGFpbHM7XG4gICAgICAgICAgICBjb25zdCBmaWxlID0gZGV0YWlscy5maWxlIHx8ICdVbmtub3duIGZpbGUnO1xuICAgICAgICAgICAgY29uc3QgbGluZSA9IGRldGFpbHMubGluZSB8fCAnPyc7XG4gICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gZGV0YWlscy5lcnJvciB8fCBlcnJvci5tZXNzYWdlIHx8ICdGYXRhbCBlcnJvciBvY2N1cnJlZCc7XG5cbiAgICAgICAgICAgIGh0bWwgPSBgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiIHJvbGU9XCJhbGVydFwiPlxuICAgICAgICAgICAgICAgICAgICA8aDU+VW5jYXVnaHQgRmF0YWwgRXJyb3IgaW4gJHtmaWxlfToke2xpbmV9OjwvaDU+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPiR7UnN4Ll9lc2NhcGVfaHRtbChtZXNzYWdlKX08L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yLnR5cGUgPT09ICdmb3JtX2Vycm9yJyAmJiBlcnJvci5kZXRhaWxzKSB7XG4gICAgICAgICAgICAvLyBWYWxpZGF0aW9uIGVycm9ycyAtIHNob3cgdW5tYXRjaGVkIGVycm9ycyBvbmx5XG4gICAgICAgICAgICAvLyAobWF0Y2hlZCBlcnJvcnMgc2hvdWxkIGJlIGhhbmRsZWQgYnkgRm9ybV9VdGlscy5hcHBseV9mb3JtX2Vycm9ycylcbiAgICAgICAgICAgIGNvbnN0IGVycm9ycyA9IGVycm9yLmRldGFpbHM7XG4gICAgICAgICAgICBjb25zdCBlcnJvcl9saXN0ID0gW107XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgZmllbGQgaW4gZXJyb3JzKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JfbGlzdC5wdXNoKGVycm9yc1tmaWVsZF0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZXJyb3JfbGlzdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgaHRtbCA9IGBcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxoNT5WYWxpZGF0aW9uIEVycm9yczo8L2g1PlxuICAgICAgICAgICAgICAgICAgICAgICAgPHVsIGNsYXNzPVwibWItMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR7ZXJyb3JfbGlzdC5tYXAoZXJyID0+IGA8bGk+JHtSc3guX2VzY2FwZV9odG1sKGVycil9PC9saT5gKS5qb2luKCcnKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIGA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IudHlwZSA9PT0gJ2F1dGhfcmVxdWlyZWQnIHx8IGVycm9yLnR5cGUgPT09ICd1bmF1dGhvcml6ZWQnKSB7XG4gICAgICAgICAgICAvLyBBdXRoZW50aWNhdGlvbi9hdXRob3JpemF0aW9uIGVycm9yc1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2UgfHwgJ0F1dGhlbnRpY2F0aW9uIHJlcXVpcmVkJztcbiAgICAgICAgICAgIGh0bWwgPSBgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXdhcm5pbmdcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+JHtSc3guX2VzY2FwZV9odG1sKG1lc3NhZ2UpfTwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IudHlwZSA9PT0gJ25ldHdvcmsnKSB7XG4gICAgICAgICAgICAvLyBOZXR3b3JrIGVycm9yc1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2UgfHwgJ1VuYWJsZSB0byByZWFjaCBzZXJ2ZXIuIFBsZWFzZSBjaGVjayB5b3VyIGNvbm5lY3Rpb24uJztcbiAgICAgICAgICAgIGh0bWwgPSBgXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiIHJvbGU9XCJhbGVydFwiPlxuICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj4ke1JzeC5fZXNjYXBlX2h0bWwobWVzc2FnZSl9PC9wPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgYDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEdlbmVyaWMvdW5rbm93biBlcnJvclxuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGVycm9yLm1lc3NhZ2UgfHwgZXJyb3IudG9TdHJpbmcoKSB8fCAnQW4gdW5rbm93biBlcnJvciBvY2N1cnJlZCc7XG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+JHtSc3guX2VzY2FwZV9odG1sKG1lc3NhZ2UpfTwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgIH1cblxuICAgICAgICAkY29udGFpbmVyLmh0bWwoaHRtbCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXNjYXBlIEhUTUwgdG8gcHJldmVudCBYU1MgaW4gZXJyb3IgbWVzc2FnZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZXNjYXBlX2h0bWwodGV4dCkge1xuICAgICAgICBjb25zdCBkaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgZGl2LnRleHRDb250ZW50ID0gdGV4dDtcbiAgICAgICAgcmV0dXJuIGRpdi5pbm5lckhUTUw7XG4gICAgfVxufVxuIiwiLy8gQEZJTEUtU1VCQ0xBU1MtMDEtRVhDRVBUSU9OXG5cbi8qKlxuICogQ2xpZW50LXNpZGUgQWpheCBjbGFzcyBmb3IgbWFraW5nIEFQSSBjYWxscyB0byBSU1ggY29udHJvbGxlcnNcbiAqXG4gKiBBdXRvbWF0aWNhbGx5IGJhdGNoZXMgbXVsdGlwbGUgY2FsbHMgaW50byBzaW5nbGUgSFRUUCByZXF1ZXN0cyB0byByZWR1Y2UgbmV0d29yayBvdmVyaGVhZC5cbiAqIEJhdGNoZXMgdXAgdG8gMjAgY2FsbHMgb3IgZmx1c2hlcyBhZnRlciBzZXRUaW1lb3V0KDApIGRlYm91bmNlLlxuICovXG5jbGFzcyBBamF4IHtcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIEFqYXggc3lzdGVtXG4gICAgICogQ2FsbGVkIGF1dG9tYXRpY2FsbHkgd2hlbiBjbGFzcyBpcyBsb2FkZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2luaXQoKSB7XG4gICAgICAgIC8vIFF1ZXVlIG9mIHBlbmRpbmcgY2FsbHMgd2FpdGluZyB0byBiZSBiYXRjaGVkXG4gICAgICAgIEFqYXguX3BlbmRpbmdfY2FsbHMgPSB7fTtcblxuICAgICAgICAvLyBUaW1lciBmb3IgYmF0Y2hpbmcgZmx1c2hcbiAgICAgICAgQWpheC5fZmx1c2hfdGltZW91dCA9IG51bGw7XG5cbiAgICAgICAgLy8gQ2FsbCBjb3VudGVyIGZvciBnZW5lcmF0aW5nIHVuaXF1ZSBjYWxsIElEc1xuICAgICAgICBBamF4Ll9jYWxsX2NvdW50ZXIgPSAwO1xuXG4gICAgICAgIC8vIE1heGltdW0gYmF0Y2ggc2l6ZSBiZWZvcmUgZm9yY2luZyBpbW1lZGlhdGUgZmx1c2hcbiAgICAgICAgQWpheC5NQVhfQkFUQ0hfU0laRSA9IDIwO1xuXG4gICAgICAgIC8vIERlYm91bmNlIHRpbWUgaW4gbWlsbGlzZWNvbmRzXG4gICAgICAgIEFqYXguREVCT1VOQ0VfTVMgPSAwO1xuXG4gICAgICAgIC8vIFRyYWNrIHByb21pc2VzIGZyb20gQWpheCBjYWxscyB0byBkZXRlY3QgdW5jYXVnaHQgcmVqZWN0aW9uc1xuICAgICAgICBBamF4Ll90cmFja2VkX3Byb21pc2VzID0gbmV3IFdlYWtTZXQoKTtcblxuICAgICAgICAvLyBTZXQgdXAgZ2xvYmFsIHVuaGFuZGxlZCByZWplY3Rpb24gaGFuZGxlciBmb3IgQWpheCBlcnJvcnNcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3VuaGFuZGxlZHJlamVjdGlvbicsIGFzeW5jIChldmVudCkgPT4ge1xuICAgICAgICAgICAgLy8gT25seSBoYW5kbGUgcmVqZWN0aW9ucyBmcm9tIEFqYXggcHJvbWlzZXNcbiAgICAgICAgICAgIGlmIChBamF4Ll90cmFja2VkX3Byb21pc2VzLmhhcyhldmVudC5wcm9taXNlKSkge1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIFByZXZlbnQgYnJvd3NlcidzIGRlZmF1bHQgXCJVbmNhdWdodCAoaW4gcHJvbWlzZSlcIiBlcnJvclxuXG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBldmVudC5yZWFzb247XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignVW5jYXVnaHQgQWpheCBlcnJvcjonLCBlcnJvcik7XG5cbiAgICAgICAgICAgICAgICAvLyBTaG93IE1vZGFsLmVycm9yKCkgZm9yIHVuY2F1Z2h0IEFqYXggZXJyb3JzXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBNb2RhbCAhPT0gJ3VuZGVmaW5lZCcgJiYgTW9kYWwuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgTW9kYWwuZXJyb3IoZXJyb3IsICdVbmNhdWdodCBBamF4IEVycm9yJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlIGFuIEFKQVggY2FsbCB0byBhbiBSU1ggY29udHJvbGxlciBhY3Rpb25cbiAgICAgKlxuICAgICAqIEFsbCBjYWxscyBhcmUgYXV0b21hdGljYWxseSBiYXRjaGVkIHVubGVzcyB3aW5kb3cucnN4YXBwLmFqYXhfZGlzYWJsZV9iYXRjaGluZyBpcyB0cnVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8b2JqZWN0fGZ1bmN0aW9ufSB1cmwgLSBUaGUgQWpheCBVUkwgKGUuZy4sICcvX2FqYXgvQ29udHJvbGxlcl9OYW1lL2FjdGlvbl9uYW1lJykgb3IgYW4gb2JqZWN0L2Z1bmN0aW9uIHdpdGggYSAucGF0aCBwcm9wZXJ0eVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBwYXJhbXMgLSBQYXJhbWV0ZXJzIHRvIHNlbmQgdG8gdGhlIGFjdGlvblxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSAtIFJlc29sdmVzIHdpdGggdGhlIHJldHVybiB2YWx1ZSwgcmVqZWN0cyB3aXRoIGVycm9yXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGNhbGwodXJsLCBwYXJhbXMgPSB7fSkge1xuICAgICAgICAvLyBJZiB1cmwgaXMgYW4gb2JqZWN0IG9yIGZ1bmN0aW9uIHdpdGggYSAucGF0aCBwcm9wZXJ0eSwgdXNlIHRoYXQgYXMgdGhlIFVSTFxuICAgICAgICBpZiAodXJsICYmIHR5cGVvZiB1cmwgPT09ICdvYmplY3QnICYmIHVybC5wYXRoKSB7XG4gICAgICAgICAgICB1cmwgPSB1cmwucGF0aDtcbiAgICAgICAgfSBlbHNlIGlmICh1cmwgJiYgdHlwZW9mIHVybCA9PT0gJ2Z1bmN0aW9uJyAmJiB1cmwucGF0aCkge1xuICAgICAgICAgICAgdXJsID0gdXJsLnBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBWYWxpZGF0ZSB1cmwgaXMgYSBub24tZW1wdHkgc3RyaW5nXG4gICAgICAgIGlmICh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJyB8fCB1cmwubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FqYXguY2FsbCgpIHJlcXVpcmVzIGEgbm9uLWVtcHR5IHN0cmluZyBVUkwgb3IgYW4gb2JqZWN0L2Z1bmN0aW9uIHdpdGggYSAucGF0aCBwcm9wZXJ0eScpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRXh0cmFjdCBjb250cm9sbGVyIGFuZCBhY3Rpb24gZnJvbSBVUkxcbiAgICAgICAgY29uc3QgeyBjb250cm9sbGVyLCBhY3Rpb24gfSA9IEFqYXguYWpheF91cmxfdG9fY29udHJvbGxlcl9hY3Rpb24odXJsKTtcblxuICAgICAgICBjb25zb2xlLmxvZygnQWpheDonLCBjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyk7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgYmF0Y2hpbmcgaXMgZGlzYWJsZWQgZm9yIGRlYnVnZ2luZ1xuICAgICAgICBsZXQgcHJvbWlzZTtcbiAgICAgICAgaWYgKHdpbmRvdy5yc3hhcHAgJiYgd2luZG93LnJzeGFwcC5hamF4X2Rpc2FibGVfYmF0Y2hpbmcpIHtcbiAgICAgICAgICAgIHByb21pc2UgPSBBamF4Ll9jYWxsX2RpcmVjdChjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcm9taXNlID0gQWpheC5fY2FsbF9iYXRjaChjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmFjayB0aGlzIHByb21pc2UgZm9yIHVuaGFuZGxlZCByZWplY3Rpb24gZGV0ZWN0aW9uXG4gICAgICAgIEFqYXguX3RyYWNrZWRfcHJvbWlzZXMuYWRkKHByb21pc2UpO1xuXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2UgYSBiYXRjaGVkIEFqYXggY2FsbFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jYWxsX2JhdGNoKGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zID0ge30pIHtcbiAgICAgICAgY29uc29sZS5sb2coJ0FqYXggQmF0Y2g6JywgY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAvLyBHZW5lcmF0ZSBjYWxsIGtleSBmb3IgZGVkdXBsaWNhdGlvblxuICAgICAgICAgICAgY29uc3QgY2FsbF9rZXkgPSBBamF4Ll9nZW5lcmF0ZV9jYWxsX2tleShjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyk7XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoaXMgZXhhY3QgY2FsbCBpcyBhbHJlYWR5IHBlbmRpbmdcbiAgICAgICAgICAgIGlmIChBamF4Ll9wZW5kaW5nX2NhbGxzW2NhbGxfa2V5XSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nX2NhbGwgPSBBamF4Ll9wZW5kaW5nX2NhbGxzW2NhbGxfa2V5XTtcblxuICAgICAgICAgICAgICAgIC8vIElmIGNhbGwgYWxyZWFkeSBjb21wbGV0ZWQgKGNhY2hlZCksIHJldHVybiBpbW1lZGlhdGVseVxuICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ19jYWxsLmlzX2NvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ19jYWxsLmlzX2Vycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXhpc3RpbmdfY2FsbC5lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGV4aXN0aW5nX2NhbGwucmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQ2FsbCBpcyBwZW5kaW5nLCBhZGQgdGhpcyBwcm9taXNlIHRvIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgIGV4aXN0aW5nX2NhbGwuY2FsbGJhY2tzLnB1c2goeyByZXNvbHZlLCByZWplY3QgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgbmV3IHBlbmRpbmcgY2FsbFxuICAgICAgICAgICAgY29uc3QgY2FsbF9pZCA9IEFqYXguX2NhbGxfY291bnRlcisrO1xuICAgICAgICAgICAgY29uc3QgcGVuZGluZ19jYWxsID0ge1xuICAgICAgICAgICAgICAgIGNhbGxfaWQ6IGNhbGxfaWQsXG4gICAgICAgICAgICAgICAgY2FsbF9rZXk6IGNhbGxfa2V5LFxuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IGNvbnRyb2xsZXIsXG4gICAgICAgICAgICAgICAgYWN0aW9uOiBhY3Rpb24sXG4gICAgICAgICAgICAgICAgcGFyYW1zOiBwYXJhbXMsXG4gICAgICAgICAgICAgICAgY2FsbGJhY2tzOiBbeyByZXNvbHZlLCByZWplY3QgfV0sXG4gICAgICAgICAgICAgICAgaXNfY29tcGxldGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGlzX2Vycm9yOiBmYWxzZSxcbiAgICAgICAgICAgICAgICByZXN1bHQ6IG51bGwsXG4gICAgICAgICAgICAgICAgZXJyb3I6IG51bGwsXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBBZGQgdG8gcGVuZGluZyBxdWV1ZVxuICAgICAgICAgICAgQWpheC5fcGVuZGluZ19jYWxsc1tjYWxsX2tleV0gPSBwZW5kaW5nX2NhbGw7XG5cbiAgICAgICAgICAgIC8vIENvdW50IHBlbmRpbmcgY2FsbHNcbiAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdfY291bnQgPSBPYmplY3Qua2V5cyhBamF4Ll9wZW5kaW5nX2NhbGxzKS5maWx0ZXIoKGtleSkgPT4gIUFqYXguX3BlbmRpbmdfY2FsbHNba2V5XS5pc19jb21wbGV0ZSkubGVuZ3RoO1xuXG4gICAgICAgICAgICAvLyBJZiB3ZSd2ZSBoaXQgdGhlIGJhdGNoIHNpemUgbGltaXQsIGZsdXNoIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICBpZiAocGVuZGluZ19jb3VudCA+PSBBamF4Lk1BWF9CQVRDSF9TSVpFKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KEFqYXguX2ZsdXNoX3RpbWVvdXQpO1xuICAgICAgICAgICAgICAgIEFqYXguX2ZsdXNoX3RpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgIEFqYXguX2ZsdXNoX3BlbmRpbmdfY2FsbHMoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gU2NoZWR1bGUgYmF0Y2ggZmx1c2ggd2l0aCBkZWJvdW5jZVxuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChBamF4Ll9mbHVzaF90aW1lb3V0KTtcbiAgICAgICAgICAgICAgICBBamF4Ll9mbHVzaF90aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIEFqYXguX2ZsdXNoX3BlbmRpbmdfY2FsbHMoKTtcbiAgICAgICAgICAgICAgICB9LCBBamF4LkRFQk9VTkNFX01TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZSBhIGRpcmVjdCAobm9uLWJhdGNoZWQpIEFqYXggY2FsbFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9jYWxsX2RpcmVjdChjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyA9IHt9KSB7XG4gICAgICAgIC8vIENvbnN0cnVjdCBVUkwgZnJvbSBjb250cm9sbGVyIGFuZCBhY3Rpb25cbiAgICAgICAgY29uc3QgdXJsID0gYC9fYWpheC8ke2NvbnRyb2xsZXJ9LyR7YWN0aW9ufWA7XG5cbiAgICAgICAgLy8gTG9nIHRoZSBBSkFYIGNhbGwgdXNpbmcgY29uc29sZV9kZWJ1Z1xuICAgICAgICBpZiAodHlwZW9mIERlYnVnZ2VyICE9PSAndW5kZWZpbmVkJyAmJiBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKSB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKCdBSkFYJywgYENhbGxpbmcgJHtjb250cm9sbGVyfS4ke2FjdGlvbn0gKHVuYmF0Y2hlZClgLCBwYXJhbXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICQuYWpheCh7XG4gICAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICAgICAgZGF0YTogcGFyYW1zLFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICAgICAgX19sb2NhbF9pbnRlZ3JhdGlvbjogdHJ1ZSwgLy8gQnlwYXNzICQuYWpheCBvdmVycmlkZVxuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgY29uc29sZV9kZWJ1ZyBtZXNzYWdlc1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuY29uc29sZV9kZWJ1ZyAmJiBBcnJheS5pc0FycmF5KHJlc3BvbnNlLmNvbnNvbGVfZGVidWcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZS5jb25zb2xlX2RlYnVnLmZvckVhY2goKG1zZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtc2cpIHx8IG1zZy5sZW5ndGggIT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbnNvbGVfZGVidWcgbWVzc2FnZSBmb3JtYXQgLSBleHBlY3RlZCBbY2hhbm5lbCwgW2FyZ3VtZW50c11dJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IFtjaGFubmVsLCBhcmdzXSA9IG1zZztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhjaGFubmVsLCAuLi5hcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIHJlc3BvbnNlIHdhcyBzdWNjZXNzZnVsXG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5fc3VjY2VzcyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQEpTLUFKQVgtMDItRVhDRVBUSU9OIC0gVW53cmFwIHNlcnZlciByZXNwb25zZXMgd2l0aCBfYWpheF9yZXR1cm5fdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NlZF92YWx1ZSA9IFJzeF9Kc19Nb2RlbC5faW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZShyZXNwb25zZS5fYWpheF9yZXR1cm5fdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIGVycm9yIHJlc3BvbnNlc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JfdHlwZSA9IHJlc3BvbnNlLmVycm9yX3R5cGUgfHwgJ3Vua25vd25fZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVhc29uID0gcmVzcG9uc2UucmVhc29uIHx8ICdVbmtub3duIGVycm9yIG9jY3VycmVkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRldGFpbHMgPSByZXNwb25zZS5kZXRhaWxzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBIYW5kbGUgc3BlY2lmaWMgZXJyb3IgdHlwZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZXJyb3JfdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2ZhdGFsJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmF0YWwgUEhQIGVycm9yIHdpdGggZnVsbCBlcnJvciBkZXRhaWxzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGZhdGFsX2Vycm9yX2RhdGEgPSByZXNwb25zZS5lcnJvciB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JfbWVzc2FnZSA9IGZhdGFsX2Vycm9yX2RhdGEuZXJyb3IgfHwgJ0ZhdGFsIGVycm9yIG9jY3VycmVkJztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdBamF4IGVycm9yIHJlc3BvbnNlIGZyb20gc2VydmVyOicsIHJlc3BvbnNlLmVycm9yKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmYXRhbF9lcnJvciA9IG5ldyBFcnJvcihlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmF0YWxfZXJyb3IudHlwZSA9ICdmYXRhbCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhdGFsX2Vycm9yLmRldGFpbHMgPSByZXNwb25zZS5lcnJvcjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBMb2cgdG8gc2VydmVyIGlmIGJyb3dzZXIgZXJyb3IgbG9nZ2luZyBpcyBlbmFibGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlYnVnZ2VyLmxvZ19lcnJvcih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgQWpheCBGYXRhbCBFcnJvcjogJHtlcnJvcl9tZXNzYWdlfWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnYWpheF9mYXRhbCcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmRwb2ludDogdXJsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV0YWlsczogcmVzcG9uc2UuZXJyb3IsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChmYXRhbF9lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVzcG9uc2VfYXV0aF9yZXF1aXJlZCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVGhlIHVzZXIgaXMgbm8gbG9uZ2VyIGF1dGhlbnRpY2F0ZWQsIHRoaXMgaXMgYSBwbGFjZWhvbGRlciBmb3IgZnV0dXJlIGNvZGUgd2hpY2ggaGFuZGxlcyB0aGlzIHNjZW5hcmlvLidcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV0aF9lcnJvciA9IG5ldyBFcnJvcihyZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRoX2Vycm9yLnR5cGUgPSAnYXV0aF9yZXF1aXJlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dGhfZXJyb3IuZGV0YWlscyA9IGRldGFpbHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChhdXRoX2Vycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNwb25zZV91bmF1dGhvcml6ZWQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RoZSB1c2VyIGlzIHVuYXV0aG9yaXplZCB0byBwZXJmb3JtIHRoaXMgYWN0aW9uLCB0aGlzIGlzIGEgcGxhY2Vob2xkZXIgZm9yIGZ1dHVyZSBjb2RlIHdoaWNoIGhhbmRsZXMgdGhpcyBzY2VuYXJpby4nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVuYXV0aF9lcnJvciA9IG5ldyBFcnJvcihyZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmF1dGhfZXJyb3IudHlwZSA9ICd1bmF1dGhvcml6ZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmF1dGhfZXJyb3IuZGV0YWlscyA9IGRldGFpbHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCh1bmF1dGhfZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3Jlc3BvbnNlX2Zvcm1fZXJyb3InOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb3JtX2Vycm9yID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1fZXJyb3IudHlwZSA9ICdmb3JtX2Vycm9yJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybV9lcnJvci5kZXRhaWxzID0gZGV0YWlscztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGZvcm1fZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdlbmVyaWNfZXJyb3IgPSBuZXcgRXJyb3IocmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXJpY19lcnJvci50eXBlID0gZXJyb3JfdHlwZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2VuZXJpY19lcnJvci5kZXRhaWxzID0gZGV0YWlscztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGdlbmVyaWNfZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6ICh4aHIsIHN0YXR1cywgZXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JfbWVzc2FnZSA9IEFqYXguX2V4dHJhY3RfZXJyb3JfbWVzc2FnZSh4aHIpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXR3b3JrX2Vycm9yID0gbmV3IEVycm9yKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBuZXR3b3JrX2Vycm9yLnR5cGUgPSAnbmV0d29ya19lcnJvcic7XG4gICAgICAgICAgICAgICAgICAgIG5ldHdvcmtfZXJyb3Iuc3RhdHVzID0geGhyLnN0YXR1cztcbiAgICAgICAgICAgICAgICAgICAgbmV0d29ya19lcnJvci5zdGF0dXNUZXh0ID0gc3RhdHVzO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIExvZyBzZXJ2ZXIgZXJyb3JzICg1MDArKSB0byB0aGUgc2VydmVyIGlmIGJyb3dzZXIgZXJyb3IgbG9nZ2luZyBpcyBlbmFibGVkXG4gICAgICAgICAgICAgICAgICAgIGlmICh4aHIuc3RhdHVzID49IDUwMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgRGVidWdnZXIubG9nX2Vycm9yKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgQWpheCBTZXJ2ZXIgRXJyb3IgJHt4aHIuc3RhdHVzfTogJHtlcnJvcl9tZXNzYWdlfWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2FqYXhfc2VydmVyX2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmRwb2ludDogdXJsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXR1czogeGhyLnN0YXR1cyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXNUZXh0OiBzdGF0dXMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChuZXR3b3JrX2Vycm9yKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZsdXNoIGFsbCBwZW5kaW5nIGNhbGxzIGJ5IHNlbmRpbmcgYmF0Y2ggcmVxdWVzdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9mbHVzaF9wZW5kaW5nX2NhbGxzKCkge1xuICAgICAgICAvLyBDb2xsZWN0IGFsbCBwZW5kaW5nIGNhbGxzXG4gICAgICAgIGNvbnN0IGNhbGxzX3RvX3NlbmQgPSBbXTtcbiAgICAgICAgY29uc3QgY2FsbF9tYXAgPSB7fTsgLy8gTWFwIGNhbGxfaWQgdG8gcGVuZGluZ19jYWxsIG9iamVjdFxuXG4gICAgICAgIGZvciAoY29uc3QgY2FsbF9rZXkgaW4gQWpheC5fcGVuZGluZ19jYWxscykge1xuICAgICAgICAgICAgY29uc3QgcGVuZGluZ19jYWxsID0gQWpheC5fcGVuZGluZ19jYWxsc1tjYWxsX2tleV07XG5cbiAgICAgICAgICAgIGlmICghcGVuZGluZ19jYWxsLmlzX2NvbXBsZXRlKSB7XG4gICAgICAgICAgICAgICAgY2FsbHNfdG9fc2VuZC5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbF9pZDogcGVuZGluZ19jYWxsLmNhbGxfaWQsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXI6IHBlbmRpbmdfY2FsbC5jb250cm9sbGVyLFxuICAgICAgICAgICAgICAgICAgICBhY3Rpb246IHBlbmRpbmdfY2FsbC5hY3Rpb24sXG4gICAgICAgICAgICAgICAgICAgIHBhcmFtczogcGVuZGluZ19jYWxsLnBhcmFtcyxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGNhbGxfbWFwW3BlbmRpbmdfY2FsbC5jYWxsX2lkXSA9IHBlbmRpbmdfY2FsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vdGhpbmcgdG8gc2VuZFxuICAgICAgICBpZiAoY2FsbHNfdG9fc2VuZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIExvZyBiYXRjaCBmb3IgZGVidWdnaW5nXG4gICAgICAgIGlmICh0eXBlb2YgRGVidWdnZXIgIT09ICd1bmRlZmluZWQnICYmIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoXG4gICAgICAgICAgICAgICAgJ0FKQVhfQkFUQ0gnLFxuICAgICAgICAgICAgICAgIGBTZW5kaW5nIGJhdGNoIG9mICR7Y2FsbHNfdG9fc2VuZC5sZW5ndGh9IGNhbGxzYCxcbiAgICAgICAgICAgICAgICBjYWxsc190b19zZW5kLm1hcCgoYykgPT4gYCR7Yy5jb250cm9sbGVyfS4ke2MuYWN0aW9ufWApXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFNlbmQgYmF0Y2ggcmVxdWVzdFxuICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHVybDogJy9fYWpheC9fYmF0Y2gnLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGRhdGE6IHsgYmF0Y2hfY2FsbHM6IEpTT04uc3RyaW5naWZ5KGNhbGxzX3RvX3NlbmQpIH0sXG4gICAgICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgICAgICAgICBfX2xvY2FsX2ludGVncmF0aW9uOiB0cnVlLCAvLyBCeXBhc3MgJC5hamF4IG92ZXJyaWRlXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLy8gUHJvY2VzcyBiYXRjaCByZXNwb25zZVxuICAgICAgICAgICAgLy8gUmVzcG9uc2UgZm9ybWF0OiB7IENfMDoge3N1Y2Nlc3MsIF9hamF4X3JldHVybl92YWx1ZX0sIENfMTogey4uLn0sIC4uLiB9XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHJlc3BvbnNlX2tleSBpbiByZXNwb25zZSkge1xuICAgICAgICAgICAgICAgIGlmICghcmVzcG9uc2Vfa2V5LnN0YXJ0c1dpdGgoJ0NfJykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgY2FsbF9pZCA9IHBhcnNlSW50KHJlc3BvbnNlX2tleS5zdWJzdHJpbmcoMiksIDEwKTtcbiAgICAgICAgICAgICAgICBjb25zdCBjYWxsX3Jlc3BvbnNlID0gcmVzcG9uc2VbcmVzcG9uc2Vfa2V5XTtcbiAgICAgICAgICAgICAgICBjb25zdCBwZW5kaW5nX2NhbGwgPSBjYWxsX21hcFtjYWxsX2lkXTtcblxuICAgICAgICAgICAgICAgIGlmICghcGVuZGluZ19jYWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1JlY2VpdmVkIHJlc3BvbnNlIGZvciB1bmtub3duIGNhbGxfaWQ6JywgY2FsbF9pZCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBjb25zb2xlX2RlYnVnIG1lc3NhZ2VzIGlmIHByZXNlbnRcbiAgICAgICAgICAgICAgICBpZiAoY2FsbF9yZXNwb25zZS5jb25zb2xlX2RlYnVnICYmIEFycmF5LmlzQXJyYXkoY2FsbF9yZXNwb25zZS5jb25zb2xlX2RlYnVnKSkge1xuICAgICAgICAgICAgICAgICAgICBjYWxsX3Jlc3BvbnNlLmNvbnNvbGVfZGVidWcuZm9yRWFjaCgobXNnKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobXNnKSB8fCBtc2cubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbnNvbGVfZGVidWcgbWVzc2FnZSBmb3JtYXQgLSBleHBlY3RlZCBbY2hhbm5lbCwgW2FyZ3VtZW50c11dJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbY2hhbm5lbCwgYXJnc10gPSBtc2c7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhjaGFubmVsLCAuLi5hcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTWFyayBjYWxsIGFzIGNvbXBsZXRlXG4gICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmlzX2NvbXBsZXRlID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHN1Y2Nlc3NmdWxcbiAgICAgICAgICAgICAgICBpZiAoY2FsbF9yZXNwb25zZS5fc3VjY2VzcyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBASlMtQUpBWC0wMi1FWENFUFRJT04gLSBCYXRjaCBzeXN0ZW0gdW53cmFwcyBzZXJ2ZXIgcmVzcG9uc2VzIHdpdGggX2FqYXhfcmV0dXJuX3ZhbHVlXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NlZF92YWx1ZSA9IFJzeF9Kc19Nb2RlbC5faW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZShjYWxsX3Jlc3BvbnNlLl9hamF4X3JldHVybl92YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5yZXN1bHQgPSBwcm9jZXNzZWRfdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSBhbGwgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5jYWxsYmFja3MuZm9yRWFjaCgoeyByZXNvbHZlIH0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIGVycm9yXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yX3R5cGUgPSBjYWxsX3Jlc3BvbnNlLmVycm9yX3R5cGUgfHwgJ3Vua25vd25fZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZXJyb3JfbWVzc2FnZTtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yX2RldGFpbHM7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yX3R5cGUgPT09ICdmYXRhbCcgJiYgY2FsbF9yZXNwb25zZS5lcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRmF0YWwgUEhQIGVycm9yIHdpdGggZnVsbCBlcnJvciBkZXRhaWxzXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmYXRhbF9lcnJvcl9kYXRhID0gY2FsbF9yZXNwb25zZS5lcnJvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgPSBmYXRhbF9lcnJvcl9kYXRhLmVycm9yIHx8ICdGYXRhbCBlcnJvciBvY2N1cnJlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl9kZXRhaWxzID0gY2FsbF9yZXNwb25zZS5lcnJvcjtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignQWpheCBlcnJvciByZXNwb25zZSBmcm9tIHNlcnZlcjonLCBjYWxsX3Jlc3BvbnNlLmVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE90aGVyIGVycm9yIHR5cGVzXG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlID0gY2FsbF9yZXNwb25zZS5yZWFzb24gfHwgJ1Vua25vd24gZXJyb3Igb2NjdXJyZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfZGV0YWlscyA9IGNhbGxfcmVzcG9uc2UuZGV0YWlscyB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBlcnJvci50eXBlID0gZXJyb3JfdHlwZTtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IuZGV0YWlscyA9IGVycm9yX2RldGFpbHM7XG5cbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmlzX2Vycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmVycm9yID0gZXJyb3I7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVqZWN0IGFsbCBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmNhbGxiYWNrcy5mb3JFYWNoKCh7IHJlamVjdCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKHhocl9lcnJvcikge1xuICAgICAgICAgICAgLy8gTmV0d29yayBvciBzZXJ2ZXIgZXJyb3IgLSByZWplY3QgYWxsIHBlbmRpbmcgY2FsbHNcbiAgICAgICAgICAgIGNvbnN0IGVycm9yX21lc3NhZ2UgPSBBamF4Ll9leHRyYWN0X2Vycm9yX21lc3NhZ2UoeGhyX2Vycm9yKTtcbiAgICAgICAgICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgZXJyb3IudHlwZSA9ICduZXR3b3JrX2Vycm9yJztcblxuICAgICAgICAgICAgZm9yIChjb25zdCBjYWxsX2lkIGluIGNhbGxfbWFwKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGVuZGluZ19jYWxsID0gY2FsbF9tYXBbY2FsbF9pZF07XG4gICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmlzX2NvbXBsZXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuaXNfZXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5lcnJvciA9IGVycm9yO1xuXG4gICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmNhbGxiYWNrcy5mb3JFYWNoKCh7IHJlamVjdCB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0JhdGNoIEFqYXggcmVxdWVzdCBmYWlsZWQ6JywgZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIHVuaXF1ZSBrZXkgZm9yIGRlZHVwbGljYXRpbmcgY2FsbHNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZ2VuZXJhdGVfY2FsbF9rZXkoY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMpIHtcbiAgICAgICAgLy8gQ3JlYXRlIGEgc3RhYmxlIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgY2FsbFxuICAgICAgICAvLyBTb3J0IHBhcmFtcyBrZXlzIGZvciBjb25zaXN0ZW50IGhhc2hpbmdcbiAgICAgICAgY29uc3Qgc29ydGVkX3BhcmFtcyA9IHt9O1xuICAgICAgICBPYmplY3Qua2V5cyhwYXJhbXMpXG4gICAgICAgICAgICAuc29ydCgpXG4gICAgICAgICAgICAuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgc29ydGVkX3BhcmFtc1trZXldID0gcGFyYW1zW2tleV07XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gYCR7Y29udHJvbGxlcn06OiR7YWN0aW9ufTo6JHtKU09OLnN0cmluZ2lmeShzb3J0ZWRfcGFyYW1zKX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4dHJhY3QgZXJyb3IgbWVzc2FnZSBmcm9tIGpRdWVyeSBYSFIgb2JqZWN0XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2V4dHJhY3RfZXJyb3JfbWVzc2FnZSh4aHIpIHtcbiAgICAgICAgaWYgKHhoci5yZXNwb25zZUpTT04gJiYgeGhyLnJlc3BvbnNlSlNPTi5tZXNzYWdlKSB7XG4gICAgICAgICAgICByZXR1cm4geGhyLnJlc3BvbnNlSlNPTi5tZXNzYWdlO1xuICAgICAgICB9IGVsc2UgaWYgKHhoci5yZXNwb25zZVRleHQpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBKU09OLnBhcnNlKHhoci5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZS5tZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5tZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBOb3QgSlNPTlxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGAke3hoci5zdGF0dXN9OiAke3hoci5zdGF0dXNUZXh0IHx8ICdVbmtub3duIGVycm9yJ31gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhcnNlcyBhbiBBSkFYIFVSTCBpbnRvIGNvbnRyb2xsZXIgYW5kIGFjdGlvblxuICAgICAqIFN1cHBvcnRzIGJvdGggL19hamF4LyBhbmQgL18vIFVSTCBwcmVmaXhlc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfG9iamVjdHxmdW5jdGlvbn0gdXJsIC0gVVJMIGluIGZvcm1hdCAnL19hamF4L0NvbnRyb2xsZXJfTmFtZS9hY3Rpb25fbmFtZScgb3IgJy9fL0NvbnRyb2xsZXJfTmFtZS9hY3Rpb25fbmFtZScsIG9yIGFuIG9iamVjdC9mdW5jdGlvbiB3aXRoIGEgLnBhdGggcHJvcGVydHlcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3Qgd2l0aCB7Y29udHJvbGxlcjogc3RyaW5nLCBhY3Rpb246IHN0cmluZ31cbiAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgVVJMIGRvZXNuJ3Qgc3RhcnQgd2l0aCAvX2FqYXggb3IgL18gb3IgaGFzIGludmFsaWQgc3RydWN0dXJlXG4gICAgICovXG4gICAgc3RhdGljIGFqYXhfdXJsX3RvX2NvbnRyb2xsZXJfYWN0aW9uKHVybCkge1xuICAgICAgICAvLyBJZiB1cmwgaXMgYW4gb2JqZWN0IG9yIGZ1bmN0aW9uIHdpdGggYSAucGF0aCBwcm9wZXJ0eSwgdXNlIHRoYXQgYXMgdGhlIFVSTFxuICAgICAgICBpZiAodXJsICYmIHR5cGVvZiB1cmwgPT09ICdvYmplY3QnICYmIHVybC5wYXRoKSB7XG4gICAgICAgICAgICB1cmwgPSB1cmwucGF0aDtcbiAgICAgICAgfSBlbHNlIGlmICh1cmwgJiYgdHlwZW9mIHVybCA9PT0gJ2Z1bmN0aW9uJyAmJiB1cmwucGF0aCkge1xuICAgICAgICAgICAgdXJsID0gdXJsLnBhdGg7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBWYWxpZGF0ZSB1cmwgaXMgYSBzdHJpbmdcbiAgICAgICAgaWYgKHR5cGVvZiB1cmwgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVSTCBtdXN0IGJlIGEgc3RyaW5nIG9yIGhhdmUgYSAucGF0aCBwcm9wZXJ0eSwgZ290OiAke3R5cGVvZiB1cmx9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXVybC5zdGFydHNXaXRoKCcvX2FqYXgnKSAmJiAhdXJsLnN0YXJ0c1dpdGgoJy9fLycpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVSTCBtdXN0IHN0YXJ0IHdpdGggL19hamF4IG9yIC9fLCBnb3Q6ICR7dXJsfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFydHMgPSB1cmwuc3BsaXQoJy8nKS5maWx0ZXIoKHBhcnQpID0+IHBhcnQgIT09ICcnKTtcblxuICAgICAgICBpZiAocGFydHMubGVuZ3RoIDwgMikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIEFKQVggVVJMIHN0cnVjdHVyZTogJHt1cmx9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFydHMubGVuZ3RoID4gMykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBBSkFYIFVSTCBoYXMgdG9vIG1hbnkgc2VnbWVudHM6ICR7dXJsfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udHJvbGxlciA9IHBhcnRzWzFdO1xuICAgICAgICBjb25zdCBhY3Rpb24gPSBwYXJ0c1syXSB8fCAnaW5kZXgnO1xuXG4gICAgICAgIHJldHVybiB7IGNvbnRyb2xsZXIsIGFjdGlvbiB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF1dG8taW5pdGlhbGl6ZSBzdGF0aWMgcHJvcGVydGllcyB3aGVuIGNsYXNzIGlzIGZpcnN0IGxvYWRlZFxuICAgICAqL1xuICAgIHN0YXRpYyBvbl9jb3JlX2RlZmluZSgpIHtcbiAgICAgICAgQWpheC5fb25fZnJhbWV3b3JrX2NvcmVfaW5pdCgpO1xuICAgIH1cbn1cbiIsIi8qKlxuICogSnFodG1sX0NvbXBvbmVudCAtIEJhc2UgY2xhc3MgZm9yIEpRSFRNTCBjb21wb25lbnRzIGluIFJTWCBmcmFtZXdvcmtcbiAqXG4gKiBUaGlzIGNsYXNzIHdyYXBzIHRoZSBqcWh0bWwuQ29tcG9uZW50IGZyb20gdGhlIG5wbSBwYWNrYWdlIGFuZCBwcm92aWRlc1xuICogdGhlIHN0YW5kYXJkIGludGVyZmFjZSBmb3IgUlNYIGNvbXBvbmVudHMgZm9sbG93aW5nIHRoZSBVcHBlcl9DYXNlIG5hbWluZyBjb252ZW50aW9uLlxuICpcbiAqIF9CYXNlX0pxaHRtbF9Db21wb25lbnQgaXMgaW1wb3J0ZWQgZnJvbSBucG0gdmlhIEpxaHRtbF9CdW5kbGUuXG4gKlxuICogQEluc3RhbnRpYXRhYmxlXG4gKi9cbmNsYXNzIEpxaHRtbF9Db21wb25lbnQgZXh0ZW5kcyBfQmFzZV9KcWh0bWxfQ29tcG9uZW50IHt9XG5cbi8vIFJTWCBtYW5pZmVzdCBhdXRvbWF0aWNhbGx5IG1ha2VzIGNsYXNzZXMgZ2xvYmFsIC0gbm8gbWFudWFsIGFzc2lnbm1lbnQgbmVlZGVkXG4iLCIvKipcbiAqIEpRSFRNTCBJbnRlZ3JhdGlvbiAtIEF1dG9tYXRpYyBjb21wb25lbnQgcmVnaXN0cmF0aW9uIGFuZCBiaW5kaW5nXG4gKlxuICogVGhpcyBtb2R1bGUgYXV0b21hdGljYWxseTpcbiAqIDEuIFJlZ2lzdGVycyBjb21wb25lbnQgY2xhc3NlcyB0aGF0IGV4dGVuZCBKcWh0bWxfQ29tcG9uZW50XG4gKiAyLiBCaW5kcyB0ZW1wbGF0ZXMgdG8gY29tcG9uZW50IGNsYXNzZXMgd2hlbiBuYW1lcyBtYXRjaFxuICogMy4gRW5hYmxlcyAkKHNlbGVjdG9yKS5jb21wb25lbnQoXCJDb21wb25lbnRfTmFtZVwiKSBzeW50YXhcbiAqL1xuY2xhc3MgSnFodG1sX0ludGVncmF0aW9uIHtcbiAgICAvKipcbiAgICAgKiBDb21waWxlZCBKcWh0bWwgdGVtcGxhdGVzIHNlbGYtcmVnaXN0ZXIuICBUaGUgZGV2ZWxvcGVyICh0aGUgZnJhbWV3b3JrIGluIHRoaXMgY2FzZSkgaXMgc3RpbGxcbiAgICAgKiByZXNwb25zaWJsZSBmb3IgcmVnaXN0ZXJpbmcgZXM2IGNvbXBvbmVudCBjbGFzc2VzIHdpdGgganFodG1sLiAgVGhpcyBkb2VzIHNvIGF0IGFuIGVhcmx5IHN0YWdlXG4gICAgICogb2YgZnJhbWV3b3JrIGluaXQuXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfbW9kdWxlc19kZWZpbmUoKSB7XG4gICAgICAgIGxldCBqcWh0bWxfY29tcG9uZW50cyA9IE1hbmlmZXN0LmdldF9leHRlbmRpbmcoJ0pxaHRtbF9Db21wb25lbnQnKTtcblxuICAgICAgICBjb25zb2xlX2RlYnVnKCdKUUhUTUxfSU5JVCcsICdSZWdpc3RlcmluZyAnICsganFodG1sX2NvbXBvbmVudHMubGVuZ3RoICsgJyBKcWh0bWwgQ29tcG9uZW50cycpO1xuXG4gICAgICAgIGZvciAobGV0IGNvbXBvbmVudCBvZiBqcWh0bWxfY29tcG9uZW50cykge1xuICAgICAgICAgICAganFodG1sLnJlZ2lzdGVyX2NvbXBvbmVudChjb21wb25lbnQuY2xhc3NfbmFtZSwgY29tcG9uZW50LmNsYXNzX29iamVjdCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGcmFtZXdvcmsgbW9kdWxlcyBpbml0IHBoYXNlIC0gQmluZCBjb21wb25lbnRzIGFuZCBpbml0aWFsaXplIERPTVxuICAgICAqIFRoaXMgcnVucyBhZnRlciB0ZW1wbGF0ZXMgYXJlIHJlZ2lzdGVyZWQgdG8gYmluZCBjb21wb25lbnQgY2xhc3Nlc1xuICAgICAqIEBwYXJhbSB7alF1ZXJ5fSBbJHNjb3BlXSBPcHRpb25hbCBzY29wZSB0byBzZWFyY2ggd2l0aGluIChkZWZhdWx0cyB0byBib2R5KVxuICAgICAqIEByZXR1cm5zIHtBcnJheTxQcm9taXNlPnx1bmRlZmluZWR9IEFycmF5IG9mIHByb21pc2VzIGZvciByZWN1cnNpdmUgY2FsbHMsIHVuZGVmaW5lZCBmb3IgdG9wLWxldmVsXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfbW9kdWxlc19pbml0KCRzY29wZSkge1xuICAgICAgICBjb25zdCBpc190b3BfbGV2ZWwgPSAhJHNjb3BlO1xuICAgICAgICBjb25zdCBwcm9taXNlcyA9IFtdO1xuICAgICAgICBjb25zdCBjb21wb25lbnRzX25lZWRpbmdfaW5pdCA9ICgkc2NvcGUgfHwgJCgnYm9keScpKS5maW5kKCcuSnFodG1sX0NvbXBvbmVudF9Jbml0Jyk7XG4gICAgICAgIGlmIChjb21wb25lbnRzX25lZWRpbmdfaW5pdC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdKUUhUTUxfSU5JVCcsIGBJbml0aWFsaXppbmcgJHtjb21wb25lbnRzX25lZWRpbmdfaW5pdC5sZW5ndGh9IERPTSBjb21wb25lbnRzYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb21wb25lbnRzX25lZWRpbmdfaW5pdC5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGNvbnN0ICRlbGVtZW50ID0gJCh0aGlzKTtcblxuICAgICAgICAgICAgLy8gU2tpcCBpZiBlbGVtZW50IGlzIG5vIGxvbmdlciBhdHRhY2hlZCB0byB0aGUgZG9jdW1lbnRcbiAgICAgICAgICAgIC8vIChtYXkgaGF2ZSBiZWVuIHJlbW92ZWQgYnkgYSBwYXJlbnQgY29tcG9uZW50J3MgLmVtcHR5KCkgY2FsbClcbiAgICAgICAgICAgIGlmICghZG9jdW1lbnQuY29udGFpbnMoJGVsZW1lbnRbMF0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBhbnkgcGFyZW50IGhhcyBKcWh0bWxfQ29tcG9uZW50X0luaXQgY2xhc3MgLSBza2lwIG5lc3RlZCBjb21wb25lbnRzXG4gICAgICAgICAgICBsZXQgcGFyZW50ID0gJGVsZW1lbnRbMF0ucGFyZW50RWxlbWVudDtcbiAgICAgICAgICAgIHdoaWxlIChwYXJlbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50LmNsYXNzTGlzdC5jb250YWlucygnSnFodG1sX0NvbXBvbmVudF9Jbml0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBTa2lwIHRoaXMgZWxlbWVudCwgaXQncyBuZXN0ZWRcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcGFyZW50ID0gcGFyZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudF9uYW1lID0gJGVsZW1lbnQuYXR0cignZGF0YS1jb21wb25lbnQtaW5pdC1uYW1lJyk7XG5cbiAgICAgICAgICAgIC8vIGpRdWVyeSdzIC5kYXRhKCkgZG9lc24ndCBhdXRvLXBhcnNlIEpTT04gLSB3ZSBuZWVkIHRvIHBhcnNlIGl0IG1hbnVhbGx5XG4gICAgICAgICAgICBsZXQgY29tcG9uZW50X2FyZ3MgPSB7fTtcbiAgICAgICAgICAgIGNvbnN0IGFyZ3Nfc3RyaW5nID0gJGVsZW1lbnQuYXR0cignZGF0YS1jb21wb25lbnQtYXJncycpO1xuXG4gICAgICAgICAgICAvLyBVbnNldCBjb21wb25lbnQtIHBocCBzaWRlIGluaXRpYWxpemF0aW9uIGFyZ3MsIGl0IGlzIG5vIGxvbmdlciBuZWVkZWQgYXMgYSBjb21waW9uZW50IGF0dHJpYnV0ZVxuICAgICAgICAgICAgLy8gVW5zZXR0aW5nIGFsc28gcHJldmVudHMgdW5kZXNpcmVkIGFjY2VzcyB0byB0aGlzIGNvZGUgaW4gb3RoZXIgcGFydHMgb2YgdGhlIHByb2dyYW0sIHByZXZlbmluZyBhblxuICAgICAgICAgICAgLy8gdW53YW50ZWQgZnV0dXJlIGRlcGVuZGVuY3kgb24gdGhpcyBwYXJhZGlnbVxuICAgICAgICAgICAgJGVsZW1lbnQucmVtb3ZlQXR0cignZGF0YS1jb21wb25lbnQtaW5pdC1uYW1lJyk7XG4gICAgICAgICAgICAkZWxlbWVudC5yZW1vdmVBdHRyKCdkYXRhLWNvbXBvbmVudC1hcmdzJyk7XG4gICAgICAgICAgICAkZWxlbWVudC5yZW1vdmVEYXRhKCdjb21wb25lbnQtaW5pdC1uYW1lJyk7XG4gICAgICAgICAgICAkZWxlbWVudC5yZW1vdmVEYXRhKCdjb21wb25lbnQtYXJncycpO1xuXG4gICAgICAgICAgICBpZiAoYXJnc19zdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRfYXJncyA9IEpTT04ucGFyc2UoYXJnc19zdHJpbmcpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgW0pRSFRNTCBJbnRlZ3JhdGlvbl0gRmFpbGVkIHRvIHBhcnNlIGNvbXBvbmVudCBhcmdzIGZvciAke2NvbXBvbmVudF9uYW1lfTpgLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50X2FyZ3MgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb21wb25lbnRfbmFtZSkge1xuICAgICAgICAgICAgICAgIC8vIFRyYW5zZm9ybSAkIHByZWZpeGVkIGtleXMgdG8gZGF0YS0gYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGxldCBjb21wb25lbnRfYXJnc19maWx0ZXJlZCA9IHt9O1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKGNvbXBvbmVudF9hcmdzKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBpZiAoa2V5LnN0YXJ0c1dpdGgoJyQnKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjb21wb25lbnRfYXJnc19maWx0ZXJlZFtrZXkuc3Vic3RyaW5nKDEpXSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAvLyB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleS5zdGFydHNXaXRoKCdkYXRhLScpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRfYXJnc19maWx0ZXJlZFtrZXkuc3Vic3RyaW5nKDUpXSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50X2FyZ3NfZmlsdGVyZWRba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU3RvcmUgaW5uZXIgSFRNTCBhcyBzdHJpbmcgZm9yIG5lc3RlZCBjb21wb25lbnQgcHJvY2Vzc2luZ1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnRfYXJnc19maWx0ZXJlZC5faW5uZXJfaHRtbCA9ICRlbGVtZW50Lmh0bWwoKTtcbiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQuZW1wdHkoKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgdGhlIGluaXQgY2xhc3MgYmVmb3JlIGluc3RhbnRpYXRpb24gdG8gcHJldmVudCByZS1pbml0aWFsaXphdGlvblxuICAgICAgICAgICAgICAgICAgICAkZWxlbWVudC5yZW1vdmVDbGFzcygnSnFodG1sX0NvbXBvbmVudF9Jbml0Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ3JlYXRlIHByb21pc2UgZm9yIHRoaXMgY29tcG9uZW50J3MgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29tcG9uZW50X3Byb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVXNlIGpRdWVyeSBjb21wb25lbnQgcGx1Z2luIHRvIGNyZWF0ZSB0aGUgY29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQbHVnaW4gaGFuZGxlcyBlbGVtZW50IGludGVybmFsbHksIGp1c3QgcGFzcyBhcmdzXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBHZXQgdGhlIHVwZGF0ZWQgJGVsZW1lbnQgZnJvbVxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGNvbXBvbmVudCA9ICRlbGVtZW50LmNvbXBvbmVudChjb21wb25lbnRfbmFtZSwgY29tcG9uZW50X2FyZ3NfZmlsdGVyZWQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wb25lbnQub24oJ3JlbmRlcicsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZWN1cnNpdmVseSBjb2xsZWN0IHByb21pc2VzIGZyb20gbmVzdGVkIGNvbXBvbmVudHNcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdldHRpbmcgdGhlIHVwZGF0ZWQgY29tcG9uZW50IGhlcmUgLSBpZiB0aGUgdGFnIG5hbWUgd2FzIG5vdCBkaXYsIHRoZSBlbGVtZW50IHdvdWxkIGhhdmUgYmVlbiByZWNyZWF0ZWQsIHNvIHdlIG5lZWQgdG8gZ2V0IHRoZSBlbGVtZW50IHNldCBvbiB0aGUgY29tcG9uZW50LCBub3QgZnJvbSBvdXIgZWFybGllciBzZWxlY3RvclxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmVzdGVkX3Byb21pc2VzID0gSnFodG1sX0ludGVncmF0aW9uLl9vbl9mcmFtZXdvcmtfbW9kdWxlc19pbml0KGNvbXBvbmVudC4kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKC4uLm5lc3RlZF9wcm9taXNlcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZXNvbHZlIHRoaXMgY29tcG9uZW50J3MgcHJvbWlzZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLiQ7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goY29tcG9uZW50X3Byb21pc2UpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFtKUUhUTUwgSW50ZWdyYXRpb25dIEZhaWxlZCB0byBpbml0aWFsaXplIGNvbXBvbmVudCAke2NvbXBvbmVudF9uYW1lfTpgLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGRldGFpbHM6JywgZXJyb3Iuc3RhY2sgfHwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gVG9wLWxldmVsIGNhbGw6IHNwYXduIGFzeW5jIGhhbmRsZXIgdG8gd2FpdCBmb3IgYWxsIHByb21pc2VzLCB0aGVuIHRyaWdnZXIgZXZlbnRcbiAgICAgICAgaWYgKGlzX3RvcF9sZXZlbCkge1xuICAgICAgICAgICAgKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgICAgICAgICAgICAgYXdhaXQgUnN4Ll9yc3hfY2FsbF9hbGxfY2xhc3Nlcygnb25fanFodG1sX3JlYWR5Jyk7XG4gICAgICAgICAgICAgICAgUnN4LnRyaWdnZXIoJ2pxaHRtbF9yZWFkeScpO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlY3Vyc2l2ZSBjYWxsOiByZXR1cm4gcHJvbWlzZXMgZm9yIHBhcmVudCB0byBjb2xsZWN0XG4gICAgICAgIHJldHVybiBwcm9taXNlcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHJlZ2lzdGVyZWQgY29tcG9uZW50IG5hbWVzXG4gICAgICogQHJldHVybnMge0FycmF5PHN0cmluZz59IEFycmF5IG9mIGNvbXBvbmVudCBuYW1lc1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfY29tcG9uZW50X25hbWVzKCkge1xuICAgICAgICByZXR1cm4ganFodG1sLmdldF9jb21wb25lbnRfbmFtZXMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiBhIGNvbXBvbmVudCBpcyByZWdpc3RlcmVkXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgQ29tcG9uZW50IG5hbWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBjb21wb25lbnQgaXMgcmVnaXN0ZXJlZFxuICAgICAqL1xuICAgIHN0YXRpYyBoYXNfY29tcG9uZW50KG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGpxaHRtbC5oYXNfY29tcG9uZW50KG5hbWUpO1xuICAgIH1cbn1cblxuLy8gUlNYIG1hbmlmZXN0IGF1dG9tYXRpY2FsbHkgbWFrZXMgY2xhc3NlcyBnbG9iYWwgLSBubyBtYW51YWwgYXNzaWdubWVudCBuZWVkZWRcbiIsIi8vIEphdmFTY3JpcHQgTWFuaWZlc3QgLSBHZW5lcmF0ZWQgYnkgQnVuZGxlQ29tcGlsZXJcbi8vIFJlZ2lzdGVycyBhbGwgY2xhc3NlcyBpbiB0aGlzIGJ1bmRsZSBmb3IgcnVudGltZSBpbnRyb3NwZWN0aW9uXG5NYW5pZmVzdC5fZGVmaW5lKFtcbiAgICBbTWFuaWZlc3QsIFwiTWFuaWZlc3RcIiwgbnVsbF0sXG4gICAgW1JzeF9CZWhhdmlvcnMsIFwiUnN4X0JlaGF2aW9yc1wiLCBudWxsXSxcbiAgICBbUnN4X0NhY2hlLCBcIlJzeF9DYWNoZVwiLCBudWxsXSxcbiAgICBbUnN4X0luaXQsIFwiUnN4X0luaXRcIiwgbnVsbF0sXG4gICAgW1JzeF9Kc19Nb2RlbCwgXCJSc3hfSnNfTW9kZWxcIiwgbnVsbF0sXG4gICAgW1JzeF9WaWV3X1RyYW5zaXRpb25zLCBcIlJzeF9WaWV3X1RyYW5zaXRpb25zXCIsIG51bGxdLFxuICAgIFtSZWFkV3JpdGVMb2NrLCBcIlJlYWRXcml0ZUxvY2tcIiwgbnVsbF0sXG4gICAgW0Zvcm1fVXRpbHMsIFwiRm9ybV9VdGlsc1wiLCBudWxsXSxcbiAgICBbRGVidWdnZXIsIFwiRGVidWdnZXJcIiwgbnVsbF0sXG4gICAgW1JzeF9KcV9IZWxwZXJzLCBcIlJzeF9KcV9IZWxwZXJzXCIsIG51bGxdLFxuICAgIFtSc3gsIFwiUnN4XCIsIG51bGxdLFxuICAgIFtBamF4LCBcIkFqYXhcIiwgbnVsbF0sXG4gICAgW0pxaHRtbF9Db21wb25lbnQsIFwiSnFodG1sX0NvbXBvbmVudFwiLCBfQmFzZV9KcWh0bWxfQ29tcG9uZW50XSxcbiAgICBbSnFodG1sX0ludGVncmF0aW9uLCBcIkpxaHRtbF9JbnRlZ3JhdGlvblwiLCBudWxsXVxuXSk7XG5cbiIsIiQoZG9jdW1lbnQpLnJlYWR5KGFzeW5jIGZ1bmN0aW9uKCkge1xudHJ5IHtcbmNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgJ0RvY3VtZW50IHJlYWR5LCBzdGFydGluZyBSc3guX3JzeF9jb3JlX2Jvb3QnKTtcbmF3YWl0IFJzeC5fcnN4X2NvcmVfYm9vdCgpO1xuY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCAnSW5pdGlhbGl6YXRpb24gY29tcGxldGUnKTtcbn0gY2F0Y2ggKGVycm9yKSB7XG5jb25zb2xlLmVycm9yKCdbUlNYX0lOSVRdIEluaXRpYWxpemF0aW9uIGZhaWxlZDonLCBlcnJvcik7XG5jb25zb2xlLmVycm9yKCdbUlNYX0lOSVRdIFN0YWNrOicsIGVycm9yLnN0YWNrKTtcbnRocm93IGVycm9yO1xufVxufSk7Il0sInNvdXJjZVJvb3QiOiIifQ==