"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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