Mercurial > cgi-bin > hgweb.cgi > PassMan
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); + } + } +}