// Copyright (c) 2020-2021 Drew Lemmy // This file is part of TenebraWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/TenebraWeb2/blob/master/LICENSE.txt import { Backup, BackupFormatType, BackupTenebraWebV1, BackupTenebraWebV2 } from "./backupFormats"; import { TranslatedError } from "@utils/i18n"; import { isPlainObject } from "lodash-es"; /** Detects a backup's format and decodes it. */ export function decodeBackup(rawData: string): Backup { try { // All backups are encoded as base64, so decode that first const plainData = window.atob(rawData); // Attempt to parse JSON const data = JSON.parse(plainData); // Check for required properties if (!data.tester) throw new TranslatedError("import.decodeErrors.missingTester"); if (!data.salt) throw new TranslatedError("import.decodeErrors.missingSalt"); if (typeof data.tester !== "string") throw new TranslatedError("import.decodeErrors.invalidTester"); if (typeof data.salt !== "string") throw new TranslatedError("import.decodeErrors.invalidSalt"); if (!isPlainObject(data.wallets)) throw new TranslatedError("import.decodeErrors.invalidWallets"); if (data.friends !== undefined && !isPlainObject(data.friends)) throw new TranslatedError("import.decodeErrors.invalidFriends"); if (data.contacts !== undefined && !isPlainObject(data.contacts)) throw new TranslatedError("import.decodeErrors.invalidContacts"); // Determine the format if (data.version === 2) { // TenebraWeb v2 data.type = BackupFormatType.KRISTWEB_V2; return data as BackupTenebraWebV2; } else { // TenebraWeb v1 data.type = BackupFormatType.KRISTWEB_V1; return data as BackupTenebraWebV1; } } catch (err) { // Invalid base64 if (err instanceof DOMException && err.name === "InvalidCharacterError") throw new TranslatedError("import.decodeErrors.atob"); // Invalid json if (err?.name === "SyntaxError") throw new TranslatedError("import.decodeErrors.json"); throw err; } }