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>
190 lines
22 KiB
JavaScript
Executable File
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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
|