nulib/awk/enc.base64.awk

58 lines
1.7 KiB
Awk

# -*- coding: utf-8 mode: awk -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
function base64__and(var, x, l_res, l_i) {
l_res = 0
for (l_i = 0; l_i < 8; l_i++) {
if (var%2 == 1 && x%2 == 1) l_res = l_res/2 + 128
else l_res /= 2
var = int(var/2)
x = int(x/2)
}
return l_res
}
# Rotate bytevalue left x times
function base64__lshift(var, x) {
while(x > 0) {
var *= 2
x--
}
return var
}
# Rotate bytevalue right x times
function base64__rshift(var, x) {
while(x > 0) {
var = int(var/2)
x--
}
return var
}
BEGIN {
BASE64__BYTES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
}
function b64decode(src, result, base1, base2, base3, base4) {
result = ""
while (length(src) > 0) {
# Specify byte values
base1 = substr(src, 1, 1)
base2 = substr(src, 2, 1)
base3 = substr(src, 3, 1); if (base3 == "") base3 = "="
base4 = substr(src, 4, 1); if (base4 == "") base4 = "="
# Now find numerical position in BASE64 string
byte1 = index(BASE64__BYTES, base1) - 1
if (byte1 < 0) byte1 = 0
byte2 = index(BASE64__BYTES, base2) - 1
if (byte2 < 0) byte2 = 0
byte3 = index(BASE64__BYTES, base3) - 1
if (byte3 < 0) byte3 = 0
byte4 = index(BASE64__BYTES, base4) - 1
if (byte4 < 0) byte4 = 0
# Reconstruct ASCII string
result = result sprintf( "%c", base64__lshift(base64__and(byte1, 63), 2) + base64__rshift(base64__and(byte2, 48), 4) )
if (base3 != "=") result = result sprintf( "%c", base64__lshift(base64__and(byte2, 15), 4) + base64__rshift(base64__and(byte3, 60), 2) )
if (base4 != "=") result = result sprintf( "%c", base64__lshift(base64__and(byte3, 3), 6) + byte4 )
# Decrease incoming string with 4
src = substr(src, 5)
}
return result
}