#!/usr/bin/env nomsu -V3.6.5.6 # This file defines actions for encoding/decoding base 64, as specified in: https://tools.ietf.org/html/rfc4648 %b64_str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" %reverse_b64 = (%b64_str.%i = (%i - 1) for %i in 1 to (length of %b64_str)) %reverse_b64."=" = 0 test: %cases = ["", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy"] for %len = %encoded in %cases: %plain = "foobar".[1, %len - 1] assume ((base64 %plain) == %encoded) or barf ".." \(quote %plain) base64 encoded to \(quote (base64 %plain)) \ ..instead of \(quote %encoded) assume ((base64 decode %encoded) == %plain) or barf ".." \(quote %encoded) base64 decoded to \(quote (base64 decode %encoded)) \ ..instead of \(quote %plain) action [base64 %str, base64 encode %str, %str base64]: %chars = [] for %i in 1 to (length of %str) via 3: %bytes = [=lua "\%str:byte(\%i, \(%i + 2))"] add %b64_str.(((%bytes.1 & 252) >> 2) + 1) to %chars if (length of %bytes) is: 3: add %b64_str.(((%bytes.1 & 3) << 4) + ((%bytes.2 & 240) >> 4) + 1) to %chars add %b64_str.(((%bytes.2 & 15) << 2) + ((%bytes.3 & 192) >> 6) + 1) to %chars add %b64_str.((%bytes.3 & 63) + 1) to %chars 2: add %b64_str.(((%bytes.1 & 3) << 4) + ((%bytes.2 & 240) >> 4) + 1) to %chars add %b64_str.(((%bytes.2 & 15) << 2) + 1) to %chars add "=" to %chars 1: add %b64_str.(((%bytes.1 & 3) << 4) + 1) to %chars add "=" to %chars add "=" to %chars return (%chars joined) action [chr %] (=lua "string.char(\%)") action [decode base64 %str, %str base64 decoded, base64 decode %str]: %chars = [] for %i in 1 to (length of %str) via 4: %indices = (%reverse_b64.(%str.%) for % in %i to (%i + 3)) add (chr ((%indices.1 << 2) + ((%indices.2 & 48) >> 4))) to %chars if (%str.(%i + 2) == "="): stop add (chr (((%indices.2 & 15) << 4) + ((%indices.3 & 60) >> 2))) to %chars if (%str.(%i + 3) == "="): stop add (chr (((%indices.3 & 3) << 6) + %indices.4)) to %chars return (%chars joined)