1 /*
  2 Derived from: http://base64.sourceforge.net/b64.c
  3 AUTHOR:         Bob Trower 08/04/01
  4 PROJECT:        Crypt Data Packaging
  5 Adapted to work with char* by Marcel Ruff 2008-10-16
  6 */
  7 #include <string.h>
  8 #include <stdlib.h>
  9 #include "base64c.h"
 10 
 11 /**
 12  * Translation Table as described in RFC1113
 13  */
 14 static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 15 
 16 /**
 17  * Translation Table to decode (created by author Bob Trower)
 18  */
 19 static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
 20 
 21 /**
 22  * Encode 3 8-bit binary bytes as 4 '6-bit' characters
 23  */
 24 static void encodeblock( unsigned char in[3], unsigned char out[4], int len )
 25 {
 26     out[0] = cb64[ in[0] >> 2 ];
 27     out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
 28     out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
 29     out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
 30 }
 31 
 32 /**
 33  * Encode binary data to base64 notation with max line width = 60 chars.
 34  *
 35  * @param inLen binary data
 36  * @param inBytes binary data
 37  * @return outStr, is NULL if input parameters are null
 38  * You need to free(outStr) it after usage.
 39  */
 40 Dll_Export extern char *Base64Encode(int inLen, const char *inBytes) {
 41         return Base64EncodeLen(inLen, inBytes, 60);
 42 }
 43 
 44 
 45 /**
 46  * Encode binary data to base64 notation.
 47  *
 48  * @param inLen binary data
 49  * @param inBytes binary data
 50  * @param lineSize line breaks as per spec, typically 60 characters, -1 switches line breaks off
 51  * @return outStr, is NULL if input parameters are null
 52  * You need to free(outStr) it after usage.
 53  */
 54 Dll_Export char *Base64EncodeLen(int inLen, const char *inBytes, int lineSize) {
 55     unsigned char in[3], out[4];
 56     char *outStr;
 57     int i, len, blocksout = 0, inPos, outPos;
 58     /*inLen == 0 will produce an empty return string */
 59     if (inBytes == 0)
 60         return 0;
 61     outStr = (char*)calloc(3*inLen+2, sizeof(char));
 62     for (inPos=0, outPos=0; inPos<inLen;) {
 63         len = 0;
 64         for( i = 0; i < 3; i++ ) {
 65             in[i] = inBytes[inPos++];
 66             if( inPos <= inLen ) {
 67                 len++;
 68             }
 69             else {
 70                 in[i] = 0;
 71             }
 72         }
 73         if( len ) {
 74             encodeblock( in, out, len );
 75             for( i = 0; i < 4; i++ ) {
 76                 outStr[outPos++] = out[i];
 77             }
 78             blocksout++;
 79         }
 80         if(lineSize != -1 && blocksout >= (lineSize/4)/* || inPos>=inLen*/) {
 81             if( blocksout ) {
 82                 outStr[outPos++] = '\r';
 83                 outStr[outPos++] = '\n';
 84             }
 85             blocksout = 0;
 86         }
 87     }
 88     *(outStr+outPos) = 0;
 89     return outStr;
 90 }
 91 
 92 /**
 93  * Decode 4 '6-bit' characters into 3 8-bit binary bytes
 94  */
 95 static void decodeblock( unsigned char in[4], unsigned char out[3] )
 96 {
 97     out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
 98     out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
 99     out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
100 }
101 
102 /**
103  * Decode the base64 to the original byte array
104  * discarding padding, line breaks and noise
105  * @param inStr The zero terminated base64 string
106  * @param outLen An out-parameter, is set to the length of the returned bytes
107  * @return the decoded bytes with length 'outLen',
108  *  is additionally guaranteed to be null terminated (but may contain other zeros).
109  *  The caller must free the returned pointer with free()
110  */
111 Dll_Export extern char *Base64Decode(const char *inStr, int *outLen) {
112     unsigned char in[4], out[3], v;
113     int i, len, inPos=0, outPos=0, inLen;
114     char *outBytes;
115     *outLen = 0;
116     if (inStr == 0) return 0;
117 
118     inLen = strlen(inStr);
119     outBytes = (char *)calloc(inLen+1, sizeof(char));
120 
121     for (inPos=0, outPos=0; inPos<inLen;) {
122         for( len = 0, i = 0; i < 4 && inPos<inLen; i++ ) {
123             v = 0;
124             while( inPos<inLen && v == 0 ) {
125                 v = (unsigned char)inStr[inPos++];
126                 v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
127                 if( v ) {
128                     v = (unsigned char) ((v == '$') ? 0 : v - 61);
129                 }
130             }
131             if(inPos<inLen) {
132                 len++;
133                 if( v ) {
134                     in[ i ] = (unsigned char) (v - 1);
135                 }
136             }
137             else {
138                 in[i] = 0;
139             }
140         }
141         if( len ) {
142             decodeblock( in, out );
143             for( i = 0; i < len - 1; i++ ) {
144                 outBytes[outPos++] = out[i];
145             }
146         }
147     }
148     *outLen = outPos;
149     return outBytes;
150 }


syntax highlighted by Code2HTML, v. 0.9.1