diff --git a/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java b/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java index 16c59f33..0c62ea6f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/db/DbPersistence.java @@ -933,10 +933,15 @@ public class DbPersistence implements Persistence { } private String getUrl(File walletFile, String password) throws StorageException { - if(JDBC_URL_INJECTION_PATTERN.matcher(walletFile.getAbsolutePath()).find()) { + File dbFile = walletFile.getAbsoluteFile(); + if(JDBC_URL_INJECTION_PATTERN.matcher(dbFile.getPath()).find()) { throw new StorageException("Wallet file path contains invalid characters"); } - return "jdbc:h2:" + walletFile.getAbsolutePath().replace("." + getType().getExtension(), "") + ";INIT=SET TRACE_LEVEL_FILE=4;TRACE_LEVEL_FILE=4;DEFRAG_ALWAYS=true;MAX_COMPACT_TIME=5000;DATABASE_TO_UPPER=false" + (password == null ? "" : ";CIPHER=AES"); + + //H2 appends the extension to the database name in the URL, so only a trailing extension can be removed - removing every occurrence would + //open a different file to the one tracked here, as would removing one from a directory name + File dbName = new File(dbFile.getParentFile(), getWalletName(dbFile, null)); + return "jdbc:h2:" + dbName.getPath() + ";INIT=SET TRACE_LEVEL_FILE=4;TRACE_LEVEL_FILE=4;DEFRAG_ALWAYS=true;MAX_COMPACT_TIME=5000;DATABASE_TO_UPPER=false" + (password == null ? "" : ";CIPHER=AES"); } private boolean persistsFor(Wallet wallet) { diff --git a/src/test/java/com/sparrowwallet/sparrow/io/DbPersistenceTest.java b/src/test/java/com/sparrowwallet/sparrow/io/DbPersistenceTest.java index 3ec27b1d..fe8553b2 100644 --- a/src/test/java/com/sparrowwallet/sparrow/io/DbPersistenceTest.java +++ b/src/test/java/com/sparrowwallet/sparrow/io/DbPersistenceTest.java @@ -175,6 +175,22 @@ public class DbPersistenceTest { Assertions.assertTrue(new Storage(PersistenceType.DB, storage.getWalletFile()).loadEncryptedWallet("pass").getWallet().isValid()); } + @Test + public void walletNameContainingExtensionUsesItsOwnFile() throws Exception { + Storage otherStorage = createUnencryptedWallet("backup2"); + otherStorage.closeAndWait(); + File otherFile = otherStorage.getWalletFile(); + Sha256Hash otherHash = getFileHash(otherFile); + + //The file for this wallet is backup.mv.db2.mv.db - removing every occurrence of the extension from the path yields the database name backup2 + Storage storage = createUnencryptedWallet("backup.mv.db2"); + storage.closeAndWait(); + + Assertions.assertTrue(storage.getWalletFile().exists(), "wallet was written to a file other than the one tracked"); + Assertions.assertTrue(new Storage(PersistenceType.DB, storage.getWalletFile()).loadUnencryptedWallet().getWallet().isValid()); + Assertions.assertEquals(otherHash, getFileHash(otherFile), "another wallet file was written by a wallet name containing the extension"); + } + @Test public void passwordRemovalDecryptsWalletFile() throws Exception { Storage storage = createUnencryptedWallet("Savings");