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