Files
rspade_system/storage-broken/rsx-tmp/babel_28288cd37dbde95f7cf4d7f7a8f69ff2.js
root 77b4d10af8 Refactor filename naming system and apply convention-based renames
Standardize settings file naming and relocate documentation files
Fix code quality violations from rsx:check
Reorganize user_management directory into logical subdirectories
Move Quill Bundle to core and align with Tom Select pattern
Simplify Site Settings page to focus on core site information
Complete Phase 5: Multi-tenant authentication with login flow and site selection
Add route query parameter rule and synchronize filename validation logic
Fix critical bug in UpdateNpmCommand causing missing JavaScript stubs
Implement filename convention rule and resolve VS Code auto-rename conflict
Implement js-sanitizer RPC server to eliminate 900+ Node.js process spawns
Implement RPC server architecture for JavaScript parsing
WIP: Add RPC server infrastructure for JS parsing (partial implementation)
Update jqhtml terminology from destroy to stop, fix datagrid DOM preservation
Add JQHTML-CLASS-01 rule and fix redundant class names
Improve code quality rules and resolve violations
Remove legacy fatal error format in favor of unified 'fatal' error type
Filter internal keys from window.rsxapp output
Update button styling and comprehensive form/modal documentation
Add conditional fly-in animation for modals
Fix non-deterministic bundle compilation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 19:10:02 +00:00

190 lines
22 KiB
JavaScript
Executable File

