UNPKG

matrix-react-sdk

Version:
167 lines (161 loc) 19.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.checkConsistency = checkConsistency; exports.setCryptoInitialised = setCryptoInitialised; exports.tryPersistStorage = tryPersistStorage; var _matrix = require("matrix-js-sdk/src/matrix"); var _logger = require("matrix-js-sdk/src/logger"); var _StorageAccess = require("./StorageAccess"); /* Copyright 2024 New Vector Ltd. Copyright 2019-2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const localStorage = window.localStorage; // The JS SDK will add a prefix of "matrix-js-sdk:" to the sync store name. const SYNC_STORE_NAME = "riot-web-sync"; const LEGACY_CRYPTO_STORE_NAME = "matrix-js-sdk:crypto"; const RUST_CRYPTO_STORE_NAME = "matrix-js-sdk::matrix-sdk-crypto"; function log(msg) { _logger.logger.log(`StorageManager: ${msg}`); } function error(msg, ...args) { _logger.logger.error(`StorageManager: ${msg}`, ...args); } function tryPersistStorage() { if (navigator.storage && navigator.storage.persist) { navigator.storage.persist().then(persistent => { _logger.logger.log("StorageManager: Persistent?", persistent); }); } else if (document.requestStorageAccess) { // Safari document.requestStorageAccess().then(() => _logger.logger.log("StorageManager: Persistent?", true), () => _logger.logger.log("StorageManager: Persistent?", false)); } else { _logger.logger.log("StorageManager: Persistence unsupported"); } } async function checkConsistency() { log("Checking storage consistency"); log(`Local storage supported? ${!!localStorage}`); log(`IndexedDB supported? ${!!(0, _StorageAccess.getIDBFactory)()}`); let dataInLocalStorage = false; let dataInCryptoStore = false; let cryptoInited = false; let healthy = true; if (localStorage) { dataInLocalStorage = localStorage.length > 0; log(`Local storage contains data? ${dataInLocalStorage}`); cryptoInited = !!localStorage.getItem("mx_crypto_initialised"); log(`Crypto initialised? ${cryptoInited}`); } else { healthy = false; error("Local storage cannot be used on this browser"); } if ((0, _StorageAccess.getIDBFactory)() && localStorage) { const results = await checkSyncStore(); if (!results.healthy) { healthy = false; } } else { healthy = false; error("Sync store cannot be used on this browser"); } if ((0, _StorageAccess.getIDBFactory)()) { const results = await checkCryptoStore(); dataInCryptoStore = results.exists; if (!results.healthy) { healthy = false; } } else { healthy = false; error("Crypto store cannot be used on this browser"); } if (dataInLocalStorage && cryptoInited && !dataInCryptoStore) { healthy = false; error("Data exists in local storage and crypto is marked as initialised " + " but no data found in crypto store. " + "IndexedDB storage has likely been evicted by the browser!"); } if (healthy) { log("Storage consistency checks passed"); } else { error("Storage consistency checks failed"); } return { dataInLocalStorage, dataInCryptoStore, cryptoInited, healthy }; } async function checkSyncStore() { let exists = false; try { exists = await _matrix.IndexedDBStore.exists((0, _StorageAccess.getIDBFactory)(), SYNC_STORE_NAME); log(`Sync store using IndexedDB contains data? ${exists}`); return { exists, healthy: true }; } catch (e) { error("Sync store using IndexedDB inaccessible", e); } log("Sync store using memory only"); return { exists, healthy: false }; } async function checkCryptoStore() { // check first if there is a rust crypto store try { const rustDbExists = await _matrix.IndexedDBCryptoStore.exists((0, _StorageAccess.getIDBFactory)(), RUST_CRYPTO_STORE_NAME); log(`Rust Crypto store using IndexedDB contains data? ${rustDbExists}`); if (rustDbExists) { // There was an existing rust database, so consider it healthy. return { exists: true, healthy: true }; } else { // No rust store, so let's check if there is a legacy store not yet migrated. try { const legacyIdbExists = await _matrix.IndexedDBCryptoStore.existsAndIsNotMigrated((0, _StorageAccess.getIDBFactory)(), LEGACY_CRYPTO_STORE_NAME); log(`Legacy Crypto store using IndexedDB contains non migrated data? ${legacyIdbExists}`); return { exists: legacyIdbExists, healthy: true }; } catch (e) { error("Legacy crypto store using IndexedDB inaccessible", e); } // No need to check local storage or memory as rust stack doesn't support them. // Given that rust stack requires indexeddb, set healthy to false. return { exists: false, healthy: false }; } } catch (e) { error("Rust crypto store using IndexedDB inaccessible", e); return { exists: false, healthy: false }; } } /** * Sets whether crypto has ever been successfully * initialised on this client. * StorageManager uses this to determine whether indexeddb * has been wiped by the browser: this flag is saved to localStorage * and if it is true and not crypto data is found, an error is * presented to the user. * * @param {boolean} cryptoInited True if crypto has been set up */ function setCryptoInitialised(cryptoInited) { localStorage.setItem("mx_crypto_initialised", String(cryptoInited)); } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfU3RvcmFnZUFjY2VzcyIsImxvY2FsU3RvcmFnZSIsIndpbmRvdyIsIlNZTkNfU1RPUkVfTkFNRSIsIkxFR0FDWV9DUllQVE9fU1RPUkVfTkFNRSIsIlJVU1RfQ1JZUFRPX1NUT1JFX05BTUUiLCJsb2ciLCJtc2ciLCJsb2dnZXIiLCJlcnJvciIsImFyZ3MiLCJ0cnlQZXJzaXN0U3RvcmFnZSIsIm5hdmlnYXRvciIsInN0b3JhZ2UiLCJwZXJzaXN0IiwidGhlbiIsInBlcnNpc3RlbnQiLCJkb2N1bWVudCIsInJlcXVlc3RTdG9yYWdlQWNjZXNzIiwiY2hlY2tDb25zaXN0ZW5jeSIsImdldElEQkZhY3RvcnkiLCJkYXRhSW5Mb2NhbFN0b3JhZ2UiLCJkYXRhSW5DcnlwdG9TdG9yZSIsImNyeXB0b0luaXRlZCIsImhlYWx0aHkiLCJsZW5ndGgiLCJnZXRJdGVtIiwicmVzdWx0cyIsImNoZWNrU3luY1N0b3JlIiwiY2hlY2tDcnlwdG9TdG9yZSIsImV4aXN0cyIsIkluZGV4ZWREQlN0b3JlIiwiZSIsInJ1c3REYkV4aXN0cyIsIkluZGV4ZWREQkNyeXB0b1N0b3JlIiwibGVnYWN5SWRiRXhpc3RzIiwiZXhpc3RzQW5kSXNOb3RNaWdyYXRlZCIsInNldENyeXB0b0luaXRpYWxpc2VkIiwic2V0SXRlbSIsIlN0cmluZyJdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9TdG9yYWdlTWFuYWdlci50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxOS0yMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7IEluZGV4ZWREQlN0b3JlLCBJbmRleGVkREJDcnlwdG9TdG9yZSB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9tYXRyaXhcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuaW1wb3J0IHsgZ2V0SURCRmFjdG9yeSB9IGZyb20gXCIuL1N0b3JhZ2VBY2Nlc3NcIjtcblxuY29uc3QgbG9jYWxTdG9yYWdlID0gd2luZG93LmxvY2FsU3RvcmFnZTtcblxuLy8gVGhlIEpTIFNESyB3aWxsIGFkZCBhIHByZWZpeCBvZiBcIm1hdHJpeC1qcy1zZGs6XCIgdG8gdGhlIHN5bmMgc3RvcmUgbmFtZS5cbmNvbnN0IFNZTkNfU1RPUkVfTkFNRSA9IFwicmlvdC13ZWItc3luY1wiO1xuY29uc3QgTEVHQUNZX0NSWVBUT19TVE9SRV9OQU1FID0gXCJtYXRyaXgtanMtc2RrOmNyeXB0b1wiO1xuY29uc3QgUlVTVF9DUllQVE9fU1RPUkVfTkFNRSA9IFwibWF0cml4LWpzLXNkazo6bWF0cml4LXNkay1jcnlwdG9cIjtcblxuZnVuY3Rpb24gbG9nKG1zZzogc3RyaW5nKTogdm9pZCB7XG4gICAgbG9nZ2VyLmxvZyhgU3RvcmFnZU1hbmFnZXI6ICR7bXNnfWApO1xufVxuXG5mdW5jdGlvbiBlcnJvcihtc2c6IHN0cmluZywgLi4uYXJnczogYW55W10pOiB2b2lkIHtcbiAgICBsb2dnZXIuZXJyb3IoYFN0b3JhZ2VNYW5hZ2VyOiAke21zZ31gLCAuLi5hcmdzKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyeVBlcnNpc3RTdG9yYWdlKCk6IHZvaWQge1xuICAgIGlmIChuYXZpZ2F0b3Iuc3RvcmFnZSAmJiBuYXZpZ2F0b3Iuc3RvcmFnZS5wZXJzaXN0KSB7XG4gICAgICAgIG5hdmlnYXRvci5zdG9yYWdlLnBlcnNpc3QoKS50aGVuKChwZXJzaXN0ZW50KSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiU3RvcmFnZU1hbmFnZXI6IFBlcnNpc3RlbnQ/XCIsIHBlcnNpc3RlbnQpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKGRvY3VtZW50LnJlcXVlc3RTdG9yYWdlQWNjZXNzKSB7XG4gICAgICAgIC8vIFNhZmFyaVxuICAgICAgICBkb2N1bWVudC5yZXF1ZXN0U3RvcmFnZUFjY2VzcygpLnRoZW4oXG4gICAgICAgICAgICAoKSA9PiBsb2dnZXIubG9nKFwiU3RvcmFnZU1hbmFnZXI6IFBlcnNpc3RlbnQ/XCIsIHRydWUpLFxuICAgICAgICAgICAgKCkgPT4gbG9nZ2VyLmxvZyhcIlN0b3JhZ2VNYW5hZ2VyOiBQZXJzaXN0ZW50P1wiLCBmYWxzZSksXG4gICAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIlN0b3JhZ2VNYW5hZ2VyOiBQZXJzaXN0ZW5jZSB1bnN1cHBvcnRlZFwiKTtcbiAgICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja0NvbnNpc3RlbmN5KCk6IFByb21pc2U8e1xuICAgIGhlYWx0aHk6IGJvb2xlYW47XG4gICAgY3J5cHRvSW5pdGVkOiBib29sZWFuO1xuICAgIGRhdGFJbkNyeXB0b1N0b3JlOiBib29sZWFuO1xuICAgIGRhdGFJbkxvY2FsU3RvcmFnZTogYm9vbGVhbjtcbn0+IHtcbiAgICBsb2coXCJDaGVja2luZyBzdG9yYWdlIGNvbnNpc3RlbmN5XCIpO1xuICAgIGxvZyhgTG9jYWwgc3RvcmFnZSBzdXBwb3J0ZWQ/ICR7ISFsb2NhbFN0b3JhZ2V9YCk7XG4gICAgbG9nKGBJbmRleGVkREIgc3VwcG9ydGVkPyAkeyEhZ2V0SURCRmFjdG9yeSgpfWApO1xuXG4gICAgbGV0IGRhdGFJbkxvY2FsU3RvcmFnZSA9IGZhbHNlO1xuICAgIGxldCBkYXRhSW5DcnlwdG9TdG9yZSA9IGZhbHNlO1xuICAgIGxldCBjcnlwdG9Jbml0ZWQgPSBmYWxzZTtcbiAgICBsZXQgaGVhbHRoeSA9IHRydWU7XG5cbiAgICBpZiAobG9jYWxTdG9yYWdlKSB7XG4gICAgICAgIGRhdGFJbkxvY2FsU3RvcmFnZSA9IGxvY2FsU3RvcmFnZS5sZW5ndGggPiAwO1xuICAgICAgICBsb2coYExvY2FsIHN0b3JhZ2UgY29udGFpbnMgZGF0YT8gJHtkYXRhSW5Mb2NhbFN0b3JhZ2V9YCk7XG5cbiAgICAgICAgY3J5cHRvSW5pdGVkID0gISFsb2NhbFN0b3JhZ2UuZ2V0SXRlbShcIm14X2NyeXB0b19pbml0aWFsaXNlZFwiKTtcbiAgICAgICAgbG9nKGBDcnlwdG8gaW5pdGlhbGlzZWQ/ICR7Y3J5cHRvSW5pdGVkfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhlYWx0aHkgPSBmYWxzZTtcbiAgICAgICAgZXJyb3IoXCJMb2NhbCBzdG9yYWdlIGNhbm5vdCBiZSB1c2VkIG9uIHRoaXMgYnJvd3NlclwiKTtcbiAgICB9XG5cbiAgICBpZiAoZ2V0SURCRmFjdG9yeSgpICYmIGxvY2FsU3RvcmFnZSkge1xuICAgICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgY2hlY2tTeW5jU3RvcmUoKTtcbiAgICAgICAgaWYgKCFyZXN1bHRzLmhlYWx0aHkpIHtcbiAgICAgICAgICAgIGhlYWx0aHkgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGhlYWx0aHkgPSBmYWxzZTtcbiAgICAgICAgZXJyb3IoXCJTeW5jIHN0b3JlIGNhbm5vdCBiZSB1c2VkIG9uIHRoaXMgYnJvd3NlclwiKTtcbiAgICB9XG5cbiAgICBpZiAoZ2V0SURCRmFjdG9yeSgpKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBjaGVja0NyeXB0b1N0b3JlKCk7XG4gICAgICAgIGRhdGFJbkNyeXB0b1N0b3JlID0gcmVzdWx0cy5leGlzdHM7XG4gICAgICAgIGlmICghcmVzdWx0cy5oZWFsdGh5KSB7XG4gICAgICAgICAgICBoZWFsdGh5ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBoZWFsdGh5ID0gZmFsc2U7XG4gICAgICAgIGVycm9yKFwiQ3J5cHRvIHN0b3JlIGNhbm5vdCBiZSB1c2VkIG9uIHRoaXMgYnJvd3NlclwiKTtcbiAgICB9XG5cbiAgICBpZiAoZGF0YUluTG9jYWxTdG9yYWdlICYmIGNyeXB0b0luaXRlZCAmJiAhZGF0YUluQ3J5cHRvU3RvcmUpIHtcbiAgICAgICAgaGVhbHRoeSA9IGZhbHNlO1xuICAgICAgICBlcnJvcihcbiAgICAgICAgICAgIFwiRGF0YSBleGlzdHMgaW4gbG9jYWwgc3RvcmFnZSBhbmQgY3J5cHRvIGlzIG1hcmtlZCBhcyBpbml0aWFsaXNlZCBcIiArXG4gICAgICAgICAgICAgICAgXCIgYnV0IG5vIGRhdGEgZm91bmQgaW4gY3J5cHRvIHN0b3JlLiBcIiArXG4gICAgICAgICAgICAgICAgXCJJbmRleGVkREIgc3RvcmFnZSBoYXMgbGlrZWx5IGJlZW4gZXZpY3RlZCBieSB0aGUgYnJvd3NlciFcIixcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoaGVhbHRoeSkge1xuICAgICAgICBsb2coXCJTdG9yYWdlIGNvbnNpc3RlbmN5IGNoZWNrcyBwYXNzZWRcIik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZXJyb3IoXCJTdG9yYWdlIGNvbnNpc3RlbmN5IGNoZWNrcyBmYWlsZWRcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZGF0YUluTG9jYWxTdG9yYWdlLFxuICAgICAgICBkYXRhSW5DcnlwdG9TdG9yZSxcbiAgICAgICAgY3J5cHRvSW5pdGVkLFxuICAgICAgICBoZWFsdGh5LFxuICAgIH07XG59XG5cbmludGVyZmFjZSBTdG9yZUNoZWNrIHtcbiAgICBleGlzdHM6IGJvb2xlYW47XG4gICAgaGVhbHRoeTogYm9vbGVhbjtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tTeW5jU3RvcmUoKTogUHJvbWlzZTxTdG9yZUNoZWNrPiB7XG4gICAgbGV0IGV4aXN0cyA9IGZhbHNlO1xuICAgIHRyeSB7XG4gICAgICAgIGV4aXN0cyA9IGF3YWl0IEluZGV4ZWREQlN0b3JlLmV4aXN0cyhnZXRJREJGYWN0b3J5KCkhLCBTWU5DX1NUT1JFX05BTUUpO1xuICAgICAgICBsb2coYFN5bmMgc3RvcmUgdXNpbmcgSW5kZXhlZERCIGNvbnRhaW5zIGRhdGE/ICR7ZXhpc3RzfWApO1xuICAgICAgICByZXR1cm4geyBleGlzdHMsIGhlYWx0aHk6IHRydWUgfTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGVycm9yKFwiU3luYyBzdG9yZSB1c2luZyBJbmRleGVkREIgaW5hY2Nlc3NpYmxlXCIsIGUpO1xuICAgIH1cbiAgICBsb2coXCJTeW5jIHN0b3JlIHVzaW5nIG1lbW9yeSBvbmx5XCIpO1xuICAgIHJldHVybiB7IGV4aXN0cywgaGVhbHRoeTogZmFsc2UgfTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tDcnlwdG9TdG9yZSgpOiBQcm9taXNlPFN0b3JlQ2hlY2s+IHtcbiAgICAvLyBjaGVjayBmaXJzdCBpZiB0aGVyZSBpcyBhIHJ1c3QgY3J5cHRvIHN0b3JlXG4gICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcnVzdERiRXhpc3RzID0gYXdhaXQgSW5kZXhlZERCQ3J5cHRvU3RvcmUuZXhpc3RzKGdldElEQkZhY3RvcnkoKSEsIFJVU1RfQ1JZUFRPX1NUT1JFX05BTUUpO1xuICAgICAgICBsb2coYFJ1c3QgQ3J5cHRvIHN0b3JlIHVzaW5nIEluZGV4ZWREQiBjb250YWlucyBkYXRhPyAke3J1c3REYkV4aXN0c31gKTtcblxuICAgICAgICBpZiAocnVzdERiRXhpc3RzKSB7XG4gICAgICAgICAgICAvLyBUaGVyZSB3YXMgYW4gZXhpc3RpbmcgcnVzdCBkYXRhYmFzZSwgc28gY29uc2lkZXIgaXQgaGVhbHRoeS5cbiAgICAgICAgICAgIHJldHVybiB7IGV4aXN0czogdHJ1ZSwgaGVhbHRoeTogdHJ1ZSB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm8gcnVzdCBzdG9yZSwgc28gbGV0J3MgY2hlY2sgaWYgdGhlcmUgaXMgYSBsZWdhY3kgc3RvcmUgbm90IHlldCBtaWdyYXRlZC5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbGVnYWN5SWRiRXhpc3RzID0gYXdhaXQgSW5kZXhlZERCQ3J5cHRvU3RvcmUuZXhpc3RzQW5kSXNOb3RNaWdyYXRlZChcbiAgICAgICAgICAgICAgICAgICAgZ2V0SURCRmFjdG9yeSgpISxcbiAgICAgICAgICAgICAgICAgICAgTEVHQUNZX0NSWVBUT19TVE9SRV9OQU1FLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgbG9nKGBMZWdhY3kgQ3J5cHRvIHN0b3JlIHVzaW5nIEluZGV4ZWREQiBjb250YWlucyBub24gbWlncmF0ZWQgZGF0YT8gJHtsZWdhY3lJZGJFeGlzdHN9YCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgZXhpc3RzOiBsZWdhY3lJZGJFeGlzdHMsIGhlYWx0aHk6IHRydWUgfTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBlcnJvcihcIkxlZ2FjeSBjcnlwdG8gc3RvcmUgdXNpbmcgSW5kZXhlZERCIGluYWNjZXNzaWJsZVwiLCBlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTm8gbmVlZCB0byBjaGVjayBsb2NhbCBzdG9yYWdlIG9yIG1lbW9yeSBhcyBydXN0IHN0YWNrIGRvZXNuJ3Qgc3VwcG9ydCB0aGVtLlxuICAgICAgICAgICAgLy8gR2l2ZW4gdGhhdCBydXN0IHN0YWNrIHJlcXVpcmVzIGluZGV4ZWRkYiwgc2V0IGhlYWx0aHkgdG8gZmFsc2UuXG4gICAgICAgICAgICByZXR1cm4geyBleGlzdHM6IGZhbHNlLCBoZWFsdGh5OiBmYWxzZSB9O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBlcnJvcihcIlJ1c3QgY3J5cHRvIHN0b3JlIHVzaW5nIEluZGV4ZWREQiBpbmFjY2Vzc2libGVcIiwgZSk7XG4gICAgICAgIHJldHVybiB7IGV4aXN0czogZmFsc2UsIGhlYWx0aHk6IGZhbHNlIH07XG4gICAgfVxufVxuXG4vKipcbiAqIFNldHMgd2hldGhlciBjcnlwdG8gaGFzIGV2ZXIgYmVlbiBzdWNjZXNzZnVsbHlcbiAqIGluaXRpYWxpc2VkIG9uIHRoaXMgY2xpZW50LlxuICogU3RvcmFnZU1hbmFnZXIgdXNlcyB0aGlzIHRvIGRldGVybWluZSB3aGV0aGVyIGluZGV4ZWRkYlxuICogaGFzIGJlZW4gd2lwZWQgYnkgdGhlIGJyb3dzZXI6IHRoaXMgZmxhZyBpcyBzYXZlZCB0byBsb2NhbFN0b3JhZ2VcbiAqIGFuZCBpZiBpdCBpcyB0cnVlIGFuZCBub3QgY3J5cHRvIGRhdGEgaXMgZm91bmQsIGFuIGVycm9yIGlzXG4gKiBwcmVzZW50ZWQgdG8gdGhlIHVzZXIuXG4gKlxuICogQHBhcmFtIHtib29sZWFufSBjcnlwdG9Jbml0ZWQgVHJ1ZSBpZiBjcnlwdG8gaGFzIGJlZW4gc2V0IHVwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRDcnlwdG9Jbml0aWFsaXNlZChjcnlwdG9Jbml0ZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShcIm14X2NyeXB0b19pbml0aWFsaXNlZFwiLCBTdHJpbmcoY3J5cHRvSW5pdGVkKSk7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBUUEsSUFBQUEsT0FBQSxHQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBRUEsSUFBQUUsY0FBQSxHQUFBRixPQUFBO0FBWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBT0EsTUFBTUcsWUFBWSxHQUFHQyxNQUFNLENBQUNELFlBQVk7O0FBRXhDO0FBQ0EsTUFBTUUsZUFBZSxHQUFHLGVBQWU7QUFDdkMsTUFBTUMsd0JBQXdCLEdBQUcsc0JBQXNCO0FBQ3ZELE1BQU1DLHNCQUFzQixHQUFHLGtDQUFrQztBQUVqRSxTQUFTQyxHQUFHQSxDQUFDQyxHQUFXLEVBQVE7RUFDNUJDLGNBQU0sQ0FBQ0YsR0FBRyxDQUFDLG1CQUFtQkMsR0FBRyxF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