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

').text(summary_msg).appendTo($alert); } // Add unmatched errors as bulleted list if (Object.keys(unmatched_errors).length > 0) { const $list = $('
    '); for (const field_name in unmatched_errors) { const error_msg = unmatched_errors[field_name]; $('
  • ').html(error_msg).appendTo($list); } $list.appendTo($alert); } if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } return animations; } /** * Applies general error messages as alert box * @param {jQuery} $parent - Parent element to prepend alert to * @param {string|Array} messages - Error message(s) to display * @returns {Array} Array of animation promises * @private */ static _apply_general_errors($parent, messages) { const animations = []; // Look for a specific error container div (e.g., in Rsx_Form component) const $error_container = $parent.find('[data-id="error_container"]').first(); const $target = $error_container.length > 0 ? $error_container : $parent; if (typeof messages === 'string') { // Single error - simple alert without list const $alert = $('').text(messages); if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } } else if (Array.isArray(messages) && messages.length > 0) { // Multiple errors - bulleted list const $alert = $(''); const $list = $alert.find('ul'); messages.forEach(msg => { const text = (msg + '').trim() || 'An error has occurred'; $('
  • ').html(text).appendTo($list); }); if ($error_container.length > 0) { animations.push($alert.hide().appendTo($target).fadeIn(300).promise()); } else { animations.push($alert.hide().prependTo($target).fadeIn(300).promise()); } } else if (typeof messages === 'object' && !Array.isArray(messages)) { // Object of unmatched field errors - convert to array const error_list = Object.values(messages).map(v => String(v).trim()).filter(v => v); if (error_list.length > 0) { return Form_Utils._apply_general_errors($parent, error_list); } } return animations; } /** * Calculates the total height of fixed/sticky headers at the top of the page * @returns {number} Total height in pixels of fixed top elements * @private */ static _get_fixed_header_height() { let total_height = 0; // Find all fixed or sticky positioned elements $('*').each(function () { const $el = $(this); const position = $el.css('position'); // Only check fixed or sticky elements if (position !== 'fixed' && position !== 'sticky') { return; } // Check if element is positioned at or near the top const top = parseInt($el.css('top')) || 0; if (top > 50) { return; // Not a top header } // Check if element is visible if (!$el.is(':visible')) { return; } // Check if element spans significant width (likely a header/navbar) const width = $el.outerWidth(); const viewport_width = $(window).width(); if (width < viewport_width * 0.5) { return; // Too narrow to be a header } // Add this element's height total_height += $el.outerHeight(); }); return total_height; } } /* === app/RSpade/Core/Js/Debugger.js (babel) === */ "use strict"; function _27e0e986_defineProperty(e, r, t) { return (r = _27e0e986_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _27e0e986_toPropertyKey(t) { var i = _27e0e986_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _27e0e986_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /** * Debugger class for console_debug and browser error logging * Handles batched submission to server when configured */ class Debugger { /** * Initialize framework error handling * Called during framework initialization */ static _on_framework_core_init() { // Check if browser error logging is enabled if (window.rsxapp && window.rsxapp.log_browser_errors) { // Register global error handler window.addEventListener('error', function (event) { Debugger._handle_browser_error({ message: event.message, filename: event.filename, lineno: event.lineno, colno: event.colno, stack: event.error ? event.error.stack : null, type: 'error' }); }); // Register unhandled promise rejection handler window.addEventListener('unhandledrejection', function (event) { Debugger._handle_browser_error({ message: event.reason ? event.reason.message || String(event.reason) : 'Unhandled promise rejection', stack: event.reason && event.reason.stack ? event.reason.stack : null, type: 'unhandledrejection' }); }); } // Register ui refresh handler Rsx.on('refresh', Debugger.on_refresh); } // In dev mode, some ui elements can be automatically applied to assist with development static on_refresh() { if (!Rsx.is_prod()) { // Add an underline 2 px blue to all a tags with href === "#" using jquery // Todo: maybe this should be a configurable debug option? // $('a[href="#"]').css({ // 'border-bottom': '2px solid blue', // 'text-decoration': 'none' // }); } } /** * JavaScript implementation of console_debug * Mirrors PHP functionality with batching for Laravel log */ static console_debug(channel) { // Check if console_debug is enabled if (!window.rsxapp || !window.rsxapp.console_debug || !window.rsxapp.console_debug.enabled) { return; } const config = window.rsxapp.console_debug; // Normalize channel name channel = String(channel).toUpperCase().replace(/[\[\]]/g, ''); // Apply filtering if (config.filter_mode === 'specific') { const specific = config.specific_channel; if (specific) { // Split comma-separated values and normalize const channels = specific.split(',').map(c => c.trim().toUpperCase()); if (!channels.includes(channel)) { return; } } } else if (config.filter_mode === 'whitelist') { const whitelist = (config.filter_channels || []).map(c => c.toUpperCase()); if (!whitelist.includes(channel)) { return; } } else if (config.filter_mode === 'blacklist') { const blacklist = (config.filter_channels || []).map(c => c.toUpperCase()); if (blacklist.includes(channel)) { return; } } // Prepare the message for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { values[_key - 1] = arguments[_key]; } let message = { channel: channel, values: values, timestamp: new Date().toISOString() }; // Add location if configured if (config.include_location || config.include_backtrace) { const error = new Error(); const stack = error.stack || ''; const stackLines = stack.split('\n'); if (config.include_location && stackLines.length > 2) { // Skip Error line and this function const callerLine = stackLines[2] || ''; const match = callerLine.match(/at\s+.*?\s+\((.*?):(\d+):(\d+)\)/) || callerLine.match(/at\s+(.*?):(\d+):(\d+)/); if (match) { message.location = `${match[1]}:${match[2]}`; } } if (config.include_backtrace) { // Include first 5 stack frames, skipping this function message.backtrace = stackLines.slice(2, 7).map(line => line.trim()).filter(line => line); } } // Output to browser console if enabled if (config.outputs && config.outputs.browser) { const prefix = config.include_benchmark ? `[${Debugger._get_time_prefix()}] ` : ''; const channelPrefix = `[${channel}]`; // Use appropriate console method based on channel let consoleMethod = 'log'; if (channel.includes('ERROR')) consoleMethod = 'error';else if (channel.includes('WARN')) consoleMethod = 'warn';else if (channel.includes('INFO')) consoleMethod = 'info'; console[consoleMethod](prefix + channelPrefix, ...values); } // Batch for Laravel log if enabled if (config.outputs && config.outputs.laravel_log) { Debugger._batch_console_message(message); } } /** * Log an error to the server * Used manually or by Ajax error handling */ static log_error(error) { // Check if browser error logging is enabled if (!window.rsxapp || !window.rsxapp.log_browser_errors) { return; } // Normalize error format let errorData = {}; if (typeof error === 'string') { errorData.message = error; errorData.type = 'manual'; } else if (error instanceof Error) { errorData.message = error.message; errorData.stack = error.stack; errorData.type = 'exception'; } else if (error && typeof error === 'object') { errorData = error; if (!errorData.type) { errorData.type = 'manual'; } } Debugger._handle_browser_error(errorData); } /** * Internal: Handle browser errors with batching */ static _handle_browser_error(errorData) { // Check limits if (Debugger._error_count >= Debugger.MAX_ERRORS_PER_PAGE) { return; } if (Debugger._error_batch_count >= Debugger.MAX_ERROR_BATCHES) { return; } Debugger._error_count++; // Add metadata errorData.url = window.location.href; errorData.userAgent = navigator.userAgent; errorData.timestamp = new Date().toISOString(); // Add to batch Debugger._error_batch.push(errorData); // Clear existing timer if (Debugger._error_timer) { clearTimeout(Debugger._error_timer); } // Set debounce timer Debugger._error_timer = setTimeout(() => { Debugger._flush_error_batch(); }, Debugger.DEBOUNCE_MS); } /** * Internal: Batch console_debug messages for Laravel log */ static _batch_console_message(message) { Debugger._console_batch.push(message); // Clear existing timer if (Debugger._console_timer) { clearTimeout(Debugger._console_timer); } // Set debounce timer Debugger._console_timer = setTimeout(() => { Debugger._flush_console_batch(); }, Debugger.DEBOUNCE_MS); } /** * Internal: Flush console_debug batch to server */ static async _flush_console_batch() { if (Debugger._console_batch.length === 0) { return; } const messages = Debugger._console_batch; Debugger._console_batch = []; Debugger._console_timer = null; try { return Ajax.call(Rsx.Route('Debugger_Controller', 'log_console_messages'), { messages: messages }); } catch (error) { // Silently fail - don't create error loop console.error('Failed to send console_debug messages to server:', error); } } /** * Internal: Flush error batch to server */ static async _flush_error_batch() { if (Debugger._error_batch.length === 0) { return; } const errors = Debugger._error_batch; Debugger._error_batch = []; Debugger._error_timer = null; Debugger._error_batch_count++; try { return Ajax.call(Rsx.Route('Debugger_Controller', 'log_browser_errors'), { errors: errors }); } catch (error) { // Silently fail - don't create error loop console.error('Failed to send browser errors to server:', error); } } /** * Internal: Get time prefix for benchmarking */ static _get_time_prefix() { const now = Date.now(); if (!Debugger._start_time) { Debugger._start_time = now; } const elapsed = now - Debugger._start_time; return (elapsed / 1000).toFixed(3) + 's'; } } // Batching state for console_debug messages _27e0e986_defineProperty(Debugger, "_console_batch", []); _27e0e986_defineProperty(Debugger, "_console_timer", null); _27e0e986_defineProperty(Debugger, "_console_batch_count", 0); // Batching state for error messages _27e0e986_defineProperty(Debugger, "_error_batch", []); _27e0e986_defineProperty(Debugger, "_error_timer", null); _27e0e986_defineProperty(Debugger, "_error_count", 0); _27e0e986_defineProperty(Debugger, "_error_batch_count", 0); // Constants _27e0e986_defineProperty(Debugger, "DEBOUNCE_MS", 2000); _27e0e986_defineProperty(Debugger, "MAX_ERRORS_PER_PAGE", 20); _27e0e986_defineProperty(Debugger, "MAX_ERROR_BATCHES", 5); // Store start time for benchmarking _27e0e986_defineProperty(Debugger, "_start_time", null); /* === app/RSpade/Core/Js/Rsx_Jq_Helpers.js (babel) === */ "use strict"; // @JS-THIS-01-EXCEPTION /** * jQuery helper extensions for the RSX framework * These extensions add utility methods to jQuery's prototype * Note: 'this' references in jQuery extensions refer to jQuery objects by design */ class Rsx_Jq_Helpers { /** * Initialize jQuery extensions when the framework core is defined * This method is called during framework initialization */ static _on_framework_core_define() { // Returns true if jquery selector matched an element $.fn.exists = function () { return this.length > 0; }; // Returns true if jquery element is visible $.fn.is_visible = function () { return this.is(':visible'); }; // Scrolls to the target element, only scrolls up. Todo: Create a version // of this that also scrolls only down, or both $.fn.scroll_up_to = function () { let speed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; if (!this.exists()) { // console.warn("Could not find target element to scroll to"); return; } if (!this.is_in_dom()) { // console.warn("Target element for scroll is not on dom"); return; } let e_top = Math.round(this.offset().top); let s_top = $('body').scrollTop(); if (e_top < 0) { let target = s_top + e_top; $('html, body').animate({ scrollTop: target }, speed); } }; // $().is(":focus") - check if element has focus $.expr[':'].focus = function (elem) { return elem === document.activeElement && (elem.type || elem.href); }; // Save native click behavior before override $.fn._click_native = $.fn.click; // Override .click() to call preventDefault by default // This prevents accidental page navigation/form submission - the correct behavior 95% of the time $.fn.click = function (handler) { // If no handler provided, trigger click event (jQuery .click() with no args) if (typeof handler === 'undefined') { return this._click_native(); } // Attach click handler with automatic preventDefault return this.on('click', function (e) { // Save original preventDefault const original_preventDefault = e.preventDefault.bind(e); // Override preventDefault to show warning when called explicitly e.preventDefault = function () { console.warn('event.preventDefault() is called automatically by RSpade .click() handlers and can be removed.'); return original_preventDefault(); }; // Call preventDefault before handler original_preventDefault(); return handler.call(this, e); }); }; // Escape hatch: click handler without preventDefault for the 5% case $.fn.click_allow_default = function (handler) { if (typeof handler === 'undefined') { return this._click_native(); } return this._click_native(handler); }; // Returns true if the jquery element exists in and is attached to the DOM $.fn.is_in_dom = function () { let $element = this; let _ancestor = function (HTMLobj) { while (HTMLobj.parentElement) { HTMLobj = HTMLobj.parentElement; } return HTMLobj; }; return _ancestor($element[0]) === document.documentElement; }; // Returns true if the element is visible in the viewport $.fn.is_in_viewport = function () { let scrolltop = $(window).scrollTop() > 0 ? $(window).scrollTop() : $('body').scrollTop(); let $element = this; const top_of_element = $element.offset().top; const bottom_of_element = $element.offset().top + $element.outerHeight(); const bottom_of_screen = scrolltop + $(window).innerHeight(); const top_of_screen = scrolltop; if (bottom_of_screen > top_of_element && top_of_screen < bottom_of_element) { return true; } else { return false; } }; // Gets the tagname of a jquery element $.fn.tagname = function () { return this.prop('tagName').toLowerCase(); }; // Returns true if a href is not same domain $.fn.is_external = function () { const host = window.location.host; const link = $('', { href: this.attr('href') })[0].hostname; return link !== host; }; // HTML5 form validation wrappers $.fn.checkValidity = function () { if (this.length === 0) return false; return this[0].checkValidity(); }; $.fn.reportValidity = function () { if (this.length === 0) return false; return this[0].reportValidity(); }; $.fn.requestSubmit = function () { if (this.length === 0) return this; this[0].requestSubmit(); return this; }; // Find related components by searching up the ancestor tree // Like .closest() but searches within ancestors instead of matching them $.fn.closest_sibling = function (selector) { let $current = this; let $parent = $current.parent(); // Keep going up the tree until we hit body while ($parent.length > 0 && !$parent.is('body')) { // Search within this parent for the selector let $found = $parent.find(selector); if ($found.length > 0) { return $found; } // Move up one level $parent = $parent.parent(); } // If we reached body, search within body as well if ($parent.is('body')) { let $found = $parent.find(selector); if ($found.length > 0) { return $found; } } // Return empty jQuery object if nothing found return $(); }; // Override $.ajax to prevent direct AJAX calls to local server // Developers must use the Ajax endpoint pattern: await Controller.method(params) const native_ajax = $.ajax; $.ajax = function (url, options) { // Handle both $.ajax(url, options) and $.ajax(options) signatures let settings; if (typeof url === 'string') { settings = options || {}; settings.url = url; } else { settings = url || {}; } // Check if this is a local request (relative URL or same domain) const request_url = settings.url || ''; const is_relative = !request_url.match(/^https?:\/\//); const is_same_domain = request_url.startsWith(window.location.origin); const is_local_request = is_relative || is_same_domain; // Allow framework Ajax.call() to function if (settings.__local_integration === true) { return native_ajax.call(this, settings); } // Allow file upload endpoint - requires native $.ajax for FormData support const is_file_upload = request_url === '/_upload' || request_url.endsWith('/_upload'); if (is_file_upload) { return native_ajax.call(this, settings); } // Block local AJAX requests that don't use the Ajax endpoint pattern if (is_local_request) { // Try to parse controller and action from URL let controller_name = null; let action_name = null; const url_match = request_url.match(/\/_rsx_api\/([^\/]+)\/([^\/\?]+)/); if (url_match) { controller_name = url_match[1]; action_name = url_match[2]; } let error_message = 'AJAX requests to localhost via $.ajax() are prohibited.\n\n'; if (controller_name && action_name) { error_message += `Instead of:\n`; error_message += ` $.ajax({url: '${request_url}', ...})\n\n`; error_message += `Use:\n`; error_message += ` await ${controller_name}.${action_name}(parameters)\n\n`; } else { error_message += `Use the Ajax endpoint pattern:\n`; error_message += ` await Controller_Name.action_name(parameters)\n\n`; } error_message += `The controller method must have the #[Ajax_Endpoint] attribute.`; shouldnt_happen(error_message); } // Allow external requests (different domain) return native_ajax.call(this, settings); }; } } /* === app/RSpade/Core/Js/Rsx.js (babel) === */ "use strict"; function _e8211f5b_defineProperty(e, r, t) { return (r = _e8211f5b_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _e8211f5b_toPropertyKey(t) { var i = _e8211f5b_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _e8211f5b_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } // @ROUTE-EXISTS-01-EXCEPTION - This file contains documentation examples with fictional route names /** * Rsx - Core JavaScript Runtime System * * The Rsx class is the central hub for the RSX JavaScript runtime, providing essential * system-level utilities that all other framework components depend on. It serves as the * foundation for the client-side framework, handling core operations that must be globally * accessible and consistently available. * * Core Responsibilities: * - Event System: Application-wide event bus for framework lifecycle and custom events * - Environment Detection: Runtime environment identification (dev/production) * - Route Management: Type-safe route generation and URL building * - Unique ID Generation: Client-side unique identifier generation * - Framework Bootstrap: Multi-phase initialization orchestration * - Logging: Centralized logging interface (delegates to console_debug) * * The Rsx class deliberately keeps its scope limited to core utilities. Advanced features * are delegated to specialized classes: * - Manifest operations → Manifest class * - Caching → Rsx_Cache class * - AJAX/API calls → Ajax_* classes * - Route proxies → Rsx_Route_Proxy class * - Behaviors → Rsx_Behaviors class * * All methods are static - Rsx is never instantiated. It's available globally from the * moment bundles load and remains constant throughout the application lifecycle. * * Usage Examples: * ```javascript * // Event system * Rsx.on('app_ready', () => console.log('App initialized')); * Rsx.trigger('custom_event', {data: 'value'}); * * // Environment detection * if (Rsx.is_dev()) { console.log('Development mode'); } * * // Route generation * const url = Rsx.Route('Controller', 'action').url(); * * // Unique IDs * const uniqueId = Rsx.uid(); // e.g., "rsx_1234567890_1" * ``` * * @static * @global */ class Rsx { // Initialize event handlers storage static _init_events() { if (typeof Rsx._event_handlers === 'undefined') { Rsx._event_handlers = {}; } if (typeof Rsx._triggered_events === 'undefined') { Rsx._triggered_events = {}; } } // Register an event handler static on(event, callback) { Rsx._init_events(); if (typeof callback !== 'function') { throw new Error('Callback must be a function'); } if (!Rsx._event_handlers[event]) { Rsx._event_handlers[event] = []; } Rsx._event_handlers[event].push(callback); // If this event was already triggered, call the callback immediately if (Rsx._triggered_events[event]) { console_debug('RSX_INIT', 'Triggering ' + event + ' for late registered callback'); callback(Rsx._triggered_events[event]); } } // Trigger an event with optional data static trigger(event) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; Rsx._init_events(); // Record that this event was triggered Rsx._triggered_events[event] = data; if (!Rsx._event_handlers[event]) { return; } console_debug('RSX_INIT', 'Triggering ' + event + ' for ' + Rsx._event_handlers[event].length + ' callbacks'); // Call all registered handlers for this event in order for (const callback of Rsx._event_handlers[event]) { callback(data); } } // Alias for trigger.refresh(''), should be called after major UI updates to apply such effects as // underlining links to unimplemented # routes static trigger_refresh() { // Use Rsx.on('refresh', callback); to register a callback for refresh this.trigger('refresh'); } // Log to server that an event happened static log(type) { let message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'notice'; Core_Log.log(type, message); } // Returns true if the app is being run in dev mode // This should affect caching and some debug checks static is_dev() { return window.rsxapp.debug; } static is_prod() { return !window.rsxapp.debug; } // Generates a unique number for the application instance static uid() { if (typeof Rsx._uid == undef) { Rsx._uid = 0; } return Rsx._uid++; } // Storage for route definitions loaded from bundles /** * Define routes from bundled data * Called by generated JavaScript in bundles */ static _define_routes(routes) { // Merge routes into the global route storage for (const class_name in routes) { if (!Rsx._routes[class_name]) { Rsx._routes[class_name] = {}; } for (const method_name in routes[class_name]) { Rsx._routes[class_name][method_name] = routes[class_name][method_name]; } } } /** * Generate URL for a controller route * * This method generates URLs for controller actions by looking up route patterns * and replacing parameters. It handles both regular routes and Ajax endpoints. * * If the route is not found in the route definitions, a default pattern is used: * `/_/{controller}/{action}` with all parameters appended as query strings. * * Usage examples: * ```javascript * // Simple route without parameters (defaults to 'index' action) * const url = Rsx.Route('Frontend_Index_Controller'); * // Returns: /dashboard * * // Route with explicit action * const url = Rsx.Route('Frontend_Index_Controller', 'index'); * // Returns: /dashboard * * // Route with integer parameter (sets 'id') * const url = Rsx.Route('Frontend_Client_View_Controller', 'view', 123); * // Returns: /clients/view/123 * * // Route with named parameters (object) * const url = Rsx.Route('Frontend_Client_View_Controller', 'view', {id: 'C001'}); * // Returns: /clients/view/C001 * * // Route with required and query parameters * const url = Rsx.Route('Frontend_Client_View_Controller', 'view', { * id: 'C001', * tab: 'history' * }); * // Returns: /clients/view/C001?tab=history * * // Route not found - uses default pattern * const url = Rsx.Route('Unimplemented_Controller', 'some_action', {foo: 'bar'}); * // Returns: /_/Unimplemented_Controller/some_action?foo=bar * * // Placeholder route * const url = Rsx.Route('Future_Controller', '#index'); * // Returns: # * ``` * * @param {string} class_name The controller class name (e.g., 'User_Controller') * @param {string} [action_name='index'] The action/method name (defaults to 'index'). Use '#action' for placeholders. * @param {number|Object} [params=null] Route parameters. Integer sets 'id', object provides named params. * @returns {string} The generated URL */ static Route(class_name) { let action_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'index'; let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; // Normalize params to object let params_obj = {}; if (typeof params === 'number') { params_obj = { id: params }; } else if (params && typeof params === 'object') { params_obj = params; } else if (params !== null && params !== undefined) { throw new Error('Params must be number, object, or null'); } // Placeholder route: action starts with # means unimplemented/scaffolding if (action_name.startsWith('#')) { return '#'; } // Check if route exists in definitions let pattern; if (Rsx._routes[class_name] && Rsx._routes[class_name][action_name]) { pattern = Rsx._routes[class_name][action_name]; } else { // Route not found - use default pattern /_/{controller}/{action} pattern = `/_/${class_name}/${action_name}`; } // Generate URL from pattern return Rsx._generate_url_from_pattern(pattern, params_obj); } /** * Generate URL from route pattern by replacing parameters * * @param {string} pattern The route pattern (e.g., '/users/:id/view') * @param {Object} params Parameters to fill into the route * @returns {string} The generated URL */ static _generate_url_from_pattern(pattern, params) { // Extract required parameters from the pattern const required_params = []; const matches = pattern.match(/:([a-zA-Z_][a-zA-Z0-9_]*)/g); if (matches) { // Remove the : prefix from each match for (const match of matches) { required_params.push(match.substring(1)); } } // Check for required parameters const missing = []; for (const required of required_params) { if (!(required in params)) { missing.push(required); } } if (missing.length > 0) { throw new Error(`Required parameters [${missing.join(', ')}] are missing for route ${pattern}`); } // Build the URL by replacing parameters let url = pattern; const used_params = {}; for (const param_name of required_params) { const value = params[param_name]; // URL encode the value const encoded_value = encodeURIComponent(value); url = url.replace(':' + param_name, encoded_value); used_params[param_name] = true; } // Collect any extra parameters for query string const query_params = {}; for (const key in params) { if (!used_params[key]) { query_params[key] = params[key]; } } // Append query string if there are extra parameters if (Object.keys(query_params).length > 0) { const query_string = Object.entries(query_params).map(_ref => { let [key, value] = _ref; return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; }).join('&'); url += '?' + query_string; } return url; } /** * Internal: Call a specific method on all classes that have it * Collects promises from return values and waits for all to resolve * @param {string} method_name The method name to call on all classes * @returns {Promise} Promise that resolves when all method calls complete */ static async _rsx_call_all_classes(method_name) { const all_classes = Manifest.get_all_classes(); const classes_with_method = []; const promise_pile = []; for (const class_info of all_classes) { const class_object = class_info.class_object; const class_name = class_info.class_name; // Check if this class has the method (static methods are on the class itself) if (typeof class_object[method_name] === 'function') { classes_with_method.push(class_name); const return_value = await class_object[method_name](); // Collect promises from return value if (return_value instanceof Promise) { promise_pile.push(return_value); } else if (Array.isArray(return_value)) { for (const item of return_value) { if (item instanceof Promise) { promise_pile.push(item); } } } if (Rsx.__stopped) { return; } } } if (classes_with_method.length > 0) { console_debug('RSX_INIT', `${method_name}: ${classes_with_method.length} classes`); } // Await all promises before returning if (promise_pile.length > 0) { console_debug('RSX_INIT', `${method_name}: Awaiting ${promise_pile.length} promises`); await Promise.all(promise_pile); } } /** * Internal: Execute multi-phase initialization for all registered classes * This runs various initialization phases in order to properly set up the application * @returns {Promise} Promise that resolves when all initialization phases complete */ static async _rsx_core_boot() { if (Rsx.__booted) { console.error('Rsx._rsx_core_boot called more than once'); return; } Rsx.__booted = true; // Get all registered classes from the manifest const all_classes = Manifest.get_all_classes(); console_debug('RSX_INIT', `Starting _rsx_core_boot with ${all_classes.length} classes`); if (!all_classes || all_classes.length === 0) { // No classes to initialize shouldnt_happen('No classes registered in js - there should be at least the core framework classes'); return; } // Define initialization phases in order const phases = [{ event: 'framework_core_define', method: '_on_framework_core_define' }, { event: 'framework_modules_define', method: '_on_framework_modules_define' }, { event: 'framework_core_init', method: '_on_framework_core_init' }, { event: 'app_modules_define', method: 'on_app_modules_define' }, { event: 'app_define', method: 'on_app_define' }, { event: 'framework_modules_init', method: '_on_framework_modules_init' }, { event: 'app_modules_init', method: 'on_app_modules_init' }, { event: 'app_init', method: 'on_app_init' }, { event: 'app_ready', method: 'on_app_ready' }]; // Execute each phase in order for (const phase of phases) { await Rsx._rsx_call_all_classes(phase.method); if (Rsx.__stopped) { return; } Rsx.trigger(phase.event); } // Ui refresh callbacks Rsx.trigger_refresh(); // All phases complete console_debug('RSX_INIT', 'Initialization complete'); // TODO: Find a good wait to wait for all jqhtml components to load, then trigger on_ready and on('ready') emulating the top level last syntax that jqhtml components operateas, but as a standard js class (such as a page class). The biggest question is, how do we efficiently choose only the top level jqhtml components. do we only consider components cretaed directly on blade templates? that seams reasonable... // Trigger _debug_ready event - this is ONLY for tooling like rsx:debug // DO NOT use this in application code - use on_app_ready() phase instead // This event exists solely for debugging tools that need to run after full initialization Rsx.trigger('_debug_ready'); } /* Calling this stops the boot process. */ static async _rsx_core_boot_stop(reason) { console.error(reason); Rsx.__stopped = true; } /** * Parse URL hash into key-value object * Handles format: #key=value&key2=value2 * * @returns {Object} Parsed hash parameters */ static _parse_hash() { const hash = window.location.hash; if (!hash || hash === '#') { return {}; } // Remove leading # and parse as query string const hash_string = hash.substring(1); const params = {}; const pairs = hash_string.split('&'); for (const pair of pairs) { const [key, value] = pair.split('='); if (key) { params[decodeURIComponent(key)] = value ? decodeURIComponent(value) : ''; } } return params; } /** * Serialize object into URL hash format * Produces format: #key=value&key2=value2 * * @param {Object} params Key-value pairs to encode * @returns {string} Encoded hash string (with leading #, or empty string) */ static _serialize_hash(params) { const pairs = []; for (const key in params) { const value = params[key]; if (value !== null && value !== undefined && value !== '') { pairs.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`); } } return pairs.length > 0 ? '#' + pairs.join('&') : ''; } /** * Get all page state from URL hash * * Usage: * ```javascript * const state = Rsx.get_all_page_state(); * // Returns: {dg_page: '2', dg_sort: 'name'} * ``` * * @returns {Object} All hash parameters as key-value pairs */ static get_all_page_state() { return Rsx._parse_hash(); } /** * Get single value from URL hash state * * Usage: * ```javascript * const page = Rsx.get_page_state('dg_page'); * // Returns: '2' or null if not set * ``` * * @param {string} key The key to retrieve * @returns {string|null} The value or null if not found */ static get_page_state(key) { var _state$key; const state = Rsx._parse_hash(); return (_state$key = state[key]) !== null && _state$key !== void 0 ? _state$key : null; } /** * Set single value in URL hash state (replaces history, doesn't add) * * Usage: * ```javascript * Rsx.set_page_state('dg_page', 2); * // URL becomes: http://example.com/page#dg_page=2 * * Rsx.set_page_state('dg_page', null); // Remove key * ``` * * @param {string} key The key to set * @param {string|number|null} value The value (null/empty removes the key) */ static set_page_state(key, value) { const state = Rsx._parse_hash(); // Update or remove the key if (value === null || value === undefined || value === '') { delete state[key]; } else { state[key] = String(value); } // Update URL without adding history const new_hash = Rsx._serialize_hash(state); const url = window.location.pathname + window.location.search + new_hash; history.replaceState(null, '', url); } /** * Set multiple values in URL hash state at once * * Usage: * ```javascript * Rsx.set_all_page_state({dg_page: 2, dg_sort: 'name'}); * // URL becomes: http://example.com/page#dg_page=2&dg_sort=name * ``` * * @param {Object} new_state Object with key-value pairs to set */ static set_all_page_state(new_state) { const state = Rsx._parse_hash(); // Merge new state for (const key in new_state) { const value = new_state[key]; if (value === null || value === undefined || value === '') { delete state[key]; } else { state[key] = String(value); } } // Update URL without adding history const new_hash = Rsx._serialize_hash(state); const url = window.location.pathname + window.location.search + new_hash; history.replaceState(null, '', url); } /** * Render an error in a DOM element * * Displays errors from Ajax calls in a standardized format. Handles different * error types (fatal, validation, auth, generic) with appropriate formatting. * * Usage: * ```javascript * try { * const result = await Controller.method(); * } catch (error) { * Rsx.render_error(error, '#error_container'); * } * ``` * * @param {Error|Object} error - Error object from Ajax call * @param {jQuery|string} container - jQuery element or selector for error display */ static render_error(error, container) { const $container = $(container); if (!$container.exists()) { console.error('Rsx.render_error: Container not found', container); return; } // Clear existing content $container.empty(); let html = ''; // Handle different error types if (error.type === 'fatal' && error.details) { // Fatal PHP error with file/line/error const details = error.details; const file = details.file || 'Unknown file'; const line = details.line || '?'; const message = details.error || error.message || 'Fatal error occurred'; html = ` `; } else if (error.type === 'form_error' && error.details) { // Validation errors - show unmatched errors only // (matched errors should be handled by Form_Utils.apply_form_errors) const errors = error.details; const error_list = []; for (const field in errors) { error_list.push(errors[field]); } if (error_list.length > 0) { html = ` `; } } else if (error.type === 'auth_required' || error.type === 'unauthorized') { // Authentication/authorization errors const message = error.message || 'Authentication required'; html = ` `; } else if (error.type === 'network') { // Network errors const message = error.message || 'Unable to reach server. Please check your connection.'; html = ` `; } else { // Generic/unknown error const message = error.message || error.toString() || 'An unknown error occurred'; html = ` `; } $container.html(html); } /** * Escape HTML to prevent XSS in error messages * @private */ static _escape_html(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } } // Gets set to true to interupt startup sequence _e8211f5b_defineProperty(Rsx, "__stopped", false); _e8211f5b_defineProperty(Rsx, "_routes", {}); /* === app/RSpade/Core/Js/Ajax.js (babel) === */ "use strict"; // @FILE-SUBCLASS-01-EXCEPTION /** * Client-side Ajax class for making API calls to RSX controllers * * Automatically batches multiple calls into single HTTP requests to reduce network overhead. * Batches up to 20 calls or flushes after setTimeout(0) debounce. */ class Ajax { /** * Initialize Ajax system * Called automatically when class is loaded */ static _on_framework_core_init() { // Queue of pending calls waiting to be batched Ajax._pending_calls = {}; // Timer for batching flush Ajax._flush_timeout = null; // Call counter for generating unique call IDs Ajax._call_counter = 0; // Maximum batch size before forcing immediate flush Ajax.MAX_BATCH_SIZE = 20; // Debounce time in milliseconds Ajax.DEBOUNCE_MS = 0; // Track promises from Ajax calls to detect uncaught rejections Ajax._tracked_promises = new WeakSet(); // Set up global unhandled rejection handler for Ajax errors window.addEventListener('unhandledrejection', async event => { // Only handle rejections from Ajax promises if (Ajax._tracked_promises.has(event.promise)) { event.preventDefault(); // Prevent browser's default "Uncaught (in promise)" error const error = event.reason; console.error('Uncaught Ajax error:', error); // Show Modal.error() for uncaught Ajax errors if (typeof Modal !== 'undefined' && Modal.error) { await Modal.error(error, 'Uncaught Ajax Error'); } } }); } /** * Make an AJAX call to an RSX controller action * * All calls are automatically batched unless window.rsxapp.ajax_disable_batching is true. * * @param {string|object|function} url - The Ajax URL (e.g., '/_ajax/Controller_Name/action_name') or an object/function with a .path property * @param {object} params - Parameters to send to the action * @returns {Promise} - Resolves with the return value, rejects with error */ static async call(url) { let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // If url is an object or function with a .path property, use that as the URL if (url && typeof url === 'object' && url.path) { url = url.path; } else if (url && typeof url === 'function' && url.path) { url = url.path; } // Validate url is a non-empty string if (typeof url !== 'string' || url.length === 0) { throw new Error('Ajax.call() requires a non-empty string URL or an object/function with a .path property'); } // Extract controller and action from URL const { controller, action } = Ajax.ajax_url_to_controller_action(url); console.log('Ajax:', controller, action, params); // Check if batching is disabled for debugging let promise; if (window.rsxapp && window.rsxapp.ajax_disable_batching) { promise = Ajax._call_direct(controller, action, params); } else { promise = Ajax._call_batch(controller, action, params); } // Track this promise for unhandled rejection detection Ajax._tracked_promises.add(promise); return promise; } /** * Make a batched Ajax call * @private */ static _call_batch(controller, action) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; console.log('Ajax Batch:', controller, action, params); return new Promise((resolve, reject) => { // Generate call key for deduplication const call_key = Ajax._generate_call_key(controller, action, params); // Check if this exact call is already pending if (Ajax._pending_calls[call_key]) { const existing_call = Ajax._pending_calls[call_key]; // If call already completed (cached), return immediately if (existing_call.is_complete) { if (existing_call.is_error) { reject(existing_call.error); } else { resolve(existing_call.result); } return; } // Call is pending, add this promise to callbacks existing_call.callbacks.push({ resolve, reject }); return; } // Create new pending call const call_id = Ajax._call_counter++; const pending_call = { call_id: call_id, call_key: call_key, controller: controller, action: action, params: params, callbacks: [{ resolve, reject }], is_complete: false, is_error: false, result: null, error: null }; // Add to pending queue Ajax._pending_calls[call_key] = pending_call; // Count pending calls const pending_count = Object.keys(Ajax._pending_calls).filter(key => !Ajax._pending_calls[key].is_complete).length; // If we've hit the batch size limit, flush immediately if (pending_count >= Ajax.MAX_BATCH_SIZE) { clearTimeout(Ajax._flush_timeout); Ajax._flush_timeout = null; Ajax._flush_pending_calls(); } else { // Schedule batch flush with debounce clearTimeout(Ajax._flush_timeout); Ajax._flush_timeout = setTimeout(() => { Ajax._flush_pending_calls(); }, Ajax.DEBOUNCE_MS); } }); } /** * Make a direct (non-batched) Ajax call * @private */ static async _call_direct(controller, action) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; // Construct URL from controller and action const url = `/_ajax/${controller}/${action}`; // Log the AJAX call using console_debug if (typeof Debugger !== 'undefined' && Debugger.console_debug) { Debugger.console_debug('AJAX', `Calling ${controller}.${action} (unbatched)`, params); } return new Promise((resolve, reject) => { $.ajax({ url: url, method: 'POST', data: params, dataType: 'json', __local_integration: true, // Bypass $.ajax override success: response => { // Handle console_debug messages if (response.console_debug && Array.isArray(response.console_debug)) { response.console_debug.forEach(msg => { if (!Array.isArray(msg) || msg.length !== 2) { throw new Error('Invalid console_debug message format - expected [channel, [arguments]]'); } const [channel, args] = msg; console.log(channel, ...args); }); } // Check if the response was successful if (response._success === true) { // @JS-AJAX-02-EXCEPTION - Unwrap server responses with _ajax_return_value const processed_value = Rsx_Js_Model._instantiate_models_recursive(response._ajax_return_value); resolve(processed_value); } else { // Handle error responses const error_type = response.error_type || 'unknown_error'; const reason = response.reason || 'Unknown error occurred'; const details = response.details || {}; // Handle specific error types switch (error_type) { case 'fatal': // Fatal PHP error with full error details const fatal_error_data = response.error || {}; const error_message = fatal_error_data.error || 'Fatal error occurred'; console.error('Ajax error response from server:', response.error); const fatal_error = new Error(error_message); fatal_error.type = 'fatal'; fatal_error.details = response.error; // Log to server if browser error logging is enabled Debugger.log_error({ message: `Ajax Fatal Error: ${error_message}`, type: 'ajax_fatal', endpoint: url, details: response.error }); reject(fatal_error); break; case 'response_auth_required': console.error('The user is no longer authenticated, this is a placeholder for future code which handles this scenario.'); const auth_error = new Error(reason); auth_error.type = 'auth_required'; auth_error.details = details; reject(auth_error); break; case 'response_unauthorized': console.error('The user is unauthorized to perform this action, this is a placeholder for future code which handles this scenario.'); const unauth_error = new Error(reason); unauth_error.type = 'unauthorized'; unauth_error.details = details; reject(unauth_error); break; case 'response_form_error': const form_error = new Error(reason); form_error.type = 'form_error'; form_error.details = details; reject(form_error); break; default: const generic_error = new Error(reason); generic_error.type = error_type; generic_error.details = details; reject(generic_error); break; } } }, error: (xhr, status, error) => { const error_message = Ajax._extract_error_message(xhr); const network_error = new Error(error_message); network_error.type = 'network_error'; network_error.status = xhr.status; network_error.statusText = status; // Log server errors (500+) to the server if browser error logging is enabled if (xhr.status >= 500) { Debugger.log_error({ message: `Ajax Server Error ${xhr.status}: ${error_message}`, type: 'ajax_server_error', endpoint: url, status: xhr.status, statusText: status }); } reject(network_error); } }); }); } /** * Flush all pending calls by sending batch request * @private */ static async _flush_pending_calls() { // Collect all pending calls const calls_to_send = []; const call_map = {}; // Map call_id to pending_call object for (const call_key in Ajax._pending_calls) { const pending_call = Ajax._pending_calls[call_key]; if (!pending_call.is_complete) { calls_to_send.push({ call_id: pending_call.call_id, controller: pending_call.controller, action: pending_call.action, params: pending_call.params }); call_map[pending_call.call_id] = pending_call; } } // Nothing to send if (calls_to_send.length === 0) { return; } // Log batch for debugging if (typeof Debugger !== 'undefined' && Debugger.console_debug) { Debugger.console_debug('AJAX_BATCH', `Sending batch of ${calls_to_send.length} calls`, calls_to_send.map(c => `${c.controller}.${c.action}`)); } try { // Send batch request const response = await $.ajax({ url: '/_ajax/_batch', method: 'POST', data: { batch_calls: JSON.stringify(calls_to_send) }, dataType: 'json', __local_integration: true // Bypass $.ajax override }); // Process batch response // Response format: { C_0: {success, _ajax_return_value}, C_1: {...}, ... } for (const response_key in response) { if (!response_key.startsWith('C_')) { continue; } const call_id = parseInt(response_key.substring(2), 10); const call_response = response[response_key]; const pending_call = call_map[call_id]; if (!pending_call) { console.error('Received response for unknown call_id:', call_id); continue; } // Handle console_debug messages if present if (call_response.console_debug && Array.isArray(call_response.console_debug)) { call_response.console_debug.forEach(msg => { if (!Array.isArray(msg) || msg.length !== 2) { throw new Error('Invalid console_debug message format - expected [channel, [arguments]]'); } const [channel, args] = msg; console.log(channel, ...args); }); } // Mark call as complete pending_call.is_complete = true; // Check if successful if (call_response._success === true) { // @JS-AJAX-02-EXCEPTION - Batch system unwraps server responses with _ajax_return_value const processed_value = Rsx_Js_Model._instantiate_models_recursive(call_response._ajax_return_value); pending_call.result = processed_value; // Resolve all callbacks pending_call.callbacks.forEach(_ref => { let { resolve } = _ref; resolve(processed_value); }); } else { // Handle error const error_type = call_response.error_type || 'unknown_error'; let error_message; let error_details; if (error_type === 'fatal' && call_response.error) { // Fatal PHP error with full error details const fatal_error_data = call_response.error; error_message = fatal_error_data.error || 'Fatal error occurred'; error_details = call_response.error; console.error('Ajax error response from server:', call_response.error); } else { // Other error types error_message = call_response.reason || 'Unknown error occurred'; error_details = call_response.details || {}; } const error = new Error(error_message); error.type = error_type; error.details = error_details; pending_call.is_error = true; pending_call.error = error; // Reject all callbacks pending_call.callbacks.forEach(_ref2 => { let { reject } = _ref2; reject(error); }); } } } catch (xhr_error) { // Network or server error - reject all pending calls const error_message = Ajax._extract_error_message(xhr_error); const error = new Error(error_message); error.type = 'network_error'; for (const call_id in call_map) { const pending_call = call_map[call_id]; pending_call.is_complete = true; pending_call.is_error = true; pending_call.error = error; pending_call.callbacks.forEach(_ref3 => { let { reject } = _ref3; reject(error); }); } console.error('Batch Ajax request failed:', error_message); } } /** * Generate a unique key for deduplicating calls * @private */ static _generate_call_key(controller, action, params) { // Create a stable string representation of the call // Sort params keys for consistent hashing const sorted_params = {}; Object.keys(params).sort().forEach(key => { sorted_params[key] = params[key]; }); return `${controller}::${action}::${JSON.stringify(sorted_params)}`; } /** * Extract error message from jQuery XHR object * @private */ static _extract_error_message(xhr) { if (xhr.responseJSON && xhr.responseJSON.message) { return xhr.responseJSON.message; } else if (xhr.responseText) { try { const response = JSON.parse(xhr.responseText); if (response.message) { return response.message; } } catch (e) { // Not JSON } } return `${xhr.status}: ${xhr.statusText || 'Unknown error'}`; } /** * Parses an AJAX URL into controller and action * Supports both /_ajax/ and /_/ URL prefixes * @param {string|object|function} url - URL in format '/_ajax/Controller_Name/action_name' or '/_/Controller_Name/action_name', or an object/function with a .path property * @returns {Object} Object with {controller: string, action: string} * @throws {Error} If URL doesn't start with /_ajax or /_ or has invalid structure */ static ajax_url_to_controller_action(url) { // If url is an object or function with a .path property, use that as the URL if (url && typeof url === 'object' && url.path) { url = url.path; } else if (url && typeof url === 'function' && url.path) { url = url.path; } // Validate url is a string if (typeof url !== 'string') { throw new Error(`URL must be a string or have a .path property, got: ${typeof url}`); } if (!url.startsWith('/_ajax') && !url.startsWith('/_/')) { throw new Error(`URL must start with /_ajax or /_, got: ${url}`); } const parts = url.split('/').filter(part => part !== ''); if (parts.length < 2) { throw new Error(`Invalid AJAX URL structure: ${url}`); } if (parts.length > 3) { throw new Error(`AJAX URL has too many segments: ${url}`); } const controller = parts[1]; const action = parts[2] || 'index'; return { controller, action }; } /** * Auto-initialize static properties when class is first loaded */ static on_core_define() { Ajax._on_framework_core_init(); } } /* === app/RSpade/Integrations/Jqhtml/Component.js (babel) === */ "use strict"; /** * Component - Base class for JQHTML components in RSX framework * * This class wraps the jqhtml.Component from the npm package and provides * the standard interface for RSX components following the Upper_Case naming convention. * * _Base_Jqhtml_Component is imported from npm via Jqhtml_Bundle. * * @Instantiatable */ class Component extends _Base_Jqhtml_Component {} // RSX manifest automatically makes classes global - no manual assignment needed /* === app/RSpade/Integrations/Jqhtml/Jqhtml_Integration.js (babel) === */ "use strict"; /** * JQHTML Integration - Automatic component registration and binding * * This module automatically: * 1. Registers component classes that extend Component * 2. Binds templates to component classes when names match * 3. Enables $(selector).component("Component_Name") syntax */ class Jqhtml_Integration { /** * Compiled Jqhtml templates self-register. The developer (the framework in this case) is still * responsible for registering es6 component classes with jqhtml. This does so at an early stage * of framework init. */ static _on_framework_modules_define() { let jqhtml_components = Manifest.get_extending('Component'); console_debug('JQHTML_INIT', 'Registering ' + jqhtml_components.length + ' Jqhtml Components'); for (let component of jqhtml_components) { jqhtml.register_component(component.class_name, component.class_object); } } /** * Framework modules init phase - Bind components and initialize DOM * This runs after templates are registered to bind component classes * @param {jQuery} [$scope] Optional scope to search within (defaults to body) * @returns {Array|undefined} Array of promises for recursive calls, undefined for top-level */ static _on_framework_modules_init($scope) { const is_top_level = !$scope; const promises = []; const components_needing_init = ($scope || $('body')).find('.Component_Init'); if (components_needing_init.length > 0) { console_debug('JQHTML_INIT', `Initializing ${components_needing_init.length} DOM components`); } components_needing_init.each(function () { const $element = $(this); // Skip if element is no longer attached to the document // (may have been removed by a parent component's .empty() call) if (!document.contains($element[0])) { return; } // Check if any parent has Component_Init class - skip nested components let parent = $element[0].parentElement; while (parent) { if (parent.classList.contains('Component_Init')) { return; // Skip this element, it's nested } parent = parent.parentElement; } const component_name = $element.attr('data-component-init-name'); // jQuery's .data() doesn't auto-parse JSON - we need to parse it manually let component_args = {}; const args_string = $element.attr('data-component-args'); // Unset component- php side initialization args, it is no longer needed as a compionent attribute // Unsetting also prevents undesired access to this code in other parts of the program, prevening an // unwanted future dependency on this paradigm $element.removeAttr('data-component-init-name'); $element.removeAttr('data-component-args'); $element.removeData('component-init-name'); $element.removeData('component-args'); if (args_string) { try { component_args = JSON.parse(args_string); } catch (e) { console.error(`[JQHTML Integration] Failed to parse component args for ${component_name}:`, e); component_args = {}; } } if (component_name) { // Transform $ prefixed keys to data- attributes let component_args_filtered = {}; for (const [key, value] of Object.entries(component_args)) { // if (key.startsWith('$')) { // component_args_filtered[key.substring(1)] = value; // } else if (key.startsWith('data-')) { component_args_filtered[key.substring(5)] = value; } else { component_args_filtered[key] = value; } } try { // Store inner HTML as string for nested component processing component_args_filtered._inner_html = $element.html(); $element.empty(); // Remove the init class before instantiation to prevent re-initialization $element.removeClass('Component_Init'); // Create promise for this component's initialization const component_promise = new Promise(resolve => { // Use jQuery component plugin to create the component // Plugin handles element internally, just pass args // Get the updated $element from let component = $element.component(component_name, component_args_filtered); component.on('render', function () { // Recursively collect promises from nested components // Getting the updated component here - if the tag name was not div, the element would have been recreated, so we need to get the element set on the component, not from our earlier selector const nested_promises = Jqhtml_Integration._on_framework_modules_init(component.$); promises.push(...nested_promises); // Resolve this component's promise resolve(); }).$; }); promises.push(component_promise); } catch (error) { console.error(`[JQHTML Integration] Failed to initialize component ${component_name}:`, error); console.error('Error details:', error.stack || error); } } }); // Top-level call: spawn async handler to wait for all promises, then trigger event if (is_top_level) { (async () => { await Promise.all(promises); await Rsx._rsx_call_all_classes('on_jqhtml_ready'); Rsx.trigger('jqhtml_ready'); })(); return; } // Recursive call: return promises for parent to collect return promises; } /** * Get all registered component names * @returns {Array} Array of component names */ static get_component_names() { return jqhtml.get_component_names(); } /** * Check if a component is registered * @param {string} name Component name * @returns {boolean} True if component is registered */ static has_component(name) { return jqhtml.has_component(name); } } // RSX manifest automatically makes classes global - no manual assignment needed /* === rsx/app/backend/backend_index.js (babel) === */ "use strict"; /** * Backend Module JavaScript */ class Backend_Index { /** * Initialize the backend/admin page * This method is automatically called by RSX framework for any class with a static on_app_ready() method * No manual registration is required */ static on_app_ready() { // Only initialize if we're on the backend page if (!$(".Backend_Index").exists()) { return; } Debugger.console_debug("JS_INIT", "Backend module initialized"); // Add any backend-specific JavaScript here // Example: Data tables, charts, admin functionality // Add active class to current sidebar link const currentPath = window.location.pathname; $('.sidebar .nav-link').each(function () { const $element = $(this); if ($element.attr('href') === currentPath) { $element.addClass('active'); } }); } } /* === storage/rsx-tmp/bundle_Backend_Bundle_d60e3c30.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], [Backend_Index, "Backend_Index", null] ]); /* === storage/rsx-tmp/bundle_Backend_Bundle_dd69eb16.js === */ // RSX Route Definitions - Generated by BundleCompiler // Provides route patterns for type-safe URL generation Rsx._define_routes({ "Backend_Index_Controller": { "index": "/admin" } }); /* === storage/rsx-tmp/bundle_Backend_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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0b3JhZ2UvcnN4LXRtcC9ucG1faW1wb3J0X2RlY2xhcmF0aW9uc185NWE2ZjYwMmM5ODAzNzYxMWI2NDBiMGI1MzQyODMwYi5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kZWNvcmF0b3IuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvYnJvd3Nlci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9kYXRldGltZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9lcnJvci5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9oYXNoLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL011dGV4LmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2FzeW5jLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL2Z1bmN0aW9ucy5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9NYW5pZmVzdC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfQmVoYXZpb3JzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9DYWNoZS5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSW5pdC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Sc3hfSnNfTW9kZWwuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X1ZpZXdfVHJhbnNpdGlvbnMuanMiLCJhcHAvUlNwYWRlL0NvcmUvSnMvUmVhZFdyaXRlTG9jay5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9Gb3JtX1V0aWxzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL0RlYnVnZ2VyLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeF9KcV9IZWxwZXJzLmpzIiwiYXBwL1JTcGFkZS9Db3JlL0pzL1JzeC5qcyIsImFwcC9SU3BhZGUvQ29yZS9Kcy9BamF4LmpzIiwiYXBwL1JTcGFkZS9JbnRlZ3JhdGlvbnMvSnFodG1sL0pxaHRtbF9Db21wb25lbnQuanMiLCJhcHAvUlNwYWRlL0ludGVncmF0aW9ucy9KcWh0bWwvSnFodG1sX0ludGVncmF0aW9uLmpzIiwicnN4L2FwcC9iYWNrZW5kL2JhY2tlbmRfaW5kZXguanMiLCJzdG9yYWdlL3JzeC10bXAvYnVuZGxlX0JhY2tlbmRfQnVuZGxlX2Q2MGUzYzMwLmpzIiwic3RvcmFnZS9yc3gtdG1wL2J1bmRsZV9CYWNrZW5kX0J1bmRsZV9kZDY5ZWIxNi5qcyIsInN0b3JhZ2UvcnN4LXRtcC9idW5kbGVfQmFja2VuZF9CdW5kbGVfZTgzZTQzZDMuanMiXSwibmFtZXMiOlsiZGVjb3JhdG9yIiwidmFsdWUiLCJpc19tb2JpbGUiLCJ0ZXN0IiwibmF2aWdhdG9yIiwidXNlckFnZW50IiwiJCIsIndpbmRvdyIsIndpZHRoIiwiaXNfZGVza3RvcCIsImdldF9vcyIsInVzZXJfYWdlbnQiLCJwbGF0Zm9ybSIsIm1hY29zX3BsYXRmb3JtcyIsIndpbmRvd3NfcGxhdGZvcm1zIiwiaW9zX3BsYXRmb3JtcyIsIm9zIiwiaXNfbW9iaWxlX2RldmljZSIsImluZGV4T2YiLCJpc19jcmF3bGVyIiwiYm90X3BhdHRlcm4iLCJzY3JvbGxfaW50b192aWV3X2lmX25lZWRlZCIsInRhcmdldCIsIiR0YXJnZXQiLCIkcGFyZW50IiwicGFyZW50IiwidGFyZ2V0X3RvcCIsInBvc2l0aW9uIiwidG9wIiwic2Nyb2xsVG9wIiwidGFyZ2V0X2hlaWdodCIsIm91dGVySGVpZ2h0IiwicGFyZW50X2hlaWdodCIsImhlaWdodCIsInNjcm9sbF9wb3NpdGlvbiIsIkRlYnVnZ2VyIiwiY29uc29sZV9kZWJ1ZyIsIm5ld19zY3JvbGxfcG9zaXRpb24iLCJNYXRoIiwibWF4IiwibWluIiwic2Nyb2xsSGVpZ2h0Iiwic2Nyb2xsX3BhZ2VfaW50b192aWV3X2lmX25lZWRlZCIsIm9mZnNldCIsIndpbmRvd19oZWlnaHQiLCJ3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uIiwiYW5pbWF0ZSIsIndhaXRfZm9yX2ltYWdlcyIsImNhbGxiYWNrIiwiJGltYWdlcyIsInRvdGFsX2ltYWdlcyIsImxlbmd0aCIsImltYWdlc19sb2FkZWQiLCJlYWNoIiwiaW1nIiwiSW1hZ2UiLCJvbmxvYWQiLCJvbmVycm9yIiwic3JjIiwiJG5ic3AiLCJlc2NhcGVfanFfc2VsZWN0b3IiLCJpZCIsInJlcGxhY2UiLCJ1bml4X3RpbWUiLCJyb3VuZCIsIkRhdGUiLCJnZXRUaW1lIiwieW1kaGlzX3RvX3VuaXgiLCJzdHJfZGF0ZSIsImRhdGUiLCJlcnJvciIsInN0ciIsImVycm9yX2NvZGUiLCJ1bmRlZiIsInN0YXR1cyIsInNob3VsZG50X2hhcHBlbiIsIm1lc3NhZ2UiLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJFcnJvciIsInN0YWNrIiwic3RhY2tMaW5lcyIsInNwbGl0IiwiY2FsbGVySW5mbyIsImNhbGxlckxpbmUiLCJtYXRjaCIsImVycm9yTWVzc2FnZSIsImNvbnNvbGUiLCJyZXBlYXQiLCJmYXRhbEVycm9yIiwibmFtZSIsImhhc2giLCJ0aGVfdmFyIiwiY2FsY19zaGExIiwiaWdub3JlZF9rZXlzIiwianNvbl9zdHJpbmdpZnlfbm9jaXJjIiwiY2FjaGUiLCJKU09OIiwic3RyaW5naWZ5Iiwia2V5IiwidiIsIl9jYWNoZV9rZXkiLCJfaGFzaF9rZXkiLCJwdXNoIiwiZmxhdF92YXIiLCJfZmxhdHRlbiIsInByZWZpeCIsImRlcHRoIiwiaXNfb2JqZWN0IiwiQWJzdHJhY3QiLCJrIiwiaGFzT3duUHJvcGVydHkiLCJpc19hcnJheSIsImkiLCJmb3JlYWNoIiwiaXNfZnVuY3Rpb24iLCJpc19udW1lcmljIiwiU3RyaW5nIiwic29ydGVyIiwic29ydCIsImEiLCJiIiwianNvbiIsImhhc2hlZCIsInNoYTEiLCJkZWVwX2VxdWFsIiwibXV0ZXgiLCJnbG9iYWxfaWQiLCJpbnN0YW5jZV9tdXRleGVzIiwiX2luc3RhbmNlX3N0b3JhZ2UiLCJXZWFrTWFwIiwiZ2xvYmFsX211dGV4ZXMiLCJfZ2xvYmFsX3N0b3JhZ2UiLCJNYXAiLCJnZXRfaW5zdGFuY2VfbXV0ZXgiLCJpbnN0YW5jZSIsIm1ldGhvZF9uYW1lIiwiaW5zdGFuY2VfbG9ja3MiLCJnZXQiLCJzZXQiLCJsb2NrX3N0YXRlIiwiYWN0aXZlIiwicXVldWUiLCJnZXRfZ2xvYmFsX211dGV4Iiwic2NoZWR1bGVfbmV4dCIsImZuIiwicmVzb2x2ZSIsInJlamVjdCIsInNoaWZ0IiwiUHJvbWlzZSIsInRoZW4iLCJmaW5hbGx5IiwiYWNxdWlyZV9sb2NrIiwiZGVzY3JpcHRvciIsIm9yaWdpbmFsX21ldGhvZCIsIl9sZW4iLCJhcmdzIiwiQXJyYXkiLCJfa2V5IiwiYXBwbHkiLCJfbGVuMiIsIl9rZXkyIiwic2xlZXAiLCJtaWxsaXNlY29uZHMiLCJyZXF1ZXN0QW5pbWF0aW9uRnJhbWUiLCJzZXRUaW1lb3V0IiwiZGVib3VuY2UiLCJjYWxsYmFja19vcl9kZWxheSIsImRlbGF5IiwiaW1tZWRpYXRlIiwiZGVjb3JhdG9yX2RlbGF5IiwiZGVjb3JhdG9yX2ltbWVkaWF0ZSIsImNvbnRleHQiLCJraW5kIiwiZGVib3VuY2VfaW1wbCIsInJ1bm5pbmciLCJxdWV1ZWQiLCJsYXN0X2VuZF90aW1lIiwidGltZXIiLCJuZXh0X2FyZ3MiLCJuZXh0X2NvbnRleHQiLCJyZXNvbHZlX3F1ZXVlIiwicmVqZWN0X3F1ZXVlIiwicnVuX2Z1bmN0aW9uIiwidGhlc2VfcmVzb2x2ZXMiLCJ0aGVzZV9yZWplY3RzIiwicmVzdWx0IiwiZXJyIiwibm93IiwiY2xlYXJUaW1lb3V0IiwiZmlyc3RfY2FsbCIsInNpbmNlIiwiSW5maW5pdHkiLCJ3YWl0Iiwicndsb2NrIiwiY2IiLCJSZWFkV3JpdGVMb2NrIiwiYWNxdWlyZSIsInJ3bG9ja19yZWFkIiwiYWNxdWlyZV9yZWFkIiwicndsb2NrX2ZvcmNlX3VubG9jayIsImZvcmNlX3VubG9jayIsInJ3bG9ja19wZW5kaW5nIiwicGVuZGluZyIsIm9iaiIsInJlc3VsdHMiLCJpc0FycmF5IiwiZm9yRWFjaCIsImluZGV4IiwicHJvbWlzZXMiLCJmaWx0ZXIiLCJhbGwiLCJuIiwiaXNOYU4iLCJwYXJzZUZsb2F0IiwiaXNGaW5pdGUiLCJpc19zdHJpbmciLCJzIiwiaXNfaW50ZWdlciIsIk51bWJlciIsImlzSW50ZWdlciIsImlzX3Byb21pc2UiLCJmdW5jdGlvbl90b19jaGVjayIsInRvU3RyaW5nIiwiY2FsbCIsImlzX2VtYWlsIiwiZW1haWwiLCJyZWdleCIsImlzc2V0IiwiZW1wdHkiLCJvYmplY3QiLCJmbG9hdCIsInZhbCIsInBhcnNlZCIsImludCIsInBhcnNlSW50IiwidmFsdWVfdW5sZXNzX251bWVyaWNfc3RyaW5nX3RoZW5fbnVtZXJpY192YWx1ZSIsImh0bWwiLCJfIiwiZXNjYXBlIiwibmwyYnIiLCJodG1sYnIiLCJ1cmxlbmNvZGUiLCJlbmNvZGVVUklDb21wb25lbnQiLCJ1cmxkZWNvZGUiLCJkZWNvZGVVUklDb21wb25lbnQiLCJqc29uX2VuY29kZSIsImpzb25fZGVjb2RlIiwicGFyc2UiLCJjaGFubmVsIiwidmFsdWVzIiwicmVwbGFjZV9hbGwiLCJzdHJpbmciLCJzZWFyY2giLCJqb2luIiwidWN3b3JkcyIsImlucHV0IiwibWFwIiwid29yZCIsImNoYXJBdCIsInRvVXBwZXJDYXNlIiwic2xpY2UiLCJjb3VudCIsIm8iLCJjIiwiY2xvbmUiLCJGdW5jdGlvbiIsInByb3RvdHlwZSIsIl9fY2xvbmUiLCJ0aGF0IiwidGVtcCIsImNsb25lZCIsImNvbnN0cnVjdG9yIiwiT2JqZWN0IiwiYXNzaWduIiwiY29hbGVzY2UiLCJmcm9tIiwicmV0dXJuX3ZhbCIsImFyZyIsImNzdl90b19hcnJheV90cmltIiwic3RyX2NzdiIsInBhcnRzIiwicmV0IiwicGFydCIsInRyaW0iLCJNYW5pZmVzdCIsIl9kZWZpbmUiLCJpdGVtcyIsIl9jbGFzc2VzIiwiaXRlbSIsImNsYXNzX29iamVjdCIsImNsYXNzX25hbWUiLCJjbGFzc19leHRlbmRzIiwiZGVjb3JhdG9ycyIsImNsYXNzIiwiZXh0ZW5kcyIsIl9uYW1lIiwiX2V4dGVuZHMiLCJfZGVjb3JhdG9ycyIsIl9idWlsZF9zdWJjbGFzc19pbmRleCIsIl9zdWJjbGFzc19pbmRleCIsImNsYXNzZGF0YSIsImN1cnJlbnRfY2xhc3NfbmFtZSIsImN1cnJlbnRfY2xhc3NkYXRhIiwiZXh0ZW5kc19uYW1lIiwiaW5jbHVkZXMiLCJnZXRfZXh0ZW5kaW5nIiwiYmFzZV9jbGFzcyIsImJhc2VfY2xhc3Nfb2JqZWN0IiwiZ2V0X2NsYXNzX2J5X25hbWUiLCJjbGFzc2VzIiwianNfaXNfc3ViY2xhc3Nfb2YiLCJsb2NhbGVDb21wYXJlIiwic3ViY2xhc3MiLCJzdXBlcmNsYXNzIiwic3ViY2xhc3Nfb2JqZWN0Iiwic3VwZXJjbGFzc19vYmplY3QiLCJjdXJyZW50X2NsYXNzIiwiZ2V0X2FsbF9jbGFzc2VzIiwiYnVpbGRfa2V5IiwicnN4YXBwIiwiZ2V0X2RlY29yYXRvcnMiLCJjbGFzc19pbmZvIiwiX3RyYW5zZm9ybV9kZWNvcmF0b3JzIiwiZ2V0X2FsbF9kZWNvcmF0b3JzIiwiY29tcGFjdF9kZWNvcmF0b3JzIiwiaGFzX2RlY29yYXRvciIsImRlY29yYXRvcl9uYW1lIiwic29tZSIsImQiLCJqc19nZXRfc3ViY2xhc3Nlc19vZiIsImJhc2VfY2xhc3NfbmFtZSIsInN1YmNsYXNzX25hbWVzIiwic3ViY2xhc3Nfb2JqZWN0cyIsInN1YmNsYXNzX25hbWUiLCJuYW1lX2EiLCJuYW1lX2IiLCJSc3hfQmVoYXZpb3JzIiwiX29uX2ZyYW1ld29ya19jb3JlX2luaXQiLCJfaW5pdF9pZ25vcmVfaW52YWxpZF9hbmNob3JfbGlua3MiLCJfdHJpbV9jb3BpZWRfdGV4dCIsImRvY3VtZW50Iiwib24iLCJlIiwiJGxpbmsiLCJocmVmIiwiYXR0ciIsImlzRGVmYXVsdFByZXZlbnRlZCIsImRhdGEiLCJwcmV2ZW50RGVmYXVsdCIsInN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbiIsInN0YXJ0c1dpdGgiLCJ0YXJnZXRJZCIsInN1YnN0cmluZyIsInRhcmdldEV4aXN0cyIsImdldEVsZW1lbnRCeUlkIiwicXVlcnlTZWxlY3RvciIsImFkZEV2ZW50TGlzdGVuZXIiLCJldmVudCIsInNoaWZ0S2V5Iiwic2VsZWN0aW9uIiwiZ2V0U2VsZWN0aW9uIiwic2VsZWN0ZWRfdGV4dCIsImNvbnRhaW5lciIsImdldFJhbmdlQXQiLCJjb21tb25BbmNlc3RvckNvbnRhaW5lciIsIm5vZGVUeXBlIiwicGFyZW50Tm9kZSIsImNsb3Nlc3QiLCJ0cmltbWVkX3RleHQiLCJjbGlwYm9hcmREYXRhIiwic2V0RGF0YSIsImxvZyIsIlJzeF9DYWNoZSIsIm9uX2NvcmVfZGVmaW5lIiwiQ29yZV9DYWNoZSIsIl9jYWNoZXMiLCJnbG9iYWwiLCJfY2FjaGVzX3NldCIsImdldF9pbnN0YW5jZSIsIk1haW4iLCJkZWJ1ZyIsImtleV9lbmNvZGVkIiwiX2VuY29kZWtleSIsImdldF9nbG9iYWwiLCJnZXRfc2Vzc2lvbiIsIl9zdXBwb3J0c1N0b3JhZ2UiLCJycyIsInNlc3Npb25TdG9yYWdlIiwiZ2V0SXRlbSIsInNldF9zZXNzaW9uIiwiX3RyeWFnYWluIiwicmVtb3ZlSXRlbSIsInNldEl0ZW0iLCJfaXNPdXRPZlNwYWNlIiwiY2xlYXIiLCJfcmVzZXQiLCJfX3N1cHBvcnRzU3RvcmFnZSIsImV4IiwiUnN4X0luaXQiLCJSc3giLCJpc19wcm9kIiwiX19lbnZpcm9ubWVudF9jaGVja3MiLCJzY3JpcHRzIiwiZ2V0RWxlbWVudHNCeVRhZ05hbWUiLCJzY3JpcHQiLCJkZWZlciIsInJlYXNvbiIsIl9yc3hfY29yZV9ib290X3N0b3AiLCJSc3hfSnNfTW9kZWwiLCJfX01PREVMIiwibW9kZWxEYXRhIiwiZmV0Y2giLCJDdXJyZW50Q2xhc3MiLCJtb2RlbE5hbWUiLCJyZXNwb25zZSIsImFqYXgiLCJ1cmwiLCJtZXRob2QiLCJkYXRhVHlwZSIsIl9pbnN0YW50aWF0ZV9tb2RlbHNfcmVjdXJzaXZlIiwiZ2V0TW9kZWxOYW1lIiwicmVmcmVzaCIsImZyZXNoIiwidG9PYmplY3QiLCJ0b0pTT04iLCJNb2RlbENsYXNzIiwiUnN4X1ZpZXdfVHJhbnNpdGlvbnMiLCJzdGFydFZpZXdUcmFuc2l0aW9uIiwiX2luamVjdF90cmFuc2l0aW9uX2NzcyIsInN0eWxlIiwiY3JlYXRlRWxlbWVudCIsInRleHRDb250ZW50IiwiaGVhZCIsImFwcGVuZENoaWxkIiwiXzUwYWU2MDllX2Fzc2VydENsYXNzQnJhbmQiLCJfNTBhZTYwOWVfZ2V0X2xvY2siLCJ3cml0ZXJfcSIsIl81MGFlNjA5ZV9zY2hlZHVsZSIsIndyaXRlcl9hY3RpdmUiLCJyZWFkZXJfcSIsInJlYWRlcnMiLCJfbG9ja3MiLCJkZWxldGUiLCJfNTBhZTYwOWVfUmVhZFdyaXRlTG9jayIsImJhdGNoIiwic3BsaWNlIiwiRm9ybV9VdGlscyIsIl9vbl9mcmFtZXdvcmtfY29yZV9kZWZpbmUiLCJwYXJhbXMiLCJhamF4X3N1Ym1pdCIsIm9wdGlvbnMiLCIkZWxlbWVudCIsImlzIiwiY29udHJvbGxlciIsImFjdGlvbiIsIkFqYXgiLCJhamF4X3VybF90b19jb250cm9sbGVyX2FjdGlvbiIsImFwcGx5X2Zvcm1fZXJyb3JzIiwicGFyZW50X3NlbGVjdG9yIiwiZXJyb3JzIiwicmVzZXRfZm9ybV9lcnJvcnMiLCJub3JtYWxpemVkIiwiX25vcm1hbGl6ZV9lcnJvcnMiLCJhbmltYXRpb25zIiwidHlwZSIsIl9hcHBseV9nZW5lcmFsX2Vycm9ycyIsImRlZHVwbGljYXRlZCIsIl9kZWR1cGxpY2F0ZV9lcnJvcnMiLCJfYXBwbHlfZmllbGRfZXJyb3JzIiwibWF0Y2hlZF9jb3VudCIsImtleXMiLCJ1bm1hdGNoZWQiLCJ1bm1hdGNoZWRfZGVkdXBsaWNhdGVkIiwidW5tYXRjaGVkX2NvdW50Iiwic3VtbWFyeV9tc2ciLCJzdW1tYXJ5X2FuaW1hdGlvbnMiLCJfYXBwbHlfY29tYmluZWRfZXJyb3IiLCIkZXJyb3JfY29udGFpbmVyIiwiZmluZCIsImZpcnN0IiwiY29udGFpbmVyX3RvcCIsImZpeGVkX2hlYWRlcl9oZWlnaHQiLCJfZ2V0X2ZpeGVkX2hlYWRlcl9oZWlnaHQiLCJ0YXJnZXRfc2Nyb2xsIiwicmVzZXQiLCJmb3JtX3NlbGVjdG9yIiwiJGZvcm0iLCJ0cmlnZ2VyIiwic2VyaWFsaXplIiwic2VyaWFsaXplQXJyYXkiLCJmb3JtX2RhdGEiLCJvbl9zdWNjZXNzIiwiZGV0YWlscyIsIm9uX2Vycm9yIiwicmVtb3ZlIiwicmVtb3ZlQ2xhc3MiLCJldmVyeSIsInVud3JhcHBlZCIsImZpZWxkIiwiU2V0Iiwic2VlbiIsImhhcyIsImFkZCIsImZpZWxkX2Vycm9ycyIsImZpZWxkX25hbWUiLCJlcnJvcl9tZXNzYWdlIiwiJGlucHV0IiwiJGVycm9yIiwiYWRkQ2xhc3MiLCJhcHBlbmRUbyIsImhpZGUiLCJmYWRlSW4iLCJwcm9taXNlIiwidW5tYXRjaGVkX2Vycm9ycyIsIiRhbGVydCIsInRleHQiLCIkbGlzdCIsImVycm9yX21zZyIsInByZXBlbmRUbyIsIm1lc3NhZ2VzIiwibXNnIiwiZXJyb3JfbGlzdCIsInRvdGFsX2hlaWdodCIsIiRlbCIsImNzcyIsIm91dGVyV2lkdGgiLCJ2aWV3cG9ydF93aWR0aCIsImxvZ19icm93c2VyX2Vycm9ycyIsIl9oYW5kbGVfYnJvd3Nlcl9lcnJvciIsImZpbGVuYW1lIiwibGluZW5vIiwiY29sbm8iLCJvbl9yZWZyZXNoIiwiZW5hYmxlZCIsImNvbmZpZyIsImZpbHRlcl9tb2RlIiwic3BlY2lmaWMiLCJzcGVjaWZpY19jaGFubmVsIiwiY2hhbm5lbHMiLCJ3aGl0ZWxpc3QiLCJmaWx0ZXJfY2hhbm5lbHMiLCJibGFja2xpc3QiLCJ0aW1lc3RhbXAiLCJ0b0lTT1N0cmluZyIsImluY2x1ZGVfbG9jYXRpb24iLCJpbmNsdWRlX2JhY2t0cmFjZSIsImxvY2F0aW9uIiwiYmFja3RyYWNlIiwibGluZSIsIm91dHB1dHMiLCJicm93c2VyIiwiaW5jbHVkZV9iZW5jaG1hcmsiLCJfZ2V0X3RpbWVfcHJlZml4IiwiY2hhbm5lbFByZWZpeCIsImNvbnNvbGVNZXRob2QiLCJsYXJhdmVsX2xvZyIsIl9iYXRjaF9jb25zb2xlX21lc3NhZ2UiLCJsb2dfZXJyb3IiLCJlcnJvckRhdGEiLCJfZXJyb3JfY291bnQiLCJNQVhfRVJST1JTX1BFUl9QQUdFIiwiX2Vycm9yX2JhdGNoX2NvdW50IiwiTUFYX0VSUk9SX0JBVENIRVMiLCJfZXJyb3JfYmF0Y2giLCJfZXJyb3JfdGltZXIiLCJfZmx1c2hfZXJyb3JfYmF0Y2giLCJERUJPVU5DRV9NUyIsIl9jb25zb2xlX2JhdGNoIiwiX2NvbnNvbGVfdGltZXIiLCJfZmx1c2hfY29uc29sZV9iYXRjaCIsIlJvdXRlIiwiX3N0YXJ0X3RpbWUiLCJlbGFwc2VkIiwidG9GaXhlZCIsIl8yN2UwZTk4Nl9kZWZpbmVQcm9wZXJ0eSIsIlJzeF9KcV9IZWxwZXJzIiwiZXhpc3RzIiwiaXNfdmlzaWJsZSIsInNjcm9sbF91cF90byIsInNwZWVkIiwiaXNfaW5fZG9tIiwiZV90b3AiLCJzX3RvcCIsImV4cHIiLCJmb2N1cyIsImVsZW0iLCJhY3RpdmVFbGVtZW50IiwiX2NsaWNrX25hdGl2ZSIsImNsaWNrIiwiaGFuZGxlciIsIm9yaWdpbmFsX3ByZXZlbnREZWZhdWx0IiwiYmluZCIsIndhcm4iLCJjbGlja19hbGxvd19kZWZhdWx0IiwiX2FuY2VzdG9yIiwiSFRNTG9iaiIsInBhcmVudEVsZW1lbnQiLCJkb2N1bWVudEVsZW1lbnQiLCJpc19pbl92aWV3cG9ydCIsInNjcm9sbHRvcCIsInRvcF9vZl9lbGVtZW50IiwiYm90dG9tX29mX2VsZW1lbnQiLCJib3R0b21fb2Zfc2NyZWVuIiwiaW5uZXJIZWlnaHQiLCJ0b3Bfb2Zfc2NyZWVuIiwidGFnbmFtZSIsInByb3AiLCJ0b0xvd2VyQ2FzZSIsImlzX2V4dGVybmFsIiwiaG9zdCIsImxpbmsiLCJob3N0bmFtZSIsImNoZWNrVmFsaWRpdHkiLCJyZXBvcnRWYWxpZGl0eSIsInJlcXVlc3RTdWJtaXQiLCJjbG9zZXN0X3NpYmxpbmciLCJzZWxlY3RvciIsIiRjdXJyZW50IiwiJGZvdW5kIiwibmF0aXZlX2FqYXgiLCJzZXR0aW5ncyIsInJlcXVlc3RfdXJsIiwiaXNfcmVsYXRpdmUiLCJpc19zYW1lX2RvbWFpbiIsIm9yaWdpbiIsImlzX2xvY2FsX3JlcXVlc3QiLCJfX2xvY2FsX2ludGVncmF0aW9uIiwiaXNfZmlsZV91cGxvYWQiLCJlbmRzV2l0aCIsImNvbnRyb2xsZXJfbmFtZSIsImFjdGlvbl9uYW1lIiwidXJsX21hdGNoIiwiX2luaXRfZXZlbnRzIiwiX2V2ZW50X2hhbmRsZXJzIiwiX3RyaWdnZXJlZF9ldmVudHMiLCJ0cmlnZ2VyX3JlZnJlc2giLCJDb3JlX0xvZyIsImlzX2RldiIsInVpZCIsIl91aWQiLCJfZGVmaW5lX3JvdXRlcyIsInJvdXRlcyIsIl9yb3V0ZXMiLCJwYXJhbXNfb2JqIiwicGF0dGVybiIsIl9nZW5lcmF0ZV91cmxfZnJvbV9wYXR0ZXJuIiwicmVxdWlyZWRfcGFyYW1zIiwibWF0Y2hlcyIsIm1pc3NpbmciLCJyZXF1aXJlZCIsInVzZWRfcGFyYW1zIiwicGFyYW1fbmFtZSIsImVuY29kZWRfdmFsdWUiLCJxdWVyeV9wYXJhbXMiLCJxdWVyeV9zdHJpbmciLCJlbnRyaWVzIiwiX3JlZiIsIl9yc3hfY2FsbF9hbGxfY2xhc3NlcyIsImFsbF9jbGFzc2VzIiwiY2xhc3Nlc193aXRoX21ldGhvZCIsInByb21pc2VfcGlsZSIsInJldHVybl92YWx1ZSIsIl9fc3RvcHBlZCIsIl9yc3hfY29yZV9ib290IiwiX19ib290ZWQiLCJwaGFzZXMiLCJwaGFzZSIsIl9wYXJzZV9oYXNoIiwiaGFzaF9zdHJpbmciLCJwYWlycyIsInBhaXIiLCJfc2VyaWFsaXplX2hhc2giLCJnZXRfYWxsX3BhZ2Vfc3RhdGUiLCJnZXRfcGFnZV9zdGF0ZSIsIl9zdGF0ZSRrZXkiLCJzdGF0ZSIsInNldF9wYWdlX3N0YXRlIiwibmV3X2hhc2giLCJwYXRobmFtZSIsImhpc3RvcnkiLCJyZXBsYWNlU3RhdGUiLCJzZXRfYWxsX3BhZ2Vfc3RhdGUiLCJuZXdfc3RhdGUiLCJyZW5kZXJfZXJyb3IiLCIkY29udGFpbmVyIiwiZmlsZSIsIl9lc2NhcGVfaHRtbCIsImRpdiIsImlubmVySFRNTCIsIl9lODIxMWY1Yl9kZWZpbmVQcm9wZXJ0eSIsIl9wZW5kaW5nX2NhbGxzIiwiX2ZsdXNoX3RpbWVvdXQiLCJfY2FsbF9jb3VudGVyIiwiTUFYX0JBVENIX1NJWkUiLCJfdHJhY2tlZF9wcm9taXNlcyIsIldlYWtTZXQiLCJNb2RhbCIsInBhdGgiLCJhamF4X2Rpc2FibGVfYmF0Y2hpbmciLCJfY2FsbF9kaXJlY3QiLCJfY2FsbF9iYXRjaCIsImNhbGxfa2V5IiwiX2dlbmVyYXRlX2NhbGxfa2V5IiwiZXhpc3RpbmdfY2FsbCIsImlzX2NvbXBsZXRlIiwiaXNfZXJyb3IiLCJjYWxsYmFja3MiLCJjYWxsX2lkIiwicGVuZGluZ19jYWxsIiwicGVuZGluZ19jb3VudCIsIl9mbHVzaF9wZW5kaW5nX2NhbGxzIiwic3VjY2VzcyIsIl9zdWNjZXNzIiwicHJvY2Vzc2VkX3ZhbHVlIiwiX2FqYXhfcmV0dXJuX3ZhbHVlIiwiZXJyb3JfdHlwZSIsImZhdGFsX2Vycm9yX2RhdGEiLCJmYXRhbF9lcnJvciIsImVuZHBvaW50IiwiYXV0aF9lcnJvciIsInVuYXV0aF9lcnJvciIsImZvcm1fZXJyb3IiLCJnZW5lcmljX2Vycm9yIiwieGhyIiwiX2V4dHJhY3RfZXJyb3JfbWVzc2FnZSIsIm5ldHdvcmtfZXJyb3IiLCJzdGF0dXNUZXh0IiwiY2FsbHNfdG9fc2VuZCIsImNhbGxfbWFwIiwiYmF0Y2hfY2FsbHMiLCJyZXNwb25zZV9rZXkiLCJjYWxsX3Jlc3BvbnNlIiwiZXJyb3JfZGV0YWlscyIsIl9yZWYyIiwieGhyX2Vycm9yIiwiX3JlZjMiLCJzb3J0ZWRfcGFyYW1zIiwicmVzcG9uc2VKU09OIiwicmVzcG9uc2VUZXh0IiwiSnFodG1sX0NvbXBvbmVudCIsIl9CYXNlX0pxaHRtbF9Db21wb25lbnQiLCJKcWh0bWxfSW50ZWdyYXRpb24iLCJfb25fZnJhbWV3b3JrX21vZHVsZXNfZGVmaW5lIiwianFodG1sX2NvbXBvbmVudHMiLCJjb21wb25lbnQiLCJqcWh0bWwiLCJyZWdpc3Rlcl9jb21wb25lbnQiLCJfb25fZnJhbWV3b3JrX21vZHVsZXNfaW5pdCIsIiRzY29wZSIsImlzX3RvcF9sZXZlbCIsImNvbXBvbmVudHNfbmVlZGluZ19pbml0IiwiY29udGFpbnMiLCJjbGFzc0xpc3QiLCJjb21wb25lbnRfbmFtZSIsImNvbXBvbmVudF9hcmdzIiwiYXJnc19zdHJpbmciLCJyZW1vdmVBdHRyIiwicmVtb3ZlRGF0YSIsImNvbXBvbmVudF9hcmdzX2ZpbHRlcmVkIiwiX2lubmVyX2h0bWwiLCJjb21wb25lbnRfcHJvbWlzZSIsIm5lc3RlZF9wcm9taXNlcyIsImdldF9jb21wb25lbnRfbmFtZXMiLCJoYXNfY29tcG9uZW50IiwiQmFja2VuZF9JbmRleCIsIm9uX2FwcF9yZWFkeSIsImN1cnJlbnRQYXRoIl0sIm1hcHBpbmdzIjoiO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVNBLFNBQVNBLENBQUNDLEtBQUssRUFBRTtFQUN0QixPQUFPQSxLQUFLO0FBQ2hCOzs7Ozs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTQyxTQUFTQSxDQUFBLEVBQUc7RUFDakIsSUFBSSxnRUFBZ0UsQ0FBQ0MsSUFBSSxDQUFDQyxTQUFTLENBQUNDLFNBQVMsQ0FBQyxFQUFFO0lBQzVGLE9BQU8sSUFBSTtFQUNmLENBQUMsTUFBTSxJQUFJQyxDQUFDLENBQUNDLE1BQU0sQ0FBQyxDQUFDQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEdBQUcsRUFBRTtJQUNoQztJQUNBLE9BQU8sSUFBSTtFQUNmLENBQUMsTUFBTTtJQUNILE9BQU8sS0FBSztFQUNoQjtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBU0MsVUFBVUEsQ0FBQSxFQUFHO0VBQ2xCLE9BQU8sQ0FBQ1As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LEVBQUUsNEJBQTRCLENBQUM7O0lBRS9EO0lBQ0E7O0lBRUE7SUFDQSxNQUFNMnRCLFdBQVcsR0FBR3h2QixNQUFNLENBQUM0aEIsUUFBUSxDQUFDb0ksUUFBUTtJQUM1Q2pxQixDQUFDLENBQUMsb0JBQW9CLENBQUMsQ0FBQytDLElBQUksQ0FBQyxZQUFXO01BQ3BDLE1BQU0rWSxRQUFRLEdBQUc5YixDQUFDLENBQUMsSUFBSSxDQUFDO01BQ3hCLElBQUk4YixRQUFRLENBQUMxRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUtxYSxXQUFXLEVBQUU7UUFDdkMzVCxRQUFRLENBQUN5RCxRQUFRLENBQUMsUUFBUSxDQUFDO01BQy9CO0lBQ0osQ0FBQyxDQUFDO0VBQ047QUFDSjs7OztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHIiwiZmlsZSI6ImJ1bmRsZV9vdXRwdXRfQmFja2VuZF9CdW5kbGUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBOUE0gSW1wb3J0IERlY2xhcmF0aW9ucyBmb3IgQXBwIEJ1bmRsZVxuLy8gQXV0by1nZW5lcmF0ZWQgdG8gcHJvdmlkZSBOUE0gbW9kdWxlcyB0byBhcHAgYnVuZGxlIHNjb3BlXG4vLyBDYWNoZSBrZXk6IDk1YTZmNjAyYzk4MDM3NjExYjY0MGIwYjUzNDI4MzBiXG5cbmNvbnN0IGpxaHRtbCA9IHdpbmRvdy5fcnN4X25wbS5qcWh0bWw7XG5pZiAoIWpxaHRtbCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1JTWCBGcmFtZXdvcmsgRXJyb3I6IE5QTSBtb2R1bGUgXCJqcWh0bWxcIiBub3QgZm91bmQuXFxuJyArXG4gICAgICAgICdFeHBlY3RlZCB3aW5kb3cuX3JzeF9ucG0uanFodG1sIHRvIGJlIGRlZmluZWQgYnkgdGhlIHZlbmRvciBidW5kbGUuJ1xuICAgICk7XG59XG5cbmNvbnN0IF9CYXNlX0pxaHRtbF9Db21wb25lbnQgPSB3aW5kb3cuX3JzeF9ucG0uX0Jhc2VfSnFodG1sX0NvbXBvbmVudDtcbmlmICghX0Jhc2VfSnFodG1sX0NvbXBvbmVudCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1JTWCBGcmFtZXdvcmsgRXJyb3I6IE5QTSBtb2R1bGUgXCJfQmFzZV9KcWh0bWxfQ29tcG9uZW50XCIgbm90IGZvdW5kLlxcbicgK1xuICAgICAgICAnRXhwZWN0ZWQgd2luZG93Ll9yc3hfbnBtLl9CYXNlX0pxaHRtbF9Db21wb25lbnQgdG8gYmUgZGVmaW5lZCBieSB0aGUgdmVuZG9yIGJ1bmRsZS4nXG4gICAgKTtcbn1cblxuLy8gQ2xlYW4gdXAgTlBNIGNvbnRhaW5lciB0byBwcmV2ZW50IGNvbnNvbGUgYWNjZXNzXG5kZWxldGUgd2luZG93Ll9yc3hfbnBtO1xuIiwiLyoqXG4gKiBEZWNvcmF0b3IgZnVuY3Rpb24gdGhhdCBtYXJrcyBhIGZ1bmN0aW9uIGFzIGEgZGVjb3JhdG9yIGltcGxlbWVudGF0aW9uLlxuICpcbiAqIFdoZW4gYSBmdW5jdGlvbiBoYXMgQGRlY29yYXRvciBpbiBpdHMgSlNEb2MgY29tbWVudCwgaXQgd2hpdGVsaXN0cyB0aGF0IGZ1bmN0aW9uXG4gKiB0byBiZSB1c2VkIGFzIGEgZGVjb3JhdG9yIG9uIG90aGVyIG1ldGhvZHMgdGhyb3VnaG91dCB0aGUgY29kZWJhc2UuXG4gKlxuICogVGhlIGZ1bmN0aW9uIGl0c2VsZiBwZXJmb3JtcyBubyBvcGVyYXRpb24gLSBpdCBzaW1wbHkgcmV0dXJucyBpdHMgaW5wdXQgdW5jaGFuZ2VkLlxuICogSXRzIHB1cnBvc2UgaXMgcHVyZWx5IGFzIGEgbWFya2VyIGZvciB0aGUgbWFuaWZlc3QgdmFsaWRhdGlvbiBzeXN0ZW0uXG4gKlxuICogVXNhZ2U6XG4gKiAgIC8vIC8qKlxuICogICAvLyAgKiBNeSBjdXN0b20gZGVjb3JhdG9yIGltcGxlbWVudGF0aW9uXG4gKiAgIC8vICAqIEBkZWNvcmF0b3JcbiAqICAgLy8gICpcXC9cbiAqICAgZnVuY3Rpb24gbXlfY3VzdG9tX2RlY29yYXRvcih0YXJnZXQsIGtleSwgZGVzY3JpcHRvcikge1xuICogICAgICAgLy8gRGVjb3JhdG9yIGltcGxlbWVudGF0aW9uXG4gKiAgIH1cbiAqXG4gKiBUaGlzIGFsbG93cyBteV9jdXN0b21fZGVjb3JhdG9yIHRvIGJlIHVzZWQgYXMgQG15X2N1c3RvbV9kZWNvcmF0b3Igb24gc3RhdGljIG1ldGhvZHMuXG4gKlxuICogVE9ETzogVGhpcyBpcyBwcm9iYWJseSBubyBsb25nZXIgbmVjZXNzYXJ5PyBtYXliZT9cbiAqL1xuZnVuY3Rpb24gZGVjb3JhdG9yKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuIiwiLypcbiAqIEJyb3dzZXIgYW5kIERPTSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIGJyb3dzZXIgZGV0ZWN0aW9uLCB2aWV3cG9ydCB1dGlsaXRpZXMsIGFuZCBET00gbWFuaXB1bGF0aW9uLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEJST1dTRVIgREVURUNUSU9OXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogRGV0ZWN0cyBpZiB1c2VyIGlzIG9uIGEgbW9iaWxlIGRldmljZSBvciB1c2luZyBtb2JpbGUgdmlld3BvcnRcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIG1vYmlsZSBkZXZpY2Ugb3Igdmlld3BvcnQgPCA5OTJweFxuICogQHRvZG8gSW1wcm92ZSB1c2VyIGFnZW50IGRldGVjdGlvbiBmb3IgYWxsIG1vYmlsZSBkZXZpY2VzXG4gKi9cbmZ1bmN0aW9uIGlzX21vYmlsZSgpIHtcbiAgICBpZiAoL0FuZHJvaWR8d2ViT1N8aVBob25lfGlQYWR8aVBvZHxCbGFja0JlcnJ5fElFTW9iaWxlfE9wZXJhIE1pbmkvaS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAoJCh3aW5kb3cpLndpZHRoKCkgPCA5OTIpIHtcbiAgICAgICAgLy8gOTkycHggPSBib290c3RyYXAgNCBjb2wtbWQtXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG59XG5cbi8qKlxuICogRGV0ZWN0cyBpZiB1c2VyIGlzIG9uIGRlc2t0b3AgKG5vdCBtb2JpbGUpXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBub3QgbW9iaWxlIGRldmljZS92aWV3cG9ydFxuICovXG5mdW5jdGlvbiBpc19kZXNrdG9wKCkge1xuICAgIHJldHVybiAhaXNfbW9iaWxlKCk7XG59XG5cbi8qKlxuICogRGV0ZWN0cyB0aGUgdXNlcidzIG9wZXJhdGluZyBzeXN0ZW1cbiAqIEByZXR1cm5zIHtzdHJpbmd9IE9TIG5hbWU6ICdNYWMgT1MnLCAnaVBob25lJywgJ2lQYWQnLCAnV2luZG93cycsICdBbmRyb2lkLVBob25lJywgJ0FuZHJvaWQtVGFibGV0JywgJ0xpbnV4Jywgb3IgJ1Vua25vd24nXG4gKi9cbmZ1bmN0aW9uIGdldF9vcygpIHtcbiAgICBsZXQgdXNlcl9hZ2VudCA9IHdpbmRvdy5uYXZpZ2F0b3IudXNlckFnZW50LFxuICAgICAgICBwbGF0Zm9ybSA9IHdpbmRvdy5uYXZpZ2F0b3IucGxhdGZvcm0sXG4gICAgICAgIG1hY29zX3BsYXRmb3JtcyA9IFsnTWFjaW50b3NoJywgJ01hY0ludGVsJywgJ01hY1BQQycsICdNYWM2OEsnXSxcbiAgICAgICAgd2luZG93c19wbGF0Zm9ybXMgPSBbJ1dpbjMyJywgJ1dpbjY0JywgJ1dpbmRvd3MnLCAnV2luQ0UnXSxcbiAgICAgICAgaW9zX3BsYXRmb3JtcyA9IFsnaVBob25lJywgJ2lQYWQnLCAnaVBvZCddLFxuICAgICAgICBvcyA9IG51bGw7XG5cbiAgICBsZXQgaXNfbW9iaWxlX2RldmljZSA9IGlzX21vYmlsZSgpO1xuXG4gICAgaWYgKG1hY29zX3BsYXRmb3Jtcy5pbmRleE9mKHBsYXRmb3JtKSAhPT0gLTEpIHtcbiAgICAgICAgb3MgPSAnTWFjIE9TJztcbiAgICB9IGVsc2UgaWYgKGlvc19wbGF0Zm9ybXMuaW5kZXhPZihwbGF0Zm9ybSkgIT09IC0xICYmIGlzX21vYmlsZV9kZXZpY2UpIHtcbiAgICAgICAgb3MgPSAnaVBob25lJztcbiAgICB9IGVsc2UgaWYgKGlvc19wbGF0Zm9ybXMuaW5kZXhPZihwbGF0Zm9ybSkgIT09IC0xICYmICFpc19tb2JpbGVfZGV2aWNlKSB7XG4gICAgICAgIG9zID0gJ2lQYWQnO1xuICAgIH0gZWxzZSBpZiAod2luZG93c19wbGF0Zm9ybXMuaW5kZXhPZihwbGF0Zm9ybSkgIT09IC0xKSB7XG4gICAgICAgIG9zID0gJ1dpbmRvd3MnO1xuICAgIH0gZWxzZSBpZiAoL0FuZHJvaWQvLnRlc3QodXNlcl9hZ2VudCkgJiYgaXNfbW9iaWxlX2RldmljZSkge1xuICAgICAgICBvcyA9ICdBbmRyb2lkLVBob25lJztcbiAgICB9IGVsc2UgaWYgKC9BbmRyb2lkLy50ZXN0KHVzZXJfYWdlbnQpICYmICFpc19tb2JpbGVfZGV2aWNlKSB7XG4gICAgICAgIG9zID0gJ0FuZHJvaWQtVGFibGV0JztcbiAgICB9IGVsc2UgaWYgKCFvcyAmJiAvTGludXgvLnRlc3QocGxhdGZvcm0pKSB7XG4gICAgICAgIG9zID0gJ0xpbnV4JztcbiAgICB9IGVsc2Uge1xuICAgICAgICBvcyA9ICdVbmtub3duJztcbiAgICB9XG5cbiAgICByZXR1cm4gb3M7XG59XG5cbi8qKlxuICogRGV0ZWN0cyBpZiB0aGUgdXNlciBhZ2VudCBpcyBhIHdlYiBjcmF3bGVyL2JvdFxuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdXNlciBhZ2VudCBhcHBlYXJzIHRvIGJlIGEgYm90L2NyYXdsZXJcbiAqL1xuZnVuY3Rpb24gaXNfY3Jhd2xlcigpIHtcbiAgICBsZXQgdXNlcl9hZ2VudCA9IG5hdmlnYXRvci51c2VyQWdlbnQ7XG4gICAgbGV0IGJvdF9wYXR0ZXJuID0gL2JvdHxzcGlkZXJ8Y3Jhd2x8c2x1cnB8YXJjaGl2ZXJ8cGluZ3xzZWFyY2h8ZGlnfHRyYWNrZXJ8bW9uaXRvcnxzbm9vcHl8eWFob298YmFpZHV8bXNufGFza3x0ZW9tYXxheGlvcy9pO1xuXG4gICAgcmV0dXJuIGJvdF9wYXR0ZXJuLnRlc3QodXNlcl9hZ2VudCk7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERPTSBTQ1JPTExJTkcgVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogU2Nyb2xscyBwYXJlbnQgY29udGFpbmVyIHRvIG1ha2UgdGFyZ2V0IGVsZW1lbnQgdmlzaWJsZSBpZiBuZWVkZWRcbiAqIEBwYXJhbSB7c3RyaW5nfEhUTUxFbGVtZW50fGpRdWVyeX0gdGFyZ2V0IC0gVGFyZ2V0IGVsZW1lbnQgdG8gc2Nyb2xsIGludG8gdmlld1xuICovXG5mdW5jdGlvbiBzY3JvbGxfaW50b192aWV3X2lmX25lZWRlZCh0YXJnZXQpIHtcbiAgICBjb25zdCAkdGFyZ2V0ID0gJCh0YXJnZXQpO1xuXG4gICAgLy8gRmluZCB0aGUgY2xvc2VzdCBwYXJlbnQgd2l0aCBvdmVyZmxvdy15OiBhdXRvXG4gICAgY29uc3QgJHBhcmVudCA9ICR0YXJnZXQucGFyZW50KCk7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGFic29sdXRlIHRvcCBwb3NpdGlvbiBvZiB0aGUgdGFyZ2V0XG4gICAgY29uc3QgdGFyZ2V0X3RvcCA9ICR0YXJnZXQucG9zaXRpb24oKS50b3AgKyAkcGFyZW50LnNjcm9sbFRvcCgpO1xuXG4gICAgY29uc3QgdGFyZ2V0X2hlaWdodCA9ICR0YXJnZXQub3V0ZXJIZWlnaHQoKTtcbiAgICBjb25zdCBwYXJlbnRfaGVpZ2h0ID0gJHBhcmVudC5oZWlnaHQoKTtcbiAgICBjb25zdCBzY3JvbGxfcG9zaXRpb24gPSAkcGFyZW50LnNjcm9sbFRvcCgpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHRhcmdldCBpcyBvdXQgb2Ygdmlld1xuICAgIGlmICh0YXJnZXRfdG9wIDwgc2Nyb2xsX3Bvc2l0aW9uIHx8IHRhcmdldF90b3AgKyB0YXJnZXRfaGVpZ2h0ID4gc2Nyb2xsX3Bvc2l0aW9uICsgcGFyZW50X2hlaWdodCkge1xuICAgICAgICBEZWJ1Z2dlci5jb25zb2xlX2RlYnVnKCdVSScsICdTY3JvbGxpbmchJywgdGFyZ2V0X3RvcCk7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuZXcgc2Nyb2xsIHBvc2l0aW9uIHRvIGNlbnRlciB0aGUgdGFyZ2V0XG4gICAgICAgIGxldCBuZXdfc2Nyb2xsX3Bvc2l0aW9uID0gdGFyZ2V0X3RvcCArIHRhcmdldF9oZWlnaHQgLyAyIC0gcGFyZW50X2hlaWdodCAvIDI7XG5cbiAgICAgICAgLy8gTGltaXQgdGhlIHNjcm9sbCBwb3NpdGlvbiBiZXR3ZWVuIDAgYW5kIHRoZSBtYXhpbXVtIHNjcm9sbGFibGUgaGVpZ2h0XG4gICAgICAgIG5ld19zY3JvbGxfcG9zaXRpb24gPSBNYXRoLm1heCgwLCBNYXRoLm1pbihuZXdfc2Nyb2xsX3Bvc2l0aW9uLCAkcGFyZW50WzBdLnNjcm9sbEhlaWdodCAtIHBhcmVudF9oZWlnaHQpKTtcblxuICAgICAgICAvLyBTY3JvbGwgdGhlIHBhcmVudCB0byB0aGUgbmV3IHNjcm9sbCBwb3NpdGlvblxuICAgICAgICAkcGFyZW50LnNjcm9sbFRvcChuZXdfc2Nyb2xsX3Bvc2l0aW9uKTtcbiAgICB9XG59XG5cbi8qKlxuICogU2Nyb2xscyBwYWdlIHRvIG1ha2UgdGFyZ2V0IGVsZW1lbnQgdmlzaWJsZSBpZiBuZWVkZWQgKHdpdGggYW5pbWF0aW9uKVxuICogQHBhcmFtIHtzdHJpbmd8SFRNTEVsZW1lbnR8alF1ZXJ5fSB0YXJnZXQgLSBUYXJnZXQgZWxlbWVudCB0byBzY3JvbGwgaW50byB2aWV3XG4gKi9cbmZ1bmN0aW9uIHNjcm9sbF9wYWdlX2ludG9fdmlld19pZl9uZWVkZWQodGFyZ2V0KSB7XG4gICAgY29uc3QgJHRhcmdldCA9ICQodGFyZ2V0KTtcblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgYWJzb2x1dGUgdG9wIHBvc2l0aW9uIG9mIHRoZSB0YXJnZXQgcmVsYXRpdmUgdG8gdGhlIGRvY3VtZW50XG4gICAgY29uc3QgdGFyZ2V0X3RvcCA9ICR0YXJnZXQub2Zmc2V0KCkudG9wO1xuXG4gICAgY29uc3QgdGFyZ2V0X2hlaWdodCA9ICR0YXJnZXQub3V0ZXJIZWlnaHQoKTtcbiAgICBjb25zdCB3aW5kb3dfaGVpZ2h0ID0gJCh3aW5kb3cpLmhlaWdodCgpO1xuICAgIGNvbnN0IHdpbmRvd19zY3JvbGxfcG9zaXRpb24gPSAkKHdpbmRvdykuc2Nyb2xsVG9wKCk7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgdGFyZ2V0IGlzIG91dCBvZiB2aWV3XG4gICAgaWYgKHRhcmdldF90b3AgPCB3aW5kb3dfc2Nyb2xsX3Bvc2l0aW9uIHx8IHRhcmdldF90b3AgKyB0YXJnZXRfaGVpZ2h0ID4gd2luZG93X3Njcm9sbF9wb3NpdGlvbiArIHdpbmRvd19oZWlnaHQpIHtcbiAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZygnVUknLCAnU2Nyb2xsaW5nIScsIHRhcmdldF90b3ApO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmV3IHNjcm9sbCBwb3NpdGlvbiB0byBjZW50ZXIgdGhlIHRhcmdldFxuICAgICAgICBjb25zdCBuZXdfc2Nyb2xsX3Bvc2l0aW9uID0gdGFyZ2V0X3RvcCArIHRhcmdldF9oZWlnaHQgLyAyIC0gd2luZG93X2hlaWdodCAvIDI7XG5cbiAgICAgICAgLy8gQW5pbWF0ZSB0aGUgc2Nyb2xsIHRvIHRoZSBuZXcgcG9zaXRpb25cbiAgICAgICAgJCgnaHRtbCwgYm9keScpLmFuaW1hdGUoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgc2Nyb2xsVG9wOiBuZXdfc2Nyb2xsX3Bvc2l0aW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIDEwMDBcbiAgICAgICAgKTsgLy8gZHVyYXRpb24gb2YgdGhlIHNjcm9sbCBhbmltYXRpb24gaW4gbWlsbGlzZWNvbmRzXG4gICAgfVxufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBET00gVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogV2FpdHMgZm9yIGFsbCBpbWFnZXMgb24gdGhlIHBhZ2UgdG8gbG9hZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgLSBGdW5jdGlvbiB0byBjYWxsIHdoZW4gYWxsIGltYWdlcyBhcmUgbG9hZGVkXG4gKi9cbmZ1bmN0aW9uIHdhaXRfZm9yX2ltYWdlcyhjYWxsYmFjaykge1xuICAgIGNvbnN0ICRpbWFnZXMgPSAkKCdpbWcnKTsgLy8gR2V0IGFsbCBpbWcgdGFnc1xuICAgIGNvbnN0IHRvdGFsX2ltYWdlcyA9ICRpbWFnZXMubGVuZ3RoO1xuICAgIGxldCBpbWFnZXNfbG9hZGVkID0gMDtcblxuICAgIGlmICh0b3RhbF9pbWFnZXMgPT09IDApIHtcbiAgICAgICAgY2FsbGJhY2soKTsgLy8gaWYgdGhlcmUgYXJlIG5vIGltYWdlcywgaW1tZWRpYXRlbHkgY2FsbCB0aGUgY2FsbGJhY2tcbiAgICB9XG5cbiAgICAkaW1hZ2VzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBpbWcgPSBuZXcgSW1hZ2UoKTtcbiAgICAgICAgaW1nLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGltYWdlc19sb2FkZWQrKztcbiAgICAgICAgICAgIGlmIChpbWFnZXNfbG9hZGVkID09PSB0b3RhbF9pbWFnZXMpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpOyAvLyBjYWxsIHRoZSBjYWxsYmFjayB3aGVuIGFsbCBpbWFnZXMgYXJlIGxvYWRlZFxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpbWcub25lcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGltYWdlc19sb2FkZWQrKztcbiAgICAgICAgICAgIGlmIChpbWFnZXNfbG9hZGVkID09PSB0b3RhbF9pbWFnZXMpIHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjaygpOyAvLyBhbHNvIGNhbGwgdGhlIGNhbGxiYWNrIGlmIGFuIGltYWdlIGZhaWxzIHRvIGxvYWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgaW1nLnNyYyA9IHRoaXMuc3JjOyAvLyB0aGlzIHRyaWdnZXJzIHRoZSBsb2FkaW5nXG4gICAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIGpRdWVyeSBlbGVtZW50IGNvbnRhaW5pbmcgYSBub24tYnJlYWtpbmcgc3BhY2VcbiAqIEByZXR1cm5zIHtqUXVlcnl9IGpRdWVyeSBzcGFuIGVsZW1lbnQgd2l0aCAmbmJzcDtcbiAqL1xuZnVuY3Rpb24gJG5ic3AoKSB7XG4gICAgcmV0dXJuICQoJzxzcGFuPiZuYnNwOzwvc3Bhbj4nKTtcbn1cblxuLyoqXG4gKiBFc2NhcGVzIHNwZWNpYWwgY2hhcmFjdGVycyBpbiBhIGpRdWVyeSBzZWxlY3RvclxuICogQHBhcmFtIHtzdHJpbmd9IGlkIC0gRWxlbWVudCBJRCB0byBlc2NhcGVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IGpRdWVyeSBzZWxlY3RvciBzdHJpbmcgd2l0aCBlc2NhcGVkIHNwZWNpYWwgY2hhcmFjdGVyc1xuICogQHdhcm5pbmcgTm90IHNhZmUgZm9yIHNlY3VyaXR5LWNyaXRpY2FsIG9wZXJhdGlvbnNcbiAqL1xuZnVuY3Rpb24gZXNjYXBlX2pxX3NlbGVjdG9yKGlkKSB7XG4gICAgcmV0dXJuICcjJyArIGlkLnJlcGxhY2UoLyg6fFxcLnxcXFt8XFxdfCx8PXxAKS9nLCAnXFxcXCQxJyk7XG59IiwiLypcbiAqIERhdGUgYW5kIHRpbWUgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSBkYXRlL3RpbWUgY29udmVyc2lvbnMgYW5kIFVuaXggdGltZXN0YW1wcy5cbiAqL1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBEQVRFL1RJTUUgVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogR2V0cyB0aGUgY3VycmVudCBVbml4IHRpbWVzdGFtcCAoc2Vjb25kcyBzaW5jZSBlcG9jaClcbiAqIEByZXR1cm5zIHtudW1iZXJ9IEN1cnJlbnQgVW5peCB0aW1lc3RhbXAgaW4gc2Vjb25kc1xuICogQHRvZG8gQ2FsY3VsYXRlIGJhc2VkIG9uIHNlcnZlciB0aW1lIGF0IHBhZ2UgcmVuZGVyXG4gKiBAdG9kbyBNb3ZlIHRvIGEgZGF0ZSBsaWJyYXJ5XG4gKi9cbmZ1bmN0aW9uIHVuaXhfdGltZSgpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGEgZGF0ZSBzdHJpbmcgdG8gVW5peCB0aW1lc3RhbXBcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJfZGF0ZSAtIERhdGUgc3RyaW5nIChZLW0tZCBIOmk6cyBmb3JtYXQpXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBVbml4IHRpbWVzdGFtcCBpbiBzZWNvbmRzXG4gKi9cbmZ1bmN0aW9uIHltZGhpc190b191bml4KHN0cl9kYXRlKSB7XG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKHN0cl9kYXRlKTtcbiAgICByZXR1cm4gZGF0ZS5nZXRUaW1lKCkgLyAxMDAwO1xufSIsIi8qXG4gKiBFcnJvciBoYW5kbGluZyB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIGVycm9yIGNyZWF0aW9uIGFuZCBkZWJ1Z2dpbmcgdXRpbGl0aWVzLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEVSUk9SIEhBTkRMSU5HXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBlcnJvciBvYmplY3QgZnJvbSBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd8T2JqZWN0fSBzdHIgLSBFcnJvciBtZXNzYWdlIG9yIGV4aXN0aW5nIGVycm9yIG9iamVjdFxuICogQHBhcmFtIHtudW1iZXJ9IFtlcnJvcl9jb2RlXSAtIE9wdGlvbmFsIGVycm9yIHN0YXR1cyBjb2RlXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBFcnJvciBvYmplY3Qgd2l0aCBlcnJvciBhbmQgc3RhdHVzIHByb3BlcnRpZXNcbiAqL1xuZnVuY3Rpb24gZXJyb3Ioc3RyLCBlcnJvcl9jb2RlKSB7XG4gICAgaWYgKHR5cGVvZiBzdHIuZXJyb3IgIT0gdW5kZWYpIHtcbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodHlwZW9mIGVycm9yX2NvZGUgPT0gdW5kZWYpIHtcbiAgICAgICAgICAgIHJldHVybiB7IGVycm9yOiBzdHIsIHN0YXR1czogbnVsbCB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHsgZXJyb3I6IHN0ciwgc3RhdHVzOiBlcnJvcl9jb2RlIH07XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogU2FuaXR5IGNoZWNrIGZhaWx1cmUgaGFuZGxlciBmb3IgSmF2YVNjcmlwdFxuICpcbiAqIFRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGNhbGxlZCB3aGVuIGEgc2FuaXR5IGNoZWNrIGZhaWxzIC0gaS5lLiwgd2hlbiB0aGUgY29kZVxuICogZW5jb3VudGVycyBhIGNvbmRpdGlvbiB0aGF0IFwic2hvdWxkbid0IGhhcHBlblwiIGlmIGV2ZXJ5dGhpbmcgaXMgd29ya2luZyBjb3JyZWN0bHkuXG4gKlxuICogVW5saWtlIFBIUCwgd2UgY2FuJ3Qgc3RvcCBKYXZhU2NyaXB0IGV4ZWN1dGlvbiwgYnV0IHdlIGNhbjpcbiAqIDEuIFRocm93IGFuIGVycm9yIHRoYXQgd2lsbCBiZSBjYXVnaHQgYnkgZXJyb3IgaGFuZGxlcnNcbiAqIDIuIExvZyBhIGNsZWFyIGVycm9yIHRvIHRoZSBjb25zb2xlXG4gKiAzLiBQcm92aWRlIHN0YWNrIHRyYWNlIGZvciBkZWJ1Z2dpbmdcbiAqXG4gKiBVc2UgdGhpcyBpbnN0ZWFkIG9mIHNpbGVudGx5IHJldHVybmluZyBvciBjb250aW51aW5nIHdoZW4gZW5jb3VudGVyaW5nIHVuZXhwZWN0ZWQgY29uZGl0aW9ucy5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSBPcHRpb25hbCBzcGVjaWZpYyBtZXNzYWdlIGFib3V0IHdoYXQgc2hvdWxkbid0IGhhdmUgaGFwcGVuZWRcbiAqIEB0aHJvd3Mge0Vycm9yfSBBbHdheXMgdGhyb3dzIHdpdGggbG9jYXRpb24gYW5kIGNvbnRleHQgaW5mb3JtYXRpb25cbiAqL1xuZnVuY3Rpb24gc2hvdWxkbnRfaGFwcGVuKG1lc3NhZ2UgPSBudWxsKSB7XG4gICAgY29uc3QgZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgICBjb25zdCBzdGFjayA9IGVycm9yLnN0YWNrIHx8ICcnO1xuICAgIGNvbnN0IHN0YWNrTGluZXMgPSBzdGFjay5zcGxpdCgnXFxuJyk7XG5cbiAgICAvLyBHZXQgdGhlIGNhbGxlciBsb2NhdGlvbiAoc2tpcCB0aGUgRXJyb3IgbGluZSBhbmQgdGhpcyBmdW5jdGlvbilcbiAgICBsZXQgY2FsbGVySW5mbyA9ICd1bmtub3duIGxvY2F0aW9uJztcbiAgICBpZiAoc3RhY2tMaW5lcy5sZW5ndGggPiAyKSB7XG4gICAgICAgIGNvbnN0IGNhbGxlckxpbmUgPSBzdGFja0xpbmVzWzJdIHx8IHN0YWNrTGluZXNbMV0gfHwgJyc7XG4gICAgICAgIC8vIEV4dHJhY3QgZmlsZSBhbmQgbGluZSBudW1iZXIgZnJvbSBzdGFjayB0cmFjZVxuICAgICAgICBjb25zdCBtYXRjaCA9IGNhbGxlckxpbmUubWF0Y2goL2F0XFxzKy4qP1xccytcXCgoLio/KTooXFxkKyk6KFxcZCspXFwpLykgfHwgY2FsbGVyTGluZS5tYXRjaCgvYXRcXHMrKC4qPyk6KFxcZCspOihcXGQrKS8pO1xuICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgIGNhbGxlckluZm8gPSBgJHttYXRjaFsxXX06JHttYXRjaFsyXX1gO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGVycm9yTWVzc2FnZSA9IGBGYXRhbDogc2hvdWxkbnRfaGFwcGVuKCkgd2FzIGNhbGxlZCBhdCAke2NhbGxlckluZm99XFxuYDtcbiAgICBlcnJvck1lc3NhZ2UgKz0gJ1RoaXMgaW5kaWNhdGVzIGEgc2FuaXR5IGNoZWNrIGZhaWxlZCAtIHRoZSBjb2RlIGlzIG5vdCBiZWhhdmluZyBhcyBleHBlY3RlZC5cXG4nO1xuXG4gICAgaWYgKG1lc3NhZ2UpIHtcbiAgICAgICAgZXJyb3JNZXNzYWdlICs9IGBEZXRhaWxzOiAke21lc3NhZ2V9XFxuYDtcbiAgICB9XG5cbiAgICBlcnJvck1lc3NhZ2UgKz0gJ1BsZWFzZSB0aG9yb3VnaGx5IHJldmlldyB0aGUgcmVsYXRlZCBjb2RlIHRvIGRldGVybWluZSB3aHkgdGhpcyBlcnJvciBvY2N1cnJlZC4nO1xuXG4gICAgLy8gTG9nIHRvIGNvbnNvbGUgd2l0aCBmdWxsIHZpc2liaWxpdHlcbiAgICBjb25zb2xlLmVycm9yKCc9Jy5yZXBlYXQoODApKTtcbiAgICBjb25zb2xlLmVycm9yKCdTQU5JVFkgQ0hFQ0sgRkFJTFVSRScpO1xuICAgIGNvbnNvbGUuZXJyb3IoJz0nLnJlcGVhdCg4MCkpO1xuICAgIGNvbnNvbGUuZXJyb3IoZXJyb3JNZXNzYWdlKTtcbiAgICBjb25zb2xlLmVycm9yKCdTdGFjayB0cmFjZTonLCBzdGFjayk7XG4gICAgY29uc29sZS5lcnJvcignPScucmVwZWF0KDgwKSk7XG5cbiAgICAvLyBUaHJvdyBlcnJvciB0byBzdG9wIGV4ZWN1dGlvbiBmbG93XG4gICAgY29uc3QgZmF0YWxFcnJvciA9IG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpO1xuICAgIGZhdGFsRXJyb3IubmFtZSA9ICdTYW5pdHlDaGVja0ZhaWx1cmUnO1xuICAgIHRocm93IGZhdGFsRXJyb3I7XG59IiwiLypcbiAqIEhhc2hpbmcgYW5kIGNvbXBhcmlzb24gdXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBSU3BhZGUgZnJhbWV3b3JrLlxuICogVGhlc2UgZnVuY3Rpb25zIGhhbmRsZSBvYmplY3QgaGFzaGluZyBhbmQgZGVlcCBjb21wYXJpc29uLlxuICovXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEhBU0hJTkcgQU5EIENPTVBBUklTT05cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgaGFzaCBmb3IgYW55IHZhbHVlIChoYW5kbGVzIG9iamVjdHMsIGFycmF5cywgY2lyY3VsYXIgcmVmZXJlbmNlcylcbiAqIEBwYXJhbSB7Kn0gdGhlX3ZhciAtIFZhbHVlIHRvIGhhc2hcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2NhbGNfc2hhMT10cnVlXSAtIElmIHRydWUsIHJldHVybnMgU0hBMSBoYXNoOyBpZiBmYWxzZSwgcmV0dXJucyBKU09OXG4gKiBAcGFyYW0ge0FycmF5PHN0cmluZz59IFtpZ25vcmVkX2tleXM9bnVsbF0gLSBLZXlzIHRvIGlnbm9yZSB3aGVuIGhhc2hpbmcgb2JqZWN0c1xuICogQHJldHVybnMge3N0cmluZ30gU0hBMSBoYXNoIG9yIEpTT04gc3RyaW5nIG9mIHRoZSB2YWx1ZVxuICovXG5mdW5jdGlvbiBoYXNoKHRoZV92YXIsIGNhbGNfc2hhMSA9IHRydWUsIGlnbm9yZWRfa2V5cyA9IG51bGwpIHtcbiAgICBpZiAodHlwZW9mIHRoZV92YXIgPT0gdW5kZWYpIHtcbiAgICAgICAgdGhlX3ZhciA9ICdfX3VuZGVmaW5lZF9fJztcbiAgICB9XG5cbiAgICBpZiAoaWdub3JlZF9rZXlzID09PSBudWxsKSB7XG4gICAgICAgIGlnbm9yZWRfa2V5cyA9IFsnJCddO1xuICAgIH1cblxuICAgIC8vIENvbnZlcnRzIHZhbHVlIHRvIGpzb24sIGRpc2NhcmRpbmcgY2lyY3VsYXIgcmVmZXJlbmNlc1xuICAgIGxldCBqc29uX3N0cmluZ2lmeV9ub2NpcmMgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgY29uc3QgY2FjaGUgPSBbXTtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlLCBmdW5jdGlvbiAoa2V5LCB2KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHYgPT09ICdvYmplY3QnICYmIHR5cGVvZiB0aGVfdmFyLl9jYWNoZV9rZXkgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGVfdmFyLl9oYXNoX2tleSgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdiA9PT0gJ29iamVjdCcgJiYgdiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmIChjYWNoZS5pbmRleE9mKHYpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBEdXBsaWNhdGUgcmVmZXJlbmNlIGZvdW5kLCBkaXNjYXJkIGtleVxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNhY2hlLnB1c2godik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdjtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8vIFR1cm4gZXZlcnkgcHJvcGVydHkgYW5kIGFsbCBpdHMgY2hpbGRyZW4gaW50byBhIHNpbmdsZSBkZXB0aCBhcnJheSBvZiB2YWx1ZXMgdGhhdCB3ZSBjYW4gdGhlblxuICAgIC8vIHNvcnQgYW5kIGhhc2ggYXMgYSB3aG9sZVxuICAgIGxldCBmbGF0X3ZhciA9IHt9O1xuICAgIGxldCBfZmxhdHRlbiA9IGZ1bmN0aW9uICh0aGVfdmFyLCBwcmVmaXgsIGRlcHRoID0gMCkge1xuICAgICAgICAvLyBJZiBhIGNsYXNzIG9iamVjdCBpcyBwcm92aWRlZCwgY2lyY3VsYXIgcmVmZXJlbmNlcyBjYW4gbWFrZSB0aGUgY2FsbCBzdGFjayByZWN1cnNpdmUuXG4gICAgICAgIC8vIEZvciB0aGUgcHVycG9zZXMgb2YgaG93IHRoZSBoYXNoIGZ1bmN0aW9uIGlzIGNhbGxlZCwgdGhpcyBzaG91bGQgYmUgc3VmZmljaWVudC5cbiAgICAgICAgaWYgKGRlcHRoID4gMTApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERvZXMgbm90IGFjY291bnQgZm9yIGRhdGVzIGkgdGhpbmsuLi5cblxuICAgICAgICBpZiAoaXNfb2JqZWN0KHRoZV92YXIpICYmIHR5cGVvZiB0aGVfdmFyLl9jYWNoZV9rZXkgPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgLy8gVXNlIF9jYWNoZV9rZXkgdG8gaGFzaCBjb21wb25lbnRzXG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0gdGhlX3Zhci5faGFzaF9rZXkoKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc19vYmplY3QodGhlX3ZhcikgJiYgdHlwZW9mIEFic3RyYWN0ICE9PSAndW5kZWZpbmVkJyAmJiB0aGVfdmFyIGluc3RhbmNlb2YgQWJzdHJhY3QpIHtcbiAgICAgICAgICAgIC8vIFN0cmluZ2lmeSBhbGwgY2xhc3Mgb2JqZWN0c1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IGpzb25fc3RyaW5naWZ5X25vY2lyYyh0aGVfdmFyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc19vYmplY3QodGhlX3ZhcikpIHtcbiAgICAgICAgICAgIC8vIEl0ZXJhdGUgb3RoZXIgb2JqZWN0c1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IHt9O1xuICAgICAgICAgICAgZm9yIChsZXQgayBpbiB0aGVfdmFyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoZV92YXIuaGFzT3duUHJvcGVydHkoaykgJiYgaWdub3JlZF9rZXlzLmluZGV4T2YoaykgPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgX2ZsYXR0ZW4odGhlX3ZhcltrXSwgcHJlZml4ICsgJy4uJyArIGssIGRlcHRoICsgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGlzX2FycmF5KHRoZV92YXIpKSB7XG4gICAgICAgICAgICAvLyBJdGVyYXRlIGFycmF5c1xuICAgICAgICAgICAgZmxhdF92YXJbcHJlZml4XSA9IFtdO1xuICAgICAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICAgICAgZm9yZWFjaCh0aGVfdmFyLCAodikgPT4ge1xuICAgICAgICAgICAgICAgIF9mbGF0dGVuKHYsIHByZWZpeCArICcuLicgKyBpLCBkZXB0aCArIDEpO1xuICAgICAgICAgICAgICAgIGkrKztcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKGlzX2Z1bmN0aW9uKHRoZV92YXIpKSB7XG4gICAgICAgICAgICAvLyBub3RoaW5nXG4gICAgICAgIH0gZWxzZSBpZiAoIWlzX251bWVyaWModGhlX3ZhcikpIHtcbiAgICAgICAgICAgIGZsYXRfdmFyW3ByZWZpeF0gPSBTdHJpbmcodGhlX3Zhcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmbGF0X3ZhcltwcmVmaXhdID0gdGhlX3ZhcjtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBfZmxhdHRlbih0aGVfdmFyLCAnXycpO1xuXG4gICAgbGV0IHNvcnRlciA9IFtdO1xuXG4gICAgZm9yZWFjaChmbGF0X3ZhciwgZnVuY3Rpb24gKHYsIGspIHtcbiAgICAgICAgc29ydGVyLnB1c2goW2ssIHZdKTtcbiAgICB9KTtcblxuICAgIHNvcnRlci5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgIHJldHVybiBhWzBdID4gYlswXTtcbiAgICB9KTtcblxuICAgIGxldCBqc29uID0gSlNPTi5zdHJpbmdpZnkoc29ydGVyKTtcblxuICAgIGlmIChjYWxjX3NoYTEpIHtcbiAgICAgICAgbGV0IGhhc2hlZCA9IHNoYTEuc2hhMShqc29uKTtcbiAgICAgICAgcmV0dXJuIGhhc2hlZDtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4ganNvbjtcbiAgICB9XG59XG5cbi8qKlxuICogRGVlcCBjb21wYXJpc29uIG9mIHR3byB2YWx1ZXMgKGlnbm9yZXMgcHJvcGVydHkgb3JkZXIgYW5kIGZ1bmN0aW9ucylcbiAqIEBwYXJhbSB7Kn0gYSAtIEZpcnN0IHZhbHVlIHRvIGNvbXBhcmVcbiAqIEBwYXJhbSB7Kn0gYiAtIFNlY29uZCB2YWx1ZSB0byBjb21wYXJlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB2YWx1ZXMgYXJlIGRlZXBseSBlcXVhbFxuICovXG5mdW5jdGlvbiBkZWVwX2VxdWFsKGEsIGIpIHtcbiAgICByZXR1cm4gaGFzaChhLCBmYWxzZSkgPT0gaGFzaChiLCBmYWxzZSk7XG59IiwiLyoqXG4gKiBNdXRleCBkZWNvcmF0b3IgZm9yIGV4Y2x1c2l2ZSBtZXRob2QgZXhlY3V0aW9uXG4gKlxuICogV2l0aG91dCBhcmd1bWVudHM6IFBlci1pbnN0YW5jZSBsb2NraW5nIChlYWNoIG9iamVjdCBoYXMgaXRzIG93biBsb2NrIHBlciBtZXRob2QpXG4gKiAgIEBtdXRleFxuICogICBhc3luYyBteV9tZXRob2QoKSB7IC4uLiB9XG4gKlxuICogV2l0aCBJRCBhcmd1bWVudDogR2xvYmFsIGxvY2tpbmcgYnkgSUQgKGFsbCBpbnN0YW5jZXMgc2hhcmUgdGhlIGxvY2spXG4gKiAgIEBtdXRleCgnb3BlcmF0aW9uX25hbWUnKVxuICogICBhc3luYyBteV9tZXRob2QoKSB7IC4uLiB9XG4gKlxuICogQGRlY29yYXRvclxuICogQHBhcmFtIHtzdHJpbmd9IFtnbG9iYWxfaWRdIC0gT3B0aW9uYWwgZ2xvYmFsIG11dGV4IElEIGZvciBjcm9zcy1pbnN0YW5jZSBsb2NraW5nXG4gKi9cbmZ1bmN0aW9uIG11dGV4KGdsb2JhbF9pZCkge1xuICAgIC8vIFN0b3JhZ2UgKHVzaW5nIElJRkVzIHRvIGtlZXAgV2Vha01hcC9NYXAgaW4gY2xvc3VyZSBzY29wZSlcbiAgICBjb25zdCBpbnN0YW5jZV9tdXRleGVzID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAoIW11dGV4Ll9pbnN0YW5jZV9zdG9yYWdlKSB7XG4gICAgICAgICAgICBtdXRleC5faW5zdGFuY2Vfc3RvcmFnZSA9IG5ldyBXZWFrTWFwKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG11dGV4Ll9pbnN0YW5jZV9zdG9yYWdlO1xuICAgIH0pKCk7XG5cbiAgICBjb25zdCBnbG9iYWxfbXV0ZXhlcyA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKCFtdXRleC5fZ2xvYmFsX3N0b3JhZ2UpIHtcbiAgICAgICAgICAgIG11dGV4Ll9nbG9iYWxfc3RvcmFnZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbXV0ZXguX2dsb2JhbF9zdG9yYWdlO1xuICAgIH0pKCk7XG5cbiAgICAvKipcbiAgICAgKiBHZXQgb3IgY3JlYXRlIGEgbXV0ZXggZm9yIGEgc3BlY2lmaWMgaW5zdGFuY2UgYW5kIG1ldGhvZFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldF9pbnN0YW5jZV9tdXRleChpbnN0YW5jZSwgbWV0aG9kX25hbWUpIHtcbiAgICAgICAgbGV0IGluc3RhbmNlX2xvY2tzID0gaW5zdGFuY2VfbXV0ZXhlcy5nZXQoaW5zdGFuY2UpO1xuICAgICAgICBpZiAoIWluc3RhbmNlX2xvY2tzKSB7XG4gICAgICAgICAgICBpbnN0YW5jZV9sb2NrcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgICAgIGluc3RhbmNlX211dGV4ZXMuc2V0KGluc3RhbmNlLCBpbnN0YW5jZV9sb2Nrcyk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbG9ja19zdGF0ZSA9IGluc3RhbmNlX2xvY2tzLmdldChtZXRob2RfbmFtZSk7XG4gICAgICAgIGlmICghbG9ja19zdGF0ZSkge1xuICAgICAgICAgICAgbG9ja19zdGF0ZSA9IHsgYWN0aXZlOiBmYWxzZSwgcXVldWU6IFtdIH07XG4gICAgICAgICAgICBpbnN0YW5jZV9sb2Nrcy5zZXQobWV0aG9kX25hbWUsIGxvY2tfc3RhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGxvY2tfc3RhdGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IG9yIGNyZWF0ZSBhIGdsb2JhbCBtdXRleCBieSBJRFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldF9nbG9iYWxfbXV0ZXgoaWQpIHtcbiAgICAgICAgbGV0IGxvY2tfc3RhdGUgPSBnbG9iYWxfbXV0ZXhlcy5nZXQoaWQpO1xuICAgICAgICBpZiAoIWxvY2tfc3RhdGUpIHtcbiAgICAgICAgICAgIGxvY2tfc3RhdGUgPSB7IGFjdGl2ZTogZmFsc2UsIHF1ZXVlOiBbXSB9O1xuICAgICAgICAgICAgZ2xvYmFsX211dGV4ZXMuc2V0KGlkLCBsb2NrX3N0YXRlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbG9ja19zdGF0ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlIHRoZSBuZXh0IHF1ZXVlZCBvcGVyYXRpb24gZm9yIGEgbXV0ZXhcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzY2hlZHVsZV9uZXh0KGxvY2tfc3RhdGUpIHtcbiAgICAgICAgaWYgKGxvY2tfc3RhdGUuYWN0aXZlIHx8IGxvY2tfc3RhdGUucXVldWUubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IGZuLCByZXNvbHZlLCByZWplY3QgfSA9IGxvY2tfc3RhdGUucXVldWUuc2hpZnQoKTtcbiAgICAgICAgbG9ja19zdGF0ZS5hY3RpdmUgPSB0cnVlO1xuXG4gICAgICAgIFByb21pc2UucmVzb2x2ZSgpXG4gICAgICAgICAgICAudGhlbihmbilcbiAgICAgICAgICAgIC50aGVuKHJlc29sdmUsIHJlamVjdClcbiAgICAgICAgICAgIC5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgICAgICBsb2NrX3N0YXRlLmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHNjaGVkdWxlX25leHQobG9ja19zdGF0ZSk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBY3F1aXJlIGEgbXV0ZXggbG9jayBhbmQgZXhlY3V0ZSBjYWxsYmFja1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFjcXVpcmVfbG9jayhsb2NrX3N0YXRlLCBmbikge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgbG9ja19zdGF0ZS5xdWV1ZS5wdXNoKHsgZm4sIHJlc29sdmUsIHJlamVjdCB9KTtcbiAgICAgICAgICAgIHNjaGVkdWxlX25leHQobG9ja19zdGF0ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIElmIGNhbGxlZCB3aXRoIGFuIElEIGFyZ3VtZW50OiBAbXV0ZXgoJ2lkJylcbiAgICBpZiAodHlwZW9mIGdsb2JhbF9pZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHRhcmdldCwga2V5LCBkZXNjcmlwdG9yKSB7XG4gICAgICAgICAgICBjb25zdCBvcmlnaW5hbF9tZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9yaWdpbmFsX21ldGhvZCAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQG11dGV4IGNhbiBvbmx5IGJlIGFwcGxpZWQgdG8gbWV0aG9kcyAodHJpZWQgdG8gYXBwbHkgdG8gJHtrZXl9KWApO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkZXNjcmlwdG9yLnZhbHVlID0gZnVuY3Rpb24oLi4uYXJncykge1xuICAgICAgICAgICAgICAgIGNvbnN0IGxvY2tfc3RhdGUgPSBnZXRfZ2xvYmFsX211dGV4KGdsb2JhbF9pZCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjcXVpcmVfbG9jayhsb2NrX3N0YXRlLCAoKSA9PiBvcmlnaW5hbF9tZXRob2QuYXBwbHkodGhpcywgYXJncykpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0dXJuIGRlc2NyaXB0b3I7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gSWYgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzOiBAbXV0ZXggKHRhcmdldCBpcyB0aGUgZmlyc3QgYXJndW1lbnQpXG4gICAgY29uc3QgdGFyZ2V0ID0gZ2xvYmFsX2lkOyAgLy8gSW4gdGhpcyBjYXNlLCBmaXJzdCBhcmcgaXMgdGFyZ2V0XG4gICAgY29uc3Qga2V5ID0gYXJndW1lbnRzWzFdO1xuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBhcmd1bWVudHNbMl07XG5cbiAgICBjb25zdCBvcmlnaW5hbF9tZXRob2QgPSBkZXNjcmlwdG9yLnZhbHVlO1xuXG4gICAgaWYgKHR5cGVvZiBvcmlnaW5hbF9tZXRob2QgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBAbXV0ZXggY2FuIG9ubHkgYmUgYXBwbGllZCB0byBtZXRob2RzICh0cmllZCB0byBhcHBseSB0byAke2tleX0pYCk7XG4gICAgfVxuXG4gICAgZGVzY3JpcHRvci52YWx1ZSA9IGZ1bmN0aW9uKC4uLmFyZ3MpIHtcbiAgICAgICAgY29uc3QgbG9ja19zdGF0ZSA9IGdldF9pbnN0YW5jZV9tdXRleCh0aGlzLCBrZXkpO1xuICAgICAgICByZXR1cm4gYWNxdWlyZV9sb2NrKGxvY2tfc3RhdGUsICgpID0+IG9yaWdpbmFsX21ldGhvZC5hcHBseSh0aGlzLCBhcmdzKSk7XG4gICAgfTtcblxuICAgIHJldHVybiBkZXNjcmlwdG9yO1xufVxuIiwiLypcbiAqIEFzeW5jIHV0aWxpdHkgZnVuY3Rpb25zIGZvciB0aGUgUlNwYWRlIGZyYW1ld29yay5cbiAqIFRoZXNlIGZ1bmN0aW9ucyBoYW5kbGUgYXN5bmNocm9ub3VzIG9wZXJhdGlvbnMsIGRlbGF5cywgZGVib3VuY2luZywgYW5kIG11dGV4ZXMuXG4gKi9cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQVNZTkMgVVRJTElUSUVTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogUGF1c2VzIGV4ZWN1dGlvbiBmb3Igc3BlY2lmaWVkIG1pbGxpc2Vjb25kc1xuICogQHBhcmFtIHtudW1iZXJ9IFttaWxsaXNlY29uZHM9MF0gLSBEZWxheSBpbiBtaWxsaXNlY29uZHMgKDAgdXNlcyByZXF1ZXN0QW5pbWF0aW9uRnJhbWUpXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gUHJvbWlzZSB0aGF0IHJlc29sdmVzIGFmdGVyIGRlbGF5XG4gKiBAZXhhbXBsZSBhd2FpdCBzbGVlcCgxMDAwKTsgLy8gV2FpdCAxIHNlY29uZFxuICovXG5mdW5jdGlvbiBzbGVlcChtaWxsaXNlY29uZHMgPSAwKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgIGlmIChtaWxsaXNlY29uZHMgPT0gMCAmJiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHtcbiAgICAgICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShyZXNvbHZlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQocmVzb2x2ZSwgbWlsbGlzZWNvbmRzKTtcbiAgICAgICAgfVxuICAgIH0pO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBkZWJvdW5jZWQgZnVuY3Rpb24gd2l0aCBleGNsdXNpdml0eSBhbmQgcHJvbWlzZSBmYW4taW5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uLCB3aGVuIGludm9rZWQsIGltbWVkaWF0ZWx5IHJ1bnMgdGhlIGNhbGxiYWNrIGV4Y2x1c2l2ZWx5LlxuICogRm9yIHN1YnNlcXVlbnQgaW52b2NhdGlvbnMsIGl0IGFwcGxpZXMgYSBkZWxheSBiZWZvcmUgcnVubmluZyB0aGUgY2FsbGJhY2sgZXhjbHVzaXZlbHkgYWdhaW4uXG4gKiBUaGUgZGVsYXkgc3RhcnRzIGFmdGVyIHRoZSBjdXJyZW50IGFzeW5jaHJvbm91cyBvcGVyYXRpb24gcmVzb2x2ZXMuXG4gKlxuICogSWYgJ2RlbGF5JyBpcyBzZXQgdG8gMCwgdGhlIGZ1bmN0aW9uIHdpbGwgb25seSBwcmV2ZW50IGVucXVldWVpbmcgbXVsdGlwbGUgZXhlY3V0aW9ucyBvZiB0aGVcbiAqIHNhbWUgbWV0aG9kIG1vcmUgdGhhbiBvbmNlLCBidXQgd2lsbCBzdGlsbCBydW4gdGhlbSBpbW1lZGlhdGVseSBpbiBhbiBleGNsdXNpdmUgc2VxdWVudGlhbCBtYW5uZXIuXG4gKlxuICogVGhlIG1vc3QgcmVjZW50IGludm9jYXRpb24gb2YgdGhlIGZ1bmN0aW9uIHdpbGwgYmUgdGhlIHBhcmFtZXRlcnMgdGhhdCBnZXQgcGFzc2VkIHRvIHRoZSBmdW5jdGlvblxuICogd2hlbiBpdCBpbnZva2VzLlxuICpcbiAqIFRoZSBmdW5jdGlvbiByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIG5leHQgZXhjbHVzaXZlIGV4ZWN1dGlvbiBjb21wbGV0ZXMuXG4gKlxuICogVXNhZ2UgYXMgZnVuY3Rpb246XG4gKiAgIGNvbnN0IGRlYm91bmNlZEZuID0gZGVib3VuY2UobXlGdW5jdGlvbiwgMjUwKTtcbiAqXG4gKiBVc2FnZSBhcyBkZWNvcmF0b3I6XG4gKiAgIEBkZWJvdW5jZSgyNTApXG4gKiAgIG15TWV0aG9kKCkgeyAuLi4gfVxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb258bnVtYmVyfSBjYWxsYmFja19vcl9kZWxheSBUaGUgY2FsbGJhY2sgZnVuY3Rpb24gT1IgZGVsYXkgd2hlbiB1c2VkIGFzIGRlY29yYXRvclxuICogQHBhcmFtIHtudW1iZXJ9IGRlbGF5IFRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHMgYmVmb3JlIHN1YnNlcXVlbnQgaW52b2NhdGlvbnNcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gaW1tZWRpYXRlIGlmIHRydWUsIHRoZSBmaXJzdCB0aW1lIHRoZSBhY3Rpb24gaXMgY2FsbGVkLCB0aGUgY2FsbGJhY2sgZXhlY3V0ZXMgaW1tZWRpYXRlbHlcbiAqIEByZXR1cm5zIHtmdW5jdGlvbn0gQSBmdW5jdGlvbiB0aGF0IHdoZW4gaW52b2tlZCwgcnVucyB0aGUgY2FsbGJhY2sgaW1tZWRpYXRlbHkgYW5kIGV4Y2x1c2l2ZWx5LFxuICpcbiAqIEBkZWNvcmF0b3JcbiAqL1xuZnVuY3Rpb24gZGVib3VuY2UoY2FsbGJhY2tfb3JfZGVsYXksIGRlbGF5LCBpbW1lZGlhdGUgPSBmYWxzZSkge1xuICAgIC8vIERlY29yYXRvciB1c2FnZTogQGRlYm91bmNlKDI1MCkgb3IgQGRlYm91bmNlKDI1MCwgdHJ1ZSlcbiAgICAvLyBGaXJzdCBhcmd1bWVudCBpcyBhIG51bWJlciAodGhlIGRlbGF5KSwgcmV0dXJucyBkZWNvcmF0b3IgZnVuY3Rpb25cbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrX29yX2RlbGF5ID09PSAnbnVtYmVyJykge1xuICAgICAgICBjb25zdCBkZWNvcmF0b3JfZGVsYXkgPSBjYWxsYmFja19vcl9kZWxheTtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9yX2ltbWVkaWF0ZSA9IGRlbGF5IHx8IGZhbHNlO1xuXG4gICAgICAgIC8vIFRDMzkgZGVjb3JhdG9yIGZvcm06IHJlY2VpdmVzICh2YWx1ZSwgY29udGV4dClcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgY29udGV4dCkge1xuICAgICAgICAgICAgaWYgKGNvbnRleHQua2luZCA9PT0gJ21ldGhvZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVib3VuY2VfaW1wbCh2YWx1ZSwgZGVjb3JhdG9yX2RlbGF5LCBkZWNvcmF0b3JfaW1tZWRpYXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGdW5jdGlvbiB1c2FnZTogZGVib3VuY2UoZm4sIDI1MClcbiAgICAvLyBGaXJzdCBhcmd1bWVudCBpcyBhIGZ1bmN0aW9uICh0aGUgY2FsbGJhY2spXG4gICAgY29uc3QgY2FsbGJhY2sgPSBjYWxsYmFja19vcl9kZWxheTtcbiAgICByZXR1cm4gZGVib3VuY2VfaW1wbChjYWxsYmFjaywgZGVsYXksIGltbWVkaWF0ZSk7XG59XG5cbi8qKlxuICogSW50ZXJuYWwgaW1wbGVtZW50YXRpb24gb2YgZGVib3VuY2UgbG9naWNcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGRlYm91bmNlX2ltcGwoY2FsbGJhY2ssIGRlbGF5LCBpbW1lZGlhdGUgPSBmYWxzZSkge1xuICAgIGxldCBydW5uaW5nID0gZmFsc2U7XG4gICAgbGV0IHF1ZXVlZCA9IGZhbHNlO1xuICAgIGxldCBsYXN0X2VuZF90aW1lID0gMDsgLy8gdGltZXN0YW1wIG9mIGxhc3QgY29tcGxldGVkIHJ1blxuICAgIGxldCB0aW1lciA9IG51bGw7XG5cbiAgICBsZXQgbmV4dF9hcmdzID0gW107XG4gICAgbGV0IG5leHRfY29udGV4dCA9IG51bGw7XG4gICAgbGV0IHJlc29sdmVfcXVldWUgPSBbXTtcbiAgICBsZXQgcmVqZWN0X3F1ZXVlID0gW107XG5cbiAgICBjb25zdCBydW5fZnVuY3Rpb24gPSBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHRoZXNlX3Jlc29sdmVzID0gcmVzb2x2ZV9xdWV1ZTtcbiAgICAgICAgY29uc3QgdGhlc2VfcmVqZWN0cyA9IHJlamVjdF9xdWV1ZTtcbiAgICAgICAgY29uc3QgYXJncyA9IG5leHRfYXJncztcbiAgICAgICAgY29uc3QgY29udGV4dCA9IG5leHRfY29udGV4dDtcblxuICAgICAgICByZXNvbHZlX3F1ZXVlID0gW107XG4gICAgICAgIHJlamVjdF9xdWV1ZSA9IFtdO1xuICAgICAgICBuZXh0X2FyZ3MgPSBbXTtcbiAgICAgICAgbmV4dF9jb250ZXh0ID0gbnVsbDtcbiAgICAgICAgcXVldWVkID0gZmFsc2U7XG4gICAgICAgIHJ1bm5pbmcgPSB0cnVlO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjYWxsYmFjay5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVzb2x2ZSBvZiB0aGVzZV9yZXNvbHZlcykgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcmVqZWN0IG9mIHRoZXNlX3JlamVjdHMpIHJlamVjdChlcnIpO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgcnVubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgbGFzdF9lbmRfdGltZSA9IERhdGUubm93KCk7XG4gICAgICAgICAgICBpZiAocXVldWVkKSB7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgICAgICB0aW1lciA9IHNldFRpbWVvdXQocnVuX2Z1bmN0aW9uLCBNYXRoLm1heChkZWxheSwgMCkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aW1lciA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIG5leHRfYXJncyA9IGFyZ3M7XG4gICAgICAgIG5leHRfY29udGV4dCA9IHRoaXM7XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmVfcXVldWUucHVzaChyZXNvbHZlKTtcbiAgICAgICAgICAgIHJlamVjdF9xdWV1ZS5wdXNoKHJlamVjdCk7XG5cbiAgICAgICAgICAgIC8vIE5vdGhpbmcgcnVubmluZyBhbmQgbm90aGluZyBzY2hlZHVsZWRcbiAgICAgICAgICAgIGlmICghcnVubmluZyAmJiAhdGltZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaXJzdF9jYWxsID0gbGFzdF9lbmRfdGltZSA9PT0gMDtcblxuICAgICAgICAgICAgICAgIGlmIChpbW1lZGlhdGUgJiYgZmlyc3RfY2FsbCkge1xuICAgICAgICAgICAgICAgICAgICBydW5fZnVuY3Rpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHNpbmNlID0gZmlyc3RfY2FsbCA/IEluZmluaXR5IDogRGF0ZS5ub3coKSAtIGxhc3RfZW5kX3RpbWU7XG4gICAgICAgICAgICAgICAgaWYgKHNpbmNlID49IGRlbGF5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bl9mdW5jdGlvbigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHdhaXQgPSBNYXRoLm1heChkZWxheSAtIHNpbmNlLCAwKTtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KHJ1bl9mdW5jdGlvbiwgd2FpdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgd2UncmUgYWxyZWFkeSBydW5uaW5nIG9yIGEgdGltZXIgZXhpc3RzLCBqdXN0IG1hcmsgcXVldWVkLlxuICAgICAgICAgICAgLy8gVGhlIGZpbmFsbHl7fSBvZiBydW5fZnVuY3Rpb24gaGFuZGxlcyBzY2hlZHVsaW5nIGFmdGVyIGZ1bGwgZGVsYXkuXG4gICAgICAgICAgICBxdWV1ZWQgPSB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBSRUFELVdSSVRFIExPQ0sgRlVOQ1RJT05TIC0gRGVsZWdhdGVkIHRvIFJlYWRXcml0ZUxvY2sgY2xhc3Ncbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBBY3F1aXJlIGFuIGV4Y2x1c2l2ZSB3cml0ZSBsb2NrIGJ5IG5hbWUuXG4gKiBPbmx5IG9uZSB3cml0ZXIgcnVucyBhdCBhIHRpbWU7IGJsb2NrcyByZWFkZXJzIHVudGlsIGZpbmlzaGVkLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fFByb21pc2U8YW55Pn0gY2JcbiAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gKi9cbmZ1bmN0aW9uIHJ3bG9jayhuYW1lLCBjYikge1xuICAgIHJldHVybiBSZWFkV3JpdGVMb2NrLmFjcXVpcmUobmFtZSwgY2IpO1xufVxuXG4vKipcbiAqIEFjcXVpcmUgYSBzaGFyZWQgcmVhZCBsb2NrIGJ5IG5hbWUuXG4gKiBNdWx0aXBsZSByZWFkZXJzIHJ1biBpbiBwYXJhbGxlbCwgYnV0IHJlYWRlcnMgYXJlIGJsb2NrZWQgYnkgcXVldWVkL2FjdGl2ZSB3cml0ZXJzLlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7KCkgPT4gYW55fFByb21pc2U8YW55Pn0gY2JcbiAqIEByZXR1cm5zIHtQcm9taXNlPGFueT59XG4gKi9cbmZ1bmN0aW9uIHJ3bG9ja19yZWFkKG5hbWUsIGNiKSB7XG4gICAgcmV0dXJuIFJlYWRXcml0ZUxvY2suYWNxdWlyZV9yZWFkKG5hbWUsIGNiKTtcbn1cblxuLyoqXG4gKiBGb3JjZWZ1bGx5IGNsZWFyIGFsbCBsb2NrcyBhbmQgcXVldWVzIGZvciBhIGdpdmVuIG5hbWUuXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICovXG5mdW5jdGlvbiByd2xvY2tfZm9yY2VfdW5sb2NrKG5hbWUpIHtcbiAgICBSZWFkV3JpdGVMb2NrLmZvcmNlX3VubG9jayhuYW1lKTtcbn1cblxuLyoqXG4gKiBJbnNwZWN0IGxvY2sgc3RhdGUgZm9yIGRlYnVnZ2luZy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lXG4gKiBAcmV0dXJucyB7e3JlYWRlcnM6bnVtYmVyLCB3cml0ZXJfYWN0aXZlOmJvb2xlYW4sIHJlYWRlcl9xOm51bWJlciwgd3JpdGVyX3E6bnVtYmVyfX1cbiAqL1xuZnVuY3Rpb24gcndsb2NrX3BlbmRpbmcobmFtZSkge1xuICAgIHJldHVybiBSZWFkV3JpdGVMb2NrLnBlbmRpbmcobmFtZSk7XG59XG4iLCIvKlxuICogQ29yZSB1dGlsaXR5IGZ1bmN0aW9ucyBmb3IgdGhlIFJTcGFkZSBmcmFtZXdvcmsuXG4gKiBUaGVzZSBmdW5jdGlvbnMgaGFuZGxlIHR5cGUgY2hlY2tpbmcsIHR5cGUgY29udmVyc2lvbiwgc3RyaW5nIG1hbmlwdWxhdGlvbixcbiAqIGFuZCBvYmplY3QvYXJyYXkgdXRpbGl0aWVzLiBUaGV5IG1pcnJvciBmdW5jdGlvbmFsaXR5IGZyb20gUEhQIGZ1bmN0aW9ucy5cbiAqXG4gKiBPdGhlciB1dGlsaXR5IGZ1bmN0aW9ucyBhcmUgb3JnYW5pemVkIGluOlxuICogLSBhc3luYy5qczogQXN5bmMgdXRpbGl0aWVzIChzbGVlcCwgZGVib3VuY2UsIG11dGV4KVxuICogLSBicm93c2VyLmpzOiBCcm93c2VyL0RPTSB1dGlsaXRpZXMgKGlzX21vYmlsZSwgc2Nyb2xsIGZ1bmN0aW9ucylcbiAqIC0gZGF0ZXRpbWUuanM6IERhdGUvdGltZSB1dGlsaXRpZXNcbiAqIC0gaGFzaC5qczogSGFzaGluZyBhbmQgY29tcGFyaXNvblxuICogLSBlcnJvci5qczogRXJyb3IgaGFuZGxpbmdcbiAqL1xuXG4vLyBUb2RvOiB0ZXN0IHRoYXQgcHJvZCBidWlsZCBpZGVudGlmaWVzIGFuZCByZW1vdmVzIHVuY2FsbGVkIGZ1bmN0aW9ucyBmcm9tIHRoZSBmaW5hbCBidW5kbGUuXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIENPTlNUQU5UUyBBTkQgSEVMUEVSU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4vLyBEZWZpbmUgY29tbW9ubHkgdXNlZCBjb25zdGFudHNcbmNvbnN0IHVuZGVmID0gJ3VuZGVmaW5lZCc7XG5cbi8qKlxuICogSXRlcmF0ZXMgb3ZlciBhcnJheXMgb3Igb2JqZWN0cyB3aXRoIHByb21pc2Ugc3VwcG9ydFxuICpcbiAqIFdvcmtzIHdpdGggYm90aCBzeW5jaHJvbm91cyBhbmQgYXN5bmNocm9ub3VzIGNhbGxiYWNrcy4gSWYgdGhlIGNhbGxiYWNrXG4gKiByZXR1cm5zIHByb21pc2VzLCB0aGV5IGFyZSBleGVjdXRlZCBpbiBwYXJhbGxlbCBhbmQgdGhpcyBmdW5jdGlvbiByZXR1cm5zXG4gKiBhIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIGFsbCBwYXJhbGxlbCB0YXNrcyBjb21wbGV0ZS5cbiAqXG4gKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gb2JqIC0gQ29sbGVjdGlvbiB0byBpdGVyYXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayAtIEZ1bmN0aW9uIHRvIGNhbGwgZm9yIGVhY2ggaXRlbSAodmFsdWUsIGtleSkgLSBjYW4gYmUgYXN5bmNcbiAqIEByZXR1cm5zIHtQcm9taXNlfHVuZGVmaW5lZH0gUHJvbWlzZSBpZiBhbnkgY2FsbGJhY2tzIHJldHVybiBwcm9taXNlcywgdW5kZWZpbmVkIG90aGVyd2lzZVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBTeW5jaHJvbm91cyB1c2FnZVxuICogZm9yZWFjaChbMSwyLDNdLCAodmFsKSA9PiBjb25zb2xlLmxvZyh2YWwpKTtcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gQXN5bmNocm9ub3VzIHVzYWdlIC0gd2FpdHMgZm9yIGFsbCB0byBjb21wbGV0ZVxuICogYXdhaXQgZm9yZWFjaChbMSwyLDNdLCBhc3luYyAodmFsKSA9PiB7XG4gKiAgICAgYXdhaXQgZmV0Y2goJy9hcGkvcHJvY2Vzcy8nICsgdmFsKTtcbiAqIH0pO1xuICovXG5mdW5jdGlvbiBmb3JlYWNoKG9iaiwgY2FsbGJhY2spIHtcbiAgICBjb25zdCByZXN1bHRzID0gW107XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7XG4gICAgICAgIG9iai5mb3JFYWNoKCh2YWx1ZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaChjYWxsYmFjayh2YWx1ZSwgaW5kZXgpKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChvYmogJiYgdHlwZW9mIG9iaiA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgZm9yIChsZXQga2V5IGluIG9iaikge1xuICAgICAgICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGNhbGxiYWNrKG9ialtrZXldLCBrZXkpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZpbHRlciBmb3IgcHJvbWlzZXNcbiAgICBjb25zdCBwcm9taXNlcyA9IHJlc3VsdHMuZmlsdGVyKChyZXN1bHQpID0+IHJlc3VsdCAmJiB0eXBlb2YgcmVzdWx0LnRoZW4gPT09ICdmdW5jdGlvbicpO1xuXG4gICAgLy8gSWYgdGhlcmUgYXJlIGFueSBwcm9taXNlcywgcmV0dXJuIFByb21pc2UuYWxsIHRvIHdhaXQgZm9yIGFsbCB0byBjb21wbGV0ZVxuICAgIGlmIChwcm9taXNlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gICAgfVxuXG4gICAgLy8gTm8gcHJvbWlzZXMgcmV0dXJuZWQsIHNvIHdlJ3JlIGRvbmVcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFRZUEUgQ0hFQ0tJTkcgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgbnVtZXJpY1xuICogQHBhcmFtIHsqfSBuIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIGZpbml0ZSBudW1iZXJcbiAqL1xuZnVuY3Rpb24gaXNfbnVtZXJpYyhuKSB7XG4gICAgcmV0dXJuICFpc05hTihwYXJzZUZsb2F0KG4pKSAmJiBpc0Zpbml0ZShuKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhIHN0cmluZ1xuICogQHBhcmFtIHsqfSBzIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIHN0cmluZ1xuICovXG5mdW5jdGlvbiBpc19zdHJpbmcocykge1xuICAgIHJldHVybiB0eXBlb2YgcyA9PSAnc3RyaW5nJztcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhbiBpbnRlZ2VyXG4gKiBAcGFyYW0geyp9IG4gLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGFuIGludGVnZXJcbiAqL1xuZnVuY3Rpb24gaXNfaW50ZWdlcihuKSB7XG4gICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIobik7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYSBwcm9taXNlLWxpa2Ugb2JqZWN0XG4gKiBAcGFyYW0geyp9IG9iaiAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaGFzIGEgdGhlbiBtZXRob2RcbiAqL1xuZnVuY3Rpb24gaXNfcHJvbWlzZShvYmopIHtcbiAgICByZXR1cm4gdHlwZW9mIG9iaiA9PSAnb2JqZWN0JyAmJiB0eXBlb2Ygb2JqLnRoZW4gPT0gJ2Z1bmN0aW9uJztcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSB2YWx1ZSBpcyBhbiBhcnJheVxuICogQHBhcmFtIHsqfSBvYmogLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGFuIGFycmF5XG4gKi9cbmZ1bmN0aW9uIGlzX2FycmF5KG9iaikge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KG9iaik7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYW4gb2JqZWN0IChleGNsdWRlcyBudWxsKVxuICogQHBhcmFtIHsqfSBvYmogLSBWYWx1ZSB0byBjaGVja1xuICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgdGhlIHZhbHVlIGlzIGFuIG9iamVjdCBhbmQgbm90IG51bGxcbiAqL1xuZnVuY3Rpb24gaXNfb2JqZWN0KG9iaikge1xuICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSAnb2JqZWN0JyAmJiBvYmogIT09IG51bGw7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgdmFsdWUgaXMgYSBmdW5jdGlvblxuICogQHBhcmFtIHsqfSBmdW5jdGlvbl90b19jaGVjayAtIFZhbHVlIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgdmFsdWUgaXMgYSBmdW5jdGlvblxuICovXG5mdW5jdGlvbiBpc19mdW5jdGlvbihmdW5jdGlvbl90b19jaGVjaykge1xuICAgIHJldHVybiBmdW5jdGlvbl90b19jaGVjayAmJiB7fS50b1N0cmluZy5jYWxsKGZ1bmN0aW9uX3RvX2NoZWNrKSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYSBzdHJpbmcgaXMgYSB2YWxpZCBlbWFpbCBhZGRyZXNzXG4gKiBVc2VzIGEgcHJhY3RpY2FsIFJGQyA1MzIyIGNvbXBsaWFudCByZWdleCB0aGF0IG1hdGNoZXMgOTkuOTklIG9mIHJlYWwtd29ybGQgZW1haWwgYWRkcmVzc2VzXG4gKiBAcGFyYW0ge3N0cmluZ30gZW1haWwgLSBFbWFpbCBhZGRyZXNzIHRvIHZhbGlkYXRlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiB0aGUgc3RyaW5nIGlzIGEgdmFsaWQgZW1haWwgYWRkcmVzc1xuICovXG5mdW5jdGlvbiBpc19lbWFpbChlbWFpbCkge1xuICAgIGlmICghaXNfc3RyaW5nKGVtYWlsKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IHJlZ2V4ID0gL15bYS16MC05ISMkJSYnKisvPT9eX2B7fH1+LV0rKD86XFwuW2EtejAtOSEjJCUmJyorLz0/Xl9ge3x9fi1dKykqQCg/OlthLXowLTldKD86W2EtejAtOS1dKlthLXowLTldKT9cXC4pK1thLXowLTldKD86W2EtejAtOS1dKlthLXowLTldKT8kL2k7XG4gICAgcmV0dXJuIHJlZ2V4LnRlc3QoZW1haWwpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGRlZmluZWQgKG5vdCB1bmRlZmluZWQpXG4gKiBAcGFyYW0geyp9IHZhbHVlIC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHZhbHVlIGlzIG5vdCB1bmRlZmluZWRcbiAqL1xuZnVuY3Rpb24gaXNzZXQodmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlICE9IHVuZGVmO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIGVtcHR5IChudWxsLCB1bmRlZmluZWQsIDAsIFwiXCIsIGVtcHR5IGFycmF5L29iamVjdClcbiAqIEBwYXJhbSB7Kn0gb2JqZWN0IC0gVmFsdWUgdG8gY2hlY2tcbiAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBjb25zaWRlcmVkIGVtcHR5XG4gKi9cbmZ1bmN0aW9uIGVtcHR5KG9iamVjdCkge1xuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09IHVuZGVmKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAob2JqZWN0ID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9iamVjdCA9PSAnc3RyaW5nJyAmJiBvYmplY3QgPT0gJycpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09ICdudW1iZXInKSB7XG4gICAgICAgIHJldHVybiBvYmplY3QgPT0gMDtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0KSkge1xuICAgICAgICByZXR1cm4gIW9iamVjdC5sZW5ndGg7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgIGlmIChvYmplY3QuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBUWVBFIENPTlZFUlNJT04gRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbi8qKlxuICogQ29udmVydHMgYSB2YWx1ZSB0byBhIGZsb2F0aW5nIHBvaW50IG51bWJlclxuICogUmV0dXJucyAwIGZvciBudWxsLCB1bmRlZmluZWQsIE5hTiwgb3Igbm9uLW51bWVyaWMgdmFsdWVzXG4gKiBAcGFyYW0geyp9IHZhbCAtIFZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IEZsb2F0aW5nIHBvaW50IG51bWJlclxuICovXG5mdW5jdGlvbiBmbG9hdCh2YWwpIHtcbiAgICAvLyBIYW5kbGUgbnVsbCwgdW5kZWZpbmVkLCBlbXB0eSBzdHJpbmdcbiAgICBpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gdW5kZWZpbmVkIHx8IHZhbCA9PT0gJycpIHtcbiAgICAgICAgcmV0dXJuIDAuMDtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gcGFyc2UgdGhlIHZhbHVlXG4gICAgY29uc3QgcGFyc2VkID0gcGFyc2VGbG9hdCh2YWwpO1xuXG4gICAgLy8gQ2hlY2sgZm9yIE5hTiBhbmQgcmV0dXJuIDAgaWYgcGFyc2luZyBmYWlsZWRcbiAgICByZXR1cm4gaXNOYU4ocGFyc2VkKSA/IDAuMCA6IHBhcnNlZDtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhIHZhbHVlIHRvIGFuIGludGVnZXJcbiAqIFJldHVybnMgMCBmb3IgbnVsbCwgdW5kZWZpbmVkLCBOYU4sIG9yIG5vbi1udW1lcmljIHZhbHVlc1xuICogQHBhcmFtIHsqfSB2YWwgLSBWYWx1ZSB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7bnVtYmVyfSBJbnRlZ2VyIHZhbHVlXG4gKi9cbmZ1bmN0aW9uIGludCh2YWwpIHtcbiAgICAvLyBIYW5kbGUgbnVsbCwgdW5kZWZpbmVkLCBlbXB0eSBzdHJpbmdcbiAgICBpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gdW5kZWZpbmVkIHx8IHZhbCA9PT0gJycpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIHBhcnNlIHRoZSB2YWx1ZVxuICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KHZhbCwgMTApO1xuXG4gICAgLy8gQ2hlY2sgZm9yIE5hTiBhbmQgcmV0dXJuIDAgaWYgcGFyc2luZyBmYWlsZWRcbiAgICByZXR1cm4gaXNOYU4ocGFyc2VkKSA/IDAgOiBwYXJzZWQ7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSB2YWx1ZSB0byBhIHN0cmluZ1xuICogUmV0dXJucyBlbXB0eSBzdHJpbmcgZm9yIG51bGwgb3IgdW5kZWZpbmVkXG4gKiBAcGFyYW0geyp9IHZhbCAtIFZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFN0cmluZyByZXByZXNlbnRhdGlvblxuICovXG5mdW5jdGlvbiBzdHIodmFsKSB7XG4gICAgLy8gSGFuZGxlIG51bGwgYW5kIHVuZGVmaW5lZCBzcGVjaWFsbHlcbiAgICBpZiAodmFsID09PSBudWxsIHx8IHZhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICAvLyBDb252ZXJ0IHRvIHN0cmluZ1xuICAgIHJldHVybiBTdHJpbmcodmFsKTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBudW1lcmljIHN0cmluZ3MgdG8gbnVtYmVycywgcmV0dXJucyBhbGwgb3RoZXIgdmFsdWVzIHVuY2hhbmdlZFxuICogVXNlZCB3aGVuIHlvdSBuZWVkIHRvIGVuc3VyZSBudW1lcmljIHR5cGVzIGJ1dCBkb24ndCB3YW50IHRvIGZvcmNlXG4gKiBjb252ZXJzaW9uIG9mIG5vbi1udW1lcmljIHZhbHVlcyAod2hpY2ggd291bGQgYmVjb21lIDApXG4gKiBAcGFyYW0geyp9IHZhbCAtIFZhbHVlIHRvIGNvbnZlcnRcbiAqIEByZXR1cm5zIHsqfSBOdW1iZXIgaWYgaW5wdXQgd2FzIG51bWVyaWMgc3RyaW5nLCBvdGhlcndpc2UgdW5jaGFuZ2VkXG4gKi9cbmZ1bmN0aW9uIHZhbHVlX3VubGVzc19udW1lcmljX3N0cmluZ190aGVuX251bWVyaWNfdmFsdWUodmFsKSB7XG4gICAgLy8gSWYgaXQncyBhbHJlYWR5IGEgbnVtYmVyLCByZXR1cm4gaXRcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIHZhbDtcbiAgICB9XG5cbiAgICAvLyBJZiBpdCdzIGEgc3RyaW5nIGFuZCBudW1lcmljLCBjb252ZXJ0IGl0XG4gICAgaWYgKGlzX3N0cmluZyh2YWwpICYmIGlzX251bWVyaWModmFsKSkge1xuICAgICAgICAvLyBVc2UgcGFyc2VGbG9hdCB0byBoYW5kbGUgYm90aCBpbnRlZ2VycyBhbmQgZmxvYXRzXG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbCk7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIGV2ZXJ5dGhpbmcgZWxzZSB1bmNoYW5nZWQgKG51bGwsIG9iamVjdHMsIG5vbi1udW1lcmljIHN0cmluZ3MsIGV0Yy4pXG4gICAgcmV0dXJuIHZhbDtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gU1RSSU5HIE1BTklQVUxBVElPTiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBFc2NhcGVzIEhUTUwgc3BlY2lhbCBjaGFyYWN0ZXJzICh1c2VzIExvZGFzaCBlc2NhcGUpXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gU3RyaW5nIHRvIGVzY2FwZVxuICogQHJldHVybnMge3N0cmluZ30gSFRNTC1lc2NhcGVkIHN0cmluZ1xuICovXG5mdW5jdGlvbiBodG1sKHN0cikge1xuICAgIHJldHVybiBfLmVzY2FwZShzdHIpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIG5ld2xpbmVzIHRvIEhUTUwgbGluZSBicmVha3NcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gY29udmVydFxuICogQHJldHVybnMge3N0cmluZ30gU3RyaW5nIHdpdGggbmV3bGluZXMgcmVwbGFjZWQgYnkgPGJyIC8+XG4gKi9cbmZ1bmN0aW9uIG5sMmJyKHN0cikge1xuICAgIGlmICh0eXBlb2Ygc3RyID09PSB1bmRlZiB8fCBzdHIgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICByZXR1cm4gKHN0ciArICcnKS5yZXBsYWNlKC8oW14+XFxyXFxuXT8pKFxcclxcbnxcXG5cXHJ8XFxyfFxcbikvZywgJyQxPGJyIC8+JDInKTtcbn1cblxuLyoqXG4gKiBFc2NhcGVzIEhUTUwgYW5kIGNvbnZlcnRzIG5ld2xpbmVzIHRvIDxiciAvPlxuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIFN0cmluZyB0byBwcm9jZXNzXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBIVE1MLWVzY2FwZWQgc3RyaW5nIHdpdGggbGluZSBicmVha3NcbiAqL1xuZnVuY3Rpb24gaHRtbGJyKHN0cikge1xuICAgIHJldHVybiBubDJicihodG1sKHN0cikpO1xufVxuXG4vKipcbiAqIFVSTC1lbmNvZGVzIGEgc3RyaW5nXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIC0gU3RyaW5nIHRvIGVuY29kZVxuICogQHJldHVybnMge3N0cmluZ30gVVJMLWVuY29kZWQgc3RyaW5nXG4gKi9cbmZ1bmN0aW9uIHVybGVuY29kZShzdHIpIHtcbiAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHN0cik7XG59XG5cbi8qKlxuICogVVJMLWRlY29kZXMgYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgLSBTdHJpbmcgdG8gZGVjb2RlXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBVUkwtZGVjb2RlZCBzdHJpbmdcbiAqL1xuZnVuY3Rpb24gdXJsZGVjb2RlKHN0cikge1xuICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoc3RyKTtcbn1cblxuLyoqXG4gKiBKU09OLWVuY29kZXMgYSB2YWx1ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSAtIFZhbHVlIHRvIGVuY29kZVxuICogQHJldHVybnMge3N0cmluZ30gSlNPTiBzdHJpbmdcbiAqL1xuZnVuY3Rpb24ganNvbl9lbmNvZGUodmFsdWUpIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xufVxuXG4vKipcbiAqIEpTT04tZGVjb2RlcyBhIHN0cmluZ1xuICogQHBhcmFtIHtzdHJpbmd9IHN0ciAtIEpTT04gc3RyaW5nIHRvIGRlY29kZVxuICogQHJldHVybnMgeyp9IERlY29kZWQgdmFsdWVcbiAqL1xuZnVuY3Rpb24ganNvbl9kZWNvZGUoc3RyKSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2Uoc3RyKTtcbn1cblxuLyoqXG4gKiBDb25zb2xlIGRlYnVnIG91dHB1dCB3aXRoIGNoYW5uZWwgZmlsdGVyaW5nXG4gKiBBbGlhcyBmb3IgRGVidWdnZXIuY29uc29sZV9kZWJ1Z1xuICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWwgLSBEZWJ1ZyBjaGFubmVsIG5hbWVcbiAqIEBwYXJhbSB7Li4uKn0gdmFsdWVzIC0gVmFsdWVzIHRvIGxvZ1xuICovXG5mdW5jdGlvbiBjb25zb2xlX2RlYnVnKGNoYW5uZWwsIC4uLnZhbHVlcykge1xuICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoY2hhbm5lbCwgLi4udmFsdWVzKTtcbn1cblxuLyoqXG4gKiBSZXBsYWNlcyBhbGwgb2NjdXJyZW5jZXMgb2YgYSBzdWJzdHJpbmcgaW4gYSBzdHJpbmdcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgLSBTdHJpbmcgdG8gc2VhcmNoIGluXG4gKiBAcGFyYW0ge3N0cmluZ30gc2VhcmNoIC0gU3Vic3RyaW5nIHRvIGZpbmRcbiAqIEBwYXJhbSB7c3RyaW5nfSByZXBsYWNlIC0gUmVwbGFjZW1lbnQgc3Vic3RyaW5nXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgd2l0aCBhbGwgb2NjdXJyZW5jZXMgcmVwbGFjZWRcbiAqL1xuZnVuY3Rpb24gcmVwbGFjZV9hbGwoc3RyaW5nLCBzZWFyY2gsIHJlcGxhY2UpIHtcbiAgICBpZiAoIWlzX3N0cmluZyhzdHJpbmcpKSB7XG4gICAgICAgIHN0cmluZyA9IHN0cmluZyArICcnO1xuICAgIH1cbiAgICByZXR1cm4gc3RyaW5nLnNwbGl0KHNlYXJjaCkuam9pbihyZXBsYWNlKTtcbn1cblxuLyoqXG4gKiBDYXBpdGFsaXplcyB0aGUgZmlyc3QgbGV0dGVyIG9mIGVhY2ggd29yZFxuICogQHBhcmFtIHtzdHJpbmd9IGlucHV0IC0gU3RyaW5nIHRvIGNhcGl0YWxpemVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IFN0cmluZyB3aXRoIGZpcnN0IGxldHRlciBvZiBlYWNoIHdvcmQgY2FwaXRhbGl6ZWRcbiAqL1xuZnVuY3Rpb24gdWN3b3JkcyhpbnB1dCkge1xuICAgIHJldHVybiBpbnB1dFxuICAgICAgICAuc3BsaXQoJyAnKVxuICAgICAgICAubWFwKCh3b3JkKSA9PiB3b3JkLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgd29yZC5zbGljZSgxKSlcbiAgICAgICAgLmpvaW4oJyAnKTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gT0JKRUNUIEFORCBBUlJBWSBVVElMSVRJRVNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuLyoqXG4gKiBDb3VudHMgdGhlIG51bWJlciBvZiBwcm9wZXJ0aWVzIGluIGFuIG9iamVjdCBvciBlbGVtZW50cyBpbiBhbiBhcnJheVxuICogQHBhcmFtIHtPYmplY3R8QXJyYXl9IG8gLSBPYmplY3Qgb3IgYXJyYXkgdG8gY291bnRcbiAqIEByZXR1cm5zIHtudW1iZXJ9IE51bWJlciBvZiBvd24gcHJvcGVydGllcy9lbGVtZW50c1xuICovXG5mdW5jdGlvbiBjb3VudChvKSB7XG4gICAgbGV0IGMgPSAwO1xuICAgIGZvciAoY29uc3QgayBpbiBvKSB7XG4gICAgICAgIGlmIChvLmhhc093blByb3BlcnR5KGspKSB7XG4gICAgICAgICAgICArK2M7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGM7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHNoYWxsb3cgY2xvbmUgb2YgYW4gb2JqZWN0LCBhcnJheSwgb3IgZnVuY3Rpb25cbiAqIEBwYXJhbSB7Kn0gb2JqIC0gVmFsdWUgdG8gY2xvbmVcbiAqIEByZXR1cm5zIHsqfSBDbG9uZWQgdmFsdWVcbiAqL1xuZnVuY3Rpb24gY2xvbmUob2JqKSB7XG4gICAgaWYgKHR5cGVvZiBGdW5jdGlvbi5wcm90b3R5cGUuX19jbG9uZSA9PSB1bmRlZikge1xuICAgICAgICBGdW5jdGlvbi5wcm90b3R5cGUuX19jbG9uZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIC8vaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTgzMzU4OC9qYXZhc2NyaXB0LWNsb25lLWEtZnVuY3Rpb25cbiAgICAgICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgbGV0IHRlbXAgPSBmdW5jdGlvbiBjbG9uZWQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoYXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmb3IgKGxldCBrZXkgaW4gdGhpcykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGVtcFtrZXldID0gdGhpc1trZXldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0ZW1wO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb2JqID09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIG9iai5fX2Nsb25lKCk7XG4gICAgfSBlbHNlIGlmIChvYmouY29uc3RydWN0b3IgJiYgb2JqLmNvbnN0cnVjdG9yID09IEFycmF5KSB7XG4gICAgICAgIHJldHVybiBvYmouc2xpY2UoMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNzI4MzYwL2hvdy1kby1pLWNvcnJlY3RseS1jbG9uZS1hLWphdmFzY3JpcHQtb2JqZWN0LzMwMDQyOTQ4IzMwMDQyOTQ4XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCBvYmopO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBmaXJzdCBub24tbnVsbC91bmRlZmluZWQgdmFsdWUgZnJvbSBhcmd1bWVudHNcbiAqIEBwYXJhbSB7Li4uKn0gYXJndW1lbnRzIC0gVmFsdWVzIHRvIGNoZWNrXG4gKiBAcmV0dXJucyB7Kn0gRmlyc3Qgbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlLCBvciBudWxsIGlmIG5vbmUgZm91bmRcbiAqL1xuZnVuY3Rpb24gY29hbGVzY2UoKSB7XG4gICAgbGV0IGFyZ3MgPSBBcnJheS5mcm9tKGFyZ3VtZW50cyk7XG4gICAgbGV0IHJldHVybl92YWwgPSBudWxsO1xuICAgIGFyZ3MuZm9yRWFjaChmdW5jdGlvbiAoYXJnKSB7XG4gICAgICAgIGlmIChyZXR1cm5fdmFsID09PSBudWxsICYmIHR5cGVvZiBhcmcgIT0gdW5kZWYgJiYgYXJnICE9PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm5fdmFsID0gYXJnO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJldHVybl92YWw7XG59XG5cbi8qKlxuICogQ29udmVydHMgQ1NWIHN0cmluZyB0byBhcnJheSwgdHJpbW1pbmcgZWFjaCBlbGVtZW50XG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyX2NzdiAtIENTViBzdHJpbmcgdG8gY29udmVydFxuICogQHJldHVybnMge0FycmF5PHN0cmluZz59IEFycmF5IG9mIHRyaW1tZWQgdmFsdWVzXG4gKiBAdG9kbyBIYW5kbGUgcXVvdGVkL2VzY2FwZWQgY2hhcmFjdGVyc1xuICovXG5mdW5jdGlvbiBjc3ZfdG9fYXJyYXlfdHJpbShzdHJfY3N2KSB7XG4gICAgY29uc3QgcGFydHMgPSBzdHJfY3N2LnNwbGl0KCcsJyk7XG4gICAgY29uc3QgcmV0ID0gW107XG4gICAgZm9yZWFjaChwYXJ0cywgKHBhcnQpID0+IHtcbiAgICAgICAgcmV0LnB1c2gocGFydC50cmltKCkpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXQ7XG59XG4iLCIvKipcbiAqIE1hbmlmZXN0IC0gSmF2YVNjcmlwdCBjbGFzcyByZWdpc3RyeSBhbmQgbWV0YWRhdGEgc3lzdGVtXG4gKlxuICogVGhpcyBjbGFzcyBtYWludGFpbnMgYSByZWdpc3RyeSBvZiBhbGwgSmF2YVNjcmlwdCBjbGFzc2VzIGluIHRoZSBidW5kbGUsXG4gKiB0cmFja2luZyB0aGVpciBuYW1lcyBhbmQgaW5oZXJpdGFuY2UgcmVsYXRpb25zaGlwcy4gSXQgcHJvdmlkZXMgdXRpbGl0aWVzXG4gKiBmb3Igd29ya2luZyB3aXRoIGNsYXNzIGhpZXJhcmNoaWVzIGFuZCBjYWxsaW5nIGluaXRpYWxpemF0aW9uIG1ldGhvZHMuXG4gKi9cbmNsYXNzIE1hbmlmZXN0IHtcbiAgICAvKipcbiAgICAgKiBEZWZpbmUgY2xhc3NlcyBpbiB0aGUgbWFuaWZlc3QgKGZyYW1ld29yayBpbnRlcm5hbClcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBpdGVtcyAtIEFycmF5IG9mIGNsYXNzIGRlZmluaXRpb25zIFtbQ2xhc3MsIFwiQ2xhc3NOYW1lXCIsIFBhcmVudENsYXNzLCBkZWNvcmF0b3JzXSwgLi4uXVxuICAgICAqL1xuICAgIHN0YXRpYyBfZGVmaW5lKGl0ZW1zKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGNsYXNzZXMgb2JqZWN0IGlmIG5vdCBhbHJlYWR5IGRlZmluZWRcbiAgICAgICAgaWYgKHR5cGVvZiBNYW5pZmVzdC5fY2xhc3NlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIE1hbmlmZXN0Ll9jbGFzc2VzID0ge307XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcm9jZXNzIGVhY2ggY2xhc3MgZGVmaW5pdGlvblxuICAgICAgICBpdGVtcy5mb3JFYWNoKChpdGVtKSA9PiB7XG4gICAgICAgICAgICBsZXQgY2xhc3Nfb2JqZWN0ID0gaXRlbVswXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19uYW1lID0gaXRlbVsxXTtcbiAgICAgICAgICAgIGxldCBjbGFzc19leHRlbmRzID0gaXRlbVsyXSB8fCBudWxsO1xuICAgICAgICAgICAgbGV0IGRlY29yYXRvcnMgPSBpdGVtWzNdIHx8IG51bGw7XG5cbiAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBjbGFzcyBpbmZvcm1hdGlvbiAodXNpbmcgb2JqZWN0IHRvIGF2b2lkIGR1cGxpY2F0ZXMpXG4gICAgICAgICAgICBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXSA9IHtcbiAgICAgICAgICAgICAgICBjbGFzczogY2xhc3Nfb2JqZWN0LFxuICAgICAgICAgICAgICAgIG5hbWU6IGNsYXNzX25hbWUsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NfZXh0ZW5kcyxcbiAgICAgICAgICAgICAgICBkZWNvcmF0b3JzOiBkZWNvcmF0b3JzLCAgLy8gU3RvcmUgY29tcGFjdCBkZWNvcmF0b3IgZGF0YVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIG1ldGFkYXRhIHRvIHRoZSBjbGFzcyBvYmplY3QgaXRzZWxmXG4gICAgICAgICAgICBjbGFzc19vYmplY3QuX25hbWUgPSBjbGFzc19uYW1lO1xuICAgICAgICAgICAgY2xhc3Nfb2JqZWN0Ll9leHRlbmRzID0gY2xhc3NfZXh0ZW5kcztcbiAgICAgICAgICAgIGNsYXNzX29iamVjdC5fZGVjb3JhdG9ycyA9IGRlY29yYXRvcnM7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIEJ1aWxkIHRoZSBzdWJjbGFzcyBpbmRleCBhZnRlciBhbGwgY2xhc3NlcyBhcmUgZGVmaW5lZFxuICAgICAgICBNYW5pZmVzdC5fYnVpbGRfc3ViY2xhc3NfaW5kZXgoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCdWlsZCBhbiBpbmRleCBvZiBzdWJjbGFzc2VzIGZvciBlZmZpY2llbnQgbG9va3Vwc1xuICAgICAqIFRoaXMgY3JlYXRlcyBhIG1hcHBpbmcgd2hlcmUgZWFjaCBjbGFzcyBuYW1lIHBvaW50cyB0byBhbiBhcnJheSBvZiBhbGwgaXRzIHN1YmNsYXNzZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYnVpbGRfc3ViY2xhc3NfaW5kZXgoKSB7XG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHN1YmNsYXNzIGluZGV4XG4gICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleCA9IHt9O1xuXG4gICAgICAgIC8vIFN0ZXAgdGhyb3VnaCBlYWNoIGNsYXNzIGFuZCB3YWxrIHVwIGl0cyBwYXJlbnQgY2hhaW5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBsZXQgY3VycmVudF9jbGFzc19uYW1lID0gY2xhc3NfbmFtZTtcbiAgICAgICAgICAgIGxldCBjdXJyZW50X2NsYXNzZGF0YSA9IGNsYXNzZGF0YTtcblxuICAgICAgICAgICAgLy8gV2FsayB1cCB0aGUgcGFyZW50IGNoYWluIHVudGlsIHdlIHJlYWNoIHRoZSByb290XG4gICAgICAgICAgICB3aGlsZSAoY3VycmVudF9jbGFzc2RhdGEpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHRlbmRzX25hbWUgPSBjdXJyZW50X2NsYXNzZGF0YS5leHRlbmRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuZHNfbmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBwYXJlbnQncyBzdWJjbGFzcyBhcnJheSBpZiBuZWVkZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFNYW5pZmVzdC5fc3ViY2xhc3NfaW5kZXhbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEFkZCB0aGlzIGNsYXNzIHRvIGl0cyBwYXJlbnQncyBzdWJjbGFzcyBsaXN0XG4gICAgICAgICAgICAgICAgICAgIGlmICghTWFuaWZlc3QuX3N1YmNsYXNzX2luZGV4W2V4dGVuZHNfbmFtZV0uaW5jbHVkZXMoY2xhc3NfbmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE1hbmlmZXN0Ll9zdWJjbGFzc19pbmRleFtleHRlbmRzX25hbWVdLnB1c2goY2xhc3NfbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBNb3ZlIHVwIHRvIHRoZSBwYXJlbnQncyBtZXRhZGF0YSAoaWYgaXQgZXhpc3RzIGluIG1hbmlmZXN0KVxuICAgICAgICAgICAgICAgICAgICBpZiAoTWFuaWZlc3QuX2NsYXNzZXNbZXh0ZW5kc19uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY3VycmVudF9jbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tleHRlbmRzX25hbWVdO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFyZW50IG5vdCBpbiBtYW5pZmVzdCAoZS5nLiwgbmF0aXZlIEphdmFTY3JpcHQgY2xhc3MpLCBzdG9wIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3NkYXRhID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vIHBhcmVudCwgd2UndmUgcmVhY2hlZCB0aGUgcm9vdFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzZGF0YSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBjbGFzc2VzIHRoYXQgZXh0ZW5kIGEgZ2l2ZW4gYmFzZSBjbGFzc1xuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gY2hlY2sgZm9yXG4gICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBvYmplY3RzIHdpdGgge2NsYXNzX25hbWUsIGNsYXNzX29iamVjdH0gZm9yIGNsYXNzZXMgdGhhdCBleHRlbmQgdGhlIGJhc2UgY2xhc3NcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2V4dGVuZGluZyhiYXNlX2NsYXNzKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgc3RyaW5nIHRvIGNsYXNzIG9iamVjdCBpZiBuZWVkZWRcbiAgICAgICAgbGV0IGJhc2VfY2xhc3Nfb2JqZWN0ID0gYmFzZV9jbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBiYXNlX2NsYXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgYmFzZV9jbGFzc19vYmplY3QgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShiYXNlX2NsYXNzKTtcbiAgICAgICAgICAgIGlmICghYmFzZV9jbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhc2UgY2xhc3Mgbm90IGZvdW5kOiAke2Jhc2VfY2xhc3N9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjbGFzc2VzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgY2xhc3NfbmFtZSBpbiBNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgY29uc3QgY2xhc3NkYXRhID0gTWFuaWZlc3QuX2NsYXNzZXNbY2xhc3NfbmFtZV07XG4gICAgICAgICAgICBpZiAoTWFuaWZlc3QuanNfaXNfc3ViY2xhc3Nfb2YoY2xhc3NkYXRhLmNsYXNzLCBiYXNlX2NsYXNzX29iamVjdCkpIHtcbiAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBjbGFzc19uYW1lOiBjbGFzc19uYW1lLFxuICAgICAgICAgICAgICAgICAgICBjbGFzc19vYmplY3Q6IGNsYXNzZGF0YS5jbGFzcyxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIGNsYXNzZXMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIGNsYXNzZXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBjbGFzcyBpcyBhIHN1YmNsYXNzIG9mIGFub3RoZXIgY2xhc3NcbiAgICAgKiBNYXRjaGVzIFBIUCBNYW5pZmVzdDo6anNfaXNfc3ViY2xhc3Nfb2YoKSBzaWduYXR1cmUgYW5kIGJlaGF2aW9yXG4gICAgICogQHBhcmFtIHtDbGFzc3xzdHJpbmd9IHN1YmNsYXNzIC0gVGhlIGNoaWxkIGNsYXNzIChvYmplY3Qgb3IgbmFtZSkgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0ge0NsYXNzfHN0cmluZ30gc3VwZXJjbGFzcyAtIFRoZSBwYXJlbnQgY2xhc3MgKG9iamVjdCBvciBuYW1lKSB0byBjaGVjayBhZ2FpbnN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgc3ViY2xhc3MgZXh0ZW5kcyBzdXBlcmNsYXNzIChkaXJlY3RseSBvciBpbmRpcmVjdGx5KVxuICAgICAqL1xuICAgIHN0YXRpYyBqc19pc19zdWJjbGFzc19vZihzdWJjbGFzcywgc3VwZXJjbGFzcykge1xuICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyBuYW1lcyB0byBjbGFzcyBvYmplY3RzXG4gICAgICAgIGxldCBzdWJjbGFzc19vYmplY3QgPSBzdWJjbGFzcztcbiAgICAgICAgaWYgKHR5cGVvZiBzdWJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1YmNsYXNzX29iamVjdCA9IE1hbmlmZXN0LmdldF9jbGFzc19ieV9uYW1lKHN1YmNsYXNzKTtcbiAgICAgICAgICAgIGlmICghc3ViY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdWJjbGFzcyAtIHJldHVybiBmYWxzZSBwZXIgc3BlY1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBzdXBlcmNsYXNzX29iamVjdCA9IHN1cGVyY2xhc3M7XG4gICAgICAgIGlmICh0eXBlb2Ygc3VwZXJjbGFzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHN1cGVyY2xhc3Nfb2JqZWN0ID0gTWFuaWZlc3QuZ2V0X2NsYXNzX2J5X25hbWUoc3VwZXJjbGFzcyk7XG4gICAgICAgICAgICBpZiAoIXN1cGVyY2xhc3Nfb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgLy8gQ2FuJ3QgcmVzb2x2ZSBzdXBlcmNsYXNzIC0gZmFpbCBsb3VkIHBlciBzcGVjXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdXBlcmNsYXNzIG5vdCBmb3VuZCBpbiBtYW5pZmVzdDogJHtzdXBlcmNsYXNzfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2xhc3NlcyBhcmUgbm90IHN1YmNsYXNzZXMgb2YgdGhlbXNlbHZlc1xuICAgICAgICBpZiAoc3ViY2xhc3Nfb2JqZWN0ID09PSBzdXBlcmNsYXNzX29iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gV2FsayB1cCB0aGUgaW5oZXJpdGFuY2UgY2hhaW5cbiAgICAgICAgbGV0IGN1cnJlbnRfY2xhc3MgPSBzdWJjbGFzc19vYmplY3Q7XG4gICAgICAgIHdoaWxlIChjdXJyZW50X2NsYXNzKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcyA9PT0gc3VwZXJjbGFzc19vYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE1vdmUgdXAgdG8gcGFyZW50IGNsYXNzXG4gICAgICAgICAgICBpZiAoY3VycmVudF9jbGFzcy5fZXh0ZW5kcykge1xuICAgICAgICAgICAgICAgIC8vIF9leHRlbmRzIG1heSBiZSBhIHN0cmluZyBvciBjbGFzcyByZWZlcmVuY2VcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRfY2xhc3MuX2V4dGVuZHMgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBNYW5pZmVzdC5nZXRfY2xhc3NfYnlfbmFtZShjdXJyZW50X2NsYXNzLl9leHRlbmRzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2NsYXNzID0gY3VycmVudF9jbGFzcy5fZXh0ZW5kcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRfY2xhc3MgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhIGNsYXNzIGJ5IGl0cyBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNsYXNzX25hbWUgLSBUaGUgbmFtZSBvZiB0aGUgY2xhc3NcbiAgICAgKiBAcmV0dXJucyB7Q2xhc3N8bnVsbH0gVGhlIGNsYXNzIG9iamVjdCBvciBudWxsIGlmIG5vdCBmb3VuZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRfY2xhc3NfYnlfbmFtZShjbGFzc19uYW1lKSB7XG4gICAgICAgIGlmICghTWFuaWZlc3QuX2NsYXNzZXMgfHwgIU1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXS5jbGFzcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHJlZ2lzdGVyZWQgY2xhc3Nlc1xuICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIHtjbGFzc19uYW1lLCBjbGFzc19vYmplY3QsIGV4dGVuZHN9XG4gICAgICovXG4gICAgc3RhdGljIGdldF9hbGxfY2xhc3NlcygpIHtcbiAgICAgICAgaWYgKCFNYW5pZmVzdC5fY2xhc3Nlcykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBjbGFzc19uYW1lIGluIE1hbmlmZXN0Ll9jbGFzc2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjbGFzc2RhdGEgPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICAgICAgICAgICAgY2xhc3NfbmFtZTogY2xhc3NkYXRhLm5hbWUsXG4gICAgICAgICAgICAgICAgY2xhc3Nfb2JqZWN0OiBjbGFzc2RhdGEuY2xhc3MsXG4gICAgICAgICAgICAgICAgZXh0ZW5kczogY2xhc3NkYXRhLmV4dGVuZHMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgYWxwaGFiZXRpY2FsbHkgYnkgY2xhc3MgbmFtZSB0byBlbnN1cmUgZGV0ZXJtaW5pc3RpYyBiZWhhdmlvciBhbmQgcHJldmVudCByYWNlIGNvbmRpdGlvbiBidWdzXG4gICAgICAgIHJlc3VsdHMuc29ydCgoYSwgYikgPT4gYS5jbGFzc19uYW1lLmxvY2FsZUNvbXBhcmUoYi5jbGFzc19uYW1lKSk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBidWlsZCBrZXkgZnJvbSB0aGUgYXBwbGljYXRpb24gY29uZmlndXJhdGlvblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBidWlsZCBrZXkgb3IgXCJOT0JVSUxEXCIgaWYgbm90IGF2YWlsYWJsZVxuICAgICAqL1xuICAgIHN0YXRpYyBidWlsZF9rZXkoKSB7XG4gICAgICAgIGlmICh3aW5kb3cucnN4YXBwICYmIHdpbmRvdy5yc3hhcHAuYnVpbGRfa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93LnJzeGFwcC5idWlsZF9rZXk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICdOT0JVSUxEJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgZGVjb3JhdG9ycyBmb3IgYSBzcGVjaWZpYyBjbGFzcyBhbmQgbWV0aG9kXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWV0aG9kX25hbWUgLSBUaGUgbWV0aG9kIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl8bnVsbH0gQXJyYXkgb2YgZGVjb3JhdG9yIG9iamVjdHMgb3IgbnVsbCBpZiBub25lIGZvdW5kXG4gICAgICovXG4gICAgc3RhdGljIGdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKSB7XG4gICAgICAgIC8vIENvbnZlcnQgY2xhc3Mgb2JqZWN0IHRvIG5hbWUgaWYgbmVlZGVkXG4gICAgICAgIGlmICh0eXBlb2YgY2xhc3NfbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNsYXNzX25hbWUgPSBjbGFzc19uYW1lLl9uYW1lIHx8IGNsYXNzX25hbWUubmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsYXNzX2luZm8gPSBNYW5pZmVzdC5fY2xhc3Nlc1tjbGFzc19uYW1lXTtcbiAgICAgICAgaWYgKCFjbGFzc19pbmZvIHx8ICFjbGFzc19pbmZvLmRlY29yYXRvcnMgfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9yc1ttZXRob2RfbmFtZV0pIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGNvbXBhY3QgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgICAgcmV0dXJuIE1hbmlmZXN0Ll90cmFuc2Zvcm1fZGVjb3JhdG9ycyhjbGFzc19pbmZvLmRlY29yYXRvcnNbbWV0aG9kX25hbWVdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIG1ldGhvZHMgd2l0aCBkZWNvcmF0b3JzIGZvciBhIGNsYXNzXG4gICAgICogQHBhcmFtIHtzdHJpbmd8Q2xhc3N9IGNsYXNzX25hbWUgLSBUaGUgY2xhc3MgbmFtZSBvciBjbGFzcyBvYmplY3RcbiAgICAgKiBAcmV0dXJucyB7T2JqZWN0fSBPYmplY3Qgd2l0aCBtZXRob2QgbmFtZXMgYXMga2V5cyBhbmQgZGVjb3JhdG9yIGFycmF5cyBhcyB2YWx1ZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2FsbF9kZWNvcmF0b3JzKGNsYXNzX25hbWUpIHtcbiAgICAgICAgLy8gQ29udmVydCBjbGFzcyBvYmplY3QgdG8gbmFtZSBpZiBuZWVkZWRcbiAgICAgICAgaWYgKHR5cGVvZiBjbGFzc19uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY2xhc3NfbmFtZSA9IGNsYXNzX25hbWUuX25hbWUgfHwgY2xhc3NfbmFtZS5uYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2xhc3NfaW5mbyA9IE1hbmlmZXN0Ll9jbGFzc2VzW2NsYXNzX25hbWVdO1xuICAgICAgICBpZiAoIWNsYXNzX2luZm8gfHwgIWNsYXNzX2luZm8uZGVjb3JhdG9ycykge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVHJhbnNmb3JtIGFsbCBkZWNvcmF0b3JzIGZyb20gY29tcGFjdCB0byBvYmplY3QgZm9ybWF0XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHt9O1xuICAgICAgICBmb3IgKGxldCBtZXRob2RfbmFtZSBpbiBjbGFzc19pbmZvLmRlY29yYXRvcnMpIHtcbiAgICAgICAgICAgIHJlc3VsdFttZXRob2RfbmFtZV0gPSBNYW5pZmVzdC5fdHJhbnNmb3JtX2RlY29yYXRvcnMoY2xhc3NfaW5mby5kZWNvcmF0b3JzW21ldGhvZF9uYW1lXSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmFuc2Zvcm0gY29tcGFjdCBkZWNvcmF0b3IgZm9ybWF0IHRvIG9iamVjdCBmb3JtYXRcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBjb21wYWN0X2RlY29yYXRvcnMgLSBBcnJheSBvZiBbbmFtZSwgW2FyZ3NdXSB0dXBsZXNcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIGRlY29yYXRvciBvYmplY3RzIHdpdGggbmFtZSBhbmQgYXJndW1lbnRzIHByb3BlcnRpZXNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJhbnNmb3JtX2RlY29yYXRvcnMoY29tcGFjdF9kZWNvcmF0b3JzKSB7XG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheShjb21wYWN0X2RlY29yYXRvcnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29tcGFjdF9kZWNvcmF0b3JzLm1hcChkZWNvcmF0b3IgPT4ge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZGVjb3JhdG9yKSAmJiBkZWNvcmF0b3IubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiBkZWNvcmF0b3JbMF0sXG4gICAgICAgICAgICAgICAgICAgIGFyZ3VtZW50czogZGVjb3JhdG9yWzFdIHx8IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEhhbmRsZSBtYWxmb3JtZWQgZGVjb3JhdG9yIGRhdGFcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ3Vua25vd24nLFxuICAgICAgICAgICAgICAgIGFyZ3VtZW50czogW11cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgbWV0aG9kIGhhcyBhIHNwZWNpZmljIGRlY29yYXRvclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfENsYXNzfSBjbGFzc19uYW1lIC0gVGhlIGNsYXNzIG5hbWUgb3IgY2xhc3Mgb2JqZWN0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZF9uYW1lIC0gVGhlIG1ldGhvZCBuYW1lXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRlY29yYXRvcl9uYW1lIC0gVGhlIGRlY29yYXRvciBuYW1lIHRvIGNoZWNrIGZvclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIHRoZSBtZXRob2QgaGFzIHRoZSBkZWNvcmF0b3JcbiAgICAgKi9cbiAgICBzdGF0aWMgaGFzX2RlY29yYXRvcihjbGFzc19uYW1lLCBtZXRob2RfbmFtZSwgZGVjb3JhdG9yX25hbWUpIHtcbiAgICAgICAgY29uc3QgZGVjb3JhdG9ycyA9IE1hbmlmZXN0LmdldF9kZWNvcmF0b3JzKGNsYXNzX25hbWUsIG1ldGhvZF9uYW1lKTtcbiAgICAgICAgaWYgKCFkZWNvcmF0b3JzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZGVjb3JhdG9ycy5zb21lKGQgPT4gZC5uYW1lID09PSBkZWNvcmF0b3JfbmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBzdWJjbGFzc2VzIG9mIGEgZ2l2ZW4gY2xhc3MgdXNpbmcgdGhlIHByZS1idWlsdCBpbmRleFxuICAgICAqIFRoaXMgaXMgdGhlIEphdmFTY3JpcHQgZXF1aXZhbGVudCBvZiBQSFAncyBNYW5pZmVzdDo6anNfZ2V0X3N1YmNsYXNzZXNfb2YoKVxuICAgICAqIEBwYXJhbSB7Q2xhc3N8c3RyaW5nfSBiYXNlX2NsYXNzIC0gVGhlIGJhc2UgY2xhc3MgKG9iamVjdCBvciBuYW1lIHN0cmluZykgdG8gZ2V0IHN1YmNsYXNzZXMgb2ZcbiAgICAgKiBAcmV0dXJucyB7QXJyYXk8Q2xhc3M+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+fSBBcnJheSBvZiBjb21wb25lbnQgbmFtZXNcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0X2NvbXBvbmVudF9uYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIGpxaHRtbC5nZXRfY29tcG9uZW50X25hbWVzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgYSBjb21wb25lbnQgaXMgcmVnaXN0ZXJlZFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIENvbXBvbmVudCBuYW1lXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFRydWUgaWYgY29tcG9uZW50IGlzIHJlZ2lzdGVyZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgaGFzX2NvbXBvbmVudChuYW1lKSB7XG4gICAgICAgIHJldHVybiBqcWh0bWwuaGFzX2NvbXBvbmVudChuYW1lKTtcbiAgICB9XG59XG5cbi8vIFJTWCBtYW5pZmVzdCBhdXRvbWF0aWNhbGx5IG1ha2VzIGNsYXNzZXMgZ2xvYmFsIC0gbm8gbWFudWFsIGFzc2lnbm1lbnQgbmVlZGVkXG4iLCIvKipcbiAqIEJhY2tlbmQgTW9kdWxlIEphdmFTY3JpcHRcbiAqL1xuY2xhc3MgQmFja2VuZF9JbmRleCB7XG4gICAgLyoqXG4gICAgICogSW5pdGlhbGl6ZSB0aGUgYmFja2VuZC9hZG1pbiBwYWdlXG4gICAgICogVGhpcyBtZXRob2QgaXMgYXV0b21hdGljYWxseSBjYWxsZWQgYnkgUlNYIGZyYW1ld29yayBmb3IgYW55IGNsYXNzIHdpdGggYSBzdGF0aWMgb25fYXBwX3JlYWR5KCkgbWV0aG9kXG4gICAgICogTm8gbWFudWFsIHJlZ2lzdHJhdGlvbiBpcyByZXF1aXJlZFxuICAgICAqL1xuICAgIHN0YXRpYyBvbl9hcHBfcmVhZHkoKSB7XG4gICAgICAgIC8vIE9ubHkgaW5pdGlhbGl6ZSBpZiB3ZSdyZSBvbiB0aGUgYmFja2VuZCBwYWdlXG4gICAgICAgIGlmICghJChcIi5CYWNrZW5kX0luZGV4XCIpLmV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoXCJKU19JTklUXCIsIFwiQmFja2VuZCBtb2R1bGUgaW5pdGlhbGl6ZWRcIik7XG4gICAgICAgIFxuICAgICAgICAvLyBBZGQgYW55IGJhY2tlbmQtc3BlY2lmaWMgSmF2YVNjcmlwdCBoZXJlXG4gICAgICAgIC8vIEV4YW1wbGU6IERhdGEgdGFibGVzLCBjaGFydHMsIGFkbWluIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgXG4gICAgICAgIC8vIEFkZCBhY3RpdmUgY2xhc3MgdG8gY3VycmVudCBzaWRlYmFyIGxpbmtcbiAgICAgICAgY29uc3QgY3VycmVudFBhdGggPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG4gICAgICAgICQoJy5zaWRlYmFyIC5uYXYtbGluaycpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICBjb25zdCAkZWxlbWVudCA9ICQodGhpcyk7XG4gICAgICAgICAgICBpZiAoJGVsZW1lbnQuYXR0cignaHJlZicpID09PSBjdXJyZW50UGF0aCkge1xuICAgICAgICAgICAgICAgICRlbGVtZW50LmFkZENsYXNzKCdhY3RpdmUnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufSIsIi8vIEphdmFTY3JpcHQgTWFuaWZlc3QgLSBHZW5lcmF0ZWQgYnkgQnVuZGxlQ29tcGlsZXJcbi8vIFJlZ2lzdGVycyBhbGwgY2xhc3NlcyBpbiB0aGlzIGJ1bmRsZSBmb3IgcnVudGltZSBpbnRyb3NwZWN0aW9uXG5NYW5pZmVzdC5fZGVmaW5lKFtcbiAgICBbTWFuaWZlc3QsIFwiTWFuaWZlc3RcIiwgbnVsbF0sXG4gICAgW1JzeF9CZWhhdmlvcnMsIFwiUnN4X0JlaGF2aW9yc1wiLCBudWxsXSxcbiAgICBbUnN4X0NhY2hlLCBcIlJzeF9DYWNoZVwiLCBudWxsXSxcbiAgICBbUnN4X0luaXQsIFwiUnN4X0luaXRcIiwgbnVsbF0sXG4gICAgW1JzeF9Kc19Nb2RlbCwgXCJSc3hfSnNfTW9kZWxcIiwgbnVsbF0sXG4gICAgW1JzeF9WaWV3X1RyYW5zaXRpb25zLCBcIlJzeF9WaWV3X1RyYW5zaXRpb25zXCIsIG51bGxdLFxuICAgIFtSZWFkV3JpdGVMb2NrLCBcIlJlYWRXcml0ZUxvY2tcIiwgbnVsbF0sXG4gICAgW0Zvcm1fVXRpbHMsIFwiRm9ybV9VdGlsc1wiLCBudWxsXSxcbiAgICBbRGVidWdnZXIsIFwiRGVidWdnZXJcIiwgbnVsbF0sXG4gICAgW1JzeF9KcV9IZWxwZXJzLCBcIlJzeF9KcV9IZWxwZXJzXCIsIG51bGxdLFxuICAgIFtSc3gsIFwiUnN4XCIsIG51bGxdLFxuICAgIFtBamF4LCBcIkFqYXhcIiwgbnVsbF0sXG4gICAgW0pxaHRtbF9Db21wb25lbnQsIFwiSnFodG1sX0NvbXBvbmVudFwiLCBfQmFzZV9KcWh0bWxfQ29tcG9uZW50XSxcbiAgICBbSnFodG1sX0ludGVncmF0aW9uLCBcIkpxaHRtbF9JbnRlZ3JhdGlvblwiLCBudWxsXSxcbiAgICBbQmFja2VuZF9JbmRleCwgXCJCYWNrZW5kX0luZGV4XCIsIG51bGxdXG5dKTtcblxuIiwiLy8gUlNYIFJvdXRlIERlZmluaXRpb25zIC0gR2VuZXJhdGVkIGJ5IEJ1bmRsZUNvbXBpbGVyXG4vLyBQcm92aWRlcyByb3V0ZSBwYXR0ZXJucyBmb3IgdHlwZS1zYWZlIFVSTCBnZW5lcmF0aW9uXG5Sc3guX2RlZmluZV9yb3V0ZXMoe1xuICAgIFwiQmFja2VuZF9JbmRleF9Db250cm9sbGVyXCI6IHtcbiAgICAgICAgXCJpbmRleFwiOiBcIi9hZG1pblwiXG4gICAgfVxufSk7XG4iLCIkKGRvY3VtZW50KS5yZWFkeShhc3luYyBmdW5jdGlvbigpIHtcbnRyeSB7XG5jb25zb2xlX2RlYnVnKCdSU1hfSU5JVCcsICdEb2N1bWVudCByZWFkeSwgc3RhcnRpbmcgUnN4Ll9yc3hfY29yZV9ib290Jyk7XG5hd2FpdCBSc3guX3JzeF9jb3JlX2Jvb3QoKTtcbmNvbnNvbGVfZGVidWcoJ1JTWF9JTklUJywgJ0luaXRpYWxpemF0aW9uIGNvbXBsZXRlJyk7XG59IGNhdGNoIChlcnJvcikge1xuY29uc29sZS5lcnJvcignW1JTWF9JTklUXSBJbml0aWFsaXphdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuY29uc29sZS5lcnJvcignW1JTWF9JTklUXSBTdGFjazonLCBlcnJvci5zdGFjayk7XG50aHJvdyBlcnJvcjtcbn1cbn0pOyJdLCJzb3VyY2VSb290IjoiIn0=