(** * Base 64 encoder * **) function b64Encoder(inputString: string):array; var byteString, a, b, c, d: byte_string; inputLength, outputLength, inputDelta, i, j: integer; inputArray, outputArray, base64: array; outputString: string; begin base64 := ( "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R", "S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j", "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1", "2","3","4","5","6","7","8","9","+","/"); inputLength := length(inputString); byteString := byte_string(inputString); if inputLength mod 3 > 0 then inputLength := ((inputLength div 3) + 1) * 3; (* rescale input length *) end; inputDelta := inputLength - length(inputString); (* equals number of appended "=" *) outputLength := (4 * (inputLength div 3)); (* scale ouput length *) outputArray := alloc(array,outputLength); inputArray := alloc(array,inputLength); for i:=0 to length(inputString)-1 do inputArray[i] := byteString[i]; (* map byte string into array *) end; for i:=0 to inputLength-1 by 3 do j := (i div 3) * 4 (* scale index of output array *) a := byte_string(inputArray[i],8); b := byte_string(252); c := byte_string(mem_and(a,b)); outputArray[j] := bit_shift(c[0],-2); writeln("1st 6-bit: ", bit_shift(c[0],-2)); a := byte_string(inputArray[i],8); b := byte_string(3); c := byte_string(mem_and(a,b)); a := byte_string(inputArray[i+1],8); b := byte_string(240); d := byte_string(mem_and(a,b)); outputArray[j+1] := bit_shift(c[0],4) + bit_shift(d[0],-4); writeln("2nd 6-bit: ", bit_shift(c[0],4) + bit_shift(d[0],-4)); a := byte_string(inputArray[i+1],8); b := byte_string(15); c := byte_string(mem_and(a,b)); a := byte_string(inputArray[i+2],8); b := byte_string(192); d := byte_string(mem_and(a,b)); outputArray[j+2] := bit_shift(c[0],2) + bit_shift(d[0],-6); writeln("3rd 6-bit: ", bit_shift(c[0],2) + bit_shift(d[0],-6)); a := byte_string(inputArray[i+2],8); b := byte_string(63); c := byte_string(mem_and(a,b)); outputArray[j+3] := c[0]; writeln("4th 6-bit: ", c[0] ); writeln("#############"); end; outputString := ""; for i:=0 to length(outputArray)-1 do if outputArray[i] <> 0 then outputString := concat(outputString,base64[outputArray[i]]); outputArray[i] := byte_string(outputArray[i]); else if i > (length(outputArray)-1) - inputDelta then outputArray[i] := byte_string(61); (* append "=" as hexa *) outputString := concat(outputString,chr(61)); else outputArray[i] := byte_string(65); (* append "A" as hexa *) outputString := concat(outputString,chr(65)); end; end; end; writeln("encoded string (", inputString, ") : ",outputString); return outputArray; end; (** * Base 64 decoder * **) function b64Decoder(inputEncString: string):string; var i, j, a, b, c, d, inputEncLength, inputEncDelta, outputDecrLength, inputPadding: integer; inputEncArray, outputDecrArray, base64: array; base64Token, inputToken: char; outputDecrString: string; begin base64 := ( "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R", "S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j", "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1", "2","3","4","5","6","7","8","9","+","/"); inputEncLength := length(inputEncString); if inputEncLength = 0 then return; end; inputEncDelta := inputEncLength mod 4; if inputEncDelta = 0 then inputEncArray := alloc(array, inputEncLength); else inputEncArray := alloc(array, inputEncLength + 4 - inputEncDelta); (* rescale input array to the factor of 4 (6-bit input) *) end; for i:=0 to length(inputEncString)-1 do inputToken := concat('"',inputEncString[i],'"'); for j:=0 to length(base64)-1 do base64Token := concat('"',base64[j],'"'); if inputToken = base64Token then inputEncArray[i] := j; (* get corresponding integer of base64 decoded token *) break; end; end; if (i >= length(inputEncString)-2) and (ord(inputEncString[i]) = 61) then (* count padding signs *) inputPadding := inputPadding + 1; end; end; outputDecrLength := (((length(inputEncArray) + 1) div 4) * 3); outputDecrArray := alloc(array, outputDecrLength); (* define scaled 8 bit output array *) outputDecrString := ""; (* fetch 6-bit scaled input array and shift bytewise into 8-bit scaled output array *) for i:=0 to length(inputEncArray)-1 by 4 do j := ((i div 4) * 3 ); (* scale 8 bit output array *) a := byte_string(inputEncArray[i], 8); b := byte_string(inputEncArray[i+1], 8); c := byte_string(48); d := byte_string(mem_and(b,c)); outputDecrArray[j] := bit_shift(a[0],2) + bit_shift(d[0],-4); writeln("1st: ", outputDecrArray[j]); a := byte_string(inputEncArray[i+1], 8); b := byte_string(15); c := byte_string(mem_and(a,b)); a := byte_string(inputEncArray[i+2], 8); b := byte_string(60); d := byte_string(mem_and(a,b)); outputDecrArray[j+1] := bit_shift(c[0],4) + bit_shift(d[0],-2); writeln("2nd: ", outputDecrArray[j+1]); a := byte_string(inputEncArray[i+2], 8); b := byte_string(3); c := byte_string(mem_and(a,b)); d := byte_string(inputEncArray[i+3], 8); outputDecrArray[j+2] := bit_shift(c[0],6) + d[0]; writeln("3rd: ", outputDecrArray[j+2]); outputDecrString := concat(outputDecrString,outputDecrArray[j]); (* avoid to append blanks of recent padding signs "=" *) if j+1 < length(outputDecrArray) - inputPadding then outputDecrString := concat(outputDecrString,outputDecrArray[j+1]); if j+2 < length(outputDecrArray) - inputPadding then outputDecrString := concat(outputDecrString,outputDecrArray[j+2]); end; end; end; return outputDecrString; end;