project BLF > class Mail > method FileEncode

Description

Method to encode a file to base64.


Parameters


imIninputmemptrMemory pointer to the original file content
ilLineBreaksinputlogicalIndication whether line breaks should be added after each 76 characters. This is necessary for attachments in mails via SMTP sockets (put it on true).
omOutoutputmemptrMemory pointer to the encoded file content
oiReturnStatusoutputintegerReturn status of the method.


Internal usage


BLF
method Mail.FileToMemptr
method Mail.ReadHandler


program code (program1/mail.p)

assign oiReturnStatus = -98.

/* omOut should have the right length set */
ASSIGN viLength = GET-SIZE(imIn)
       viMod = viLength MODULO 3.
IF viMod <> 0 THEN ASSIGN viLength = viLength + 3 - viMod.

ASSIGN viLength = viLength * 4 / 3.

IF ilLineBreaks THEN ASSIGN viLength = viLength + INTEGER(viLength / 76).
set-size(omOut) = 0.
SET-SIZE(omOut) = viLength.

/* Base64 encoding converts three bytes of input to
   four bytes of output */
DO WHILE NOT vlDone :
    ASSIGN viInBuffer[1] = GET-BYTE(imIn,viCount + 1)
           viInBuffer[2] = GET-BYTE(imIn,viCount + 2)
           viInBuffer[3] = GET-BYTE(imIn,viCount + 3).
    /*
    // Calculate the outBuffer
    // The first byte of our in buffer will always be valid
    // but we must check to make sure the other two bytes
    // are not -1 before using them.
    // The basic idea is that the three bytes get split into
    // four bytes along these lines:
    // [AAAAAABB] [BBBBCCCCC] [CCDDDDDD]
    // [xxAAAAAA] [xxBBBBBB] [xxCCCCCC] [xxDDDDDD]
    // bytes are considered to be zero when absent.
    // the four bytes are then mapped to common ASCII symbols
    */
    /* // A's: first six bits of first byte
    */
    ASSIGN viPos = viPos + 1.
    PUT-BYTE(omOut,viPos) = asc(vcBase64Chars[ get-bits(viInBuffer[1],3,6) + 1]).
    if (viInBuffer[2] <> ?)
    THEN DO :
        /*
        // B's: last two bits of first byte, first four bits of second byte
        */
        ASSIGN viPos = viPos + 1.
        PUT-BYTE(omOut,viPos) = asc(vcBase64Chars[ get-bits(viInBuffer[1],1,2) * 16 + get-bits(viInBuffer[2],5,4) + 1]).
        
        if (viInBuffer[3] <> ?)
        THEN DO :
            /*
            // C's: last four bits of second byte, first two bits of third byte
            */
            ASSIGN viPos = viPos + 1.
            PUT-BYTE(omOut,viPos) = asc(vcBase64Chars[ get-bits(viInBuffer[2],1,4) * 4 + get-bits(viInBuffer[3],7,2) + 1]).
            /*
            // D's: last six bits of third byte
            */
            ASSIGN viPos = viPos + 1.
            PUT-BYTE(omOut,viPos) = asc(vcBase64Chars[ get-bits(viInBuffer[3],1,6) + 1]).
        END.
        ELSE DO :
            /*
            // C's: last four bits of second byte
            */
            ASSIGN viPos = viPos + 1.
            PUT-BYTE(omOut,viPos) = asc(vcBase64Chars[ get-bits(viInBuffer[2],1,4) * 4 + 1]).
            /*
            // an equals sign for a character that is not a Base64 character
            */
            ASSIGN viPos = viPos + 1.
            PUT-BYTE(omOut,viPos) = ASC("=":U).
            ASSIGN vlDone = TRUE.
       END.
    END.
    ELSE DO :
        /*
        // B's: last two bits of first byte
        */
        ASSIGN viPos = viPos + 1.
        PUT-BYTE(omOut,viPos) = asc(vcBase64Chars[ get-bits(viInBuffer[1],1,2) * 16 + 1]).
        /*
        // an equal signs for characters that is not a Base64 characters
        */
        ASSIGN viPos = viPos + 1.
        PUT-BYTE(omOut,viPos) = ASC("=":U).
        ASSIGN viPos = viPos + 1.
        PUT-BYTE(omOut,viPos) = ASC("=":U).
        ASSIGN vlDone = TRUE.
    END.
    IF ilLineBreaks 
    THEN DO :
        ASSIGN viLineCount = viLineCount + 4.
        IF viLineCount >= 76
        THEN DO :
            ASSIGN viPos = viPos + 1.
            PUT-BYTE(omOut,viPos) = 10.
            ASSIGN viLineCount = 0.
        END.
    END.
    ASSIGN viCount = viCount + 3.
    IF viCount >= GET-SIZE(imIn) THEN ASSIGN vlDone = TRUE.
END.

assign oiReturnStatus = 0.