/* === 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; } /* === rsx/theme/quill/quill_cdn.js (babel) === */ "use strict"; /** * Quill Editor - Utility Functions * * Provides utility functions for working with Quill editor. */ /** * Ensures Quill is loaded before executing callback * @param {Function} callback - Function to call when Quill is ready */ function quill_ready(callback) { if (typeof window.Quill !== 'undefined') { callback(); } else { setTimeout(() => quill_ready(callback), 50); } } /* === 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_Quill_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_Quill_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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0b3JhZ2UvcnN4LXRtcC9ucG1faW1wb3J0X2RlY2xhcmF0aW9uc185NWE2ZjYwMmM5ODAzNzYxMWI2NDBiMGI1MzQyODMwYi5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kZWNvcmF0b3IuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvYnJvd3Nlci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kYXRldGltZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9lcnJvci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9oYXNoLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL011dGV4LmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2FzeW5jLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2Z1bmN0aW9ucy5qcyIsInJzeC90aGVtZS9xdWlsbC9xdWlsbF9jZG4uanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvTWFuaWZlc3QuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X0JlaGF2aW9ycy5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfQ2FjaGUuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X0luaXQuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X0pzX01vZGVsLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9WaWV3X1RyYW5zaXRpb25zLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JlYWRXcml0ZUxvY2suanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvRm9ybV9VdGlscy5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9EZWJ1Z2dlci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSnFfSGVscGVycy5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3guanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvQWpheC5qcyIsImFwcC9SU3BhZGUvSW50ZWdyYXRpb25zL0pxaHRtbC9KcWh0bWxfQ29tcG9uZW50LmpzIiwiYXBwL1JTcGFkZS9JbnRlZ3JhdGlvbnMvSnFodG1sL0pxaHRtbF9JbnRlZ3JhdGlvbi5qcyIsInN0b3JhZ2UvcnN4LXRtcC9idW5kbGVfUXVpbGxfQnVuZGxlXzU3YjJhMzU2LmpzIiwic3RvcmFnZS9yc3gtdG1wL2J1bmRsZV9RdWlsbF9CdW5kbGVfZTgzZTQzZDMuanMiXSwibmFtZXMiOlsiZGVjb3JhdG9yIiwidmFsdWUiLCJpc19tb2JpbGUiLCJ0ZXN0IiwibmF2aWdhdG9yIiwidXNlckFnZW50IiwiJCIsIndpbmRvdyIsIndpZHRoIiwiaXNfZGVza3RvcCIsImdldF9vcyIsInVzZXJfYWdlbnQiLCJwbGF0Zm9ybSIsIm1hY29zX3BsYXRmb3JtcyIsIndpbmRvd3NfcGxhdGZvcm1zIiwiaW9zX3BsYXRmb3JtcyIsIm9zIiwiaXNfbW9iaWxlX2RldmljZSIsImluZGV4T2YiLCJpc19jcmF3bGVyIiwiYm90X3BhdHRlcm4iLCJzY3JvbGxfaW50b192aWV3X2lmX25lZWRlZCIsInRhcmdldCIsIiR0YXJnZXQiLCIkcGFyZW50IiwicGFyZW50IiwidGFyZ2V0X3RvcCIsInBvc2l0aW9uIiwidG9wIiwic2Nyb2xsVG9wIiwidGFyZ2V0X2hlaWdodCIsIm91dGVySGVpZ2h0IiwicGFyZW50X2hlaWdodCIsImhlaWdodCIsInNjcm9sbF9wb3NpdGlvbiIsIkRlYnVnZ2VyIiwiY29uc29sZV9kZWJ1ZyIsIm5ld19zY3JvbGxfcG9zaXRpb24iLCJNYXRoIiwibWF4IiwibWluIiwic2Nyb2xsSGVpZ2h0Iiwic2Nyb2xsX3BhZ2VfaW50b192aWV3X2lmX25lZWRlZCIsIm9mZnNldCIsIndpbmRvd19oZWlnaHQiLCJ3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uIiwiYW5pbWF0ZSIsIndhaXRfZm9yX2ltYWdlcyIsImNhbGxiYWNrIiwiJGltYWdlcyIsInRvdGFsX2ltYWdlcyIsImxlbmd0aCIsImltYWdlc19sb2FkZWQiLCJlYWNoIiwiaW1nIiwiSW1hZ2UiLCJvbmxvYWQiLCJvbmVycm9yIiwic3JjIiwiJG5ic3AiLCJlc2NhcGVfanFfc2VsZWN0b3IiLCJpZCIsInJlcGxhY2UiLCJ1bml4X3RpbWUiLCJyb3VuZCIsIkRhdGUiLCJnZXRUaW1lIiwieW1kaGlzX3RvX3VuaXgiLCJzdHJfZGF0ZSIsImRhdGUiLCJlcnJvciIsInN0ciIsImVycm9yX2NvZGUiLCJ1bmRlZiIsInN0YXR1cyIsInNob3VsZG50X2hhcHBlbiIsIm1lc3NhZ2UiLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJFcnJvciIsInN0YWNrIiwic3RhY2tMaW5lcyIsInNwbGl0IiwiY2FsbGVySW5mbyIsImNhbGxlckxpbmUiLCJtYXRjaCIsImVycm9yTWVzc2FnZSIsImNvbnNvbGUiLCJyZXBlYXQiLCJmYXRhbEVycm9yIiwibmFtZSIsImhhc2giLCJ0aGVfdmFyIiwiY2FsY19zaGExIiwiaWdub3JlZF9rZXlzIiwianNvbl9zdHJpbmdpZnlfbm9jaXJjIiwiY2FjaGUiLCJKU09OIiwic3RyaW5naWZ5Iiwia2V5IiwidiIsIl9jYWNoZV9rZXkiLCJfaGFzaF9rZXkiLCJwdXNoIiwiZmxhdF92YXIiLCJfZmxhdHRlbiIsInByZWZpeCIsImRlcHRoIiwiaXNfb2JqZWN0IiwiQWJzdHJhY3QiLCJrIiwiaGFzT3duUHJvcGVydHkiLCJpc19hcnJheSIsImkiLCJmb3JlYWNoIiwiaXNfZnVuY3Rpb24iLCJpc19udW1lcmljIiwiU3RyaW5nIiwic29ydGVyIiwic29ydCIsImEiLCJiIiwianNvbiIsImhhc2hlZCIsInNoYTEiLCJkZWVwX2VxdWFsIiwibXV0ZXgiLCJnbG9iYWxfaWQiLCJpbnN0YW5jZV9tdXRleGVzIiwiX2luc3RhbmNlX3N0b3JhZ2UiLCJXZWFrTWFwIiwiZ2xvYmFsX211dGV4ZXMiLCJfZ2xvYmFsX3N0b3JhZ2UiLCJNYXAiLCJnZXRfaW5zdGFuY2VfbXV0ZXgiLCJpbnN0YW5jZSIsIm1ldGhvZF9uYW1lIiwiaW5zdGFuY2VfbG9ja3MiLCJnZXQiLCJzZXQiLCJsb2NrX3N0YXRlIiwiYWN0aXZlIiwicXVldWUiLCJnZXRfZ2xvYmFsX211dGV4Iiwic2NoZWR1bGVfbmV4dCIsImZuIiwicmVzb2x2ZSIsInJlamVjdCIsInNoaWZ0IiwiUHJvbWlzZSIsInRoZW4iLCJmaW5hbGx5IiwiYWNxdWlyZV9sb2NrIiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsX21ldGhvZCIsIl9sZW4iLCJhcmdzIiwiQXJyYXkiLCJfa2V5IiwiYXBwbHkiLCJfbGVuMiIsIl9rZXkyIiwic2xlZXAiLCJtaWxsaXNlY29uZHMiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJzZXRUaW1lb3V0IiwiZGVib3VuY2UiLCJjYWxsYmFja19vcl9kZWxheSIsImRlbGF5IiwiaW1tZWRpYXRlIiwiZGVjb3JhdG9yX2RlbGF5IiwiZGVjb3JhdG9yX2ltbWVkaWF0ZSIsImNvbnRleHQiLCJraW5kIiwiZGVib3VuY2VfaW1wbCIsInJ1bm5pbmciLCJxdWV1ZWQiLCJsYXN0X2VuZF90aW1lIiwidGltZXIiLCJuZXh0X2FyZ3MiLCJuZXh0X2NvbnRleHQiLCJyZXNvbHZlX3F1ZXVlIiwicmVqZWN0X3F1ZXVlIiwicnVuX2Z1bmN0aW9uIiwidGhlc2VfcmVzb2x2ZXMiLCJ0aGVzZV9yZWplY3RzIiwicmVzdWx0IiwiZXJyIiwibm93IiwiY2xlYXJUaW1lb3V0IiwiZmlyc3RfY2FsbCIsInNpbmNlIiwiSW5maW5pdHkiLCJ3YWl0Iiwicndsb2NrIiwiY2IiLCJSZWFkV3JpdGVMb2NrIiwiYWNxdWlyZSIsInJ3bG9ja19yZWFkIiwiYWNxdWlyZV9yZWFkIiwicndsb2NrX2ZvcmNlX3VubG9jayIsImZvcmNlX3VubG9jayIsInJ3bG9ja19wZW5kaW5nIiwicGVuZGluZyIsIm9iaiIsInJlc3VsdHMiLCJpc0FycmF5IiwiZm9yRWFjaCIsImluZGV4IiwicHJvbWlzZXMiLCJmaWx0ZXIiLCJhbGwiLCJuIiwiaXNOYU4iLCJwYXJzZUZsb2F0IiwiaXNGaW5pdGUiLCJpc19zdHJpbmciLCJzIiwiaXNfaW50ZWdlciIsIk51bWJlciIsImlzSW50ZWdlciIsImlzX3Byb21pc2UiLCJmdW5jdGlvbl90b19jaGVjayIsInRvU3RyaW5nIiwiY2FsbCIsImlzX2VtYWlsIiwiZW1haWwiLCJyZWdleCIsImlzc2V0IiwiZW1wdHkiLCJvYmplY3QiLCJmbG9hdCIsInZhbCIsInBhcnNlZCIsImludCIsInBhcnNlSW50IiwidmFsdWVfdW5sZXNzX251bWVyaWNfc3RyaW5nX3RoZW5fbnVtZXJpY192YWx1ZSIsImh0bWwiLCJfIiwiZXNjYXBlIiwibmwyYnIiLCJodG1sYnIiLCJ1cmxlbmNvZGUiLCJlbmNvZGVVUklDb21wb25lbnQiLCJ1cmxkZWNvZGUiLCJkZWNvZGVVUklDb21wb25lbnQiLCJqc29uX2VuY29kZSIsImpzb25fZGVjb2RlIiwicGFyc2UiLCJjaGFubmVsIiwidmFsdWVzIiwicmVwbGFjZV9hbGwiLCJzdHJpbmciLCJzZWFyY2giLCJqb2luIiwidWN3b3JkcyIsImlucHV0IiwibWFwIiwid29yZCIsImNoYXJBdCIsInRvVXBwZXJDYXNlIiwic2xpY2UiLCJjb3VudCIsIm8iLCJjIiwiY2xvbmUiLCJGdW5jdGlvbiIsInByb3RvdHlwZSIsIl9fY2xvbmUiLCJ0aGF0IiwidGVtcCIsImNsb25lZCIsImNvbnN0cnVjdG9yIiwiT2JqZWN0IiwiYXNzaWduIiwiY29hbGVzY2UiLCJmcm9tIiwicmV0dXJuX3ZhbCIsImFyZyIsImNzdl90b19hcnJheV90cmltIiwic3RyX2NzdiIsInBhcnRzIiwicmV0IiwicGFydCIsInRyaW0iLCJxdWlsbF9yZWFkeSIsIlF1aWxsIiwiTWFuaWZlc3QiLCJfZGVmaW5lIiwiaXRlbXMiLCJfY2xhc3NlcyIsIml0ZW0iLCJjbGFzc19vYmplY3QiLCJjbGFzc19uYW1lIiwiY2xhc3NfZXh0ZW5kcyIsImRlY29yYXRvcnMiLCJjbGFzcyIsImV4dGVuZHMiLCJfbmFtZSIsIl9leHRlbmRzIiwiX2RlY29yYXRvcnMiLCJfYnVpbGRfc3ViY2xhc3NfaW5kZXgiLCJfc3ViY2xhc3NfaW5kZXgiLCJjbGFzc2RhdGEiLCJjdXJyZW50X2NsYXNzX25hbWUiLCJjdXJyZW50X2NsYXNzZGF0YSIsImV4dGVuZHNfbmFtZSIsImluY2x1ZGVzIiwiZ2V0X2V4dGVuZGluZyIsImJhc2VfY2xhc3MiLCJiYXNlX2NsYXNzX29iamVjdCIsImdldF9jbGFzc19ieV9uYW1lIiwiY2xhc3NlcyIsImpzX2lzX3N1YmNsYXNzX29mIiwibG9jYWxlQ29tcGFyZSIsInN1YmNsYXNzIiwic3VwZXJjbGFzcyIsInN1YmNsYXNzX29iamVjdCIsInN1cGVyY2xhc3Nfb2JqZWN0IiwiY3VycmVudF9jbGFzcyIsImdldF9hbGxfY2xhc3NlcyIsImJ1aWxkX2tleSIsInJzeGFwcCIsImdldF9kZWNvcmF0b3JzIiwiY2xhc3NfaW5mbyIsIl90cmFuc2Zvcm1fZGVjb3JhdG9ycyIsImdldF9hbGxfZGVjb3JhdG9ycyIsImNvbXBhY3RfZGVjb3JhdG9ycyIsImhhc19kZWNvcmF0b3IiLCJkZWNvcmF0b3JfbmFtZSIsInNvbWUiLCJkIiwianNfZ2V0X3N1YmNsYXNzZXNfb2YiLCJiYXNlX2NsYXNzX25hbWUiLCJzdWJjbGFzc19uYW1lcyIsInN1YmNsYXNzX29iamVjdHMiLCJzdWJjbGFzc19uYW1lIiwibmFtZV9hIiwibmFtZV9iIiwiUnN4X0JlaGF2aW9ycyIsIl9vbl9mcmFtZXdvcmtfY29yZV9pbml0IiwiX2luaXRfaWdub3JlX2ludmFsaWRfYW5jaG9yX2xpbmtzIiwiX3RyaW1fY29waWVkX3RleHQiLCJkb2N1bWVudCIsIm9uIiwiZSIsIiRsaW5rIiwiaHJlZiIsImF0dHIiLCJpc0RlZmF1bHRQcmV2ZW50ZWQiLCJkYXRhIiwicHJldmVudERlZmF1bHQiLCJzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24iLCJzdGFydHNXaXRoIiwidGFyZ2V0SWQiLCJzdWJzdHJpbmciLCJ0YXJnZXRFeGlzdHMiLCJnZXRFbGVtZW50QnlJZCIsInF1ZXJ5U2VsZWN0b3IiLCJhZGRFdmVudExpc3RlbmVyIiwiZXZlbnQiLCJzaGlmdEtleSIsInNlbGVjdGlvbiIsImdldFNlbGVjdGlvbiIsInNlbGVjdGVkX3RleHQiLCJjb250YWluZXIiLCJnZXRSYW5nZUF0IiwiY29tbW9uQW5jZXN0b3JDb250YWluZXIiLCJub2RlVHlwZSIsInBhcmVudE5vZGUiLCJjbG9zZXN0IiwidHJpbW1lZF90ZXh0IiwiY2xpcGJvYXJkRGF0YSIsInNldERhdGEiLCJsb2ciLCJSc3hfQ2FjaGUiLCJvbl9jb3JlX2RlZmluZSIsIkNvcmVfQ2FjaGUiLCJfY2FjaGVzIiwiZ2xvYmFsIiwiX2NhY2hlc19zZXQiLCJnZXRfaW5zdGFuY2UiLCJNYWluIiwiZGVidWciLCJrZXlfZW5jb2RlZCIsIl9lbmNvZGVrZXkiLCJnZXRfZ2xvYmFsIiwiZ2V0X3Nlc3Npb24iLCJfc3VwcG9ydHNTdG9yYWdlIiwicnMiLCJzZXNzaW9uU3RvcmFnZSIsImdldEl0ZW0iLCJzZXRfc2Vzc2lvbiIsIl90cnlhZ2FpbiIsInJlbW92ZUl0ZW0iLCJzZXRJdGVtIiwiX2lzT3V0T2ZTcGFjZSIsImNsZWFyIiwiX3Jlc2V0IiwiX19zdXBwb3J0c1N0b3JhZ2UiLCJleCIsIlJzeF9Jbml0IiwiUnN4IiwiaXNfcHJvZCIsIl9fZW52aXJvbm1lbnRfY2hlY2tzIiwic2NyaXB0cyIsImdldEVsZW1lbnRzQnlUYWdOYW1lIiwic2NyaXB0IiwiZGVmZXIiLCJyZWFzb24iLCJfcnN4X2NvcmVfYm9vdF9zdG9wIiwiUnN4X0pzX01vZGVsIiwiX19NT0RFTCIsIm1vZGVsRGF0YSIsImZldGNoIiwiQ3VycmVudENsYXNzIiwibW9kZWxOYW1lIiwicmVzcG9uc2UiLCJhamF4IiwidXJsIiwibWV0aG9kIiwiZGF0YVR5cGUiLCJfaW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZSIsImdldE1vZGVsTmFtZSIsInJlZnJlc2giLCJmcmVzaCIsInRvT2JqZWN0IiwidG9KU09OIiwiTW9kZWxDbGFzcyIsIlJzeF9WaWV3X1RyYW5zaXRpb25zIiwic3RhcnRWaWV3VHJhbnNpdGlvbiIsIl9pbmplY3RfdHJhbnNpdGlvbl9jc3MiLCJzdHlsZSIsImNyZWF0ZUVsZW1lbnQiLCJ0ZXh0Q29udGVudCIsImhlYWQiLCJhcHBlbmRDaGlsZCIsIl81MGFlNjA5ZV9hc3NlcnRDbGFzc0JyYW5kIiwiXzUwYWU2MDllX2dldF9sb2NrIiwid3JpdGVyX3EiLCJfNTBhZTYwOWVfc2NoZWR1bGUiLCJ3cml0ZXJfYWN0aXZlIiwicmVhZGVyX3EiLCJyZWFkZXJzIiwiX2xvY2tzIiwiZGVsZXRlIiwiXzUwYWU2MDllX1JlYWRXcml0ZUxvY2siLCJiYXRjaCIsInNwbGljZSIsIkZvcm1fVXRpbHMiLCJfb25fZnJhbWV3b3JrX2NvcmVfZGVmaW5lIiwicGFyYW1zIiwiYWpheF9zdWJtaXQiLCJvcHRpb25zIiwiJGVsZW1lbnQiLCJpcyIsImNvbnRyb2xsZXIiLCJhY3Rpb24iLCJBamF4IiwiYWpheF91cmxfdG9fY29udHJvbGxlcl9hY3Rpb24iLCJhcHBseV9mb3JtX2Vycm9ycyIsInBhcmVudF9zZWxlY3RvciIsImVycm9ycyIsInJlc2V0X2Zvcm1fZXJyb3JzIiwibm9ybWFsaXplZCIsIl9ub3JtYWxpemVfZXJyb3JzIiwiYW5pbWF0aW9ucyIsInR5cGUiLCJfYXBwbHlfZ2VuZXJhbF9lcnJvcnMiLCJkZWR1cGxpY2F0ZWQiLCJfZGVkdXBsaWNhdGVfZXJyb3JzIiwiX2FwcGx5X2ZpZWxkX2Vycm9ycyIsIm1hdGNoZWRfY291bnQiLCJrZXlzIiwidW5tYXRjaGVkIiwidW5tYXRjaGVkX2RlZHVwbGljYXRlZCIsInVubWF0Y2hlZF9jb3VudCIsInN1bW1hcnlfbXNnIiwic3VtbWFyeV9hbmltYXRpb25zIiwiX2FwcGx5X2NvbWJpbmVkX2Vycm9yIiwiJGVycm9yX2NvbnRhaW5lciIsImZpbmQiLCJmaXJzdCIsImNvbnRhaW5lcl90b3AiLCJmaXhlZF9oZWFkZXJfaGVpZ2h0IiwiX2dldF9maXhlZF9oZWFkZXJfaGVpZ2h0IiwidGFyZ2V0X3Njcm9sbCIsInJlc2V0IiwiZm9ybV9zZWxlY3RvciIsIiRmb3JtIiwidHJpZ2dlciIsInNlcmlhbGl6ZSIsInNlcmlhbGl6ZUFycmF5IiwiZm9ybV9kYXRhIiwib25fc3VjY2VzcyIsImRldGFpbHMiLCJvbl9lcnJvciIsInJlbW92ZSIsInJlbW92ZUNsYXNzIiwiZXZlcnkiLCJ1bndyYXBwZWQiLCJmaWVsZCIsIlNldCIsInNlZW4iLCJoYXMiLCJhZGQiLCJmaWVsZF9lcnJvcnMiLCJmaWVsZF9uYW1lIiwiZXJyb3JfbWVzc2FnZSIsIiRpbnB1dCIsIiRlcnJvciIsImFkZENsYXNzIiwiYXBwZW5kVG8iLCJoaWRlIiwiZmFkZUluIiwicHJvbWlzZSIsInVubWF0Y2hlZF9lcnJvcnMiLCIkYWxlcnQiLCJ0ZXh0IiwiJGxpc3QiLCJlcnJvcl9tc2ciLCJwcmVwZW5kVG8iLCJtZXNzYWdlcyIsIm1zZyIsImVycm9yX2xpc3QiLCJ0b3RhbF9oZWlnaHQiLCIkZWwiLCJjc3MiLCJvdXRlcldpZHRoIiwidmlld3BvcnRfd2lkdGgiLCJsb2dfYnJvd3Nlcl9lcnJvcnMiLCJfaGFuZGxlX2Jyb3dzZXJfZXJyb3IiLCJmaWxlbmFtZSIsImxpbmVubyIsImNvbG5vIiwib25fcmVmcmVzaCIsImVuYWJsZWQiLCJjb25maWciLCJmaWx0ZXJfbW9kZSIsInNwZWNpZmljIiwic3BlY2lmaWNfY2hhbm5lbCIsImNoYW5uZWxzIiwid2hpdGVsaXN0IiwiZmlsdGVyX2NoYW5uZWxzIiwiYmxhY2tsaXN0IiwidGltZXN0YW1wIiwidG9JU09TdHJpbmciLCJpbmNsdWRlX2xvY2F0aW9uIiwiaW5jbHVkZV9iYWNrdHJhY2UiLCJsb2NhdGlvbiIsImJhY2t0cmFjZSIsImxpbmUiLCJvdXRwdXRzIiwiYnJvd3NlciIsImluY2x1ZGVfYmVuY2htYXJrIiwiX2dldF90aW1lX3ByZWZpeCIsImNoYW5uZWxQcmVmaXgiLCJjb25zb2xlTWV0aG9kIiwibGFyYXZlbF9sb2ciLCJfYmF0Y2hfY29uc29sZV9tZXNzYWdlIiwibG9nX2Vycm9yIiwiZXJyb3JEYXRhIiwiX2Vycm9yX2NvdW50IiwiTUFYX0VSUk9SU19QRVJfUEFHRSIsIl9lcnJvcl9iYXRjaF9jb3VudCIsIk1BWF9FUlJPUl9CQVRDSEVTIiwiX2Vycm9yX2JhdGNoIiwiX2Vycm9yX3RpbWVyIiwiX2ZsdXNoX2Vycm9yX2JhdGNoIiwiREVCT1VOQ0VfTVMiLCJfY29uc29sZV9iYXRjaCIsIl9jb25zb2xlX3RpbWVyIiwiX2ZsdXNoX2NvbnNvbGVfYmF0Y2giLCJSb3V0ZSIsIl9zdGFydF90aW1lIiwiZWxhcHNlZCIsInRvRml4ZWQiLCJfMjdlMGU5ODZfZGVmaW5lUHJvcGVydHkiLCJSc3hfSnFfSGVscGVycyIsImV4aXN0cyIsImlzX3Zpc2libGUiLCJzY3JvbGxfdXBfdG8iLCJzcGVlZCIsImlzX2luX2RvbSIsImVfdG9wIiwic190b3AiLCJleHByIiwiZm9jdXMiLCJlbGVtIiwiYWN0aXZlRWxlbWVudCIsIl9jbGlja19uYXRpdmUiLCJjbGljayIsImhhbmRsZXIiLCJvcmlnaW5hbF9wcmV2ZW50RGVmYXVsdCIsImJpbmQiLCJ3YXJuIiwiY2xpY2tfYWxsb3dfZGVmYXVsdCIsIl9hbmNlc3RvciIsIkhUTUxvYmoiLCJwYXJlbnRFbGVtZW50IiwiZG9jdW1lbnRFbGVtZW50IiwiaXNfaW5fdmlld3BvcnQiLCJzY3JvbGx0b3AiLCJ0b3Bfb2ZfZWxlbWVudCIsImJvdHRvbV9vZl9lbGVtZW50IiwiYm90dG9tX29mX3NjcmVlbiIsImlubmVySGVpZ2h0IiwidG9wX29mX3NjcmVlbiIsInRhZ25hbWUiLCJwcm9wIiwidG9Mb3dlckNhc2UiLCJpc19leHRlcm5hbCIsImhvc3QiLCJsaW5rIiwiaG9zdG5hbWUiLCJjaGVja1ZhbGlkaXR5IiwicmVwb3J0VmFsaWRpdHkiLCJyZXF1ZXN0U3VibWl0IiwiY2xvc2VzdF9zaWJsaW5nIiwic2VsZWN0b3IiLCIkY3VycmVudCIsIiRmb3VuZCIsIm5hdGl2ZV9hamF4Iiwic2V0dGluZ3MiLCJyZXF1ZXN0X3VybCIsImlzX3JlbGF0aXZlIiwiaXNfc2FtZV9kb21haW4iLCJvcmlnaW4iLCJpc19sb2NhbF9yZXF1ZXN0IiwiX19sb2NhbF9pbnRlZ3JhdGlvbiIsImlzX2ZpbGVfdXBsb2FkIiwiZW5kc1dpdGgiLCJjb250cm9sbGVyX25hbWUiLCJhY3Rpb25fbmFtZSIsInVybF9tYXRjaCIsIl9pbml0X2V2ZW50cyIsIl9ldmVudF9oYW5kbGVycyIsIl90cmlnZ2VyZWRfZXZlbnRzIiwidHJpZ2dlcl9yZWZyZXNoIiwiQ29yZV9Mb2ciLCJpc19kZXYiLCJ1aWQiLCJfdWlkIiwiX2RlZmluZV9yb3V0ZXMiLCJyb3V0ZXMiLCJfcm91dGVzIiwicGFyYW1zX29iaiIsInBhdHRlcm4iLCJfZ2VuZXJhdGVfdXJsX2Zyb21fcGF0dGVybiIsInJlcXVpcmVkX3BhcmFtcyIsIm1hdGNoZXMiLCJtaXNzaW5nIiwicmVxdWlyZWQiLCJ1c2VkX3BhcmFtcyIsInBhcmFtX25hbWUiLCJlbmNvZGVkX3ZhbHVlIiwicXVlcnlfcGFyYW1zIiwicXVlcnlfc3RyaW5nIiwiZW50cmllcyIsIl9yZWYiLCJfcnN4X2NhbGxfYWxsX2NsYXNzZXMiLCJhbGxfY2xhc3NlcyIsImNsYXNzZXNfd2l0aF9tZXRob2QiLCJwcm9taXNlX3BpbGUiLCJyZXR1cm5fdmFsdWUiLCJfX3N0b3BwZWQiLCJfcnN4X2NvcmVfYm9vdCIsIl9fYm9vdGVkIiwicGhhc2VzIiwicGhhc2UiLCJfcGFyc2VfaGFzaCIsImhhc2hfc3RyaW5nIiwicGFpcnMiLCJwYWlyIiwiX3NlcmlhbGl6ZV9oYXNoIiwiZ2V0X2FsbF9wYWdlX3N0YXRlIiwiZ2V0X3BhZ2Vfc3RhdGUiLCJfc3RhdGUka2V5Iiwic3RhdGUiLCJzZXRfcGFnZV9zdGF0ZSIsIm5ld19oYXNoIiwicGF0aG5hbWUiLCJoaXN0b3J5IiwicmVwbGFjZVN0YXRlIiwic2V0X2FsbF9wYWdlX3N0YXRlIiwibmV3X3N0YXRlIiwicmVuZGVyX2Vycm9yIiwiJGNvbnRhaW5lciIsImZpbGUiLCJfZXNjYXBlX2h0bWwiLCJkaXYiLCJpbm5lckhUTUwiLCJfZTgyMTFmNWJfZGVmaW5lUHJvcGVydHkiLCJfcGVuZGluZ19jYWxscyIsIl9mbHVzaF90aW1lb3V0IiwiX2NhbGxfY291bnRlciIsIk1BWF9CQVRDSF9TSVpFIiwiX3RyYWNrZWRfcHJvbWlzZXMiLCJXZWFrU2V0IiwiTW9kYWwiLCJwYXRoIiwiYWpheF9kaXNhYmxlX2JhdGNoaW5nIiwiX2NhbGxfZGlyZWN0IiwiX2NhbGxfYmF0Y2giLCJjYWxsX2tleSIsIl9nZW5lcmF0ZV9jYWxsX2tleSIsImV4aXN0aW5nX2NhbGwiLCJpc19jb21wbGV0ZSIsImlzX2Vycm9yIiwiY2FsbGJhY2tzIiwiY2FsbF9pZCIsInBlbmRpbmdfY2FsbCIsInBlbmRpbmdfY291bnQiLCJfZmx1c2hfcGVuZGluZ19jYWxscyIsInN1Y2Nlc3MiLCJfc3VjY2VzcyIsInByb2Nlc3NlZF92YWx1ZSIsIl9hamF4X3JldHVybl92YWx1ZSIsImVycm9yX3R5cGUiLCJmYXRhbF9lcnJvcl9kYXRhIiwiZmF0YWxfZXJyb3IiLCJlbmRwb2ludCIsImF1dGhfZXJyb3IiLCJ1bmF1dGhfZXJyb3IiLCJmb3JtX2Vycm9yIiwiZ2VuZXJpY19lcnJvciIsInhociIsIl9leHRyYWN0X2Vycm9yX21lc3NhZ2UiLCJuZXR3b3JrX2Vycm9yIiwic3RhdHVzVGV4dCIsImNhbGxzX3RvX3NlbmQiLCJjYWxsX21hcCIsImJhdGNoX2NhbGxzIiwicmVzcG9uc2Vfa2V5IiwiY2FsbF9yZXNwb25zZSIsImVycm9yX2RldGFpbHMiLCJfcmVmMiIsInhocl9lcnJvciIsIl9yZWYzIiwic29ydGVkX3BhcmFtcyIsInJlc3BvbnNlSlNPTiIsInJlc3BvbnNlVGV4dCIsIkpxaHRtbF9Db21wb25lbnQiLCJfQmFzZV9KcWh0bWxfQ29tcG9uZW50IiwiSnFodG1sX0ludGVncmF0aW9uIiwiX29uX2ZyYW1ld29ya19tb2R1bGVzX2RlZmluZSIsImpxaHRtbF9jb21wb25lbnRzIiwiY29tcG9uZW50IiwianFodG1sIiwicmVnaXN0ZXJfY29tcG9uZW50IiwiX29uX2ZyYW1ld29ya19tb2R1bGVzX2luaXQiLCIkc2NvcGUiLCJpc190b3BfbGV2ZWwiLCJjb21wb25lbnRzX25lZWRpbmdfaW5pdCIsImNvbnRhaW5zIiwiY2xhc3NMaXN0IiwiY29tcG9uZW50X25hbWUiLCJjb21wb25lbnRfYXJncyIsImFyZ3Nfc3RyaW5nIiwicmVtb3ZlQXR0ciIsInJlbW92ZURhdGEiLCJjb21wb25lbnRfYXJnc19maWx0ZXJlZCIsIl9pbm5lcl9odG1sIiwiY29tcG9uZW50X3Byb21pc2UiLCJuZXN0ZWRfcHJvbWlzZXMiLCJnZXRfY29tcG9uZW50X25hbWVzIiwiaGFzX2NvbXBvbmVudCJdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQSxTQUFTQSxDQUFDQyxLQUFLLEVBQUU7RUFDdEIsT0FBT0EsS0FBSztBQUNoQjs7Ozs7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsU0FBU0EsQ0FBQSxFQUFHO0VBQ2pCLElBQUksZ0VBQWdFLENBQUNDLElBQUksQ0FBQ0MsU0FBUyxDQUFDQyxTQUFTLENBQUMsRUFBRTtJQUM1RixPQUFPLElBQUk7RUFDZixDQUFDLE1BQU0sSUFBSUMsQ0FBQyxDQUFDQyxNQUFNLENBQUMsQ0FBQ0MsS0FBSyxDQUFDLENBQUMsR0FBRyxHQUFHLEVBQUU7SUFDaEM7SUFDQSxPQUFPLElBQUk7RUFDZixDQUFDLE1BQU07SUFDSCxPQUFPLEtBQUs7RUFDaEI7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNDLFVBQVVBLENBQUEsRUFBRztFQUNsQixPQUFPLENBQUNQLFNBQVMsQ0FBQyxDQUFDO0FBQ3ZCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU1EsTUFBTUEsQ0FBQSxFQUFHO0VBQ2QsSUFBSUMsVUFB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRyIsImZpbGUiOiJidW5kbGVfb3V0cHV0X1F1aWxsX0J1bmRsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8vIE5QTSBJbXBvcnQgRGVjbGFyYXRpb25zIGZvciBBcHAgQnVuZGxlXG4vLyBBdXRvLWdlbmVyYXRlZCB0byBwcm92aWRlIE5QTSBtb2R1bGVzIHRvIGFwcCBidW5kbGUgc2NvcGVcbi8vIENhY2hlIGtleTogOTVhNmY2MDJjOTgwMzc2MTFiNjQwYjBiNTM0MjgzMGJcblxuY29uc3QganFodG1sID0gd2luZG93Ll9yc3hfbnBtLmpxaHRtbDtcbmlmICghanFodG1sKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnUlNYIEZyYW1ld29yayBFcnJvcjogTlBNIG1vZHVsZSBcImpxaHRtbFwiIG5vdCBmb3VuZC5cXG4nICtcbiAgICAgICAgJ0V4cGVjdGVkIHdpbmRvdy5fcnN4X25wbS5qcWh0bWwgdG8gYmUgZGVmaW5lZCBieSB0aGUgdmVuZG9yIGJ1bmRsZS4nXG4gICAgKTtcbn1cblxuY29uc3QgX0Jhc2VfSnFodG1sX0NvbXBvbmVudCA9IHdpbmRvdy5fcnN4X25wbS5fQmFzZV9KcWh0bWxfQ29tcG9uZW50O1xuaWYgKCFfQmFzZV9KcWh0bWxfQ29tcG9uZW50KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnUlNYIEZyYW1ld29yayBFcnJvcjogTlBNIG1vZHVsZSBcIl9CYXNlX0pxaHRtbF9Db21wb25lbnRcIiBub3QgZm91bmQuXFxuJyArXG4gICAgICAgICdFeHBlY3RlZCB3aW5kb3cuX3JzeF9ucG0uX0Jhc2VfSnFodG1sX0NvbXBvbmVudCB0byBiZSBkZWZpbmVkIGJ5IHRoZSB2ZW5kb3IgYnVuZGxlLidcbiAgICApO1xufVxuXG4vLyBDbGVhbiB1cCBOUE0gY29udGFpbmVyIHRvIHByZXZlbnQgY29uc29sZSBhY2Nlc3NcbmRlbGV0ZSB3aW5kb3cuX3JzeF9ucG07XG4iLCIvKipcbiAqIERlY29yYXRvciBmdW5jdGlvbiB0aGF0IG1hcmtzIGEgZnVuY3Rpb24gYXMgYSBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb24uXG4gKlxuICogV2hlbiBhIGZ1bmN0aW9uIGhhcyBAZGVjb3JhdG9yIGluIGl0cyBKU0RvYyBjb21tZW50LCBpdCB3aGl0ZWxpc3RzIHRoYXQgZnVuY3Rpb25cbiAqIHRvIGJlIHVzZWQgYXMgYSBkZWNvcmF0b3Igb24gb3RoZXIgbWV0aG9kcyB0aHJvdWdob3V0IHRoZSBjb2RlYmFzZS5cbiAqXG4gKiBUaGUgZnVuY3Rpb24gaXRzZWxmIHBlcmZvcm1zIG5vIG9wZXJhdGlvbiAtIGl0IHNpbXBseSByZXR1cm5zIGl0cyBpbnB1dCB1bmNoYW5nZWQuXG4gKiBJdHMgcHVycG9zZSBpcyBwdXJlbHkgYXMgYSBtYXJrZXIgZm9yIHRoZSBtYW5pZmVzdCB2YWxpZGF0aW9uIHN5c3RlbS5cbiAqXG4gKiBVc2FnZTpcbiAqICAgLy8gLyoqXG4gKiAgIC8vICAqIE15IGN1c3RvbSBkZWNvcmF0b3IgaW1wbGVtZW50YXRpb25cbiAqICAgLy8gICogQGRlY29yYXRvclxuICogICAvLyAgKlxcL1xuICogICBmdW5jdGlvbiBteV9jdXN0b21fZGVjb3JhdG9yKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKSB7XG4gKiAgICAgICAvLyBEZWNvcmF0b3IgaW1wbGVtZW50YXRpb25cbiAqICAgfVxuICpcbiAqIFRoaXMgYWxsb3dzIG15X2N1c3RvbV9kZWNvcmF0b3IgdG8gYmUgdXNlZCBhcyBAbXlfY3VzdG9tX2RlY29yYXRvciBvbiBzdGF0aWMgbWV0aG9kcy5cbiAqXG4gKiBUT0RPOiBUaGlzIGlzIHByb2JhYmx5IG5vIGxvbmdlciBuZWNlc3Nhcnk/IG1heWJlP1xuICovXG5mdW5jdGlvbiBkZWNvcmF0b3IodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG59XG4iLCIvKlxuICogQnJvd3NlciBhbmQgRE9NIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgYnJvd3NlciBkZXRlY3Rpb24sIHZpZXdwb3J0IHV0aWxpdGllcywgYW5kIERPTSBtYW5pcHVsYXRpb24uXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQlJPV1NFUiBERVRFQ1RJT05cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHVzZXIgaXMgb24gYSBtb2JpbGUgZGV2aWNlIG9yIHVzaW5nIG1vYmlsZSB2aWV3cG9ydFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgbW9iaWxlIGRldmljZSBvciB2aWV3cG9ydCA8IDk5MnB4XG4gKiBAdG9kbyBJbXByb3ZlIHVzZXIgYWdlbnQgZGV0ZWN0aW9uIGZvciBhbGwgbW9iaWxlIGRldmljZXNcbiAqL1xuZnVuY3Rpb24gaXNfbW9iaWxlKCkge1xuICAgIGlmICgvQW5kcm9pZHx3ZWJPU3xpUGhvbmV8aVBhZHxpUG9kfEJsYWNrQmVycnl8SUVNb2JpbGV8T3BlcmEgTWluaS9pLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmICgkKHdpbmRvdykud2lkdGgoKSA8IDk5Mikge1xuICAgICAgICAvLyA5OTJweCA9IGJvb3RzdHJhcCA0IGNvbC1tZC1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHVzZXIgaXMgb24gZGVza3RvcCAobm90IG1vYmlsZSlcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG5vdCBtb2JpbGUgZGV2aWNlL3ZpZXdwb3J0XG4gKi9cbmZ1bmN0aW9uIGlzX2Rlc2t0b3AoKSB7XG4gICAgcmV0dXJuICFpc19tb2JpbGUoKTtcbn1cblxuLyoqXG4gKiBEZXRlY3RzIHRoZSB1c2VyJ3Mgb3BlcmF0aW5nIHN5c3RlbVxuICogQHJldHVybnMge3N0cmluZ30gT1MgbmFtZTogJ01hYyBPUycsICdpUGhvbmUnLCAnaVBhZCcsICdXaW5kb3dzJywgJ0FuZHJvaWQtUGhvbmUnLCAnQW5kcm9pZC1UYWJsZXQnLCAnTGludXgnLCBvciAnVW5rbm93bidcbiAqL1xuZnVuY3Rpb24gZ2V0X29zKCkge1xuICAgIGxldCB1c2VyX2FnZW50ID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQsXG4gICAgICAgIHBsYXRmb3JtID0gd2luZG93Lm5hdmlnYXRvci5wbGF0Zm9ybSxcbiAgICAgICAgbWFjb3NfcGxhdGZvcm1zID0gWydNYWNpbnRvc2gnLCAnTWFjSW50ZWwnLCAnTWFjUFBDJywgJ01hYzY4SyddLFxuICAgICAgICB3aW5kb3dzX3BsYXRmb3JtcyA9IFsnV2luMzInLCAnV2luNjQnLCAnV2luZG93cycsICdXaW5DRSddLFxuICAgICAgICBpb3NfcGxhdGZvcm1zID0gWydpUGhvbmUnLCAnaVBhZCcsICdpUG9kJ10sXG4gICAgICAgIG9zID0gbnVsbDtcblxuICAgIGxldCBpc19tb2JpbGVfZGV2aWNlID0gaXNfbW9iaWxlKCk7XG5cbiAgICBpZiAobWFjb3NfcGxhdGZvcm1zLmluZGV4T2YocGxhdGZvcm0pICE9PSAtMSkge1xuICAgICAgICBvcyA9ICdNYWMgT1MnO1xuICAgIH0gZWxzZSBpZiAoaW9zX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEgJiYgaXNfbW9iaWxlX2RldmljZSkge1xuICAgICAgICBvcyA9ICdpUGhvbmUnO1xuICAgIH0gZWxzZSBpZiAoaW9zX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEgJiYgIWlzX21vYmlsZV9kZXZpY2UpIHtcbiAgICAgICAgb3MgPSAnaVBhZCc7XG4gICAgfSBlbHNlIGlmICh3aW5kb3dzX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEpIHtcbiAgICAgICAgb3MgPSAnV2luZG93cyc7XG4gICAgfSBlbHNlIGlmICgvQW5kcm9pZC8udGVzdCh1c2VyX2FnZW50KSAmJiBpc19tb2JpbGVfZGV2aWNlKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQtUGhvbmUnO1xuICAgIH0gZWxzZSBpZiAoL0FuZHJvaWQvLnRlc3QodXNlcl9hZ2VudCkgJiYgIWlzX21vYmlsZV9kZXZpY2UpIHtcbiAgICAgICAgb3MgPSAnQW5kcm9pZC1UYWJsZXQnO1xuICAgIH0gZWxzZSBpZiAoIW9zICYmIC9MaW51eC8udGVzdChwbGF0Zm9ybSkpIHtcbiAgICAgICAgb3MgPSAnTGludXgnO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG9zID0gJ1Vua25vd24nO1xuICAgIH1cblxuICAgIHJldHVybiBvcztcbn1cblxuLyoqXG4gKiBEZXRlY3RzIGlmIHRoZSB1c2VyIGFnZW50IGlzIGEgd2ViIGNyYXdsZXIvYm90XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB1c2VyIGFnZW50IGFwcGVhcnMgdG8gYmUgYSBib3QvY3Jhd2xlclxuICovXG5mdW5jdGlvbiBpc19jcmF3bGVyKCkge1xuICAgIGxldCB1c2VyX2FnZW50ID0gbmF2aWdhdG9yLnVzZXJBZ2VudDtcbiAgICBsZXQgYm90X3BhdHRlcm4gPSAvYm90fHNwaWRlcnxjcmF3bHxzbHVycHxhcmNoaXZlcnxwaW5nfHNlYXJjaHxkaWd8dHJhY2tlcnxtb25pdG9yfHNub29weXx5YWhvb3xiYWlkdXxtc258YXNrfHRlb21hfGF4aW9zL2k7XG5cbiAgICByZXR1cm4gYm90X3BhdHRlcm4udGVzdCh1c2VyX2FnZW50KTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRE9NIFNDUk9MTElORyBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBTY3JvbGxzIHBhcmVudCBjb250YWluZXIgdG8gbWFrZSB0YXJnZXQgZWxlbWVudCB2aXNpYmxlIGlmIG5lZWRlZFxuICogQHBhcmFtIHtzdHJpbmd8SFRNTEVsZW1lbnR8alF1ZXJ5fSB0YXJnZXQgLSBUYXJnZXQgZWxlbWVudCB0byBzY3JvbGwgaW50byB2aWV3XG4gKi9cbmZ1bmN0aW9uIHNjcm9sbF9pbnRvX3ZpZXdfaWZfbmVlZGVkKHRhcmdldCkge1xuICAgIGNvbnN0ICR0YXJnZXQgPSAkKHRhcmdldCk7XG5cbiAgICAvLyBGaW5kIHRoZSBjbG9zZXN0IHBhcmVudCB3aXRoIG92ZXJmbG93LXk6IGF1dG9cbiAgICBjb25zdCAkcGFyZW50ID0gJHRhcmdldC5wYXJlbnQoKTtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgYWJzb2x1dGUgdG9wIHBvc2l0aW9uIG9mIHRoZSB0YXJnZXRcbiAgICBjb25zdCB0YXJnZXRfdG9wID0gJHRhcmdldC5wb3NpdGlvbigpLnRvcCArICRwYXJlbnQuc2Nyb2xsVG9wKCk7XG5cbiAgICBjb25zdCB0YXJnZXRfaGVpZ2h0ID0gJHRhcmdldC5vdXRlckhlaWdodCgpO1xuICAgIGNvbnN0IHBhcmVudF9oZWlnaHQgPSAkcGFyZW50LmhlaWdodCgpO1xuICAgIGNvbnN0IHNjcm9sbF9wb3NpdGlvbiA9ICRwYXJlbnQuc2Nyb2xsVG9wKCk7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgdGFyZ2V0IGlzIG91dCBvZiB2aWV3XG4gICAgaWYgKHRhcmdldF90b3AgPCBzY3JvbGxfcG9zaXRpb24gfHwgdGFyZ2V0X3RvcCArIHRhcmdldF9oZWlnaHQgPiBzY3JvbGxfcG9zaXRpb24gKyBwYXJlbnRfaGVpZ2h0KSB7XG4gICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ1VJJywgJ1Njcm9sbGluZyEnLCB0YXJnZXRfdG9wKTtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG5ldyBzY3JvbGwgcG9zaXRpb24gdG8gY2VudGVyIHRoZSB0YXJnZXRcbiAgICAgICAgbGV0IG5ld19zY3JvbGxfcG9zaXRpb24gPSB0YXJnZXRfdG9wICsgdGFyZ2V0X2hlaWdodCAvIDIgLSBwYXJlbnRfaGVpZ2h0IC8gMjtcblxuICAgICAgICAvLyBMaW1pdCB0aGUgc2Nyb2xsIHBvc2l0aW9uIGJldHdlZW4gMCBhbmQgdGhlIG1heGltdW0gc2Nyb2xsYWJsZSBoZWlnaHRcbiAgICAgICAgbmV3X3Njcm9sbF9wb3NpdGlvbiA9IE1hdGgubWF4KDAsIE1hdGgubWluKG5ld19zY3JvbGxfcG9zaXRpb24sICRwYXJlbnRbMF0uc2Nyb2xsSGVpZ2h0IC0gcGFyZW50X2hlaWdodCkpO1xuXG4gICAgICAgIC8vIFNjcm9sbCB0aGUgcGFyZW50IHRvIHRoZSBuZXcgc2Nyb2xsIHBvc2l0aW9uXG4gICAgICAgICRwYXJlbnQuc2Nyb2xsVG9wKG5ld19zY3JvbGxfcG9zaXRpb24pO1xuICAgIH1cbn1cblxuLyoqXG4gKiBTY3JvbGxzIHBhZ2UgdG8gbWFrZSB0YXJnZXQgZWxlbWVudCB2aXNpYmxlIGlmIG5lZWRlZCAod2l0aCBhbmltYXRpb24pXG4gKiBAcGFyYW0ge3N0cmluZ3xIVE1MRWxlbWVudHxqUXVlcnl9IHRhcmdldCAtIFRhcmdldCBlbGVtZW50IHRvIHNjcm9sbCBpbnRvIHZpZXdcbiAqL1xuZnVuY3Rpb24gc2Nyb2xsX3BhZ2VfaW50b192aWV3X2lmX25lZWRlZCh0YXJnZXQpIHtcbiAgICBjb25zdCAkdGFyZ2V0ID0gJCh0YXJnZXQpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBhYnNvbHV0ZSB0b3AgcG9zaXRpb24gb2YgdGhlIHRhcmdldCByZWxhdGl2ZSB0byB0aGUgZG9jdW1lbnRcbiAgICBjb25zdCB0YXJnZXRfdG9wID0gJHRhcmdldC5vZmZzZXQoKS50b3A7XG5cbiAgICBjb25zdCB0YXJnZXRfaGVpZ2h0ID0gJHRhcmdldC5vdXRlckhlaWdodCgpO1xuICAgIGNvbnN0IHdpbmRvd19oZWlnaHQgPSAkKHdpbmRvdykuaGVpZ2h0KCk7XG4gICAgY29uc3Qgd2luZG93X3Njcm9sbF9wb3NpdGlvbiA9ICQod2luZG93KS5zY3JvbGxUb3AoKTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB0YXJnZXQgaXMgb3V0IG9mIHZpZXdcbiAgICBpZiAodGFyZ2V0X3RvcCA8IHdpbmRvd19zY3JvbGxfcG9zaXRpb24gfHwgdGFyZ2V0X3RvcCArIHRhcmdldF9oZWlnaHQgPiB3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uICsgd2luZG93X2hlaWdodCkge1xuICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKCdVSScsICdTY3JvbGxpbmchJywgdGFyZ2V0X3RvcCk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuZXcgc2Nyb2xsIHBvc2l0aW9uIHRvIGNlbnRlciB0aGUgdGFyZ2V0XG4gICAgICAgIGNvbnN0IG5ld19zY3JvbGxfcG9zaXRpb24gPSB0YXJnZXRfdG9wICsgdGFyZ2V0X2hlaWdodCAvIDIgLSB3aW5kb3dfaGVpZ2h0IC8gMjtcblxuICAgICAgICAvLyBBbmltYXRlIHRoZSBzY3JvbGwgdG8gdGhlIG5ldyBwb3NpdGlvblxuICAgICAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZShcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzY3JvbGxUb3A6IG5ld19zY3JvbGxfcG9zaXRpb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgMTAwMFxuICAgICAgICApOyAvLyBkdXJhdGlvbiBvZiB0aGUgc2Nyb2xsIGFuaW1hdGlvbiBpbiBtaWxsaXNlY29uZHNcbiAgICB9XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERPTSBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBXYWl0cyBmb3IgYWxsIGltYWdlcyBvbiB0aGUgcGFnZSB0byBsb2FkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGNhbGwgd2hlbiBhbGwgaW1hZ2VzIGFyZSBsb2FkZWRcbiAqL1xuZnVuY3Rpb24gd2FpdF9mb3JfaW1hZ2VzKGNhbGxiYWNrKSB7XG4gICAgY29uc3QgJGltYWdlcyA9ICQoJ2ltZycpOyAvLyBHZXQgYWxsIGltZyB0YWdzXG4gICAgY29uc3QgdG90YWxfaW1hZ2VzID0gJGltYWdlcy5sZW5ndGg7XG4gICAgbGV0IGltYWdlc19sb2FkZWQgPSAwO1xuXG4gICAgaWYgKHRvdGFsX2ltYWdlcyA9PT0gMCkge1xuICAgICAgICBjYWxsYmFjaygpOyAvLyBpZiB0aGVyZSBhcmUgbm8gaW1hZ2VzLCBpbW1lZGlhdGVseSBjYWxsIHRoZSBjYWxsYmFja1xuICAgIH1cblxuICAgICRpbWFnZXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnN0IGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBpbWcub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaW1hZ2VzX2xvYWRlZCsrO1xuICAgICAgICAgICAgaWYgKGltYWdlc19sb2FkZWQgPT09IHRvdGFsX2ltYWdlcykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7IC8vIGNhbGwgdGhlIGNhbGxiYWNrIHdoZW4gYWxsIGltYWdlcyBhcmUgbG9hZGVkXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGltZy5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaW1hZ2VzX2xvYWRlZCsrO1xuICAgICAgICAgICAgaWYgKGltYWdlc19sb2FkZWQgPT09IHRvdGFsX2ltYWdlcykge1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKCk7IC8vIGFsc28gY2FsbCB0aGUgY2FsbGJhY2sgaWYgYW4gaW1hZ2UgZmFpbHMgdG8gbG9hZFxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpbWcuc3JjID0gdGhpcy5zcmM7IC8vIHRoaXMgdHJpZ2dlcnMgdGhlIGxvYWRpbmdcbiAgICB9KTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgalF1ZXJ5IGVsZW1lbnQgY29udGFpbmluZyBhIG5vbi1icmVha2luZyBzcGFjZVxuICogQHJldHVybnMge2pRdWVyeX0galF1ZXJ5IHNwYW4gZWxlbWVudCB3aXRoICZuYnNwO1xuICovXG5mdW5jdGlvbiAkbmJzcCgpIHtcbiAgICByZXR1cm4gJCgnPHNwYW4+Jm5ic3A7PC9zcGFuPicpO1xufVxuXG4vKipcbiAqIEVzY2FwZXMgc3BlY2lhbCBjaGFyYWN0ZXJzIGluIGEgalF1ZXJ5IHNlbGVjdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gaWQgLSBFbGVtZW50IElEIHRvIGVzY2FwZVxuICogQHJldHVybnMge3N0cmluZ30galF1ZXJ5IHNlbGVjdG9yIHN0cmluZyB3aXRoIGVzY2FwZWQgc3BlY2lhbCBjaGFyYWN0ZXJzXG4gKiBAd2FybmluZyBOb3Qgc2FmZSBmb3Igc2VjdXJpdHktY3JpdGljYWwgb3BlcmF0aW9uc1xuICovXG5mdW5jdGlvbiBlc2NhcGVfanFfc2VsZWN0b3IoaWQpIHtcbiAgICByZXR1cm4gJyMnICsgaWQucmVwbGFjZSgvKDp8XFwufFxcW3xcXF18LHw9fEApL2csICdcXFxcJDEnKTtcbn0iLCIvKlxuICogRGF0ZSBhbmQgdGltZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIGRhdGUvdGltZSBjb252ZXJzaW9ucyBhbmQgVW5peCB0aW1lc3RhbXBzLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERBVEUvVElNRSBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBHZXRzIHRoZSBjdXJyZW50IFVuaXggdGltZXN0YW1wIChzZWNvbmRzIHNpbmNlIGVwb2NoKVxuICogQHJldHVybnMge251bWJlcn0gQ3VycmVudCBVbml4IHRpbWVzdGFtcCBpbiBzZWNvbmRzXG4gKiBAdG9kbyBDYWxjdWxhdGUgYmFzZWQgb24gc2VydmVyIHRpbWUgYXQgcGFnZSByZW5kZXJcbiAqIEB0b2RvIE1vdmUgdG8gYSBkYXRlIGxpYnJhcnlcbiAqL1xuZnVuY3Rpb24gdW5peF90aW1lKCkge1xuICAgIHJldHVybiBNYXRoLnJvdW5kKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBkYXRlIHN0cmluZyB0byBVbml4IHRpbWVzdGFtcFxuICogQHBhcmFtIHtzdHJpbmd9IHN0cl9kYXRlIC0gRGF0ZSBzdHJpbmcgKFktbS1kIEg6aTpzIGZvcm1hdClcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFVuaXggdGltZXN0YW1wIGluIHNlY29uZHNcbiAqL1xuZnVuY3Rpb24geW1kaGlzX3RvX3VuaXgoc3RyX2RhdGUpIHtcbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoc3RyX2RhdGUpO1xuICAgIHJldHVybiBkYXRlLmdldFRpbWUoKSAvIDEwMDA7XG59IiwiLypcbiAqIEVycm9yIGhhbmRsaW5nIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgZXJyb3IgY3JlYXRpb24gYW5kIGRlYnVnZ2luZyB1dGlsaXRpZXMuXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRVJST1IgSEFORExJTkdcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDcmVhdGVzIGFuIGVycm9yIG9iamVjdCBmcm9tIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R9IHN0ciAtIEVycm9yIG1lc3NhZ2Ugb3IgZXhpc3RpbmcgZXJyb3Igb2JqZWN0XG4gKiBAcGFyYW0ge251bWJlcn0gW2Vycm9yX2NvZGVdIC0gT3B0aW9uYWwgZXJyb3Igc3RhdHVzIGNvZGVcbiAqIEByZXR1cm5zIHtPYmplY3R9IEVycm9yIG9iamVjdCB3aXRoIGVycm9yIGFuZCBzdGF0dXMgcHJvcGVydGllc1xuICovXG5mdW5jdGlvbiBlcnJvcihzdHIsIGVycm9yX2NvZGUpIHtcbiAgICBpZiAodHlwZW9mIHN0ci5lcnJvciAhPSB1bmRlZikge1xuICAgICAgICByZXR1cm4gc3RyO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3JfY29kZSA9PSB1bmRlZikge1xuICAgICAgICAgICAgcmV0dXJuIHsgZXJyb3I6IHN0ciwgc3RhdHVzOiBudWxsIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4geyBlcnJvcjogc3RyLCBzdGF0dXM6IGVycm9yX2NvZGUgfTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBTYW5pdHkgY2hlY2sgZmFpbHVyZSBoYW5kbGVyIGZvciBKYXZhU2NyaXB0XG4gKlxuICogVGhpcyBmdW5jdGlvbiBzaG91bGQgYmUgY2FsbGVkIHdoZW4gYSBzYW5pdHkgY2hlY2sgZmFpbHMgLSBpLmUuLCB3aGVuIHRoZSBjb2RlXG4gKiBlbmNvdW50ZXJzIGEgY29uZGl0aW9uIHRoYXQgXCJzaG91bGRuJ3QgaGFwcGVuXCIgaWYgZXZlcnl0aGluZyBpcyB3b3JraW5nIGNvcnJlY3RseS5cbiAqXG4gKiBVbmxpa2UgUEhQLCB3ZSBjYW4ndCBzdG9wIEphdmFTY3JpcHQgZXhlY3V0aW9uLCBidXQgd2UgY2FuOlxuICogMS4gVGhyb3cgYW4gZXJyb3IgdGhhdCB3aWxsIGJlIGNhdWdodCBieSBlcnJvciBoYW5kbGVyc1xuICogMi4gTG9nIGEgY2xlYXIgZXJyb3IgdG8gdGhlIGNvbnNvbGVcbiAqIDMuIFByb3ZpZGUgc3RhY2sgdHJhY2UgZm9yIGRlYnVnZ2luZ1xuICpcbiAqIFVzZSB0aGlzIGluc3RlYWQgb2Ygc2lsZW50bHkgcmV0dXJuaW5nIG9yIGNvbnRpbnVpbmcgd2hlbiBlbmNvdW50ZXJpbmcgdW5leHBlY3RlZCBjb25kaXRpb25zLlxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIE9wdGlvbmFsIHNwZWNpZmljIG1lc3NhZ2UgYWJvdXQgd2hhdCBzaG91bGRuJ3QgaGF2ZSBoYXBwZW5lZFxuICogQHRocm93cyB7RXJyb3J9IEFsd2F5cyB0aHJvd3Mgd2l0aCBsb2NhdGlvbiBhbmQgY29udGV4dCBpbmZvcm1hdGlvblxuICovXG5mdW5jdGlvbiBzaG91bGRudF9oYXBwZW4obWVzc2FnZSA9IG51bGwpIHtcbiAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcigpO1xuICAgIGNvbnN0IHN0YWNrID0gZXJyb3Iuc3RhY2sgfHwgJyc7XG4gICAgY29uc3Qgc3RhY2tMaW5lcyA9IHN0YWNrLnNwbGl0KCdcXG4nKTtcblxuICAgIC8vIEdldCB0aGUgY2FsbGVyIGxvY2F0aW9uIChza2lwIHRoZSBFcnJvciBsaW5lIGFuZCB0aGlzIGZ1bmN0aW9uKVxuICAgIGxldCBjYWxsZXJJbmZvID0gJ3Vua25vd24gbG9jYXRpb24nO1xuICAgIGlmIChzdGFja0xpbmVzLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgY29uc3QgY2FsbGVyTGluZSA9IHN0YWNrTGluZXNbMl0gfHwgc3RhY2tMaW5lc1sxXSB8fCAnJztcbiAgICAgICAgLy8gRXh0cmFjdCBmaWxlIGFuZCBsaW5lIG51bWJlciBmcm9tIHN0YWNrIHRyYWNlXG4gICAgICAgIGNvbnN0IG1hdGNoID0gY2FsbGVyTGluZS5tYXRjaCgvYXRcXHMrLio/XFxzK1xcKCguKj8pOihcXGQrKTooXFxkKylcXCkvKSB8fCBjYWxsZXJMaW5lLm1hdGNoKC9hdFxccysoLio/KTooXFxkKyk6KFxcZCspLyk7XG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgY2FsbGVySW5mbyA9IGAke21hdGNoWzFdfToke21hdGNoWzJdfWA7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgZXJyb3JNZXNzYWdlID0gYEZhdGFsOiBzaG91bGRudF9oYXBwZW4oKSB3YXMgY2FsbGVkIGF0ICR7Y2FsbGVySW5mb31cXG5gO1xuICAgIGVycm9yTWVzc2FnZSArPSAnVGhpcyBpbmRpY2F0ZXMgYSBzYW5pdHkgY2hlY2sgZmFpbGVkIC0gdGhlIGNvZGUgaXMgbm90IGJlaGF2aW5nIGFzIGV4cGVjdGVkLlxcbic7XG5cbiAgICBpZiAobWVzc2FnZSkge1xuICAgICAgICBlcnJvck1lc3NhZ2UgKz0gYERldGFpbHM6ICR7bWVzc2FnZX1cXG5gO1xuICAgIH1cblxuICAgIGVycm9yTWVzc2FnZSArPSAnUGxlYXNlIHRob3JvdWdobHkgcmV2aWV3IHRoZSByZWxhdGVkIGNvZGUgdG8gZGV0ZXJtaW5lIHdoeSB0aGlzIGVycm9yIG9jY3VycmVkLic7XG5cbiAgICAvLyBMb2cgdG8gY29uc29sZSB3aXRoIGZ1bGwgdmlzaWJpbGl0eVxuICAgIGNvbnNvbGUuZXJyb3IoJz0nLnJlcGVhdCg4MCkpO1xuICAgIGNvbnNvbGUuZXJyb3IoJ1NBTklUWSBDSEVDSyBGQUlMVVJFJyk7XG4gICAgY29uc29sZS5lcnJvcignPScucmVwZWF0KDgwKSk7XG4gICAgY29uc29sZS5lcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgIGNvbnNvbGUuZXJyb3IoJ1N0YWNrIHRyYWNlOicsIHN0YWNrKTtcbiAgICBjb25zb2xlLmVycm9yKCc9Jy5yZXBlYXQoODApKTtcblxuICAgIC8vIFRocm93IGVycm9yIHRvIHN0b3AgZXhlY3V0aW9uIGZsb3dcbiAgICBjb25zdCBmYXRhbEVycm9yID0gbmV3IEVycm9yKGVycm9yTWVzc2FnZSk7XG4gICAgZmF0YWxFcnJvci5uYW1lID0gJ1Nhbml0eUNoZWNrRmFpbHVyZSc7XG4gICAgdGhyb3cgZmF0YWxFcnJvcjtcbn0iLCIvKlxuICogSGFzaGluZyBhbmQgY29tcGFyaXNvbiB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIG9iamVjdCBoYXNoaW5nIGFuZCBkZWVwIGNvbXBhcmlzb24uXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gSEFTSElORyBBTkQgQ09NUEFSSVNPTlxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBoYXNoIGZvciBhbnkgdmFsdWUgKGhhbmRsZXMgb2JqZWN0cywgYXJyYXlzLCBjaXJjdWxhciByZWZlcmVuY2VzKVxuICogQHBhcmFtIHsqfSB0aGVfdmFyIC0gVmFsdWUgdG8gaGFzaFxuICogQHBhcmFtIHtib29sZWFufSBbY2FsY19zaGExPXRydWVdIC0gSWYgdHJ1ZSwgcmV0dXJucyBTSEExIGhhc2g7IGlmIGZhbHNlLCByZXR1cm5zIEpTT05cbiAqIEBwYXJhbSB7QXJyYXk8c3RyaW5nPn0gW2lnbm9yZWRfa2V5cz1udWxsXSAtIEtleXMgdG8gaWdub3JlIHdoZW4gaGFzaGluZyBvYmplY3RzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTSEExIGhhc2ggb3IgSlNPTiBzdHJpbmcgb2YgdGhlIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIGhhc2godGhlX3ZhciwgY2FsY19zaGExID0gdHJ1ZSwgaWdub3JlZF9rZXlzID0gbnVsbCkge1xuICAgIGlmICh0eXBlb2YgdGhlX3ZhciA9PSB1bmRlZikge1xuICAgICAgICB0aGVfdmFyID0gJ19fdW5kZWZpbmVkX18nO1xuICAgIH1cblxuICAgIGlmIChpZ25vcmVkX2tleXMgPT09IG51bGwpIHtcbiAgICAgICAgaWdub3JlZF9rZXlzID0gWyckJ107XG4gICAgfVxuXG4gICAgLy8gQ29udmVydHMgdmFsdWUgdG8ganNvbiwgZGlzY2FyZGluZyBjaXJjdWxhciByZWZlcmVuY2VzXG4gICAgbGV0IGpzb25fc3RyaW5naWZ5X25vY2lyYyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBjb25zdCBjYWNoZSA9IFtdO1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUsIGZ1bmN0aW9uIChrZXksIHYpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIHRoZV92YXIuX2NhY2hlX2tleSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoZV92YXIuX2hhc2hfa2V5KCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2ID09PSAnb2JqZWN0JyAmJiB2ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGNhY2hlLmluZGV4T2YodikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIER1cGxpY2F0ZSByZWZlcmVuY2UgZm91bmQsIGRpc2NhcmQga2V5XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FjaGUucHVzaCh2KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB2O1xuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgLy8gVHVybiBldmVyeSBwcm9wZXJ0eSBhbmQgYWxsIGl0cyBjaGlsZHJlbiBpbnRvIGEgc2luZ2xlIGRlcHRoIGFycmF5IG9mIHZhbHVlcyB0aGF0IHdlIGNhbiB0aGVuXG4gICAgLy8gc29ydCBhbmQgaGFzaCBhcyBhIHdob2xlXG4gICAgbGV0IGZsYXRfdmFyID0ge307XG4gICAgbGV0IF9mbGF0dGVuID0gZnVuY3Rpb24gKHRoZV92YXIsIHByZWZpeCwgZGVwdGggPSAwKSB7XG4gICAgICAgIC8vIElmIGEgY2xhc3Mgb2JqZWN0IGlzIHByb3ZpZGVkLCBjaXJjdWxhciByZWZlcmVuY2VzIGNhbiBtYWtlIHRoZSBjYWxsIHN0YWNrIHJlY3Vyc2l2ZS5cbiAgICAgICAgLy8gRm9yIHRoZSBwdXJwb3NlcyBvZiBob3cgdGhlIGhhc2ggZnVuY3Rpb24gaXMgY2FsbGVkLCB0aGlzIHNob3VsZCBiZSBzdWZmaWNpZW50LlxuICAgICAgICBpZiAoZGVwdGggPiAxMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRG9lcyBub3QgYWNjb3VudCBmb3IgZGF0ZXMgaSB0aGluay4uLlxuXG4gICAgICAgIGlmIChpc19vYmplY3QodGhlX3ZhcikgJiYgdHlwZW9mIHRoZV92YXIuX2NhY2hlX2tleSA9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAvLyBVc2UgX2NhY2hlX2tleSB0byBoYXNoIGNvbXBvbmVudHNcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSB0aGVfdmFyLl9oYXNoX2tleSgpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzX29iamVjdCh0aGVfdmFyKSAmJiB0eXBlb2YgQWJzdHJhY3QgIT09ICd1bmRlZmluZWQnICYmIHRoZV92YXIgaW5zdGFuY2VvZiBBYnN0cmFjdCkge1xuICAgICAgICAgICAgLy8gU3RyaW5naWZ5IGFsbCBjbGFzcyBvYmplY3RzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0ganNvbl9zdHJpbmdpZnlfbm9jaXJjKHRoZV92YXIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzX29iamVjdCh0aGVfdmFyKSkge1xuICAgICAgICAgICAgLy8gSXRlcmF0ZSBvdGhlciBvYmplY3RzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0ge307XG4gICAgICAgICAgICBmb3IgKGxldCBrIGluIHRoZV92YXIpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhlX3Zhci5oYXNPd25Qcm9wZXJ0eShrKSAmJiBpZ25vcmVkX2tleXMuaW5kZXhPZihrKSA9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBfZmxhdHRlbih0aGVfdmFyW2tdLCBwcmVmaXggKyAnLi4nICsgaywgZGVwdGggKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoaXNfYXJyYXkodGhlX3ZhcikpIHtcbiAgICAgICAgICAgIC8vIEl0ZXJhdGUgYXJyYXlzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0gW107XG4gICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICBmb3JlYWNoKHRoZV92YXIsICh2KSA9PiB7XG4gICAgICAgICAgICAgICAgX2ZsYXR0ZW4odiwgcHJlZml4ICsgJy4uJyArIGksIGRlcHRoICsgMSk7XG4gICAgICAgICAgICAgICAgaSsrO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNfZnVuY3Rpb24odGhlX3ZhcikpIHtcbiAgICAgICAgICAgIC8vIG5vdGhpbmdcbiAgICAgICAgfSBlbHNlIGlmICghaXNfbnVtZXJpYyh0aGVfdmFyKSkge1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IFN0cmluZyh0aGVfdmFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSB0aGVfdmFyO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIF9mbGF0dGVuKHRoZV92YXIsICdfJyk7XG5cbiAgICBsZXQgc29ydGVyID0gW107XG5cbiAgICBmb3JlYWNoKGZsYXRfdmFyLCBmdW5jdGlvbiAodiwgaykge1xuICAgICAgICBzb3J0ZXIucHVzaChbaywgdl0pO1xuICAgIH0pO1xuXG4gICAgc29ydGVyLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGFbMF0gPiBiWzBdO1xuICAgIH0pO1xuXG4gICAgbGV0IGpzb24gPSBKU09OLnN0cmluZ2lmeShzb3J0ZXIpO1xuXG4gICAgaWYgKGNhbGNfc2hhMSkge1xuICAgICAgICBsZXQgaGFzaGVkID0gc2hhMS5zaGExKGpzb24pO1xuICAgICAgICByZXR1cm4gaGFzaGVkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBqc29uO1xuICAgIH1cbn1cblxuLyoqXG4gKiBEZWVwIGNvbXBhcmlzb24gb2YgdHdvIHZhbHVlcyAoaWdub3JlcyBwcm9wZXJ0eSBvcmRlciBhbmQgZnVuY3Rpb25zKVxuICogQHBhcmFtIHsqfSBhIC0gRmlyc3QgdmFsdWUgdG8gY29tcGFyZVxuICogQHBhcmFtIHsqfSBiIC0gU2Vjb25kIHZhbHVlIHRvIGNvbXBhcmVcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlcyBhcmUgZGVlcGx5IGVxdWFsXG4gKi9cbmZ1bmN0aW9uIGRlZXBfZXF1YWwoYSwgYikge1xuICAgIHJldHVybiBoYXNoKGEsIGZhbHNlKSA9PSBoYXNoKGIsIGZhbHNlKTtcbn0iLCIvKipcbiAqIE11dGV4IGRlY29yYXRvciBmb3IgZXhjbHVzaXZlIG1ldGhvZCBleGVjdXRpb25cbiAqXG4gKiBXaXRob3V0IGFyZ3VtZW50czogUGVyLWluc3RhbmNlIGxvY2tpbmcgKGVhY2ggb2JqZWN0IGhhcyBpdHMgb3duIGxvY2sgcGVyIG1ldGhvZClcbiAqICAgQG11dGV4XG4gKiAgIGFzeW5jIG15X21ldGhvZCgpIHsgLi4uIH1cbiAqXG4gKiBXaXRoIElEIGFyZ3VtZW50OiBHbG9iYWwgbG9ja2luZyBieSBJRCAoYWxsIGluc3RhbmNlcyBzaGFyZSB0aGUgbG9jaylcbiAqICAgQG11dGV4KCdvcGVyYXRpb25fbmFtZScpXG4gKiAgIGFzeW5jIG15X21ldGhvZCgpIHsgLi4uIH1cbiAqXG4gKiBAZGVjb3JhdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gW2dsb2JhbF9pZF0gLSBPcHRpb25hbCBnbG9iYWwgbXV0ZXggSUQgZm9yIGNyb3NzLWluc3RhbmNlIGxvY2tpbmdcbiAqL1xuZnVuY3Rpb24gbXV0ZXgoZ2xvYmFsX2lkKSB7XG4gICAgLy8gU3RvcmFnZSAodXNpbmcgSUlGRXMgdG8ga2VlcCBXZWFrTWFwL01hcCBpbiBjbG9zdXJlIHNjb3BlKVxuICAgIGNvbnN0IGluc3RhbmNlX211dGV4ZXMgPSAoZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICghbXV0ZXguX2luc3RhbmNlX3N0b3JhZ2UpIHtcbiAgICAgICAgICAgIG11dGV4Ll9pbnN0YW5jZV9zdG9yYWdlID0gbmV3IFdlYWtNYXAoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbXV0ZXguX2luc3RhbmNlX3N0b3JhZ2U7XG4gICAgfSkoKTtcblxuICAgIGNvbnN0IGdsb2JhbF9tdXRleGVzID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIW11dGV4Ll9nbG9iYWxfc3RvcmFnZSkge1xuICAgICAgICAgICAgbXV0ZXguX2dsb2JhbF9zdG9yYWdlID0gbmV3IE1hcCgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtdXRleC5fZ2xvYmFsX3N0b3JhZ2U7XG4gICAgfSkoKTtcblxuICAgIC8qKlxuICAgICAqIEdldCBvciBjcmVhdGUgYSBtdXRleCBmb3IgYSBzcGVjaWZpYyBpbnN0YW5jZSBhbmQgbWV0aG9kXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0X2luc3RhbmNlX211dGV4KGluc3RhbmNlLCBtZXRob2RfbmFtZSkge1xuICAgICAgICBsZXQgaW5zdGFuY2VfbG9ja3MgPSBpbnN0YW5jZV9tdXRleGVzLmdldChpbnN0YW5jZSk7XG4gICAgICAgIGlmICghaW5zdGFuY2VfbG9ja3MpIHtcbiAgICAgICAgICAgIGluc3RhbmNlX2xvY2tzID0gbmV3IE1hcCgpO1xuICAgICAgICAgICAgaW5zdGFuY2VfbXV0ZXhlcy5zZXQoaW5zdGFuY2UsIGluc3RhbmNlX2xvY2tzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsb2NrX3N0YXRlID0gaW5zdGFuY2VfbG9ja3MuZ2V0KG1ldGhvZF9uYW1lKTtcbiAgICAgICAgaWYgKCFsb2NrX3N0YXRlKSB7XG4gICAgICAgICAgICBsb2NrX3N0YXRlID0geyBhY3RpdmU6IGZhbHNlLCBxdWV1ZTogW10gfTtcbiAgICAgICAgICAgIGluc3RhbmNlX2xvY2tzLnNldChtZXRob2RfbmFtZSwgbG9ja19zdGF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbG9ja19zdGF0ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgb3IgY3JlYXRlIGEgZ2xvYmFsIG11dGV4IGJ5IElEXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0X2dsb2JhbF9tdXRleChpZCkge1xuICAgICAgICBsZXQgbG9ja19zdGF0ZSA9IGdsb2JhbF9tdXRleGVzLmdldChpZCk7XG4gICAgICAgIGlmICghbG9ja19zdGF0ZSkge1xuICAgICAgICAgICAgbG9ja19zdGF0ZSA9IHsgYWN0aXZlOiBmYWxzZSwgcXVldWU6IFtdIH07XG4gICAgICAgICAgICBnbG9iYWxfbXV0ZXhlcy5zZXQoaWQsIGxvY2tfc3RhdGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2NrX3N0YXRlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGUgdGhlIG5leHQgcXVldWVkIG9wZXJhdGlvbiBmb3IgYSBtdXRleFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHNjaGVkdWxlX25leHQobG9ja19zdGF0ZSkge1xuICAgICAgICBpZiAobG9ja19zdGF0ZS5hY3RpdmUgfHwgbG9ja19zdGF0ZS5xdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHsgZm4sIHJlc29sdmUsIHJlamVjdCB9ID0gbG9ja19zdGF0ZS5xdWV1ZS5zaGlmdCgpO1xuICAgICAgICBsb2NrX3N0YXRlLmFjdGl2ZSA9IHRydWU7XG5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgICAgICAgIC50aGVuKGZuKVxuICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KVxuICAgICAgICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxvY2tfc3RhdGUuYWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc2NoZWR1bGVfbmV4dChsb2NrX3N0YXRlKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFjcXVpcmUgYSBtdXRleCBsb2NrIGFuZCBleGVjdXRlIGNhbGxiYWNrXG4gICAgICovXG4gICAgZnVuY3Rpb24gYWNxdWlyZV9sb2NrKGxvY2tfc3RhdGUsIGZuKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBsb2NrX3N0YXRlLnF1ZXVlLnB1c2goeyBmbiwgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgc2NoZWR1bGVfbmV4dChsb2NrX3N0YXRlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gSWYgY2FsbGVkIHdpdGggYW4gSUQgYXJndW1lbnQ6IEBtdXRleCgnaWQnKVxuICAgIGlmICh0eXBlb2YgZ2xvYmFsX2lkID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24odGFyZ2V0LCBrZXksIGRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsX21ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb3JpZ2luYWxfbWV0aG9kICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBAbXV0ZXggY2FuIG9ubHkgYmUgYXBwbGllZCB0byBtZXRob2RzICh0cmllZCB0byBhcHBseSB0byAke2tleX0pYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlc2NyaXB0b3IudmFsdWUgPSBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbG9ja19zdGF0ZSA9IGdldF9nbG9iYWxfbXV0ZXgoZ2xvYmFsX2lkKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNxdWlyZV9sb2NrKGxvY2tfc3RhdGUsICgpID0+IG9yaWdpbmFsX21ldGhvZC5hcHBseSh0aGlzLCBhcmdzKSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBJZiBjYWxsZWQgd2l0aG91dCBhcmd1bWVudHM6IEBtdXRleCAodGFyZ2V0IGlzIHRoZSBmaXJzdCBhcmd1bWVudClcbiAgICBjb25zdCB0YXJnZXQgPSBnbG9iYWxfaWQ7ICAvLyBJbiB0aGlzIGNhc2UsIGZpcnN0IGFyZyBpcyB0YXJnZXRcbiAgICBjb25zdCBrZXkgPSBhcmd1bWVudHNbMV07XG4gICAgY29uc3QgZGVzY3JpcHRvciA9IGFyZ3VtZW50c1syXTtcblxuICAgIGNvbnN0IG9yaWdpbmFsX21ldGhvZCA9IGRlc2NyaXB0b3IudmFsdWU7XG5cbiAgICBpZiAodHlwZW9mIG9yaWdpbmFsX21ldGhvZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEBtdXRleCBjYW4gb25seSBiZSBhcHBsaWVkIHRvIG1ldGhvZHMgKHRyaWVkIHRvIGFwcGx5IHRvICR7a2V5fSlgKTtcbiAgICB9XG5cbiAgICBkZXNjcmlwdG9yLnZhbHVlID0gZnVuY3Rpb24oLi4uYXJncykge1xuICAgICAgICBjb25zdCBsb2NrX3N0YXRlID0gZ2V0X2luc3RhbmNlX211dGV4KHRoaXMsIGtleSk7XG4gICAgICAgIHJldHVybiBhY3F1aXJlX2xvY2sobG9ja19zdGF0ZSwgKCkgPT4gb3JpZ2luYWxfbWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3MpKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRlc2NyaXB0b3I7XG59XG4iLCIvKlxuICogQXN5bmMgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSBhc3luY2hyb25vdXMgb3BlcmF0aW9ucywgZGVsYXlzLCBkZWJvdW5jaW5nLCBhbmQgbXV0ZXhlcy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBBU1lOQyBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBQYXVzZXMgZXhlY3V0aW9uIGZvciBzcGVjaWZpZWQgbWlsbGlzZWNvbmRzXG4gKiBAcGFyYW0ge251bWJlcn0gW21pbGxpc2Vjb25kcz0wXSAtIERlbGF5IGluIG1pbGxpc2Vjb25kcyAoMCB1c2VzIHJlcXVlc3RBbmltYXRpb25GcmFtZSlcbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgZGVsYXlcbiAqIEBleGFtcGxlIGF3YWl0IHNsZWVwKDEwMDApOyAvLyBXYWl0IDEgc2Vjb25kXG4gKi9cbmZ1bmN0aW9uIHNsZWVwKG1pbGxpc2Vjb25kcyA9IDApIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgaWYgKG1pbGxpc2Vjb25kcyA9PSAwICYmIHJlcXVlc3RBbmltYXRpb25GcmFtZSkge1xuICAgICAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKHJlc29sdmUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0VGltZW91dChyZXNvbHZlLCBtaWxsaXNlY29uZHMpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB3aXRoIGV4Y2x1c2l2aXR5IGFuZCBwcm9taXNlIGZhbi1pblxuICpcbiAqIFRoaXMgZnVuY3Rpb24sIHdoZW4gaW52b2tlZCwgaW1tZWRpYXRlbHkgcnVucyB0aGUgY2FsbGJhY2sgZXhjbHVzaXZlbHkuXG4gKiBGb3Igc3Vic2VxdWVudCBpbnZvY2F0aW9ucywgaXQgYXBwbGllcyBhIGRlbGF5IGJlZm9yZSBydW5uaW5nIHRoZSBjYWxsYmFjayBleGNsdXNpdmVseSBhZ2Fpbi5cbiAqIFRoZSBkZWxheSBzdGFydHMgYWZ0ZXIgdGhlIGN1cnJlbnQgYXN5bmNocm9ub3VzIG9wZXJhdGlvbiByZXNvbHZlcy5cbiAqXG4gKiBJZiAnZGVsYXknIGlzIHNldCB0byAwLCB0aGUgZnVuY3Rpb24gd2lsbCBvbmx5IHByZXZlbnQgZW5xdWV1ZWluZyBtdWx0aXBsZSBleGVjdXRpb25zIG9mIHRoZVxuICogc2FtZSBtZXRob2QgbW9yZSB0aGFuIG9uY2UsIGJ1dCB3aWxsIHN0aWxsIHJ1biB0aGVtIGltbWVkaWF0ZWx5IGluIGFuIGV4Y2x1c2l2ZSBzZXF1ZW50aWFsIG1hbm5lci5cbiAqXG4gKiBUaGUgbW9zdCByZWNlbnQgaW52b2NhdGlvbiBvZiB0aGUgZnVuY3Rpb24gd2lsbCBiZSB0aGUgcGFyYW1ldGVycyB0aGF0IGdldCBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uXG4gKiB3aGVuIGl0IGludm9rZXMuXG4gKlxuICogVGhlIGZ1bmN0aW9uIHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbmV4dCBleGNsdXNpdmUgZXhlY3V0aW9uIGNvbXBsZXRlcy5cbiAqXG4gKiBVc2FnZSBhcyBmdW5jdGlvbjpcbiAqICAgY29uc3QgZGVib3VuY2VkRm4gPSBkZWJvdW5jZShteUZ1bmN0aW9uLCAyNTApO1xuICpcbiAqIFVzYWdlIGFzIGRlY29yYXRvcjpcbiAqICAgQGRlYm91bmNlKDI1MClcbiAqICAgbXlNZXRob2QoKSB7IC4uLiB9XG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbnxudW1iZXJ9IGNhbGxiYWNrX29yX2RlbGF5IFRoZSBjYWxsYmFjayBmdW5jdGlvbiBPUiBkZWxheSB3aGVuIHVzZWQgYXMgZGVjb3JhdG9yXG4gKiBAcGFyYW0ge251bWJlcn0gZGVsYXkgVGhlIGRlbGF5IGluIG1pbGxpc2Vjb25kcyBiZWZvcmUgc3Vic2VxdWVudCBpbnZvY2F0aW9uc1xuICogQHBhcmFtIHtib29sZWFufSBpbW1lZGlhdGUgaWYgdHJ1ZSwgdGhlIGZpcnN0IHRpbWUgdGhlIGFjdGlvbiBpcyBjYWxsZWQsIHRoZSBjYWxsYmFjayBleGVjdXRlcyBpbW1lZGlhdGVseVxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRoYXQgd2hlbiBpbnZva2VkLCBydW5zIHRoZSBjYWxsYmFjayBpbW1lZGlhdGVseSBhbmQgZXhjbHVzaXZlbHksXG4gKlxuICogQGRlY29yYXRvclxuICovXG5mdW5jdGlvbiBkZWJvdW5jZShjYWxsYmFja19vcl9kZWxheSwgZGVsYXksIGltbWVkaWF0ZSA9IGZhbHNlKSB7XG4gICAgLy8gRGVjb3JhdG9yIHVzYWdlOiBAZGVib3VuY2UoMjUwKSBvciBAZGVib3VuY2UoMjUwLCB0cnVlKVxuICAgIC8vIEZpcnN0IGFyZ3VtZW50IGlzIGEgbnVtYmVyICh0aGUgZGVsYXkpLCByZXR1cm5zIGRlY29yYXRvciBmdW5jdGlvblxuICAgIGlmICh0eXBlb2YgY2FsbGJhY2tfb3JfZGVsYXkgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbnN0IGRlY29yYXRvcl9kZWxheSA9IGNhbGxiYWNrX29yX2RlbGF5O1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JfaW1tZWRpYXRlID0gZGVsYXkgfHwgZmFsc2U7XG5cbiAgICAgICAgLy8gVEMzOSBkZWNvcmF0b3IgZm9ybTogcmVjZWl2ZXMgKHZhbHVlLCBjb250ZXh0KVxuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBjb250ZXh0KSB7XG4gICAgICAgICAgICBpZiAoY29udGV4dC5raW5kID09PSAnbWV0aG9kJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBkZWJvdW5jZV9pbXBsKHZhbHVlLCBkZWNvcmF0b3JfZGVsYXksIGRlY29yYXRvcl9pbW1lZGlhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZ1bmN0aW9uIHVzYWdlOiBkZWJvdW5jZShmbiwgMjUwKVxuICAgIC8vIEZpcnN0IGFyZ3VtZW50IGlzIGEgZnVuY3Rpb24gKHRoZSBjYWxsYmFjaylcbiAgICBjb25zdCBjYWxsYmFjayA9IGNhbGxiYWNrX29yX2RlbGF5O1xuICAgIHJldHVybiBkZWJvdW5jZV9pbXBsKGNhbGxiYWNrLCBkZWxheSwgaW1tZWRpYXRlKTtcbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiBkZWJvdW5jZSBsb2dpY1xuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2VfaW1wbChjYWxsYmFjaywgZGVsYXksIGltbWVkaWF0ZSA9IGZhbHNlKSB7XG4gICAgbGV0IHJ1bm5pbmcgPSBmYWxzZTtcbiAgICBsZXQgcXVldWVkID0gZmFsc2U7XG4gICAgbGV0IGxhc3RfZW5kX3RpbWUgPSAwOyAvLyB0aW1lc3RhbXAgb2YgbGFzdCBjb21wbGV0ZWQgcnVuXG4gICAgbGV0IHRpbWVyID0gbnVsbDtcblxuICAgIGxldCBuZXh0X2FyZ3MgPSBbXTtcbiAgICBsZXQgbmV4dF9jb250ZXh0ID0gbnVsbDtcbiAgICBsZXQgcmVzb2x2ZV9xdWV1ZSA9IFtdO1xuICAgIGxldCByZWplY3RfcXVldWUgPSBbXTtcblxuICAgIGNvbnN0IHJ1bl9mdW5jdGlvbiA9IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgdGhlc2VfcmVzb2x2ZXMgPSByZXNvbHZlX3F1ZXVlO1xuICAgICAgICBjb25zdCB0aGVzZV9yZWplY3RzID0gcmVqZWN0X3F1ZXVlO1xuICAgICAgICBjb25zdCBhcmdzID0gbmV4dF9hcmdzO1xuICAgICAgICBjb25zdCBjb250ZXh0ID0gbmV4dF9jb250ZXh0O1xuXG4gICAgICAgIHJlc29sdmVfcXVldWUgPSBbXTtcbiAgICAgICAgcmVqZWN0X3F1ZXVlID0gW107XG4gICAgICAgIG5leHRfYXJncyA9IFtdO1xuICAgICAgICBuZXh0X2NvbnRleHQgPSBudWxsO1xuICAgICAgICBxdWV1ZWQgPSBmYWxzZTtcbiAgICAgICAgcnVubmluZyA9IHRydWU7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGNhbGxiYWNrLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgZm9yIChjb25zdCByZXNvbHZlIG9mIHRoZXNlX3Jlc29sdmVzKSByZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgZm9yIChjb25zdCByZWplY3Qgb2YgdGhlc2VfcmVqZWN0cykgcmVqZWN0KGVycik7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgICAgICAgICBsYXN0X2VuZF90aW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgIGlmIChxdWV1ZWQpIHtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICAgICAgICAgIHRpbWVyID0gc2V0VGltZW91dChydW5fZnVuY3Rpb24sIE1hdGgubWF4KGRlbGF5LCAwKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRpbWVyID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbmV4dF9hcmdzID0gYXJncztcbiAgICAgICAgbmV4dF9jb250ZXh0ID0gdGhpcztcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgcmVzb2x2ZV9xdWV1ZS5wdXNoKHJlc29sdmUpO1xuICAgICAgICAgICAgcmVqZWN0X3F1ZXVlLnB1c2gocmVqZWN0KTtcblxuICAgICAgICAgICAgLy8gTm90aGluZyBydW5uaW5nIGFuZCBub3RoaW5nIHNjaGVkdWxlZFxuICAgICAgICAgICAgaWYgKCFydW5uaW5nICYmICF0aW1lcikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0X2NhbGwgPSBsYXN0X2VuZF90aW1lID09PSAwO1xuXG4gICAgICAgICAgICAgICAgaWYgKGltbWVkaWF0ZSAmJiBmaXJzdF9jYWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bl9mdW5jdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3Qgc2luY2UgPSBmaXJzdF9jYWxsID8gSW5maW5pdHkgOiBEYXRlLm5vdygpIC0gbGFzdF9lbmRfdGltZTtcbiAgICAgICAgICAgICAgICBpZiAoc2luY2UgPj0gZGVsYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgcnVuX2Z1bmN0aW9uKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgd2FpdCA9IE1hdGgubWF4KGRlbGF5IC0gc2luY2UsIDApO1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICAgICAgICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQocnVuX2Z1bmN0aW9uLCB3YWl0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB3ZSdyZSBhbHJlYWR5IHJ1bm5pbmcgb3IgYSB0aW1lciBleGlzdHMsIGp1c3QgbWFyayBxdWV1ZWQuXG4gICAgICAgICAgICAvLyBUaGUgZmluYWxseXt9IG9mIHJ1bl9mdW5jdGlvbiBoYW5kbGVzIHNjaGVkdWxpbmcgYWZ0ZXIgZnVsbCBkZWxheS5cbiAgICAgICAgICAgIHF1ZXVlZCA9IHRydWU7XG4gICAgICAgIH0pO1xuICAgIH07XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJFQUQtV1JJVEUgTE9DSyBGVU5DVElPTlMgLSBEZWxlZ2F0ZWQgdG8gUmVhZFdyaXRlTG9jayBjbGFzc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEFjcXVpcmUgYW4gZXhjbHVzaXZlIHdyaXRlIGxvY2sgYnkgbmFtZS5cbiAqIE9ubHkgb25lIHdyaXRlciBydW5zIGF0IGEgdGltZTsgYmxvY2tzIHJlYWRlcnMgdW50aWwgZmluaXNoZWQuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHsoKSA9PiBhbnl8UHJvbWlzZTxhbnk+fSBjYlxuICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAqL1xuZnVuY3Rpb24gcndsb2NrKG5hbWUsIGNiKSB7XG4gICAgcmV0dXJuIFJlYWRXcml0ZUxvY2suYWNxdWlyZShuYW1lLCBjYik7XG59XG5cbi8qKlxuICogQWNxdWlyZSBhIHNoYXJlZCByZWFkIGxvY2sgYnkgbmFtZS5cbiAqIE11bHRpcGxlIHJlYWRlcnMgcnVuIGluIHBhcmFsbGVsLCBidXQgcmVhZGVycyBhcmUgYmxvY2tlZCBieSBxdWV1ZWQvYWN0aXZlIHdyaXRlcnMuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICogQHBhcmFtIHsoKSA9PiBhbnl8UHJvbWlzZTxhbnk+fSBjYlxuICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAqL1xuZnVuY3Rpb24gcndsb2NrX3JlYWQobmFtZSwgY2IpIHtcbiAgICByZXR1cm4gUmVhZFdyaXRlTG9jay5hY3F1aXJlX3JlYWQobmFtZSwgY2IpO1xufVxuXG4vKipcbiAqIEZvcmNlZnVsbHkgY2xlYXIgYWxsIGxvY2tzIGFuZCBxdWV1ZXMgZm9yIGEgZ2l2ZW4gbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKi9cbmZ1bmN0aW9uIHJ3bG9ja19mb3JjZV91bmxvY2sobmFtZSkge1xuICAgIFJlYWRXcml0ZUxvY2suZm9yY2VfdW5sb2NrKG5hbWUpO1xufVxuXG4vKipcbiAqIEluc3BlY3QgbG9jayBzdGF0ZSBmb3IgZGVidWdnaW5nLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHt7cmVhZGVyczpudW1iZXIsIHdyaXRlcl9hY3RpdmU6Ym9vbGVhbiwgcmVhZGVyX3E6bnVtYmVyLCB3cml0ZXJfcTpudW1iZXJ9fVxuICovXG5mdW5jdGlvbiByd2xvY2tfcGVuZGluZyhuYW1lKSB7XG4gICAgcmV0dXJuIFJlYWRXcml0ZUxvY2sucGVuZGluZyhuYW1lKTtcbn1cbiIsIi8qXG4gKiBDb3JlIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgdHlwZSBjaGVja2luZywgdHlwZSBjb252ZXJzaW9uLCBzdHJpbmcgbWFuaXB1bGF0aW9uLFxuICogYW5kIG9iamVjdC9hcnJheSB1dGlsaXRpZXMuIFRoZXkgbWlycm9yIGZ1bmN0aW9uYWxpdHkgZnJvbSBQSFAgZnVuY3Rpb25zLlxuICpcbiAqIE90aGVyIHV0aWxpdHkgZnVuY3Rpb25zIGFyZSBvcmdhbml6ZWQgaW46XG4gKiAtIGFzeW5jLmpzOiBBc3luYyB1dGlsaXRpZXMgKHNsZWVwLCBkZWJvdW5jZSwgbXV0ZXgpXG4gKiAtIGJyb3dzZXIuanM6IEJyb3dzZXIvRE9NIHV0aWxpdGllcyAoaXNfbW9iaWxlLCBzY3JvbGwgZnVuY3Rpb25zKVxuICogLSBkYXRldGltZS5qczogRGF0ZS90aW1lIHV0aWxpdGllc1xuICogLSBoYXNoLmpzOiBIYXNoaW5nIGFuZCBjb21wYXJpc29uXG4gKiAtIGVycm9yLmpzOiBFcnJvciBoYW5kbGluZ1xuICovXG5cbi8vIFRvZG86IHRlc3QgdGhhdCBwcm9kIGJ1aWxkIGlkZW50aWZpZXMgYW5kIHJlbW92ZXMgdW5jYWxsZWQgZnVuY3Rpb25zIGZyb20gdGhlIGZpbmFsIGJ1bmRsZS5cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ09OU1RBTlRTIEFORCBIRUxQRVJTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8vIERlZmluZSBjb21tb25seSB1c2VkIGNvbnN0YW50c1xuY29uc3QgdW5kZWYgPSAndW5kZWZpbmVkJztcblxuLyoqXG4gKiBJdGVyYXRlcyBvdmVyIGFycmF5cyBvciBvYmplY3RzIHdpdGggcHJvbWlzZSBzdXBwb3J0XG4gKlxuICogV29ya3Mgd2l0aCBib3RoIHN5bmNocm9ub3VzIGFuZCBhc3luY2hyb25vdXMgY2FsbGJhY2tzLiBJZiB0aGUgY2FsbGJhY2tcbiAqIHJldHVybnMgcHJvbWlzZXMsIHRoZXkgYXJlIGV4ZWN1dGVkIGluIHBhcmFsbGVsIGFuZCB0aGlzIGZ1bmN0aW9uIHJldHVybnNcbiAqIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIHBhcmFsbGVsIHRhc2tzIGNvbXBsZXRlLlxuICpcbiAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBvYmogLSBDb2xsZWN0aW9uIHRvIGl0ZXJhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIC0gRnVuY3Rpb24gdG8gY2FsbCBmb3IgZWFjaCBpdGVtICh2YWx1ZSwga2V5KSAtIGNhbiBiZSBhc3luY1xuICogQHJldHVybnMge1Byb21pc2V8dW5kZWZpbmVkfSBQcm9taXNlIGlmIGFueSBjYWxsYmFja3MgcmV0dXJuIHByb21pc2VzLCB1bmRlZmluZWQgb3RoZXJ3aXNlXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFN5bmNocm9ub3VzIHVzYWdlXG4gKiBmb3JlYWNoKFsxLDIsM10sICh2YWwpID0+IGNvbnNvbGUubG9nKHZhbCkpO1xuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBBc3luY2hyb25vdXMgdXNhZ2UgLSB3YWl0cyBmb3IgYWxsIHRvIGNvbXBsZXRlXG4gKiBhd2FpdCBmb3JlYWNoKFsxLDIsM10sIGFzeW5jICh2YWwpID0+IHtcbiAqICAgICBhd2FpdCBmZXRjaCgnL2FwaS9wcm9jZXNzLycgKyB2YWwpO1xuICogfSk7XG4gKi9cbmZ1bmN0aW9uIGZvcmVhY2gob2JqLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBbXTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICAgICAgb2JqLmZvckVhY2goKHZhbHVlLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGNhbGxiYWNrKHZhbHVlLCBpbmRleCkpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKG9iaiAmJiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgICAgICBmb3IgKGxldCBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goY2FsbGJhY2sob2JqW2tleV0sIGtleSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmlsdGVyIGZvciBwcm9taXNlc1xuICAgIGNvbnN0IHByb21pc2VzID0gcmVzdWx0cy5maWx0ZXIoKHJlc3VsdCkgPT4gcmVzdWx0ICYmIHR5cGVvZiByZXN1bHQudGhlbiA9PT0gJ2Z1bmN0aW9uJyk7XG5cbiAgICAvLyBJZiB0aGVyZSBhcmUgYW55IHByb21pc2VzLCByZXR1cm4gUHJvbWlzZS5hbGwgdG8gd2FpdCBmb3IgYWxsIHRvIGNvbXBsZXRlXG4gICAgaWYgKHByb21pc2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKTtcbiAgICB9XG5cbiAgICAvLyBObyBwcm9taXNlcyByZXR1cm5lZCwgc28gd2UncmUgZG9uZVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG59XG5cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVFlQRSBDSEVDS0lORyBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBudW1lcmljXG4gKiBAcGFyYW0geyp9IG4gLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGEgZmluaXRlIG51bWJlclxuICovXG5mdW5jdGlvbiBpc19udW1lcmljKG4pIHtcbiAgICByZXR1cm4gIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGEgc3RyaW5nXG4gKiBAcGFyYW0geyp9IHMgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGEgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIGlzX3N0cmluZyhzKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBzID09ICdzdHJpbmcnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGFuIGludGVnZXJcbiAqIEBwYXJhbSB7Kn0gbiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYW4gaW50ZWdlclxuICovXG5mdW5jdGlvbiBpc19pbnRlZ2VyKG4pIHtcbiAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihuKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIHByb21pc2UtbGlrZSBvYmplY3RcbiAqIEBwYXJhbSB7Kn0gb2JqIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBoYXMgYSB0aGVuIG1ldGhvZFxuICovXG5mdW5jdGlvbiBpc19wcm9taXNlKG9iaikge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqID09ICdvYmplY3QnICYmIHR5cGVvZiBvYmoudGhlbiA9PSAnZnVuY3Rpb24nO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGFuIGFycmF5XG4gKiBAcGFyYW0geyp9IG9iaiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYW4gYXJyYXlcbiAqL1xuZnVuY3Rpb24gaXNfYXJyYXkob2JqKSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkob2JqKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhbiBvYmplY3QgKGV4Y2x1ZGVzIG51bGwpXG4gKiBAcGFyYW0geyp9IG9iaiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYW4gb2JqZWN0IGFuZCBub3QgbnVsbFxuICovXG5mdW5jdGlvbiBpc19vYmplY3Qob2JqKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIG9iaiAhPT0gbnVsbDtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIGZ1bmN0aW9uXG4gKiBAcGFyYW0geyp9IGZ1bmN0aW9uX3RvX2NoZWNrIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIGZ1bmN0aW9uXG4gKi9cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uKGZ1bmN0aW9uX3RvX2NoZWNrKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uX3RvX2NoZWNrICYmIHt9LnRvU3RyaW5nLmNhbGwoZnVuY3Rpb25fdG9fY2hlY2spID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHN0cmluZyBpcyBhIHZhbGlkIGVtYWlsIGFkZHJlc3NcbiAqIFVzZXMgYSBwcmFjdGljYWwgUkZDIDUzMjIgY29tcGxpYW50IHJlZ2V4IHRoYXQgbWF0Y2hlcyA5OS45OSUgb2YgcmVhbC13b3JsZCBlbWFpbCBhZGRyZXNzZXNcbiAqIEBwYXJhbSB7c3RyaW5nfSBlbWFpbCAtIEVtYWlsIGFkZHJlc3MgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBzdHJpbmcgaXMgYSB2YWxpZCBlbWFpbCBhZGRyZXNzXG4gKi9cbmZ1bmN0aW9uIGlzX2VtYWlsKGVtYWlsKSB7XG4gICAgaWYgKCFpc19zdHJpbmcoZW1haWwpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgcmVnZXggPSAvXlthLXowLTkhIyQlJicqKy89P15fYHt8fX4tXSsoPzpcXC5bYS16MC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKSpAKD86W2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pP1xcLikrW2EtejAtOV0oPzpbYS16MC05LV0qW2EtejAtOV0pPyQvaTtcbiAgICByZXR1cm4gcmVnZXgudGVzdChlbWFpbCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgZGVmaW5lZCAobm90IHVuZGVmaW5lZClcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdmFsdWUgaXMgbm90IHVuZGVmaW5lZFxuICovXG5mdW5jdGlvbiBpc3NldCh2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgIT0gdW5kZWY7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgZW1wdHkgKG51bGwsIHVuZGVmaW5lZCwgMCwgXCJcIiwgZW1wdHkgYXJyYXkvb2JqZWN0KVxuICogQHBhcmFtIHsqfSBvYmplY3QgLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGNvbnNpZGVyZWQgZW1wdHlcbiAqL1xuZnVuY3Rpb24gZW1wdHkob2JqZWN0KSB7XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gdW5kZWYpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChvYmplY3QgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09ICdzdHJpbmcnICYmIG9iamVjdCA9PSAnJykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA9PSAwO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiAhb2JqZWN0Lmxlbmd0aDtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBvYmplY3QgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAobGV0IGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgaWYgKG9iamVjdC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRZUEUgQ09OVkVSU0lPTiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHZhbHVlIHRvIGEgZmxvYXRpbmcgcG9pbnQgbnVtYmVyXG4gKiBSZXR1cm5zIDAgZm9yIG51bGwsIHVuZGVmaW5lZCwgTmFOLCBvciBub24tbnVtZXJpYyB2YWx1ZXNcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMge251bWJlcn0gRmxvYXRpbmcgcG9pbnQgbnVtYmVyXG4gKi9cbmZ1bmN0aW9uIGZsb2F0KHZhbCkge1xuICAgIC8vIEhhbmRsZSBudWxsLCB1bmRlZmluZWQsIGVtcHR5IHN0cmluZ1xuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQgfHwgdmFsID09PSAnJykge1xuICAgICAgICByZXR1cm4gMC4wO1xuICAgIH1cblxuICAgIC8vIFRyeSB0byBwYXJzZSB0aGUgdmFsdWVcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUZsb2F0KHZhbCk7XG5cbiAgICAvLyBDaGVjayBmb3IgTmFOIGFuZCByZXR1cm4gMCBpZiBwYXJzaW5nIGZhaWxlZFxuICAgIHJldHVybiBpc05hTihwYXJzZWQpID8gMC4wIDogcGFyc2VkO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgdmFsdWUgdG8gYW4gaW50ZWdlclxuICogUmV0dXJucyAwIGZvciBudWxsLCB1bmRlZmluZWQsIE5hTiwgb3Igbm9uLW51bWVyaWMgdmFsdWVzXG4gKiBAcGFyYW0geyp9IHZhbCAtIFZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IEludGVnZXIgdmFsdWVcbiAqL1xuZnVuY3Rpb24gaW50KHZhbCkge1xuICAgIC8vIEhhbmRsZSBudWxsLCB1bmRlZmluZWQsIGVtcHR5IHN0cmluZ1xuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQgfHwgdmFsID09PSAnJykge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gcGFyc2UgdGhlIHZhbHVlXG4gICAgY29uc3QgcGFyc2VkID0gcGFyc2VJbnQodmFsLCAxMCk7XG5cbiAgICAvLyBDaGVjayBmb3IgTmFOIGFuZCByZXR1cm4gMCBpZiBwYXJzaW5nIGZhaWxlZFxuICAgIHJldHVybiBpc05hTihwYXJzZWQpID8gMCA6IHBhcnNlZDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHZhbHVlIHRvIGEgc3RyaW5nXG4gKiBSZXR1cm5zIGVtcHR5IHN0cmluZyBmb3IgbnVsbCBvciB1bmRlZmluZWRcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gKi9cbmZ1bmN0aW9uIHN0cih2YWwpIHtcbiAgICAvLyBIYW5kbGUgbnVsbCBhbmQgdW5kZWZpbmVkIHNwZWNpYWxseVxuICAgIGlmICh2YWwgPT09IG51bGwgfHwgdmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIC8vIENvbnZlcnQgdG8gc3RyaW5nXG4gICAgcmV0dXJuIFN0cmluZyh2YWwpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIG51bWVyaWMgc3RyaW5ncyB0byBudW1iZXJzLCByZXR1cm5zIGFsbCBvdGhlciB2YWx1ZXMgdW5jaGFuZ2VkXG4gKiBVc2VkIHdoZW4geW91IG5lZWQgdG8gZW5zdXJlIG51bWVyaWMgdHlwZXMgYnV0IGRvbid0IHdhbnQgdG8gZm9yY2VcbiAqIGNvbnZlcnNpb24gb2Ygbm9uLW51bWVyaWMgdmFsdWVzICh3aGljaCB3b3VsZCBiZWNvbWUgMClcbiAqIEBwYXJhbSB7Kn0gdmFsIC0gVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMgeyp9IE51bWJlciBpZiBpbnB1dCB3YXMgbnVtZXJpYyBzdHJpbmcsIG90aGVyd2lzZSB1bmNoYW5nZWRcbiAqL1xuZnVuY3Rpb24gdmFsdWVfdW5sZXNzX251bWVyaWNfc3RyaW5nX3RoZW5fbnVtZXJpY192YWx1ZSh2YWwpIHtcbiAgICAvLyBJZiBpdCdzIGFscmVhZHkgYSBudW1iZXIsIHJldHVybiBpdFxuICAgIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gdmFsO1xuICAgIH1cblxuICAgIC8vIElmIGl0J3MgYSBzdHJpbmcgYW5kIG51bWVyaWMsIGNvbnZlcnQgaXRcbiAgICBpZiAoaXNfc3RyaW5nKHZhbCkgJiYgaXNfbnVtZXJpYyh2YWwpKSB7XG4gICAgICAgIC8vIFVzZSBwYXJzZUZsb2F0IHRvIGhhbmRsZSBib3RoIGludGVnZXJzIGFuZCBmbG9hdHNcbiAgICAgICAgcmV0dXJuIHBhcnNlRmxvYXQodmFsKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm4gZXZlcnl0aGluZyBlbHNlIHVuY2hhbmdlZCAobnVsbCwgb2JqZWN0cywgbm9uLW51bWVyaWMgc3RyaW5ncywgZXRjLilcbiAgICByZXR1cm4gdmFsO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBTVFJJTkcgTUFOSVBVTEFUSU9OIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIEVzY2FwZXMgSFRNTCBzcGVjaWFsIGNoYXJhY3RlcnMgKHVzZXMgTG9kYXNoIGVzY2FwZSlcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gZXNjYXBlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBIVE1MLWVzY2FwZWQgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIGh0bWwoc3RyKSB7XG4gICAgcmV0dXJuIF8uZXNjYXBlKHN0cik7XG59XG5cbi8qKlxuICogQ29udmVydHMgbmV3bGluZXMgdG8gSFRNTCBsaW5lIGJyZWFrc1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgd2l0aCBuZXdsaW5lcyByZXBsYWNlZCBieSA8YnIgLz5cbiAqL1xuZnVuY3Rpb24gbmwyYnIoc3RyKSB7XG4gICAgaWYgKHR5cGVvZiBzdHIgPT09IHVuZGVmIHx8IHN0ciA9PT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuICAgIHJldHVybiAoc3RyICsgJycpLnJlcGxhY2UoLyhbXj5cXHJcXG5dPykoXFxyXFxufFxcblxccnxcXHJ8XFxuKS9nLCAnJDE8YnIgLz4kMicpO1xufVxuXG4vKipcbiAqIEVzY2FwZXMgSFRNTCBhbmQgY29udmVydHMgbmV3bGluZXMgdG8gPGJyIC8+XG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gU3RyaW5nIHRvIHByb2Nlc3NcbiAqIEByZXR1cm5zIHtzdHJpbmd9IEhUTUwtZXNjYXBlZCBzdHJpbmcgd2l0aCBsaW5lIGJyZWFrc1xuICovXG5mdW5jdGlvbiBodG1sYnIoc3RyKSB7XG4gICAgcmV0dXJuIG5sMmJyKGh0bWwoc3RyKSk7XG59XG5cbi8qKlxuICogVVJMLWVuY29kZXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gZW5jb2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBVUkwtZW5jb2RlZCBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gdXJsZW5jb2RlKHN0cikge1xuICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQoc3RyKTtcbn1cblxuLyoqXG4gKiBVUkwtZGVjb2RlcyBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBkZWNvZGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFVSTC1kZWNvZGVkIHN0cmluZ1xuICovXG5mdW5jdGlvbiB1cmxkZWNvZGUoc3RyKSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzdHIpO1xufVxuXG4vKipcbiAqIEpTT04tZW5jb2RlcyBhIHZhbHVlXG4gKiBAcGFyYW0geyp9IHZhbHVlIC0gVmFsdWUgdG8gZW5jb2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBKU09OIHN0cmluZ1xuICovXG5mdW5jdGlvbiBqc29uX2VuY29kZSh2YWx1ZSkge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG59XG5cbi8qKlxuICogSlNPTi1kZWNvZGVzIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gSlNPTiBzdHJpbmcgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyB7Kn0gRGVjb2RlZCB2YWx1ZVxuICovXG5mdW5jdGlvbiBqc29uX2RlY29kZShzdHIpIHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xufVxuXG4vKipcbiAqIENvbnNvbGUgZGVidWcgb3V0cHV0IHdpdGggY2hhbm5lbCBmaWx0ZXJpbmdcbiAqIEFsaWFzIGZvciBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbCAtIERlYnVnIGNoYW5uZWwgbmFtZVxuICogQHBhcmFtIHsuLi4qfSB2YWx1ZXMgLSBWYWx1ZXMgdG8gbG9nXG4gKi9cbmZ1bmN0aW9uIGNvbnNvbGVfZGVidWcoY2hhbm5lbCwgLi4udmFsdWVzKSB7XG4gICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZyhjaGFubmVsLCAuLi52YWx1ZXMpO1xufVxuXG4vKipcbiAqIFJlcGxhY2VzIGFsbCBvY2N1cnJlbmNlcyBvZiBhIHN1YnN0cmluZyBpbiBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyAtIFN0cmluZyB0byBzZWFyY2ggaW5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzZWFyY2ggLSBTdWJzdHJpbmcgdG8gZmluZFxuICogQHBhcmFtIHtzdHJpbmd9IHJlcGxhY2UgLSBSZXBsYWNlbWVudCBzdWJzdHJpbmdcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFN0cmluZyB3aXRoIGFsbCBvY2N1cnJlbmNlcyByZXBsYWNlZFxuICovXG5mdW5jdGlvbiByZXBsYWNlX2FsbChzdHJpbmcsIHNlYXJjaCwgcmVwbGFjZSkge1xuICAgIGlmICghaXNfc3RyaW5nKHN0cmluZykpIHtcbiAgICAgICAgc3RyaW5nID0gc3RyaW5nICsgJyc7XG4gICAgfVxuICAgIHJldHVybiBzdHJpbmcuc3BsaXQoc2VhcmNoKS5qb2luKHJlcGxhY2UpO1xufVxuXG4vKipcbiAqIENhcGl0YWxpemVzIHRoZSBmaXJzdCBsZXR0ZXIgb2YgZWFjaCB3b3JkXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5wdXQgLSBTdHJpbmcgdG8gY2FwaXRhbGl6ZVxuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHdpdGggZmlyc3QgbGV0dGVyIG9mIGVhY2ggd29yZCBjYXBpdGFsaXplZFxuICovXG5mdW5jdGlvbiB1Y3dvcmRzKGlucHV0KSB7XG4gICAgcmV0dXJuIGlucHV0XG4gICAgICAgIC5zcGxpdCgnICcpXG4gICAgICAgIC5tYXAoKHdvcmQpID0+IHdvcmQuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyB3b3JkLnNsaWNlKDEpKVxuICAgICAgICAuam9pbignICcpO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBPQkpFQ1QgQU5EIEFSUkFZIFVUSUxJVElFU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vKipcbiAqIENvdW50cyB0aGUgbnVtYmVyIG9mIHByb3BlcnRpZXMgaW4gYW4gb2JqZWN0IG9yIGVsZW1lbnRzIGluIGFuIGFycmF5XG4gKiBAcGFyYW0ge09iamVjdHxBcnJheX0gbyAtIE9iamVjdCBvciBhcnJheSB0byBjb3VudFxuICogQHJldHVybnMge251bWJlcn0gTnVtYmVyIG9mIG93biBwcm9wZXJ0aWVzL2VsZW1lbnRzXG4gKi9cbmZ1bmN0aW9uIGNvdW50KG8pIHtcbiAgICBsZXQgYyA9IDA7XG4gICAgZm9yIChjb25zdCBrIGluIG8pIHtcbiAgICAgICAgaWYgKG8uaGFzT3duUHJvcGVydHkoaykpIHtcbiAgICAgICAgICAgICsrYztcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc2hhbGxvdyBjbG9uZSBvZiBhbiBvYmplY3QsIGFycmF5LCBvciBmdW5jdGlvblxuICogQHBhcmFtIHsqfSBvYmogLSBWYWx1ZSB0byBjbG9uZVxuICogQHJldHVybnMgeyp9IENsb25lZCB2YWx1ZVxuICovXG5mdW5jdGlvbiBjbG9uZShvYmopIHtcbiAgICBpZiAodHlwZW9mIEZ1bmN0aW9uLnByb3RvdHlwZS5fX2Nsb25lID09IHVuZGVmKSB7XG4gICAgICAgIEZ1bmN0aW9uLnByb3RvdHlwZS5fX2Nsb25lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy9odHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xODMzNTg4L2phdmFzY3JpcHQtY2xvbmUtYS1mdW5jdGlvblxuICAgICAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICBsZXQgdGVtcCA9IGZ1bmN0aW9uIGNsb25lZCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGZvciAobGV0IGtleSBpbiB0aGlzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB0ZW1wW2tleV0gPSB0aGlzW2tleV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRlbXA7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvYmogPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gb2JqLl9fY2xvbmUoKTtcbiAgICB9IGVsc2UgaWYgKG9iai5jb25zdHJ1Y3RvciAmJiBvYmouY29uc3RydWN0b3IgPT0gQXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIG9iai5zbGljZSgwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83MjgzNjAvaG93LWRvLWktY29ycmVjdGx5LWNsb25lLWEtamF2YXNjcmlwdC1vYmplY3QvMzAwNDI5NDgjMzAwNDI5NDhcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIG9iaik7XG4gICAgfVxufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IG5vbi1udWxsL3VuZGVmaW5lZCB2YWx1ZSBmcm9tIGFyZ3VtZW50c1xuICogQHBhcmFtIHsuLi4qfSBhcmd1bWVudHMgLSBWYWx1ZXMgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHsqfSBGaXJzdCBub24tbnVsbC91bmRlZmluZWQgdmFsdWUsIG9yIG51bGwgaWYgbm9uZSBmb3VuZFxuICovXG5mdW5jdGlvbiBjb2FsZXNjZSgpIHtcbiAgICBsZXQgYXJncyA9IEFycmF5LmZyb20oYXJndW1lbnRzKTtcbiAgICBsZXQgcmV0dXJuX3ZhbCA9IG51bGw7XG4gICAgYXJncy5mb3JFYWNoKGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgaWYgKHJldHVybl92YWwgPT09IG51bGwgJiYgdHlwZW9mIGFyZyAhPSB1bmRlZiAmJiBhcmcgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybl92YWwgPSBhcmc7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmV0dXJuX3ZhbDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBDU1Ygc3RyaW5nIHRvIGFycmF5LCB0cmltbWluZyBlYWNoIGVsZW1lbnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJfY3N2IC0gQ1NWIHN0cmluZyB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn0gQXJyYXkgb2YgdHJpbW1lZCB2YWx1ZXNcbiAqIEB0b2RvIEhhbmRsZSBxdW90ZWQvZXNjYXBlZCBjaGFyYWN0ZXJzXG4gKi9cbmZ1bmN0aW9uIGNzdl90b19hcnJheV90cmltKHN0cl9jc3YpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHN0cl9jc3Yuc3BsaXQoJywnKTtcbiAgICBjb25zdCByZXQgPSBbXTtcbiAgICBmb3JlYWNoKHBhcnRzLCAocGFydCkgPT4ge1xuICAgICAgICByZXQucHVzaChwYXJ0LnRyaW0oKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJldDtcbn1cbiIsIi8qKlxuICogUXVpbGwgRWRpdG9yIC0gVXRpbGl0eSBGdW5jdGlvbnNcbiAqXG4gKiBQcm92aWRlcyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3Igd29ya2luZyB3aXRoIFF1aWxsIGVkaXRvci5cbiAqL1xuXG4vKipcbiAqIEVuc3VyZXMgUXVpbGwgaXMgbG9hZGVkIGJlZm9yZSBleGVjdXRpbmcgY2FsbGJhY2tcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIC0gRnVuY3Rpb24gdG8gY2FsbCB3aGVuIFF1aWxsIGlzIHJlYWR5XG4gKi9cbmZ1bmN0aW9uIHF1aWxsX3JlYWR5KGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cuUXVpbGwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiBxdWlsbF9yZWFkeShjYWxsYmFjayksIDUwKTtcbiAgICB9XG59XG4iLCIvKipcbiAqIE1hbmlmZXN0IC0gSmF2YVNjcmlwdCBjbGFzcyByZWdpc3RyeSBhbmQgbWV0YWRhdGEgc3lzdGVtXG4gKlxuICogVGhpcyBjbGFzcyBtYWludGFpbnMgYSByZWdpc3RyeSBvZiBhbGwgSmF2YVNjcmlwdCBjbGFzc2VzIGluIHRoZSBidW5kbGUsXG4gKiB0cmFja2luZyB0aGVpciBuYW1lcyBhbmQgaW5oZXJpdGFuY2UgcmVsYXRpb25zaGlwcy4gSXQgcHJvdmlkZXMgdXRpbGl0aWVzXG4gKiBmb3Igd29ya2luZyB3aXRoIGNsYXNzIGhpZXJhcmNoaWVzIGFuZCBjYWxsaW5nIGluaXRpYWxpemF0aW9uIG1ldGhvZHMuXG4gKi9cbmNsYXNzIE1hbmlmZXN0IHtcbiAgICAvKipcbiAgICAgKiBEZWZpbmUgY2xhc3NlcyBpbiB0aGUgbWFuaWZlc3QgKGZyYW1ld29yayBpbnRlcm5hbClcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBpdGVtcyAtIEFycmF5IG9mIGNsYXNzIGRlZmluaXRpb25zIFtbQ2xhc3MsIFwiQ2xhc3NOYW1lXCIsIFBhcmVudENsYXNzLCBkZWNvcmF0b3JzXSwgLi4uXVxuICAgICAqL1xuICAgIHN0YXRpYyBfZGVmaW5lKGl0ZW1zKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGNsYXNzZXMgb2JqZWN0IGlmIG5vdCBhbHJlYWR5IGRlZmluZWRcbiAgICAgICAgaWYgKHR5cGVvZiBNYW5pZmVzdC5fY2xhc3NlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9jbGFzc2VzID0ge307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm9jZXNzIGVhY2ggY2xhc3MgZGVmaW5pdGlvblxuICAgICAgICBpdGVtcy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgICAgICBsZXQgY2xhc3Nfb2JqZWN0ID0gaXRlbVswXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19uYW1lID0gaXRlbVsxXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19leHRlbmRzID0gaXRlbVsyXSB8fCBudWxsO1xuICAgICAgICAgICAgbGV0IGRlY29yYXRvcnMgPSBpdGVtWzNdIHx8IG51bGw7XG5cbiAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBjbGFzcyBpbmZvcm1hdGlvbiAodXNpbmcgb2JqZWN0IHRvIGF2b2lkIGR1cGxpY2F0ZXMpXG4gICAgICAgICAgICBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXSA9IHtcbiAgICAgICAgICAgICAgICBjbGFzczogY2xhc3Nfb2JqZWN0LFxuICAgICAgICAgICAgICAgIG5hbWU6IGNsYXNzX25hbWUsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NfZXh0ZW5kcyxcbiAgICAgICAgICAgICAgICBkZWNvcmF0b3JzOiBkZWNvcmF0b3JzLCAgLy8gU3RvcmUgY29tcGFjdCBkZWNvcmF0b3IgZGF0YVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIG1ldGFkYXRhIHRvIHRoZSBjbGFzcyBvYmplY3QgaXRzZWxmXG4gICAgICAgICAgICBjbGFzc19vYmplY3QuX25hbWUgPSBjbGFzc19uYW1lO1xuICAgICAgICAgICAgY2xhc3Nfb2JqZWN0Ll9leHRlbmRzID0gY2xhc3NfZXh0ZW5kcztcbiAgICAgICAgICAgIGNsYXNzX29iamVjdC5fZGVjb3JhdG9ycyA9IGRlY29yYXRvcnM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBzdWJjbGFzcyBpbmRleCBhZnRlciBhbGwgY2xhc3NlcyBhcmUgZGVmaW5lZFxuICAgICAgICBNYW5pZmVzdC5fYnVpbGRfc3ViY2xhc3NfaW5kZXgoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiBpbmRleCBvZiBzdWJjbGFzc2VzIGZvciBlZmZpY2llbnQgbG9va3Vwc1xuICAgICAqIFRoaXMgY3JlYXRlcyBhIG1hcHBpbmcgd2hlcmUgZWFjaCBjbGFzcyBuYW1lIHBvaW50cyB0byBhbiBhcnJheSBvZiBhbGwgaXRzIHN1YmNsYXNzZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYnVpbGRfc3ViY2xhc3NfaW5kZXgoKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHN1YmNsYXNzIGluZGV4XG4gICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleCA9IHt9O1xuXG4gICAgICAgIC8vIFN0ZXAgdGhyb3VnaCBlYWNoIGNsYXNzIGFuZCB3YWxrIHVwIGl0cyBwYXJlbnQgY2hhaW5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBsZXQgY3VycmVudF9jbGFzc19uYW1lID0gY2xhc3NfbmFtZTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50X2NsYXNzZGF0YSA9IGNsYXNzZGF0YTtcblxuICAgICAgICAgICAgLy8gV2FsayB1cCB0aGUgcGFyZW50IGNoYWluIHVudGlsIHdlIHJlYWNoIHRoZSByb290XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudF9jbGFzc2RhdGEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHRlbmRzX25hbWUgPSBjdXJyZW50X2NsYXNzZGF0YS5leHRlbmRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuZHNfbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBwYXJlbnQncyBzdWJjbGFzcyBhcnJheSBpZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGNsYXNzIHRvIGl0cyBwYXJlbnQncyBzdWJjbGFzcyBsaXN0XG4gICAgICAgICAgICAgICAgICAgIGlmICghTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0uaW5jbHVkZXMoY2xhc3NfbmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdLnB1c2goY2xhc3NfbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBNb3ZlIHVwIHRvIHRoZSBwYXJlbnQncyBtZXRhZGF0YSAoaWYgaXQgZXhpc3RzIGluIG1hbmlmZXN0KVxuICAgICAgICAgICAgICAgICAgICBpZiAoTWFuaWZlc3QuX2NsYXNzZXNbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tleHRlbmRzX25hbWVdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFyZW50IG5vdCBpbiBtYW5pZmVzdCAoZS5nLiwgbmF0aXZlIEphdmFTY3JpcHQgY2xhc3MpLCBzdG9wIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3NkYXRhID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vIHBhcmVudCwgd2UndmUgcmVhY2hlZCB0aGUgcm9vdFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGEgZ2l2ZW4gYmFzZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gY2hlY2sgZm9yXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBvYmplY3RzIHdpdGgge2NsYXNzX25hbWUsIGNsYXNzX29iamVjdH0gZm9yIGNsYXNzZXMgdGhhdCBleHRlbmQgdGhlIGJhc2UgY2xhc3NcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2V4dGVuZGluZyhiYXNlX2NsYXNzKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIGNsYXNzIG9iamVjdCBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3Nfb2JqZWN0ID0gYmFzZV9jbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBiYXNlX2NsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgYmFzZV9jbGFzc19vYmplY3QgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShiYXNlX2NsYXNzKTtcbiAgICAgICAgICAgIGlmICghYmFzZV9jbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhc2UgY2xhc3Mgbm90IGZvdW5kOiAke2Jhc2VfY2xhc3N9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc2VzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBpZiAoTWFuaWZlc3QuanNfaXNfc3ViY2xhc3Nfb2YoY2xhc3NkYXRhLmNsYXNzLCBiYXNlX2NsYXNzX29iamVjdCkpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbGFzc19uYW1lOiBjbGFzc19uYW1lLFxuICAgICAgICAgICAgICAgICAgICBjbGFzc19vYmplY3Q6IGNsYXNzZGF0YS5jbGFzcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIGNsYXNzZXMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIGNsYXNzZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBjbGFzcyBpcyBhIHN1YmNsYXNzIG9mIGFub3RoZXIgY2xhc3NcbiAgICAgKiBNYXRjaGVzIFBIUCBNYW5pZmVzdDo6anNfaXNfc3ViY2xhc3Nfb2YoKSBzaWduYXR1cmUgYW5kIGJlaGF2aW9yXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IHN1YmNsYXNzIC0gVGhlIGNoaWxkIGNsYXNzIChvYmplY3Qgb3IgbmFtZSkgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gc3VwZXJjbGFzcyAtIFRoZSBwYXJlbnQgY2xhc3MgKG9iamVjdCBvciBuYW1lKSB0byBjaGVjayBhZ2FpbnN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgc3ViY2xhc3MgZXh0ZW5kcyBzdXBlcmNsYXNzIChkaXJlY3RseSBvciBpbmRpcmVjdGx5KVxuICAgICAqL1xuICAgIHN0YXRpYyBqc19pc19zdWJjbGFzc19vZihzdWJjbGFzcywgc3VwZXJjbGFzcykge1xuICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyBuYW1lcyB0byBjbGFzcyBvYmplY3RzXG4gICAgICAgIGxldCBzdWJjbGFzc19vYmplY3QgPSBzdWJjbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBzdWJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdCA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKHN1YmNsYXNzKTtcbiAgICAgICAgICAgIGlmICghc3ViY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdWJjbGFzcyAtIHJldHVybiBmYWxzZSBwZXIgc3BlY1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzdXBlcmNsYXNzX29iamVjdCA9IHN1cGVyY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2Ygc3VwZXJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1cGVyY2xhc3Nfb2JqZWN0ID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoc3VwZXJjbGFzcyk7XG4gICAgICAgICAgICBpZiAoIXN1cGVyY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdXBlcmNsYXNzIC0gZmFpbCBsb3VkIHBlciBzcGVjXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdXBlcmNsYXNzIG5vdCBmb3VuZCBpbiBtYW5pZmVzdDogJHtzdXBlcmNsYXNzfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2xhc3NlcyBhcmUgbm90IHN1YmNsYXNzZXMgb2YgdGhlbXNlbHZlc1xuICAgICAgICBpZiAoc3ViY2xhc3Nfb2JqZWN0ID09PSBzdXBlcmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2FsayB1cCB0aGUgaW5oZXJpdGFuY2UgY2hhaW5cbiAgICAgICAgbGV0IGN1cnJlbnRfY2xhc3MgPSBzdWJjbGFzc19vYmplY3Q7XG4gICAgICAgIHdoaWxlIChjdXJyZW50X2NsYXNzKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcyA9PT0gc3VwZXJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1vdmUgdXAgdG8gcGFyZW50IGNsYXNzXG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcy5fZXh0ZW5kcykge1xuICAgICAgICAgICAgICAgIC8vIF9leHRlbmRzIG1heSBiZSBhIHN0cmluZyBvciBjbGFzcyByZWZlcmVuY2VcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRfY2xhc3MuX2V4dGVuZHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShjdXJyZW50X2NsYXNzLl9leHRlbmRzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzID0gY3VycmVudF9jbGFzcy5fZXh0ZW5kcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhIGNsYXNzIGJ5IGl0cyBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzX25hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY2xhc3NcbiAgICAgKiBAcmV0dXJucyB7Q2xhc3N8bnVsbH0gVGhlIGNsYXNzIG9iamVjdCBvciBudWxsIGlmIG5vdCBmb3VuZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfY2xhc3NfYnlfbmFtZShjbGFzc19uYW1lKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMgfHwgIU1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXS5jbGFzcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHJlZ2lzdGVyZWQgY2xhc3Nlc1xuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIHtjbGFzc19uYW1lLCBjbGFzc19vYmplY3QsIGV4dGVuZHN9XG4gICAgICovXG4gICAgc3RhdGljIGdldF9hbGxfY2xhc3NlcygpIHtcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjbGFzc19uYW1lIGluIE1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgY2xhc3NfbmFtZTogY2xhc3NkYXRhLm5hbWUsXG4gICAgICAgICAgICAgICAgY2xhc3Nfb2JqZWN0OiBjbGFzc2RhdGEuY2xhc3MsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NkYXRhLmV4dGVuZHMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIHJlc3VsdHMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBidWlsZCBrZXkgZnJvbSB0aGUgYXBwbGljYXRpb24gY29uZmlndXJhdGlvblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBidWlsZCBrZXkgb3IgXCJOT0JVSUxEXCIgaWYgbm90IGF2YWlsYWJsZVxuICAgICAqL1xuICAgIHN0YXRpYyBidWlsZF9rZXkoKSB7XG4gICAgICAgIGlmICh3aW5kb3cucnN4YXBwICYmIHdpbmRvdy5yc3hhcHAuYnVpbGRfa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LnJzeGFwcC5idWlsZF9rZXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdOT0JVSUxEJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGVjb3JhdG9ycyBmb3IgYSBzcGVjaWZpYyBjbGFzcyBhbmQgbWV0aG9kXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kX25hbWUgLSBUaGUgbWV0aG9kIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8bnVsbH0gQXJyYXkgb2YgZGVjb3JhdG9yIG9iamVjdHMgb3IgbnVsbCBpZiBub25lIGZvdW5kXG4gICAgICovXG4gICAgc3RhdGljIGdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIC8vIENvbnZlcnQgY2xhc3Mgb2JqZWN0IHRvIG5hbWUgaWYgbmVlZGVkXG4gICAgICAgIGlmICh0eXBlb2YgY2xhc3NfbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNsYXNzX25hbWUgPSBjbGFzc19uYW1lLl9uYW1lIHx8IGNsYXNzX25hbWUubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsYXNzX2luZm8gPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgaWYgKCFjbGFzc19pbmZvIHx8ICFjbGFzc19pbmZvLmRlY29yYXRvcnMgfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9yc1ttZXRob2RfbmFtZV0pIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGNvbXBhY3QgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgICAgcmV0dXJuIE1hbmlmZXN0Ll90cmFuc2Zvcm1fZGVjb3JhdG9ycyhjbGFzc19pbmZvLmRlY29yYXRvcnNbbWV0aG9kX25hbWVdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIG1ldGhvZHMgd2l0aCBkZWNvcmF0b3JzIGZvciBhIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3Qgd2l0aCBtZXRob2QgbmFtZXMgYXMga2V5cyBhbmQgZGVjb3JhdG9yIGFycmF5cyBhcyB2YWx1ZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2FsbF9kZWNvcmF0b3JzKGNsYXNzX25hbWUpIHtcbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgaWYgKHR5cGVvZiBjbGFzc19uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY2xhc3NfbmFtZSA9IGNsYXNzX25hbWUuX25hbWUgfHwgY2xhc3NfbmFtZS5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xhc3NfaW5mbyA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICBpZiAoIWNsYXNzX2luZm8gfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9ycykge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGFsbCBkZWNvcmF0b3JzIGZyb20gY29tcGFjdCB0byBvYmplY3QgZm9ybWF0XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgICBmb3IgKGxldCBtZXRob2RfbmFtZSBpbiBjbGFzc19pbmZvLmRlY29yYXRvcnMpIHtcbiAgICAgICAgICAgIHJlc3VsdFttZXRob2RfbmFtZV0gPSBNYW5pZmVzdC5fdHJhbnNmb3JtX2RlY29yYXRvcnMoY2xhc3NfaW5mby5kZWNvcmF0b3JzW21ldGhvZF9uYW1lXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmFuc2Zvcm0gY29tcGFjdCBkZWNvcmF0b3IgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjb21wYWN0X2RlY29yYXRvcnMgLSBBcnJheSBvZiBbbmFtZSwgW2FyZ3NdXSB0dXBsZXNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIGRlY29yYXRvciBvYmplY3RzIHdpdGggbmFtZSBhbmQgYXJndW1lbnRzIHByb3BlcnRpZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJhbnNmb3JtX2RlY29yYXRvcnMoY29tcGFjdF9kZWNvcmF0b3JzKSB7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb21wYWN0X2RlY29yYXRvcnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcGFjdF9kZWNvcmF0b3JzLm1hcChkZWNvcmF0b3IgPT4ge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGVjb3JhdG9yKSAmJiBkZWNvcmF0b3IubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBkZWNvcmF0b3JbMF0sXG4gICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50czogZGVjb3JhdG9yWzFdIHx8IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEhhbmRsZSBtYWxmb3JtZWQgZGVjb3JhdG9yIGRhdGFcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ3Vua25vd24nLFxuICAgICAgICAgICAgICAgIGFyZ3VtZW50czogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgbWV0aG9kIGhhcyBhIHNwZWNpZmljIGRlY29yYXRvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfENsYXNzfSBjbGFzc19uYW1lIC0gVGhlIGNsYXNzIG5hbWUgb3IgY2xhc3Mgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZF9uYW1lIC0gVGhlIG1ldGhvZCBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRlY29yYXRvcl9uYW1lIC0gVGhlIGRlY29yYXRvciBuYW1lIHRvIGNoZWNrIGZvclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBtZXRob2QgaGFzIHRoZSBkZWNvcmF0b3JcbiAgICAgKi9cbiAgICBzdGF0aWMgaGFzX2RlY29yYXRvcihjbGFzc19uYW1lLCBtZXRob2RfbmFtZSwgZGVjb3JhdG9yX25hbWUpIHtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9ycyA9IE1hbmlmZXN0LmdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKTtcbiAgICAgICAgaWYgKCFkZWNvcmF0b3JzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGVjb3JhdG9ycy5zb21lKGQgPT4gZC5uYW1lID09PSBkZWNvcmF0b3JfbmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBzdWJjbGFzc2VzIG9mIGEgZ2l2ZW4gY2xhc3MgdXNpbmcgdGhlIHByZS1idWlsdCBpbmRleFxuICAgICAqIFRoaXMgaXMgdGhlIEphdmFTY3JpcHQgZXF1aXZhbGVudCBvZiBQSFAncyBNYW5pZmVzdDo6anNfZ2V0X3N1YmNsYXNzZXNfb2YoKVxuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gZ2V0IHN1YmNsYXNzZXMgb2ZcbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8Q2xhc3M+fSBBcnJheSBvZiBhY3R1YWwgY2xhc3Mgb2JqZWN0cyB0aGF0IGFyZSBzdWJjbGFzc2VzIG9mIHRoZSBiYXNlIGNsYXNzXG4gICAgICovXG4gICAgc3RhdGljIGpzX2dldF9zdWJjbGFzc2VzX29mKGJhc2VfY2xhc3MpIHtcbiAgICAgICAgLy8gSW5pdGlhbGl6ZSBpbmRleCBpZiBuZWVkZWRcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXgpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9idWlsZF9zdWJjbGFzc19pbmRleCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3NfbmFtZSA9IGJhc2VfY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2YgYmFzZV9jbGFzcyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGJhc2VfY2xhc3NfbmFtZSA9IGJhc2VfY2xhc3MuX25hbWUgfHwgYmFzZV9jbGFzcy5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGJhc2UgY2xhc3MgZXhpc3RzXG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXNbYmFzZV9jbGFzc19uYW1lXSkge1xuICAgICAgICAgICAgLy8gQmFzZSBjbGFzcyBub3QgaW4gbWFuaWZlc3QgLSByZXR1cm4gZW1wdHkgYXJyYXlcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCBzdWJjbGFzcyBuYW1lcyBmcm9tIHRoZSBpbmRleFxuICAgICAgICBjb25zdCBzdWJjbGFzc19uYW1lcyA9IE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtiYXNlX2NsYXNzX25hbWVdIHx8IFtdO1xuXG4gICAgICAgIC8vIENvbnZlcnQgbmFtZXMgdG8gYWN0dWFsIGNsYXNzIG9iamVjdHNcbiAgICAgICAgY29uc3Qgc3ViY2xhc3Nfb2JqZWN0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBzdWJjbGFzc19uYW1lIG9mIHN1YmNsYXNzX25hbWVzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tzdWJjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdHMucHVzaChjbGFzc2RhdGEuY2xhc3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU29ydCBieSBjbGFzcyBuYW1lIGZvciBkZXRlcm1pbmlzdGljIGJlaGF2aW9yXG4gICAgICAgIHN1YmNsYXNzX29iamVjdHMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgICAgICAgY29uc3QgbmFtZV9hID0gYS5fbmFtZSB8fCBhLm5hbWU7XG4gICAgICAgICAgICBjb25zdCBuYW1lX2IgPSBiLl9uYW1lIHx8IGIubmFtZTtcbiAgICAgICAgICAgIHJldHVybiBuYW1lX2EubG9jYWxlQ29tcGFyZShuYW1lX2IpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gc3ViY2xhc3Nfb2JqZWN0cztcbiAgICB9XG59XG5cbi8vIFJTWCBtYW5pZmVzdCBhdXRvbWF0aWNhbGx5IG1ha2VzIGNsYXNzZXMgZ2xvYmFsIC0gbm8gbWFudWFsIGFzc2lnbm1lbnQgbmVlZGVkXG4iLCIvKipcbiAqIFJzeF9CZWhhdmlvcnMgLSBDb3JlIEZyYW1ld29yayBVc2VyIEV4cGVyaWVuY2UgRW5oYW5jZW1lbnRzXG4gKlxuICogVGhpcyBjbGFzcyBwcm92aWRlcyBhdXRvbWF0aWMgcXVhbGl0eS1vZi1saWZlIGJlaGF2aW9ycyB0aGF0IGltcHJvdmUgdGhlIGRlZmF1bHRcbiAqIGJyb3dzZXIgZXhwZXJpZW5jZSBmb3IgUlNYIGFwcGxpY2F0aW9ucy4gVGhlc2UgYmVoYXZpb3JzIGFyZSB0cmFuc3BhcmVudCB0b1xuICogYXBwbGljYXRpb24gZGV2ZWxvcGVycyBhbmQgcnVuIGF1dG9tYXRpY2FsbHkgb24gZnJhbWV3b3JrIGluaXRpYWxpemF0aW9uLlxuICpcbiAqIFRoZXNlIGJlaGF2aW9ycyB1c2UgalF1ZXJ5IGV2ZW50IGRlbGVnYXRpb24gdG8gaGFuZGxlIGJvdGggZXhpc3RpbmcgYW5kIGR5bmFtaWNhbGx5XG4gKiBhZGRlZCBjb250ZW50LiBUaGV5IGFyZSBpbXBsZW1lbnRlZCB3aXRoIGxvdyBwcmlvcml0eSB0byBhbGxvdyBhcHBsaWNhdGlvbiBjb2RlIHRvXG4gKiBvdmVycmlkZSBkZWZhdWx0IGJlaGF2aW9ycyB3aGVuIG5lZWRlZC5cbiAqXG4gKiBAaW50ZXJuYWwgRnJhbWV3b3JrIHVzZSBvbmx5IC0gbm90IHBhcnQgb2YgcHVibGljIEFQSVxuICovXG5jbGFzcyBSc3hfQmVoYXZpb3JzIHtcbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2luaXQoKSB7XG4gICAgICAgIFJzeF9CZWhhdmlvcnMuX2luaXRfaWdub3JlX2ludmFsaWRfYW5jaG9yX2xpbmtzKCk7XG4gICAgICAgIFJzeF9CZWhhdmlvcnMuX3RyaW1fY29waWVkX3RleHQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAtIEFuY2hvciBsaW5rIGhhbmRsaW5nOiBQcmV2ZW50cyBicm9rZW4gXCIjXCIgbGlua3MgZnJvbSBjYXVzaW5nIHBhZ2UganVtcHMgb3IgVVJMIGNoYW5nZXNcbiAgICAgKiAtIElnbm9yZXMgXCIjXCIgKGVtcHR5IGhhc2gpIHRvIHByZXZlbnQgc2Nyb2xsLXRvLXRvcCBiZWhhdmlvclxuICAgICAqIC0gSWdub3JlcyBcIiNwbGFjZWhvbGRlcipcIiBsaW5rcyB1c2VkIGFzIHJvdXRlIHBsYWNlaG9sZGVycyBkdXJpbmcgZGV2ZWxvcG1lbnRcbiAgICAgKiAtIFZhbGlkYXRlcyBhbmNob3IgdGFyZ2V0cyBleGlzdCBiZWZvcmUgYWxsb3dpbmcgbmF2aWdhdGlvblxuICAgICAqIC0gUHJlc2VydmVzIG5vcm1hbCBhbmNob3IgYmVoYXZpb3Igd2hlbiB0YXJnZXRzIGV4aXN0XG4gICAgICovXG4gICAgc3RhdGljIF9pbml0X2lnbm9yZV9pbnZhbGlkX2FuY2hvcl9saW5rcygpIHtcbiAgICAgICAgcmV0dXJuOyAvLyBkaXNhYmxlZCBmb3Igbm93IC0gbWFrZSB0aGlzIGludG8gYSBjb25maWd1cmFibGUgb3B0aW9uXG5cbiAgICAgICAgLy8gVXNlIGV2ZW50IGRlbGVnYXRpb24gb24gZG9jdW1lbnQgdG8gaGFuZGxlIGFsbCBjdXJyZW50IGFuZCBmdXR1cmUgYW5jaG9yIGNsaWNrc1xuICAgICAgICAvLyBVc2UgbW91c2Vkb3duIGluc3RlYWQgb2YgY2xpY2sgdG8gcnVuIGJlZm9yZSBtb3N0IGFwcGxpY2F0aW9uIGhhbmRsZXJzXG4gICAgICAgICQoZG9jdW1lbnQpLm9uKCdtb3VzZWRvd24nLCAnYVtocmVmXj1cIiNcIl0nLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgY29uc3QgJGxpbmsgPSAkKHRoaXMpO1xuICAgICAgICAgICAgY29uc3QgaHJlZiA9ICRsaW5rLmF0dHIoJ2hyZWYnKTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgYW5vdGhlciBoYW5kbGVyIGhhcyBhbHJlYWR5IHByZXZlbnRlZCBkZWZhdWx0XG4gICAgICAgICAgICBpZiAoZS5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQWxsb3cgZGF0YS1yc3gtYWxsb3ctaGFzaCBhdHRyaWJ1dGUgdG8gYnlwYXNzIHRoaXMgYmVoYXZpb3JcbiAgICAgICAgICAgIGlmICgkbGluay5kYXRhKCdyc3gtYWxsb3ctaGFzaCcpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBIYW5kbGUgZW1wdHkgaGFzaCAtIHByZXZlbnQgc2Nyb2xsIHRvIHRvcFxuICAgICAgICAgICAgaWYgKGhyZWYgPT09ICcjJykge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSGFuZGxlIHBsYWNlaG9sZGVyIGxpbmtzIHVzZWQgZHVyaW5nIGRldmVsb3BtZW50XG4gICAgICAgICAgICBpZiAoaHJlZi5zdGFydHNXaXRoKCcjcGxhY2Vob2xkZXInKSkge1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICBlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRm9yIG90aGVyIGhhc2ggbGlua3MsIGNoZWNrIGlmIHRhcmdldCBleGlzdHNcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldElkID0gaHJlZi5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICBpZiAodGFyZ2V0SWQpIHtcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBmb3IgZWxlbWVudCB3aXRoIG1hdGNoaW5nIElEIG9yIG5hbWUgYXR0cmlidXRlXG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0RXhpc3RzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGFyZ2V0SWQpICE9PSBudWxsIHx8IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYFtuYW1lPVwiJHt0YXJnZXRJZH1cIl1gKSAhPT0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmICghdGFyZ2V0RXhpc3RzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRhcmdldCBkb2Vzbid0IGV4aXN0IC0gcHJldmVudCBuYXZpZ2F0aW9uXG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBUYXJnZXQgZXhpc3RzIC0gYWxsb3cgbm9ybWFsIGFuY2hvciBiZWhhdmlvclxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAtIENvcHkgdGV4dCB0cmltbWluZzogQXV0b21hdGljYWxseSByZW1vdmVzIGxlYWRpbmcvdHJhaWxpbmcgd2hpdGVzcGFjZSBmcm9tIGNvcGllZCB0ZXh0XG4gICAgICogLSBIb2xkIFNoaWZ0IHRvIHByZXNlcnZlIHdoaXRlc3BhY2VcbiAgICAgKiAtIFNraXBzIHRyaW1taW5nIGluIGNvZGUgYmxvY2tzLCB0ZXh0YXJlYXMsIGFuZCBjb250ZW50ZWRpdGFibGUgZWxlbWVudHNcbiAgICAgKi9cbiAgICBzdGF0aWMgX3RyaW1fY29waWVkX3RleHQoKSB7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NvcHknLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIC8vIERvbid0IHRyaW0gaWYgdXNlciBpcyBob2xkaW5nIFNoaWZ0IChhbGxvd3MgY29weWluZyB3aXRoIHdoaXRlc3BhY2UgaWYgbmVlZGVkKVxuICAgICAgICAgICAgaWYgKGV2ZW50LnNoaWZ0S2V5KSByZXR1cm47XG5cbiAgICAgICAgICAgIGxldCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBsZXQgc2VsZWN0ZWRfdGV4dCA9IHNlbGVjdGlvbi50b1N0cmluZygpO1xuXG4gICAgICAgICAgICAvLyBEb24ndCB0cmltIGlmIHNlbGVjdGlvbiBpcyBlbXB0eVxuICAgICAgICAgICAgaWYgKCFzZWxlY3RlZF90ZXh0KSByZXR1cm47XG5cbiAgICAgICAgICAgIC8vIERvbid0IHRyaW0gaWYgY29weWluZyBmcm9tIGNvZGUgYmxvY2tzLCB0ZXh0YXJlYXMsIG9yIGNvbnRlbnQtZWRpdGFibGUgKHByZXNlcnZlIGZvcm1hdHRpbmcpXG4gICAgICAgICAgICBsZXQgY29udGFpbmVyID0gc2VsZWN0aW9uLmdldFJhbmdlQXQoMCkuY29tbW9uQW5jZXN0b3JDb250YWluZXI7XG4gICAgICAgICAgICBpZiAoY29udGFpbmVyLm5vZGVUeXBlID09PSAzKSBjb250YWluZXIgPSBjb250YWluZXIucGFyZW50Tm9kZTsgLy8gVGV4dCBub2RlIHRvIGVsZW1lbnRcbiAgICAgICAgICAgIGlmIChjb250YWluZXIuY2xvc2VzdCgncHJlLCBjb2RlLCAuY29kZS1ibG9jaywgdGV4dGFyZWEsIFtjb250ZW50ZWRpdGFibGU9XCJ0cnVlXCJdJykpIHJldHVybjtcblxuICAgICAgICAgICAgbGV0IHRyaW1tZWRfdGV4dCA9IHNlbGVjdGVkX3RleHQudHJpbSgpO1xuXG4gICAgICAgICAgICAvLyBPbmx5IG1vZGlmeSBpZiB0aGVyZSdzIGFjdHVhbGx5IHdoaXRlc3BhY2UgdG8gdHJpbVxuICAgICAgICAgICAgaWYgKHRyaW1tZWRfdGV4dCAhPT0gc2VsZWN0ZWRfdGV4dCAmJiB0cmltbWVkX3RleHQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgZXZlbnQuY2xpcGJvYXJkRGF0YS5zZXREYXRhKCd0ZXh0L3BsYWluJywgdHJpbW1lZF90ZXh0KTtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnQ29weTogdHJpbW1lZCB3aGl0ZXNwYWNlIGZyb20gc2VsZWN0aW9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsIi8vIFNpbXBsZSBrZXkgdmFsdWUgY2FjaGUuICBDYW4gb25seSBzdG9yZSA1MDAwIGVudHJpZXMsIHdpbGwgcmVzZXQgYWZ0ZXIgNTAwMCBlbnRyaWVzLlxuXG4vLyBUb2RvOiBrZWVwIGxvY2FsIGNhY2hlIGNvbmNlcHQgdGhlIHNhbWUsIHJlcGxhY2UgZ2xvYmFsIGNhY2hlIGNvbmNlcHQgd2l0aCB0aGUgbm92IDIwMTkgdmVyc2lvbiBvZlxuLy8gc2Vzc2lvbiBjYWNoZS4gIFVzZSBhIHNlc3Npb24ga2V5ICYgYnVpbGQga2V5IHRvIHRyYWNrIGNhY2hlIGtleXMgc28gY2FjaGVkIHZhbHVlcyBvbmx5IGxhc3QgdW50aWwgdXNlciBsb2dzIG91dC5cbi8vIHJldmlldyBzZXNzaW9uIGNvZGUgdG8gZW5zdXJlIHRoYXQgc2Vzc2lvbiBrZXkgKmFsd2F5cyogcm90YXRlcyBvbiBsb2dvdXQuICBNYWtlIHNlc3Npb24gaWQgYSBwcm90ZWN0ZWQgdmFsdWUuXG5jbGFzcyBSc3hfQ2FjaGUge1xuICAgIHN0YXRpYyBvbl9jb3JlX2RlZmluZSgpIHtcbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzID0ge1xuICAgICAgICAgICAgZ2xvYmFsOiB7fSxcbiAgICAgICAgICAgIGluc3RhbmNlOiB7fSxcbiAgICAgICAgfTtcblxuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBBbGlhcyBmb3IgZ2V0X2luc3RhbmNlXG4gICAgc3RhdGljIGdldChrZXkpIHtcbiAgICAgICAgcmV0dXJuIFJzeF9DYWNoZS5nZXRfaW5zdGFuY2Uoa2V5KTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIGZyb20gdGhlIHBvb2wgb2YgY2FjaGVkIGRhdGEgZm9yIHRoaXMgJ2luc3RhbmNlJy4gIEFuIGluc3RhbmNlXG4gICAgLy8gaW4gdGhpcyBjYXNlIGlzIGEgdmlydHVhbCBwYWdlIGxvYWQgLyBuYXZpZ2F0aW9uIGluIHRoZSBTUEEuICBDYWxsIE1haW4ubGliLnJlc2V0KCkgdG8gcmVzZXQuXG4gICAgLy8gUmV0dXJucyBudWxsIG9uIGZhaWx1cmVcbiAgICBzdGF0aWMgZ2V0X2luc3RhbmNlKGtleSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBpZiAodHlwZW9mIENvcmVfQ2FjaGUuX2NhY2hlcy5pbnN0YW5jZVtrZXlfZW5jb2RlZF0gIT0gdW5kZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKENvcmVfQ2FjaGUuX2NhY2hlcy5pbnN0YW5jZVtrZXlfZW5jb2RlZF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBudWxsIG9uIGZhaWx1cmVcbiAgICAvLyBSZXR1cm5zIGEgY2FjaGVkIHZhbHVlIGZyb20gZ2xvYmFsIGNhY2hlICh1bmlxdWUgdG8gcGFnZSBsb2FkLCBzdXJ2aXZlcyByZXNldCgpKVxuICAgIHN0YXRpYyBnZXRfZ2xvYmFsKGtleSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBpZiAodHlwZW9mIENvcmVfQ2FjaGUuX2NhY2hlcy5nbG9iYWxba2V5X2VuY29kZWRdICE9IHVuZGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShDb3JlX0NhY2hlLl9jYWNoZXMuZ2xvYmFsW2tleV9lbmNvZGVkXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBTZXRzIGEgdmFsdWUgaW4gaW5zdGFuY2UgYW5kIGdsb2JhbCBjYWNoZSAobm90IHNoYXJlZCBiZXR3ZWVuIGJyb3dzZXIgdGFicylcbiAgICBzdGF0aWMgc2V0KGtleSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKE1haW4uZGVidWcoJ25vX2FwaV9jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiA2NCAqIDEwMjQpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ0NBQ0hFJywgJ1dhcm5pbmcgLSBub3QgY2FjaGluZyBsYXJnZSBjYWNoZSBlbnRyeScsIGtleSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlcy5nbG9iYWxba2V5X2VuY29kZWRdID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXMuaW5zdGFuY2Vba2V5X2VuY29kZWRdID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuXG4gICAgICAgIC8vIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoXCJDQUNIRVwiLCBcIlNldFwiLCBrZXksIHZhbHVlKTtcblxuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0Kys7XG5cbiAgICAgICAgLy8gUmVzZXQgY2FjaGUgYWZ0ZXIgNTAwMCBpdGVtcyBzZXRcbiAgICAgICAgaWYgKENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPiA1MDAwKSB7XG4gICAgICAgICAgICAvLyBHZXQgYW4gYWNjdXJhdGUgY291bnRcbiAgICAgICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPSBjb3VudChDb3JlX0NhY2hlLl9jYWNoZXMuZ2xvYmFsKTtcblxuICAgICAgICAgICAgaWYgKENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPiA1MDAwKSB7XG4gICAgICAgICAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzID0ge1xuICAgICAgICAgICAgICAgICAgICBnbG9iYWw6IHt9LFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZToge30sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybnMgbnVsbCBvbiBmYWlsdXJlXG4gICAgLy8gUmV0dXJucyBhIGNhY2hlZCB2YWx1ZSBmcm9tIHNlc3Npb24gY2FjaGUgKHNoYXJlZCBiZXR3ZWVuIGJyb3dzZXIgdGFicylcbiAgICBzdGF0aWMgZ2V0X3Nlc3Npb24oa2V5KSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJzeF9DYWNoZS5fc3VwcG9ydHNTdG9yYWdlKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBsZXQgcnMgPSBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKGtleV9lbmNvZGVkKTtcblxuICAgICAgICBpZiAoIWVtcHR5KHJzKSkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UocnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZXRzIGEgdmFsdWUgaW4gc2Vzc2lvbiBjYWNoZSAoc2hhcmVkIGJldHdlZW4gYnJvd3NlciB0YWJzKVxuICAgIHN0YXRpYyBzZXRfc2Vzc2lvbihrZXksIHZhbHVlLCBfdHJ5YWdhaW4gPSB0cnVlKSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+IDY0ICogMTAyNCkge1xuICAgICAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZygnQ0FDSEUnLCAnV2FybmluZyAtIG5vdCBjYWNoaW5nIGxhcmdlIGNhY2hlIGVudHJ5Jywga2V5KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghUnN4X0NhY2hlLl9zdXBwb3J0c1N0b3JhZ2UoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5yZW1vdmVJdGVtKGtleV9lbmNvZGVkKTtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0oa2V5X2VuY29kZWQsIEpTT04uc3RyaW5naWZ5KHZhbHVlKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChSc3hfQ2FjaGUuX2lzT3V0T2ZTcGFjZShlKSAmJiBzZXNzaW9uU3RvcmFnZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgIGlmIChfdHJ5YWdhaW4pIHtcbiAgICAgICAgICAgICAgICAgICAgQ29yZV9DYWNoZS5zZXRfc2Vzc2lvbihrZXksIHZhbHVlLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIF9yZXNldCgpIHtcbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzLmluc3RhbmNlID0ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yIGdpdmVuIGtleSBvZiBhbnkgdHlwZSBpbmNsdWRpbmcgYW4gb2JqZWN0LCByZXR1cm4gYSBzdHJpbmcgcmVwcmVzZW50aW5nXG4gICAgICogdGhlIGtleSB0aGF0IHRoZSBjYWNoZWQgdmFsdWUgc2hvdWxkIGJlIHN0b3JlZCBhcyBpbiBzZXNzaW9uc3RvcmFnZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZW5jb2Rla2V5KGtleSkge1xuICAgICAgICBjb25zdCBwcmVmaXggPSAnY2FjaGVfJztcblxuICAgICAgICAvLyBTZXNzaW9uIHJlaW1wbGVtZW50XG4gICAgICAgIC8vIHZhciBwcmVmaXggPSBcImNhY2hlX1wiICsgU3BhLnNlc3Npb24oKS51c2VyX2lkKCkgKyBcIl9cIjtcblxuICAgICAgICBpZiAoaXNfc3RyaW5nKGtleSkgJiYga2V5Lmxlbmd0aCA8IDE1MCAmJiBrZXkuaW5kZXhPZignICcpID09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgTWFuaWZlc3QuYnVpbGRfa2V5KCkgKyAnXycgKyBrZXk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgaGFzaChbTWFuaWZlc3QuYnVpbGRfa2V5KCksIGtleV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGV0ZXJtaW5lcyBpZiBzZXNzaW9uU3RvcmFnZSBpcyBzdXBwb3J0ZWQgaW4gdGhlIGJyb3dzZXI7XG4gICAgLy8gcmVzdWx0IGlzIGNhY2hlZCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlIGluc3RlYWQgb2YgYmVpbmcgcnVuIGVhY2ggdGltZS5cbiAgICAvLyBGZWF0dXJlIGRldGVjdGlvbiBpcyBiYXNlZCBvbiBob3cgTW9kZXJuaXpyIGRvZXMgaXQ7XG4gICAgLy8gaXQncyBub3Qgc3RyYWlnaHRmb3J3YXJkIGR1ZSB0byBGRjQgaXNzdWVzLlxuICAgIC8vIEl0J3Mgbm90IHJ1biBhdCBwYXJzZS10aW1lIGFzIGl0IHRha2VzIDIwMG1zIGluIEFuZHJvaWQuXG4gICAgLy8gQ29kZSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9wYW1lbGFmb3gvbHNjYWNoZS9ibG9iL21hc3Rlci9sc2NhY2hlLmpzLCBBcGFjaGUgTGljZW5zZSBQYW1lbGFmb3hcbiAgICBzdGF0aWMgX3N1cHBvcnRzU3RvcmFnZSgpIHtcbiAgICAgICAgbGV0IGtleSA9ICdfX2NhY2hldGVzdF9fJztcbiAgICAgICAgbGV0IHZhbHVlID0ga2V5O1xuXG4gICAgICAgIGlmIChSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNvbWUgYnJvd3NlcnMgd2lsbCB0aHJvdyBhbiBlcnJvciBpZiB5b3UgdHJ5IHRvIGFjY2VzcyBsb2NhbCBzdG9yYWdlIChlLmcuIGJyYXZlIGJyb3dzZXIpXG4gICAgICAgIC8vIGhlbmNlIGNoZWNrIGlzIGluc2lkZSBhIHRyeS9jYXRjaFxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCFzZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2UucmVtb3ZlSXRlbShrZXkpO1xuICAgICAgICAgICAgUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlID0gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gSWYgd2UgaGl0IHRoZSBsaW1pdCwgYW5kIHdlIGRvbid0IGhhdmUgYW4gZW1wdHkgc2Vzc2lvblN0b3JhZ2UgdGhlbiBpdCBtZWFucyB3ZSBoYXZlIHN1cHBvcnRcbiAgICAgICAgICAgIGlmIChSc3hfQ2FjaGUuX2lzT3V0T2ZTcGFjZShlKSAmJiBzZXNzaW9uU3RvcmFnZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgPSB0cnVlOyAvLyBqdXN0IG1heGVkIGl0IG91dCBhbmQgZXZlbiB0aGUgc2V0IHRlc3QgZmFpbGVkLlxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2U7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgdG8gc2V0IGlmIHRoZSBlcnJvciBpcyB1cyBkZWFsaW5nIHdpdGggYmVpbmcgb3V0IG9mIHNwYWNlXG4gICAgc3RhdGljIF9pc091dE9mU3BhY2UoZSkge1xuICAgICAgICByZXR1cm4gZSAmJiAoZS5uYW1lID09PSAnUVVPVEFfRVhDRUVERURfRVJSJyB8fCBlLm5hbWUgPT09ICdOU19FUlJPUl9ET01fUVVPVEFfUkVBQ0hFRCcgfHwgZS5uYW1lID09PSAnUXVvdGFFeGNlZWRlZEVycm9yJyk7XG4gICAgfVxufVxuIiwiLyoqXG4gKiBSc3hfSW5pdCAtIENvcmUgZnJhbWV3b3JrIGluaXRpYWxpemF0aW9uIGFuZCBlbnZpcm9ubWVudCB2YWxpZGF0aW9uXG4gKi9cbmNsYXNzIFJzeF9Jbml0IHtcbiAgICAvKipcbiAgICAgKiBDYWxsZWQgdmlhIFJzeC5fcnN4X2NvcmVfYm9vdFxuICAgICAqIEluaXRpYWxpemVzIHRoZSBjb3JlIGVudmlyb25tZW50IGFuZCBydW5zIGJhc2ljIHNhbml0eSBjaGVja3NcbiAgICAgKi9cbiAgICBzdGF0aWMgX29uX2ZyYW1ld29ya19jb3JlX2luaXQoKSB7XG4gICAgICAgIGlmICghUnN4LmlzX3Byb2QoKSkge1xuICAgICAgICAgICAgUnN4X0luaXQuX19lbnZpcm9ubWVudF9jaGVja3MoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERldmVsb3BtZW50IGVudmlyb25tZW50IGNoZWNrcyB0byBlbnN1cmUgcHJvcGVyIGNvbmZpZ3VyYXRpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgX19lbnZpcm9ubWVudF9jaGVja3MoKSB7XG4gICAgICAgIC8vIEZpbmQgYWxsIHNjcmlwdCB0YWdzIGluIHRoZSBET01cbiAgICAgICAgY29uc3Qgc2NyaXB0cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCdzY3JpcHQnKTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNjcmlwdHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IHNjcmlwdCA9IHNjcmlwdHNbaV07XG5cbiAgICAgICAgICAgIC8vIFNraXAgaW5saW5lIHNjcmlwdHMgKG5vIHNyYyBhdHRyaWJ1dGUpXG4gICAgICAgICAgICBpZiAoIXNjcmlwdC5zcmMpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgc2NyaXB0IGhhcyBkZWZlciBhdHRyaWJ1dGVcbiAgICAgICAgICAgIGlmICghc2NyaXB0LmRlZmVyKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3JjID0gc2NyaXB0LnNyYyB8fCAnKGlubGluZSBzY3JpcHQpJztcbiAgICAgICAgICAgICAgICBjb25zdCByZWFzb24gPSBgQWxsIHNjcmlwdCB0YWdzIHVzZWQgaW4gYW4gUlNwYWRlIHByb2plY3QgbXVzdCBoYXZlIGRlZmVyIGF0dHJpYnV0ZS4gRm91bmQgc2NyaXB0IHdpdGhvdXQgZGVmZXI6ICR7c3JjfWA7XG5cbiAgICAgICAgICAgICAgICAvLyBTdG9wIGZyYW1ld29yayBib290IHdpdGggcmVhc29uXG4gICAgICAgICAgICAgICAgUnN4Ll9yc3hfY29yZV9ib290X3N0b3AocmVhc29uKTtcblxuICAgICAgICAgICAgICAgIC8vIEFsc28gbG9nIHRvIGNvbnNvbGUgZm9yIHZpc2liaWxpdHlcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbUlNYIEJPT1QgU1RPUFBFRF0gJHtyZWFzb259YCk7XG5cbiAgICAgICAgICAgICAgICAvLyBTdG9wIGNoZWNraW5nIGFmdGVyIGZpcnN0IHZpb2xhdGlvblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn0iLCIvLyBARklMRS1TVUJDTEFTUy0wMS1FWENFUFRJT05cblxuLyoqXG4gKiBCYXNlIGNsYXNzIGZvciBKYXZhU2NyaXB0IE9STSBtb2RlbHNcbiAqXG4gKiBQcm92aWRlcyBjb3JlIGZ1bmN0aW9uYWxpdHkgZm9yIGZldGNoaW5nIHJlY29yZHMgZnJvbSBiYWNrZW5kIFBIUCBtb2RlbHMuXG4gKiBBbGwgbW9kZWwgc3R1YnMgZ2VuZXJhdGVkIGJ5IHRoZSBtYW5pZmVzdCBleHRlbmQgdGhpcyBiYXNlIGNsYXNzLlxuICpcbiAqIEV4YW1wbGUgdXNhZ2U6XG4gKiAgIC8vIEZldGNoIHNpbmdsZSByZWNvcmRcbiAqICAgY29uc3QgdXNlciA9IGF3YWl0IFVzZXJfTW9kZWwuZmV0Y2goMTIzKTtcbiAqXG4gKiAgIC8vIEZldGNoIG11bHRpcGxlIHJlY29yZHNcbiAqICAgY29uc3QgdXNlcnMgPSBhd2FpdCBVc2VyX01vZGVsLmZldGNoKFsxLCAyLCAzXSk7XG4gKlxuICogICAvLyBDcmVhdGUgaW5zdGFuY2Ugd2l0aCBkYXRhXG4gKiAgIGNvbnN0IHVzZXIgPSBuZXcgVXNlcl9Nb2RlbCh7aWQ6IDEsIG5hbWU6ICdKb2huJ30pO1xuICpcbiAqICBASW5zdGFudGlhdGFibGVcbiAqL1xuY2xhc3MgUnN4X0pzX01vZGVsIHtcbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3RvciAtIEluaXRpYWxpemUgbW9kZWwgaW5zdGFuY2Ugd2l0aCBkYXRhXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gZGF0YSAtIEtleS12YWx1ZSBwYWlycyB0byBwb3B1bGF0ZSB0aGUgbW9kZWxcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihkYXRhID0ge30pIHtcbiAgICAgICAgLy8gX19NT0RFTCBTWVNURU06IEVuYWJsZXMgYXV0b21hdGljIE9STSBpbnN0YW50aWF0aW9uIHdoZW4gZmV0Y2hpbmcgZnJvbSBQSFAgbW9kZWxzLlxuICAgICAgICAvLyBQSFAgbW9kZWxzIGFkZCBcIl9fTU9ERUxcIjogXCJDbGFzc05hbWVcIiB0byBKU09OLCBKYXZhU2NyaXB0IHVzZXMgaXQgdG8gY3JlYXRlIHByb3BlciBpbnN0YW5jZXMuXG4gICAgICAgIC8vIFRoaXMgcHJvdmlkZXMgdHlwZWQgbW9kZWwgb2JqZWN0cyBpbnN0ZWFkIG9mIHBsYWluIEpTT04sIHdpdGggbWV0aG9kcyBhbmQgdHlwZSBjaGVja2luZy5cblxuICAgICAgICAvLyBUaGlzIGNvbnN0cnVjdG9yIGZpbHRlcnMgb3V0IHRoZSBfX01PREVMIG1hcmtlciB0aGF0IHdhcyB1c2VkIHRvIGlkZW50aWZ5IHdoaWNoIGNsYXNzXG4gICAgICAgIC8vIHRvIGluc3RhbnRpYXRlLCBrZWVwaW5nIG9ubHkgdGhlIGFjdHVhbCBkYXRhIHByb3BlcnRpZXMgb24gdGhlIGluc3RhbmNlLlxuICAgICAgICBjb25zdCB7IF9fTU9ERUwsIC4uLm1vZGVsRGF0YSB9ID0gZGF0YTtcbiAgICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCBtb2RlbERhdGEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZldGNoIHJlY29yZChzKSBmcm9tIHRoZSBiYWNrZW5kIG1vZGVsXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBtaXJyb3JzIHRoZSBQSFAgTW9kZWw6OmZldGNoKCkgZnVuY3Rpb25hbGl0eS5cbiAgICAgKiBUaGUgYmFja2VuZCBtb2RlbCBtdXN0IGhhdmUgYSBmZXRjaCgpIG1ldGhvZCB3aXRoIHRoZVxuICAgICAqICNbQWpheF9FbmRwb2ludF9Nb2RlbF9GZXRjaF0gYW5ub3RhdGlvbiB0byBiZSBjYWxsYWJsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfEFycmF5fSBpZCAtIFNpbmdsZSBJRCBvciBhcnJheSBvZiBJRHMgdG8gZmV0Y2hcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gLSBTaW5nbGUgbW9kZWwgaW5zdGFuY2UsIGFycmF5IG9mIGluc3RhbmNlcywgb3IgZmFsc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgZmV0Y2goaWQpIHtcbiAgICAgICAgY29uc3QgQ3VycmVudENsYXNzID0gdGhpcztcbiAgICAgICAgLy8gR2V0IHRoZSBtb2RlbCBjbGFzcyBuYW1lIGZyb20gdGhlIGN1cnJlbnQgY2xhc3NcbiAgICAgICAgY29uc3QgbW9kZWxOYW1lID0gQ3VycmVudENsYXNzLm5hbWU7XG5cbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCAkLmFqYXgoe1xuICAgICAgICAgICAgdXJsOiBgL19mZXRjaC8ke21vZGVsTmFtZX1gLFxuICAgICAgICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICAgICAgICBkYXRhOiB7IGlkOiBpZCB9LFxuICAgICAgICAgICAgZGF0YVR5cGU6ICdqc29uJyxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gSGFuZGxlIHJlc3BvbnNlIGJhc2VkIG9uIHR5cGVcbiAgICAgICAgaWYgKHJlc3BvbnNlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXNlIF9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlIHRvIGhhbmRsZSBPUk0gaW5zdGFudGlhdGlvblxuICAgICAgICAvLyBUaGlzIHdpbGwgYXV0b21hdGljYWxseSBkZXRlY3QgX19NT0RFTCBwcm9wZXJ0aWVzIGFuZCBjcmVhdGUgYXBwcm9wcmlhdGUgaW5zdGFuY2VzXG4gICAgICAgIHJldHVybiBSc3hfSnNfTW9kZWwuX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUocmVzcG9uc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgbW9kZWwgY2xhc3MgbmFtZVxuICAgICAqIFVzZWQgaW50ZXJuYWxseSBmb3IgQVBJIGNhbGxzXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgY2xhc3MgbmFtZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRNb2RlbE5hbWUoKSB7XG4gICAgICAgIGNvbnN0IEN1cnJlbnRDbGFzcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBDdXJyZW50Q2xhc3MubmFtZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWZyZXNoIHRoaXMgaW5zdGFuY2Ugd2l0aCBsYXRlc3QgZGF0YSBmcm9tIHNlcnZlclxuICAgICAqXG4gICAgICogQHJldHVybnMge1Byb21pc2V9IFVwZGF0ZWQgaW5zdGFuY2Ugb3IgZmFsc2UgaWYgbm90IGZvdW5kXG4gICAgICovXG4gICAgYXN5bmMgcmVmcmVzaCgpIHtcbiAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgICAgIGlmICghdGhhdC5pZCkge1xuICAgICAgICAgICAgc2hvdWxkbnRfaGFwcGVuKCdDYW5ub3QgcmVmcmVzaCBtb2RlbCB3aXRob3V0IGlkIHByb3BlcnR5Jyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmcmVzaCA9IGF3YWl0IHRoYXQuY29uc3RydWN0b3IuZmV0Y2godGhhdC5pZCk7XG5cbiAgICAgICAgaWYgKGZyZXNoID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIHRoaXMgaW5zdGFuY2Ugd2l0aCBmcmVzaCBkYXRhXG4gICAgICAgIE9iamVjdC5hc3NpZ24odGhhdCwgZnJlc2gpO1xuICAgICAgICByZXR1cm4gdGhhdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IG1vZGVsIGluc3RhbmNlIHRvIHBsYWluIG9iamVjdFxuICAgICAqIFVzZWZ1bCBmb3Igc2VyaWFsaXphdGlvbiBvciBzZW5kaW5nIHRvIEFQSXNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFBsYWluIG9iamVjdCByZXByZXNlbnRhdGlvblxuICAgICAqL1xuICAgIHRvT2JqZWN0KCkge1xuICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgY29uc3Qgb2JqID0ge307XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHRoYXQpIHtcbiAgICAgICAgICAgIGlmICh0aGF0Lmhhc093blByb3BlcnR5KGtleSkgJiYgdHlwZW9mIHRoYXRba2V5XSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIG9ialtrZXldID0gdGhhdFtrZXldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCBtb2RlbCBpbnN0YW5jZSB0byBKU09OIHN0cmluZ1xuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ30gSlNPTiByZXByZXNlbnRhdGlvblxuICAgICAqL1xuICAgIHRvSlNPTigpIHtcbiAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGF0LnRvT2JqZWN0KCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlY3Vyc2l2ZWx5IGluc3RhbnRpYXRlIE9STSBtb2RlbHMgaW4gcmVzcG9uc2UgZGF0YVxuICAgICAqXG4gICAgICogTG9va3MgZm9yIG9iamVjdHMgd2l0aCBfX01PREVMIHByb3BlcnR5IGFuZCBpbnN0YW50aWF0ZXMgdGhlIGFwcHJvcHJpYXRlXG4gICAgICogSmF2YVNjcmlwdCBtb2RlbCBjbGFzcyBpZiBpdCBleGlzdHMgaW4gdGhlIGdsb2JhbCBzY29wZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gZGF0YSAtIFRoZSBkYXRhIHRvIHByb2Nlc3MgKGNhbiBiZSBhbnkgdHlwZSlcbiAgICAgKiBAcmV0dXJucyB7Kn0gVGhlIGRhdGEgd2l0aCBPUk0gb2JqZWN0cyBpbnN0YW50aWF0ZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUoZGF0YSkge1xuICAgICAgICAvLyBfX01PREVMIFNZU1RFTTogRW5hYmxlcyBhdXRvbWF0aWMgT1JNIGluc3RhbnRpYXRpb24gd2hlbiBmZXRjaGluZyBmcm9tIFBIUCBtb2RlbHMuXG4gICAgICAgIC8vIFBIUCBtb2RlbHMgYWRkIFwiX19NT0RFTFwiOiBcIkNsYXNzTmFtZVwiIHRvIEpTT04sIEphdmFTY3JpcHQgdXNlcyBpdCB0byBjcmVhdGUgcHJvcGVyIGluc3RhbmNlcy5cbiAgICAgICAgLy8gVGhpcyBwcm92aWRlcyB0eXBlZCBtb2RlbCBvYmplY3RzIGluc3RlYWQgb2YgcGxhaW4gSlNPTiwgd2l0aCBtZXRob2RzIGFuZCB0eXBlIGNoZWNraW5nLlxuXG4gICAgICAgIC8vIFRoaXMgcmVjdXJzaXZlIHByb2Nlc3NvciBzY2FucyBhbGwgQVBJIHJlc3BvbnNlIGRhdGEgbG9va2luZyBmb3IgX19NT0RFTCBtYXJrZXJzLlxuICAgICAgICAvLyBXaGVuIGZvdW5kLCBpdCBhdHRlbXB0cyB0byBpbnN0YW50aWF0ZSB0aGUgYXBwcm9wcmlhdGUgSmF2YVNjcmlwdCBtb2RlbCBjbGFzcyxcbiAgICAgICAgLy8gY29udmVydGluZyB7X19NT0RFTDogXCJVc2VyX01vZGVsXCIsIGlkOiAxLCBuYW1lOiBcIkpvaG5cIn0gaW50byBuZXcgVXNlcl9Nb2RlbCh7Li4ufSkuXG4gICAgICAgIC8vIFdvcmtzIHJlY3Vyc2l2ZWx5IHRocm91Z2ggYXJyYXlzIGFuZCBuZXN0ZWQgb2JqZWN0cyB0byBoYW5kbGUgY29tcGxleCBkYXRhIHN0cnVjdHVyZXMuXG4gICAgICAgIC8vIEhhbmRsZSBudWxsL3VuZGVmaW5lZFxuICAgICAgICBpZiAoZGF0YSA9PT0gbnVsbCB8fCBkYXRhID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIGFycmF5cyAtIHJlY3Vyc2l2ZWx5IHByb2Nlc3MgZWFjaCBlbGVtZW50XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgICAgICByZXR1cm4gZGF0YS5tYXAoKGl0ZW0pID0+IFJzeF9Kc19Nb2RlbC5faW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZShpdGVtKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW5kbGUgb2JqZWN0c1xuICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGlzIG9iamVjdCBoYXMgYSBfX01PREVMIHByb3BlcnR5XG4gICAgICAgICAgICBpZiAoZGF0YS5fX01PREVMICYmIHR5cGVvZiBkYXRhLl9fTU9ERUwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgLy8gVHJ5IHRvIGZpbmQgdGhlIG1vZGVsIGNsYXNzIGluIHRoZSBnbG9iYWwgc2NvcGVcbiAgICAgICAgICAgICAgICBjb25zdCBNb2RlbENsYXNzID0gd2luZG93W2RhdGEuX19NT0RFTF07XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgbW9kZWwgY2xhc3MgZXhpc3RzIGFuZCBleHRlbmRzIFJzeF9Kc19Nb2RlbCwgaW5zdGFudGlhdGUgaXRcbiAgICAgICAgICAgICAgICAvLyBEeW5hbWljIG1vZGVsIHJlc29sdXRpb24gcmVxdWlyZXMgY2hlY2tpbmcgY2xhc3MgZXhpc3RlbmNlIC0gQEpTLURFRkVOU0lWRS0wMS1FWENFUFRJT05cbiAgICAgICAgICAgICAgICBpZiAoTW9kZWxDbGFzcyAmJiBNb2RlbENsYXNzLnByb3RvdHlwZSBpbnN0YW5jZW9mIFJzeF9Kc19Nb2RlbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE1vZGVsQ2xhc3MoZGF0YSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZWN1cnNpdmVseSBwcm9jZXNzIGFsbCBvYmplY3QgcHJvcGVydGllc1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IFJzeF9Kc19Nb2RlbC5faW5zdGFudGlhdGVfbW9kZWxzX3JlY3Vyc2l2ZShkYXRhW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXR1cm4gcHJpbWl0aXZlIHZhbHVlcyBhcy1pc1xuICAgICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG59XG4iLCIvKipcbiAqIFZpZXdfVHJhbnNpdGlvbnMgLSBTbW9vdGggcGFnZS10by1wYWdlIHRyYW5zaXRpb25zIHVzaW5nIFZpZXcgVHJhbnNpdGlvbnMgQVBJXG4gKlxuICogRW5hYmxlcyBjcm9zcy1kb2N1bWVudCB2aWV3IHRyYW5zaXRpb25zIHNvIHRoZSBicm93c2VyIGRvZXNuJ3QgcGFpbnQgdGhlIG5ldyBwYWdlXG4gKiB1bnRpbCBpdCdzIHJlYWR5LCBjcmVhdGluZyBzbW9vdGggYW5pbWF0aW9ucyBiZXR3ZWVuIHBhZ2VzLlxuICpcbiAqIEZhbGxzIGJhY2sgZ3JhY2VmdWxseSBpZiBWaWV3IFRyYW5zaXRpb25zIEFQSSBpcyBub3QgYXZhaWxhYmxlLlxuICovXG5jbGFzcyBSc3hfVmlld19UcmFuc2l0aW9ucyB7XG4gICAgLyoqXG4gICAgICogQ2FsbGVkIGR1cmluZyBmcmFtZXdvcmsgY29yZSBpbml0IHBoYXNlXG4gICAgICogQ2hlY2tzIGZvciBWaWV3IFRyYW5zaXRpb25zIEFQSSBzdXBwb3J0IGFuZCBlbmFibGVzIGlmIGF2YWlsYWJsZVxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCgpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgVmlldyBUcmFuc2l0aW9ucyBBUEkgaXMgc3VwcG9ydGVkXG4gICAgICAgIGlmICghZG9jdW1lbnQuc3RhcnRWaWV3VHJhbnNpdGlvbikge1xuICAgICAgICAgICAgY29uc29sZV9kZWJ1ZygnVklFV19UUkFOU0lUSU9OUycsICdWaWV3IFRyYW5zaXRpb25zIEFQSSBub3Qgc3VwcG9ydGVkLCBza2lwcGluZycpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRW5hYmxlIGNyb3NzLWRvY3VtZW50IHZpZXcgdHJhbnNpdGlvbnMgdmlhIENTU1xuICAgICAgICBSc3hfVmlld19UcmFuc2l0aW9ucy5faW5qZWN0X3RyYW5zaXRpb25fY3NzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5qZWN0IENTUyB0byBlbmFibGUgY3Jvc3MtZG9jdW1lbnQgdmlldyB0cmFuc2l0aW9uc1xuICAgICAqXG4gICAgICogVGhlIEB2aWV3LXRyYW5zaXRpb24geyBuYXZpZ2F0aW9uOiBhdXRvOyB9IHJ1bGUgdGVsbHMgdGhlIGJyb3dzZXIgdG86XG4gICAgICogMS4gQ2FwdHVyZSBhIHNuYXBzaG90IG9mIHRoZSBjdXJyZW50IHBhZ2UgYmVmb3JlIG5hdmlnYXRpb25cbiAgICAgKiAyLiBGZXRjaCB0aGUgbmV3IHBhZ2VcbiAgICAgKiAzLiBXYWl0IHVudGlsIHRoZSBuZXcgcGFnZSBpcyBmdWxseSBsb2FkZWQgYW5kIHBhaW50ZWQgKGRvY3VtZW50LnJlYWR5KVxuICAgICAqIDQuIEFuaW1hdGUgc21vb3RobHkgYmV0d2VlbiB0aGUgdHdvIHN0YXRlc1xuICAgICAqXG4gICAgICogVGhpcyBwcmV2ZW50cyB0aGUgd2hpdGUgZmxhc2ggZHVyaW5nIG5hdmlnYXRpb24gYW5kIGNyZWF0ZXMgYXBwLWxpa2UgdHJhbnNpdGlvbnMuXG4gICAgICovXG4gICAgc3RhdGljIF9pbmplY3RfdHJhbnNpdGlvbl9jc3MoKSB7XG4gICAgICAgIGNvbnN0IHN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3R5bGUnKTtcblxuICAgICAgICBzdHlsZS50ZXh0Q29udGVudCA9IGBcbiAgICAgICAgICAgIEB2aWV3LXRyYW5zaXRpb24ge1xuICAgICAgICAgICAgICAgIG5hdmlnYXRpb246IGF1dG87XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qIERpc2FibGUgYW5pbWF0aW9uIC0gaW5zdGFudCB0cmFuc2l0aW9uICovXG4gICAgICAgICAgICA6OnZpZXctdHJhbnNpdGlvbi1ncm91cCgqKSxcbiAgICAgICAgICAgIDo6dmlldy10cmFuc2l0aW9uLW9sZCgqKSxcbiAgICAgICAgICAgIDo6dmlldy10cmFuc2l0aW9uLW5ldygqKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uLWR1cmF0aW9uOiAwcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgYDtcblxuICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHN0eWxlKTtcbiAgICB9XG59XG4iLCIvKipcbiAqIFJlYWRXcml0ZUxvY2sgaW1wbGVtZW50YXRpb24gZm9yIFJTcGFkZSBmcmFtZXdvcmtcbiAqIFByb3ZpZGVzIGV4Y2x1c2l2ZSAod3JpdGUpIGFuZCBzaGFyZWQgKHJlYWQpIGxvY2tpbmcgbWVjaGFuaXNtcyBmb3IgYXN5bmNocm9ub3VzIG9wZXJhdGlvbnNcbiAqL1xuY2xhc3MgUmVhZFdyaXRlTG9jayB7XG4gICAgc3RhdGljICNsb2NrcyA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIEdldCBvciBjcmVhdGUgYSBsb2NrIG9iamVjdCBmb3IgYSBnaXZlbiBuYW1lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgI2dldF9sb2NrKG5hbWUpIHtcbiAgICAgICAgbGV0IHMgPSB0aGlzLiNsb2Nrcy5nZXQobmFtZSk7XG4gICAgICAgIGlmICghcykge1xuICAgICAgICAgICAgcyA9IHsgcmVhZGVyczogMCwgd3JpdGVyX2FjdGl2ZTogZmFsc2UsIHJlYWRlcl9xOiBbXSwgd3JpdGVyX3E6IFtdIH07XG4gICAgICAgICAgICB0aGlzLiNsb2Nrcy5zZXQobmFtZSwgcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2NoZWR1bGUgdGhlIG5leHQgb3BlcmF0aW9uIGZvciBhIGxvY2tcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyAjc2NoZWR1bGUobmFtZSkge1xuICAgICAgICBjb25zdCBzID0gdGhpcy4jZ2V0X2xvY2sobmFtZSk7XG4gICAgICAgIGlmIChzLndyaXRlcl9hY3RpdmUgfHwgcy5yZWFkZXJzID4gMCkgcmV0dXJuO1xuXG4gICAgICAgIC8vIHJ1biBvbmUgd3JpdGVyIGlmIHF1ZXVlZFxuICAgICAgICBpZiAocy53cml0ZXJfcS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zdCB7IGNiLCByZXNvbHZlLCByZWplY3QgfSA9IHMud3JpdGVyX3Euc2hpZnQoKTtcbiAgICAgICAgICAgIHMud3JpdGVyX2FjdGl2ZSA9IHRydWU7XG4gICAgICAgICAgICBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgICAgICAgICAgIC50aGVuKGNiKVxuICAgICAgICAgICAgICAgIC50aGVuKHJlc29sdmUsIHJlamVjdClcbiAgICAgICAgICAgICAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHMud3JpdGVyX2FjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLiNzY2hlZHVsZShuYW1lKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG90aGVyd2lzZSBydW4gYWxsIHF1ZXVlZCByZWFkZXJzIGluIHBhcmFsbGVsXG4gICAgICAgIGlmIChzLnJlYWRlcl9xLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IGJhdGNoID0gcy5yZWFkZXJfcS5zcGxpY2UoMCk7XG4gICAgICAgICAgICBzLnJlYWRlcnMgKz0gYmF0Y2gubGVuZ3RoO1xuICAgICAgICAgICAgZm9yIChjb25zdCB7IGNiLCByZXNvbHZlLCByZWplY3QgfSBvZiBiYXRjaCkge1xuICAgICAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKGNiKVxuICAgICAgICAgICAgICAgICAgICAudGhlbihyZXNvbHZlLCByZWplY3QpXG4gICAgICAgICAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMucmVhZGVycyAtPSAxO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHMucmVhZGVycyA9PT0gMCkgdGhpcy4jc2NoZWR1bGUobmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWNxdWlyZSBhbiBleGNsdXNpdmUgbXV0ZXggbG9jayBieSBuYW1lLlxuICAgICAqIE9ubHkgb25lIHdyaXRlciBydW5zIGF0IGEgdGltZTsgYmxvY2tzIHJlYWRlcnMgdW50aWwgZmluaXNoZWQuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKiBAcGFyYW0geygpID0+IGFueXxQcm9taXNlPGFueT59IGNiXG4gICAgICogQHJldHVybnMge1Byb21pc2U8YW55Pn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYWNxdWlyZShuYW1lLCBjYikge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgcyA9IHRoaXMuI2dldF9sb2NrKG5hbWUpO1xuICAgICAgICAgICAgcy53cml0ZXJfcS5wdXNoKHsgY2IsIHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgIHRoaXMuI3NjaGVkdWxlKG5hbWUpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBY3F1aXJlIGEgc2hhcmVkIHJlYWQgbG9jayBieSBuYW1lLlxuICAgICAqIE11bHRpcGxlIHJlYWRlcnMgY2FuIHJ1biBpbiBwYXJhbGxlbDsgYmxvY2tzIHdoZW4gd3JpdGVyIGlzIGFjdGl2ZS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqIEBwYXJhbSB7KCkgPT4gYW55fFByb21pc2U8YW55Pn0gY2JcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxhbnk+fVxuICAgICAqL1xuICAgIHN0YXRpYyBhY3F1aXJlX3JlYWQobmFtZSwgY2IpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHMgPSB0aGlzLiNnZXRfbG9jayhuYW1lKTtcbiAgICAgICAgICAgIGlmIChzLndyaXRlcl9hY3RpdmUgfHwgcy53cml0ZXJfcS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgcy5yZWFkZXJfcS5wdXNoKHsgY2IsIHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4jc2NoZWR1bGUobmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzLnJlYWRlcnMgKz0gMTtcbiAgICAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAgICAgLnRoZW4oY2IpXG4gICAgICAgICAgICAgICAgLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KVxuICAgICAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcy5yZWFkZXJzIC09IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmIChzLnJlYWRlcnMgPT09IDApIHRoaXMuI3NjaGVkdWxlKG5hbWUpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JjZS11bmxvY2sgYSBtdXRleCAodXNlIHdpdGggY2F1dGlvbikuXG4gICAgICogQ29tcGxldGVseSByZW1vdmVzIHRoZSBsb2NrIHN0YXRlLCBwb3RlbnRpYWxseSBicmVha2luZyB3YWl0aW5nIG9wZXJhdGlvbnMuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAgICAgKi9cbiAgICBzdGF0aWMgZm9yY2VfdW5sb2NrKG5hbWUpIHtcbiAgICAgICAgdGhpcy4jbG9ja3MuZGVsZXRlKG5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBpbmZvcm1hdGlvbiBhYm91dCBwZW5kaW5nIG9wZXJhdGlvbnMgb24gYSBtdXRleC5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqIEByZXR1cm5zIHt7cmVhZGVyczogbnVtYmVyLCB3cml0ZXJfYWN0aXZlOiBib29sZWFuLCByZWFkZXJfcTogbnVtYmVyLCB3cml0ZXJfcTogbnVtYmVyfX1cbiAgICAgKi9cbiAgICBzdGF0aWMgcGVuZGluZyhuYW1lKSB7XG4gICAgICAgIGNvbnN0IHMgPSB0aGlzLiNsb2Nrcy5nZXQobmFtZSk7XG4gICAgICAgIGlmICghcykgcmV0dXJuIHsgcmVhZGVyczogMCwgd3JpdGVyX2FjdGl2ZTogZmFsc2UsIHJlYWRlcl9xOiAwLCB3cml0ZXJfcTogMCB9O1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcmVhZGVyczogcy5yZWFkZXJzLFxuICAgICAgICAgICAgd3JpdGVyX2FjdGl2ZTogcy53cml0ZXJfYWN0aXZlLFxuICAgICAgICAgICAgcmVhZGVyX3E6IHMucmVhZGVyX3EubGVuZ3RoLFxuICAgICAgICAgICAgd3JpdGVyX3E6IHMud3JpdGVyX3EubGVuZ3RoXG4gICAgICAgIH07XG4gICAgfVxufSIsIi8qKlxuICogRm9ybSB1dGlsaXRpZXMgZm9yIHZhbGlkYXRpb24gYW5kIGVycm9yIGhhbmRsaW5nXG4gKi9cbmNsYXNzIEZvcm1fVXRpbHMge1xuICAgIC8qKlxuICAgICAqIEZyYW1ld29yayBpbml0aWFsaXphdGlvbiBob29rIHRvIHJlZ2lzdGVyIGpRdWVyeSBwbHVnaW5cbiAgICAgKiBDcmVhdGVzICQuZm4uYWpheF9zdWJtaXQoKSBmb3IgZm9ybSBlbGVtZW50c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9kZWZpbmUocGFyYW1zID0ge30pIHtcbiAgICAgICAgJC5mbi5hamF4X3N1Ym1pdCA9IGZ1bmN0aW9uKG9wdGlvbnMgPSB7fSkge1xuICAgICAgICAgICAgY29uc3QgJGVsZW1lbnQgPSAkKHRoaXMpO1xuXG4gICAgICAgICAgICBpZiAoISRlbGVtZW50LmlzKCdmb3JtJykpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FqYXhfc3VibWl0KCkgY2FuIG9ubHkgYmUgY2FsbGVkIG9uIGZvcm0gZWxlbWVudHMnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgdXJsID0gJGVsZW1lbnQuYXR0cignYWN0aW9uJyk7XG4gICAgICAgICAgICBpZiAoIXVybCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRm9ybSBtdXN0IGhhdmUgYW4gYWN0aW9uIGF0dHJpYnV0ZScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCB7IGNvbnRyb2xsZXIsIGFjdGlvbiB9ID0gQWpheC5hamF4X3VybF90b19jb250cm9sbGVyX2FjdGlvbih1cmwpO1xuXG4gICAgICAgICAgICByZXR1cm4gRm9ybV9VdGlscy5hamF4X3N1Ym1pdCgkZWxlbWVudCwgY29udHJvbGxlciwgYWN0aW9uLCBvcHRpb25zKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93cyBmb3JtIHZhbGlkYXRpb24gZXJyb3JzXG4gICAgICpcbiAgICAgKiBSRVFVSVJFRCBIVE1MIFNUUlVDVFVSRTpcbiAgICAgKiBGb3IgaW5saW5lIGZpZWxkIGVycm9ycyB0byBkaXNwbGF5IHByb3Blcmx5LCBmb3JtIGZpZWxkcyBtdXN0IGZvbGxvdyB0aGlzIHN0cnVjdHVyZTpcbiAgICAgKlxuICAgICAqIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICogICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCIgZm9yPVwiZmllbGQtbmFtZVwiPkZpZWxkIExhYmVsPC9sYWJlbD5cbiAgICAgKiAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY29udHJvbFwiIGlkPVwiZmllbGQtbmFtZVwiIG5hbWU9XCJmaWVsZC1uYW1lXCIgdHlwZT1cInRleHRcIj5cbiAgICAgKiA8L2Rpdj5cbiAgICAgKlxuICAgICAqIEtleSByZXF1aXJlbWVudHM6XG4gICAgICogLSBXcmFwIGVhY2ggZmllbGQgaW4gYSBjb250YWluZXIgd2l0aCBjbGFzcyBcImZvcm0tZ3JvdXBcIiAob3IgXCJmb3JtLWNoZWNrXCIgLyBcImlucHV0LWdyb3VwXCIpXG4gICAgICogLSBJbnB1dCBtdXN0IGhhdmUgYSBcIm5hbWVcIiBhdHRyaWJ1dGUgbWF0Y2hpbmcgdGhlIGVycm9yIGtleVxuICAgICAqIC0gVXNlIFwiZm9ybS1jb250cm9sXCIgY2xhc3Mgb24gaW5wdXRzIGZvciBCb290c3RyYXAgNSBzdHlsaW5nXG4gICAgICpcbiAgICAgKiBBY2NlcHRzIHRocmVlIGZvcm1hdHM6XG4gICAgICogLSBTdHJpbmc6IFNpbmdsZSBlcnJvciBzaG93biBhcyBhbGVydFxuICAgICAqIC0gQXJyYXkgb2Ygc3RyaW5nczogTXVsdGlwbGUgZXJyb3JzIHNob3duIGFzIGJ1bGxldGVkIGFsZXJ0XG4gICAgICogLSBPYmplY3Q6IEZpZWxkIG5hbWVzIG1hcHBlZCB0byBlcnJvcnMsIHNob3duIGlubGluZSAodW5tYXRjaGVkIHNob3duIGFzIGFsZXJ0KVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmVudF9zZWxlY3RvciAtIGpRdWVyeSBzZWxlY3RvciBmb3IgcGFyZW50IGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xPYmplY3R8QXJyYXl9IGVycm9ycyAtIEVycm9yIG1lc3NhZ2VzIHRvIGRpc3BsYXlcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIGFuaW1hdGlvbnMgY29tcGxldGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYXBwbHlfZm9ybV9lcnJvcnMocGFyZW50X3NlbGVjdG9yLCBlcnJvcnMpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcnMpO1xuXG4gICAgICAgIGNvbnN0ICRwYXJlbnQgPSAkKHBhcmVudF9zZWxlY3Rvcik7XG5cbiAgICAgICAgLy8gUmVzZXQgdGhlIGZvcm0gZXJyb3JzIGJlZm9yZSBhcHBseWluZyBuZXcgb25lc1xuICAgICAgICBGb3JtX1V0aWxzLnJlc2V0X2Zvcm1fZXJyb3JzKHBhcmVudF9zZWxlY3Rvcik7XG5cbiAgICAgICAgLy8gTm9ybWFsaXplIGlucHV0IHRvIHN0YW5kYXJkIGZvcm1hdFxuICAgICAgICBjb25zdCBub3JtYWxpemVkID0gRm9ybV9VdGlscy5fbm9ybWFsaXplX2Vycm9ycyhlcnJvcnMpO1xuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgbGV0IGFuaW1hdGlvbnMgPSBbXTtcblxuICAgICAgICAgICAgaWYgKG5vcm1hbGl6ZWQudHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAvLyBTaW5nbGUgZXJyb3IgbWVzc2FnZVxuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMgPSBGb3JtX1V0aWxzLl9hcHBseV9nZW5lcmFsX2Vycm9ycygkcGFyZW50LCBub3JtYWxpemVkLmRhdGEpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChub3JtYWxpemVkLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgICAgICAvLyBBcnJheSBvZiBlcnJvciBtZXNzYWdlc1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlZHVwbGljYXRlZCA9IEZvcm1fVXRpbHMuX2RlZHVwbGljYXRlX2Vycm9ycyhub3JtYWxpemVkLmRhdGEpO1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMgPSBGb3JtX1V0aWxzLl9hcHBseV9nZW5lcmFsX2Vycm9ycygkcGFyZW50LCBkZWR1cGxpY2F0ZWQpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChub3JtYWxpemVkLnR5cGUgPT09ICdmaWVsZHMnKSB7XG4gICAgICAgICAgICAgICAgLy8gRmllbGQtc3BlY2lmaWMgZXJyb3JzXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gRm9ybV9VdGlscy5fYXBwbHlfZmllbGRfZXJyb3JzKCRwYXJlbnQsIG5vcm1hbGl6ZWQuZGF0YSk7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucyA9IHJlc3VsdC5hbmltYXRpb25zO1xuXG4gICAgICAgICAgICAgICAgLy8gQ291bnQgbWF0Y2hlZCBmaWVsZHNcbiAgICAgICAgICAgICAgICBjb25zdCBtYXRjaGVkX2NvdW50ID0gT2JqZWN0LmtleXMobm9ybWFsaXplZC5kYXRhKS5sZW5ndGggLSBPYmplY3Qua2V5cyhyZXN1bHQudW5tYXRjaGVkKS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgY29uc3QgdW5tYXRjaGVkX2RlZHVwbGljYXRlZCA9IEZvcm1fVXRpbHMuX2RlZHVwbGljYXRlX2Vycm9ycyhyZXN1bHQudW5tYXRjaGVkKTtcbiAgICAgICAgICAgICAgICBjb25zdCB1bm1hdGNoZWRfY291bnQgPSBPYmplY3Qua2V5cyh1bm1hdGNoZWRfZGVkdXBsaWNhdGVkKS5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICAvLyBTaG93IHN1bW1hcnkgYWxlcnQgaWYgdGhlcmUgYXJlIGFueSBmaWVsZCBlcnJvcnMgKG1hdGNoZWQgb3IgdW5tYXRjaGVkKVxuICAgICAgICAgICAgICAgIGlmIChtYXRjaGVkX2NvdW50ID4gMCB8fCB1bm1hdGNoZWRfY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEJ1aWxkIHN1bW1hcnkgbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICBsZXQgc3VtbWFyeV9tc2cgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoZWRfY291bnQgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdW1tYXJ5X21zZyA9IG1hdGNoZWRfY291bnQgPT09IDFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/ICdQbGVhc2UgY29ycmVjdCB0aGUgZXJyb3IgaGlnaGxpZ2h0ZWQgYmVsb3cuJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ1BsZWFzZSBjb3JyZWN0IHRoZSBlcnJvcnMgaGlnaGxpZ2h0ZWQgYmVsb3cuJztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGFyZSB1bm1hdGNoZWQgZXJyb3JzLCBhZGQgdGhlbSBhcyBhIGJ1bGxldGVkIGxpc3RcbiAgICAgICAgICAgICAgICAgICAgaWYgKHVubWF0Y2hlZF9jb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN1bW1hcnlfYW5pbWF0aW9ucyA9IEZvcm1fVXRpbHMuX2FwcGx5X2NvbWJpbmVkX2Vycm9yKCRwYXJlbnQsIHN1bW1hcnlfbXNnLCB1bm1hdGNoZWRfZGVkdXBsaWNhdGVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCguLi5zdW1tYXJ5X2FuaW1hdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSnVzdCB0aGUgc3VtbWFyeSBtZXNzYWdlLCBubyB1bm1hdGNoZWQgZXJyb3JzXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdW1tYXJ5X2FuaW1hdGlvbnMgPSBGb3JtX1V0aWxzLl9hcHBseV9nZW5lcmFsX2Vycm9ycygkcGFyZW50LCBzdW1tYXJ5X21zZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhbmltYXRpb25zLnB1c2goLi4uc3VtbWFyeV9hbmltYXRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUmVzb2x2ZSB0aGUgcHJvbWlzZSBvbmNlIGFsbCBhbmltYXRpb25zIGFyZSBjb21wbGV0ZVxuICAgICAgICAgICAgUHJvbWlzZS5hbGwoYW5pbWF0aW9ucykudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gU2Nyb2xsIHRvIGVycm9yIGNvbnRhaW5lciBpZiBpdCBleGlzdHNcbiAgICAgICAgICAgICAgICBjb25zdCAkZXJyb3JfY29udGFpbmVyID0gJHBhcmVudC5maW5kKCdbZGF0YS1pZD1cImVycm9yX2NvbnRhaW5lclwiXScpLmZpcnN0KCk7XG4gICAgICAgICAgICAgICAgaWYgKCRlcnJvcl9jb250YWluZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250YWluZXJfdG9wID0gJGVycm9yX2NvbnRhaW5lci5vZmZzZXQoKS50b3A7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIGZpeGVkIGhlYWRlciBvZmZzZXRcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZml4ZWRfaGVhZGVyX2hlaWdodCA9IEZvcm1fVXRpbHMuX2dldF9maXhlZF9oZWFkZXJfaGVpZ2h0KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gU2Nyb2xsIHRvIHBvc2l0aW9uIGVycm9yIGNvbnRhaW5lciAyMHB4IGJlbG93IGFueSBmaXhlZCBoZWFkZXJzXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldF9zY3JvbGwgPSBjb250YWluZXJfdG9wIC0gZml4ZWRfaGVhZGVyX2hlaWdodCAtIDIwO1xuICAgICAgICAgICAgICAgICAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxUb3A6IHRhcmdldF9zY3JvbGxcbiAgICAgICAgICAgICAgICAgICAgfSwgNTAwKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xlYXJzIGZvcm0gdmFsaWRhdGlvbiBlcnJvcnMgYW5kIHJlc2V0cyBhbGwgZm9ybSB2YWx1ZXMgdG8gZGVmYXVsdHNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xqUXVlcnl9IGZvcm1fc2VsZWN0b3IgLSBqUXVlcnkgc2VsZWN0b3Igb3IgalF1ZXJ5IG9iamVjdCBmb3IgZm9ybSBlbGVtZW50XG4gICAgICovXG4gICAgc3RhdGljIHJlc2V0KGZvcm1fc2VsZWN0b3IpIHtcbiAgICAgICAgY29uc3QgJGZvcm0gPSB0eXBlb2YgZm9ybV9zZWxlY3RvciA9PT0gJ3N0cmluZycgPyAkKGZvcm1fc2VsZWN0b3IpIDogZm9ybV9zZWxlY3RvcjtcblxuICAgICAgICBGb3JtX1V0aWxzLnJlc2V0X2Zvcm1fZXJyb3JzKGZvcm1fc2VsZWN0b3IpO1xuICAgICAgICAkZm9ybS50cmlnZ2VyKCdyZXNldCcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZXMgZm9ybSBkYXRhIGludG8ga2V5LXZhbHVlIG9iamVjdFxuICAgICAqIFJldHVybnMgYWxsIGlucHV0IGVsZW1lbnRzIHdpdGggbmFtZSBhdHRyaWJ1dGVzIGFzIG9iamVjdCBwcm9wZXJ0aWVzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8alF1ZXJ5fSBmb3JtX3NlbGVjdG9yIC0galF1ZXJ5IHNlbGVjdG9yIG9yIGpRdWVyeSBvYmplY3QgZm9yIGZvcm0gZWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IEZvcm0gZGF0YSBhcyBrZXktdmFsdWUgcGFpcnNcbiAgICAgKi9cbiAgICBzdGF0aWMgc2VyaWFsaXplKGZvcm1fc2VsZWN0b3IpIHtcbiAgICAgICAgY29uc3QgJGZvcm0gPSB0eXBlb2YgZm9ybV9zZWxlY3RvciA9PT0gJ3N0cmluZycgPyAkKGZvcm1fc2VsZWN0b3IpIDogZm9ybV9zZWxlY3RvcjtcbiAgICAgICAgY29uc3QgZGF0YSA9IHt9O1xuXG4gICAgICAgICRmb3JtLnNlcmlhbGl6ZUFycmF5KCkuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgZGF0YVtpdGVtLm5hbWVdID0gaXRlbS52YWx1ZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3VibWl0cyBmb3JtIHRvIFJTWCBjb250cm9sbGVyIGFjdGlvbiB2aWEgQUpBWFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfGpRdWVyeX0gZm9ybV9zZWxlY3RvciAtIGpRdWVyeSBzZWxlY3RvciBvciBqUXVlcnkgb2JqZWN0IGZvciBmb3JtIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY29udHJvbGxlciAtIENvbnRyb2xsZXIgY2xhc3MgbmFtZSAoZS5nLiwgJ1VzZXJfQ29udHJvbGxlcicpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbiAtIEFjdGlvbiBtZXRob2QgbmFtZSAoZS5nLiwgJ3NhdmVfcHJvZmlsZScpXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBPcHRpb25hbCBjb25maWd1cmF0aW9uIHtvbl9zdWNjZXNzOiBmbiwgb25fZXJyb3I6IGZufVxuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCByZXNwb25zZSBkYXRhXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIGFqYXhfc3VibWl0KGZvcm1fc2VsZWN0b3IsIGNvbnRyb2xsZXIsIGFjdGlvbiwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIGNvbnN0ICRmb3JtID0gdHlwZW9mIGZvcm1fc2VsZWN0b3IgPT09ICdzdHJpbmcnID8gJChmb3JtX3NlbGVjdG9yKSA6IGZvcm1fc2VsZWN0b3I7XG4gICAgICAgIGNvbnN0IGZvcm1fZGF0YSA9IEZvcm1fVXRpbHMuc2VyaWFsaXplKCRmb3JtKTtcblxuICAgICAgICBGb3JtX1V0aWxzLnJlc2V0X2Zvcm1fZXJyb3JzKGZvcm1fc2VsZWN0b3IpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IEFqYXguY2FsbChjb250cm9sbGVyLCBhY3Rpb24sIGZvcm1fZGF0YSk7XG5cbiAgICAgICAgICAgIGlmIChvcHRpb25zLm9uX3N1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zLm9uX3N1Y2Nlc3MocmVzcG9uc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBpZiAoZXJyb3IudHlwZSA9PT0gJ2Zvcm1fZXJyb3InICYmIGVycm9yLmRldGFpbHMpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBGb3JtX1V0aWxzLmFwcGx5X2Zvcm1fZXJyb3JzKGZvcm1fc2VsZWN0b3IsIGVycm9yLmRldGFpbHMpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBGb3JtX1V0aWxzLmFwcGx5X2Zvcm1fZXJyb3JzKGZvcm1fc2VsZWN0b3IsIGVycm9yLm1lc3NhZ2UgfHwgJ0FuIGVycm9yIG9jY3VycmVkJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChvcHRpb25zLm9uX2Vycm9yKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5vbl9lcnJvcihlcnJvcik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBmb3JtIHZhbGlkYXRpb24gZXJyb3JzXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHBhcmVudF9zZWxlY3RvciAtIGpRdWVyeSBzZWxlY3RvciBmb3IgcGFyZW50IGVsZW1lbnRcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzZXRfZm9ybV9lcnJvcnMocGFyZW50X3NlbGVjdG9yKSB7XG4gICAgICAgIGNvbnN0ICRwYXJlbnQgPSAkKHBhcmVudF9zZWxlY3Rvcik7XG5cbiAgICAgICAgLy8gUmVtb3ZlIGZsYXNoIG1lc3NhZ2VzXG4gICAgICAgICQoJy5mbGFzaC1tZXNzYWdlcycpLnJlbW92ZSgpO1xuXG4gICAgICAgIC8vIFJlbW92ZSBhbGVydC1kYW5nZXIgbWVzc2FnZXNcbiAgICAgICAgJHBhcmVudC5maW5kKCcuYWxlcnQtZGFuZ2VyJykucmVtb3ZlKCk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIHZhbGlkYXRpb24gZXJyb3IgY2xhc3NlcyBhbmQgdGV4dCBmcm9tIGZvcm0gZWxlbWVudHNcbiAgICAgICAgJHBhcmVudC5maW5kKCcuaXMtaW52YWxpZCcpLnJlbW92ZUNsYXNzKCdpcy1pbnZhbGlkJyk7XG4gICAgICAgICRwYXJlbnQuZmluZCgnLmludmFsaWQtZmVlZGJhY2snKS5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAgIC8qKlxuICAgICAqIE5vcm1hbGl6ZXMgZXJyb3IgaW5wdXQgaW50byBzdGFuZGFyZCBmb3JtYXRzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fEFycmF5fSBlcnJvcnMgLSBSYXcgZXJyb3IgaW5wdXRcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBOb3JtYWxpemVkIGVycm9ycyBhcyB7dHlwZTogJ3N0cmluZyd8J2FycmF5J3wnZmllbGRzJywgZGF0YTogLi4ufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9ub3JtYWxpemVfZXJyb3JzKGVycm9ycykge1xuICAgICAgICAvLyBIYW5kbGUgbnVsbC91bmRlZmluZWRcbiAgICAgICAgaWYgKCFlcnJvcnMpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdzdHJpbmcnLCBkYXRhOiAnQW4gZXJyb3IgaGFzIG9jY3VycmVkJyB9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIHN0cmluZ1xuICAgICAgICBpZiAodHlwZW9mIGVycm9ycyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdzdHJpbmcnLCBkYXRhOiBlcnJvcnMgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEhhbmRsZSBhcnJheVxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShlcnJvcnMpKSB7XG4gICAgICAgICAgICAvLyBBcnJheSBvZiBzdHJpbmdzIC0gZ2VuZXJhbCBlcnJvcnNcbiAgICAgICAgICAgIGlmIChlcnJvcnMuZXZlcnkoKGUpID0+IHR5cGVvZiBlID09PSAnc3RyaW5nJykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyB0eXBlOiAnYXJyYXknLCBkYXRhOiBlcnJvcnMgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEFycmF5IHdpdGggb2JqZWN0IGFzIGZpcnN0IGVsZW1lbnQgLSBleHRyYWN0IGl0XG4gICAgICAgICAgICBpZiAoZXJyb3JzLmxlbmd0aCA+IDAgJiYgdHlwZW9mIGVycm9yc1swXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRm9ybV9VdGlscy5fbm9ybWFsaXplX2Vycm9ycyhlcnJvcnNbMF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRW1wdHkgb3IgbWl4ZWQgYXJyYXlcbiAgICAgICAgICAgIHJldHVybiB7IHR5cGU6ICdhcnJheScsIGRhdGE6IFtdIH07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBIYW5kbGUgb2JqZWN0IC0gY2hlY2sgZm9yIExhcmF2ZWwgcmVzcG9uc2Ugd3JhcHBlclxuICAgICAgICBpZiAodHlwZW9mIGVycm9ycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIC8vIFVud3JhcCB7ZXJyb3JzOiB7Li4ufX0gb3Ige2Vycm9yOiB7Li4ufX1cbiAgICAgICAgICAgIGNvbnN0IHVud3JhcHBlZCA9IGVycm9ycy5lcnJvcnMgfHwgZXJyb3JzLmVycm9yO1xuICAgICAgICAgICAgaWYgKHVud3JhcHBlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBGb3JtX1V0aWxzLl9ub3JtYWxpemVfZXJyb3JzKHVud3JhcHBlZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENvbnZlcnQgTGFyYXZlbCB2YWxpZGF0b3IgZm9ybWF0IHtmaWVsZDogW21zZzEsIG1zZzJdfSB0byB7ZmllbGQ6IG1zZzF9XG4gICAgICAgICAgICBjb25zdCBub3JtYWxpemVkID0ge307XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIGVycm9ycykge1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcnMuaGFzT3duUHJvcGVydHkoZmllbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZXJyb3JzW2ZpZWxkXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRbZmllbGRdID0gdmFsdWVbMF07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZFtmaWVsZF0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRbZmllbGRdID0gU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHsgdHlwZTogJ2ZpZWxkcycsIGRhdGE6IG5vcm1hbGl6ZWQgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmFsIGNhdGNoLWFsbCpcbiAgICAgICAgcmV0dXJuIHsgdHlwZTogJ3N0cmluZycsIGRhdGE6IFN0cmluZyhlcnJvcnMpIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBkdXBsaWNhdGUgZXJyb3IgbWVzc2FnZXMgZnJvbSBhcnJheSBvciBvYmplY3QgdmFsdWVzXG4gICAgICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGVycm9ycyAtIEVycm9ycyB0byBkZWR1cGxpY2F0ZVxuICAgICAqIEByZXR1cm5zIHtBcnJheXxPYmplY3R9IERlZHVwbGljYXRlZCBlcnJvcnNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZGVkdXBsaWNhdGVfZXJyb3JzKGVycm9ycykge1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShlcnJvcnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gWy4uLm5ldyBTZXQoZXJyb3JzKV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGVycm9ycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0KCk7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIGVycm9ycykge1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gZXJyb3JzW2tleV07XG4gICAgICAgICAgICAgICAgaWYgKCFzZWVuLmhhcyh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2Vlbi5hZGQodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZXJyb3JzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFwcGxpZXMgZmllbGQtc3BlY2lmaWMgdmFsaWRhdGlvbiBlcnJvcnMgdG8gZm9ybSBpbnB1dHNcbiAgICAgKiBAcGFyYW0ge2pRdWVyeX0gJHBhcmVudCAtIFBhcmVudCBlbGVtZW50IGNvbnRhaW5pbmcgZm9ybVxuICAgICAqIEBwYXJhbSB7T2JqZWN0fSBmaWVsZF9lcnJvcnMgLSBPYmplY3QgbWFwcGluZyBmaWVsZCBuYW1lcyB0byBlcnJvciBtZXNzYWdlc1xuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IE9iamVjdCBjb250YWluaW5nIHthbmltYXRpb25zOiBBcnJheSwgdW5tYXRjaGVkOiBPYmplY3R9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2FwcGx5X2ZpZWxkX2Vycm9ycygkcGFyZW50LCBmaWVsZF9lcnJvcnMpIHtcbiAgICAgICAgY29uc3QgYW5pbWF0aW9ucyA9IFtdO1xuICAgICAgICBjb25zdCB1bm1hdGNoZWQgPSB7fTtcblxuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkX25hbWUgaW4gZmllbGRfZXJyb3JzKSB7XG4gICAgICAgICAgICBjb25zdCBlcnJvcl9tZXNzYWdlID0gZmllbGRfZXJyb3JzW2ZpZWxkX25hbWVdO1xuICAgICAgICAgICAgY29uc3QgJGlucHV0ID0gJHBhcmVudC5maW5kKGBbbmFtZT1cIiR7ZmllbGRfbmFtZX1cIl1gKTtcblxuICAgICAgICAgICAgaWYgKCEkaW5wdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdW5tYXRjaGVkW2ZpZWxkX25hbWVdID0gZXJyb3JfbWVzc2FnZTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgJGVycm9yID0gJCgnPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIj48L2Rpdj4nKS5odG1sKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgY29uc3QgJHRhcmdldCA9ICRpbnB1dC5jbG9zZXN0KCcuZm9ybS1ncm91cCwgLmZvcm0tY2hlY2ssIC5pbnB1dC1ncm91cCcpO1xuXG4gICAgICAgICAgICBpZiAoISR0YXJnZXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdW5tYXRjaGVkW2ZpZWxkX25hbWVdID0gZXJyb3JfbWVzc2FnZTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJGlucHV0LmFkZENsYXNzKCdpcy1pbnZhbGlkJyk7XG4gICAgICAgICAgICAkZXJyb3IuYXBwZW5kVG8oJHRhcmdldCk7XG4gICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGVycm9yLmhpZGUoKS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgYW5pbWF0aW9ucywgdW5tYXRjaGVkIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXBwbGllcyBjb21iaW5lZCBlcnJvciBtZXNzYWdlIHdpdGggc3VtbWFyeSBhbmQgdW5tYXRjaGVkIGZpZWxkIGVycm9yc1xuICAgICAqIEBwYXJhbSB7alF1ZXJ5fSAkcGFyZW50IC0gUGFyZW50IGVsZW1lbnQgY29udGFpbmluZyBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN1bW1hcnlfbXNnIC0gU3VtbWFyeSBtZXNzYWdlIChlLmcuLCBcIlBsZWFzZSBjb3JyZWN0IHRoZSBlcnJvcnMgYmVsb3dcIilcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gdW5tYXRjaGVkX2Vycm9ycyAtIE9iamVjdCBvZiBmaWVsZCBlcnJvcnMgdGhhdCBjb3VsZG4ndCBiZSBtYXRjaGVkIHRvIGZpZWxkc1xuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2YgYW5pbWF0aW9uIHByb21pc2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2FwcGx5X2NvbWJpbmVkX2Vycm9yKCRwYXJlbnQsIHN1bW1hcnlfbXNnLCB1bm1hdGNoZWRfZXJyb3JzKSB7XG4gICAgICAgIGNvbnN0IGFuaW1hdGlvbnMgPSBbXTtcbiAgICAgICAgY29uc3QgJGVycm9yX2NvbnRhaW5lciA9ICRwYXJlbnQuZmluZCgnW2RhdGEtaWQ9XCJlcnJvcl9jb250YWluZXJcIl0nKS5maXJzdCgpO1xuICAgICAgICBjb25zdCAkdGFyZ2V0ID0gJGVycm9yX2NvbnRhaW5lci5sZW5ndGggPiAwID8gJGVycm9yX2NvbnRhaW5lciA6ICRwYXJlbnQ7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFsZXJ0IHdpdGggc3VtbWFyeSBtZXNzYWdlIGFuZCBidWxsZXRlZCBsaXN0IG9mIHVubWF0Y2hlZCBlcnJvcnNcbiAgICAgICAgY29uc3QgJGFsZXJ0ID0gJCgnPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiIHJvbGU9XCJhbGVydFwiPjwvZGl2PicpO1xuXG4gICAgICAgIC8vIEFkZCBzdW1tYXJ5IG1lc3NhZ2UgaWYgcHJvdmlkZWRcbiAgICAgICAgaWYgKHN1bW1hcnlfbXNnKSB7XG4gICAgICAgICAgICAkKCc8cCBjbGFzcz1cIm1iLTJcIj48L3A+JykudGV4dChzdW1tYXJ5X21zZykuYXBwZW5kVG8oJGFsZXJ0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFkZCB1bm1hdGNoZWQgZXJyb3JzIGFzIGJ1bGxldGVkIGxpc3RcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHVubWF0Y2hlZF9lcnJvcnMpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0ICRsaXN0ID0gJCgnPHVsIGNsYXNzPVwibWItMFwiPjwvdWw+Jyk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkX25hbWUgaW4gdW5tYXRjaGVkX2Vycm9ycykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yX21zZyA9IHVubWF0Y2hlZF9lcnJvcnNbZmllbGRfbmFtZV07XG4gICAgICAgICAgICAgICAgJCgnPGxpPjwvbGk+JykuaHRtbChlcnJvcl9tc2cpLmFwcGVuZFRvKCRsaXN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICRsaXN0LmFwcGVuZFRvKCRhbGVydCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJGVycm9yX2NvbnRhaW5lci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBhbmltYXRpb25zLnB1c2goJGFsZXJ0LmhpZGUoKS5hcHBlbmRUbygkdGFyZ2V0KS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRhbGVydC5oaWRlKCkucHJlcGVuZFRvKCR0YXJnZXQpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYW5pbWF0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBcHBsaWVzIGdlbmVyYWwgZXJyb3IgbWVzc2FnZXMgYXMgYWxlcnQgYm94XG4gICAgICogQHBhcmFtIHtqUXVlcnl9ICRwYXJlbnQgLSBQYXJlbnQgZWxlbWVudCB0byBwcmVwZW5kIGFsZXJ0IHRvXG4gICAgICogQHBhcmFtIHtzdHJpbmd8QXJyYXl9IG1lc3NhZ2VzIC0gRXJyb3IgbWVzc2FnZShzKSB0byBkaXNwbGF5XG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBhbmltYXRpb24gcHJvbWlzZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYXBwbHlfZ2VuZXJhbF9lcnJvcnMoJHBhcmVudCwgbWVzc2FnZXMpIHtcbiAgICAgICAgY29uc3QgYW5pbWF0aW9ucyA9IFtdO1xuXG4gICAgICAgIC8vIExvb2sgZm9yIGEgc3BlY2lmaWMgZXJyb3IgY29udGFpbmVyIGRpdiAoZS5nLiwgaW4gUnN4X0Zvcm0gY29tcG9uZW50KVxuICAgICAgICBjb25zdCAkZXJyb3JfY29udGFpbmVyID0gJHBhcmVudC5maW5kKCdbZGF0YS1pZD1cImVycm9yX2NvbnRhaW5lclwiXScpLmZpcnN0KCk7XG4gICAgICAgIGNvbnN0ICR0YXJnZXQgPSAkZXJyb3JfY29udGFpbmVyLmxlbmd0aCA+IDAgPyAkZXJyb3JfY29udGFpbmVyIDogJHBhcmVudDtcblxuICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2VzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgLy8gU2luZ2xlIGVycm9yIC0gc2ltcGxlIGFsZXJ0IHdpdGhvdXQgbGlzdFxuICAgICAgICAgICAgY29uc3QgJGFsZXJ0ID0gJCgnPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiIHJvbGU9XCJhbGVydFwiPjwvZGl2PicpLnRleHQobWVzc2FnZXMpO1xuICAgICAgICAgICAgaWYgKCRlcnJvcl9jb250YWluZXIubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkYWxlcnQuaGlkZSgpLmFwcGVuZFRvKCR0YXJnZXQpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFuaW1hdGlvbnMucHVzaCgkYWxlcnQuaGlkZSgpLnByZXBlbmRUbygkdGFyZ2V0KS5mYWRlSW4oMzAwKS5wcm9taXNlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkobWVzc2FnZXMpICYmIG1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIC8vIE11bHRpcGxlIGVycm9ycyAtIGJ1bGxldGVkIGxpc3RcbiAgICAgICAgICAgIGNvbnN0ICRhbGVydCA9ICQoJzxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj48dWwgY2xhc3M9XCJtYi0wXCI+PC91bD48L2Rpdj4nKTtcbiAgICAgICAgICAgIGNvbnN0ICRsaXN0ID0gJGFsZXJ0LmZpbmQoJ3VsJyk7XG5cbiAgICAgICAgICAgIG1lc3NhZ2VzLmZvckVhY2goKG1zZykgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRleHQgPSAobXNnICsgJycpLnRyaW0oKSB8fCAnQW4gZXJyb3IgaGFzIG9jY3VycmVkJztcbiAgICAgICAgICAgICAgICAkKCc8bGk+PC9saT4nKS5odG1sKHRleHQpLmFwcGVuZFRvKCRsaXN0KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoJGVycm9yX2NvbnRhaW5lci5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRhbGVydC5oaWRlKCkuYXBwZW5kVG8oJHRhcmdldCkuZmFkZUluKDMwMCkucHJvbWlzZSgpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYW5pbWF0aW9ucy5wdXNoKCRhbGVydC5oaWRlKCkucHJlcGVuZFRvKCR0YXJnZXQpLmZhZGVJbigzMDApLnByb21pc2UoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1lc3NhZ2VzID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShtZXNzYWdlcykpIHtcbiAgICAgICAgICAgIC8vIE9iamVjdCBvZiB1bm1hdGNoZWQgZmllbGQgZXJyb3JzIC0gY29udmVydCB0byBhcnJheVxuICAgICAgICAgICAgY29uc3QgZXJyb3JfbGlzdCA9IE9iamVjdC52YWx1ZXMobWVzc2FnZXMpXG4gICAgICAgICAgICAgICAgLm1hcCgodikgPT4gU3RyaW5nKHYpLnRyaW0oKSlcbiAgICAgICAgICAgICAgICAuZmlsdGVyKCh2KSA9PiB2KTtcbiAgICAgICAgICAgIGlmIChlcnJvcl9saXN0Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gRm9ybV9VdGlscy5fYXBwbHlfZ2VuZXJhbF9lcnJvcnMoJHBhcmVudCwgZXJyb3JfbGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYW5pbWF0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSB0b3RhbCBoZWlnaHQgb2YgZml4ZWQvc3RpY2t5IGhlYWRlcnMgYXQgdGhlIHRvcCBvZiB0aGUgcGFnZVxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFRvdGFsIGhlaWdodCBpbiBwaXhlbHMgb2YgZml4ZWQgdG9wIGVsZW1lbnRzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dldF9maXhlZF9oZWFkZXJfaGVpZ2h0KCkge1xuICAgICAgICBsZXQgdG90YWxfaGVpZ2h0ID0gMDtcblxuICAgICAgICAvLyBGaW5kIGFsbCBmaXhlZCBvciBzdGlja3kgcG9zaXRpb25lZCBlbGVtZW50c1xuICAgICAgICAkKCcqJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGNvbnN0ICRlbCA9ICQodGhpcyk7XG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9ICRlbC5jc3MoJ3Bvc2l0aW9uJyk7XG5cbiAgICAgICAgICAgIC8vIE9ubHkgY2hlY2sgZml4ZWQgb3Igc3RpY2t5IGVsZW1lbnRzXG4gICAgICAgICAgICBpZiAocG9zaXRpb24gIT09ICdmaXhlZCcgJiYgcG9zaXRpb24gIT09ICdzdGlja3knKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBlbGVtZW50IGlzIHBvc2l0aW9uZWQgYXQgb3IgbmVhciB0aGUgdG9wXG4gICAgICAgICAgICBjb25zdCB0b3AgPSBwYXJzZUludCgkZWwuY3NzKCd0b3AnKSkgfHwgMDtcbiAgICAgICAgICAgIGlmICh0b3AgPiA1MCkge1xuICAgICAgICAgICAgICAgIHJldHVybjsgLy8gTm90IGEgdG9wIGhlYWRlclxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBlbGVtZW50IGlzIHZpc2libGVcbiAgICAgICAgICAgIGlmICghJGVsLmlzKCc6dmlzaWJsZScpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiBlbGVtZW50IHNwYW5zIHNpZ25pZmljYW50IHdpZHRoIChsaWtlbHkgYSBoZWFkZXIvbmF2YmFyKVxuICAgICAgICAgICAgY29uc3Qgd2lkdGggPSAkZWwub3V0ZXJXaWR0aCgpO1xuICAgICAgICAgICAgY29uc3Qgdmlld3BvcnRfd2lkdGggPSAkKHdpbmRvdykud2lkdGgoKTtcbiAgICAgICAgICAgIGlmICh3aWR0aCA8IHZpZXdwb3J0X3dpZHRoICogMC41KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBUb28gbmFycm93IHRvIGJlIGEgaGVhZGVyXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEFkZCB0aGlzIGVsZW1lbnQncyBoZWlnaHRcbiAgICAgICAgICAgIHRvdGFsX2hlaWdodCArPSAkZWwub3V0ZXJIZWlnaHQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRvdGFsX2hlaWdodDtcbiAgICB9XG59XG4iLCIvKipcbiAqIERlYnVnZ2VyIGNsYXNzIGZvciBjb25zb2xlX2RlYnVnIGFuZCBicm93c2VyIGVycm9yIGxvZ2dpbmdcbiAqIEhhbmRsZXMgYmF0Y2hlZCBzdWJtaXNzaW9uIHRvIHNlcnZlciB3aGVuIGNvbmZpZ3VyZWRcbiAqL1xuY2xhc3MgRGVidWdnZXIge1xuICAgIC8vIEJhdGNoaW5nIHN0YXRlIGZvciBjb25zb2xlX2RlYnVnIG1lc3NhZ2VzXG4gICAgc3RhdGljIF9jb25zb2xlX2JhdGNoID0gW107XG4gICAgc3RhdGljIF9jb25zb2xlX3RpbWVyID0gbnVsbDtcbiAgICBzdGF0aWMgX2NvbnNvbGVfYmF0Y2hfY291bnQgPSAwO1xuXG4gICAgLy8gQmF0Y2hpbmcgc3RhdGUgZm9yIGVycm9yIG1lc3NhZ2VzXG4gICAgc3RhdGljIF9lcnJvcl9iYXRjaCA9IFtdO1xuICAgIHN0YXRpYyBfZXJyb3JfdGltZXIgPSBudWxsO1xuICAgIHN0YXRpYyBfZXJyb3JfY291bnQgPSAwO1xuICAgIHN0YXRpYyBfZXJyb3JfYmF0Y2hfY291bnQgPSAwO1xuXG4gICAgLy8gQ29uc3RhbnRzXG4gICAgc3RhdGljIERFQk9VTkNFX01TID0gMjAwMDtcbiAgICBzdGF0aWMgTUFYX0VSUk9SU19QRVJfUEFHRSA9IDIwO1xuICAgIHN0YXRpYyBNQVhfRVJST1JfQkFUQ0hFUyA9IDU7XG5cbiAgICAvLyBTdG9yZSBzdGFydCB0aW1lIGZvciBiZW5jaG1hcmtpbmdcbiAgICBzdGF0aWMgX3N0YXJ0X3RpbWUgPSBudWxsO1xuXG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBmcmFtZXdvcmsgZXJyb3IgaGFuZGxpbmdcbiAgICAgKiBDYWxsZWQgZHVyaW5nIGZyYW1ld29yayBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCgpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgYnJvd3NlciBlcnJvciBsb2dnaW5nIGlzIGVuYWJsZWRcbiAgICAgICAgaWYgKHdpbmRvdy5yc3hhcHAgJiYgd2luZG93LnJzeGFwcC5sb2dfYnJvd3Nlcl9lcnJvcnMpIHtcbiAgICAgICAgICAgIC8vIFJlZ2lzdGVyIGdsb2JhbCBlcnJvciBoYW5kbGVyXG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgICAgICBEZWJ1Z2dlci5faGFuZGxlX2Jyb3dzZXJfZXJyb3Ioe1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBldmVudC5tZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICBmaWxlbmFtZTogZXZlbnQuZmlsZW5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGxpbmVubzogZXZlbnQubGluZW5vLFxuICAgICAgICAgICAgICAgICAgICBjb2xubzogZXZlbnQuY29sbm8sXG4gICAgICAgICAgICAgICAgICAgIHN0YWNrOiBldmVudC5lcnJvciA/IGV2ZW50LmVycm9yLnN0YWNrIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBSZWdpc3RlciB1bmhhbmRsZWQgcHJvbWlzZSByZWplY3Rpb24gaGFuZGxlclxuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3VuaGFuZGxlZHJlamVjdGlvbicsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIERlYnVnZ2VyLl9oYW5kbGVfYnJvd3Nlcl9lcnJvcih7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGV2ZW50LnJlYXNvbiA/IGV2ZW50LnJlYXNvbi5tZXNzYWdlIHx8IFN0cmluZyhldmVudC5yZWFzb24pIDogJ1VuaGFuZGxlZCBwcm9taXNlIHJlamVjdGlvbicsXG4gICAgICAgICAgICAgICAgICAgIHN0YWNrOiBldmVudC5yZWFzb24gJiYgZXZlbnQucmVhc29uLnN0YWNrID8gZXZlbnQucmVhc29uLnN0YWNrIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3VuaGFuZGxlZHJlamVjdGlvbicsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZ2lzdGVyIHVpIHJlZnJlc2ggaGFuZGxlclxuICAgICAgICBSc3gub24oJ3JlZnJlc2gnLCBEZWJ1Z2dlci5vbl9yZWZyZXNoKTtcbiAgICB9XG5cbiAgICAvLyBJbiBkZXYgbW9kZSwgc29tZSB1aSBlbGVtZW50cyBjYW4gYmUgYXV0b21hdGljYWxseSBhcHBsaWVkIHRvIGFzc2lzdCB3aXRoIGRldmVsb3BtZW50XG4gICAgc3RhdGljIG9uX3JlZnJlc2goKSB7XG4gICAgICAgIGlmICghUnN4LmlzX3Byb2QoKSkge1xuICAgICAgICAgICAgLy8gQWRkIGFuIHVuZGVybGluZSAyIHB4IGJsdWUgdG8gYWxsIGEgdGFncyB3aXRoIGhyZWYgPT09IFwiI1wiIHVzaW5nIGpxdWVyeVxuICAgICAgICAgICAgLy8gVG9kbzogbWF5YmUgdGhpcyBzaG91bGQgYmUgYSBjb25maWd1cmFibGUgZGVidWcgb3B0aW9uP1xuICAgICAgICAgICAgLy8gJCgnYVtocmVmPVwiI1wiXScpLmNzcyh7XG4gICAgICAgICAgICAvLyAgICAgJ2JvcmRlci1ib3R0b20nOiAnMnB4IHNvbGlkIGJsdWUnLFxuICAgICAgICAgICAgLy8gICAgICd0ZXh0LWRlY29yYXRpb24nOiAnbm9uZSdcbiAgICAgICAgICAgIC8vIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbiBvZiBjb25zb2xlX2RlYnVnXG4gICAgICogTWlycm9ycyBQSFAgZnVuY3Rpb25hbGl0eSB3aXRoIGJhdGNoaW5nIGZvciBMYXJhdmVsIGxvZ1xuICAgICAqL1xuICAgIHN0YXRpYyBjb25zb2xlX2RlYnVnKGNoYW5uZWwsIC4uLnZhbHVlcykge1xuICAgICAgICAvLyBDaGVjayBpZiBjb25zb2xlX2RlYnVnIGlzIGVuYWJsZWRcbiAgICAgICAgaWYgKCF3aW5kb3cucnN4YXBwIHx8ICF3aW5kb3cucnN4YXBwLmNvbnNvbGVfZGVidWcgfHwgIXdpbmRvdy5yc3hhcHAuY29uc29sZV9kZWJ1Zy5lbmFibGVkKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjb25maWcgPSB3aW5kb3cucnN4YXBwLmNvbnNvbGVfZGVidWc7XG5cbiAgICAgICAgLy8gTm9ybWFsaXplIGNoYW5uZWwgbmFtZVxuICAgICAgICBjaGFubmVsID0gU3RyaW5nKGNoYW5uZWwpXG4gICAgICAgICAgICAudG9VcHBlckNhc2UoKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1tcXFtcXF1dL2csICcnKTtcblxuICAgICAgICAvLyBBcHBseSBmaWx0ZXJpbmdcbiAgICAgICAgaWYgKGNvbmZpZy5maWx0ZXJfbW9kZSA9PT0gJ3NwZWNpZmljJykge1xuICAgICAgICAgICAgY29uc3Qgc3BlY2lmaWMgPSBjb25maWcuc3BlY2lmaWNfY2hhbm5lbDtcbiAgICAgICAgICAgIGlmIChzcGVjaWZpYykge1xuICAgICAgICAgICAgICAgIC8vIFNwbGl0IGNvbW1hLXNlcGFyYXRlZCB2YWx1ZXMgYW5kIG5vcm1hbGl6ZVxuICAgICAgICAgICAgICAgIGNvbnN0IGNoYW5uZWxzID0gc3BlY2lmaWMuc3BsaXQoJywnKS5tYXAoKGMpID0+IGMudHJpbSgpLnRvVXBwZXJDYXNlKCkpO1xuICAgICAgICAgICAgICAgIGlmICghY2hhbm5lbHMuaW5jbHVkZXMoY2hhbm5lbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChjb25maWcuZmlsdGVyX21vZGUgPT09ICd3aGl0ZWxpc3QnKSB7XG4gICAgICAgICAgICBjb25zdCB3aGl0ZWxpc3QgPSAoY29uZmlnLmZpbHRlcl9jaGFubmVscyB8fCBbXSkubWFwKChjKSA9PiBjLnRvVXBwZXJDYXNlKCkpO1xuICAgICAgICAgICAgaWYgKCF3aGl0ZWxpc3QuaW5jbHVkZXMoY2hhbm5lbCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoY29uZmlnLmZpbHRlcl9tb2RlID09PSAnYmxhY2tsaXN0Jykge1xuICAgICAgICAgICAgY29uc3QgYmxhY2tsaXN0ID0gKGNvbmZpZy5maWx0ZXJfY2hhbm5lbHMgfHwgW10pLm1hcCgoYykgPT4gYy50b1VwcGVyQ2FzZSgpKTtcbiAgICAgICAgICAgIGlmIChibGFja2xpc3QuaW5jbHVkZXMoY2hhbm5lbCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmVwYXJlIHRoZSBtZXNzYWdlXG4gICAgICAgIGxldCBtZXNzYWdlID0ge1xuICAgICAgICAgICAgY2hhbm5lbDogY2hhbm5lbCxcbiAgICAgICAgICAgIHZhbHVlczogdmFsdWVzLFxuICAgICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gQWRkIGxvY2F0aW9uIGlmIGNvbmZpZ3VyZWRcbiAgICAgICAgaWYgKGNvbmZpZy5pbmNsdWRlX2xvY2F0aW9uIHx8IGNvbmZpZy5pbmNsdWRlX2JhY2t0cmFjZSkge1xuICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgICAgICAgICAgIGNvbnN0IHN0YWNrID0gZXJyb3Iuc3RhY2sgfHwgJyc7XG4gICAgICAgICAgICBjb25zdCBzdGFja0xpbmVzID0gc3RhY2suc3BsaXQoJ1xcbicpO1xuXG4gICAgICAgICAgICBpZiAoY29uZmlnLmluY2x1ZGVfbG9jYXRpb24gJiYgc3RhY2tMaW5lcy5sZW5ndGggPiAyKSB7XG4gICAgICAgICAgICAgICAgLy8gU2tpcCBFcnJvciBsaW5lIGFuZCB0aGlzIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgY29uc3QgY2FsbGVyTGluZSA9IHN0YWNrTGluZXNbMl0gfHwgJyc7XG4gICAgICAgICAgICAgICAgY29uc3QgbWF0Y2ggPSBjYWxsZXJMaW5lLm1hdGNoKC9hdFxccysuKj9cXHMrXFwoKC4qPyk6KFxcZCspOihcXGQrKVxcKS8pIHx8IGNhbGxlckxpbmUubWF0Y2goL2F0XFxzKyguKj8pOihcXGQrKTooXFxkKykvKTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5sb2NhdGlvbiA9IGAke21hdGNoWzFdfToke21hdGNoWzJdfWA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY29uZmlnLmluY2x1ZGVfYmFja3RyYWNlKSB7XG4gICAgICAgICAgICAgICAgLy8gSW5jbHVkZSBmaXJzdCA1IHN0YWNrIGZyYW1lcywgc2tpcHBpbmcgdGhpcyBmdW5jdGlvblxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuYmFja3RyYWNlID0gc3RhY2tMaW5lc1xuICAgICAgICAgICAgICAgICAgICAuc2xpY2UoMiwgNylcbiAgICAgICAgICAgICAgICAgICAgLm1hcCgobGluZSkgPT4gbGluZS50cmltKCkpXG4gICAgICAgICAgICAgICAgICAgIC5maWx0ZXIoKGxpbmUpID0+IGxpbmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gT3V0cHV0IHRvIGJyb3dzZXIgY29uc29sZSBpZiBlbmFibGVkXG4gICAgICAgIGlmIChjb25maWcub3V0cHV0cyAmJiBjb25maWcub3V0cHV0cy5icm93c2VyKSB7XG4gICAgICAgICAgICBjb25zdCBwcmVmaXggPSBjb25maWcuaW5jbHVkZV9iZW5jaG1hcmsgPyBgWyR7RGVidWdnZXIuX2dldF90aW1lX3ByZWZpeCgpfV0gYCA6ICcnO1xuICAgICAgICAgICAgY29uc3QgY2hhbm5lbFByZWZpeCA9IGBbJHtjaGFubmVsfV1gO1xuXG4gICAgICAgICAgICAvLyBVc2UgYXBwcm9wcmlhdGUgY29uc29sZSBtZXRob2QgYmFzZWQgb24gY2hhbm5lbFxuICAgICAgICAgICAgbGV0IGNvbnNvbGVNZXRob2QgPSAnbG9nJztcbiAgICAgICAgICAgIGlmIChjaGFubmVsLmluY2x1ZGVzKCdFUlJPUicpKSBjb25zb2xlTWV0aG9kID0gJ2Vycm9yJztcbiAgICAgICAgICAgIGVsc2UgaWYgKGNoYW5uZWwuaW5jbHVkZXMoJ1dBUk4nKSkgY29uc29sZU1ldGhvZCA9ICd3YXJuJztcbiAgICAgICAgICAgIGVsc2UgaWYgKGNoYW5uZWwuaW5jbHVkZXMoJ0lORk8nKSkgY29uc29sZU1ldGhvZCA9ICdpbmZvJztcblxuICAgICAgICAgICAgY29uc29sZVtjb25zb2xlTWV0aG9kXShwcmVmaXggKyBjaGFubmVsUHJlZml4LCAuLi52YWx1ZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmF0Y2ggZm9yIExhcmF2ZWwgbG9nIGlmIGVuYWJsZWRcbiAgICAgICAgaWYgKGNvbmZpZy5vdXRwdXRzICYmIGNvbmZpZy5vdXRwdXRzLmxhcmF2ZWxfbG9nKSB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5fYmF0Y2hfY29uc29sZV9tZXNzYWdlKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTG9nIGFuIGVycm9yIHRvIHRoZSBzZXJ2ZXJcbiAgICAgKiBVc2VkIG1hbnVhbGx5IG9yIGJ5IEFqYXggZXJyb3IgaGFuZGxpbmdcbiAgICAgKi9cbiAgICBzdGF0aWMgbG9nX2Vycm9yKGVycm9yKSB7XG4gICAgICAgIC8vIENoZWNrIGlmIGJyb3dzZXIgZXJyb3IgbG9nZ2luZyBpcyBlbmFibGVkXG4gICAgICAgIGlmICghd2luZG93LnJzeGFwcCB8fCAhd2luZG93LnJzeGFwcC5sb2dfYnJvd3Nlcl9lcnJvcnMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE5vcm1hbGl6ZSBlcnJvciBmb3JtYXRcbiAgICAgICAgbGV0IGVycm9yRGF0YSA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIGVycm9yID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgZXJyb3JEYXRhLm1lc3NhZ2UgPSBlcnJvcjtcbiAgICAgICAgICAgIGVycm9yRGF0YS50eXBlID0gJ21hbnVhbCc7XG4gICAgICAgIH0gZWxzZSBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICAgICAgZXJyb3JEYXRhLm1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgZXJyb3JEYXRhLnN0YWNrID0gZXJyb3Iuc3RhY2s7XG4gICAgICAgICAgICBlcnJvckRhdGEudHlwZSA9ICdleGNlcHRpb24nO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yICYmIHR5cGVvZiBlcnJvciA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGVycm9yRGF0YSA9IGVycm9yO1xuICAgICAgICAgICAgaWYgKCFlcnJvckRhdGEudHlwZSkge1xuICAgICAgICAgICAgICAgIGVycm9yRGF0YS50eXBlID0gJ21hbnVhbCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBEZWJ1Z2dlci5faGFuZGxlX2Jyb3dzZXJfZXJyb3IoZXJyb3JEYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogSGFuZGxlIGJyb3dzZXIgZXJyb3JzIHdpdGggYmF0Y2hpbmdcbiAgICAgKi9cbiAgICBzdGF0aWMgX2hhbmRsZV9icm93c2VyX2Vycm9yKGVycm9yRGF0YSkge1xuICAgICAgICAvLyBDaGVjayBsaW1pdHNcbiAgICAgICAgaWYgKERlYnVnZ2VyLl9lcnJvcl9jb3VudCA+PSBEZWJ1Z2dlci5NQVhfRVJST1JTX1BFUl9QQUdFKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKERlYnVnZ2VyLl9lcnJvcl9iYXRjaF9jb3VudCA+PSBEZWJ1Z2dlci5NQVhfRVJST1JfQkFUQ0hFUykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgRGVidWdnZXIuX2Vycm9yX2NvdW50Kys7XG5cbiAgICAgICAgLy8gQWRkIG1ldGFkYXRhXG4gICAgICAgIGVycm9yRGF0YS51cmwgPSB3aW5kb3cubG9jYXRpb24uaHJlZjtcbiAgICAgICAgZXJyb3JEYXRhLnVzZXJBZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgICAgIGVycm9yRGF0YS50aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG5cbiAgICAgICAgLy8gQWRkIHRvIGJhdGNoXG4gICAgICAgIERlYnVnZ2VyLl9lcnJvcl9iYXRjaC5wdXNoKGVycm9yRGF0YSk7XG5cbiAgICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgdGltZXJcbiAgICAgICAgaWYgKERlYnVnZ2VyLl9lcnJvcl90aW1lcikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KERlYnVnZ2VyLl9lcnJvcl90aW1lcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgZGVib3VuY2UgdGltZXJcbiAgICAgICAgRGVidWdnZXIuX2Vycm9yX3RpbWVyID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5fZmx1c2hfZXJyb3JfYmF0Y2goKTtcbiAgICAgICAgfSwgRGVidWdnZXIuREVCT1VOQ0VfTVMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBCYXRjaCBjb25zb2xlX2RlYnVnIG1lc3NhZ2VzIGZvciBMYXJhdmVsIGxvZ1xuICAgICAqL1xuICAgIHN0YXRpYyBfYmF0Y2hfY29uc29sZV9tZXNzYWdlKG1lc3NhZ2UpIHtcbiAgICAgICAgRGVidWdnZXIuX2NvbnNvbGVfYmF0Y2gucHVzaChtZXNzYWdlKTtcblxuICAgICAgICAvLyBDbGVhciBleGlzdGluZyB0aW1lclxuICAgICAgICBpZiAoRGVidWdnZXIuX2NvbnNvbGVfdGltZXIpIHtcbiAgICAgICAgICAgIGNsZWFyVGltZW91dChEZWJ1Z2dlci5fY29uc29sZV90aW1lcik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgZGVib3VuY2UgdGltZXJcbiAgICAgICAgRGVidWdnZXIuX2NvbnNvbGVfdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIERlYnVnZ2VyLl9mbHVzaF9jb25zb2xlX2JhdGNoKCk7XG4gICAgICAgIH0sIERlYnVnZ2VyLkRFQk9VTkNFX01TKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogRmx1c2ggY29uc29sZV9kZWJ1ZyBiYXRjaCB0byBzZXJ2ZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX2ZsdXNoX2NvbnNvbGVfYmF0Y2goKSB7XG4gICAgICAgIGlmIChEZWJ1Z2dlci5fY29uc29sZV9iYXRjaC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gRGVidWdnZXIuX2NvbnNvbGVfYmF0Y2g7XG4gICAgICAgIERlYnVnZ2VyLl9jb25zb2xlX2JhdGNoID0gW107XG4gICAgICAgIERlYnVnZ2VyLl9jb25zb2xlX3RpbWVyID0gbnVsbDtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIEFqYXguY2FsbChSc3guUm91dGUoJ0RlYnVnZ2VyX0NvbnRyb2xsZXInLCAnbG9nX2NvbnNvbGVfbWVzc2FnZXMnKSwgeyBtZXNzYWdlczogbWVzc2FnZXMgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvLyBTaWxlbnRseSBmYWlsIC0gZG9uJ3QgY3JlYXRlIGVycm9yIGxvb3BcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0ZhaWxlZCB0byBzZW5kIGNvbnNvbGVfZGVidWcgbWVzc2FnZXMgdG8gc2VydmVyOicsIGVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBGbHVzaCBlcnJvciBiYXRjaCB0byBzZXJ2ZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgYXN5bmMgX2ZsdXNoX2Vycm9yX2JhdGNoKCkge1xuICAgICAgICBpZiAoRGVidWdnZXIuX2Vycm9yX2JhdGNoLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXJyb3JzID0gRGVidWdnZXIuX2Vycm9yX2JhdGNoO1xuICAgICAgICBEZWJ1Z2dlci5fZXJyb3JfYmF0Y2ggPSBbXTtcbiAgICAgICAgRGVidWdnZXIuX2Vycm9yX3RpbWVyID0gbnVsbDtcbiAgICAgICAgRGVidWdnZXIuX2Vycm9yX2JhdGNoX2NvdW50Kys7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBBamF4LmNhbGwoUnN4LlJvdXRlKCdEZWJ1Z2dlcl9Db250cm9sbGVyJywgJ2xvZ19icm93c2VyX2Vycm9ycycpLCB7IGVycm9yczogZXJyb3JzIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgLy8gU2lsZW50bHkgZmFpbCAtIGRvbid0IGNyZWF0ZSBlcnJvciBsb29wXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gc2VuZCBicm93c2VyIGVycm9ycyB0byBzZXJ2ZXI6JywgZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW50ZXJuYWw6IEdldCB0aW1lIHByZWZpeCBmb3IgYmVuY2htYXJraW5nXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRfdGltZV9wcmVmaXgoKSB7XG4gICAgICAgIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICAgIGlmICghRGVidWdnZXIuX3N0YXJ0X3RpbWUpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLl9zdGFydF90aW1lID0gbm93O1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGVsYXBzZWQgPSBub3cgLSBEZWJ1Z2dlci5fc3RhcnRfdGltZTtcbiAgICAgICAgcmV0dXJuIChlbGFwc2VkIC8gMTAwMCkudG9GaXhlZCgzKSArICdzJztcbiAgICB9XG59XG4iLCIvLyBASlMtVEhJUy0wMS1FWENFUFRJT05cbi8qKlxuICogalF1ZXJ5IGhlbHBlciBleHRlbnNpb25zIGZvciB0aGUgUlNYIGZyYW1ld29ya1xuICogVGhlc2UgZXh0ZW5zaW9ucyBhZGQgdXRpbGl0eSBtZXRob2RzIHRvIGpRdWVyeSdzIHByb3RvdHlwZVxuICogTm90ZTogJ3RoaXMnIHJlZmVyZW5jZXMgaW4galF1ZXJ5IGV4dGVuc2lvbnMgcmVmZXIgdG8galF1ZXJ5IG9iamVjdHMgYnkgZGVzaWduXG4gKi9cbmNsYXNzIFJzeF9KcV9IZWxwZXJzIHtcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIGpRdWVyeSBleHRlbnNpb25zIHdoZW4gdGhlIGZyYW1ld29yayBjb3JlIGlzIGRlZmluZWRcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZHVyaW5nIGZyYW1ld29yayBpbml0aWFsaXphdGlvblxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX2NvcmVfZGVmaW5lKCkge1xuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYganF1ZXJ5IHNlbGVjdG9yIG1hdGNoZWQgYW4gZWxlbWVudFxuICAgICAgICAkLmZuLmV4aXN0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxlbmd0aCA+IDA7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIGpxdWVyeSBlbGVtZW50IGlzIHZpc2libGVcbiAgICAgICAgJC5mbi5pc192aXNpYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXMoJzp2aXNpYmxlJyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gU2Nyb2xscyB0byB0aGUgdGFyZ2V0IGVsZW1lbnQsIG9ubHkgc2Nyb2xscyB1cC4gIFRvZG86IENyZWF0ZSBhIHZlcnNpb25cbiAgICAgICAgLy8gb2YgdGhpcyB0aGF0IGFsc28gc2Nyb2xscyBvbmx5IGRvd24sIG9yIGJvdGhcbiAgICAgICAgJC5mbi5zY3JvbGxfdXBfdG8gPSBmdW5jdGlvbiAoc3BlZWQgPSAwKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZXhpc3RzKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLndhcm4oXCJDb3VsZCBub3QgZmluZCB0YXJnZXQgZWxlbWVudCB0byBzY3JvbGwgdG9cIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIXRoaXMuaXNfaW5fZG9tKCkpIHtcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLndhcm4oXCJUYXJnZXQgZWxlbWVudCBmb3Igc2Nyb2xsIGlzIG5vdCBvbiBkb21cIik7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgZV90b3AgPSBNYXRoLnJvdW5kKHRoaXMub2Zmc2V0KCkudG9wKTtcbiAgICAgICAgICAgIGxldCBzX3RvcCA9ICQoJ2JvZHknKS5zY3JvbGxUb3AoKTtcbiAgICAgICAgICAgIGlmIChlX3RvcCA8IDApIHtcbiAgICAgICAgICAgICAgICBsZXQgdGFyZ2V0ID0gc190b3AgKyBlX3RvcDtcbiAgICAgICAgICAgICAgICAkKCdodG1sLCBib2R5JykuYW5pbWF0ZShcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsVG9wOiB0YXJnZXQsXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIHNwZWVkXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvLyAkKCkuaXMoXCI6Zm9jdXNcIikgLSBjaGVjayBpZiBlbGVtZW50IGhhcyBmb2N1c1xuICAgICAgICAkLmV4cHJbJzonXS5mb2N1cyA9IGZ1bmN0aW9uIChlbGVtKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbSA9PT0gZG9jdW1lbnQuYWN0aXZlRWxlbWVudCAmJiAoZWxlbS50eXBlIHx8IGVsZW0uaHJlZik7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gU2F2ZSBuYXRpdmUgY2xpY2sgYmVoYXZpb3IgYmVmb3JlIG92ZXJyaWRlXG4gICAgICAgICQuZm4uX2NsaWNrX25hdGl2ZSA9ICQuZm4uY2xpY2s7XG5cbiAgICAgICAgLy8gT3ZlcnJpZGUgLmNsaWNrKCkgdG8gY2FsbCBwcmV2ZW50RGVmYXVsdCBieSBkZWZhdWx0XG4gICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWNjaWRlbnRhbCBwYWdlIG5hdmlnYXRpb24vZm9ybSBzdWJtaXNzaW9uIC0gdGhlIGNvcnJlY3QgYmVoYXZpb3IgOTUlIG9mIHRoZSB0aW1lXG4gICAgICAgICQuZm4uY2xpY2sgPSBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICAgICAgLy8gSWYgbm8gaGFuZGxlciBwcm92aWRlZCwgdHJpZ2dlciBjbGljayBldmVudCAoalF1ZXJ5IC5jbGljaygpIHdpdGggbm8gYXJncylcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaGFuZGxlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fY2xpY2tfbmF0aXZlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCBjbGljayBoYW5kbGVyIHdpdGggYXV0b21hdGljIHByZXZlbnREZWZhdWx0XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5vbignY2xpY2snLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgIC8vIFNhdmUgb3JpZ2luYWwgcHJldmVudERlZmF1bHRcbiAgICAgICAgICAgICAgICBjb25zdCBvcmlnaW5hbF9wcmV2ZW50RGVmYXVsdCA9IGUucHJldmVudERlZmF1bHQuYmluZChlKTtcblxuICAgICAgICAgICAgICAgIC8vIE92ZXJyaWRlIHByZXZlbnREZWZhdWx0IHRvIHNob3cgd2FybmluZyB3aGVuIGNhbGxlZCBleHBsaWNpdGx5XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ2V2ZW50LnByZXZlbnREZWZhdWx0KCkgaXMgY2FsbGVkIGF1dG9tYXRpY2FsbHkgYnkgUlNwYWRlIC5jbGljaygpIGhhbmRsZXJzIGFuZCBjYW4gYmUgcmVtb3ZlZC4nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsX3ByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIC8vIENhbGwgcHJldmVudERlZmF1bHQgYmVmb3JlIGhhbmRsZXJcbiAgICAgICAgICAgICAgICBvcmlnaW5hbF9wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhbmRsZXIuY2FsbCh0aGlzLCBlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEVzY2FwZSBoYXRjaDogY2xpY2sgaGFuZGxlciB3aXRob3V0IHByZXZlbnREZWZhdWx0IGZvciB0aGUgNSUgY2FzZVxuICAgICAgICAkLmZuLmNsaWNrX2FsbG93X2RlZmF1bHQgPSBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBoYW5kbGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jbGlja19uYXRpdmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9jbGlja19uYXRpdmUoaGFuZGxlcik7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoZSBqcXVlcnkgZWxlbWVudCBleGlzdHMgaW4gYW5kIGlzIGF0dGFjaGVkIHRvIHRoZSBET01cbiAgICAgICAgJC5mbi5pc19pbl9kb20gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBsZXQgJGVsZW1lbnQgPSB0aGlzO1xuICAgICAgICAgICAgbGV0IF9hbmNlc3RvciA9IGZ1bmN0aW9uIChIVE1Mb2JqKSB7XG4gICAgICAgICAgICAgICAgd2hpbGUgKEhUTUxvYmoucGFyZW50RWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBIVE1Mb2JqID0gSFRNTG9iai5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gSFRNTG9iajtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gX2FuY2VzdG9yKCRlbGVtZW50WzBdKSA9PT0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFJldHVybnMgdHJ1ZSBpZiB0aGUgZWxlbWVudCBpcyB2aXNpYmxlIGluIHRoZSB2aWV3cG9ydFxuICAgICAgICAkLmZuLmlzX2luX3ZpZXdwb3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbGV0IHNjcm9sbHRvcCA9ICQod2luZG93KS5zY3JvbGxUb3AoKSA+IDAgPyAkKHdpbmRvdykuc2Nyb2xsVG9wKCkgOiAkKCdib2R5Jykuc2Nyb2xsVG9wKCk7XG5cbiAgICAgICAgICAgIGxldCAkZWxlbWVudCA9IHRoaXM7XG5cbiAgICAgICAgICAgIGNvbnN0IHRvcF9vZl9lbGVtZW50ID0gJGVsZW1lbnQub2Zmc2V0KCkudG9wO1xuICAgICAgICAgICAgY29uc3QgYm90dG9tX29mX2VsZW1lbnQgPSAkZWxlbWVudC5vZmZzZXQoKS50b3AgKyAkZWxlbWVudC5vdXRlckhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgYm90dG9tX29mX3NjcmVlbiA9IHNjcm9sbHRvcCArICQod2luZG93KS5pbm5lckhlaWdodCgpO1xuICAgICAgICAgICAgY29uc3QgdG9wX29mX3NjcmVlbiA9IHNjcm9sbHRvcDtcblxuICAgICAgICAgICAgaWYgKGJvdHRvbV9vZl9zY3JlZW4gPiB0b3Bfb2ZfZWxlbWVudCAmJiB0b3Bfb2Zfc2NyZWVuIDwgYm90dG9tX29mX2VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEdldHMgdGhlIHRhZ25hbWUgb2YgYSBqcXVlcnkgZWxlbWVudFxuICAgICAgICAkLmZuLnRhZ25hbWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcm9wKCd0YWdOYW1lJykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBSZXR1cm5zIHRydWUgaWYgYSBocmVmIGlzIG5vdCBzYW1lIGRvbWFpblxuICAgICAgICAkLmZuLmlzX2V4dGVybmFsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3QgaG9zdCA9IHdpbmRvdy5sb2NhdGlvbi5ob3N0O1xuICAgICAgICAgICAgY29uc3QgbGluayA9ICQoJzxhPicsIHtcbiAgICAgICAgICAgICAgICBocmVmOiB0aGlzLmF0dHIoJ2hyZWYnKSxcbiAgICAgICAgICAgIH0pWzBdLmhvc3RuYW1lO1xuICAgICAgICAgICAgcmV0dXJuIGxpbmsgIT09IGhvc3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gSFRNTDUgZm9ybSB2YWxpZGF0aW9uIHdyYXBwZXJzXG4gICAgICAgICQuZm4uY2hlY2tWYWxpZGl0eSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbMF0uY2hlY2tWYWxpZGl0eSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgICQuZm4ucmVwb3J0VmFsaWRpdHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzWzBdLnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgJC5mbi5yZXF1ZXN0U3VibWl0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIHRoaXNbMF0ucmVxdWVzdFN1Ym1pdCgpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRmluZCByZWxhdGVkIGNvbXBvbmVudHMgYnkgc2VhcmNoaW5nIHVwIHRoZSBhbmNlc3RvciB0cmVlXG4gICAgICAgIC8vIExpa2UgLmNsb3Nlc3QoKSBidXQgc2VhcmNoZXMgd2l0aGluIGFuY2VzdG9ycyBpbnN0ZWFkIG9mIG1hdGNoaW5nIHRoZW1cbiAgICAgICAgJC5mbi5jbG9zZXN0X3NpYmxpbmcgPSBmdW5jdGlvbiAoc2VsZWN0b3IpIHtcbiAgICAgICAgICAgIGxldCAkY3VycmVudCA9IHRoaXM7XG4gICAgICAgICAgICBsZXQgJHBhcmVudCA9ICRjdXJyZW50LnBhcmVudCgpO1xuXG4gICAgICAgICAgICAvLyBLZWVwIGdvaW5nIHVwIHRoZSB0cmVlIHVudGlsIHdlIGhpdCBib2R5XG4gICAgICAgICAgICB3aGlsZSAoJHBhcmVudC5sZW5ndGggPiAwICYmICEkcGFyZW50LmlzKCdib2R5JykpIHtcbiAgICAgICAgICAgICAgICAvLyBTZWFyY2ggd2l0aGluIHRoaXMgcGFyZW50IGZvciB0aGUgc2VsZWN0b3JcbiAgICAgICAgICAgICAgICBsZXQgJGZvdW5kID0gJHBhcmVudC5maW5kKHNlbGVjdG9yKTtcbiAgICAgICAgICAgICAgICBpZiAoJGZvdW5kLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICRmb3VuZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBNb3ZlIHVwIG9uZSBsZXZlbFxuICAgICAgICAgICAgICAgICRwYXJlbnQgPSAkcGFyZW50LnBhcmVudCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB3ZSByZWFjaGVkIGJvZHksIHNlYXJjaCB3aXRoaW4gYm9keSBhcyB3ZWxsXG4gICAgICAgICAgICBpZiAoJHBhcmVudC5pcygnYm9keScpKSB7XG4gICAgICAgICAgICAgICAgbGV0ICRmb3VuZCA9ICRwYXJlbnQuZmluZChzZWxlY3Rvcik7XG4gICAgICAgICAgICAgICAgaWYgKCRmb3VuZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAkZm91bmQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBSZXR1cm4gZW1wdHkgalF1ZXJ5IG9iamVjdCBpZiBub3RoaW5nIGZvdW5kXG4gICAgICAgICAgICByZXR1cm4gJCgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIE92ZXJyaWRlICQuYWpheCB0byBwcmV2ZW50IGRpcmVjdCBBSkFYIGNhbGxzIHRvIGxvY2FsIHNlcnZlclxuICAgICAgICAvLyBEZXZlbG9wZXJzIG11c3QgdXNlIHRoZSBBamF4IGVuZHBvaW50IHBhdHRlcm46IGF3YWl0IENvbnRyb2xsZXIubWV0aG9kKHBhcmFtcylcbiAgICAgICAgY29uc3QgbmF0aXZlX2FqYXggPSAkLmFqYXg7XG4gICAgICAgICQuYWpheCA9IGZ1bmN0aW9uICh1cmwsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBib3RoICQuYWpheCh1cmwsIG9wdGlvbnMpIGFuZCAkLmFqYXgob3B0aW9ucykgc2lnbmF0dXJlc1xuICAgICAgICAgICAgbGV0IHNldHRpbmdzO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSBvcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLnVybCA9IHVybDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSB1cmwgfHwge307XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBsb2NhbCByZXF1ZXN0IChyZWxhdGl2ZSBVUkwgb3Igc2FtZSBkb21haW4pXG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0X3VybCA9IHNldHRpbmdzLnVybCB8fCAnJztcbiAgICAgICAgICAgIGNvbnN0IGlzX3JlbGF0aXZlID0gIXJlcXVlc3RfdXJsLm1hdGNoKC9eaHR0cHM/OlxcL1xcLy8pO1xuICAgICAgICAgICAgY29uc3QgaXNfc2FtZV9kb21haW4gPSByZXF1ZXN0X3VybC5zdGFydHNXaXRoKHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pO1xuICAgICAgICAgICAgY29uc3QgaXNfbG9jYWxfcmVxdWVzdCA9IGlzX3JlbGF0aXZlIHx8IGlzX3NhbWVfZG9tYWluO1xuXG4gICAgICAgICAgICAvLyBBbGxvdyBmcmFtZXdvcmsgQWpheC5jYWxsKCkgdG8gZnVuY3Rpb25cbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5fX2xvY2FsX2ludGVncmF0aW9uID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZV9hamF4LmNhbGwodGhpcywgc2V0dGluZ3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBbGxvdyBmaWxlIHVwbG9hZCBlbmRwb2ludCAtIHJlcXVpcmVzIG5hdGl2ZSAkLmFqYXggZm9yIEZvcm1EYXRhIHN1cHBvcnRcbiAgICAgICAgICAgIGNvbnN0IGlzX2ZpbGVfdXBsb2FkID0gcmVxdWVzdF91cmwgPT09ICcvX3VwbG9hZCcgfHwgcmVxdWVzdF91cmwuZW5kc1dpdGgoJy9fdXBsb2FkJyk7XG4gICAgICAgICAgICBpZiAoaXNfZmlsZV91cGxvYWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlX2FqYXguY2FsbCh0aGlzLCBzZXR0aW5ncyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJsb2NrIGxvY2FsIEFKQVggcmVxdWVzdHMgdGhhdCBkb24ndCB1c2UgdGhlIEFqYXggZW5kcG9pbnQgcGF0dGVyblxuICAgICAgICAgICAgaWYgKGlzX2xvY2FsX3JlcXVlc3QpIHtcbiAgICAgICAgICAgICAgICAvLyBUcnkgdG8gcGFyc2UgY29udHJvbGxlciBhbmQgYWN0aW9uIGZyb20gVVJMXG4gICAgICAgICAgICAgICAgbGV0IGNvbnRyb2xsZXJfbmFtZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgbGV0IGFjdGlvbl9uYW1lID0gbnVsbDtcbiAgICAgICAgICAgICAgICBjb25zdCB1cmxfbWF0Y2ggPSByZXF1ZXN0X3VybC5tYXRjaCgvXFwvX3JzeF9hcGlcXC8oW15cXC9dKylcXC8oW15cXC9cXD9dKykvKTtcbiAgICAgICAgICAgICAgICBpZiAodXJsX21hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXJfbmFtZSA9IHVybF9tYXRjaFsxXTtcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uX25hbWUgPSB1cmxfbWF0Y2hbMl07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IGVycm9yX21lc3NhZ2UgPSAnQUpBWCByZXF1ZXN0cyB0byBsb2NhbGhvc3QgdmlhICQuYWpheCgpIGFyZSBwcm9oaWJpdGVkLlxcblxcbic7XG5cbiAgICAgICAgICAgICAgICBpZiAoY29udHJvbGxlcl9uYW1lICYmIGFjdGlvbl9uYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYEluc3RlYWQgb2Y6XFxuYDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgICAkLmFqYXgoe3VybDogJyR7cmVxdWVzdF91cmx9JywgLi4ufSlcXG5cXG5gO1xuICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGBVc2U6XFxuYDtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSArPSBgICBhd2FpdCAke2NvbnRyb2xsZXJfbmFtZX0uJHthY3Rpb25fbmFtZX0ocGFyYW1ldGVycylcXG5cXG5gO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYFVzZSB0aGUgQWpheCBlbmRwb2ludCBwYXR0ZXJuOlxcbmA7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yX21lc3NhZ2UgKz0gYCAgYXdhaXQgQ29udHJvbGxlcl9OYW1lLmFjdGlvbl9uYW1lKHBhcmFtZXRlcnMpXFxuXFxuYDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlICs9IGBUaGUgY29udHJvbGxlciBtZXRob2QgbXVzdCBoYXZlIHRoZSAjW0FqYXhfRW5kcG9pbnRdIGF0dHJpYnV0ZS5gO1xuXG4gICAgICAgICAgICAgICAgc2hvdWxkbnRfaGFwcGVuKGVycm9yX21lc3NhZ2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBbGxvdyBleHRlcm5hbCByZXF1ZXN0cyAoZGlmZmVyZW50IGRvbWFpbilcbiAgICAgICAgICAgIHJldHVybiBuYXRpdmVfYWpheC5jYWxsKHRoaXMsIHNldHRpbmdzKTtcbiAgICAgICAgfTtcbiAgICB9XG59IiwiLy8gQFJPVVRFLUVYSVNUUy0wMS1FWENFUFRJT04gLSBUaGlzIGZpbGUgY29udGFpbnMgZG9jdW1lbnRhdGlvbiBleGFtcGxlcyB3aXRoIGZpY3Rpb25hbCByb3V0ZSBuYW1lc1xuXG4vKipcbiAqIFJzeCAtIENvcmUgSmF2YVNjcmlwdCBSdW50aW1lIFN5c3RlbVxuICpcbiAqIFRoZSBSc3ggY2xhc3MgaXMgdGhlIGNlbnRyYWwgaHViIGZvciB0aGUgUlNYIEphdmFTY3JpcHQgcnVudGltZSwgcHJvdmlkaW5nIGVzc2VudGlhbFxuICogc3lzdGVtLWxldmVsIHV0aWxpdGllcyB0aGF0IGFsbCBvdGhlciBmcmFtZXdvcmsgY29tcG9uZW50cyBkZXBlbmQgb24uIEl0IHNlcnZlcyBhcyB0aGVcbiAqIGZvdW5kYXRpb24gZm9yIHRoZSBjbGllbnQtc2lkZSBmcmFtZXdvcmssIGhhbmRsaW5nIGNvcmUgb3BlcmF0aW9ucyB0aGF0IG11c3QgYmUgZ2xvYmFsbHlcbiAqIGFjY2Vzc2libGUgYW5kIGNvbnNpc3RlbnRseSBhdmFpbGFibGUuXG4gKlxuICogQ29yZSBSZXNwb25zaWJpbGl0aWVzOlxuICogLSBFdmVudCBTeXN0ZW06IEFwcGxpY2F0aW9uLXdpZGUgZXZlbnQgYnVzIGZvciBmcmFtZXdvcmsgbGlmZWN5Y2xlIGFuZCBjdXN0b20gZXZlbnRzXG4gKiAtIEVudmlyb25tZW50IERldGVjdGlvbjogUnVudGltZSBlbnZpcm9ubWVudCBpZGVudGlmaWNhdGlvbiAoZGV2L3Byb2R1Y3Rpb24pXG4gKiAtIFJvdXRlIE1hbmFnZW1lbnQ6IFR5cGUtc2FmZSByb3V0ZSBnZW5lcmF0aW9uIGFuZCBVUkwgYnVpbGRpbmdcbiAqIC0gVW5pcXVlIElEIEdlbmVyYXRpb246IENsaWVudC1zaWRlIHVuaXF1ZSBpZGVudGlmaWVyIGdlbmVyYXRpb25cbiAqIC0gRnJhbWV3b3JrIEJvb3RzdHJhcDogTXVsdGktcGhhc2UgaW5pdGlhbGl6YXRpb24gb3JjaGVzdHJhdGlvblxuICogLSBMb2dnaW5nOiBDZW50cmFsaXplZCBsb2dnaW5nIGludGVyZmFjZSAoZGVsZWdhdGVzIHRvIGNvbnNvbGVfZGVidWcpXG4gKlxuICogVGhlIFJzeCBjbGFzcyBkZWxpYmVyYXRlbHkga2VlcHMgaXRzIHNjb3BlIGxpbWl0ZWQgdG8gY29yZSB1dGlsaXRpZXMuIEFkdmFuY2VkIGZlYXR1cmVzXG4gKiBhcmUgZGVsZWdhdGVkIHRvIHNwZWNpYWxpemVkIGNsYXNzZXM6XG4gKiAtIE1hbmlmZXN0IG9wZXJhdGlvbnMg4oaSIE1hbmlmZXN0IGNsYXNzXG4gKiAtIENhY2hpbmcg4oaSIFJzeF9DYWNoZSBjbGFzc1xuICogLSBBSkFYL0FQSSBjYWxscyDihpIgQWpheF8qIGNsYXNzZXNcbiAqIC0gUm91dGUgcHJveGllcyDihpIgUnN4X1JvdXRlX1Byb3h5IGNsYXNzXG4gKiAtIEJlaGF2aW9ycyDihpIgUnN4X0JlaGF2aW9ycyBjbGFzc1xuICpcbiAqIEFsbCBtZXRob2RzIGFyZSBzdGF0aWMgLSBSc3ggaXMgbmV2ZXIgaW5zdGFudGlhdGVkLiBJdCdzIGF2YWlsYWJsZSBnbG9iYWxseSBmcm9tIHRoZVxuICogbW9tZW50IGJ1bmRsZXMgbG9hZCBhbmQgcmVtYWlucyBjb25zdGFudCB0aHJvdWdob3V0IHRoZSBhcHBsaWNhdGlvbiBsaWZlY3ljbGUuXG4gKlxuICogVXNhZ2UgRXhhbXBsZXM6XG4gKiBgYGBqYXZhc2NyaXB0XG4gKiAvLyBFdmVudCBzeXN0ZW1cbiAqIFJzeC5vbignYXBwX3JlYWR5JywgKCkgPT4gY29uc29sZS5sb2coJ0FwcCBpbml0aWFsaXplZCcpKTtcbiAqIFJzeC50cmlnZ2VyKCdjdXN0b21fZXZlbnQnLCB7ZGF0YTogJ3ZhbHVlJ30pO1xuICpcbiAqIC8vIEVudmlyb25tZW50IGRldGVjdGlvblxuICogaWYgKFJzeC5pc19kZXYoKSkgeyBjb25zb2xlLmxvZygnRGV2ZWxvcG1lbnQgbW9kZScpOyB9XG4gKlxuICogLy8gUm91dGUgZ2VuZXJhdGlvblxuICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdDb250cm9sbGVyJywgJ2FjdGlvbicpLnVybCgpO1xuICpcbiAqIC8vIFVuaXF1ZSBJRHNcbiAqIGNvbnN0IHVuaXF1ZUlkID0gUnN4LnVpZCgpOyAvLyBlLmcuLCBcInJzeF8xMjM0NTY3ODkwXzFcIlxuICogYGBgXG4gKlxuICogQHN0YXRpY1xuICogQGdsb2JhbFxuICovXG5jbGFzcyBSc3gge1xuICAgIC8vIEdldHMgc2V0IHRvIHRydWUgdG8gaW50ZXJ1cHQgc3RhcnR1cCBzZXF1ZW5jZVxuICAgIHN0YXRpYyBfX3N0b3BwZWQgPSBmYWxzZTtcblxuICAgIC8vIEluaXRpYWxpemUgZXZlbnQgaGFuZGxlcnMgc3RvcmFnZVxuICAgIHN0YXRpYyBfaW5pdF9ldmVudHMoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgUnN4Ll9ldmVudF9oYW5kbGVycyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIFJzeC5fZXZlbnRfaGFuZGxlcnMgPSB7fTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIFJzeC5fdHJpZ2dlcmVkX2V2ZW50cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIFJzeC5fdHJpZ2dlcmVkX2V2ZW50cyA9IHt9O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmVnaXN0ZXIgYW4gZXZlbnQgaGFuZGxlclxuICAgIHN0YXRpYyBvbihldmVudCwgY2FsbGJhY2spIHtcbiAgICAgICAgUnN4Ll9pbml0X2V2ZW50cygpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XSA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgUnN4Ll9ldmVudF9oYW5kbGVyc1tldmVudF0ucHVzaChjYWxsYmFjayk7XG5cbiAgICAgICAgLy8gSWYgdGhpcyBldmVudCB3YXMgYWxyZWFkeSB0cmlnZ2VyZWQsIGNhbGwgdGhlIGNhbGxiYWNrIGltbWVkaWF0ZWx5XG4gICAgICAgIGlmIChSc3guX3RyaWdnZXJlZF9ldmVudHNbZXZlbnRdKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdUcmlnZ2VyaW5nICcgKyBldmVudCArICcgZm9yIGxhdGUgcmVnaXN0ZXJlZCBjYWxsYmFjaycpO1xuICAgICAgICAgICAgY2FsbGJhY2soUnN4Ll90cmlnZ2VyZWRfZXZlbnRzW2V2ZW50XSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBUcmlnZ2VyIGFuIGV2ZW50IHdpdGggb3B0aW9uYWwgZGF0YVxuICAgIHN0YXRpYyB0cmlnZ2VyKGV2ZW50LCBkYXRhID0ge30pIHtcbiAgICAgICAgUnN4Ll9pbml0X2V2ZW50cygpO1xuXG4gICAgICAgIC8vIFJlY29yZCB0aGF0IHRoaXMgZXZlbnQgd2FzIHRyaWdnZXJlZFxuICAgICAgICBSc3guX3RyaWdnZXJlZF9ldmVudHNbZXZlbnRdID0gZGF0YTtcblxuICAgICAgICBpZiAoIVJzeC5fZXZlbnRfaGFuZGxlcnNbZXZlbnRdKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdUcmlnZ2VyaW5nICcgKyBldmVudCArICcgZm9yICcgKyBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XS5sZW5ndGggKyAnIGNhbGxiYWNrcycpO1xuXG4gICAgICAgIC8vIENhbGwgYWxsIHJlZ2lzdGVyZWQgaGFuZGxlcnMgZm9yIHRoaXMgZXZlbnQgaW4gb3JkZXJcbiAgICAgICAgZm9yIChjb25zdCBjYWxsYmFjayBvZiBSc3guX2V2ZW50X2hhbmRsZXJzW2V2ZW50XSkge1xuICAgICAgICAgICAgY2FsbGJhY2soZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBbGlhcyBmb3IgdHJpZ2dlci5yZWZyZXNoKCcnKSwgc2hvdWxkIGJlIGNhbGxlZCBhZnRlciBtYWpvciBVSSB1cGRhdGVzIHRvIGFwcGx5IHN1Y2ggZWZmZWN0cyBhc1xuICAgIC8vIHVuZGVybGluaW5nIGxpbmtzIHRvIHVuaW1wbGVtZW50ZWQgIyByb3V0ZXNcbiAgICBzdGF0aWMgdHJpZ2dlcl9yZWZyZXNoKCkge1xuICAgICAgICAvLyBVc2UgUnN4Lm9uKCdyZWZyZXNoJywgY2FsbGJhY2spOyB0byByZWdpc3RlciBhIGNhbGxiYWNrIGZvciByZWZyZXNoXG4gICAgICAgIHRoaXMudHJpZ2dlcigncmVmcmVzaCcpO1xuICAgIH1cblxuICAgIC8vIExvZyB0byBzZXJ2ZXIgdGhhdCBhbiBldmVudCBoYXBwZW5lZFxuICAgIHN0YXRpYyBsb2codHlwZSwgbWVzc2FnZSA9ICdub3RpY2UnKSB7XG4gICAgICAgIENvcmVfTG9nLmxvZyh0eXBlLCBtZXNzYWdlKTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIHRydWUgaWYgdGhlIGFwcCBpcyBiZWluZyBydW4gaW4gZGV2IG1vZGVcbiAgICAvLyBUaGlzIHNob3VsZCBhZmZlY3QgY2FjaGluZyBhbmQgc29tZSBkZWJ1ZyBjaGVja3NcbiAgICBzdGF0aWMgaXNfZGV2KCkge1xuICAgICAgICByZXR1cm4gd2luZG93LnJzeGFwcC5kZWJ1ZztcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNfcHJvZCgpIHtcbiAgICAgICAgcmV0dXJuICF3aW5kb3cucnN4YXBwLmRlYnVnO1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlcyBhIHVuaXF1ZSBudW1iZXIgZm9yIHRoZSBhcHBsaWNhdGlvbiBpbnN0YW5jZVxuICAgIHN0YXRpYyB1aWQoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgUnN4Ll91aWQgPT0gdW5kZWYpIHtcbiAgICAgICAgICAgIFJzeC5fdWlkID0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUnN4Ll91aWQrKztcbiAgICB9XG5cbiAgICAvLyBTdG9yYWdlIGZvciByb3V0ZSBkZWZpbml0aW9ucyBsb2FkZWQgZnJvbSBidW5kbGVzXG4gICAgc3RhdGljIF9yb3V0ZXMgPSB7fTtcblxuICAgIC8qKlxuICAgICAqIERlZmluZSByb3V0ZXMgZnJvbSBidW5kbGVkIGRhdGFcbiAgICAgKiBDYWxsZWQgYnkgZ2VuZXJhdGVkIEphdmFTY3JpcHQgaW4gYnVuZGxlc1xuICAgICAqL1xuICAgIHN0YXRpYyBfZGVmaW5lX3JvdXRlcyhyb3V0ZXMpIHtcbiAgICAgICAgLy8gTWVyZ2Ugcm91dGVzIGludG8gdGhlIGdsb2JhbCByb3V0ZSBzdG9yYWdlXG4gICAgICAgIGZvciAoY29uc3QgY2xhc3NfbmFtZSBpbiByb3V0ZXMpIHtcbiAgICAgICAgICAgIGlmICghUnN4Ll9yb3V0ZXNbY2xhc3NfbmFtZV0pIHtcbiAgICAgICAgICAgICAgICBSc3guX3JvdXRlc1tjbGFzc19uYW1lXSA9IHt9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChjb25zdCBtZXRob2RfbmFtZSBpbiByb3V0ZXNbY2xhc3NfbmFtZV0pIHtcbiAgICAgICAgICAgICAgICBSc3guX3JvdXRlc1tjbGFzc19uYW1lXVttZXRob2RfbmFtZV0gPSByb3V0ZXNbY2xhc3NfbmFtZV1bbWV0aG9kX25hbWVdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgVVJMIGZvciBhIGNvbnRyb2xsZXIgcm91dGVcbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGdlbmVyYXRlcyBVUkxzIGZvciBjb250cm9sbGVyIGFjdGlvbnMgYnkgbG9va2luZyB1cCByb3V0ZSBwYXR0ZXJuc1xuICAgICAqIGFuZCByZXBsYWNpbmcgcGFyYW1ldGVycy4gSXQgaGFuZGxlcyBib3RoIHJlZ3VsYXIgcm91dGVzIGFuZCBBamF4IGVuZHBvaW50cy5cbiAgICAgKlxuICAgICAqIElmIHRoZSByb3V0ZSBpcyBub3QgZm91bmQgaW4gdGhlIHJvdXRlIGRlZmluaXRpb25zLCBhIGRlZmF1bHQgcGF0dGVybiBpcyB1c2VkOlxuICAgICAqIGAvXy97Y29udHJvbGxlcn0ve2FjdGlvbn1gIHdpdGggYWxsIHBhcmFtZXRlcnMgYXBwZW5kZWQgYXMgcXVlcnkgc3RyaW5ncy5cbiAgICAgKlxuICAgICAqIFVzYWdlIGV4YW1wbGVzOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiAvLyBTaW1wbGUgcm91dGUgd2l0aG91dCBwYXJhbWV0ZXJzIChkZWZhdWx0cyB0byAnaW5kZXgnIGFjdGlvbilcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0luZGV4X0NvbnRyb2xsZXInKTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvZGFzaGJvYXJkXG4gICAgICpcbiAgICAgKiAvLyBSb3V0ZSB3aXRoIGV4cGxpY2l0IGFjdGlvblxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfSW5kZXhfQ29udHJvbGxlcicsICdpbmRleCcpO1xuICAgICAqIC8vIFJldHVybnM6IC9kYXNoYm9hcmRcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggaW50ZWdlciBwYXJhbWV0ZXIgKHNldHMgJ2lkJylcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0NsaWVudF9WaWV3X0NvbnRyb2xsZXInLCAndmlldycsIDEyMyk7XG4gICAgICogLy8gUmV0dXJuczogL2NsaWVudHMvdmlldy8xMjNcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggbmFtZWQgcGFyYW1ldGVycyAob2JqZWN0KVxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnJvbnRlbmRfQ2xpZW50X1ZpZXdfQ29udHJvbGxlcicsICd2aWV3Jywge2lkOiAnQzAwMSd9KTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvY2xpZW50cy92aWV3L0MwMDFcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIHdpdGggcmVxdWlyZWQgYW5kIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgICAgKiBjb25zdCB1cmwgPSBSc3guUm91dGUoJ0Zyb250ZW5kX0NsaWVudF9WaWV3X0NvbnRyb2xsZXInLCAndmlldycsIHtcbiAgICAgKiAgICAgaWQ6ICdDMDAxJyxcbiAgICAgKiAgICAgdGFiOiAnaGlzdG9yeSdcbiAgICAgKiB9KTtcbiAgICAgKiAvLyBSZXR1cm5zOiAvY2xpZW50cy92aWV3L0MwMDE/dGFiPWhpc3RvcnlcbiAgICAgKlxuICAgICAqIC8vIFJvdXRlIG5vdCBmb3VuZCAtIHVzZXMgZGVmYXVsdCBwYXR0ZXJuXG4gICAgICogY29uc3QgdXJsID0gUnN4LlJvdXRlKCdVbmltcGxlbWVudGVkX0NvbnRyb2xsZXInLCAnc29tZV9hY3Rpb24nLCB7Zm9vOiAnYmFyJ30pO1xuICAgICAqIC8vIFJldHVybnM6IC9fL1VuaW1wbGVtZW50ZWRfQ29udHJvbGxlci9zb21lX2FjdGlvbj9mb289YmFyXG4gICAgICpcbiAgICAgKiAvLyBQbGFjZWhvbGRlciByb3V0ZVxuICAgICAqIGNvbnN0IHVybCA9IFJzeC5Sb3V0ZSgnRnV0dXJlX0NvbnRyb2xsZXInLCAnI2luZGV4Jyk7XG4gICAgICogLy8gUmV0dXJuczogI1xuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzX25hbWUgVGhlIGNvbnRyb2xsZXIgY2xhc3MgbmFtZSAoZS5nLiwgJ1VzZXJfQ29udHJvbGxlcicpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IFthY3Rpb25fbmFtZT0naW5kZXgnXSBUaGUgYWN0aW9uL21ldGhvZCBuYW1lIChkZWZhdWx0cyB0byAnaW5kZXgnKS4gVXNlICcjYWN0aW9uJyBmb3IgcGxhY2Vob2xkZXJzLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfE9iamVjdH0gW3BhcmFtcz1udWxsXSBSb3V0ZSBwYXJhbWV0ZXJzLiBJbnRlZ2VyIHNldHMgJ2lkJywgb2JqZWN0IHByb3ZpZGVzIG5hbWVkIHBhcmFtcy5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIFVSTFxuICAgICAqL1xuICAgIHN0YXRpYyBSb3V0ZShjbGFzc19uYW1lLCBhY3Rpb25fbmFtZSA9ICdpbmRleCcsIHBhcmFtcyA9IG51bGwpIHtcbiAgICAgICAgLy8gTm9ybWFsaXplIHBhcmFtcyB0byBvYmplY3RcbiAgICAgICAgbGV0IHBhcmFtc19vYmogPSB7fTtcbiAgICAgICAgaWYgKHR5cGVvZiBwYXJhbXMgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBwYXJhbXNfb2JqID0geyBpZDogcGFyYW1zIH07XG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBwYXJhbXNfb2JqID0gcGFyYW1zO1xuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtcyAhPT0gbnVsbCAmJiBwYXJhbXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQYXJhbXMgbXVzdCBiZSBudW1iZXIsIG9iamVjdCwgb3IgbnVsbCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUGxhY2Vob2xkZXIgcm91dGU6IGFjdGlvbiBzdGFydHMgd2l0aCAjIG1lYW5zIHVuaW1wbGVtZW50ZWQvc2NhZmZvbGRpbmdcbiAgICAgICAgaWYgKGFjdGlvbl9uYW1lLnN0YXJ0c1dpdGgoJyMnKSkge1xuICAgICAgICAgICAgcmV0dXJuICcjJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGlmIHJvdXRlIGV4aXN0cyBpbiBkZWZpbml0aW9uc1xuICAgICAgICBsZXQgcGF0dGVybjtcbiAgICAgICAgaWYgKFJzeC5fcm91dGVzW2NsYXNzX25hbWVdICYmIFJzeC5fcm91dGVzW2NsYXNzX25hbWVdW2FjdGlvbl9uYW1lXSkge1xuICAgICAgICAgICAgcGF0dGVybiA9IFJzeC5fcm91dGVzW2NsYXNzX25hbWVdW2FjdGlvbl9uYW1lXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFJvdXRlIG5vdCBmb3VuZCAtIHVzZSBkZWZhdWx0IHBhdHRlcm4gL18ve2NvbnRyb2xsZXJ9L3thY3Rpb259XG4gICAgICAgICAgICBwYXR0ZXJuID0gYC9fLyR7Y2xhc3NfbmFtZX0vJHthY3Rpb25fbmFtZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgVVJMIGZyb20gcGF0dGVyblxuICAgICAgICByZXR1cm4gUnN4Ll9nZW5lcmF0ZV91cmxfZnJvbV9wYXR0ZXJuKHBhdHRlcm4sIHBhcmFtc19vYmopO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIFVSTCBmcm9tIHJvdXRlIHBhdHRlcm4gYnkgcmVwbGFjaW5nIHBhcmFtZXRlcnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwYXR0ZXJuIFRoZSByb3V0ZSBwYXR0ZXJuIChlLmcuLCAnL3VzZXJzLzppZC92aWV3JylcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIFBhcmFtZXRlcnMgdG8gZmlsbCBpbnRvIHRoZSByb3V0ZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBnZW5lcmF0ZWQgVVJMXG4gICAgICovXG4gICAgc3RhdGljIF9nZW5lcmF0ZV91cmxfZnJvbV9wYXR0ZXJuKHBhdHRlcm4sIHBhcmFtcykge1xuICAgICAgICAvLyBFeHRyYWN0IHJlcXVpcmVkIHBhcmFtZXRlcnMgZnJvbSB0aGUgcGF0dGVyblxuICAgICAgICBjb25zdCByZXF1aXJlZF9wYXJhbXMgPSBbXTtcbiAgICAgICAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWF0Y2goLzooW2EtekEtWl9dW2EtekEtWjAtOV9dKikvZyk7XG4gICAgICAgIGlmIChtYXRjaGVzKSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgdGhlIDogcHJlZml4IGZyb20gZWFjaCBtYXRjaFxuICAgICAgICAgICAgZm9yIChjb25zdCBtYXRjaCBvZiBtYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgcmVxdWlyZWRfcGFyYW1zLnB1c2gobWF0Y2guc3Vic3RyaW5nKDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGZvciByZXF1aXJlZCBwYXJhbWV0ZXJzXG4gICAgICAgIGNvbnN0IG1pc3NpbmcgPSBbXTtcbiAgICAgICAgZm9yIChjb25zdCByZXF1aXJlZCBvZiByZXF1aXJlZF9wYXJhbXMpIHtcbiAgICAgICAgICAgIGlmICghKHJlcXVpcmVkIGluIHBhcmFtcykpIHtcbiAgICAgICAgICAgICAgICBtaXNzaW5nLnB1c2gocmVxdWlyZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1pc3NpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXF1aXJlZCBwYXJhbWV0ZXJzIFske21pc3Npbmcuam9pbignLCAnKX1dIGFyZSBtaXNzaW5nIGZvciByb3V0ZSAke3BhdHRlcm59YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBCdWlsZCB0aGUgVVJMIGJ5IHJlcGxhY2luZyBwYXJhbWV0ZXJzXG4gICAgICAgIGxldCB1cmwgPSBwYXR0ZXJuO1xuICAgICAgICBjb25zdCB1c2VkX3BhcmFtcyA9IHt9O1xuXG4gICAgICAgIGZvciAoY29uc3QgcGFyYW1fbmFtZSBvZiByZXF1aXJlZF9wYXJhbXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcGFyYW1zW3BhcmFtX25hbWVdO1xuICAgICAgICAgICAgLy8gVVJMIGVuY29kZSB0aGUgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IGVuY29kZWRfdmFsdWUgPSBlbmNvZGVVUklDb21wb25lbnQodmFsdWUpO1xuICAgICAgICAgICAgdXJsID0gdXJsLnJlcGxhY2UoJzonICsgcGFyYW1fbmFtZSwgZW5jb2RlZF92YWx1ZSk7XG4gICAgICAgICAgICB1c2VkX3BhcmFtc1twYXJhbV9uYW1lXSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb2xsZWN0IGFueSBleHRyYSBwYXJhbWV0ZXJzIGZvciBxdWVyeSBzdHJpbmdcbiAgICAgICAgY29uc3QgcXVlcnlfcGFyYW1zID0ge307XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHBhcmFtcykge1xuICAgICAgICAgICAgaWYgKCF1c2VkX3BhcmFtc1trZXldKSB7XG4gICAgICAgICAgICAgICAgcXVlcnlfcGFyYW1zW2tleV0gPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEFwcGVuZCBxdWVyeSBzdHJpbmcgaWYgdGhlcmUgYXJlIGV4dHJhIHBhcmFtZXRlcnNcbiAgICAgICAgaWYgKE9iamVjdC5rZXlzKHF1ZXJ5X3BhcmFtcykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgcXVlcnlfc3RyaW5nID0gT2JqZWN0LmVudHJpZXMocXVlcnlfcGFyYW1zKVxuICAgICAgICAgICAgICAgIC5tYXAoKFtrZXksIHZhbHVlXSkgPT4gYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGtleSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKX1gKVxuICAgICAgICAgICAgICAgIC5qb2luKCcmJyk7XG4gICAgICAgICAgICB1cmwgKz0gJz8nICsgcXVlcnlfc3RyaW5nO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVybDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnRlcm5hbDogQ2FsbCBhIHNwZWNpZmljIG1ldGhvZCBvbiBhbGwgY2xhc3NlcyB0aGF0IGhhdmUgaXRcbiAgICAgKiBDb2xsZWN0cyBwcm9taXNlcyBmcm9tIHJldHVybiB2YWx1ZXMgYW5kIHdhaXRzIGZvciBhbGwgdG8gcmVzb2x2ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RfbmFtZSBUaGUgbWV0aG9kIG5hbWUgdG8gY2FsbCBvbiBhbGwgY2xhc3Nlc1xuICAgICAqIEByZXR1cm5zIHtQcm9taXNlfSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiBhbGwgbWV0aG9kIGNhbGxzIGNvbXBsZXRlXG4gICAgICovXG4gICAgc3RhdGljIGFzeW5jIF9yc3hfY2FsbF9hbGxfY2xhc3NlcyhtZXRob2RfbmFtZSkge1xuICAgICAgICBjb25zdCBhbGxfY2xhc3NlcyA9IE1hbmlmZXN0LmdldF9hbGxfY2xhc3NlcygpO1xuICAgICAgICBjb25zdCBjbGFzc2VzX3dpdGhfbWV0aG9kID0gW107XG4gICAgICAgIGNvbnN0IHByb21pc2VfcGlsZSA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3QgY2xhc3NfaW5mbyBvZiBhbGxfY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3Nfb2JqZWN0ID0gY2xhc3NfaW5mby5jbGFzc19vYmplY3Q7XG4gICAgICAgICAgICBjb25zdCBjbGFzc19uYW1lID0gY2xhc3NfaW5mby5jbGFzc19uYW1lO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGlzIGNsYXNzIGhhcyB0aGUgbWV0aG9kIChzdGF0aWMgbWV0aG9kcyBhcmUgb24gdGhlIGNsYXNzIGl0c2VsZilcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2xhc3Nfb2JqZWN0W21ldGhvZF9uYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIGNsYXNzZXNfd2l0aF9tZXRob2QucHVzaChjbGFzc19uYW1lKTtcbiAgICAgICAgICAgICAgICBjb25zdCByZXR1cm5fdmFsdWUgPSBhd2FpdCBjbGFzc19vYmplY3RbbWV0aG9kX25hbWVdKCk7XG5cbiAgICAgICAgICAgICAgICAvLyBDb2xsZWN0IHByb21pc2VzIGZyb20gcmV0dXJuIHZhbHVlXG4gICAgICAgICAgICAgICAgaWYgKHJldHVybl92YWx1ZSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZV9waWxlLnB1c2gocmV0dXJuX3ZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkocmV0dXJuX3ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgcmV0dXJuX3ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXRlbSBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlX3BpbGUucHVzaChpdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChSc3guX19zdG9wcGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2xhc3Nlc193aXRoX21ldGhvZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsIGAke21ldGhvZF9uYW1lfTogJHtjbGFzc2VzX3dpdGhfbWV0aG9kLmxlbmd0aH0gY2xhc3Nlc2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXdhaXQgYWxsIHByb21pc2VzIGJlZm9yZSByZXR1cm5pbmdcbiAgICAgICAgaWYgKHByb21pc2VfcGlsZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBjb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsIGAke21ldGhvZF9uYW1lfTogQXdhaXRpbmcgJHtwcm9taXNlX3BpbGUubGVuZ3RofSBwcm9taXNlc2ApO1xuICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZV9waWxlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEludGVybmFsOiBFeGVjdXRlIG11bHRpLXBoYXNlIGluaXRpYWxpemF0aW9uIGZvciBhbGwgcmVnaXN0ZXJlZCBjbGFzc2VzXG4gICAgICogVGhpcyBydW5zIHZhcmlvdXMgaW5pdGlhbGl6YXRpb24gcGhhc2VzIGluIG9yZGVyIHRvIHByb3Blcmx5IHNldCB1cCB0aGUgYXBwbGljYXRpb25cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gYWxsIGluaXRpYWxpemF0aW9uIHBoYXNlcyBjb21wbGV0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfcnN4X2NvcmVfYm9vdCgpIHtcbiAgICAgICAgaWYgKFJzeC5fX2Jvb3RlZCkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcignUnN4Ll9yc3hfY29yZV9ib290IGNhbGxlZCBtb3JlIHRoYW4gb25jZScpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgUnN4Ll9fYm9vdGVkID0gdHJ1ZTtcblxuICAgICAgICAvLyBHZXQgYWxsIHJlZ2lzdGVyZWQgY2xhc3NlcyBmcm9tIHRoZSBtYW5pZmVzdFxuICAgICAgICBjb25zdCBhbGxfY2xhc3NlcyA9IE1hbmlmZXN0LmdldF9hbGxfY2xhc3NlcygpO1xuXG4gICAgICAgIGNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgYFN0YXJ0aW5nIF9yc3hfY29yZV9ib290IHdpdGggJHthbGxfY2xhc3Nlcy5sZW5ndGh9IGNsYXNzZXNgKTtcblxuICAgICAgICBpZiAoIWFsbF9jbGFzc2VzIHx8IGFsbF9jbGFzc2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgLy8gTm8gY2xhc3NlcyB0byBpbml0aWFsaXplXG4gICAgICAgICAgICBzaG91bGRudF9oYXBwZW4oJ05vIGNsYXNzZXMgcmVnaXN0ZXJlZCBpbiBqcyAtIHRoZXJlIHNob3VsZCBiZSBhdCBsZWFzdCB0aGUgY29yZSBmcmFtZXdvcmsgY2xhc3NlcycpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmaW5lIGluaXRpYWxpemF0aW9uIHBoYXNlcyBpbiBvcmRlclxuICAgICAgICBjb25zdCBwaGFzZXMgPSBbXG4gICAgICAgICAgICB7IGV2ZW50OiAnZnJhbWV3b3JrX2NvcmVfZGVmaW5lJywgbWV0aG9kOiAnX29uX2ZyYW1ld29ya19jb3JlX2RlZmluZScgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdmcmFtZXdvcmtfbW9kdWxlc19kZWZpbmUnLCBtZXRob2Q6ICdfb25fZnJhbWV3b3JrX21vZHVsZXNfZGVmaW5lJyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2ZyYW1ld29ya19jb3JlX2luaXQnLCBtZXRob2Q6ICdfb25fZnJhbWV3b3JrX2NvcmVfaW5pdCcgfSxcbiAgICAgICAgICAgIHsgZXZlbnQ6ICdhcHBfbW9kdWxlc19kZWZpbmUnLCBtZXRob2Q6ICdvbl9hcHBfbW9kdWxlc19kZWZpbmUnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX2RlZmluZScsIG1ldGhvZDogJ29uX2FwcF9kZWZpbmUnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnZnJhbWV3b3JrX21vZHVsZXNfaW5pdCcsIG1ldGhvZDogJ19vbl9mcmFtZXdvcmtfbW9kdWxlc19pbml0JyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9tb2R1bGVzX2luaXQnLCBtZXRob2Q6ICdvbl9hcHBfbW9kdWxlc19pbml0JyB9LFxuICAgICAgICAgICAgeyBldmVudDogJ2FwcF9pbml0JywgbWV0aG9kOiAnb25fYXBwX2luaXQnIH0sXG4gICAgICAgICAgICB7IGV2ZW50OiAnYXBwX3JlYWR5JywgbWV0aG9kOiAnb25fYXBwX3JlYWR5JyB9LFxuICAgICAgICBdO1xuXG4gICAgICAgIC8vIEV4ZWN1dGUgZWFjaCBwaGFzZSBpbiBvcmRlclxuICAgICAgICBmb3IgKGNvbnN0IHBoYXNlIG9mIHBoYXNlcykge1xuICAgICAgICAgICAgYXdhaXQgUnN4Ll9yc3hfY2FsbF9hbGxfY2xhc3NlcyhwaGFzZS5tZXRob2QpO1xuXG4gICAgICAgICAgICBpZiAoUnN4Ll9fc3RvcHBlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgUnN4LnRyaWdnZXIocGhhc2UuZXZlbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVWkgcmVmcmVzaCBjYWxsYmFja3NcbiAgICAgICAgUnN4LnRyaWdnZXJfcmVmcmVzaCgpO1xuXG4gICAgICAgIC8vIEFsbCBwaGFzZXMgY29tcGxldGVcbiAgICAgICAgY29uc29sZV9kZWJ1ZygnUlNYX0lOSVQnLCAnSW5pdGlhbGl6YXRpb24gY29tcGxldGUnKTtcblxuICAgICAgICAvLyBUT0RPOiBGaW5kIGEgZ29vZCB3YWl0IHRvIHdhaXQgZm9yIGFsbCBqcWh0bWwgY29tcG9uZW50cyB0byBsb2FkLCB0aGVuIHRyaWdnZXIgb25fcmVhZHkgYW5kIG9uKCdyZWFkeScpIGVtdWxhdGluZyB0aGUgdG9wIGxldmVsIGxhc3Qgc3ludGF4IHRoYXQganFodG1sIGNvbXBvbmVudHMgb3BlcmF0ZWFzLCBidXQgYXMgYSBzdGFuZGFyZCBqcyBjbGFzcyAoc3VjaCBhcyBhIHBhZ2UgY2xhc3MpLiAgVGhlIGJpZ2dlc3QgcXVlc3Rpb24gaXMsIGhvdyBkbyB3ZSBlZmZpY2llbnRseSBjaG9vc2Ugb25seSB0aGUgdG9wIGxldmVsIGpxaHRtbCBjb21wb25lbnRzLiAgZG8gd2Ugb25seSBjb25zaWRlciBjb21wb25lbnRzIGNyZXRhZWQgZGlyZWN0bHkgb24gYmxhZGUgdGVtcGxhdGVzPyB0aGF0IHNlYW1zIHJlYXNvbmFibGUuLi5cblxuICAgICAgICAvLyBUcmlnZ2VyIF9kZWJ1Z19yZWFkeSBldmVudCAtIHRoaXMgaXMgT05MWSBmb3IgdG9vbGluZyBsaWtlIHJzeDpkZWJ1Z1xuICAgICAgICAvLyBETyBOT1QgdXNlIHRoaXMgaW4gYXBwbGljYXRpb24gY29kZSAtIHVzZSBvbl9hcHBfcmVhZHkoKSBwaGFzZSBpbnN0ZWFkXG4gICAgICAgIC8vIFRoaXMgZXZlbnQgZXhpc3RzIHNvbGVseSBmb3IgZGVidWdnaW5nIHRvb2xzIHRoYXQgbmVlZCB0byBydW4gYWZ0ZXIgZnVsbCBpbml0aWFsaXphdGlvblxuICAgICAgICBSc3gudHJpZ2dlcignX2RlYnVnX3JlYWR5Jyk7XG4gICAgfVxuXG4gICAgLyogQ2FsbGluZyB0aGlzIHN0b3BzIHRoZSBib290IHByb2Nlc3MuICovXG4gICAgc3RhdGljIGFzeW5jIF9yc3hfY29yZV9ib290X3N0b3AocmVhc29uKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IocmVhc29uKTtcbiAgICAgICAgUnN4Ll9fc3RvcHBlZCA9IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2UgVVJMIGhhc2ggaW50byBrZXktdmFsdWUgb2JqZWN0XG4gICAgICogSGFuZGxlcyBmb3JtYXQ6ICNrZXk9dmFsdWUma2V5Mj12YWx1ZTJcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtPYmplY3R9IFBhcnNlZCBoYXNoIHBhcmFtZXRlcnNcbiAgICAgKi9cbiAgICBzdGF0aWMgX3BhcnNlX2hhc2goKSB7XG4gICAgICAgIGNvbnN0IGhhc2ggPSB3aW5kb3cubG9jYXRpb24uaGFzaDtcbiAgICAgICAgaWYgKCFoYXNoIHx8IGhhc2ggPT09ICcjJykge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVtb3ZlIGxlYWRpbmcgIyBhbmQgcGFyc2UgYXMgcXVlcnkgc3RyaW5nXG4gICAgICAgIGNvbnN0IGhhc2hfc3RyaW5nID0gaGFzaC5zdWJzdHJpbmcoMSk7XG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHt9O1xuXG4gICAgICAgIGNvbnN0IHBhaXJzID0gaGFzaF9zdHJpbmcuc3BsaXQoJyYnKTtcbiAgICAgICAgZm9yIChjb25zdCBwYWlyIG9mIHBhaXJzKSB7XG4gICAgICAgICAgICBjb25zdCBba2V5LCB2YWx1ZV0gPSBwYWlyLnNwbGl0KCc9Jyk7XG4gICAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgcGFyYW1zW2RlY29kZVVSSUNvbXBvbmVudChrZXkpXSA9IHZhbHVlID8gZGVjb2RlVVJJQ29tcG9uZW50KHZhbHVlKSA6ICcnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBhcmFtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgb2JqZWN0IGludG8gVVJMIGhhc2ggZm9ybWF0XG4gICAgICogUHJvZHVjZXMgZm9ybWF0OiAja2V5PXZhbHVlJmtleTI9dmFsdWUyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcGFyYW1zIEtleS12YWx1ZSBwYWlycyB0byBlbmNvZGVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBFbmNvZGVkIGhhc2ggc3RyaW5nICh3aXRoIGxlYWRpbmcgIywgb3IgZW1wdHkgc3RyaW5nKVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplX2hhc2gocGFyYW1zKSB7XG4gICAgICAgIGNvbnN0IHBhaXJzID0gW107XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHBhcmFtcykge1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwYXJhbXNba2V5XTtcbiAgICAgICAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSAnJykge1xuICAgICAgICAgICAgICAgIHBhaXJzLnB1c2goYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGtleSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYWlycy5sZW5ndGggPiAwID8gJyMnICsgcGFpcnMuam9pbignJicpIDogJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBwYWdlIHN0YXRlIGZyb20gVVJMIGhhc2hcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBjb25zdCBzdGF0ZSA9IFJzeC5nZXRfYWxsX3BhZ2Vfc3RhdGUoKTtcbiAgICAgKiAvLyBSZXR1cm5zOiB7ZGdfcGFnZTogJzInLCBkZ19zb3J0OiAnbmFtZSd9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBBbGwgaGFzaCBwYXJhbWV0ZXJzIGFzIGtleS12YWx1ZSBwYWlyc1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfYWxsX3BhZ2Vfc3RhdGUoKSB7XG4gICAgICAgIHJldHVybiBSc3guX3BhcnNlX2hhc2goKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgc2luZ2xlIHZhbHVlIGZyb20gVVJMIGhhc2ggc3RhdGVcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBjb25zdCBwYWdlID0gUnN4LmdldF9wYWdlX3N0YXRlKCdkZ19wYWdlJyk7XG4gICAgICogLy8gUmV0dXJuczogJzInIG9yIG51bGwgaWYgbm90IHNldFxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IHRvIHJldHJpZXZlXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBUaGUgdmFsdWUgb3IgbnVsbCBpZiBub3QgZm91bmRcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X3BhZ2Vfc3RhdGUoa2V5KSB7XG4gICAgICAgIGNvbnN0IHN0YXRlID0gUnN4Ll9wYXJzZV9oYXNoKCk7XG4gICAgICAgIHJldHVybiBzdGF0ZVtrZXldID8/IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHNpbmdsZSB2YWx1ZSBpbiBVUkwgaGFzaCBzdGF0ZSAocmVwbGFjZXMgaGlzdG9yeSwgZG9lc24ndCBhZGQpXG4gICAgICpcbiAgICAgKiBVc2FnZTpcbiAgICAgKiBgYGBqYXZhc2NyaXB0XG4gICAgICogUnN4LnNldF9wYWdlX3N0YXRlKCdkZ19wYWdlJywgMik7XG4gICAgICogLy8gVVJMIGJlY29tZXM6IGh0dHA6Ly9leGFtcGxlLmNvbS9wYWdlI2RnX3BhZ2U9MlxuICAgICAqXG4gICAgICogUnN4LnNldF9wYWdlX3N0YXRlKCdkZ19wYWdlJywgbnVsbCk7IC8vIFJlbW92ZSBrZXlcbiAgICAgKiBgYGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSB0byBzZXRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8bnVsbH0gdmFsdWUgVGhlIHZhbHVlIChudWxsL2VtcHR5IHJlbW92ZXMgdGhlIGtleSlcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0X3BhZ2Vfc3RhdGUoa2V5LCB2YWx1ZSkge1xuICAgICAgICBjb25zdCBzdGF0ZSA9IFJzeC5fcGFyc2VfaGFzaCgpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBvciByZW1vdmUgdGhlIGtleVxuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBzdGF0ZVtrZXldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RhdGVba2V5XSA9IFN0cmluZyh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgVVJMIHdpdGhvdXQgYWRkaW5nIGhpc3RvcnlcbiAgICAgICAgY29uc3QgbmV3X2hhc2ggPSBSc3guX3NlcmlhbGl6ZV9oYXNoKHN0YXRlKTtcbiAgICAgICAgY29uc3QgdXJsID0gd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lICsgd2luZG93LmxvY2F0aW9uLnNlYXJjaCArIG5ld19oYXNoO1xuICAgICAgICBoaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCAnJywgdXJsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgbXVsdGlwbGUgdmFsdWVzIGluIFVSTCBoYXNoIHN0YXRlIGF0IG9uY2VcbiAgICAgKlxuICAgICAqIFVzYWdlOlxuICAgICAqIGBgYGphdmFzY3JpcHRcbiAgICAgKiBSc3guc2V0X2FsbF9wYWdlX3N0YXRlKHtkZ19wYWdlOiAyLCBkZ19zb3J0OiAnbmFtZSd9KTtcbiAgICAgKiAvLyBVUkwgYmVjb21lczogaHR0cDovL2V4YW1wbGUuY29tL3BhZ2UjZGdfcGFnZT0yJmRnX3NvcnQ9bmFtZVxuICAgICAqIGBgYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtPYmplY3R9IG5ld19zdGF0ZSBPYmplY3Qgd2l0aCBrZXktdmFsdWUgcGFpcnMgdG8gc2V0XG4gICAgICovXG4gICAgc3RhdGljIHNldF9hbGxfcGFnZV9zdGF0ZShuZXdfc3RhdGUpIHtcbiAgICAgICAgY29uc3Qgc3RhdGUgPSBSc3guX3BhcnNlX2hhc2goKTtcblxuICAgICAgICAvLyBNZXJnZSBuZXcgc3RhdGVcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gbmV3X3N0YXRlKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IG5ld19zdGF0ZVtrZXldO1xuICAgICAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHN0YXRlW2tleV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0YXRlW2tleV0gPSBTdHJpbmcodmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIFVSTCB3aXRob3V0IGFkZGluZyBoaXN0b3J5XG4gICAgICAgIGNvbnN0IG5ld19oYXNoID0gUnN4Ll9zZXJpYWxpemVfaGFzaChzdGF0ZSk7XG4gICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSArIHdpbmRvdy5sb2NhdGlvbi5zZWFyY2ggKyBuZXdfaGFzaDtcbiAgICAgICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUobnVsbCwgJycsIHVybCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVuZGVyIGFuIGVycm9yIGluIGEgRE9NIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIERpc3BsYXlzIGVycm9ycyBmcm9tIEFqYXggY2FsbHMgaW4gYSBzdGFuZGFyZGl6ZWQgZm9ybWF0LiBIYW5kbGVzIGRpZmZlcmVudFxuICAgICAqIGVycm9yIHR5cGVzIChmYXRhbCwgdmFsaWRhdGlvbiwgYXV0aCwgZ2VuZXJpYykgd2l0aCBhcHByb3ByaWF0ZSBmb3JtYXR0aW5nLlxuICAgICAqXG4gICAgICogVXNhZ2U6XG4gICAgICogYGBgamF2YXNjcmlwdFxuICAgICAqIHRyeSB7XG4gICAgICogICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IENvbnRyb2xsZXIubWV0aG9kKCk7XG4gICAgICogfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgKiAgICAgUnN4LnJlbmRlcl9lcnJvcihlcnJvciwgJyNlcnJvcl9jb250YWluZXInKTtcbiAgICAgKiB9XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0Vycm9yfE9iamVjdH0gZXJyb3IgLSBFcnJvciBvYmplY3QgZnJvbSBBamF4IGNhbGxcbiAgICAgKiBAcGFyYW0ge2pRdWVyeXxzdHJpbmd9IGNvbnRhaW5lciAtIGpRdWVyeSBlbGVtZW50IG9yIHNlbGVjdG9yIGZvciBlcnJvciBkaXNwbGF5XG4gICAgICovXG4gICAgc3RhdGljIHJlbmRlcl9lcnJvcihlcnJvciwgY29udGFpbmVyKSB7XG4gICAgICAgIGNvbnN0ICRjb250YWluZXIgPSAkKGNvbnRhaW5lcik7XG5cbiAgICAgICAgaWYgKCEkY29udGFpbmVyLmV4aXN0cygpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdSc3gucmVuZGVyX2Vycm9yOiBDb250YWluZXIgbm90IGZvdW5kJywgY29udGFpbmVyKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENsZWFyIGV4aXN0aW5nIGNvbnRlbnRcbiAgICAgICAgJGNvbnRhaW5lci5lbXB0eSgpO1xuXG4gICAgICAgIGxldCBodG1sID0gJyc7XG5cbiAgICAgICAgLy8gSGFuZGxlIGRpZmZlcmVudCBlcnJvciB0eXBlc1xuICAgICAgICBpZiAoZXJyb3IudHlwZSA9PT0gJ2ZhdGFsJyAmJiBlcnJvci5kZXRhaWxzKSB7XG4gICAgICAgICAgICAvLyBGYXRhbCBQSFAgZXJyb3Igd2l0aCBmaWxlL2xpbmUvZXJyb3JcbiAgICAgICAgICAgIGNvbnN0IGRldGFpbHMgPSBlcnJvci5kZXRhaWxzO1xuICAgICAgICAgICAgY29uc3QgZmlsZSA9IGRldGFpbHMuZmlsZSB8fCAnVW5rbm93biBmaWxlJztcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBkZXRhaWxzLmxpbmUgfHwgJz8nO1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IGRldGFpbHMuZXJyb3IgfHwgZXJyb3IubWVzc2FnZSB8fCAnRmF0YWwgZXJyb3Igb2NjdXJyZWQnO1xuXG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPGg1PlVuY2F1Z2h0IEZhdGFsIEVycm9yIGluICR7ZmlsZX06JHtsaW5lfTo8L2g1PlxuICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj4ke1JzeC5fZXNjYXBlX2h0bWwobWVzc2FnZSl9PC9wPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgYDtcbiAgICAgICAgfSBlbHNlIGlmIChlcnJvci50eXBlID09PSAnZm9ybV9lcnJvcicgJiYgZXJyb3IuZGV0YWlscykge1xuICAgICAgICAgICAgLy8gVmFsaWRhdGlvbiBlcnJvcnMgLSBzaG93IHVubWF0Y2hlZCBlcnJvcnMgb25seVxuICAgICAgICAgICAgLy8gKG1hdGNoZWQgZXJyb3JzIHNob3VsZCBiZSBoYW5kbGVkIGJ5IEZvcm1fVXRpbHMuYXBwbHlfZm9ybV9lcnJvcnMpXG4gICAgICAgICAgICBjb25zdCBlcnJvcnMgPSBlcnJvci5kZXRhaWxzO1xuICAgICAgICAgICAgY29uc3QgZXJyb3JfbGlzdCA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkIGluIGVycm9ycykge1xuICAgICAgICAgICAgICAgIGVycm9yX2xpc3QucHVzaChlcnJvcnNbZmllbGRdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGVycm9yX2xpc3QubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGh0bWwgPSBgXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aDU+VmFsaWRhdGlvbiBFcnJvcnM6PC9oNT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx1bCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAke2Vycm9yX2xpc3QubWFwKGVyciA9PiBgPGxpPiR7UnN4Ll9lc2NhcGVfaHRtbChlcnIpfTwvbGk+YCkuam9pbignJyl9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3VsPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICBgO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGVycm9yLnR5cGUgPT09ICdhdXRoX3JlcXVpcmVkJyB8fCBlcnJvci50eXBlID09PSAndW5hdXRob3JpemVkJykge1xuICAgICAgICAgICAgLy8gQXV0aGVudGljYXRpb24vYXV0aG9yaXphdGlvbiBlcnJvcnNcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8ICdBdXRoZW50aWNhdGlvbiByZXF1aXJlZCc7XG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC13YXJuaW5nXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPiR7UnN4Ll9lc2NhcGVfaHRtbChtZXNzYWdlKX08L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgICAgICB9IGVsc2UgaWYgKGVycm9yLnR5cGUgPT09ICduZXR3b3JrJykge1xuICAgICAgICAgICAgLy8gTmV0d29yayBlcnJvcnNcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8ICdVbmFibGUgdG8gcmVhY2ggc2VydmVyLiBQbGVhc2UgY2hlY2sgeW91ciBjb25uZWN0aW9uLic7XG4gICAgICAgICAgICBodG1sID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIiByb2xlPVwiYWxlcnRcIj5cbiAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+JHtSc3guX2VzY2FwZV9odG1sKG1lc3NhZ2UpfTwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBHZW5lcmljL3Vua25vd24gZXJyb3JcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlIHx8IGVycm9yLnRvU3RyaW5nKCkgfHwgJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQnO1xuICAgICAgICAgICAgaHRtbCA9IGBcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCIgcm9sZT1cImFsZXJ0XCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPiR7UnN4Ll9lc2NhcGVfaHRtbChtZXNzYWdlKX08L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICBgO1xuICAgICAgICB9XG5cbiAgICAgICAgJGNvbnRhaW5lci5odG1sKGh0bWwpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVzY2FwZSBIVE1MIHRvIHByZXZlbnQgWFNTIGluIGVycm9yIG1lc3NhZ2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2VzY2FwZV9odG1sKHRleHQpIHtcbiAgICAgICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIGRpdi50ZXh0Q29udGVudCA9IHRleHQ7XG4gICAgICAgIHJldHVybiBkaXYuaW5uZXJIVE1MO1xuICAgIH1cbn1cbiIsIi8vIEBGSUxFLVNVQkNMQVNTLTAxLUVYQ0VQVElPTlxuXG4vKipcbiAqIENsaWVudC1zaWRlIEFqYXggY2xhc3MgZm9yIG1ha2luZyBBUEkgY2FsbHMgdG8gUlNYIGNvbnRyb2xsZXJzXG4gKlxuICogQXV0b21hdGljYWxseSBiYXRjaGVzIG11bHRpcGxlIGNhbGxzIGludG8gc2luZ2xlIEhUVFAgcmVxdWVzdHMgdG8gcmVkdWNlIG5ldHdvcmsgb3ZlcmhlYWQuXG4gKiBCYXRjaGVzIHVwIHRvIDIwIGNhbGxzIG9yIGZsdXNoZXMgYWZ0ZXIgc2V0VGltZW91dCgwKSBkZWJvdW5jZS5cbiAqL1xuY2xhc3MgQWpheCB7XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSBBamF4IHN5c3RlbVxuICAgICAqIENhbGxlZCBhdXRvbWF0aWNhbGx5IHdoZW4gY2xhc3MgaXMgbG9hZGVkXG4gICAgICovXG4gICAgc3RhdGljIF9vbl9mcmFtZXdvcmtfY29yZV9pbml0KCkge1xuICAgICAgICAvLyBRdWV1ZSBvZiBwZW5kaW5nIGNhbGxzIHdhaXRpbmcgdG8gYmUgYmF0Y2hlZFxuICAgICAgICBBamF4Ll9wZW5kaW5nX2NhbGxzID0ge307XG5cbiAgICAgICAgLy8gVGltZXIgZm9yIGJhdGNoaW5nIGZsdXNoXG4gICAgICAgIEFqYXguX2ZsdXNoX3RpbWVvdXQgPSBudWxsO1xuXG4gICAgICAgIC8vIENhbGwgY291bnRlciBmb3IgZ2VuZXJhdGluZyB1bmlxdWUgY2FsbCBJRHNcbiAgICAgICAgQWpheC5fY2FsbF9jb3VudGVyID0gMDtcblxuICAgICAgICAvLyBNYXhpbXVtIGJhdGNoIHNpemUgYmVmb3JlIGZvcmNpbmcgaW1tZWRpYXRlIGZsdXNoXG4gICAgICAgIEFqYXguTUFYX0JBVENIX1NJWkUgPSAyMDtcblxuICAgICAgICAvLyBEZWJvdW5jZSB0aW1lIGluIG1pbGxpc2Vjb25kc1xuICAgICAgICBBamF4LkRFQk9VTkNFX01TID0gMDtcblxuICAgICAgICAvLyBUcmFjayBwcm9taXNlcyBmcm9tIEFqYXggY2FsbHMgdG8gZGV0ZWN0IHVuY2F1Z2h0IHJlamVjdGlvbnNcbiAgICAgICAgQWpheC5fdHJhY2tlZF9wcm9taXNlcyA9IG5ldyBXZWFrU2V0KCk7XG5cbiAgICAgICAgLy8gU2V0IHVwIGdsb2JhbCB1bmhhbmRsZWQgcmVqZWN0aW9uIGhhbmRsZXIgZm9yIEFqYXggZXJyb3JzXG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCd1bmhhbmRsZWRyZWplY3Rpb24nLCBhc3luYyAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIC8vIE9ubHkgaGFuZGxlIHJlamVjdGlvbnMgZnJvbSBBamF4IHByb21pc2VzXG4gICAgICAgICAgICBpZiAoQWpheC5fdHJhY2tlZF9wcm9taXNlcy5oYXMoZXZlbnQucHJvbWlzZSkpIHtcbiAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBQcmV2ZW50IGJyb3dzZXIncyBkZWZhdWx0IFwiVW5jYXVnaHQgKGluIHByb21pc2UpXCIgZXJyb3JcblxuICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0gZXZlbnQucmVhc29uO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ1VuY2F1Z2h0IEFqYXggZXJyb3I6JywgZXJyb3IpO1xuXG4gICAgICAgICAgICAgICAgLy8gU2hvdyBNb2RhbC5lcnJvcigpIGZvciB1bmNhdWdodCBBamF4IGVycm9yc1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgTW9kYWwgIT09ICd1bmRlZmluZWQnICYmIE1vZGFsLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IE1vZGFsLmVycm9yKGVycm9yLCAnVW5jYXVnaHQgQWpheCBFcnJvcicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFrZSBhbiBBSkFYIGNhbGwgdG8gYW4gUlNYIGNvbnRyb2xsZXIgYWN0aW9uXG4gICAgICpcbiAgICAgKiBBbGwgY2FsbHMgYXJlIGF1dG9tYXRpY2FsbHkgYmF0Y2hlZCB1bmxlc3Mgd2luZG93LnJzeGFwcC5hamF4X2Rpc2FibGVfYmF0Y2hpbmcgaXMgdHJ1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG9iamVjdHxmdW5jdGlvbn0gdXJsIC0gVGhlIEFqYXggVVJMIChlLmcuLCAnL19hamF4L0NvbnRyb2xsZXJfTmFtZS9hY3Rpb25fbmFtZScpIG9yIGFuIG9iamVjdC9mdW5jdGlvbiB3aXRoIGEgLnBhdGggcHJvcGVydHlcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcGFyYW1zIC0gUGFyYW1ldGVycyB0byBzZW5kIHRvIHRoZSBhY3Rpb25cbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZX0gLSBSZXNvbHZlcyB3aXRoIHRoZSByZXR1cm4gdmFsdWUsIHJlamVjdHMgd2l0aCBlcnJvclxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBjYWxsKHVybCwgcGFyYW1zID0ge30pIHtcbiAgICAgICAgLy8gSWYgdXJsIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB3aXRoIGEgLnBhdGggcHJvcGVydHksIHVzZSB0aGF0IGFzIHRoZSBVUkxcbiAgICAgICAgaWYgKHVybCAmJiB0eXBlb2YgdXJsID09PSAnb2JqZWN0JyAmJiB1cmwucGF0aCkge1xuICAgICAgICAgICAgdXJsID0gdXJsLnBhdGg7XG4gICAgICAgIH0gZWxzZSBpZiAodXJsICYmIHR5cGVvZiB1cmwgPT09ICdmdW5jdGlvbicgJiYgdXJsLnBhdGgpIHtcbiAgICAgICAgICAgIHVybCA9IHVybC5wYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgdXJsIGlzIGEgbm9uLWVtcHR5IHN0cmluZ1xuICAgICAgICBpZiAodHlwZW9mIHVybCAhPT0gJ3N0cmluZycgfHwgdXJsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBamF4LmNhbGwoKSByZXF1aXJlcyBhIG5vbi1lbXB0eSBzdHJpbmcgVVJMIG9yIGFuIG9iamVjdC9mdW5jdGlvbiB3aXRoIGEgLnBhdGggcHJvcGVydHknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEV4dHJhY3QgY29udHJvbGxlciBhbmQgYWN0aW9uIGZyb20gVVJMXG4gICAgICAgIGNvbnN0IHsgY29udHJvbGxlciwgYWN0aW9uIH0gPSBBamF4LmFqYXhfdXJsX3RvX2NvbnRyb2xsZXJfYWN0aW9uKHVybCk7XG5cbiAgICAgICAgY29uc29sZS5sb2coJ0FqYXg6JywgY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMpO1xuXG4gICAgICAgIC8vIENoZWNrIGlmIGJhdGNoaW5nIGlzIGRpc2FibGVkIGZvciBkZWJ1Z2dpbmdcbiAgICAgICAgbGV0IHByb21pc2U7XG4gICAgICAgIGlmICh3aW5kb3cucnN4YXBwICYmIHdpbmRvdy5yc3hhcHAuYWpheF9kaXNhYmxlX2JhdGNoaW5nKSB7XG4gICAgICAgICAgICBwcm9taXNlID0gQWpheC5fY2FsbF9kaXJlY3QoY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcHJvbWlzZSA9IEFqYXguX2NhbGxfYmF0Y2goY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhY2sgdGhpcyBwcm9taXNlIGZvciB1bmhhbmRsZWQgcmVqZWN0aW9uIGRldGVjdGlvblxuICAgICAgICBBamF4Ll90cmFja2VkX3Byb21pc2VzLmFkZChwcm9taXNlKTtcblxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlIGEgYmF0Y2hlZCBBamF4IGNhbGxcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2FsbF9iYXRjaChjb250cm9sbGVyLCBhY3Rpb24sIHBhcmFtcyA9IHt9KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdBamF4IEJhdGNoOicsIGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zKTtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgLy8gR2VuZXJhdGUgY2FsbCBrZXkgZm9yIGRlZHVwbGljYXRpb25cbiAgICAgICAgICAgIGNvbnN0IGNhbGxfa2V5ID0gQWpheC5fZ2VuZXJhdGVfY2FsbF9rZXkoY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMpO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGlzIGV4YWN0IGNhbGwgaXMgYWxyZWFkeSBwZW5kaW5nXG4gICAgICAgICAgICBpZiAoQWpheC5fcGVuZGluZ19jYWxsc1tjYWxsX2tleV0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ19jYWxsID0gQWpheC5fcGVuZGluZ19jYWxsc1tjYWxsX2tleV07XG5cbiAgICAgICAgICAgICAgICAvLyBJZiBjYWxsIGFscmVhZHkgY29tcGxldGVkIChjYWNoZWQpLCByZXR1cm4gaW1tZWRpYXRlbHlcbiAgICAgICAgICAgICAgICBpZiAoZXhpc3RpbmdfY2FsbC5pc19jb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhpc3RpbmdfY2FsbC5pc19lcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGV4aXN0aW5nX2NhbGwuZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShleGlzdGluZ19jYWxsLnJlc3VsdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIENhbGwgaXMgcGVuZGluZywgYWRkIHRoaXMgcHJvbWlzZSB0byBjYWxsYmFja3NcbiAgICAgICAgICAgICAgICBleGlzdGluZ19jYWxsLmNhbGxiYWNrcy5wdXNoKHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIG5ldyBwZW5kaW5nIGNhbGxcbiAgICAgICAgICAgIGNvbnN0IGNhbGxfaWQgPSBBamF4Ll9jYWxsX2NvdW50ZXIrKztcbiAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdfY2FsbCA9IHtcbiAgICAgICAgICAgICAgICBjYWxsX2lkOiBjYWxsX2lkLFxuICAgICAgICAgICAgICAgIGNhbGxfa2V5OiBjYWxsX2tleSxcbiAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBjb250cm9sbGVyLFxuICAgICAgICAgICAgICAgIGFjdGlvbjogYWN0aW9uLFxuICAgICAgICAgICAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgICAgICAgICAgICAgIGNhbGxiYWNrczogW3sgcmVzb2x2ZSwgcmVqZWN0IH1dLFxuICAgICAgICAgICAgICAgIGlzX2NvbXBsZXRlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBpc19lcnJvcjogZmFsc2UsXG4gICAgICAgICAgICAgICAgcmVzdWx0OiBudWxsLFxuICAgICAgICAgICAgICAgIGVycm9yOiBudWxsLFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIHRvIHBlbmRpbmcgcXVldWVcbiAgICAgICAgICAgIEFqYXguX3BlbmRpbmdfY2FsbHNbY2FsbF9rZXldID0gcGVuZGluZ19jYWxsO1xuXG4gICAgICAgICAgICAvLyBDb3VudCBwZW5kaW5nIGNhbGxzXG4gICAgICAgICAgICBjb25zdCBwZW5kaW5nX2NvdW50ID0gT2JqZWN0LmtleXMoQWpheC5fcGVuZGluZ19jYWxscykuZmlsdGVyKChrZXkpID0+ICFBamF4Ll9wZW5kaW5nX2NhbGxzW2tleV0uaXNfY29tcGxldGUpLmxlbmd0aDtcblxuICAgICAgICAgICAgLy8gSWYgd2UndmUgaGl0IHRoZSBiYXRjaCBzaXplIGxpbWl0LCBmbHVzaCBpbW1lZGlhdGVseVxuICAgICAgICAgICAgaWYgKHBlbmRpbmdfY291bnQgPj0gQWpheC5NQVhfQkFUQ0hfU0laRSkge1xuICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChBamF4Ll9mbHVzaF90aW1lb3V0KTtcbiAgICAgICAgICAgICAgICBBamF4Ll9mbHVzaF90aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICBBamF4Ll9mbHVzaF9wZW5kaW5nX2NhbGxzKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFNjaGVkdWxlIGJhdGNoIGZsdXNoIHdpdGggZGVib3VuY2VcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoQWpheC5fZmx1c2hfdGltZW91dCk7XG4gICAgICAgICAgICAgICAgQWpheC5fZmx1c2hfdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBBamF4Ll9mbHVzaF9wZW5kaW5nX2NhbGxzKCk7XG4gICAgICAgICAgICAgICAgfSwgQWpheC5ERUJPVU5DRV9NUyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2UgYSBkaXJlY3QgKG5vbi1iYXRjaGVkKSBBamF4IGNhbGxcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfY2FsbF9kaXJlY3QoY29udHJvbGxlciwgYWN0aW9uLCBwYXJhbXMgPSB7fSkge1xuICAgICAgICAvLyBDb25zdHJ1Y3QgVVJMIGZyb20gY29udHJvbGxlciBhbmQgYWN0aW9uXG4gICAgICAgIGNvbnN0IHVybCA9IGAvX2FqYXgvJHtjb250cm9sbGVyfS8ke2FjdGlvbn1gO1xuXG4gICAgICAgIC8vIExvZyB0aGUgQUpBWCBjYWxsIHVzaW5nIGNvbnNvbGVfZGVidWdcbiAgICAgICAgaWYgKHR5cGVvZiBEZWJ1Z2dlciAhPT0gJ3VuZGVmaW5lZCcgJiYgRGVidWdnZXIuY29uc29sZV9kZWJ1Zykge1xuICAgICAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZygnQUpBWCcsIGBDYWxsaW5nICR7Y29udHJvbGxlcn0uJHthY3Rpb259ICh1bmJhdGNoZWQpYCwgcGFyYW1zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAkLmFqYXgoe1xuICAgICAgICAgICAgICAgIHVybDogdXJsLFxuICAgICAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgICAgIGRhdGE6IHBhcmFtcyxcbiAgICAgICAgICAgICAgICBkYXRhVHlwZTogJ2pzb24nLFxuICAgICAgICAgICAgICAgIF9fbG9jYWxfaW50ZWdyYXRpb246IHRydWUsIC8vIEJ5cGFzcyAkLmFqYXggb3ZlcnJpZGVcbiAgICAgICAgICAgICAgICBzdWNjZXNzOiAocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIGNvbnNvbGVfZGVidWcgbWVzc2FnZXNcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmNvbnNvbGVfZGVidWcgJiYgQXJyYXkuaXNBcnJheShyZXNwb25zZS5jb25zb2xlX2RlYnVnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UuY29uc29sZV9kZWJ1Zy5mb3JFYWNoKChtc2cpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobXNnKSB8fCBtc2cubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb25zb2xlX2RlYnVnIG1lc3NhZ2UgZm9ybWF0IC0gZXhwZWN0ZWQgW2NoYW5uZWwsIFthcmd1bWVudHNdXScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbY2hhbm5lbCwgYXJnc10gPSBtc2c7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coY2hhbm5lbCwgLi4uYXJncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSByZXNwb25zZSB3YXMgc3VjY2Vzc2Z1bFxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UuX3N1Y2Nlc3MgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEBKUy1BSkFYLTAyLUVYQ0VQVElPTiAtIFVud3JhcCBzZXJ2ZXIgcmVzcG9uc2VzIHdpdGggX2FqYXhfcmV0dXJuX3ZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9jZXNzZWRfdmFsdWUgPSBSc3hfSnNfTW9kZWwuX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUocmVzcG9uc2UuX2FqYXhfcmV0dXJuX3ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBlcnJvciByZXNwb25zZXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yX3R5cGUgPSByZXNwb25zZS5lcnJvcl90eXBlIHx8ICd1bmtub3duX2Vycm9yJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlYXNvbiA9IHJlc3BvbnNlLnJlYXNvbiB8fCAnVW5rbm93biBlcnJvciBvY2N1cnJlZCc7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkZXRhaWxzID0gcmVzcG9uc2UuZGV0YWlscyB8fCB7fTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIHNwZWNpZmljIGVycm9yIHR5cGVzXG4gICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGVycm9yX3R5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdmYXRhbCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhdGFsIFBIUCBlcnJvciB3aXRoIGZ1bGwgZXJyb3IgZGV0YWlsc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmYXRhbF9lcnJvcl9kYXRhID0gcmVzcG9uc2UuZXJyb3IgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yX21lc3NhZ2UgPSBmYXRhbF9lcnJvcl9kYXRhLmVycm9yIHx8ICdGYXRhbCBlcnJvciBvY2N1cnJlZCc7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignQWpheCBlcnJvciByZXNwb25zZSBmcm9tIHNlcnZlcjonLCByZXNwb25zZS5lcnJvcik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmF0YWxfZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3JfbWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhdGFsX2Vycm9yLnR5cGUgPSAnZmF0YWwnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYXRhbF9lcnJvci5kZXRhaWxzID0gcmVzcG9uc2UuZXJyb3I7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTG9nIHRvIHNlcnZlciBpZiBicm93c2VyIGVycm9yIGxvZ2dpbmcgaXMgZW5hYmxlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWJ1Z2dlci5sb2dfZXJyb3Ioe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYEFqYXggRmF0YWwgRXJyb3I6ICR7ZXJyb3JfbWVzc2FnZX1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2FqYXhfZmF0YWwnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kcG9pbnQ6IHVybCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldGFpbHM6IHJlc3BvbnNlLmVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZmF0YWxfZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3Jlc3BvbnNlX2F1dGhfcmVxdWlyZWQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1RoZSB1c2VyIGlzIG5vIGxvbmdlciBhdXRoZW50aWNhdGVkLCB0aGlzIGlzIGEgcGxhY2Vob2xkZXIgZm9yIGZ1dHVyZSBjb2RlIHdoaWNoIGhhbmRsZXMgdGhpcyBzY2VuYXJpby4nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGF1dGhfZXJyb3IgPSBuZXcgRXJyb3IocmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0aF9lcnJvci50eXBlID0gJ2F1dGhfcmVxdWlyZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRoX2Vycm9yLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoYXV0aF9lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVzcG9uc2VfdW5hdXRob3JpemVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdUaGUgdXNlciBpcyB1bmF1dGhvcml6ZWQgdG8gcGVyZm9ybSB0aGlzIGFjdGlvbiwgdGhpcyBpcyBhIHBsYWNlaG9sZGVyIGZvciBmdXR1cmUgY29kZSB3aGljaCBoYW5kbGVzIHRoaXMgc2NlbmFyaW8uJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1bmF1dGhfZXJyb3IgPSBuZXcgRXJyb3IocmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5hdXRoX2Vycm9yLnR5cGUgPSAndW5hdXRob3JpemVkJztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5hdXRoX2Vycm9yLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QodW5hdXRoX2Vycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdyZXNwb25zZV9mb3JtX2Vycm9yJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZm9ybV9lcnJvciA9IG5ldyBFcnJvcihyZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtX2Vycm9yLnR5cGUgPSAnZm9ybV9lcnJvcic7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1fZXJyb3IuZGV0YWlscyA9IGRldGFpbHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChmb3JtX2Vycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBnZW5lcmljX2Vycm9yID0gbmV3IEVycm9yKHJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyaWNfZXJyb3IudHlwZSA9IGVycm9yX3R5cGU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVyaWNfZXJyb3IuZGV0YWlscyA9IGRldGFpbHM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChnZW5lcmljX2Vycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGVycm9yOiAoeGhyLCBzdGF0dXMsIGVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yX21lc3NhZ2UgPSBBamF4Ll9leHRyYWN0X2Vycm9yX21lc3NhZ2UoeGhyKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV0d29ya19lcnJvciA9IG5ldyBFcnJvcihlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgbmV0d29ya19lcnJvci50eXBlID0gJ25ldHdvcmtfZXJyb3InO1xuICAgICAgICAgICAgICAgICAgICBuZXR3b3JrX2Vycm9yLnN0YXR1cyA9IHhoci5zdGF0dXM7XG4gICAgICAgICAgICAgICAgICAgIG5ldHdvcmtfZXJyb3Iuc3RhdHVzVGV4dCA9IHN0YXR1cztcblxuICAgICAgICAgICAgICAgICAgICAvLyBMb2cgc2VydmVyIGVycm9ycyAoNTAwKykgdG8gdGhlIHNlcnZlciBpZiBicm93c2VyIGVycm9yIGxvZ2dpbmcgaXMgZW5hYmxlZFxuICAgICAgICAgICAgICAgICAgICBpZiAoeGhyLnN0YXR1cyA+PSA1MDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIERlYnVnZ2VyLmxvZ19lcnJvcih7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYEFqYXggU2VydmVyIEVycm9yICR7eGhyLnN0YXR1c306ICR7ZXJyb3JfbWVzc2FnZX1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdhamF4X3NlcnZlcl9lcnJvcicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5kcG9pbnQ6IHVybCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0dXM6IHhoci5zdGF0dXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzVGV4dDogc3RhdHVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV0d29ya19lcnJvcik7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGbHVzaCBhbGwgcGVuZGluZyBjYWxscyBieSBzZW5kaW5nIGJhdGNoIHJlcXVlc3RcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBhc3luYyBfZmx1c2hfcGVuZGluZ19jYWxscygpIHtcbiAgICAgICAgLy8gQ29sbGVjdCBhbGwgcGVuZGluZyBjYWxsc1xuICAgICAgICBjb25zdCBjYWxsc190b19zZW5kID0gW107XG4gICAgICAgIGNvbnN0IGNhbGxfbWFwID0ge307IC8vIE1hcCBjYWxsX2lkIHRvIHBlbmRpbmdfY2FsbCBvYmplY3RcblxuICAgICAgICBmb3IgKGNvbnN0IGNhbGxfa2V5IGluIEFqYXguX3BlbmRpbmdfY2FsbHMpIHtcbiAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdfY2FsbCA9IEFqYXguX3BlbmRpbmdfY2FsbHNbY2FsbF9rZXldO1xuXG4gICAgICAgICAgICBpZiAoIXBlbmRpbmdfY2FsbC5pc19jb21wbGV0ZSkge1xuICAgICAgICAgICAgICAgIGNhbGxzX3RvX3NlbmQucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxfaWQ6IHBlbmRpbmdfY2FsbC5jYWxsX2lkLFxuICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVyOiBwZW5kaW5nX2NhbGwuY29udHJvbGxlcixcbiAgICAgICAgICAgICAgICAgICAgYWN0aW9uOiBwZW5kaW5nX2NhbGwuYWN0aW9uLFxuICAgICAgICAgICAgICAgICAgICBwYXJhbXM6IHBlbmRpbmdfY2FsbC5wYXJhbXMsXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBjYWxsX21hcFtwZW5kaW5nX2NhbGwuY2FsbF9pZF0gPSBwZW5kaW5nX2NhbGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBOb3RoaW5nIHRvIHNlbmRcbiAgICAgICAgaWYgKGNhbGxzX3RvX3NlbmQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMb2cgYmF0Y2ggZm9yIGRlYnVnZ2luZ1xuICAgICAgICBpZiAodHlwZW9mIERlYnVnZ2VyICE9PSAndW5kZWZpbmVkJyAmJiBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKSB7XG4gICAgICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKFxuICAgICAgICAgICAgICAgICdBSkFYX0JBVENIJyxcbiAgICAgICAgICAgICAgICBgU2VuZGluZyBiYXRjaCBvZiAke2NhbGxzX3RvX3NlbmQubGVuZ3RofSBjYWxsc2AsXG4gICAgICAgICAgICAgICAgY2FsbHNfdG9fc2VuZC5tYXAoKGMpID0+IGAke2MuY29udHJvbGxlcn0uJHtjLmFjdGlvbn1gKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBTZW5kIGJhdGNoIHJlcXVlc3RcbiAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgJC5hamF4KHtcbiAgICAgICAgICAgICAgICB1cmw6ICcvX2FqYXgvX2JhdGNoJyxcbiAgICAgICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgICAgICBkYXRhOiB7IGJhdGNoX2NhbGxzOiBKU09OLnN0cmluZ2lmeShjYWxsc190b19zZW5kKSB9LFxuICAgICAgICAgICAgICAgIGRhdGFUeXBlOiAnanNvbicsXG4gICAgICAgICAgICAgICAgX19sb2NhbF9pbnRlZ3JhdGlvbjogdHJ1ZSwgLy8gQnlwYXNzICQuYWpheCBvdmVycmlkZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIC8vIFByb2Nlc3MgYmF0Y2ggcmVzcG9uc2VcbiAgICAgICAgICAgIC8vIFJlc3BvbnNlIGZvcm1hdDogeyBDXzA6IHtzdWNjZXNzLCBfYWpheF9yZXR1cm5fdmFsdWV9LCBDXzE6IHsuLi59LCAuLi4gfVxuICAgICAgICAgICAgZm9yIChjb25zdCByZXNwb25zZV9rZXkgaW4gcmVzcG9uc2UpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXJlc3BvbnNlX2tleS5zdGFydHNXaXRoKCdDXycpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IGNhbGxfaWQgPSBwYXJzZUludChyZXNwb25zZV9rZXkuc3Vic3RyaW5nKDIpLCAxMCk7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FsbF9yZXNwb25zZSA9IHJlc3BvbnNlW3Jlc3BvbnNlX2tleV07XG4gICAgICAgICAgICAgICAgY29uc3QgcGVuZGluZ19jYWxsID0gY2FsbF9tYXBbY2FsbF9pZF07XG5cbiAgICAgICAgICAgICAgICBpZiAoIXBlbmRpbmdfY2FsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdSZWNlaXZlZCByZXNwb25zZSBmb3IgdW5rbm93biBjYWxsX2lkOicsIGNhbGxfaWQpO1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBIYW5kbGUgY29uc29sZV9kZWJ1ZyBtZXNzYWdlcyBpZiBwcmVzZW50XG4gICAgICAgICAgICAgICAgaWYgKGNhbGxfcmVzcG9uc2UuY29uc29sZV9kZWJ1ZyAmJiBBcnJheS5pc0FycmF5KGNhbGxfcmVzcG9uc2UuY29uc29sZV9kZWJ1ZykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbF9yZXNwb25zZS5jb25zb2xlX2RlYnVnLmZvckVhY2goKG1zZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1zZykgfHwgbXNnLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb25zb2xlX2RlYnVnIG1lc3NhZ2UgZm9ybWF0IC0gZXhwZWN0ZWQgW2NoYW5uZWwsIFthcmd1bWVudHNdXScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgW2NoYW5uZWwsIGFyZ3NdID0gbXNnO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coY2hhbm5lbCwgLi4uYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE1hcmsgY2FsbCBhcyBjb21wbGV0ZVxuICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5pc19jb21wbGV0ZSA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBzdWNjZXNzZnVsXG4gICAgICAgICAgICAgICAgaWYgKGNhbGxfcmVzcG9uc2UuX3N1Y2Nlc3MgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQEpTLUFKQVgtMDItRVhDRVBUSU9OIC0gQmF0Y2ggc3lzdGVtIHVud3JhcHMgc2VydmVyIHJlc3BvbnNlcyB3aXRoIF9hamF4X3JldHVybl92YWx1ZVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwcm9jZXNzZWRfdmFsdWUgPSBSc3hfSnNfTW9kZWwuX2luc3RhbnRpYXRlX21vZGVsc19yZWN1cnNpdmUoY2FsbF9yZXNwb25zZS5fYWpheF9yZXR1cm5fdmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwucmVzdWx0ID0gcHJvY2Vzc2VkX3ZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJlc29sdmUgYWxsIGNhbGxiYWNrc1xuICAgICAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuY2FsbGJhY2tzLmZvckVhY2goKHsgcmVzb2x2ZSB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEhhbmRsZSBlcnJvclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvcl90eXBlID0gY2FsbF9yZXNwb25zZS5lcnJvcl90eXBlIHx8ICd1bmtub3duX2Vycm9yJztcbiAgICAgICAgICAgICAgICAgICAgbGV0IGVycm9yX21lc3NhZ2U7XG4gICAgICAgICAgICAgICAgICAgIGxldCBlcnJvcl9kZXRhaWxzO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcl90eXBlID09PSAnZmF0YWwnICYmIGNhbGxfcmVzcG9uc2UuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZhdGFsIFBIUCBlcnJvciB3aXRoIGZ1bGwgZXJyb3IgZGV0YWlsc1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmF0YWxfZXJyb3JfZGF0YSA9IGNhbGxfcmVzcG9uc2UuZXJyb3I7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl9tZXNzYWdlID0gZmF0YWxfZXJyb3JfZGF0YS5lcnJvciB8fCAnRmF0YWwgZXJyb3Igb2NjdXJyZWQnO1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfZGV0YWlscyA9IGNhbGxfcmVzcG9uc2UuZXJyb3I7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0FqYXggZXJyb3IgcmVzcG9uc2UgZnJvbSBzZXJ2ZXI6JywgY2FsbF9yZXNwb25zZS5lcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBPdGhlciBlcnJvciB0eXBlc1xuICAgICAgICAgICAgICAgICAgICAgICAgZXJyb3JfbWVzc2FnZSA9IGNhbGxfcmVzcG9uc2UucmVhc29uIHx8ICdVbmtub3duIGVycm9yIG9jY3VycmVkJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yX2RldGFpbHMgPSBjYWxsX3Jlc3BvbnNlLmRldGFpbHMgfHwge307XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IudHlwZSA9IGVycm9yX3R5cGU7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yLmRldGFpbHMgPSBlcnJvcl9kZXRhaWxzO1xuXG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5pc19lcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5lcnJvciA9IGVycm9yO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFJlamVjdCBhbGwgY2FsbGJhY2tzXG4gICAgICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5jYWxsYmFja3MuZm9yRWFjaCgoeyByZWplY3QgfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoICh4aHJfZXJyb3IpIHtcbiAgICAgICAgICAgIC8vIE5ldHdvcmsgb3Igc2VydmVyIGVycm9yIC0gcmVqZWN0IGFsbCBwZW5kaW5nIGNhbGxzXG4gICAgICAgICAgICBjb25zdCBlcnJvcl9tZXNzYWdlID0gQWpheC5fZXh0cmFjdF9lcnJvcl9tZXNzYWdlKHhocl9lcnJvcik7XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihlcnJvcl9tZXNzYWdlKTtcbiAgICAgICAgICAgIGVycm9yLnR5cGUgPSAnbmV0d29ya19lcnJvcic7XG5cbiAgICAgICAgICAgIGZvciAoY29uc3QgY2FsbF9pZCBpbiBjYWxsX21hcCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBlbmRpbmdfY2FsbCA9IGNhbGxfbWFwW2NhbGxfaWRdO1xuICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5pc19jb21wbGV0ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcGVuZGluZ19jYWxsLmlzX2Vycm9yID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBwZW5kaW5nX2NhbGwuZXJyb3IgPSBlcnJvcjtcblxuICAgICAgICAgICAgICAgIHBlbmRpbmdfY2FsbC5jYWxsYmFja3MuZm9yRWFjaCgoeyByZWplY3QgfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdCYXRjaCBBamF4IHJlcXVlc3QgZmFpbGVkOicsIGVycm9yX21lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYSB1bmlxdWUga2V5IGZvciBkZWR1cGxpY2F0aW5nIGNhbGxzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dlbmVyYXRlX2NhbGxfa2V5KGNvbnRyb2xsZXIsIGFjdGlvbiwgcGFyYW1zKSB7XG4gICAgICAgIC8vIENyZWF0ZSBhIHN0YWJsZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGNhbGxcbiAgICAgICAgLy8gU29ydCBwYXJhbXMga2V5cyBmb3IgY29uc2lzdGVudCBoYXNoaW5nXG4gICAgICAgIGNvbnN0IHNvcnRlZF9wYXJhbXMgPSB7fTtcbiAgICAgICAgT2JqZWN0LmtleXMocGFyYW1zKVxuICAgICAgICAgICAgLnNvcnQoKVxuICAgICAgICAgICAgLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgICAgIHNvcnRlZF9wYXJhbXNba2V5XSA9IHBhcmFtc1trZXldO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGAke2NvbnRyb2xsZXJ9Ojoke2FjdGlvbn06OiR7SlNPTi5zdHJpbmdpZnkoc29ydGVkX3BhcmFtcyl9YDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeHRyYWN0IGVycm9yIG1lc3NhZ2UgZnJvbSBqUXVlcnkgWEhSIG9iamVjdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9leHRyYWN0X2Vycm9yX21lc3NhZ2UoeGhyKSB7XG4gICAgICAgIGlmICh4aHIucmVzcG9uc2VKU09OICYmIHhoci5yZXNwb25zZUpTT04ubWVzc2FnZSkge1xuICAgICAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZUpTT04ubWVzc2FnZTtcbiAgICAgICAgfSBlbHNlIGlmICh4aHIucmVzcG9uc2VUZXh0KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3BvbnNlID0gSlNPTi5wYXJzZSh4aHIucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UubWVzc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UubWVzc2FnZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gTm90IEpTT05cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBgJHt4aHIuc3RhdHVzfTogJHt4aHIuc3RhdHVzVGV4dCB8fCAnVW5rbm93biBlcnJvcid9YDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZXMgYW4gQUpBWCBVUkwgaW50byBjb250cm9sbGVyIGFuZCBhY3Rpb25cbiAgICAgKiBTdXBwb3J0cyBib3RoIC9fYWpheC8gYW5kIC9fLyBVUkwgcHJlZml4ZXNcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xvYmplY3R8ZnVuY3Rpb259IHVybCAtIFVSTCBpbiBmb3JtYXQgJy9fYWpheC9Db250cm9sbGVyX05hbWUvYWN0aW9uX25hbWUnIG9yICcvXy9Db250cm9sbGVyX05hbWUvYWN0aW9uX25hbWUnLCBvciBhbiBvYmplY3QvZnVuY3Rpb24gd2l0aCBhIC5wYXRoIHByb3BlcnR5XG4gICAgICogQHJldHVybnMge09iamVjdH0gT2JqZWN0IHdpdGgge2NvbnRyb2xsZXI6IHN0cmluZywgYWN0aW9uOiBzdHJpbmd9XG4gICAgICogQHRocm93cyB7RXJyb3J9IElmIFVSTCBkb2Vzbid0IHN0YXJ0IHdpdGggL19hamF4IG9yIC9fIG9yIGhhcyBpbnZhbGlkIHN0cnVjdHVyZVxuICAgICAqL1xuICAgIHN0YXRpYyBhamF4X3VybF90b19jb250cm9sbGVyX2FjdGlvbih1cmwpIHtcbiAgICAgICAgLy8gSWYgdXJsIGlzIGFuIG9iamVjdCBvciBmdW5jdGlvbiB3aXRoIGEgLnBhdGggcHJvcGVydHksIHVzZSB0aGF0IGFzIHRoZSBVUkxcbiAgICAgICAgaWYgKHVybCAmJiB0eXBlb2YgdXJsID09PSAnb2JqZWN0JyAmJiB1cmwucGF0aCkge1xuICAgICAgICAgICAgdXJsID0gdXJsLnBhdGg7XG4gICAgICAgIH0gZWxzZSBpZiAodXJsICYmIHR5cGVvZiB1cmwgPT09ICdmdW5jdGlvbicgJiYgdXJsLnBhdGgpIHtcbiAgICAgICAgICAgIHVybCA9IHVybC5wYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgdXJsIGlzIGEgc3RyaW5nXG4gICAgICAgIGlmICh0eXBlb2YgdXJsICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVUkwgbXVzdCBiZSBhIHN0cmluZyBvciBoYXZlIGEgLnBhdGggcHJvcGVydHksIGdvdDogJHt0eXBlb2YgdXJsfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF1cmwuc3RhcnRzV2l0aCgnL19hamF4JykgJiYgIXVybC5zdGFydHNXaXRoKCcvXy8nKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVUkwgbXVzdCBzdGFydCB3aXRoIC9fYWpheCBvciAvXywgZ290OiAke3VybH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhcnRzID0gdXJsLnNwbGl0KCcvJykuZmlsdGVyKChwYXJ0KSA9PiBwYXJ0ICE9PSAnJyk7XG5cbiAgICAgICAgaWYgKHBhcnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBBSkFYIFVSTCBzdHJ1Y3R1cmU6ICR7dXJsfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnRzLmxlbmd0aCA+IDMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQUpBWCBVUkwgaGFzIHRvbyBtYW55IHNlZ21lbnRzOiAke3VybH1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBwYXJ0c1sxXTtcbiAgICAgICAgY29uc3QgYWN0aW9uID0gcGFydHNbMl0gfHwgJ2luZGV4JztcblxuICAgICAgICByZXR1cm4geyBjb250cm9sbGVyLCBhY3Rpb24gfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdXRvLWluaXRpYWxpemUgc3RhdGljIHByb3BlcnRpZXMgd2hlbiBjbGFzcyBpcyBmaXJzdCBsb2FkZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgb25fY29yZV9kZWZpbmUoKSB7XG4gICAgICAgIEFqYXguX29uX2ZyYW1ld29ya19jb3JlX2luaXQoKTtcbiAgICB9XG59XG4iLCIvKipcbiAqIEpxaHRtbF9Db21wb25lbnQgLSBCYXNlIGNsYXNzIGZvciBKUUhUTUwgY29tcG9uZW50cyBpbiBSU1ggZnJhbWV3b3JrXG4gKlxuICogVGhpcyBjbGFzcyB3cmFwcyB0aGUganFodG1sLkNvbXBvbmVudCBmcm9tIHRoZSBucG0gcGFja2FnZSBhbmQgcHJvdmlkZXNcbiAqIHRoZSBzdGFuZGFyZCBpbnRlcmZhY2UgZm9yIFJTWCBjb21wb25lbnRzIGZvbGxvd2luZyB0aGUgVXBwZXJfQ2FzZSBuYW1pbmcgY29udmVudGlvbi5cbiAqXG4gKiBfQmFzZV9KcWh0bWxfQ29tcG9uZW50IGlzIGltcG9ydGVkIGZyb20gbnBtIHZpYSBKcWh0bWxfQnVuZGxlLlxuICpcbiAqIEBJbnN0YW50aWF0YWJsZVxuICovXG5jbGFzcyBKcWh0bWxfQ29tcG9uZW50IGV4dGVuZHMgX0Jhc2VfSnFodG1sX0NvbXBvbmVudCB7fVxuXG4vLyBSU1ggbWFuaWZlc3QgYXV0b21hdGljYWxseSBtYWtlcyBjbGFzc2VzIGdsb2JhbCAtIG5vIG1hbnVhbCBhc3NpZ25tZW50IG5lZWRlZFxuIiwiLyoqXG4gKiBKUUhUTUwgSW50ZWdyYXRpb24gLSBBdXRvbWF0aWMgY29tcG9uZW50IHJlZ2lzdHJhdGlvbiBhbmQgYmluZGluZ1xuICpcbiAqIFRoaXMgbW9kdWxlIGF1dG9tYXRpY2FsbHk6XG4gKiAxLiBSZWdpc3RlcnMgY29tcG9uZW50IGNsYXNzZXMgdGhhdCBleHRlbmQgSnFodG1sX0NvbXBvbmVudFxuICogMi4gQmluZHMgdGVtcGxhdGVzIHRvIGNvbXBvbmVudCBjbGFzc2VzIHdoZW4gbmFtZXMgbWF0Y2hcbiAqIDMuIEVuYWJsZXMgJChzZWxlY3RvcikuY29tcG9uZW50KFwiQ29tcG9uZW50X05hbWVcIikgc3ludGF4XG4gKi9cbmNsYXNzIEpxaHRtbF9JbnRlZ3JhdGlvbiB7XG4gICAgLyoqXG4gICAgICogQ29tcGlsZWQgSnFodG1sIHRlbXBsYXRlcyBzZWxmLXJlZ2lzdGVyLiAgVGhlIGRldmVsb3BlciAodGhlIGZyYW1ld29yayBpbiB0aGlzIGNhc2UpIGlzIHN0aWxsXG4gICAgICogcmVzcG9uc2libGUgZm9yIHJlZ2lzdGVyaW5nIGVzNiBjb21wb25lbnQgY2xhc3NlcyB3aXRoIGpxaHRtbC4gIFRoaXMgZG9lcyBzbyBhdCBhbiBlYXJseSBzdGFnZVxuICAgICAqIG9mIGZyYW1ld29yayBpbml0LlxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX21vZHVsZXNfZGVmaW5lKCkge1xuICAgICAgICBsZXQganFodG1sX2NvbXBvbmVudHMgPSBNYW5pZmVzdC5nZXRfZXh0ZW5kaW5nKCdKcWh0bWxfQ29tcG9uZW50Jyk7XG5cbiAgICAgICAgY29uc29sZV9kZWJ1ZygnSlFIVE1MX0lOSVQnLCAnUmVnaXN0ZXJpbmcgJyArIGpxaHRtbF9jb21wb25lbnRzLmxlbmd0aCArICcgSnFodG1sIENvbXBvbmVudHMnKTtcblxuICAgICAgICBmb3IgKGxldCBjb21wb25lbnQgb2YganFodG1sX2NvbXBvbmVudHMpIHtcbiAgICAgICAgICAgIGpxaHRtbC5yZWdpc3Rlcl9jb21wb25lbnQoY29tcG9uZW50LmNsYXNzX25hbWUsIGNvbXBvbmVudC5jbGFzc19vYmplY3QpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnJhbWV3b3JrIG1vZHVsZXMgaW5pdCBwaGFzZSAtIEJpbmQgY29tcG9uZW50cyBhbmQgaW5pdGlhbGl6ZSBET01cbiAgICAgKiBUaGlzIHJ1bnMgYWZ0ZXIgdGVtcGxhdGVzIGFyZSByZWdpc3RlcmVkIHRvIGJpbmQgY29tcG9uZW50IGNsYXNzZXNcbiAgICAgKiBAcGFyYW0ge2pRdWVyeX0gWyRzY29wZV0gT3B0aW9uYWwgc2NvcGUgdG8gc2VhcmNoIHdpdGhpbiAoZGVmYXVsdHMgdG8gYm9keSlcbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8UHJvbWlzZT58dW5kZWZpbmVkfSBBcnJheSBvZiBwcm9taXNlcyBmb3IgcmVjdXJzaXZlIGNhbGxzLCB1bmRlZmluZWQgZm9yIHRvcC1sZXZlbFxuICAgICAqL1xuICAgIHN0YXRpYyBfb25fZnJhbWV3b3JrX21vZHVsZXNfaW5pdCgkc2NvcGUpIHtcbiAgICAgICAgY29uc3QgaXNfdG9wX2xldmVsID0gISRzY29wZTtcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBbXTtcbiAgICAgICAgY29uc3QgY29tcG9uZW50c19uZWVkaW5nX2luaXQgPSAoJHNjb3BlIHx8ICQoJ2JvZHknKSkuZmluZCgnLkpxaHRtbF9Db21wb25lbnRfSW5pdCcpO1xuICAgICAgICBpZiAoY29tcG9uZW50c19uZWVkaW5nX2luaXQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc29sZV9kZWJ1ZygnSlFIVE1MX0lOSVQnLCBgSW5pdGlhbGl6aW5nICR7Y29tcG9uZW50c19uZWVkaW5nX2luaXQubGVuZ3RofSBET00gY29tcG9uZW50c2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29tcG9uZW50c19uZWVkaW5nX2luaXQuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zdCAkZWxlbWVudCA9ICQodGhpcyk7XG5cbiAgICAgICAgICAgIC8vIFNraXAgaWYgZWxlbWVudCBpcyBubyBsb25nZXIgYXR0YWNoZWQgdG8gdGhlIGRvY3VtZW50XG4gICAgICAgICAgICAvLyAobWF5IGhhdmUgYmVlbiByZW1vdmVkIGJ5IGEgcGFyZW50IGNvbXBvbmVudCdzIC5lbXB0eSgpIGNhbGwpXG4gICAgICAgICAgICBpZiAoIWRvY3VtZW50LmNvbnRhaW5zKCRlbGVtZW50WzBdKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgYW55IHBhcmVudCBoYXMgSnFodG1sX0NvbXBvbmVudF9Jbml0IGNsYXNzIC0gc2tpcCBuZXN0ZWQgY29tcG9uZW50c1xuICAgICAgICAgICAgbGV0IHBhcmVudCA9ICRlbGVtZW50WzBdLnBhcmVudEVsZW1lbnQ7XG4gICAgICAgICAgICB3aGlsZSAocGFyZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudC5jbGFzc0xpc3QuY29udGFpbnMoJ0pxaHRtbF9Db21wb25lbnRfSW5pdCcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjsgLy8gU2tpcCB0aGlzIGVsZW1lbnQsIGl0J3MgbmVzdGVkXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnRFbGVtZW50O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBjb21wb25lbnRfbmFtZSA9ICRlbGVtZW50LmF0dHIoJ2RhdGEtY29tcG9uZW50LWluaXQtbmFtZScpO1xuXG4gICAgICAgICAgICAvLyBqUXVlcnkncyAuZGF0YSgpIGRvZXNuJ3QgYXV0by1wYXJzZSBKU09OIC0gd2UgbmVlZCB0byBwYXJzZSBpdCBtYW51YWxseVxuICAgICAgICAgICAgbGV0IGNvbXBvbmVudF9hcmdzID0ge307XG4gICAgICAgICAgICBjb25zdCBhcmdzX3N0cmluZyA9ICRlbGVtZW50LmF0dHIoJ2RhdGEtY29tcG9uZW50LWFyZ3MnKTtcblxuICAgICAgICAgICAgLy8gVW5zZXQgY29tcG9uZW50LSBwaHAgc2lkZSBpbml0aWFsaXphdGlvbiBhcmdzLCBpdCBpcyBubyBsb25nZXIgbmVlZGVkIGFzIGEgY29tcGlvbmVudCBhdHRyaWJ1dGVcbiAgICAgICAgICAgIC8vIFVuc2V0dGluZyBhbHNvIHByZXZlbnRzIHVuZGVzaXJlZCBhY2Nlc3MgdG8gdGhpcyBjb2RlIGluIG90aGVyIHBhcnRzIG9mIHRoZSBwcm9ncmFtLCBwcmV2ZW5pbmcgYW5cbiAgICAgICAgICAgIC8vIHVud2FudGVkIGZ1dHVyZSBkZXBlbmRlbmN5IG9uIHRoaXMgcGFyYWRpZ21cbiAgICAgICAgICAgICRlbGVtZW50LnJlbW92ZUF0dHIoJ2RhdGEtY29tcG9uZW50LWluaXQtbmFtZScpO1xuICAgICAgICAgICAgJGVsZW1lbnQucmVtb3ZlQXR0cignZGF0YS1jb21wb25lbnQtYXJncycpO1xuICAgICAgICAgICAgJGVsZW1lbnQucmVtb3ZlRGF0YSgnY29tcG9uZW50LWluaXQtbmFtZScpO1xuICAgICAgICAgICAgJGVsZW1lbnQucmVtb3ZlRGF0YSgnY29tcG9uZW50LWFyZ3MnKTtcblxuICAgICAgICAgICAgaWYgKGFyZ3Nfc3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50X2FyZ3MgPSBKU09OLnBhcnNlKGFyZ3Nfc3RyaW5nKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFtKUUhUTUwgSW50ZWdyYXRpb25dIEZhaWxlZCB0byBwYXJzZSBjb21wb25lbnQgYXJncyBmb3IgJHtjb21wb25lbnRfbmFtZX06YCwgZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudF9hcmdzID0ge307XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY29tcG9uZW50X25hbWUpIHtcbiAgICAgICAgICAgICAgICAvLyBUcmFuc2Zvcm0gJCBwcmVmaXhlZCBrZXlzIHRvIGRhdGEtIGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBsZXQgY29tcG9uZW50X2FyZ3NfZmlsdGVyZWQgPSB7fTtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhjb21wb25lbnRfYXJncykpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgKGtleS5zdGFydHNXaXRoKCckJykpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gY29tcG9uZW50X2FyZ3NfZmlsdGVyZWRba2V5LnN1YnN0cmluZygxKV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgLy8gfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnZGF0YS0nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50X2FyZ3NfZmlsdGVyZWRba2V5LnN1YnN0cmluZyg1KV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN0b3JlIGlubmVyIEhUTUwgYXMgc3RyaW5nIGZvciBuZXN0ZWQgY29tcG9uZW50IHByb2Nlc3NpbmdcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50X2FyZ3NfZmlsdGVyZWQuX2lubmVyX2h0bWwgPSAkZWxlbWVudC5odG1sKCk7XG4gICAgICAgICAgICAgICAgICAgICRlbGVtZW50LmVtcHR5KCk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSBpbml0IGNsYXNzIGJlZm9yZSBpbnN0YW50aWF0aW9uIHRvIHByZXZlbnQgcmUtaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgICAgICAgICAgJGVsZW1lbnQucmVtb3ZlQ2xhc3MoJ0pxaHRtbF9Db21wb25lbnRfSW5pdCcpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBwcm9taXNlIGZvciB0aGlzIGNvbXBvbmVudCdzIGluaXRpYWxpemF0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbXBvbmVudF9wcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFVzZSBqUXVlcnkgY29tcG9uZW50IHBsdWdpbiB0byBjcmVhdGUgdGhlIGNvbXBvbmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGx1Z2luIGhhbmRsZXMgZWxlbWVudCBpbnRlcm5hbGx5LCBqdXN0IHBhc3MgYXJnc1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSB1cGRhdGVkICRlbGVtZW50IGZyb21cbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBjb21wb25lbnQgPSAkZWxlbWVudC5jb21wb25lbnQoY29tcG9uZW50X25hbWUsIGNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50Lm9uKCdyZW5kZXInLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVjdXJzaXZlbHkgY29sbGVjdCBwcm9taXNlcyBmcm9tIG5lc3RlZCBjb21wb25lbnRzXG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBHZXR0aW5nIHRoZSB1cGRhdGVkIGNvbXBvbmVudCBoZXJlIC0gaWYgdGhlIHRhZyBuYW1lIHdhcyBub3QgZGl2LCB0aGUgZWxlbWVudCB3b3VsZCBoYXZlIGJlZW4gcmVjcmVhdGVkLCBzbyB3ZSBuZWVkIHRvIGdldCB0aGUgZWxlbWVudCBzZXQgb24gdGhlIGNvbXBvbmVudCwgbm90IGZyb20gb3VyIGVhcmxpZXIgc2VsZWN0b3JcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG5lc3RlZF9wcm9taXNlcyA9IEpxaHRtbF9JbnRlZ3JhdGlvbi5fb25fZnJhbWV3b3JrX21vZHVsZXNfaW5pdChjb21wb25lbnQuJCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCguLi5uZXN0ZWRfcHJvbWlzZXMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVzb2x2ZSB0aGlzIGNvbXBvbmVudCdzIHByb21pc2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KS4kO1xuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKGNvbXBvbmVudF9wcm9taXNlKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBbSlFIVE1MIEludGVncmF0aW9uXSBGYWlsZWQgdG8gaW5pdGlhbGl6ZSBjb21wb25lbnQgJHtjb21wb25lbnRfbmFtZX06YCwgZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBkZXRhaWxzOicsIGVycm9yLnN0YWNrIHx8IGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFRvcC1sZXZlbCBjYWxsOiBzcGF3biBhc3luYyBoYW5kbGVyIHRvIHdhaXQgZm9yIGFsbCBwcm9taXNlcywgdGhlbiB0cmlnZ2VyIGV2ZW50XG4gICAgICAgIGlmIChpc190b3BfbGV2ZWwpIHtcbiAgICAgICAgICAgIChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuICAgICAgICAgICAgICAgIGF3YWl0IFJzeC5fcnN4X2NhbGxfYWxsX2NsYXNzZXMoJ29uX2pxaHRtbF9yZWFkeScpO1xuICAgICAgICAgICAgICAgIFJzeC50cmlnZ2VyKCdqcWh0bWxfcmVhZHknKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWN1cnNpdmUgY2FsbDogcmV0dXJuIHByb21pc2VzIGZvciBwYXJlbnQgdG8gY29sbGVjdFxuICAgICAgICByZXR1cm4gcHJvbWlzZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCByZWdpc3RlcmVkIGNvbXBvbmVudCBuYW1lc1xuICAgICAqIEByZXR1cm5zIHtBcnJheTxzdHJpbmc+fSBBcnJheSBvZiBjb21wb25lbnQgbmFtZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2NvbXBvbmVudF9uYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIGpxaHRtbC5nZXRfY29tcG9uZW50X25hbWVzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBjb21wb25lbnQgaXMgcmVnaXN0ZXJlZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIENvbXBvbmVudCBuYW1lXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgY29tcG9uZW50IGlzIHJlZ2lzdGVyZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgaGFzX2NvbXBvbmVudChuYW1lKSB7XG4gICAgICAgIHJldHVybiBqcWh0bWwuaGFzX2NvbXBvbmVudChuYW1lKTtcbiAgICB9XG59XG5cbi8vIFJTWCBtYW5pZmVzdCBhdXRvbWF0aWNhbGx5IG1ha2VzIGNsYXNzZXMgZ2xvYmFsIC0gbm8gbWFudWFsIGFzc2lnbm1lbnQgbmVlZGVkXG4iLCIvLyBKYXZhU2NyaXB0IE1hbmlmZXN0IC0gR2VuZXJhdGVkIGJ5IEJ1bmRsZUNvbXBpbGVyXG4vLyBSZWdpc3RlcnMgYWxsIGNsYXNzZXMgaW4gdGhpcyBidW5kbGUgZm9yIHJ1bnRpbWUgaW50cm9zcGVjdGlvblxuTWFuaWZlc3QuX2RlZmluZShbXG4gICAgW01hbmlmZXN0LCBcIk1hbmlmZXN0XCIsIG51bGxdLFxuICAgIFtSc3hfQmVoYXZpb3JzLCBcIlJzeF9CZWhhdmlvcnNcIiwgbnVsbF0sXG4gICAgW1JzeF9DYWNoZSwgXCJSc3hfQ2FjaGVcIiwgbnVsbF0sXG4gICAgW1JzeF9Jbml0LCBcIlJzeF9Jbml0XCIsIG51bGxdLFxuICAgIFtSc3hfSnNfTW9kZWwsIFwiUnN4X0pzX01vZGVsXCIsIG51bGxdLFxuICAgIFtSc3hfVmlld19UcmFuc2l0aW9ucywgXCJSc3hfVmlld19UcmFuc2l0aW9uc1wiLCBudWxsXSxcbiAgICBbUmVhZFdyaXRlTG9jaywgXCJSZWFkV3JpdGVMb2NrXCIsIG51bGxdLFxuICAgIFtGb3JtX1V0aWxzLCBcIkZvcm1fVXRpbHNcIiwgbnVsbF0sXG4gICAgW0RlYnVnZ2VyLCBcIkRlYnVnZ2VyXCIsIG51bGxdLFxuICAgIFtSc3hfSnFfSGVscGVycywgXCJSc3hfSnFfSGVscGVyc1wiLCBudWxsXSxcbiAgICBbUnN4LCBcIlJzeFwiLCBudWxsXSxcbiAgICBbQWpheCwgXCJBamF4XCIsIG51bGxdLFxuICAgIFtKcWh0bWxfQ29tcG9uZW50LCBcIkpxaHRtbF9Db21wb25lbnRcIiwgX0Jhc2VfSnFodG1sX0NvbXBvbmVudF0sXG4gICAgW0pxaHRtbF9JbnRlZ3JhdGlvbiwgXCJKcWh0bWxfSW50ZWdyYXRpb25cIiwgbnVsbF1cbl0pO1xuXG4iLCIkKGRvY3VtZW50KS5yZWFkeShhc3luYyBmdW5jdGlvbigpIHtcbnRyeSB7XG5jb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdEb2N1bWVudCByZWFkeSwgc3RhcnRpbmcgUnN4Ll9yc3hfY29yZV9ib290Jyk7XG5hd2FpdCBSc3guX3JzeF9jb3JlX2Jvb3QoKTtcbmNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgJ0luaXRpYWxpemF0aW9uIGNvbXBsZXRlJyk7XG59IGNhdGNoIChlcnJvcikge1xuY29uc29sZS5lcnJvcignW1JTWF9JTklUXSBJbml0aWFsaXphdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuY29uc29sZS5lcnJvcignW1JTWF9JTklUXSBTdGFjazonLCBlcnJvci5zdGFjayk7XG50aHJvdyBlcnJvcjtcbn1cbn0pOyJdLCJzb3VyY2VSb290IjoiIn0=