view 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 source

#
# 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)
}