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