util/Base64.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 Name:      Base64.cpp
00003 Project:   xmlBlaster.org
00004 Copyright: 2001-2002 Randy Charles Morin randy@kbcafe.com
00005 Comment:   http://www.kbcafe.com/articles/HowTo.Base64.pdf
00006            Allowed to distribute under xmlBlasters LGPL in email
00007            from Randy Charles Morin <randy@kbcafe.com> from 2004-01-18
00008 Minor change by Marcel Ruff xmlBlaster@marcelruff.info
00009 http://www.xmlBlaster.org
00010 ------------------------------------------------------------------------------*/
00011 #include <string>
00012 #include <vector>
00013 #include <util/Base64.h>
00014 
00015 using namespace std;
00016 using namespace org::xmlBlaster::util;
00017 
00018 std::string Base64::Encode(const std::vector<unsigned char> & vby)
00019 {
00020    std::string retval;
00021    if (vby.size() == 0)
00022    {
00023       return retval;
00024    }
00025    retval.reserve(vby.size()/3*4+4);
00026    for (std::vector<unsigned char>::size_type i=0;i<vby.size();i+=3)
00027    {
00028       unsigned char by1=0,by2=0,by3=0;
00029       by1 = vby[i];
00030       if (i+1<vby.size())
00031       {
00032          by2 = vby[i+1];
00033       };
00034       if (i+2<vby.size())
00035       {
00036          by3 = vby[i+2];
00037       }
00038       unsigned char by4=0,by5=0,by6=0,by7=0;
00039       by4 = by1>>2;
00040       by5 = ((by1&0x3)<<4)|(by2>>4);
00041       by6 = ((by2&0xf)<<2)|(by3>>6);
00042       by7 = by3&0x3f;
00043       retval += Encode(by4);
00044       retval += Encode(by5);
00045       if (i+1<vby.size())
00046       {
00047          retval += Encode(by6);
00048       }
00049       else
00050       {
00051          retval += "=";
00052       };
00053       if (i+2<vby.size())
00054       {
00055          retval += Encode(by7);
00056       }
00057       else
00058       {
00059          retval += "=";
00060       }
00061    }
00062    return retval;
00063 }
00064 
00065 std::vector<unsigned char> Base64::Decode(const std::string & _str)
00066 {
00067    std::string str;
00068    for (std::string::size_type j=0;j<_str.length();j++)
00069    {
00070       if (IsBase64(_str[j]))
00071       {
00072          str += _str[j];
00073       }
00074    }
00075    std::vector<unsigned char> retval;
00076    if (str.length() == 0)
00077    {
00078       return retval;
00079    }
00080    retval.reserve(str.size()/4*3+3);
00081    for (std::string::size_type i=0;i<str.length();i+=4)
00082    {
00083       char c1='A',c2='A',c3='A',c4='A';
00084       c1 = str[i];
00085       if (i+1<str.length())
00086       {
00087          c2 = str[i+1];
00088       };
00089       if (i+2<str.length())
00090       {
00091          c3 = str[i+2];
00092       };
00093       if (i+3<str.length())
00094       {
00095          c4 = str[i+3];
00096       };
00097       unsigned char by1=0,by2=0,by3=0,by4=0;
00098       by1 = Decode(c1);
00099       by2 = Decode(c2);
00100       by3 = Decode(c3);
00101       by4 = Decode(c4);
00102       retval.push_back( (by1<<2)|(by2>>4) );
00103       if (c3 != '=')
00104       {
00105          retval.push_back( ((by2&0xf)<<4)|(by3>>2) );
00106       }
00107       if (c4 != '=')
00108       {
00109          retval.push_back( ((by3&0x3)<<6)|by4 );
00110       }
00111    }
00112    return retval;
00113 }
00114 
00115 
00116 #ifdef BASE64_MAIN
00117 // For testing only
00118 // g++ -Wall -g -o Base64 Base64.cpp -DBASE64_MAIN=1 -I../
00119 #include <iostream>
00120 #include <fstream>
00121 static void inout(char * szFilename);
00122 
00123 int main(int argc, char* argv[])
00124 {
00125    if (argc != 2)
00126       std::cerr << "Usage: base64 [file]" << std::endl;
00127    inout(argv[1]);
00128    return 0;
00129 }
00130 
00131 void inout(char * szFilename)
00132 {
00133    std::vector<unsigned char> vby1;
00134 
00135    {  // Read the given file ...
00136       std::ifstream infile;
00137       infile.open(szFilename, std::ios::binary); //std::ios::in+std::ios::binary);
00138       if (!infile.is_open())
00139       {
00140          std::cerr << "File not open!";
00141          return;
00142       }
00143       infile >> std::noskipws;
00144       unsigned char uc;
00145       while (true)
00146       {
00147          infile >> uc;
00148          if (!infile.eof())
00149          {
00150             vby1.push_back(uc);
00151          }
00152          else
00153          {
00154             break;
00155          }
00156       }
00157       std::cout << "File length is " << vby1.size() << std::endl;
00158    }
00159 
00160    // Encode the file content ...
00161    std::vector<unsigned char>::iterator j;
00162    std::string str = Base64::Encode(vby1);
00163    std::cout << "Interim" << std::endl;
00164    std::cout << str << std::endl << std::endl;
00165 
00166    {  // Dump encoding to file ...
00167       std::ofstream outfile;
00168       std::string strOutfile = szFilename;
00169       strOutfile += ".b64";
00170       outfile.open(strOutfile.c_str(), std::ios::binary); // std::ios::out+std::ios::binary);
00171       if (!outfile.is_open())
00172       {
00173         std::cerr << "File not open!";
00174          return;
00175       }
00176       outfile << str;
00177       std::cout << "Dumped encoding to file " << strOutfile << std::endl;
00178    }
00179 
00180    // decode back again and test the cycle ...
00181    std::vector<unsigned char> vby2;
00182    vby2 = Base64::Decode(str);
00183    std::vector<unsigned char>::iterator k;
00184    int i=1;
00185    j = vby2.begin();
00186    k = vby1.begin();
00187    if (vby1.size() != vby2.size())
00188    {
00189       std::cerr << "Error in size " << vby1.size() << " " << vby2.size() << std::endl;
00190       return;
00191    }
00192    for (;j!=vby2.end();j++,k++,i++)
00193    {
00194       if (*j != *k)
00195       {
00196          std::cerr << "Error in translation " << i << std::endl;
00197          return;
00198       }
00199    }
00200    /*
00201    {
00202       std::ofstream outfile;
00203       std::string strOutfile = szFilename;
00204       strOutfile += ".bak";
00205       outfile.open(strOutfile.c_str(), std::ios::binary); // std::ios::out+std::ios::binary);
00206       if (!outfile.is_open())
00207       {
00208         std::cerr << "File not open!";
00209          return;
00210       }
00211       unsigned char uc;
00212       j = vby2.begin();
00213       for (;j!=vby2.end();j++)
00214       {
00215          uc = *j;
00216          outfile << uc;
00217       }
00218    }
00219    */
00220    std::cout << "Success, test OK" << std::endl;
00221    return;
00222 }
00223 #endif // BASE64_MAIN
00224