diff src/main/kotlin/name/blackcap/passman/CreateSubcommand.kt @ 0:a6cfdffcaa94

Initial commit, incomplete but it runs sorta.
author David Barts <n5jrn@me.com>
date Sun, 11 Sep 2022 16:11:37 -0700
parents
children eafa3779aef8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/kotlin/name/blackcap/passman/CreateSubcommand.kt	Sun Sep 11 16:11:37 2022 -0700
@@ -0,0 +1,98 @@
+package name.blackcap.passman
+
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.DefaultParser
+import org.apache.commons.cli.Options
+import org.apache.commons.cli.ParseException
+import kotlin.system.exitProcess
+
+class CreateSubcommand(): Subcommand() {
+    private lateinit var commandLine: CommandLine
+
+    override fun run(args: Array<String>) {
+        val options = Options().apply {
+            addOption("g", "generate", false, "Use password generator.")
+            addOption("l", "length", true, "Length of generated password.")
+            addOption("s", "symbols", false, "Use symbol characters in generated password.")
+            addOption("v", "verbose", false, "Print the generated password.")
+        }
+        try {
+            commandLine = DefaultParser().parse(options, args)
+        } catch (e: ParseException) {
+            die(e.message ?: "syntax error", 2)
+        }
+        checkArguments()
+        val db = Database.open()
+
+        val entry = if (commandLine.hasOption("generate")) {
+            val rawLength = commandLine.getOptionValue("length")
+            val length = try {
+                rawLength?.toInt() ?: DEFAULT_GENERATED_LENGTH
+            } catch (e: NumberFormatException) {
+                die("$rawLength - invalid length")
+                -1  /* will never happen */
+            }
+            val symbols = commandLine.hasOption("symbols")
+            val verbose = commandLine.hasOption("verbose")
+            Entry.withGeneratedPassword(length, symbols, verbose)
+        } else {
+            Entry.withPromptedPassword()
+        }
+        val id = db.makeKey(entry.name)
+
+        db.connection.prepareStatement("select count(*) from passwords where id = ?").use {
+            it.setLong(1, id)
+            val result = it.executeQuery()
+            result.next()
+            val count = result.getInt(1)
+            if (count > 0) {
+                die("record matching ${entry.name} already exists")
+            }
+        }
+
+        try {
+            if (entry.notes.isBlank()) {
+                db.connection.prepareStatement("insert into passwords (id, name, username, password, created) values (?, ?, ?, ?, ?)")
+                    .use {
+                        it.setLong(1, id)
+                        it.setEncryptedString(2, entry.name, db.encryption)
+                        it.setEncryptedString(3, entry.username, db.encryption)
+                        it.setEncrypted(4, entry.password, db.encryption)
+                        it.setLong(5, System.currentTimeMillis())
+                        it.execute()
+                    }
+            } else {
+                db.connection.prepareStatement("insert into passwords (id, name, username, password, notes, created) values (?, ?, ?, ?, ?, ?)")
+                    .use {
+                        it.setLong(1, db.makeKey(entry.name))
+                        it.setEncryptedString(2, entry.name, db.encryption)
+                        it.setEncryptedString(3, entry.username, db.encryption)
+                        it.setEncrypted(4, entry.password, db.encryption)
+                        it.setEncryptedString(5, entry.notes, db.encryption)
+                        it.setLong(6, System.currentTimeMillis())
+                        it.execute()
+                    }
+            }
+        } finally {
+            entry.password.clear()
+        }
+    }
+
+    private fun checkArguments(): Unit {
+        var bad = false
+        if (!commandLine.hasOption("generate")) {
+            for (option in listOf<String>("length", "symbols", "verbose")) {
+                if (commandLine.hasOption(option)) {
+                    error("--$option requires --generate")
+                    bad = true
+                }
+            }
+        }
+        if (commandLine.args.isNotEmpty()) {
+            error("unexpected trailing arguments")
+        }
+        if (bad) {
+            exitProcess(2);
+        }
+    }
+}