"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');
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSc3hfQ2FjaGUiLCJvbl9jb3JlX2RlZmluZSIsIkNvcmVfQ2FjaGUiLCJfY2FjaGVzIiwiZ2xvYmFsIiwiaW5zdGFuY2UiLCJfY2FjaGVzX3NldCIsImdldCIsImtleSIsImdldF9pbnN0YW5jZSIsIk1haW4iLCJkZWJ1ZyIsImtleV9lbmNvZGVkIiwiX2VuY29kZWtleSIsInVuZGVmIiwiSlNPTiIsInBhcnNlIiwiZ2V0X2dsb2JhbCIsInNldCIsInZhbHVlIiwibGVuZ3RoIiwiRGVidWdnZXIiLCJjb25zb2xlX2RlYnVnIiwic3RyaW5naWZ5IiwiY291bnQiLCJnZXRfc2Vzc2lvbiIsIl9zdXBwb3J0c1N0b3JhZ2UiLCJycyIsInNlc3Npb25TdG9yYWdlIiwiZ2V0SXRlbSIsImVtcHR5Iiwic2V0X3Nlc3Npb24iLCJfdHJ5YWdhaW4iLCJhcmd1bWVudHMiLCJ1bmRlZmluZWQiLCJyZW1vdmVJdGVtIiwic2V0SXRlbSIsImUiLCJfaXNPdXRPZlNwYWNlIiwiY2xlYXIiLCJfcmVzZXQiLCJwcmVmaXgiLCJpc19zdHJpbmciLCJpbmRleE9mIiwiTWFuaWZlc3QiLCJidWlsZF9rZXkiLCJoYXNoIiwiX19zdXBwb3J0c1N0b3JhZ2UiLCJleCIsIm5hbWUiXSwic291cmNlcyI6WyJhcHAvUlNwYWRlL0NvcmUvSnMvUnN4X0NhY2hlLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFNpbXBsZSBrZXkgdmFsdWUgY2FjaGUuICBDYW4gb25seSBzdG9yZSA1MDAwIGVudHJpZXMsIHdpbGwgcmVzZXQgYWZ0ZXIgNTAwMCBlbnRyaWVzLlxuXG4vLyBUb2RvOiBrZWVwIGxvY2FsIGNhY2hlIGNvbmNlcHQgdGhlIHNhbWUsIHJlcGxhY2UgZ2xvYmFsIGNhY2hlIGNvbmNlcHQgd2l0aCB0aGUgbm92IDIwMTkgdmVyc2lvbiBvZlxuLy8gc2Vzc2lvbiBjYWNoZS4gIFVzZSBhIHNlc3Npb24ga2V5ICYgYnVpbGQga2V5IHRvIHRyYWNrIGNhY2hlIGtleXMgc28gY2FjaGVkIHZhbHVlcyBvbmx5IGxhc3QgdW50aWwgdXNlciBsb2dzIG91dC5cbi8vIHJldmlldyBzZXNzaW9uIGNvZGUgdG8gZW5zdXJlIHRoYXQgc2Vzc2lvbiBrZXkgKmFsd2F5cyogcm90YXRlcyBvbiBsb2dvdXQuICBNYWtlIHNlc3Npb24gaWQgYSBwcm90ZWN0ZWQgdmFsdWUuXG5jbGFzcyBSc3hfQ2FjaGUge1xuICAgIHN0YXRpYyBvbl9jb3JlX2RlZmluZSgpIHtcbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzID0ge1xuICAgICAgICAgICAgZ2xvYmFsOiB7fSxcbiAgICAgICAgICAgIGluc3RhbmNlOiB7fSxcbiAgICAgICAgfTtcblxuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBBbGlhcyBmb3IgZ2V0X2luc3RhbmNlXG4gICAgc3RhdGljIGdldChrZXkpIHtcbiAgICAgICAgcmV0dXJuIFJzeF9DYWNoZS5nZXRfaW5zdGFuY2Uoa2V5KTtcbiAgICB9XG5cbiAgICAvLyBSZXR1cm5zIGZyb20gdGhlIHBvb2wgb2YgY2FjaGVkIGRhdGEgZm9yIHRoaXMgJ2luc3RhbmNlJy4gIEFuIGluc3RhbmNlXG4gICAgLy8gaW4gdGhpcyBjYXNlIGlzIGEgdmlydHVhbCBwYWdlIGxvYWQgLyBuYXZpZ2F0aW9uIGluIHRoZSBTUEEuICBDYWxsIE1haW4ubGliLnJlc2V0KCkgdG8gcmVzZXQuXG4gICAgLy8gUmV0dXJucyBudWxsIG9uIGZhaWx1cmVcbiAgICBzdGF0aWMgZ2V0X2luc3RhbmNlKGtleSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBpZiAodHlwZW9mIENvcmVfQ2FjaGUuX2NhY2hlcy5pbnN0YW5jZVtrZXlfZW5jb2RlZF0gIT0gdW5kZWYpIHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKENvcmVfQ2FjaGUuX2NhY2hlcy5pbnN0YW5jZVtrZXlfZW5jb2RlZF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gUmV0dXJucyBudWxsIG9uIGZhaWx1cmVcbiAgICAvLyBSZXR1cm5zIGEgY2FjaGVkIHZhbHVlIGZyb20gZ2xvYmFsIGNhY2hlICh1bmlxdWUgdG8gcGFnZSBsb2FkLCBzdXJ2aXZlcyByZXNldCgpKVxuICAgIHN0YXRpYyBnZXRfZ2xvYmFsKGtleSkge1xuICAgICAgICBpZiAoTWFpbi5kZWJ1Zygnbm9fYXBpX2NhY2hlJykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBpZiAodHlwZW9mIENvcmVfQ2FjaGUuX2NhY2hlcy5nbG9iYWxba2V5X2VuY29kZWRdICE9IHVuZGVmKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShDb3JlX0NhY2hlLl9jYWNoZXMuZ2xvYmFsW2tleV9lbmNvZGVkXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBTZXRzIGEgdmFsdWUgaW4gaW5zdGFuY2UgYW5kIGdsb2JhbCBjYWNoZSAobm90IHNoYXJlZCBiZXR3ZWVuIGJyb3dzZXIgdGFicylcbiAgICBzdGF0aWMgc2V0KGtleSwgdmFsdWUpIHtcbiAgICAgICAgaWYgKE1haW4uZGVidWcoJ25vX2FwaV9jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiA2NCAqIDEwMjQpIHtcbiAgICAgICAgICAgIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoJ0NBQ0hFJywgJ1dhcm5pbmcgLSBub3QgY2FjaGluZyBsYXJnZSBjYWNoZSBlbnRyeScsIGtleSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlcy5nbG9iYWxba2V5X2VuY29kZWRdID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXMuaW5zdGFuY2Vba2V5X2VuY29kZWRdID0gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuXG4gICAgICAgIC8vIERlYnVnZ2VyLmNvbnNvbGVfZGVidWcoXCJDQUNIRVwiLCBcIlNldFwiLCBrZXksIHZhbHVlKTtcblxuICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0Kys7XG5cbiAgICAgICAgLy8gUmVzZXQgY2FjaGUgYWZ0ZXIgNTAwMCBpdGVtcyBzZXRcbiAgICAgICAgaWYgKENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPiA1MDAwKSB7XG4gICAgICAgICAgICAvLyBHZXQgYW4gYWNjdXJhdGUgY291bnRcbiAgICAgICAgICAgIENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPSBjb3VudChDb3JlX0NhY2hlLl9jYWNoZXMuZ2xvYmFsKTtcblxuICAgICAgICAgICAgaWYgKENvcmVfQ2FjaGUuX2NhY2hlc19zZXQgPiA1MDAwKSB7XG4gICAgICAgICAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzID0ge1xuICAgICAgICAgICAgICAgICAgICBnbG9iYWw6IHt9LFxuICAgICAgICAgICAgICAgICAgICBpbnN0YW5jZToge30sXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBDb3JlX0NhY2hlLl9jYWNoZXNfc2V0ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybnMgbnVsbCBvbiBmYWlsdXJlXG4gICAgLy8gUmV0dXJucyBhIGNhY2hlZCB2YWx1ZSBmcm9tIHNlc3Npb24gY2FjaGUgKHNoYXJlZCBiZXR3ZWVuIGJyb3dzZXIgdGFicylcbiAgICBzdGF0aWMgZ2V0X3Nlc3Npb24oa2V5KSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIVJzeF9DYWNoZS5fc3VwcG9ydHNTdG9yYWdlKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGtleV9lbmNvZGVkID0gUnN4X0NhY2hlLl9lbmNvZGVrZXkoa2V5KTtcblxuICAgICAgICBsZXQgcnMgPSBzZXNzaW9uU3RvcmFnZS5nZXRJdGVtKGtleV9lbmNvZGVkKTtcblxuICAgICAgICBpZiAoIWVtcHR5KHJzKSkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UocnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZXRzIGEgdmFsdWUgaW4gc2Vzc2lvbiBjYWNoZSAoc2hhcmVkIGJldHdlZW4gYnJvd3NlciB0YWJzKVxuICAgIHN0YXRpYyBzZXRfc2Vzc2lvbihrZXksIHZhbHVlLCBfdHJ5YWdhaW4gPSB0cnVlKSB7XG4gICAgICAgIGlmIChNYWluLmRlYnVnKCdub19hcGlfY2FjaGUnKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA+IDY0ICogMTAyNCkge1xuICAgICAgICAgICAgRGVidWdnZXIuY29uc29sZV9kZWJ1ZygnQ0FDSEUnLCAnV2FybmluZyAtIG5vdCBjYWNoaW5nIGxhcmdlIGNhY2hlIGVudHJ5Jywga2V5KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghUnN4X0NhY2hlLl9zdXBwb3J0c1N0b3JhZ2UoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQga2V5X2VuY29kZWQgPSBSc3hfQ2FjaGUuX2VuY29kZWtleShrZXkpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5yZW1vdmVJdGVtKGtleV9lbmNvZGVkKTtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0oa2V5X2VuY29kZWQsIEpTT04uc3RyaW5naWZ5KHZhbHVlKSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChSc3hfQ2FjaGUuX2lzT3V0T2ZTcGFjZShlKSAmJiBzZXNzaW9uU3RvcmFnZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgIGlmIChfdHJ5YWdhaW4pIHtcbiAgICAgICAgICAgICAgICAgICAgQ29yZV9DYWNoZS5zZXRfc2Vzc2lvbihrZXksIHZhbHVlLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgc3RhdGljIF9yZXNldCgpIHtcbiAgICAgICAgQ29yZV9DYWNoZS5fY2FjaGVzLmluc3RhbmNlID0ge307XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yIGdpdmVuIGtleSBvZiBhbnkgdHlwZSBpbmNsdWRpbmcgYW4gb2JqZWN0LCByZXR1cm4gYSBzdHJpbmcgcmVwcmVzZW50aW5nXG4gICAgICogdGhlIGtleSB0aGF0IHRoZSBjYWNoZWQgdmFsdWUgc2hvdWxkIGJlIHN0b3JlZCBhcyBpbiBzZXNzaW9uc3RvcmFnZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZW5jb2Rla2V5KGtleSkge1xuICAgICAgICBjb25zdCBwcmVmaXggPSAnY2FjaGVfJztcblxuICAgICAgICAvLyBTZXNzaW9uIHJlaW1wbGVtZW50XG4gICAgICAgIC8vIHZhciBwcmVmaXggPSBcImNhY2hlX1wiICsgU3BhLnNlc3Npb24oKS51c2VyX2lkKCkgKyBcIl9cIjtcblxuICAgICAgICBpZiAoaXNfc3RyaW5nKGtleSkgJiYga2V5Lmxlbmd0aCA8IDE1MCAmJiBrZXkuaW5kZXhPZignICcpID09IC0xKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgTWFuaWZlc3QuYnVpbGRfa2V5KCkgKyAnXycgKyBrZXk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgaGFzaChbTWFuaWZlc3QuYnVpbGRfa2V5KCksIGtleV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGV0ZXJtaW5lcyBpZiBzZXNzaW9uU3RvcmFnZSBpcyBzdXBwb3J0ZWQgaW4gdGhlIGJyb3dzZXI7XG4gICAgLy8gcmVzdWx0IGlzIGNhY2hlZCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlIGluc3RlYWQgb2YgYmVpbmcgcnVuIGVhY2ggdGltZS5cbiAgICAvLyBGZWF0dXJlIGRldGVjdGlvbiBpcyBiYXNlZCBvbiBob3cgTW9kZXJuaXpyIGRvZXMgaXQ7XG4gICAgLy8gaXQncyBub3Qgc3RyYWlnaHRmb3J3YXJkIGR1ZSB0byBGRjQgaXNzdWVzLlxuICAgIC8vIEl0J3Mgbm90IHJ1biBhdCBwYXJzZS10aW1lIGFzIGl0IHRha2VzIDIwMG1zIGluIEFuZHJvaWQuXG4gICAgLy8gQ29kZSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9wYW1lbGFmb3gvbHNjYWNoZS9ibG9iL21hc3Rlci9sc2NhY2hlLmpzLCBBcGFjaGUgTGljZW5zZSBQYW1lbGFmb3hcbiAgICBzdGF0aWMgX3N1cHBvcnRzU3RvcmFnZSgpIHtcbiAgICAgICAgbGV0IGtleSA9ICdfX2NhY2hldGVzdF9fJztcbiAgICAgICAgbGV0IHZhbHVlID0ga2V5O1xuXG4gICAgICAgIGlmIChSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFJzeF9DYWNoZS5fX3N1cHBvcnRzU3RvcmFnZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNvbWUgYnJvd3NlcnMgd2lsbCB0aHJvdyBhbiBlcnJvciBpZiB5b3UgdHJ5IHRvIGFjY2VzcyBsb2NhbCBzdG9yYWdlIChlLmcuIGJyYXZlIGJyb3dzZXIpXG4gICAgICAgIC8vIGhlbmNlIGNoZWNrIGlzIGluc2lkZSBhIHRyeS9jYXRjaFxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKCFzZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKGtleSwgdmFsdWUpO1xuICAgICAgICAgICAgc2Vzc2lvblN0b3JhZ2UucmVtb3ZlSXRlbShrZXkpO1xuICAgICAgICAgICAgUnN4X0NhY2hlLl9fc3VwcG9ydHNTdG9yYWdlID0gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gSWYgd2UgaGl0IHRoZSBsaW1pdCwgYW5kIHdlIGRvbid0IGhhdmUgYW4gZW1wdHkgc2Vzc2lvblN0b3JhZ2UgdGhlbiBpdCBtZWFucyB3ZSBoYXZlIHN1cHBvcnRcbiAgICAgICAgICAgIGlmIChSc3hfQ2FjaGUuX2lzT3V0T2ZTcGFjZShlKSAmJiBzZXNzaW9uU3RvcmFnZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgPSB0cnVlOyAvLyBqdXN0IG1heGVkIGl0IG91dCBhbmQgZXZlbiB0aGUgc2V0IHRlc3QgZmFpbGVkLlxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2UgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBSc3hfQ2FjaGUuX19zdXBwb3J0c1N0b3JhZ2U7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgdG8gc2V0IGlmIHRoZSBlcnJvciBpcyB1cyBkZWFsaW5nIHdpdGggYmVpbmcgb3V0IG9mIHNwYWNlXG4gICAgc3RhdGljIF9pc091dE9mU3BhY2UoZSkge1xuICAgICAgICByZXR1cm4gZSAmJiAoZS5uYW1lID09PSAnUVVPVEFfRVhDRUVERURfRVJSJyB8fCBlLm5hbWUgPT09ICdOU19FUlJPUl9ET01fUVVPVEFfUkVBQ0hFRCcgfHwgZS5uYW1lID09PSAnUXVvdGFFeGNlZWRlZEVycm9yJyk7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOztBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU1BLFNBQVMsQ0FBQztFQUNaLE9BQU9DLGNBQWNBLENBQUEsRUFBRztJQUNwQkMsVUFBVSxDQUFDQyxPQUFPLEdBQUc7TUFDakJDLE1BQU0sRUFBRSxDQUFDLENBQUM7TUFDVkMsUUFBUSxFQUFFLENBQUM7SUFDZixDQUFDO0lBRURILFVBQVUsQ0FBQ0ksV0FBVyxHQUFHLENBQUM7RUFDOUI7O0VBRUE7RUFDQSxPQUFPQyxHQUFHQSxDQUFDQyxHQUFHLEVBQUU7SUFDWixPQUFPUixTQUFTLENBQUNTLFlBQVksQ0FBQ0QsR0FBRyxDQUFDO0VBQ3RDOztFQUVBO0VBQ0E7RUFDQTtFQUNBLE9BQU9DLFlBQVlBLENBQUNELEdBQUcsRUFBRTtJQUNyQixJQUFJRSxJQUFJLENBQUNDLEtBQUssQ0FBQyxjQUFjLENBQUMsRUFBRTtNQUM1QixPQUFPLElBQUk7SUFDZjtJQUVBLElBQUlDLFdBQVcsR0FBR1osU0FBUyxDQUFDYSxVQUFVLENBQUNMLEdBQUcsQ0FBQztJQUUzQyxJQUFJLE9BQU9OLFVBQVUsQ0FBQ0MsT0FBTyxDQUFDRSxRQUFRLENB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