diff tools/format-dump.awk @ 3:2b9244d20ecf

Add awk script to pretty print pwsdump output
author Guido Berhoerster <guido+libpws@berhoerster.name>
date Fri, 03 Apr 2015 14:57:57 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/format-dump.awk	Fri Apr 03 14:57:57 2015 +0200
@@ -0,0 +1,168 @@
+#
+# Copyright (C) 2016 Guido Berhoerster <guido+pws@berhoerster.name>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+function hextodec(hex,  len, dec, i, xdigit, decdigit) {
+    len = length(hex)
+    dec = 0
+
+    for (i = 1; i <= len; i++) {
+        xdigit = tolower(substr(hex, i, 1))
+        if (xdigit ~ /[0123456789abcdef]/) {
+            decdigit = xdigits[xdigit]
+        } else {
+            return 0
+        }
+        dec += decdigit * (16 ^ (len - i))
+    }
+
+    return dec
+}
+
+function get_header_field_description(type) {
+    return (type in header_field_description) ? \
+            header_field_description[type] : "Unknown"
+}
+
+function get_record_field_description(type) {
+    return (type in record_field_description) ? \
+            record_field_description[type] : "Unknown"
+}
+
+BEGIN {
+    xdigits["0"] = 0
+    xdigits["1"] = 1
+    xdigits["2"] = 2
+    xdigits["3"] = 3
+    xdigits["4"] = 4
+    xdigits["5"] = 5
+    xdigits["6"] = 6
+    xdigits["7"] = 7
+    xdigits["8"] = 8
+    xdigits["9"] = 9
+    xdigits["a"] = 10
+    xdigits["b"] = 11
+    xdigits["c"] = 12
+    xdigits["d"] = 13
+    xdigits["e"] = 14
+    xdigits["f"] = 15
+
+    header_field_description[0] =  "Version"
+    header_field_description[1] =  "UUID"
+    header_field_description[2] =  "Non-default preferences"
+    header_field_description[3] =  "Tree Display Status"
+    header_field_description[4] =  "Timestamp of last save"
+    header_field_description[5] =  "Who performed last save"
+    header_field_description[6] =  "What performed last save"
+    header_field_description[7] =  "Last saved by user"
+    header_field_description[8] =  "Last saved on host"
+    header_field_description[9] =  "Database Name"
+    header_field_description[10] =  "Database Description"
+    header_field_description[11] =  "Database Filters"
+    header_field_description[12] =  "Reserved"
+    header_field_description[13] =  "Reserved"
+    header_field_description[14] =  "Reserved"
+    header_field_description[15] =  "Recently Used Entries"
+    header_field_description[16] =  "Named Password Policies"
+    header_field_description[17] =  "Empty Groups"
+    header_field_description[18] =  "Yubico"
+
+    record_field_description[1] =  "UUID"
+    record_field_description[2] =  "Group"
+    record_field_description[3] =  "Title"
+    record_field_description[4] =  "Username"
+    record_field_description[5] =  "Notes"
+    record_field_description[6] =  "Password"
+    record_field_description[7] =  "Creation Time"
+    record_field_description[8] =  "Password Modification Time"
+    record_field_description[9] =  "Last Access Time"
+    record_field_description[10] =  "Password Expiry Time"
+    record_field_description[11] =  "Reserved"
+    record_field_description[12] =  "Last Modification Time"
+    record_field_description[13] =  "URL"
+    record_field_description[14] =  "Autotype"
+    record_field_description[15] =  "Password History"
+    record_field_description[16] =  "Password Policy"
+    record_field_description[17] =  "Password Expiry Interval"
+    record_field_description[18] =  "Run command"
+    record_field_description[19] =  "Double-Click Action"
+    record_field_description[20] =  "EMail address"
+    record_field_description[21] =  "Protected Entry"
+    record_field_description[22] =  "Own symbols for password"
+    record_field_description[23] =  "Shift Double-Click Action"
+    record_field_description[24] =  "Password Policy Name"
+    record_field_description[25] =  "Entry keyboard shortcut"
+
+    for (type in header_field_description) {
+        description_len = length(record_field_description[type])
+        if (description_len > header_field_description_max_len) {
+            header_field_description_max_len = description_len
+        }
+    }
+    for (type in record_field_description) {
+        description_len = length(record_field_description[type])
+        if (description_len > record_field_description_max_len) {
+            record_field_description_max_len = description_len
+        }
+    }
+
+    lineno = 1
+    record = 1
+    state = "INITIAL"
+}
+
+{
+    lineno++
+}
+
+/^#/ {
+    next
+}
+
+state == "INITIAL" && /^[Hh][eE][Aa][Dd][Ee][Rr]$/ {
+    print "Header:"
+    state = "HEADER"
+    next
+}
+
+state ~ /HEADER|RECORD/ && /^[Rr][Ee][Cc][Oo][Rr][Dd] / {
+    printf("\nRecord %d:\n", record++)
+    state = "RECORD"
+    next
+}
+
+state ~ /HEADER|RECORD/ && \
+        /^[0123456789AaBbCcDdEeFf][0123456789AaBbCcDdEeFf]:/ {
+    type = hextodec(substr($0, 1, 2))
+    value = substr($0, 4)
+    printf("%*s (0x%02x): %s\n", state == "HEADER" ? \
+            header_field_description_max_len : \
+            record_field_description_max_len, \
+            state == "HEADER" ? get_header_field_description(type) : \
+            get_record_field_description(type), type, value)
+    next
+}
+
+{
+    print "syntax error in line " lineno
+    exit(1)
+}