/**************************************************************
 *
 *      (Slightly modified Mozilla implementation of base64)
 * 
 *************************************************************/

#include <stdlib.h> // Malloc
#include <stdio.h>  // fprintf // stderr

void *safe_malloc(size_t size)
{
        void *tmp;
        if(tmp=malloc(size))
        {
                return tmp;
        }
        else
        {
                fprintf(stderr,"Error: Malloc(%d)\n",size);
                exit(-1);
        }
}


char basis_64[] =
   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
int intlmime_encode_base64 (const char *in, char *out)
{
    unsigned char c1, c2, c3;
    c1 = in[0];
    c2 = in[1];
    c3 = in[2];

    *out++ = basis_64[c1>>2];
    *out++ = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];

    *out++ = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
    *out++ = basis_64[c3 & 0x3F];
    return 1;
}

char *base64_encode (char *subject, size_t size)
{
    char *output = 0;
    char *pSrc, *pDest ;
    int i ;

    output = (char *)safe_malloc(size * 4 / 3 + 4);
    if (output == NULL)
        return NULL;

    pSrc = subject;
    pDest = output ;
    for (i = size; i >= 3; i -= 3)
    {
        if (intlmime_encode_base64(pSrc, pDest) == 0) /* error */
        {
            pSrc += 3;
            pDest += 3;
        }
        else
        {
            pSrc += 3;
            pDest += 4;
        }
    }
    /* in case (i % 3 ) == 1 or 2 */
    if(i > 0)
    {
        char in[3];
        int j;
        in[0] = in[1] = in[2] ='\0';
        for(j=0;j<i;j++)
            in[j] = *pSrc++;
        intlmime_encode_base64(in, pDest);
        for(j=i+1;j<4;j++)
            pDest[j] = '=';
        pDest += 4;
    }
    *pDest = '\0';
    return output;
}

