From 8b3d59918dfc7f087974f7ded052f1d17dd005dd Mon Sep 17 00:00:00 2001
From: goose <goose@6dbc8c32-bb84-406f-8558-d1cf31a0ab0c>
Date: Sat, 11 Jul 2020 18:51:52 +0000
Subject: [PATCH] Addition of base64 module and prog

git-svn-id: https://spexeah.com:8443/svn/Asuro@975 6dbc8c32-bb84-406f-8558-d1cf31a0ab0c
---
 src/include/base64.pas   | 195 +++++++++++++++++++++++++++++++++++++++
 src/include/md5.pas      |   7 ++
 src/kernel.pas           |   6 +-
 src/prog/base64_prog.pas |  66 +++++++++++++
 4 files changed, 273 insertions(+), 1 deletion(-)
 create mode 100644 src/include/base64.pas
 create mode 100644 src/prog/base64_prog.pas

diff --git a/src/include/base64.pas b/src/include/base64.pas
new file mode 100644
index 00000000..aa2103ca
--- /dev/null
+++ b/src/include/base64.pas
@@ -0,0 +1,195 @@
+{ 
+	Include->Base64 - Base64 encode and decode.
+	
+    @author(Angus C <angus@actm.uk>)
+}
+
+unit base64;
+
+interface
+
+uses
+    lmemorymanager,
+    strings,
+    util;
+
+const
+    base64_enc_map : array[0..63] of char = ('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','+','/');
+
+function b64_encode(src : PuInt8; len : uInt32; out_len : PuInt32) : PuInt8;
+function b64_decode(src : PuInt8; len : uInt32; out_len : PuInt32) : PuInt8;
+
+function b64_encode_str(src : PChar) : PChar;
+function b64_decode_str(src : PChar) : PChar;
+
+implementation
+
+function b64_encode(src : PuInt8; len : uInt32; out_len : PuInt32) : PuInt8;
+var
+    olen      : uInt32;
+    line_len  : uInt32;
+    b64end    : PuInt8;
+    b64in     : PuInt8;
+    b64pos    : PuInt8;
+    output    : PuInt8;
+
+begin
+    olen := len * 4 div 3 + 4; // 3-byte blocks to 4-byte
+    olen := olen + (olen div 72); // line feeds
+    olen := olen + 1; // nul termination
+
+    output := nil;
+    if olen < len then begin
+        // integer overflow
+    end else begin
+        output := PuInt8(kalloc(olen));
+        b64end := PuInt8(uInt32(src) + uInt32(len));
+        b64in  := src;
+        b64pos := output;
+        line_len := 0;
+        while (uInt32(b64end) - uInt32(b64in)) >= 3 do begin
+            b64pos^ := uInt8(base64_enc_map[b64in[0] shr 2]);
+            inc(b64pos);
+            b64pos^ := uInt8(base64_enc_map[((b64in[0] and $03) shl 4) or (b64in[1] shr 4)]);
+            inc(b64pos);
+            b64pos^ := uInt8(base64_enc_map[((b64in[1] and $0F) shl 2) or (b64in[2] shr 6)]);
+            inc(b64pos);
+            b64pos^ := uInt8(base64_enc_map[b64in[2] and $3F]);
+            inc(b64pos);
+            inc(b64in, 3);
+            inc(line_len, 4);
+            if line_len >= 72 then begin
+                b64pos^ := $0A;
+                inc(b64pos);
+            end;
+        end;
+        
+        if (uInt32(b64end) - uInt32(b64in)) > 0 then begin
+            b64pos^ := uInt8(base64_enc_map[b64in[0] shr 2]);
+            inc(b64pos);
+            if (uInt32(b64end) - uInt32(b64in)) = 1 then begin
+                b64pos^ := uInt8(base64_enc_map[((b64in[0] and $03) shl 4)]);
+                inc(b64pos);
+                b64pos^ := $3D;
+                inc(b64pos);
+            end else begin
+                b64pos^ := uInt8(base64_enc_map[((b64in[0] and $03) shl 4) or (b64in[1] shr 4)]);
+                inc(b64pos);
+                b64pos^ := uInt8(base64_enc_map[((b64in[1] and $0F) shl 2)]);
+                inc(b64pos);
+            end;
+            b64pos^ := $3D;
+            inc(b64pos);
+            inc(line_len, 4);
+        end;
+
+        if line_len > 0 then begin
+            b64pos^ := $0A;
+            inc(b64pos);
+        end;
+        b64pos^ := $0;
+        if out_len <> nil then begin
+            out_len^ := uInt32(b64pos) - uInt32(output);
+        end;
+    end;
+    b64_encode := output;
+end;
+
+function b64_decode(src : PuInt8; len : uInt32; out_len : PuInt32) : PuInt8;
+var
+    b64tmp  : uInt8;
+    b64pos  : PuInt8;
+    output  : PuInt8;
+    i       : uInt32;
+    count   : uInt32;
+    olen    : uInt32;
+    pad     : uInt32;
+    dtable  : array[0..255] of uInt8;
+    block   : array[0..3] of uInt8;
+
+begin
+    pad := 0;
+    memset(uInt32(@dtable[0]), $80, 256);
+
+    for i := 0 to (sizeof(base64_enc_map) - 2) do begin
+        dtable[uInt8(base64_enc_map[i])] := uInt8(i);
+    end;
+    dtable[uInt8('=')] := 0;
+
+    count := 0;
+    for i := 0 to (len - 1) do begin
+        if dtable[uInt8(src[i])] <> $80 then begin
+            inc(count)
+        end;
+    end;
+    if count = 0 or count mod 4 then begin
+        // something went wrong
+    end else begin
+        olen := count div 4 * 3;
+        b64pos := PuInt8(kalloc(olen));
+        output := b64pos;
+        if output = nil then begin
+            // something went wrong
+        end else begin
+            count := 0;
+            for i := 0 to (len - 1) do begin
+                b64tmp := uInt8(dtable[src[i]]);
+                if b64tmp = $80 then begin
+                    continue;
+                end;
+                if src[i] = uInt8('=') then begin
+                    inc(pad);
+                end;
+                block[count] := b64tmp;
+                inc(count);
+                if count = 4 then begin
+                    b64pos^ := uInt8((block[0] shl 2) or (block[1] shr 4));
+                    inc(b64pos);
+                    b64pos^ := uInt8((block[1] shl 4) or (block[2] shr 2));
+                    inc(b64pos);
+                    b64pos^ := uInt8((block[2] shl 6) or block[3]);
+                    inc(b64pos);
+                    count := 0;
+                    if pad > 0 then begin
+                        if pad = 1 then begin
+                            dec(b64pos);
+                        end else if pad = 2 then begin
+                            dec(b64pos, 2);
+                        end else begin
+                            kfree(void(output));
+                            b64_decode := nil;
+                            exit;
+                        end;
+                        break;
+                    end;
+                end;
+            end;
+        end;
+        out_len^ := uInt32(b64pos) - uInt32(output);
+    end;
+    b64_decode := output;
+end;
+
+function b64_encode_str(src : PChar) : PChar;
+var
+    src_len : uInt32;
+begin
+    src_len := stringSize(src);
+    b64_encode_str := PChar(b64_encode(PuInt8(src), src_len, nil));
+end;
+
+function b64_decode_str(src : PChar) : PChar;
+var
+    src_len : uInt32;
+begin
+    src_len := stringSize(src);
+    b64_decode_str := PChar(b64_decode(PuInt8(src), src_len, nil));
+end;
+
+end.
\ No newline at end of file
diff --git a/src/include/md5.pas b/src/include/md5.pas
index e891ebeb..e3b92fac 100644
--- a/src/include/md5.pas
+++ b/src/include/md5.pas
@@ -1,3 +1,10 @@
+{ 
+	Include->MD5 - MD5 checksum.
+	
+    @author(Angus C <angus@actm.uk>)
+	@author(Kieron Morris <kjm@kieronmorris.me>)
+}
+
 unit md5;
 
 interface
