changeset 3:eafa3779aef8

More bug fixes, quote strings in diagnostics.
author David Barts <n5jrn@me.com>
date Sun, 11 Sep 2022 20:36:06 -0700
parents 3c792ad36b3d
children 02b101422726
files pom.xml src/main/kotlin/name/blackcap/passman/CreateSubcommand.kt src/main/kotlin/name/blackcap/passman/Database.kt src/main/kotlin/name/blackcap/passman/DeleteSubcommand.kt src/main/kotlin/name/blackcap/passman/Main.kt src/main/kotlin/name/blackcap/passman/ReadSubcommand.kt src/main/kotlin/name/blackcap/passman/See.kt src/main/kotlin/name/blackcap/passman/UpdateSubcommand.kt
diffstat 8 files changed, 67 insertions(+), 67 deletions(-) [+]
line wrap: on
line diff
--- a/pom.xml	Sun Sep 11 18:24:55 2022 -0700
+++ b/pom.xml	Sun Sep 11 20:36:06 2022 -0700
@@ -81,24 +81,23 @@
                 <artifactId>maven-assembly-plugin</artifactId>
                 <executions>
                     <execution>
+                        <id>make-assembly</id>
                         <phase>package</phase>
                         <goals>
                             <goal>single</goal>
                         </goals>
-                        <configuration>
-                            <archive>
-                                <manifest>
-                                    <mainClass>
-                                        name.blackcap.passman.MainKt
-                                    </mainClass>
-                                </manifest>
-                            </archive>
-                            <descriptorRefs>
-                                <descriptorRef>jar-with-dependencies</descriptorRef>
-                            </descriptorRefs>
-                        </configuration>
                     </execution>
                 </executions>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>name.blackcap.passman.MainKt</mainClass>
+                        </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
             </plugin>
         </plugins>
     </build>
--- a/src/main/kotlin/name/blackcap/passman/CreateSubcommand.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/CreateSubcommand.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -29,7 +29,7 @@
             val length = try {
                 rawLength?.toInt() ?: DEFAULT_GENERATED_LENGTH
             } catch (e: NumberFormatException) {
-                die("$rawLength - invalid length")
+                die("${see(rawLength)} - invalid length")
                 -1  /* will never happen */
             }
             val symbols = commandLine.hasOption("symbols")
@@ -46,7 +46,7 @@
             result.next()
             val count = result.getInt(1)
             if (count > 0) {
-                die("record matching ${entry.name} already exists")
+                die("record matching ${see(entry.name)} already exists")
             }
         }
 
--- a/src/main/kotlin/name/blackcap/passman/Database.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/Database.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -18,9 +18,9 @@
             val exists = Files.exists(Path.of(fileName))
             if (!exists) {
                 if (create) {
-                    error("initializing database $fileName")
+                    error("initializing database ${see(fileName, simple = true)}")
                 } else {
-                    die("$fileName not found")
+                    die("${see(fileName, simple = true)} not found")
                 }
             }
             val masterPassword = getPassword(passwordPrompt, !exists)
@@ -99,8 +99,6 @@
                     val readFromDb = result.getDecryptedString(1, database.encryption)
                     if (readFromDb != PLAINTEXT) {
                         /* might also get thrown by getDecryptedString if bad */
-                        println("     got: " + dump(readFromDb))
-                        println("expected: " + dump(PLAINTEXT))
                         throw GeneralSecurityException("bad key!")
                     }
                 }
--- a/src/main/kotlin/name/blackcap/passman/DeleteSubcommand.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/DeleteSubcommand.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -2,6 +2,19 @@
 
 class DeleteSubcommand(): Subcommand() {
     override fun run(args: Array<String>) {
-        println("Not yet implemented")
+        if (args.isEmpty()) {
+            die("expecting a site name", 2)
+        }
+        if (args.size > 1) {
+            die("unexpected trailing arguments", 2)
+        }
+        val nameIn = args[0]
+        val db = Database.open()
+        db.connection.prepareStatement("delete from passwords where id = ?").use {
+            it.setLong(1, db.makeKey(nameIn))
+            if (it.executeUpdate() == 0) {
+                die("no record matches ${see(nameIn)}")
+            }
+        }
     }
 }
\ No newline at end of file
--- a/src/main/kotlin/name/blackcap/passman/Main.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/Main.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -21,7 +21,7 @@
 fun runSubcommand(name: String, args: Array<String>): Unit {
     val instance = getInstanceForClass(getClassForSubcommand(name))
     if (instance == null) {
-        die("$name - unknown subcommand", 2)
+        die("${see(name)} - unknown subcommand", 2)
     } else {
         instance.run(args)
     }
--- a/src/main/kotlin/name/blackcap/passman/ReadSubcommand.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/ReadSubcommand.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -31,7 +31,7 @@
             it.setLong(1, id)
             val result = it.executeQuery()
             if (!result.next()) {
-                die("no record matches $nameIn")
+                die("no record matches ${see(nameIn)}")
             }
             val entry = Entry(
                 name = result.getDecryptedString(1, db.encryption),
@@ -63,4 +63,4 @@
             it.execute()
         }
     }
