misc-scripts/baseenc.sh

113 lines
2.3 KiB
Bash

#!/bin/sh
usage() {
printf 'usage: %s [-np] [-a alphabet] [-t type] [file ...]\n' \
"${0##*/}" >&2
exit 64
}
case "$(printf %s "${0##*/}" | tr A-Z a-z)" in
*16l*|*hexl*)
type=16l;;
*16*) type=16u;;
*32hexl*|*32x*l)
type=32x;;
*32hex*|*32x*)
type=32X;;
*32l*) type=32l;;
*32*) type=32u;;
*64s*) type=64s;;
*) type=64;;
esac
b16upper=0123456789ABCDEF
b16lower=0123456789abcdef
b32upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
b32lower=abcdefghijklmnopqrstuvwxyz234567
b32hexupper=0123456789ABCDEFGHIJKLMNOPQRSTUV
b32hexlower=0123456789abcdefghijklmnopqrstuv
b64=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
b64safe=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
alphabet=
pad=1
nl=1
while getopts a:npt: opt; do
case "$opt" in
a) alphabet="$OPTARG";;
n) nl=0;;
p) pad=0;;
t) case "$(printf %s "$OPTARG" | tr A-WYZ a-wyz)" in
16|16u|16upper)
type=16u;;
16l|16lower)
type=16l;;
32|32u|32upper)
type=32u;;
32l|32lower)
type=32l;;
32X) type=32X;;
32x) type=32x;;
64) type=64;;
64s|64safe)
type=64s;;
*) usage;;
esac
;;
*) usage;;
esac
done
shift $((OPTIND - 1))
case "$type" in
16u) alphabet="${alphabet:-$b16upper}"
bits=4;;
16l) alphabet="${alphabet:-$b16lower}"
bits=4;;
32u) alphabet="${alphabet:-$b32upper}"
bits=5;;
32l) alphabet="${alphabet:-$b32lower}"
bits=5;;
32X) alphabet="${alphabet:-$b32hexupper}"
bits=5;;
32x) alphabet="${alphabet:-$b32hexlower}"
bits=5;;
64) alphabet="${alphabet:-$b64}"
bits=6;;
64s) alphabet="${alphabet:-$b64safe}"
bits=6;;
*) usage;; # Unreachable
esac
od -An -tu1 -v -- "$@" | sed 's/^ *//' | tr -s ' ' '\n' |
sed 's/^00*//' | awk -vbits="$bits" -valphabet="$alphabet" \
-vnl="$nl" -vpad="$pad" '
function leftshift(a, b) {
return a * 2 ** b
}
function rightshift(a, b) {
return int(a / 2 ** b)
}
function mask(a, b) {
return a > 0 ? a % leftshift(1, b) : a
}
BEGIN {
split(alphabet, a, "")
} {
t = leftshift(t, 8) + $0
b += 8
while (b >= bits) {
b -= bits
printf "%s", a[rightshift(t, b) + 1]
t = mask(t, b)
count++
}
} END {
if (b > 0) {
printf "%s", a[leftshift(t, bits - b) + 1]
count++
}
if (pad && bits == 5)
for (count += 0; count % 8 != 0; count++)
printf "="
if (pad && bits == 6)
for (count += 0; count % 4 != 0; count++)
printf "="
if (nl)
print ""
}'