1 /*------------------------------------------------------------------------------
2 Name: Base64.cpp
3 Project: xmlBlaster.org
4 Copyright: 2001-2002 Randy Charles Morin randy@kbcafe.com
5 Comment: http://www.kbcafe.com/articles/HowTo.Base64.pdf
6 Allowed to distribute under xmlBlasters LGPL in email
7 from Randy Charles Morin <randy@kbcafe.com> from 2004-01-18
8 Minor change by Marcel Ruff xmlBlaster@marcelruff.info
9 http://www.xmlBlaster.org
10 ------------------------------------------------------------------------------*/
11 #include <string>
12 #include <vector>
13 #include <util/Base64.h>
14
15 using namespace std;
16 using namespace org::xmlBlaster::util;
17
18 std::string Base64::Encode(const std::vector<unsigned char> & vby)
19 {
20 std::string retval;
21 if (vby.size() == 0)
22 {
23 return retval;
24 }
25 retval.reserve(vby.size()/3*4+4);
26 for (std::vector<unsigned char>::size_type i=0;i<vby.size();i+=3)
27 {
28 unsigned char by1=0,by2=0,by3=0;
29 by1 = vby[i];
30 if (i+1<vby.size())
31 {
32 by2 = vby[i+1];
33 };
34 if (i+2<vby.size())
35 {
36 by3 = vby[i+2];
37 }
38 unsigned char by4=0,by5=0,by6=0,by7=0;
39 by4 = by1>>2;
40 by5 = ((by1&0x3)<<4)|(by2>>4);
41 by6 = ((by2&0xf)<<2)|(by3>>6);
42 by7 = by3&0x3f;
43 retval += Encode(by4);
44 retval += Encode(by5);
45 if (i+1<vby.size())
46 {
47 retval += Encode(by6);
48 }
49 else
50 {
51 retval += "=";
52 };
53 if (i+2<vby.size())
54 {
55 retval += Encode(by7);
56 }
57 else
58 {
59 retval += "=";
60 }
61 }
62 return retval;
63 }
64
65 std::vector<unsigned char> Base64::Decode(const std::string & _str)
66 {
67 std::string str;
68 for (std::string::size_type j=0;j<_str.length();j++)
69 {
70 if (IsBase64(_str[j]))
71 {
72 str += _str[j];
73 }
74 }
75 std::vector<unsigned char> retval;
76 if (str.length() == 0)
77 {
78 return retval;
79 }
80 retval.reserve(str.size()/4*3+3);
81 for (std::string::size_type i=0;i<str.length();i+=4)
82 {
83 char c1='A',c2='A',c3='A',c4='A';
84 c1 = str[i];
85 if (i+1<str.length())
86 {
87 c2 = str[i+1];
88 };
89 if (i+2<str.length())
90 {
91 c3 = str[i+2];
92 };
93 if (i+3<str.length())
94 {
95 c4 = str[i+3];
96 };
97 unsigned char by1=0,by2=0,by3=0,by4=0;
98 by1 = Decode(c1);
99 by2 = Decode(c2);
100 by3 = Decode(c3);
101 by4 = Decode(c4);
102 retval.push_back( (by1<<2)|(by2>>4) );
103 if (c3 != '=')
104 {
105 retval.push_back( ((by2&0xf)<<4)|(by3>>2) );
106 }
107 if (c4 != '=')
108 {
109 retval.push_back( ((by3&0x3)<<6)|by4 );
110 }
111 }
112 return retval;
113 }
114
115
116 #ifdef BASE64_MAIN
117 // For testing only
118 // g++ -Wall -g -o Base64 Base64.cpp -DBASE64_MAIN=1 -I../
119 #include <iostream>
120 #include <fstream>
121 static void inout(char * szFilename);
122
123 int main(int argc, char* argv[])
124 {
125 if (argc != 2)
126 std::cerr << "Usage: base64 [file]" << std::endl;
127 inout(argv[1]);
128 return 0;
129 }
130
131 void inout(char * szFilename)
132 {
133 std::vector<unsigned char> vby1;
134
135 { // Read the given file ...
136 std::ifstream infile;
137 infile.open(szFilename, std::ios::binary); //std::ios::in+std::ios::binary);
138 if (!infile.is_open())
139 {
140 std::cerr << "File not open!";
141 return;
142 }
143 infile >> std::noskipws;
144 unsigned char uc;
145 while (true)
146 {
147 infile >> uc;
148 if (!infile.eof())
149 {
150 vby1.push_back(uc);
151 }
152 else
153 {
154 break;
155 }
156 }
157 std::cout << "File length is " << vby1.size() << std::endl;
158 }
159
160 // Encode the file content ...
161 std::vector<unsigned char>::iterator j;
162 std::string str = Base64::Encode(vby1);
163 std::cout << "Interim" << std::endl;
164 std::cout << str << std::endl << std::endl;
165
166 { // Dump encoding to file ...
167 std::ofstream outfile;
168 std::string strOutfile = szFilename;
169 strOutfile += ".b64";
170 outfile.open(strOutfile.c_str(), std::ios::binary); // std::ios::out+std::ios::binary);
171 if (!outfile.is_open())
172 {
173 std::cerr << "File not open!";
174 return;
175 }
176 outfile << str;
177 std::cout << "Dumped encoding to file " << strOutfile << std::endl;
178 }
179
180 // decode back again and test the cycle ...
181 std::vector<unsigned char> vby2;
182 vby2 = Base64::Decode(str);
183 std::vector<unsigned char>::iterator k;
184 int i=1;
185 j = vby2.begin();
186 k = vby1.begin();
187 if (vby1.size() != vby2.size())
188 {
189 std::cerr << "Error in size " << vby1.size() << " " << vby2.size() << std::endl;
190 return;
191 }
192 for (;j!=vby2.end();j++,k++,i++)
193 {
194 if (*j != *k)
195 {
196 std::cerr << "Error in translation " << i << std::endl;
197 return;
198 }
199 }
200 /*
201 {
202 std::ofstream outfile;
203 std::string strOutfile = szFilename;
204 strOutfile += ".bak";
205 outfile.open(strOutfile.c_str(), std::ios::binary); // std::ios::out+std::ios::binary);
206 if (!outfile.is_open())
207 {
208 std::cerr << "File not open!";
209 return;
210 }
211 unsigned char uc;
212 j = vby2.begin();
213 for (;j!=vby2.end();j++)
214 {
215 uc = *j;
216 outfile << uc;
217 }
218 }
219 */
220 std::cout << "Success, test OK" << std::endl;
221 return;
222 }
223 #endif // BASE64_MAIN
syntax highlighted by Code2HTML, v. 0.9.1