diff --git a/src/kernel.pas b/src/kernel.pas
index fb93c398..d499b639 100644
--- a/src/kernel.pas
+++ b/src/kernel.pas
@@ -46,7 +46,10 @@ uses
      edit,
      udpcat,
      cpu,
-     md5, md5sum,
+     md5,
+     md5sum,
+     base64,
+     base64_prog,
      rand;
  
 procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall;
@@ -227,6 +230,7 @@ begin
      edit.init();
      udpcat.init();
      md5sum.init();
+     base64_prog.init();
      terminal.run();
 
      { Init Splash }
diff --git a/src/prog/base64_prog.pas b/src/prog/base64_prog.pas
new file mode 100644
index 00000000..d83cbfff
--- /dev/null
+++ b/src/prog/base64_prog.pas
@@ -0,0 +1,66 @@
+{ 
+	Prog->Base64 - Base64 encode and decode.
+	
+	@author(Angus C <angus@actm.uk>)
+}
+unit base64_prog;
+
+interface
+
+uses
+    console, terminal, keyboard, util, strings, tracer, base64, lmemorymanager;
+
+procedure init();
+
+implementation
+
+procedure run(Params : PParamList);
+var
+    input     : pchar;
+    pinput    : pchar;
+    encdec    : pchar;
+    result    : pchar;
+    i         : uInt32;
+    PSize     : uInt32;
+
+begin
+    tracer.push_trace('base64_prog.run');
+    if paramCount(Params) > 1 then begin
+        encdec := getParam(0, Params);
+        if stringEquals(encdec, 'encode') then begin
+            PSize := 0;
+            for i := 1 to ParamCount(params) - 1 do begin
+                PSize := PSize + stringSize(getParam(i, Params));
+            end;
+            Psize := PSize + 1 + (ParamCount(params) - 1);
+            input := pchar(kalloc(PSize));
+            pinput := input;
+            for i := 1 to ParamCount(params) - 1 do begin
+                memcpy(uInt32(getParam(i, Params)), uInt32(pinput), stringSize(getParam(i, Params)));
+                inc(pinput, stringSize(getParam(i, Params)));
+                pinput^ := ' ';
+                inc(pinput);
+            end;
+            dec(pinput);
+            pinput^ := #0;
+            result := b64_encode_str(input);
+            writestringlnWND(result, getTerminalHWND);
+            kfree(void(result));
+        end else if stringEquals(encdec, 'decode') then begin
+            input := getParam(1, Params);
+            result := b64_decode_str(input);
+            writestringlnWND(result, getTerminalHWND);
+            kfree(void(result));
+        end else writestringlnWND('Usage: base64 <encode/decode> <text>', getTerminalHWND);
+    end else begin
+        writestringlnWND('Usage: base64 <encode/decode> <text>', getTerminalHWND);
+    end;
+end;
+
+procedure init();
+begin
+    tracer.push_trace('base64_prog.init');
+    terminal.registerCommand('BASE64', @Run, 'Perform Base64 Encode/Decode.');
+end;
+
+end.
\ No newline at end of file