1 // Base64Encoder.cpp
2 //
3 // Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Matthew Flood
4 // See file AUTHORS for contact information
5 //
6 // This file is part of RudeConfig.
7 //
8 // RudeConfig is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2, or (at your option)
11 // any later version.
12 //
13 // RudeConfig is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with RudeConfig; (see COPYING) if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 // 02111-1307, USA.
22 //------------------------------------------------------------------------
23
24 #include "Base64Encoder.h"
25
26 #ifndef INCLUDED_CSTRING
27 #include <string.h>
28 #define INCLUDED_CSTRING
29 #endif
30
31 namespace rude{
32 namespace config{
33
34 // translates a 6 bit char into a base-64 character
35 //
c_encode(char uc)36 inline char Base64Encoder::c_encode(char uc)
37 {
38 if (uc < 26)
39 {
40 return 'A'+uc;
41 }
42 if (uc < 52)
43 {
44 return 'a'+(uc-26);
45 }
46 if (uc < 62)
47 {
48 return '0'+(uc-52);
49 }
50 if (uc == 62)
51 {
52 return '+';
53 }
54 return '/';
55 }
56
57 // translates one base-64 character into a six-bit pattern
58 //
c_decode(char c)59 inline unsigned char Base64Encoder::c_decode(char c)
60 {
61 if (c >= 'A' && c <= 'Z')
62 {
63 return c - 'A';
64 }
65 if (c >= 'a' && c <= 'z')
66 {
67 return c - 'a' + 26;
68 }
69 if (c >= '0' && c <= '9')
70 {
71 return c - '0' + 52;
72 }
73 if (c == '+')
74 {
75 return 62;
76 };
77 return 63;
78 }
79
80
encode(const char * data,int datalength,int & outlength)81 char * Base64Encoder::encode(const char *data, int datalength, int &outlength)
82 {
83
84
85 int linelength=0;
86 outlength=0;
87
88 if (data == (char*) 0 || datalength == 0)
89 {
90 return (char*) 0;
91 };
92
93 char *retval=new char[datalength * 2];
94 const char *crlf="\n";
95 int crlflength=strlen(crlf);
96 int maxlinelength=76;
97
98 for (int i=0; i<datalength; i+=3)
99 {
100 unsigned char by1, by2, by3, by4, by5, by6, by7;
101 by1 = data[i];
102
103 if (i+1 < datalength)
104 {
105 by2 = data[i+1];
106 }
107 else
108 {
109 by2=0;
110 }
111
112 if (i+2 < datalength)
113 {
114 by3 = data[i+2];
115 }
116 else
117 {
118 by3=0;
119 }
120
121 by4 = by1>>2;
122 by5 = ((by1 & 0x3)<<4)|( by2>>4 );
123 by6 = ((by2 & 0xf)<<2)|( by3>>6 );
124 by7 = by3 & 0x3f;
125
126
127
128 retval[outlength++] = c_encode(by4);
129 linelength++;
130
131 retval[outlength++] = c_encode(by5);
132 linelength++;
133
134 if (i+1 < datalength)
135 {
136 retval[outlength++]= c_encode(by6);
137 linelength++;
138 }
139 else
140 {
141 retval[outlength++]= '=';
142 linelength++;
143 }
144
145 if (i+2<datalength)
146 {
147 retval[outlength++]= c_encode(by7);
148 linelength++;
149 }
150 else
151 {
152 retval[outlength++]= '=';
153 linelength++;
154 };
155
156 // only set linelength if maxlinelength > 0
157 //
158 if (maxlinelength != 0 && linelength >= maxlinelength)
159 {
160 for(int y=0; y< crlflength; y++)
161 {
162 retval[outlength++]= crlf[y];
163 }
164
165 // we just created a line - reset current linelength
166 //
167 linelength=0;
168 }
169 };
170 retval[outlength]='\0';
171 return retval;
172 }
173
174
decode(const char * data,int datalength,int & outlength)175 char * Base64Encoder::decode(const char *data, int datalength, int &outlength)
176 {
177 // Error if incoming data is NULL
178 // Error if nothing to decode
179 //
180 if(data == (char *) 0 || datalength == 0)
181 {
182 return (char*) 0;
183 }
184
185
186 outlength=0;
187
188 // rawlength is the length of the encoded data excluding
189 // any non-base64 characters
190 //
191 int rawlength=0;
192
193
194 // create return buffer
195 //
196 char *outbuffer=new char[datalength];
197
198 // copy all base64 characters into outbuffer,
199 // in other words, strip away CRLF's and non-b64 characters...
200 //
201 for (int j=0;j < datalength; j++)
202 {
203 if (IsBase64(data[j]))
204 {
205 outbuffer[rawlength++]= data[j];
206 }
207 }
208
209 // there's no base64 characters to decode
210 //
211 if (rawlength == 0 || datalength == 0)
212 {
213 delete [] outbuffer;
214 return (char*) NULL;
215 }
216
217
218
219 for (int i=0; i<rawlength; i+=4)
220
221 {
222
223
224
225 char c1 = outbuffer[i];
226 char c2='A',c3='A',c4='A';
227
228 if (i+1 < rawlength)
229
230 {
231
232 c2 = outbuffer[i+1];
233
234 };
235
236 if (i+2 < rawlength)
237
238 {
239
240 c3 = outbuffer[i+2];
241
242 };
243
244 if (i+3 < rawlength)
245
246 {
247
248 c4 = outbuffer[i+3];
249
250 };
251
252
253
254 unsigned char by1,by2,by3,by4;
255
256 by1 = c_decode(c1);
257
258 by2 = c_decode(c2);
259
260 by3 = c_decode(c3);
261
262 by4 = c_decode(c4);
263
264
265
266 outbuffer[outlength]=( (by1<<2)|(by2>>4) );
267 outlength++;
268
269
270 if (c3 != '=')
271
272 {
273
274 outbuffer[outlength]=( ((by2&0xf)<<4)|(by3>>2) );
275 outlength++;
276 }
277
278
279
280 if (c4 != '=')
281
282 {
283
284 outbuffer[outlength]=( ((by3&0x3)<<6)|by4 );
285 outlength++;
286 };
287
288 };
289 // NULL terminate decoded data
290 // in case caller ignores outlength
291 // for text data
292 //
293 outbuffer[outlength]=(char) 0;
294 return outbuffer;
295 }
296
297 //The last helper function returns true is a character is a valid
298 //base-64 character and false otherwise.
IsBase64(char c)299 inline bool Base64Encoder::IsBase64(char c)
300 {
301 if (c >= 'A' && c <= 'Z')
302 {
303 return true;
304 }
305 if (c >= 'a' && c <= 'z')
306 {
307 return true;
308 }
309 if (c >= '0' && c <= '9')
310 {
311 return true;
312 }
313 if (c == '+')
314 {
315 return true;
316 };
317 if (c == '/')
318 {
319 return true;
320 };
321 if (c == '=')
322 {
323 return true;
324 };
325 return false;
326 }
327
328 }}
329
330