diff src/main/kotlin/name/blackcap/passman/Database.kt @ 21:ea65ab890f66

More work to support interactive feature.
author David Barts <n5jrn@me.com>
date Tue, 02 Jul 2024 11:27:39 -0700
parents 7d80cbcb67bb
children
line wrap: on
line diff
--- a/src/main/kotlin/name/blackcap/passman/Database.kt	Sun Jun 30 22:28:52 2024 -0700
+++ b/src/main/kotlin/name/blackcap/passman/Database.kt	Tue Jul 02 11:27:39 2024 -0700
@@ -12,6 +12,7 @@
         private const val PLAINTEXT = "This is a test."
         private const val SALT_LENGTH = 16
         private const val DEFAULT_PROMPT = "Decryption key: "
+        lateinit var default: Database
 
         fun open(passwordPrompt: String = DEFAULT_PROMPT, fileName: String = DB_FILE,
                  create: Boolean = true): Database {
@@ -20,10 +21,14 @@
                 if (create) {
                     error("initializing database ${see(fileName)}")
                 } else {
-                    die("${see(fileName)} not found")
+                    throw DatabaseException("${see(fileName)} not found")
                 }
             }
-            val masterPassword = getPassword(passwordPrompt, !exists)
+            val masterPassword = try {
+                getPassword(passwordPrompt, !exists)
+            } catch (e: ConsoleException) {
+                throw DatabaseException(e.message, cause = e)
+            }
             val conn = DriverManager.getConnection("jdbc:sqlite:$fileName")
             val enc = if (exists) { reuse(conn, masterPassword) } else { init(conn, masterPassword) }
             val ret = Database(conn, enc)
@@ -37,15 +42,14 @@
                     it.setString(1, "salt")
                     val result = it.executeQuery()
                     if (!result.next()) {
-                        die("corrupt database, missing salt parameter")
+                        throw DatabaseException("corrupt database, missing salt parameter")
                     }
                     val salt = result.getBytes(1)
                     return Encryption(masterPassword, salt)
                 }
             } catch (e: SQLException) {
                 e.printStackTrace()
-                die("unable to reopen database")
-                throw RuntimeException("this will never happen")
+                throw DatabaseException("unable to reopen database", e)
             }
         }
 
@@ -83,8 +87,7 @@
                 return encryption
             } catch (e: SQLException) {
                 e.printStackTrace()
-                die("unable to initialize database")
-                throw RuntimeException("this will never happen")
+                throw DatabaseException("unable to initialize database", e)
             }
         }
 
@@ -94,7 +97,7 @@
                     stmt.setString(1, "test")
                     val result = stmt.executeQuery()
                     if (!result.next()) {
-                        die("corrupt database, missing test parameter")
+                        throw DatabaseException("corrupt database, missing test parameter")
                     }
                     val readFromDb = result.getDecryptedString(1, database.encryption)
                     if (readFromDb != PLAINTEXT) {
@@ -104,9 +107,9 @@
                 }
             } catch (e: SQLException) {
                 e.printStackTrace()
-                die("unable to verify decryption key")
+                throw DatabaseException("unable to verify decryption key", e)
             } catch (e: GeneralSecurityException) {
-                die("invalid decryption key")
+                throw DatabaseException("invalid decryption key", e)
             }
         }
     }
@@ -114,6 +117,8 @@
     fun makeKey(name: String): Long = Hashing.hash(encryption.encryptFromString0(name.lowercase()))
 }
 
+class DatabaseException(message: String, cause: Throwable? = null) : MessagedException(message, cause)
+
 fun ResultSet.getDecryptedString(columnIndex: Int, encryption: Encryption): String? {
     return encryption.decryptToString(getBytes(columnIndex) ?: return null)
 }