Good day Stack you may think that this is the same question that has been answered before about the old base64
, xxd
, hexdump
combination of commands to convert strings into base64, but instead of using external commands i'm trying to do the same only using builtins from bash like printf
, read
, echo
... i am translating a C source from here and i have the encoding working so far but i have stumbled into a problematic C line
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
...
char *p;
...
p = strchr(b64, c);
...
in[phase] = p - b64; //Problematic line
The thing is that p
and b64
are char arrays and i don't understand what's doing the arithmetic expression with the two char arrays to obtain a number, it could be something like not or xor O_o. I'm still learning C and i don't know a lot.
This is what i have so far:
#!/bin/bash
declare -r b64=( {A..Z} {a..z} {0..9} {+,/} )
function ord() {
for i in {0..3}; do
printf '%d ' "'${1:$i:1}"
done
}
#TODO
function decodeblock() {
local out in=( $(ord $1) )
out[0]=$(( ${in[0]} << 2 | ${in[1]} >> 4 ))
out[1]=$(( ${in[1]} << 4 | ${in[2]} >> 2 ))
out[2]=$(( ${in[2]} << 6 | ${in[3]} >> 0 ))
printf "%s" "${out[@]}"
}
function encodeblock() {
local in=( $(ord "$1") ) len=$2 out index
index=$(( ${in[0]} >> 2 ))
out[0]=${b64[$index]}
index=$(( ((${in[0]} & 0x03) << 4) | ((${in[1]} & 0xf0) >> 4) ))
out[1]=${b64[$index]}
index=$(( ((${in[1]} & 0x0f) << 2) | ((${in[2]} & 0xc0) >> 6) ))
out[2]=$( (($len > 1)) && echo -n ${b64[$index]} || echo -n '=' )
index=$(( ${in[2]} & 0x3f ))
out[3]=$( (($len > 2)) && echo -n ${b64[$index]} || echo -n '=' )
printf "%s" "${out[@]}"
}
function b64_decode() {
local c i=0 phase=0 block p b64src="$1"
for (( i = 0 ; i < ${#b64src} ; i++)); do
c="${b64src:$i:1}"
[[ "$c" == '=' ]] && decodeblock "$b64src" && break
p="$c${b64[@]##*$c}"
if [[ -n "$p" ]]; then
#TODO
b64src[$phase]=
phase=$(( ($phase + 1) % 4 ))
if [[ $phase -eq 0 ]]; then
decodeblock "$b64src"
b64src=''
fi
((i++))
fi
done
}
function b64_encode() {
local block j=0 len clrstr="$1"
while [[ -n "${clrstr:$j:1}" ]]; do
len=0
for (( i = 0 ; i < 3 ; i++ )); do
block+="${clrstr:$j:1}"
[[ -n "${clrstr:$j:1}" ]] && { ((len++)) ; ((j++)); }
done
[[ -n $len ]] && encodeblock "${block[@]}" $len
block='' ; len=0
done
}
echo -n 'hello world' | base64 #DEBUG
b64_encode 'hello world' #DEBUG
b64_decode "$( b64_encode 'hello world' )"
Regards and thanks.
strchr(b64, c)
searches the character c
into the string b64
and returns a pointer to it if found; subtracting b64
from this value simply yields the index of the character inside b64
.
Long story short it's getting the index of c
in b64
. As for how to implement this in the shell, here you may find some inspiration.