-}
\ No newline at end of file
+}
--- a/src/main/kotlin/name/blackcap/passman/See.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/See.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -1,56 +1,46 @@
 package name.blackcap.passman
 
+/* Would be nice if there was a more programmatic and comprehensive way of
+   doing this, but alas. Even the oft-recommended StringEscapeUtils does
+   something cruder than the below. Le sigh. */
+
 import java.util.Formatter
 
-private val UNPRINTABLE = setOf<Character.UnicodeBlock>(
-    Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS,
-    Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS_EXTENDED,
-    Character.UnicodeBlock.COMBINING_HALF_MARKS,
-    Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS_SUPPLEMENT,
-    Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS,
-    Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES,
-    Character.UnicodeBlock.HIGH_SURROGATES,
-    Character.UnicodeBlock.LOW_SURROGATES,
-    Character.UnicodeBlock.PRIVATE_USE_AREA,
-    Character.UnicodeBlock.SPECIALS,
+private const val DELIM = '"'
 
-)
+private val STD_ESC_MAP = mapOf<Char, Char>('\t' to 't', '\b' to 'b', '\n' to 'n',
+    '\r' to 'r', '\u000c' to 'f', '\"' to '"', '\\' to '\\')
+private const val MIN_ASCII = ' '
+private const val MAX_ASCII = '~'
+private const val MIN_8859 = '\u00a1'
+private const val MAX_8859 = '\u00ff'
+private const val SHY = '\u00ad'
 
-private val DELIM = '"'
+fun see(input: String, simple: Boolean = false): String =
+    if (simple) seeSimple(input) else seeAggressive(input)
 
-private val EXEMPT = setOf<Char>(' ')
-private val PREFIXED = setOf<Char>(DELIM, '\\')
+private fun seeSimple(input: String): String = StringBuilder().run {
+    append(DELIM)
+    append(input)
+    append(DELIM)
+    toString()
+}
 
-fun see(input: String): String {
-    val accum = StringBuilder()
-    val formatter = Formatter(accum)
-    accum.append(DELIM)
+private fun seeAggressive(input: String): String {
+    val accum = Formatter()
+    accum.format("%c", DELIM)
     for (ch in input) {
-        val block = Character.UnicodeBlock.of(ch)
-        if (ch in EXEMPT) {
-            accum.append(ch)
-        } else if (block == null || block in UNPRINTABLE || Character.isSpaceChar(ch) || Character.isWhitespace(ch)) {
-            formatter.format("\\u%04x", ch.code)
-        } else if (ch in PREFIXED) {
-            accum.append('\\')
-            accum.append(ch)
+        if ((ch in MIN_ASCII..MAX_ASCII) || ((ch != SHY) && (ch in MIN_8859 .. MAX_8859))) {
+            accum.format("%c", ch)
+            continue
+        }
+        val mapped = STD_ESC_MAP[ch]
+        if (mapped != null) {
+            accum.format("\\%c", mapped)
         } else {
-            accum.append(ch)
+            accum.format("\\u%04x", ch.code)
         }
     }
-    accum.append(DELIM)
+    accum.format("%c", DELIM)
     return accum.toString()
 }
-
-fun dump(input: String): String {
-    val accum = StringBuilder()
-    var needSpace = false
-    for (ch in input) {
-        if (needSpace) {
-            accum.append(' ')
-        }
-        accum.append(ch.code)
-        needSpace = true
-    }
-    return accum.toString()
-}
--- a/src/main/kotlin/name/blackcap/passman/UpdateSubcommand.kt	Sun Sep 11 18:24:55 2022 -0700
+++ b/src/main/kotlin/name/blackcap/passman/UpdateSubcommand.kt	Sun Sep 11 20:36:06 2022 -0700
@@ -53,7 +53,7 @@
             try {
                 rawLength?.toInt() ?: DEFAULT_GENERATED_LENGTH
             } catch (e: NumberFormatException) {
-                die("$rawLength - invalid length")
+                die("${see(rawLength)} - invalid length")
                 -1  /* will never happen */
             }
         }
@@ -90,7 +90,7 @@
             result.next()
             val count = result.getInt(1)
             if (count < 1) {
-                die("no record matches $nameIn")
+                die("no record matches " + see(nameIn))
             }
         }
     }
@@ -167,4 +167,4 @@
         addOne("password", newPassword)
     }
 
-}
\ No newline at end of file
+}