/* from64.p

   Decodes a Base64 file and creates a binary file of the original data.

   Code by Andrew Maizels 2001

   This program is in the public domain and may be freely used, modified
   and re-distributed for any purpose. */

def input param pc-infile as char no-undo.
def input param pc-outfile as char no-undo.

def var lc-in as char no-undo.
def var lr-in as raw no-undo.
def var lc-tfile as char no-undo.
def var lc-hex as char init "0123456789ABCDEF" no-undo.
def var lc-hdr as char no-undo.
def var li-len as int no-undo.
def var li-i as int no-undo.

def stream binary-s.
def stream base64-s.
def stream temp-s.

/* Change this if you want to keep the temporary file somewhere else.
   Note that the program will close and re-open this file, so you can't
   unlink it at this point.  The file is deleted at the end of the program. */
lc-tfile = "/tmp/" + string(etime) + ".tmp64".

input stream base64-s from value(pc-infile).
output stream temp-s to value(lc-tfile).
output stream binary-s to value(pc-outfile) no-map no-convert.

repeat:
    import stream base64-s unformatted lc-in.

    /* Determine the length of the RAW data.  A well-formed Base64 string 
       will always be a multiple of 4 bytes long.  */
    li-len = length(lc-in) / 4 * 3.
    if lc-in matches "*==" then li-len = li-len - 2.
    else if lc-in matches "*=" then li-len = li-len - 1.

    lc-hdr = "".
    do li-i = 1 to 4:
        lc-hdr = substr(lc-hex,li-len mod 16 + 1,1) + lc-hdr.
        li-len = trunc(li-len / 16,0).
    end.
    put stream temp-s unformatted "02" lc-hdr lc-in skip.
end.

output stream temp-s close.
input stream temp-s from value(lc-tfile).

repeat:
    import stream temp-s lr-in.
    put stream binary-s control lr-in.
end.

input stream base64-s close.
input stream temp-s close.
output stream binary-s close.
                            
os-delete value(lc-tfile).
