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