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 "base64.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 = 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  */
110 Dll_Export extern char *Base64Decode(const char *inStr, int *outLen) {
111     unsigned char in[4], out[3], v;
112     int i, len, inPos=0, outPos=0, inLen;
113     char *outBytes;
114     *outLen = 0;
115     if (inStr == 0) return 0;
116 
117     inLen = strlen(inStr);
118     outBytes = calloc(inLen+1, sizeof(char));
119 
120     for (inPos=0, outPos=0; inPos<inLen;) {
121         for( len = 0, i = 0; i < 4 && inPos<inLen; i++ ) {
122             v = 0;
123             while( inPos<inLen && v == 0 ) {
124                 v = (unsigned char)inStr[inPos++];
125                 v = (unsigned char) ((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
126                 if( v ) {
127                     v = (unsigned char) ((v == '$') ? 0 : v - 61);
128                 }
129             }
130             if(inPos<inLen) {
131                 len++;
132                 if( v ) {
133                     in[ i ] = (unsigned char) (v - 1);
134                 }
135             }
136             else {
137                 in[i] = 0;
138             }
139         }
140         if( len ) {
141             decodeblock( in, out );
142             for( i = 0; i < len - 1; i++ ) {
143                 outBytes[outPos++] = out[i];
144             }
145         }
146     }
147     *outLen = outPos;
148     return outBytes;
149 }


syntax highlighted by Code2HTML, v. 0.9.1