90 lines
1.7 KiB
Bash
90 lines
1.7 KiB
Bash
#!/bin/sh
|
|
usage() {
|
|
printf 'usage: %s [-s] [-t type] [file ...]\n' "${0##*/}" >&2
|
|
exit 64
|
|
}
|
|
case "$(printf %s "${0##*/}" | tr A-Z a-z)" in
|
|
*16*) type=16;;
|
|
*32hex*|*32x*)
|
|
type=32x;;
|
|
*32*) type=32;;
|
|
*64s*) type=64s;;
|
|
*64*) type=64;;
|
|
*) type=64;;
|
|
esac
|
|
b16=0123456789ABCDEF
|
|
b32=ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
|
|
b32hex=0123456789ABCDEFGHIJKLMNOPQRSTUV
|
|
b64=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
|
|
b64safe=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
|
|
strict=0
|
|
while getopts t:s opt; do
|
|
case "$opt" in
|
|
t) case "$(printf %s "$OPTARG" | tr A-Z a-z)" in
|
|
16) type=16;;
|
|
32) type=32;;
|
|
32x) type=32x;;
|
|
64) type=64;;
|
|
64s|64safe)
|
|
type=64s;;
|
|
*) usage;;
|
|
esac
|
|
;;
|
|
s) strict=1;;
|
|
*) usage;;
|
|
esac
|
|
done
|
|
shift $((OPTIND - 1))
|
|
case "$type" in
|
|
16) alphabet="$b16"
|
|
insensitive=1
|
|
bits=4;;
|
|
32) alphabet="$b32"
|
|
insensitive=1
|
|
bits=5;;
|
|
32x) alphabet="$b32hex"
|
|
insensitive=1
|
|
bits=5;;
|
|
64) alphabet="$b64"
|
|
insensitive=0
|
|
bits=6;;
|
|
64s) alphabet="$b64safe"
|
|
insensitive=0
|
|
bits=6;;
|
|
*) usage;; # Unreachable
|
|
esac
|
|
cat -- "$@" | awk -vbits="$bits" -valphabet="$alphabet" \
|
|
-vinsensitive="$insensitive" -vstrict="$strict" '
|
|
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 {
|
|
FS=""
|
|
split(alphabet, al, "")
|
|
for (n in al)
|
|
a[al[n]] = n - 1
|
|
if (insensitive)
|
|
for (c in a)
|
|
a[tolower(c)] = a[c]
|
|
} {
|
|
for (i = 1; i <= NF; i++) {
|
|
if ($i in a) {
|
|
t = leftshift(t, bits) + a[$i]
|
|
b += bits
|
|
while (b >= 8) {
|
|
b -= 8
|
|
printf "%c", rightshift(t, b)
|
|
t = mask(t, b)
|
|
count++
|
|
}
|
|
} else if (strict && $i != "=")
|
|
exit 65
|
|
}
|
|
}'
|