- // base64.cpp 
-   
- #include <stdio.h> // for size_t 
-   
-   
- // function prototypes 
- size_t base64_encode (char *dest, const char *source, size_t source_len); 
- size_t base64_decode (unsigned char *dest, const unsigned char *source, size_t source_len); 
-   
-   
- size_t base64_encode (char *dest, const char *source, size_t source_len) 
- { 
-    // encode a string in its base64 equivalent. It is up to the caller to ensure 
-    // that dest is large enough to contain the base64 representation of source. 
-    // Typically, a 4/3 size ratio is needed (i.e. when source is 30 bytes long, 
-    // dest should be large enough to contain 40 bytes). 
-    // When finished, return the length of the decoded data. 
-   
-    static const char char_values[64 + 1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
-   
-    unsigned char bytes[3]; 
-    char *ptr; 
-   
-    ptr = dest; // save where the destination buffer starts 
-   
-    // as long as there are more than 3 characters left... 
-    while (source_len >= 3) 
-    { 
-       // get 3 bytes from source string 
-       bytes[0] = *(source++); 
-       bytes[1] = *(source++); 
-       bytes[2] = *(source++); 
-   
-       // split these 3 bytes in 4 chunks of 6 bit each and replace each of them 
-       // with the corresponding character 
-       *(ptr++) = char_values[bytes[0] >> 2]; 
-       *(ptr++) = char_values[((bytes[0] & 0x03) << 4) | (bytes[1] >> 4)]; 
-       *(ptr++) = char_values[((bytes[1] & 0x0F) << 2) | (bytes[2] >> 6)]; 
-       *(ptr++) = char_values[bytes[2] & 0x3F]; 
-   
-       source_len -= 3; // 3 characters less to process 
-    } 
-   
-    // are there any characters left ? 
-    if (source_len > 0) 
-    { 
-       // encode the 6 most significant bits of the first character 
-       bytes[0] = *(source++); 
-       *(ptr++) = char_values[bytes[0] >> 2]; 
-   
-       // is there a second character to encode ? 
-       if (source_len > 1) 
-       { 
-          // encode the 2 least significant bytes of the first character 
-          // and the 8 bytes of the second character over 2 characters 
-          bytes[1] = *source; 
-          *(ptr++) = char_values [((bytes[0] & 0x03) << 4) | (bytes[1] >> 4)]; 
-          *(ptr++) = char_values [(bytes[1] & 0x0F) << 2]; 
-       } 
-   
-       // else it was the only character left 
-       else 
-       { 
-          // encode the 2 least significant bytes of that character 
-          *(ptr++) = char_values[(bytes[0] & 0x03) << 4]; 
-          *(ptr++) = '='; // padding (no character left) 
-       } 
-   
-       *(ptr++) = '='; // padding (no character left) 
-    } 
-   
-    *ptr = 0; // terminate the string 
-    return (ptr - dest); // finished, source has been base64-encoded in dest 
- } 
-   
-   
- size_t base64_decode (unsigned char *dest, const unsigned char *source, size_t source_len) 
- { 
-    // decodes a base64 string into its 8-bit equivalent. It is up to the caller 
-    // to ensure that dest is large enough to contain the decoded representation 
-    // of source. Typically, a 3/4 size ratio is needed (i.e. when source is 40 
-    // bytes long, dest should be large enough to contain 30 bytes). 
-    // When finished, return the length of the decoded data. 
-   
-    #define __ 0xFF 
-    static const unsigned char dtable[256] = 
-    { 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, 62, __, __, __, 63, // _ _ _ _ _ _ _ _ _ _ _ + _ _ _ / 
-       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, __, __, __,  0, __, __, // 0 1 2 3 4 5 6 7 8 9 _ _ _ = _ _ 
-       __,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // _ A B C D E F G H I J K L M N O 
-       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, __, __, __, __, __, // P Q R S T U V W X Y Z _ _ _ _ _ 
-       __, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // _ a b c d e f g h i j k l m n o 
-       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, __, __, __, __, __, // p q r s t u v w x y z _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-       __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __  // _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
-    }; 
-    #undef __ 
-    unsigned char rawin[4]; 
-    unsigned char block[4]; 
-    unsigned char *pos; 
-    unsigned char tmp; 
-    size_t char_index; 
-    size_t count; 
-   
-    pos = dest; // initialize output stream writer at the beginning of the stream 
-    count = 0; // reset the block character counter 
-   
-    // for each base64 character in source... 
-    for (char_index = 0; char_index < source_len; char_index++) 
-    { 
-       tmp = dtable[source[char_index]]; // peek at the translation of this character in the table 
-       if (tmp == 0xFF) 
-          continue; // skip (ignore) all non-base64 characters 
-   
-       rawin[count] = source[char_index]; // keep track of the character we're translating 
-       block[count] = tmp; // store the translation in the current block 
-       count++; // there's one character more in the current 4-character block 
-   
-       // each time we've filled a 4-character block, decode it in 3 bytes in the output stream 
-       if (count == 4) 
-       { 
-          *pos++ = (block[0] << 2) | (block[1] >> 4); 
-          *pos++ = (block[1] << 4) | (block[2] >> 2); 
-          *pos++ = (block[2] << 6) | (block[3] >> 0); 
-          count = 0; // and reset the character counter for the next block 
-       } 
-    } 
-   
-    // handle stream end: have we decoded anything ? 
-    if (pos > dest) 
-    { 
-       if (rawin[2] == '=') 
-          pos -= 2; 
-       else if (rawin[3] == '=') 
-          pos--; 
-    } 
-   
-    *pos = 0; // drop a string terminator where the decoded stream ends (but don't take it in account in the length) 
-    return (pos - dest); // source has been base64-decoded in dest, return decoded length 
- } 
-   
-   
- #ifdef TEST_BASE64 
- #include <stdlib.h> 
- #include <string.h> 
- int main (int argc, char **argv) 
- { 
-    FILE *fp; 
-    char *inbuf; 
-    size_t inbuf_size; 
-    char *outbuf; 
-    size_t outbuf_size; 
-    int should_decode; 
-   
-    if ((argc < 4) || ((strcmp (argv[1], "encode") != 0) && (strcmp (argv[1], "decode") != 0))) 
-    { 
-       fprintf (stderr, "usage: %s <encode|decode> <infile> <outfile>\n", argv[0]); 
-       exit (1); 
-    } 
-   
-    should_decode = (strcmp (argv[1], "decode") == 0); 
-   
-    fp = fopen (argv[2], "rb"); 
-    if (fp == NULL) 
-    { 
-       fprintf (stderr, "error: unable to open input file '%s'\n", argv[2]); 
-       exit (1); 
-    } 
-    fseek (fp, 0, SEEK_END); 
-    inbuf_size = ftell (fp); 
-    fseek (fp, 0, SEEK_SET); 
-    inbuf = (char *) malloc (inbuf_size); 
-    if (inbuf == NULL) 
-    { 
-       fprintf (stderr, "error: malloc() failed for %zd bytes while reading input file '%s'\n", inbuf_size, argv[2]); 
-       exit (1); 
-    } 
-    fread (inbuf, inbuf_size, 1, fp); 
-    fclose (fp); 
-   
-    outbuf_size = 2 * inbuf_size; 
-    outbuf = (char *) malloc (outbuf_size); 
-    if (outbuf == NULL) 
-    { 
-       fprintf (stderr, "error: malloc() failed for %zd bytes while preparing output file '%s'\n", outbuf_size, argv[3]); 
-       exit (1); 
-    } 
-   
-    if (should_decode) 
-       outbuf_size = base64_decode ((unsigned char *) outbuf, (unsigned char *) inbuf, inbuf_size); 
-    else 
-       outbuf_size = base64_encode (outbuf, inbuf, inbuf_size); 
-   
-    fp = fopen (argv[3], "wb"); 
-    if (fp == NULL) 
-    { 
-       fprintf (stderr, "error: unable to open output file '%s'\n", argv[3]); 
-       exit (1); 
-    } 
-    fwrite (outbuf, outbuf_size, 1, fp); 
-    fclose (fp); 
-   
-    free (inbuf); 
-    free (outbuf); 
-    return (0); 
- } 
- #endif // TEST_BASE64 
-