comparison src/main/kotlin/name/blackcap/passman/PasswordSubcommand.kt @ 15:0fc90892a3ae

Add password subcommand.
author David Barts <n5jrn@me.com>
date Fri, 03 Feb 2023 18:48:13 -0800
parents
children ea65ab890f66
comparison
equal deleted inserted replaced
14:4dae7a15ee48 15:0fc90892a3ae
1 package name.blackcap.passman
2
3 import java.nio.file.Files
4 import java.nio.file.Path
5 import java.nio.file.StandardCopyOption
6 import kotlin.system.exitProcess
7
8 class PasswordSubcommand : Subcommand() {
9 override fun run(args: Array<String>) {
10 // Parse arguments
11 if (args.size > 0 && (args[0] == "-h" || args[0].startsWith("--h"))) {
12 println("usage: passman password")
13 exitProcess(0)
14 }
15 if (!args.isEmpty()) {
16 die("unexpected arguments", 2)
17 }
18
19 // Open databases
20 println("Changing database encryption key...")
21 val oldPath = Path.of(DB_FILE)
22 val oldDb = Database.open(fileName = DB_FILE, passwordPrompt = "Old database key: ")
23 val newPath = Path.of(NEW_DB_FILE)
24 if (Files.exists(newPath)) {
25 println("WARNING: deleting ${see(NEW_DB_FILE)}")
26 Files.delete(newPath)
27 }
28 val newDb = Database.open(fileName = NEW_DB_FILE, passwordPrompt = "New database key: ", create = true)
29
30 // Copy old to new
31 println("WARNING: do not interrupt this process or data may be lost!")
32 copyRecords(oldDb, newDb)
33
34 // Wrap up
35 oldDb.connection.close()
36 newDb.connection.close()
37 Files.move(newPath, oldPath, StandardCopyOption.REPLACE_EXISTING)
38 println("Database key changed.")
39 }
40
41 private fun copyRecords(oldDb: Database, newDb: Database) {
42 oldDb.connection.prepareStatement("select name, username, password, notes, created, modified, accessed from passwords").use { old ->
43 val results = old.executeQuery()
44 while (results.next()) {
45 newDb.connection.prepareStatement("insert into passwords (id, name, username, password, notes, created, modified, accessed) values (?, ?, ?, ?, ?, ?, ?, ?)").use { new ->
46 // id and name
47 val name = results.getDecryptedString(1, oldDb.encryption)!!
48 new.setLong(1, newDb.makeKey(name))
49 new.setEncryptedString(2, name, newDb.encryption)
50 // username
51 new.setEncryptedString(3,
52 results.getDecryptedString(2, oldDb.encryption)!!, newDb.encryption)
53 // password
54 val password = results.getDecrypted(3, oldDb.encryption)!!
55 new.setEncrypted(4, password, newDb.encryption)
56 password.clear()
57 // notes
58 new.setEncryptedString(5,
59 results.getDecryptedString(4, oldDb.encryption), newDb.encryption)
60 // created, modified, accessed
61 new.setDateOrNull(6, results.getLong(5))
62 new.setDateOrNull(7, results.getLong(6))
63 new.setDateOrNull(8, results.getLong(7))
64 new.executeUpdate()
65 }
66 }
67 }
68 }
69 }