diff options
| author | Vineet Kumar <git@vineetk.net> | 2026-05-22 18:08:13 -0400 |
|---|---|---|
| committer | Vineet Kumar <git@vineetk.net> | 2026-05-23 19:30:28 -0400 |
| commit | fad20e27b359f216405aad0e0f0cb7d329bc4817 (patch) | |
| tree | f4ebabbfa910d8fee135169d0e121f7472b9d6d5 /contrib | |
| parent | 57fe13541580c324a17c1847b0e0e67bb581d94b (diff) | |
add converter script from kasi.sh to kasi.el format
Diffstat (limited to 'contrib')
| -rw-r--r-- | contrib/convert.sh | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/contrib/convert.sh b/contrib/convert.sh new file mode 100644 index 0000000..79ca5d1 --- /dev/null +++ b/contrib/convert.sh | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | # converts kasi.sh key-value pairs to kasi.el sexps | ||
| 3 | |||
| 4 | # kasi.sh format | ||
| 5 | # password_on_first_line | ||
| 6 | # Username: someone | ||
| 7 | # Email: bob@example.org | ||
| 8 | # TOTP: some_base32_string | ||
| 9 | # anything else can go here too | ||
| 10 | |||
| 11 | # kasi.el format | ||
| 12 | # -*- mode: lisp -*- | ||
| 13 | # ((password "password_here") | ||
| 14 | # (username "someone") | ||
| 15 | # (email "bob@example.org") | ||
| 16 | # (totp "some_base32_string") | ||
| 17 | # (extra-content "\ | ||
| 18 | # anything not matched | ||
| 19 | # goes in here") | ||
| 20 | # | ||
| 21 | # if any of the fields are not parsed/found in original, it will be | ||
| 22 | # set to nil in sexp | ||
| 23 | |||
| 24 | KASI_DIR="/data/kasi" | ||
| 25 | KASI_EXT=".age" | ||
| 26 | KASI_DECRYPT="age -d -i $HOME/.ssh/id_ed25519" | ||
| 27 | KASI_ENCRYPT="age -R $HOME/.ssh/id_ed25519.pub" | ||
| 28 | |||
| 29 | lisp_val() { | ||
| 30 | if [ -z "$1" ]; then | ||
| 31 | printf 'nil' | ||
| 32 | else | ||
| 33 | printf '"%s"' "$(printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g')" | ||
| 34 | fi | ||
| 35 | } | ||
| 36 | |||
| 37 | convert() { | ||
| 38 | f="${KASI_DIR}/${1}${KASI_EXT}" | ||
| 39 | contents="$($KASI_DECRYPT "$f")" || { | ||
| 40 | printf 'error: failed to decrypt %s\n' "$f" >&2 | ||
| 41 | return 1 | ||
| 42 | } | ||
| 43 | |||
| 44 | first_line=$(printf '%s\n' "$contents" | sed -n '1p') | ||
| 45 | second_line=$(printf '%s\n' "$contents" | sed -n '2p') | ||
| 46 | last_char=$(printf '%s' "$contents" | tail -c 1) | ||
| 47 | if [ "$first_line" = "; -*- mode: lisp -*-" ] && [ "${second_line#((}" != "$second_line" ] && [ "$last_char" = ")" ]; then | ||
| 48 | printf 'skipping %s (already converted)\n' "$1" >&2 | ||
| 49 | return 0 | ||
| 50 | fi | ||
| 51 | |||
| 52 | password=$(printf '%s\n' "$contents" | sed -n '1p') | ||
| 53 | username=$(printf '%s\n' "$contents" | sed -n 's/^Username:[[:space:]]*//p' | sed 's/[[:space:]]*$//' | head -1) | ||
| 54 | email=$(printf '%s\n' "$contents" | sed -n 's/^Email:[[:space:]]*//p' | sed 's/[[:space:]]*$//' | head -1) | ||
| 55 | totp=$(printf '%s\n' "$contents" | sed -n 's/^TOTP:[[:space:]]*//p' | sed 's/[[:space:]]*$//' | head -1) | ||
| 56 | |||
| 57 | extra=$(printf '%s\n' "$contents" | awk 'NR > 1 && !/^(Username|Email|TOTP):/ && NF') | ||
| 58 | |||
| 59 | printf '; -*- mode: lisp -*-\n' | ||
| 60 | printf '((password %s)\n' "$(lisp_val "$password")" | ||
| 61 | printf ' (username %s)\n' "$(lisp_val "$username")" | ||
| 62 | printf ' (email %s)\n' "$(lisp_val "$email")" | ||
| 63 | printf ' (totp %s)\n' "$(lisp_val "$totp")" | ||
| 64 | |||
| 65 | if [ -z "$extra" ]; then | ||
| 66 | printf ' (extra-content nil))\n' | ||
| 67 | else | ||
| 68 | esc=$(printf '%s' "$extra" | sed 's/\\/\\\\/g; s/"/\\"/g') | ||
| 69 | printf ' (extra-content "\\\n%s"))\n' "$esc" | ||
| 70 | fi | ||
| 71 | } | ||
| 72 | |||
| 73 | cd "$KASI_DIR" | ||
| 74 | for i in */*"$KASI_EXT"; do | ||
| 75 | i="${i%%$KASI_EXT}" | ||
| 76 | j="$(mktemp)" | ||
| 77 | convert "$i" > "$j" | ||
| 78 | $KASI_ENCRYPT <"$j" >"$i""$KASI_EXT" | ||
| 79 | rm "$j" | ||
| 80 | done | ||
